This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

long long move bug?


All,

I ran into a problem this week when running code with lots of long long
variables (which eventually start causing spills).  Whenever gcc spills a long
long, reloads it, and then copies it to another pair of registers, it seems to
be confused about which registers to use for the copy.

Here's a snippet of asm from objdump:

     lwz     r10,48(r1) /* reload the long long you spilled previously */
     lwz     r11,52(r1) /* r10 = upper32 bits, r11 = lower32 bits */

    /* do the copy */
     mr      r12,r11 	/* r12 has copy of lower32_bits */
     mr      r11,r10	/* r11 has copy of upper32_bits */

     addc    r9,r11,r12  /* Do the 64-bit *2 using reg+reg */
     adde    r8,r10,r11

When you use the copied value, you end up with the wrong arguments to the first
addc.

What you want above, logically, is
	addc r9, lower32_bits, lower_32_bits
	adde r8, upper32_bits, upper_32_bits

What you get with the above generatd code sequence, logically, is:
	addc r9, upper32_bits, lower32_bits
	adde r8, upper32_bits, upper32_bits.

which is incorrect.

I suspect that when the code was generated, what was probably meant was:
	mr r13,r11
	mr r12,r10
	addc r11,r13
	adde r10,r12

instead of the actual code sequence which modifies r11, but attempts to use it
as though it hasn't changed. 

Actually, I'm not sure either why the copy takes place at all, but I'm betting
it has to do with passes and when optimizations can/can't take place (and other
things I don't fully understand yet!).

I was running the released 2.95.3 on a linux machine, compiling for PowerPC
750.  I do not know if this happens for non-powerpc targets.  An artificial
testcase which does nothing but repeatedly multiply 20 long longs by 2 is
attached.  My compiler flags were: -funroll-loops -funroll-all-loops -O3
-fno-inline-functions -fomit-frame-pointer -mcpu=750  -o llspill.stnd.e
llspill.c

Testing with 3.0 does not encounter the problem, although the generated code is
now so different that it's hard to tell if this problem has been completely
fixed there or not.

Can someone tell me if this is a known bug, and if it's definitely been fixed
in 3.0?

Thanks,
Becky
volatile int one = 1;

/* use 20 test vars t1-t20 */
static long long t1;
static long long t2;
static long long t3;
static long long t4;
static long long t5;
static long long t6;
static long long t7;
static long long t8;
static long long t9;
static long long t10;
static long long t11;
static long long t12;
static long long t13;
static long long t14;
static long long t15;
static long long t16;
static long long t17;
static long long t18;
static long long t19;
static long long t20;

void test(long long x, long long y) 
{
  if(x != y)
    printf("FAIL: %lld != %lld\n", x,y);
  else
    printf("PASS: %lld == %lld\n", x,y);

  return;
}

int main(void) 
{
  int expected = 8;

  t1 = one; t2 = one; t3 = one; t4 = one;
  t5 = one; t6 = one; t7 = one; t8 = one; 
  t9 = one; t10 = one; t11 = one; t12 = one;
  t13 = one; t14 = one; t15 = one; t16 = one;
  t17 = one; t18 = one; t19 = one; t20 = one;

  t1 *= 2; t2 *= 2; t3 *= 2; t4 *= 2; t5 *= 2;
  t6 *= 2; t7 *= 2; t8 *= 2; t9 *= 2; t10 *= 2;
  t11 *= 2; t12 *= 2; t13 *= 2; t14 *= 2; t15 *= 2;
  t16 *= 2; t17 *= 2; t18 *= 2; t19 *= 2; t20 *= 2;

  t1 *= 2; t2 *= 2; t3 *= 2; t4 *= 2; t5 *= 2;
  t6 *= 2; t7 *= 2; t8 *= 2; t9 *= 2; t10 *= 2;
  t11 *= 2; t12 *= 2; t13 *= 2; t14 *= 2; t15 *= 2;
  t16 *= 2; t17 *= 2; t18 *= 2; t19 *= 2; t20 *= 2;

  t1 *= 2; t2 *= 2; t3 *= 2; t4 *= 2; t5 *= 2;
  t6 *= 2; t7 *= 2; t8 *= 2; t9 *= 2; t10 *= 2;
  t11 *= 2; t12 *= 2; t13 *= 2; t14 *= 2; t15 *= 2;
  t16 *= 2; t17 *= 2; t18 *= 2; t19 *= 2; t20 *= 2;

  /* We did 3 multiplies by 2, so expect the result to be
     1 * 2 * 2 * 2 = 8 */
  test(t1,expected);
  test(t2,expected);
  test(t3,expected);
  test(t4,expected);
  test(t5,expected);
  test(t6,expected);
  test(t7,expected);
  test(t8,expected);
  test(t9,expected);
  test(t10,expected);
  test(t11,expected);
  test(t12,expected);
  test(t13,expected);
  test(t14,expected);
  test(t15,expected);
  test(t16,expected);
  test(t17,expected);
  test(t18,expected);
  test(t19,expected);
  test(t20,expected);

  return;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]