Hello! Attached patch moves remaining non-structural checks from ix86_decompose_address to ix86_legitimate_address_p. The patch also introduces ix86_validate_address_register to remove some code duplication.
2013-11-18 Uros Bizjak <ubiz...@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. Tested on x86_64-pc-linux-gnu {,-m32} and committed to mainline SVN. The patch will be backported to other release branches together with previous ix86_decompose_address patch [1]. [1] http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01977.html Uros.
Index: i386.c =================================================================== --- i386.c (revision 204925) +++ i386.c (working copy) @@ -11773,27 +11773,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); - - /* 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 @@ -11850,7 +11829,7 @@ ix86_decompose_address (rtx addr, struct ix86_addr 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; @@ -11914,7 +11893,7 @@ ix86_decompose_address (rtx addr, struct ix86_addr break; case SUBREG: - if (!ix86_address_subreg_operand (SUBREG_REG (op))) + if (!REG_P (SUBREG_REG (op))) return 0; /* FALLTHRU */ @@ -11967,18 +11946,12 @@ ix86_decompose_address (rtx addr, struct ix86_addr 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) { @@ -12495,6 +12468,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. @@ -12510,6 +12522,7 @@ ix86_legitimate_address_p (enum machine_mode mode 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. */ @@ -12519,23 +12532,16 @@ ix86_legitimate_address_p (enum machine_mode mode 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. */ + if (reg == NULL_RTX) return false; - if (GET_MODE (base) != SImode && GET_MODE (base) != DImode) - return false; - if ((strict && ! REG_OK_FOR_BASE_STRICT_P (reg)) || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (reg))) /* Base is not valid. */ @@ -12545,19 +12551,11 @@ ix86_legitimate_address_p (enum machine_mode mode /* Validate index register. */ if (index) { - rtx reg; + rtx reg = ix86_validate_address_register (index); - 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. */ + if (reg == NULL_RTX) return false; - if (GET_MODE (index) != SImode && GET_MODE (index) != DImode) - return false; - if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (reg)) || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (reg))) /* Index is not valid. */ @@ -12569,6 +12567,12 @@ ix86_legitimate_address_p (enum machine_mode mode && 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) {