On Fri, Aug 5, 2011 at 8:51 PM, Uros Bizjak <ubiz...@gmail.com> wrote:
> As I read this sentence, the RTX is forced into a temporary register, > and reload tries to satisfy "o" constraint with plus ((reg ...) > (const_int ...)), as said at the introduction of "o" constraint a > couple of pages earlier. Unfortunately, this does not seem to be the > case. > > Is there anything wrong with my approach, or is there something wrong in > reload? To answer my own question, the problem was in *add<dwi>3_doubleword pattern, defined as: (define_insn_and_split "*add<dwi>3_doubleword" [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o") (plus:<DWI> (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0") (match_operand:<DWI> 2 "<general_operand>" "ro<di>,r<di>"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, <DWI>mode, operands)" When reload tried to satisfy alternative 1 (the "o" and matching "0") with a non-offsettable (in this particular case, zero-extended) address, it CSE'd operand 0 and operand 1 to a temporary TImode register. Unfortunately a Timode move has its own constraints: (define_insn "*movti_internal_rex64" [(set (match_operand:TI 0 "nonimmediate_operand" "=!r,o,x,x,xm") (match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))] "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))" where move from/to a general register to/from non-offsettable memory is not valid. Although, it would be nice for reload to subsequently fix CSE'd non-offsetable memory by copying address to temporary reg (*as said in the documentation*), we could simply require an XMM temporary for TImode reloads to/from integer registers, and this fixes ICE for x32. The testcase to play with (gcc -O2 -mx32): --cut here-- void test (__int128 *array, int idx, int off) { __int128 *dest = &array [idx]; dest[0] += 1; dest[off] = 0; } --cut here-- So, following additional patch saves the day: Index: i386/i386.c =================================================================== --- i386/i386.c (revision 177536) +++ i386/i386.c (working copy) @@ -28233,6 +28248,15 @@ ix86_secondary_reload (bool in_p, rtx x, reg_class enum machine_mode mode, secondary_reload_info *sri ATTRIBUTE_UNUSED) { + /* Double-word spills from general registers to non-offsettable + memory references go through XMM register. Following code + handles zero-extended addresses on x32 target. */ + if (TARGET_64BIT + && GET_MODE_SIZE (mode) > UNITS_PER_WORD + && rclass == GENERAL_REGS + && !offsettable_memref_p (x)) + return SSE_REGS; + /* QImode spills from non-QI registers require intermediate register on 32bit targets. */ if (!TARGET_64BIT Uros.