As Robert pointed out here: http://gcc.gnu.org/ml/gcc-patches/2014-04/msg00416.html
we're a bit too eager when folding stuff into an 'X' constraint. The value at expand time is sensible, but after that asm_operand_ok allows arbitrary rtx expressions, including any number of registers as well as MEMs with unchecked addresses. This is a target-independent problem, as shown by the testcase below. Reload would give bogus "impossible constraint in asm" errors while LRA ICEs. Tested on x86_64-linux-gnu. OK to install? Thanks, Richard gcc/ * recog.c (asm_operand_ok): Tighten MEM validity for 'X'. gcc/testsuite/ * gcc.dg/torture/asm-x-constraint-1.c: New test. Index: gcc/recog.c =================================================================== --- gcc/recog.c 2014-04-12 22:43:54.729854903 +0100 +++ gcc/recog.c 2014-04-15 21:47:32.139873570 +0100 @@ -1840,7 +1840,17 @@ asm_operand_ok (rtx op, const char *cons break; case 'X': - result = 1; + /* Although the asm itself doesn't impose any restrictions on + the operand, we still need to restrict it to something that + can be reloaded and printed. + + MEM operands are always reloaded to make them legitimate, + regardless of the constraint, so we need to handle them + in the same way as for 'm' and 'g'. Since 'X' is not treated + as an address constraint, the only other valid operand types + are constants and registers. */ + result = (CONSTANT_P (op) + || general_operand (op, VOIDmode)); break; case 'g': Index: gcc/testsuite/gcc.dg/torture/asm-x-constraint-1.c =================================================================== --- /dev/null 2014-04-15 08:10:27.294524132 +0100 +++ gcc/testsuite/gcc.dg/torture/asm-x-constraint-1.c 2014-04-15 19:11:29.830962008 +0100 @@ -0,0 +1,27 @@ +void +noprop1 (int **x, int y, int z) +{ + int *ptr = *x + y * z / 11; + __asm__ __volatile__ ("noprop1 %0" : : "X" (*ptr)); +} + +void +noprop2 (int **x, int y, int z) +{ + int *ptr = *x + y * z / 11; + __asm__ __volatile__ ("noprop2 %0" : : "X" (ptr)); +} + +int *global_var; + +void +const1 (void) +{ + __asm__ __volatile__ ("const1 %0" : : "X" (global_var)); +} + +void +const2 (void) +{ + __asm__ __volatile__ ("const2 %0" : : "X" (*global_var)); +}