i386-protos.h (ix86_split_lea_for_addr): Add additional argument.
authorYuri Rumyantsev <ysrumyan@gmail.com>
Thu, 16 Aug 2012 19:58:11 +0000 (21:58 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Thu, 16 Aug 2012 19:58:11 +0000 (21:58 +0200)
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.

From-SVN: r190452

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md

index 39f2df0764a8d5636101a62f97682d4e0a1c350f..5c50794cbdc6184df2cd7d1162022ccae07ede18 100644 (file)
@@ -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>
 
index a1daedafc6049ed824ac2baaf2371c9d6d131bda..29bd69a4715706dee0a70c32f78e6c180cdc3cc4 100644 (file)
@@ -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);
index 624dab1554d6bf2e0871fba12819a05d5ba19fc0..976bbb4514c5db4462e4e26d98d79e273952a499 100644 (file)
@@ -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);
index 16a5c13bea77d9798f38ab4c79106a11bc501edd..7756832f2ebf5ef1bc7ad37d1fdbb13dfa83a471 100644 (file)
       || 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")