[4.8 & 4.9] Backport of r211885

Felix Yang fei.yang0953@gmail.com
Wed Oct 8 15:00:00 GMT 2014


The enclosed patch for 4.8 & 4.9 branch is a backport of r211885 from trunk.

The only change is to use:

for (def_rec = DF_INSN_INFO_DEFS (insn_info); *def_rec; def_rec++)

other than the new FOR_EACH_INSN_INFO_DEF interface.

Bootstrapped on x86_64-SUSE-Linux for both branches. OK to apply?


Index: gcc/loop-invariant.c
===================================================================
--- gcc/loop-invariant.c    (revision 216001)
+++ gcc/loop-invariant.c    (working copy)
@@ -839,6 +839,41 @@ check_dependencies (rtx insn, bitmap depends_on)
   return true;
 }

+/* Pre-check candidate DEST to skip the one which can not make a valid insn
+   during move_invariant_reg.  SIMPLE is to skip HARD_REGISTER.  */
+
+static bool
+pre_check_invariant_p (bool simple, rtx dest)
+{
+  if (simple && REG_P (dest) && DF_REG_DEF_COUNT (REGNO (dest)) > 1)
+    {
+      df_ref use;
+      rtx ref;
+      unsigned int i = REGNO (dest);
+      struct df_insn_info *insn_info;
+      df_ref *def_rec;
+
+      for (use = DF_REG_USE_CHAIN (i); use; use = DF_REF_NEXT_REG (use))
+    {
+      ref = DF_REF_INSN (use);
+      insn_info = DF_INSN_INFO_GET (ref);
+
+      for (def_rec = DF_INSN_INFO_DEFS (insn_info); *def_rec; def_rec++)
+        if (DF_REF_REGNO (*def_rec) == i)
+          {
+        /* Multi definitions at this stage, most likely are due to
+           instruction constraints, which requires both read and write
+           on the same register.  Since move_invariant_reg is not
+           powerful enough to handle such cases, just ignore the INV
+           and leave the chance to others.  */
+        return false;
+          }
+    }
+    }
+
+  return true;
+}
+
 /* Finds invariant in INSN.  ALWAYS_REACHED is true if the insn is always
    executed.  ALWAYS_EXECUTED is true if the insn is always executed,
    unless the program ends due to a function call.  */
@@ -869,6 +904,7 @@ find_invariant_insn (rtx insn, bool always_reached
     simple = false;

   if (!may_assign_reg_p (SET_DEST (set))
+      || !pre_check_invariant_p (simple, dest)
       || !check_maybe_invariant (SET_SRC (set)))
     return;


Cheers,
Felix



More information about the Gcc-patches mailing list