Hi! Without this patch, cprop can propagate e.g. a SYMBOL_REF to former (mem (plus (reg) (const_int))) making it invalid RTL (as plus of CONSTANT_P arguments must be simplified or surrounded by CONST).
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2014-01-31 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/57915 * recog.c (simplify_while_replacing): For PLUS/MINUS with both operands CONSTANT_P where one operand is equal to TO call simplify_gen_binary. * gcc.target/i386/pr57915.c: New test. --- gcc/recog.c.jj 2014-01-23 10:53:05.000000000 +0100 +++ gcc/recog.c 2014-01-31 16:08:06.371826412 +0100 @@ -590,6 +590,14 @@ simplify_while_replacing (rtx *loc, rtx validate_change (object, loc, simplify_gen_binary (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1); + /* Canonicalize addition of two constants, that must be either + simplified into a constant or (const (plus (...) (...))). */ + else if (CONSTANT_P (XEXP (x, 0)) + && CONSTANT_P (XEXP (x, 1)) + && (XEXP (x, 0) == to || XEXP (x, 1) == to)) + validate_change (object, loc, + simplify_gen_binary + (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1); break; case MINUS: if (CONST_SCALAR_INT_P (XEXP (x, 1))) @@ -599,6 +607,14 @@ simplify_while_replacing (rtx *loc, rtx simplify_gen_unary (NEG, GET_MODE (x), XEXP (x, 1), GET_MODE (x))), 1); + /* Canonicalize subtraction of two constants, that must be either + simplified into a constant or (const (minus (...) (...))). */ + else if (CONSTANT_P (XEXP (x, 0)) + && CONSTANT_P (XEXP (x, 1)) + && (XEXP (x, 0) == to || XEXP (x, 1) == to)) + validate_change (object, loc, + simplify_gen_binary + (MINUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1); break; case ZERO_EXTEND: case SIGN_EXTEND: --- gcc/testsuite/gcc.target/i386/pr57915.c.jj 2014-01-31 16:10:47.436942155 +0100 +++ gcc/testsuite/gcc.target/i386/pr57915.c 2014-01-31 16:10:21.000000000 +0100 @@ -0,0 +1,33 @@ +/* PR rtl-optimization/57915 */ +/* { dg-do compile } */ +/* { dg-options "-Os" } */ + +extern struct T { char a[8]; char b[16]; } t; +int c; +void foo (void); + +extern inline char * +baz (char *x, const char *y) +{ + const char *e = y; + unsigned long f, g; + asm ("" : "+c" (f), "+D" (e) : "a" ('\0'), "X" (*e)); + g = e - 1 - y; + __builtin_memcpy (x, y, g); + x[g] = '\0'; + return x; +} + +void +bar (void) +{ + char d[16]; + baz (d, t.b); + + for (;;) + { + foo (); + if (c) + baz (d, t.b); + } +} Jakub