+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);