/* Check that the div0s instruction is used for integer sign comparisons.
   Each test case is expected to emit at least one div0s insn.
   Problems when combining the div0s comparison result with surrounding
   logic usually show up as redundant tst insns.  */
/* { dg-do compile }  */
/* { dg-options "-O2" } */
/* { dg-final { scan-assembler-times "div0s" 42 } } */
/* { dg-final { scan-assembler-not "tst" } } */
/* { dg-final { scan-assembler-not "not\t" } }  */
/* { dg-final { scan-assembler-not "nott" } }  */

/* { dg-final { scan-assembler-times "negc" 10 { target { ! sh2a } } } }  */
/* { dg-final { scan-assembler-times "movrt" 10 { target { sh2a } } } }  */

typedef unsigned char bool;

int other_func_a (int, int);
int other_func_b (int, int);

bool
test_00 (int a, int b)
{
  return (a ^ b) >= 0;
}

bool
test_01 (int a, int b)
{
  return (a ^ b) < 0;
}

int
test_02 (int a, int b, int c, int d)
{
  if ((a ^ b) < 0)
    return other_func_a (a, c);
  else
    return other_func_b (d, b);
}

int
test_03 (int a, int b, int c, int d)
{
  if ((a ^ b) >= 0)
    return other_func_a (a, c);
  else
    return other_func_b (d, b);
}

int
test_04 (int a, int b)
{
  return (a ^ b) >= 0 ? -20 : -40;
}

bool
test_05 (int a, int b)
{
  return (a ^ b) < 0;
}

int
test_06 (int a, int b)
{
  return (a ^ b) < 0 ? -20 : -40;
}

bool
test_07 (int a, int b)
{
  return (a < 0) == (b < 0);
}

int
test_08 (int a, int b)
{
  return (a < 0) == (b < 0) ? -20 : -40;
}

bool
test_09 (int a, int b)
{
  return (a < 0) != (b < 0);
}

int
test_10 (int a, int b)
{
  return (a < 0) != (b < 0) ? -20 : -40;
}

bool
test_11 (int a, int b)
{
  return (a >= 0) ^ (b < 0);
}

int
test_12 (int a, int b)
{
  return (a >= 0) ^ (b < 0) ? -20 : -40;
}

bool
test_13 (int a, int b)
{
  return !((a >= 0) ^ (b < 0));
}

int
test_14 (int a, int b)
{
  return !((a >= 0) ^ (b < 0)) ? -20 : -40;
}

bool
test_15 (int a, int b)
{
 return (a & 0x80000000) == (b & 0x80000000);
}

int
test_16 (int a, int b)
{
  return (a & 0x80000000) == (b & 0x80000000) ? -20 : -40;
}

bool
test_17 (int a, int b)
{
  return (a & 0x80000000) != (b & 0x80000000);
}

int
test_18 (int a, int b)
{
  return (a & 0x80000000) != (b & 0x80000000) ? -20 : -40;
}

int
test_19 (unsigned int a, unsigned int b)
{
  return (a ^ b) >> 31;
}

int
test_20 (unsigned int a, unsigned int b)
{
  return (a >> 31) ^ (b >> 31);
}

int
test_21 (int a, int b)
{
  return ((a & 0x80000000) ^ (b & 0x80000000)) >> 31 ? -30 : -10;
}

int
test_22 (int a, int b, int c, int d)
{
  if ((a < 0) == (b < 0))
    return other_func_a (a, b);
  else
    return other_func_b (c, d);
}

bool
test_23 (int a, int b, int c, int d)
{
  /* Should emit 2x div0s.  */
  return ((a < 0) == (b < 0)) | ((c < 0) == (d < 0));
}

bool
test_24 (int a, int b)
{
  return a >= 0 != b >= 0;
}

bool
test_25 (int a, int b)
{
  return !(a < 0 != b < 0);
}

int
test_26 (int a, int b, int c, int d)
{
  return a >= 0 != b >= 0 ? c : d;
}

int
test_27 (int a, int b)
{
  return a >= 0 == b >= 0;
}

int
test_28 (int a, int b, int c, int d)
{
  return a >= 0 == b >= 0 ? c : d;
}

int
test_29 (int a, int b)
{
  return ((a >> 31) ^ (b >= 0)) & 1;
}

int
test_30 (int a, int b)
{
  return ((a >> 31) ^ (b >> 31)) & 1;
}

// -------------------------------------------------------

bool
test_31 (int a, int b)
{
  /* 2x exts.w, div0s  */
  return ((a & 0x8000) ^ (b & 0x8000)) != 0;
}

bool
test_32 (int a, int b)
{
  /* 2x exts.w, div0s  */
  return (a & 0x8000) != (b & 0x8000);
}

bool
test_33 (int a, int b)
{
  /* 2x add/shll, div0s  */
  return ((a & (1<<30)) ^ (b & (1<<30))) != 0;
}

bool
test_34 (int a, int b)
{
  /* 2x exts.b, div0s  */
  return (a & 0x80) != (b & 0x80);
}

bool
test_35 (signed char a, signed char b)
{
  /* 2x exts.b, div0s  */
  return (a < 0) != (b < 0);
}

bool
test_36 (short a, short b)
{
  /* 2x exts.w, div0s  */
  return (a < 0) != (b < 0);
}

int
test_37 (short a, short b)
{
  /* 2x exts.w, div0s  */
  return (a < 0) != (b < 0) ? 40 : -10;
}

bool
test_38 (int a, int b)
{
  /* 2x shll8, div0s  */
  return ((a & (1<<23)) ^ (b & (1<<23))) != 0;
}

bool
test_39 (int a, int b)
{
  /* 2x shll2, div0s  */
  return ((a & (1<<29)) ^ (b & (1<<29))) != 0;
}

bool
test_40 (short a, short b)
{
  /* 2x exts.w, div0s, negc  */
  return (a < 0) == (b < 0);
}
