2012-07-24 Uros Bizjak <ubizjak@gmail.com>
PR target/53961
* config/i386/i386.c (ix86_legitimate_address_p): Move check for
negative constant address for TARGET_X32 ...
(ix86_decompose_address): ... here. Reject constant addresses
that don't satisfy x86_64_immediate_operand predicate.
2012-07-23 Uros Bizjak <ubizjak@gmail.com>
PR target/53961
* config/i386/i386.md (*lea): Add asserts to detect invalid addresses.
* config/i386/i386.c (ix86_print_operand_address): Ditto.
(ix86_decompose_address): Allow (zero_extend:DI (subreg:SI (...)))
addresses. Prevent zero extensions of CONST_INT operands.
2012-07-22 Uros Bizjak <ubizjak@gmail.com>
PR target/53961
* config/i386/i386.md (*lea): New insn pattern.
(*lea_1): Remove.
(*lea<mode>_2): Ditto.
(*lea_{3,4,5,6}_zext): Ditto.
* config/i386/predicates.md (lea_address_operand): Do not reject
zero-extended address operands.
* config/i386/constraints.md (j): Remove address constraint.
* config/i386/i386.c (ix86_decompose_address): Allow SImode subreg
of an address.
(ix86_print_operand_address): Handle SImode subreg of an address.
(ix86_avoid_lea_for_addr): Reject zero-extended addresses for now.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@190089
138bc75d-0d04-0410-961f-
82ee72b054a4
+2012-08-02 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2012-07-24 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/53961
+ * config/i386/i386.c (ix86_legitimate_address_p): Move check for
+ negative constant address for TARGET_X32 ...
+ (ix86_decompose_address): ... here. Reject constant addresses
+ that don't satisfy x86_64_immediate_operand predicate.
+
+ 2012-07-23 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/53961
+ * config/i386/i386.md (*lea): Add asserts to detect invalid addresses.
+ * config/i386/i386.c (ix86_print_operand_address): Ditto.
+ (ix86_decompose_address): Allow (zero_extend:DI (subreg:SI (...)))
+ addresses. Prevent zero extensions of CONST_INT operands.
+
+ 2012-07-22 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/53961
+ * config/i386/i386.md (*lea): New insn pattern.
+ (*lea_1): Remove.
+ (*lea<mode>_2): Ditto.
+ (*lea_{3,4,5,6}_zext): Ditto.
+ * config/i386/predicates.md (lea_address_operand): Do not reject
+ zero-extended address operands.
+ * config/i386/constraints.md (j): Remove address constraint.
+ * config/i386/i386.c (ix86_decompose_address): Allow SImode subreg
+ of an address.
+ (ix86_print_operand_address): Handle SImode subreg of an address.
+ (ix86_avoid_lea_for_addr): Reject zero-extended addresses for now.
+
2012-08-01 Uros Bizjak <ubizjak@gmail.com>
Backport from mainline
;;; Unused letters:
;;; B H T W
-;;; h k v
+;;; h jk v
;; Integer register constraints.
;; It is not necessary to define 'r' here.
(and (not (match_test "TARGET_X32"))
(match_operand 0 "memory_operand")))
-(define_address_constraint "j"
- "@internal Address operand that can be zero extended in LEA instruction."
- (and (not (match_code "const_int"))
- (match_operand 0 "address_operand")))
-
;; Integer constant constraints.
(define_constraint "I"
"Integer constant in the range 0 @dots{} 31, for 32-bit shifts."
{
if (GET_CODE (addr) == ZERO_EXTEND
&& GET_MODE (XEXP (addr, 0)) == SImode)
- addr = XEXP (addr, 0);
+ {
+ addr = XEXP (addr, 0);
+ if (CONST_INT_P (addr))
+ return 0;
+ }
else if (GET_CODE (addr) == AND
&& const_32bit_mask (XEXP (addr, 1), DImode))
{
addr = XEXP (addr, 0);
- /* Strip subreg. */
+ /* Adjust SUBREGs. */
if (GET_CODE (addr) == SUBREG
&& GET_MODE (SUBREG_REG (addr)) == SImode)
- addr = SUBREG_REG (addr);
+ {
+ addr = SUBREG_REG (addr);
+ if (CONST_INT_P (addr))
+ return 0;
+ }
+ else if (GET_MODE (addr) == DImode)
+ addr = gen_rtx_SUBREG (SImode, addr, 0);
+ else if (GET_MODE (addr) != VOIDmode)
+ return 0;
+ }
+ }
+
+ /* Allow SImode subregs of DImode addresses,
+ they will be emitted with addr32 prefix. */
+ if (TARGET_64BIT && GET_MODE (addr) == SImode)
+ {
+ if (GET_CODE (addr) == SUBREG
+ && GET_MODE (SUBREG_REG (addr)) == DImode)
+ {
+ addr = SUBREG_REG (addr);
+ if (CONST_INT_P (addr))
+ return 0;
}
}
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 */
rtx base, index, disp;
HOST_WIDE_INT scale;
- /* Since constant address in x32 is signed extended to 64bit,
- we have to prevent addresses from 0x80000000 to 0xffffffff. */
- if (TARGET_X32
- && CONST_INT_P (addr)
- && INTVAL (addr) < 0)
- return false;
-
if (ix86_decompose_address (addr, &parts) <= 0)
/* Decomposition failed. */
return false;
}
else
{
- /* Print SImode register names for zero-extended
- addresses to force addr32 prefix. */
- if (TARGET_64BIT
- && (GET_CODE (addr) == ZERO_EXTEND
- || GET_CODE (addr) == AND))
+ /* Print SImode register names to force addr32 prefix. */
+ if (GET_CODE (addr) == SUBREG)
{
+ gcc_assert (TARGET_64BIT);
+ gcc_assert (GET_MODE (addr) == SImode);
+ gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
+ gcc_assert (!code);
+ code = 'l';
+ }
+ else if (GET_CODE (addr) == ZERO_EXTEND
+ || GET_CODE (addr) == AND)
+ {
+ gcc_assert (TARGET_64BIT);
+ gcc_assert (GET_MODE (addr) == DImode);
gcc_assert (!code);
code = 'l';
}
struct ix86_address parts;
int ok;
+ /* FIXME: Handle zero-extended addresses. */
+ if (GET_CODE (operands[1]) == ZERO_EXTEND
+ || GET_CODE (operands[1]) == AND)
+ return false;
+
/* Check we need to optimize. */
if (!TARGET_OPT_AGU || optimize_function_for_size_p (cfun))
return false;
DONE;
})
\f
+;; Load effective address instructions
+
+(define_insn_and_split "*lea<mode>"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (match_operand:SWI48 1 "lea_address_operand" "p"))]
+ ""
+{
+ rtx addr = operands[1];
+
+ if (GET_CODE (addr) == SUBREG)
+ {
+ gcc_assert (TARGET_64BIT);
+ gcc_assert (<MODE>mode == SImode);
+ gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
+ return "lea{l}\t{%E1, %0|%0, %E1}";
+ }
+ else if (GET_CODE (addr) == ZERO_EXTEND
+ || GET_CODE (addr) == AND)
+ {
+ gcc_assert (TARGET_64BIT);
+ gcc_assert (<MODE>mode == DImode);
+ return "lea{l}\t{%E1, %k0|%k0, %E1}";
+ }
+ else
+ return "lea{<imodesuffix>}\t{%E1, %0|%0, %E1}";
+}
+ "reload_completed && ix86_avoid_lea_for_addr (insn, operands)"
+ [(const_int 0)]
+{
+ ix86_split_lea_for_addr (operands, <MODE>mode);
+ DONE;
+}
+ [(set_attr "type" "lea")
+ (set_attr "mode" "<MODE>")])
+\f
;; Add instructions
(define_expand "add<mode>3"
[(set_attr "type" "alu")
(set_attr "mode" "QI")])
-(define_insn_and_split "*lea_1"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (subreg:SI (match_operand:DI 1 "lea_address_operand" "p") 0))]
- "TARGET_64BIT"
- "lea{l}\t{%E1, %0|%0, %E1}"
- "&& reload_completed && ix86_avoid_lea_for_addr (insn, operands)"
- [(const_int 0)]
-{
- ix86_split_lea_for_addr (operands, SImode);
- DONE;
-}
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
-
-(define_insn_and_split "*lea<mode>_2"
- [(set (match_operand:SWI48 0 "register_operand" "=r")
- (match_operand:SWI48 1 "lea_address_operand" "p"))]
- ""
- "lea{<imodesuffix>}\t{%E1, %0|%0, %E1}"
- "reload_completed && ix86_avoid_lea_for_addr (insn, operands)"
- [(const_int 0)]
-{
- ix86_split_lea_for_addr (operands, <MODE>mode);
- DONE;
-}
- [(set_attr "type" "lea")
- (set_attr "mode" "<MODE>")])
-
-(define_insn "*lea_3_zext"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (subreg:SI (match_operand:DI 1 "lea_address_operand" "j") 0)))]
- "TARGET_64BIT"
- "lea{l}\t{%E1, %k0|%k0, %E1}"
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
-
-(define_insn "*lea_4_zext"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (match_operand:SI 1 "lea_address_operand" "j")))]
- "TARGET_64BIT"
- "lea{l}\t{%E1, %k0|%k0, %E1}"
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
-
-(define_insn "*lea_5_zext"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (and:DI
- (subreg:DI (match_operand:SI 1 "lea_address_operand" "p") 0)
- (match_operand:DI 2 "const_32bit_mask" "n")))]
- "TARGET_64BIT"
- "lea{l}\t{%E1, %k0|%k0, %E1}"
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
-
-(define_insn "*lea_6_zext"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (and:DI
- (match_operand:DI 1 "lea_address_operand" "p")
- (match_operand:DI 2 "const_32bit_mask" "n")))]
- "TARGET_64BIT"
- "lea{l}\t{%E1, %k0|%k0, %E1}"
- [(set_attr "type" "lea")
- (set_attr "mode" "SI")])
-
(define_insn "*add<mode>_1"
[(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r")
(plus:SWI48
struct ix86_address parts;
int ok;
- /* LEA handles zero-extend by itself. */
- if (GET_CODE (op) == ZERO_EXTEND
- || GET_CODE (op) == AND)
- return false;
-
ok = ix86_decompose_address (op, &parts);
gcc_assert (ok);
return parts.seg == SEG_DEFAULT;