Hi! This patch fixes a 4.8 ICE (on trunk the bug went latent by GIMPLE optimization changes). The problem is we have a REG_EQUAL (unsigned_float:DF (reg:SI ...)) and cse_process_notes_1 attempts to replace the reg with CONST_INT that has the top most bit set. As CONST_INTs are canonicalized by sign extending it, simplify_unary* ICEs on it because it doesn't know the original mode of the argument and thus if the e.g. -1 in the CONST_INT is 0xff, 0xffff, 0xffffffff, 0xffffffffffffffffULL. cse_process_notes_1 already punts similarly on SIGN_EXTEND/ZERO_EXTEND/SUBREG, this just handles UNSIGNED_FLOAT similarly, but allows unsigned values that aren't negative when canonicalized, one doesn't need the mode in that case, if the CONST_INT was valid for the original mode, then it shouldn't have any bits set beyond it's precision.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.8? 2013-12-31 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/59647 * cse.c (cse_process_notes_1): Don't substitute negative VOIDmode new_rtx into UNSIGNED_FLOAT rtxes. * g++.dg/opt/pr59647.C: New test. --- gcc/cse.c.jj 2013-03-16 08:30:37.000000000 +0100 +++ gcc/cse.c 2013-12-31 15:31:16.469885722 +0100 @@ -6082,6 +6082,18 @@ cse_process_notes_1 (rtx x, rtx object, return x; } + case UNSIGNED_FLOAT: + { + rtx new_rtx = cse_process_notes (XEXP (x, 0), object, changed); + /* We don't substitute negative VOIDmode constants into these rtx, + since they would impede folding. */ + if (GET_MODE (new_rtx) != VOIDmode + || (CONST_INT_P (new_rtx) && INTVAL (new_rtx) >= 0) + || (CONST_DOUBLE_P (new_rtx) && CONST_DOUBLE_HIGH (new_rtx) >= 0)) + validate_change (object, &XEXP (x, 0), new_rtx, 0); + return x; + } + case REG: i = REG_QTY (REGNO (x)); --- gcc/testsuite/g++.dg/opt/pr59647.C.jj 2013-12-31 15:16:16.259454995 +0100 +++ gcc/testsuite/g++.dg/opt/pr59647.C 2013-12-31 15:15:51.000000000 +0100 @@ -0,0 +1,32 @@ +// PR rtl-optimization/59647 +// { dg-do compile } +// { dg-options "-O2 -fno-tree-vrp" } +// { dg-additional-options "-msse2 -mfpmath=sse" { target { { i?86-*-* x86_64-*-* } && ia32 } } } + +void f1 (int); +void f2 (); +double f3 (int); + +struct A +{ + int f4 () const + { + if (a == 0) + return 1; + return 0; + } + unsigned f5 () + { + if (!f4 ()) + f2 (); + return a; + } + int a; +}; + +void +f6 (A *x) +{ + unsigned b = x->f5 (); + f1 (b - 1 - f3 (x->f5 () - 1U)); +} Jakub