diff options
author | Uros Bizjak <ubizjak@gmail.com> | 2011-07-20 23:43:38 +0200 |
---|---|---|
committer | Uros Bizjak <uros@gcc.gnu.org> | 2011-07-20 23:43:38 +0200 |
commit | 00b40d0da26a32c18f696c8f301b51f55960d155 (patch) | |
tree | 60a4c9cc32d02505deb16553b1575c7a5eba5f2e /gcc | |
parent | 87f5355496a23915469b71b0292ab04377cf0ebd (diff) | |
download | gcc-00b40d0da26a32c18f696c8f301b51f55960d155.zip gcc-00b40d0da26a32c18f696c8f301b51f55960d155.tar.gz gcc-00b40d0da26a32c18f696c8f301b51f55960d155.tar.bz2 |
i386.c (ix86_decompose_address): Allow only subregs of DImode hard registers in index.
* 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.
From-SVN: r176536
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 47 |
2 files changed, 39 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a33530a..0451e1b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2011-07-20 Uros Bizjak <ubizjak@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. + 2011-07-20 Robert Millan <rmh@gnu.org> * config.gcc (mips*-*-linux*): Remove redundant tm_file entry. @@ -13,12 +22,11 @@ memory address space to the type's address space. 2011-07-20 Georg-Johann Lay <avr@gjlay.de> - + PR target/36467 PR target/49687 - * config/avr/avr.md (mulhi3): Use register_or_s9_operand for - operand2 and expand appropriately if there is a CONST_INT in - operand2. + * config/avr/avr.md (mulhi3): Use register_or_s9_operand for operand2 + and expand appropriately if there is a CONST_INT in operand2. (usmulqihi3): New insn. (*sumulqihi3): New insn. (*osmulqihi3): New insn. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 22f756b..fbebd4c4 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -11197,6 +11197,16 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) 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_mode mode ATTRIBUTE_UNUSED, 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_mode mode ATTRIBUTE_UNUSED, 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_mode mode ATTRIBUTE_UNUSED, 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) { |