On Wed, Jul 20, 2011 at 9:46 PM, Uros Bizjak <ubiz...@gmail.com> wrote:
>> Note that SUBREG_PROMOTED_UNSIGNED_P wasn't designed for paradoxical subregs, >> but for regular subregs (typically of word-sized objects). You should check >> that the ones created for x32 (because of POINTERS_EXTEND_UNSIGNED I guess) >> are legitimate. I have left out paradoxical subreg stuff ATM and committed following patch that allows subregs of multi-word values in addresses. 2011-07-20 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.c (ix86_decompose_address): Allow only subregs of DImode hard registers in index. (ix86_legitimate_address_p): Allow subregs of base and index to span more than a word. Assert that subregs of base and index satisfy register_no_elim_operand predicates. Reject addresses where base and index have different modes. Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32} and committed to mainline SVN. (I will prepare a followup [RFC] patch that also allows paradoxical (?) subregs for experimenting and testing on x32 target). Uros.
Index: i386.c =================================================================== --- i386.c (revision 176533) +++ i386.c (working copy) @@ -11197,6 +11197,16 @@ ix86_decompose_address (rtx addr, struct else disp = addr; /* displacement */ + if (index) + { + if (REG_P (index)) + ; + /* Allow only subregs of DImode hard regs. */ + else if (GET_CODE (index) == SUBREG + && !register_no_elim_operand (SUBREG_REG (index), DImode)) + return 0; + } + /* Extract the integral value of scale. */ if (scale_rtx) { @@ -11630,23 +11640,18 @@ ix86_legitimate_address_p (enum machine_ disp = parts.disp; scale = parts.scale; - /* Validate base register. - - Don't allow SUBREG's that span more than a word here. It can lead to spill - failures when the base is one word out of a two word structure, which is - represented internally as a DImode int. */ - + /* Validate base register. */ if (base) { rtx reg; if (REG_P (base)) reg = base; - else if (GET_CODE (base) == SUBREG - && REG_P (SUBREG_REG (base)) - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (base))) - <= UNITS_PER_WORD) - reg = SUBREG_REG (base); + else if (GET_CODE (base) == SUBREG && REG_P (SUBREG_REG (base))) + { + reg = SUBREG_REG (base); + gcc_assert (register_no_elim_operand (reg, DImode)); + } else /* Base is not a register. */ return false; @@ -11660,21 +11665,18 @@ ix86_legitimate_address_p (enum machine_ return false; } - /* Validate index register. - - Don't allow SUBREG's that span more than a word here -- same as above. */ - + /* Validate index register. */ if (index) { rtx reg; if (REG_P (index)) reg = index; - else if (GET_CODE (index) == SUBREG - && REG_P (SUBREG_REG (index)) - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (index))) - <= UNITS_PER_WORD) - reg = SUBREG_REG (index); + else if (GET_CODE (index) == SUBREG && REG_P (SUBREG_REG (index))) + { + reg = SUBREG_REG (index); + gcc_assert (register_no_elim_operand (reg, DImode)); + } else /* Index is not a register. */ return false; @@ -11688,6 +11690,11 @@ ix86_legitimate_address_p (enum machine_ return false; } + /* Index and base should have the same mode. */ + if (base && index + && GET_MODE (base) != GET_MODE (index)) + return false; + /* Validate scale factor. */ if (scale != 1) {