The result of expand_expr_addr_expr_1 is eventually converted to tmode, and any variable offset is likewise applied in tmode, so tmode also seems like the natural mode for applying constant offsets. This patch makes sure that the operand is converted to tmode first, just like we do for variable offsets. It fixes a case where the new plus_constant assert triggers.
Tested on x86_64-linux-gnu. Also tested by HJ on x32 (thanks). OK to install? Richard gcc/ PR middle-end/53698 * expr.c (expand_expr_addr_expr_1): Convert to tmode before performing an addition. gcc/testsuite/ PR middle-end/53698 * gcc.target/i386/pr53698.c: New test. Index: gcc/expr.c =================================================================== --- gcc/expr.c 2012-06-06 10:09:21.000000000 +0100 +++ gcc/expr.c 2012-06-18 09:35:35.361926943 +0100 @@ -7631,6 +7631,7 @@ expand_expr_addr_expr_1 (tree exp, rtx t of such an object. */ gcc_assert ((bitpos % BITS_PER_UNIT) == 0); + result = convert_memory_address_addr_space (tmode, result, as); result = plus_constant (tmode, result, bitpos / BITS_PER_UNIT); if (modifier < EXPAND_SUM) result = force_operand (result, target); Index: gcc/testsuite/gcc.target/i386/pr53698.c =================================================================== --- /dev/null 2012-05-16 15:38:36.131804707 +0100 +++ gcc/testsuite/gcc.target/i386/pr53698.c 2012-06-18 09:36:01.033855874 +0100 @@ -0,0 +1,16 @@ +/* { dg-do compile { target { ! { ia32 } } } } */ +/* { dg-options "-O -mx32 -maddress-mode=long -fno-tree-dominator-opts" } */ + +extern char foo[]; + +void +test2 (void) +{ + int s; + for (s = 0;; ++s) + { + if (foo[s] != s) + __builtin_abort (); + foo[s] = s; + } +}