aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c52
-rw-r--r--gcc/config/i386/i386.md2
4 files changed, 63 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 39f2df0..5c50794cb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2012-08-16 Yuri Rumyantsev <ysrumyan@gmail.com>
+
+ * config/i386/i386-protos.h (ix86_split_lea_for_addr) : Add
+ additional argument.
+ * config/i386/i386.md (ix86_split_lea_for_addr) : Add
+ additional argument curr_insn.
+ * config/i386/i386.c (ix86_split_lea_for_addr): Load base or index
+ register first, depending on their defintion distances.
+ (ix86_lea_outperforms): Prefer LEA only if split cost exceeds
+ AGU stall.
+ (find_nearest_reg-def): New function. Find register with
+ nearest definition.
+
2012-08-16 Walter Lee <walt@tilera.com>
* config.gcc (tilegx-*-linux*): Add feedback.h.
@@ -74,7 +87,7 @@
* config/avr/t-avr: Replace occurrences of $(CC) with $(COMPILER).
* config/avr/avr.c (avr_legitimize_reload_address): Add casts
for reload_type enums.
- (DEF_BUILTIN): Cast the icode to enum insn_code.
+ (DEF_BUILTIN): Cast the icode to enum insn_code.
2012-08-15 Segher Boessenkool <segher@kernel.crashing.org>
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index a1daeda..29bd69a 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -95,7 +95,7 @@ extern bool ix86_binary_operator_ok (enum rtx_code, enum machine_mode, rtx[]);
extern bool ix86_avoid_lea_for_add (rtx, rtx[]);
extern bool ix86_use_lea_for_mov (rtx, rtx[]);
extern bool ix86_avoid_lea_for_addr (rtx, rtx[]);
-extern void ix86_split_lea_for_addr (rtx[], enum machine_mode);
+extern void ix86_split_lea_for_addr (rtx, rtx[], enum machine_mode);
extern bool ix86_lea_for_add_ok (rtx, rtx[]);
extern bool ix86_vec_interleave_v2df_operator_ok (rtx operands[3], bool high);
extern bool ix86_dep_by_shift_count (const_rtx set_insn, const_rtx use_insn);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 624dab1..976bbb4 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -16942,9 +16942,9 @@ ix86_lea_outperforms (rtx insn, unsigned int regno0, unsigned int regno1,
dist_define += split_cost + IX86_LEA_PRIORITY;
/* If there is no use in memory addess then we just check
- that split cost does not exceed AGU stall. */
+ that split cost exceeds AGU stall. */
if (dist_use < 0)
- return dist_define >= LEA_MAX_STALL;
+ return dist_define > LEA_MAX_STALL;
/* If this insn has both backward non-agu dependence and forward
agu dependence, the one with short distance takes effect. */
@@ -17127,13 +17127,41 @@ ix86_emit_binop (enum rtx_code code, enum machine_mode mode,
emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
}
+/* Return true if regno1 def is nearest to the insn. */
+
+static bool
+find_nearest_reg_def (rtx insn, int regno1, int regno2)
+{
+ rtx prev = insn;
+ rtx start = BB_HEAD (BLOCK_FOR_INSN (insn));
+
+ if (insn == start)
+ return false;
+ while (prev && prev != start)
+ {
+ if (!INSN_P (prev) || !NONDEBUG_INSN_P (prev))
+ {
+ prev = PREV_INSN (prev);
+ continue;
+ }
+ if (insn_defines_reg (regno1, INVALID_REGNUM, prev))
+ return true;
+ else if (insn_defines_reg (regno2, INVALID_REGNUM, prev))
+ return false;
+ prev = PREV_INSN (prev);
+ }
+
+ /* None of the regs is defined in the bb. */
+ return false;
+}
+
/* Split lea instructions into a sequence of instructions
which are executed on ALU to avoid AGU stalls.
It is assumed that it is allowed to clobber flags register
at lea position. */
void
-ix86_split_lea_for_addr (rtx operands[], enum machine_mode mode)
+ix86_split_lea_for_addr (rtx insn, rtx operands[], enum machine_mode mode)
{
unsigned int regno0, regno1, regno2;
struct ix86_address parts;
@@ -17220,8 +17248,22 @@ ix86_split_lea_for_addr (rtx operands[], enum machine_mode mode)
tmp = parts.base;
else
{
- emit_insn (gen_rtx_SET (VOIDmode, target, parts.base));
- tmp = parts.index;
+ rtx tmp1;
+
+ /* Find better operand for SET instruction, depending
+ on which definition is farther from the insn. */
+ if (find_nearest_reg_def (insn, regno1, regno2))
+ tmp = parts.index, tmp1 = parts.base;
+ else
+ tmp = parts.base, tmp1 = parts.index;
+
+ emit_insn (gen_rtx_SET (VOIDmode, target, tmp));
+
+ if (parts.disp && parts.disp != const0_rtx)
+ ix86_emit_binop (PLUS, mode, target, parts.disp);
+
+ ix86_emit_binop (PLUS, mode, target, tmp1);
+ return;
}
ix86_emit_binop (PLUS, mode, target, tmp);
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 16a5c13..7756832 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -5520,7 +5520,7 @@
|| GET_CODE (operands[1]) == AND)
mode = SImode;
- ix86_split_lea_for_addr (operands, mode);
+ ix86_split_lea_for_addr (curr_insn, operands, mode);
DONE;
}
[(set_attr "type" "lea")