diff options
author | uros <uros@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-19 19:41:40 +0000 |
---|---|---|
committer | uros <uros@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-19 19:41:40 +0000 |
commit | 1c89d8edd123941446063cdf8e7c9cbb4abcb805 (patch) | |
tree | 6f4f2179a57de20caf607e89ad8103959daede2d | |
parent | 82c53e7765641c8fd9a6705f18d537b3da2894d2 (diff) | |
download | gcc-1c89d8edd123941446063cdf8e7c9cbb4abcb805.tar.gz |
Backport from mainline
2013-11-18 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.c (ix86_decompose_address): Use REG_P instead of
ix86_address_subreg_operand. Move subreg checks to
ix86_validate_address_register. Move address override check to
ix86_legitimate_address_p.
(ix86_validate_address_register): New function.
(ix86_legitimate_address_p): Call ix86_validate_address_register
to validate base and index registers. Add address override check
from ix86_decompose_address.
(ix86_decompose_address): Remove.
Backport from mainline
2013-11-17 Uros Bizjak <ubizjak@gmail.com>
PR target/59153
* config/i386/i386.c (ix86_address_subreg_operand): Do not
reject non-integer subregs.
(ix86_decompose_address): Do not reject invalid CONST_INT RTXes.
Move check for invalid x32 constant addresses ...
(ix86_legitimate_address_p): ... here.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_8-branch@205053 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 25 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 126 |
2 files changed, 85 insertions, 66 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 42b862f5030..4e41b08e5d0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2013-11-19 Uros Bizjak <ubizjak@gmail.com> + + Backport from mainline + 2013-11-18 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.c (ix86_decompose_address): Use REG_P instead of + ix86_address_subreg_operand. Move subreg checks to + ix86_validate_address_register. Move address override check to + ix86_legitimate_address_p. + (ix86_validate_address_register): New function. + (ix86_legitimate_address_p): Call ix86_validate_address_register + to validate base and index registers. Add address override check + from ix86_decompose_address. + (ix86_decompose_address): Remove. + + Backport from mainline + 2013-11-17 Uros Bizjak <ubizjak@gmail.com> + + PR target/59153 + * config/i386/i386.c (ix86_address_subreg_operand): Do not + reject non-integer subregs. + (ix86_decompose_address): Do not reject invalid CONST_INT RTXes. + Move check for invalid x32 constant addresses ... + (ix86_legitimate_address_p): ... here. + 2013-11-19 Richard Biener <rguenther@suse.de> Backport from mainline diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 13dd164846a..542aa70ce42 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -11569,30 +11569,6 @@ ix86_live_on_entry (bitmap regs) } } -/* Determine if op is suitable SUBREG RTX for address. */ - -static bool -ix86_address_subreg_operand (rtx op) -{ - enum machine_mode mode; - - if (!REG_P (op)) - return false; - - mode = GET_MODE (op); - - if (GET_MODE_CLASS (mode) != MODE_INT) - return false; - - /* Don't allow SUBREGs that span more than a word. It can lead to spill - failures when the register is one word out of a two word structure. */ - if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) - return false; - - /* Allow only SUBREGs of non-eliminable hard registers. */ - return register_no_elim_operand (op, mode); -} - /* Extract the parts of an RTL expression that is a valid memory address for an instruction. Return 0 if the structure of the address is grossly off. Return -1 if the address contains ASHIFT, so it is not @@ -11649,7 +11625,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) base = addr; else if (GET_CODE (addr) == SUBREG) { - if (ix86_address_subreg_operand (SUBREG_REG (addr))) + if (REG_P (SUBREG_REG (addr))) base = addr; else return 0; @@ -11713,7 +11689,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) break; case SUBREG: - if (!ix86_address_subreg_operand (SUBREG_REG (op))) + if (!REG_P (SUBREG_REG (op))) return 0; /* FALLTHRU */ @@ -11758,19 +11734,6 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) scale = 1 << scale; retval = -1; } - else if (CONST_INT_P (addr)) - { - if (!x86_64_immediate_operand (addr, VOIDmode)) - return 0; - - /* Constant addresses are sign extended to 64bit, we have to - prevent addresses from 0x80000000 to 0xffffffff in x32 mode. */ - if (TARGET_X32 - && val_signbit_known_set_p (SImode, INTVAL (addr))) - return 0; - - disp = addr; - } else disp = addr; /* displacement */ @@ -11779,18 +11742,12 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) if (REG_P (index)) ; else if (GET_CODE (index) == SUBREG - && ix86_address_subreg_operand (SUBREG_REG (index))) + && REG_P (SUBREG_REG (index))) ; else return 0; } -/* Address override works only on the (%reg) part of %fs:(%reg). */ - if (seg != SEG_DEFAULT - && ((base && GET_MODE (base) != word_mode) - || (index && GET_MODE (index) != word_mode))) - return 0; - /* Extract the integral value of scale. */ if (scale_rtx) { @@ -12266,6 +12223,45 @@ ix86_legitimize_reload_address (rtx x, return false; } +/* Determine if op is suitable RTX for an address register. + Return naked register if a register or a register subreg is + found, otherwise return NULL_RTX. */ + +static rtx +ix86_validate_address_register (rtx op) +{ + enum machine_mode mode = GET_MODE (op); + + /* Only SImode or DImode registers can form the address. */ + if (mode != SImode && mode != DImode) + return NULL_RTX; + + if (REG_P (op)) + return op; + else if (GET_CODE (op) == SUBREG) + { + rtx reg = SUBREG_REG (op); + + if (!REG_P (reg)) + return NULL_RTX; + + mode = GET_MODE (reg); + + /* Don't allow SUBREGs that span more than a word. It can + lead to spill failures when the register is one word out + of a two word structure. */ + if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) + return NULL_RTX; + + /* Allow only SUBREGs of non-eliminable hard registers. */ + if (register_no_elim_operand (reg, mode)) + return reg; + } + + /* Op is not a register. */ + return NULL_RTX; +} + /* Recognizes RTL expressions that are valid memory addresses for an instruction. The MODE argument is the machine mode for the MEM expression that wants to use this address. @@ -12281,6 +12277,7 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, struct ix86_address parts; rtx base, index, disp; HOST_WIDE_INT scale; + enum ix86_address_seg seg; if (ix86_decompose_address (addr, &parts) <= 0) /* Decomposition failed. */ @@ -12290,21 +12287,14 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, index = parts.index; disp = parts.disp; scale = parts.scale; + seg = parts.seg; /* Validate base register. */ if (base) { - rtx reg; + rtx reg = ix86_validate_address_register (base); - if (REG_P (base)) - reg = base; - else if (GET_CODE (base) == SUBREG && REG_P (SUBREG_REG (base))) - reg = SUBREG_REG (base); - else - /* Base is not a register. */ - return false; - - if (GET_MODE (base) != SImode && GET_MODE (base) != DImode) + if (reg == NULL_RTX) return false; if ((strict && ! REG_OK_FOR_BASE_STRICT_P (reg)) @@ -12316,17 +12306,9 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, /* Validate index register. */ if (index) { - rtx reg; - - if (REG_P (index)) - reg = index; - else if (GET_CODE (index) == SUBREG && REG_P (SUBREG_REG (index))) - reg = SUBREG_REG (index); - else - /* Index is not a register. */ - return false; + rtx reg = ix86_validate_address_register (index); - if (GET_MODE (index) != SImode && GET_MODE (index) != DImode) + if (reg == NULL_RTX) return false; if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (reg)) @@ -12340,6 +12322,12 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, && GET_MODE (base) != GET_MODE (index)) return false; + /* Address override works only on the (%reg) part of %fs:(%reg). */ + if (seg != SEG_DEFAULT + && ((base && GET_MODE (base) != word_mode) + || (index && GET_MODE (index) != word_mode))) + return false; + /* Validate scale factor. */ if (scale != 1) { @@ -12461,6 +12449,12 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, && !x86_64_immediate_operand (disp, VOIDmode)) /* Displacement is out of range. */ return false; + /* In x32 mode, constant addresses are sign extended to 64bit, so + we have to prevent addresses from 0x80000000 to 0xffffffff. */ + else if (TARGET_X32 && !(index || base) + && CONST_INT_P (disp) + && val_signbit_known_set_p (SImode, INTVAL (disp))) + return false; } /* Everything looks valid. */ |