------- Comment #3 from wilson at tuliptree dot org 2008-04-12 00:45 ------- Subject: Re: New: unsinged long long and while loop evaluation regression?
I can reproduce this on a 32-bit x86-linux machine (i.e. a 32-bit HWI). The unsigned long long 0xffffffff becomes a (const_double -1 0), and then in expand_mult in expmed.c we have /* If we are multiplying in DImode, it may still be a win to try to work with shifts and adds. */ if (CONST_DOUBLE_HIGH (op1) == 0) coeff = CONST_DOUBLE_LOW (op1); After this line, expand_mult thinks we are multiplying by -1 and we get the wrong result. I think there is a false assumption here that we can get CONST_DOUBLEs which can be simplified to a single word. Maybe in the olden days we always created a CONST_DOUBLE for DImode constants? This stuff has changed so many times it is hard to remember. I don't think we do it that way anymore. Anyways, if this assumption is not false, then the code needs to look more like the code in immed_double_const in emit-rtl.c, which does /* If this integer fits in one word, return a CONST_INT. */ if ((i1 == 0 && i0 >= 0) || (i1 == ~0 && i0 < 0)) return GEN_INT (i0); where i1 is CONST_DOUBLE_HIGH and i0 is CONST_DOUBLE_LOW, and only in the case that this tests succeeds can we set coeff to CONST_DOUBLE_LOW. The same bug is in mainline, and probably goes a long ways back. Jim -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35885