aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorUros Bizjak <uros@gcc.gnu.org>2011-08-09 09:38:02 +0200
committerUros Bizjak <uros@gcc.gnu.org>2011-08-09 09:38:02 +0200
commit3968b0504cfc12e1b1f7d6eb385f4d7427a1b32b (patch)
tree33c06d4aae57b46692c60158762e4baab5567af5 /gcc/config
parent2292df601d58ad005a47652004c8b76dafd3f00f (diff)
downloadgcc-3968b0504cfc12e1b1f7d6eb385f4d7427a1b32b.zip
gcc-3968b0504cfc12e1b1f7d6eb385f4d7427a1b32b.tar.gz
gcc-3968b0504cfc12e1b1f7d6eb385f4d7427a1b32b.tar.bz2
re PR target/49781 ([x32] Unnecessary lea in x32 mode)
PR target/49781 * config/i386/i386.md (reload_noff_load): New. (reload_noff_store): Ditto. * config/i386/i386.c (ix86_secondary_reload): Use CODE_FOR_reload_noff_load and CODE_FOR_reload_noff_store to handle double-word moves from/to non-offsetable addresses instead of generating XMM temporary. From-SVN: r177583
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/i386.c15
-rw-r--r--gcc/config/i386/i386.md34
2 files changed, 45 insertions, 4 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 9a21e6b..6810356 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -28247,17 +28247,24 @@ ix86_preferred_output_reload_class (rtx x, reg_class_t regclass)
static reg_class_t
ix86_secondary_reload (bool in_p, rtx x, reg_class_t rclass,
- enum machine_mode mode,
- secondary_reload_info *sri ATTRIBUTE_UNUSED)
+ enum machine_mode mode, secondary_reload_info *sri)
{
/* Double-word spills from general registers to non-offsettable memory
- references (zero-extended addresses) go through XMM register. */
+ references (zero-extended addresses) require special handling. */
if (TARGET_64BIT
&& MEM_P (x)
&& GET_MODE_SIZE (mode) > UNITS_PER_WORD
&& rclass == GENERAL_REGS
&& !offsettable_memref_p (x))
- return SSE_REGS;
+ {
+ sri->icode = (in_p
+ ? CODE_FOR_reload_noff_load
+ : CODE_FOR_reload_noff_store);
+ /* Add the cost of move to a temporary. */
+ sri->extra_cost = 1;
+
+ return NO_REGS;
+ }
/* QImode spills from non-QI registers require
intermediate register on 32bit targets. */
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index ee93e71..9dc5c85 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -2073,6 +2073,40 @@
(const_string "orig")))
(set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,DI,TI,DI,TI,DI,DI,DI,DI,DI")])
+;; Reload patterns to support multi-word load/store
+;; with non-offsetable address.
+(define_expand "reload_noff_store"
+ [(parallel [(match_operand 0 "memory_operand" "=m")
+ (match_operand 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "=&r")])]
+ "TARGET_64BIT"
+{
+ rtx mem = operands[0];
+ rtx addr = XEXP (mem, 0);
+
+ emit_move_insn (operands[2], addr);
+ mem = replace_equiv_address_nv (mem, operands[2]);
+
+ emit_insn (gen_rtx_SET (VOIDmode, mem, operands[1]));
+ DONE;
+})
+
+(define_expand "reload_noff_load"
+ [(parallel [(match_operand 0 "register_operand" "=r")
+ (match_operand 1 "memory_operand" "m")
+ (match_operand:DI 2 "register_operand" "=r")])]
+ "TARGET_64BIT"
+{
+ rtx mem = operands[1];
+ rtx addr = XEXP (mem, 0);
+
+ emit_move_insn (operands[2], addr);
+ mem = replace_equiv_address_nv (mem, operands[2]);
+
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], mem));
+ DONE;
+})
+
;; Convert impossible stores of immediate to existing instructions.
;; First try to get scratch register and go through it. In case this
;; fails, move by 32bit parts.