+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.
* 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>
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);
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. */
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;
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);