Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 190362) +++ config/i386/i386.c (working copy) @@ -16942,9 +16942,9 @@ 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,38 @@ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob))); } +/* Return true if regno1 def is nearest to insn and false otherwise. */ +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); + } + return false; /* both regs are not defined in bb. */ +} + /* 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 +17245,18 @@ tmp = parts.base; else { - emit_insn (gen_rtx_SET (VOIDmode, target, parts.base)); - tmp = parts.index; + rtx tmp1; + /* Find better operand for SET instruction which + definition is farther from 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); Index: config/i386/i386-protos.h =================================================================== --- config/i386/i386-protos.h (revision 190362) +++ config/i386/i386-protos.h (working copy) @@ -95,7 +95,7 @@ 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); Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 190362) +++ config/i386/i386.md (working copy) @@ -5517,7 +5517,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")