From: Uros Bizjak Date: Wed, 20 Nov 2013 16:01:46 +0000 (+0100) Subject: backport: re PR target/59153 (ICE: in memory_address_length, at config/i386/i386... X-Git-Tag: releases/gcc-4.7.4~392 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9e05e128b3e772e967bb53951ed5324975662182;p=thirdparty%2Fgcc.git backport: re PR target/59153 (ICE: in memory_address_length, at config/i386/i386.c:24617 with -O -flive-range-shrinkage -mdispatch-scheduler -march=bdver1) Backport from mainline 2013-11-18 Uros Bizjak * 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 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. Bacport from mainline 2012-03-13 Uros Bizjak * config/i386/i386.c (ix86_decompose_address): Prevent %fs:(%reg) addresses only when %reg is not in word mode. From-SVN: r205122 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index edb6a7717ec8..524a9ff2b035 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +2013-11-19 Uros Bizjak + + Backport from mainline + 2013-11-18 Uros Bizjak + + * 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 + + 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. + + Bacport from mainline + 2012-03-13 Uros Bizjak + + * config/i386/i386.c (ix86_decompose_address): Prevent %fs:(%reg) + addresses only when %reg is not in word mode. + 2013-11-10 Karlson2k Kai Tietz diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 4f700a381854..a30c3f6e5feb 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -11434,30 +11434,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 @@ -11522,7 +11498,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; @@ -11580,7 +11556,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 */ @@ -11625,19 +11601,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 */ @@ -11646,7 +11609,7 @@ 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; @@ -12125,6 +12088,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. @@ -12140,6 +12142,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. */ @@ -12149,21 +12152,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; - - 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; + rtx reg = ix86_validate_address_register (base); - if (GET_MODE (base) != SImode && GET_MODE (base) != DImode) + if (reg == NULL_RTX) return false; if ((strict && ! REG_OK_FOR_BASE_STRICT_P (reg)) @@ -12175,17 +12171,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)) @@ -12199,6 +12187,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) { @@ -12320,6 +12314,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. */