re PR rtl-optimization/34503 (Issues with constant/copy propagation implementation...
authorThomas Preud'homme <thomas.preudhomme@arm.com>
Fri, 24 Apr 2015 04:49:34 +0000 (04:49 +0000)
committerThomas Preud'homme <thopre01@gcc.gnu.org>
Fri, 24 Apr 2015 04:49:34 +0000 (04:49 +0000)
2015-04-24  Thomas Preud'homme  <thomas.preudhomme@arm.com>
            Steven Bosscher <steven@gcc.gnu.org>

    gcc/
    PR rtl-optimization/34503
    * cprop.c (cprop_reg_p): New.
    (hash_scan_set): Use above function to check if register can be
    propagated.
    (find_avail_set): Return up to two sets, one whose source is a
    register and one whose source is a constant.  Sets are returned in an
    array passed as parameter rather than as a return value.
    (cprop_insn): Use a do while loop rather than a goto.  Try each of the
    sets returned by find_avail_set, starting with the one whose source is
    a constant. Use cprop_reg_p to check if register can be propagated.
    (do_local_cprop): Use cprop_reg_p to check if register can be
    propagated.
    (implicit_set_cond_p): Likewise.

    gcc/testsuite/
    PR rtl-optimization/34503
    * gcc.target/arm/pr64616.c: New file.

Co-Authored-By: Steven Bosscher <steven@gcc.gnu.org>
From-SVN: r222398

gcc/ChangeLog
gcc/cprop.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/pr64616.c [new file with mode: 0644]

index 2eaacfdfd1418577a53ef338617043f11c8f02c5..7f2d944e6438a78acc4b8ebab44ebebe2b19cbba 100644 (file)
@@ -1,3 +1,20 @@
+2015-04-24  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+           Steven Bosscher <steven@gcc.gnu.org>
+
+       PR rtl-optimization/34503
+       * cprop.c (cprop_reg_p): New.
+       (hash_scan_set): Use above function to check if register can be
+       propagated.
+       (find_avail_set): Return up to two sets, one whose source is a
+       register and one whose source is a constant.  Sets are returned in an
+       array passed as parameter rather than as a return value.
+       (cprop_insn): Use a do while loop rather than a goto.  Try each of the
+       sets returned by find_avail_set, starting with the one whose source is
+       a constant. Use cprop_reg_p to check if register can be propagated.
+       (do_local_cprop): Use cprop_reg_p to check if register can be
+       propagated.
+       (implicit_set_cond_p): Likewise.
+
 2015-04-23  Jan Hubicka  <hubicka@ucw.cz>
 
        * ipa-icf.c (sem_function::equals_wpa): Compare thunk info.
index 0103686563881f1c45ff763f5ae8f6b23468d358..845b6444b2eed209ef90c64d1247b7e10335ff12 100644 (file)
@@ -285,6 +285,15 @@ cprop_constant_p (const_rtx x)
   return CONSTANT_P (x) && (GET_CODE (x) != CONST || shared_const_p (x));
 }
 
+/* Determine whether the rtx X should be treated as a register that can
+   be propagated.  Any pseudo-register is fine.  */
+
+static bool
+cprop_reg_p (const_rtx x)
+{
+  return REG_P (x) && !HARD_REGISTER_P (x);
+}
+
 /* Scan SET present in INSN and add an entry to the hash TABLE.
    IMPLICIT is true if it's an implicit set, false otherwise.  */
 
@@ -295,8 +304,7 @@ hash_scan_set (rtx set, rtx_insn *insn, struct hash_table_d *table,
   rtx src = SET_SRC (set);
   rtx dest = SET_DEST (set);
 
-  if (REG_P (dest)
-      && ! HARD_REGISTER_P (dest)
+  if (cprop_reg_p (dest)
       && reg_available_p (dest, insn)
       && can_copy_p (GET_MODE (dest)))
     {
@@ -321,9 +329,8 @@ hash_scan_set (rtx set, rtx_insn *insn, struct hash_table_d *table,
        src = XEXP (note, 0), set = gen_rtx_SET (VOIDmode, dest, src);
 
       /* Record sets for constant/copy propagation.  */
-      if ((REG_P (src)
+      if ((cprop_reg_p (src)
           && src != dest
-          && ! HARD_REGISTER_P (src)
           && reg_available_p (src, insn))
          || cprop_constant_p (src))
        insert_set_in_table (dest, src, insn, table, implicit);
@@ -821,15 +828,15 @@ try_replace_reg (rtx from, rtx to, rtx_insn *insn)
   return success;
 }
 
-/* Find a set of REGNOs that are available on entry to INSN's block.  Return
-   NULL no such set is found.  */
+/* Find a set of REGNOs that are available on entry to INSN's block.  If found,
+   SET_RET[0] will be assigned a set with a register source and SET_RET[1] a
+   set with a constant source.  If not found the corresponding entry is set to
+   NULL.  */
 
-static struct cprop_expr *
-find_avail_set (int regno, rtx_insn *insn)
+static void
+find_avail_set (int regno, rtx_insn *insn, struct cprop_expr *set_ret[2])
 {
-  /* SET1 contains the last set found that can be returned to the caller for
-     use in a substitution.  */
-  struct cprop_expr *set1 = 0;
+  set_ret[0] = set_ret[1] = NULL;
 
   /* Loops are not possible here.  To get a loop we would need two sets
      available at the start of the block containing INSN.  i.e. we would
@@ -869,8 +876,10 @@ find_avail_set (int regno, rtx_insn *insn)
          If the source operand changed, we may still use it for the next
          iteration of this loop, but we may not use it for substitutions.  */
 
-      if (cprop_constant_p (src) || reg_not_set_p (src, insn))
-       set1 = set;
+      if (cprop_constant_p (src))
+       set_ret[1] = set;
+      else if (reg_not_set_p (src, insn))
+       set_ret[0] = set;
 
       /* If the source of the set is anything except a register, then
         we have reached the end of the copy chain.  */
@@ -881,10 +890,6 @@ find_avail_set (int regno, rtx_insn *insn)
         and see if we have an available copy into SRC.  */
       regno = REGNO (src);
     }
-
-  /* SET1 holds the last set that was available and anticipatable at
-     INSN.  */
-  return set1;
 }
 
 /* Subroutine of cprop_insn that tries to propagate constants into
@@ -1048,40 +1053,40 @@ cprop_insn (rtx_insn *insn)
   int changed = 0, changed_this_round;
   rtx note;
 
-retry:
-  changed_this_round = 0;
-  reg_use_count = 0;
-  note_uses (&PATTERN (insn), find_used_regs, NULL);
-
-  /* We may win even when propagating constants into notes.  */
-  note = find_reg_equal_equiv_note (insn);
-  if (note)
-    find_used_regs (&XEXP (note, 0), NULL);
-
-  for (i = 0; i < reg_use_count; i++)
+  do
     {
-      rtx reg_used = reg_use_table[i];
-      unsigned int regno = REGNO (reg_used);
-      rtx src;
-      struct cprop_expr *set;
+      changed_this_round = 0;
+      reg_use_count = 0;
+      note_uses (&PATTERN (insn), find_used_regs, NULL);
 
-      /* If the register has already been set in this block, there's
-        nothing we can do.  */
-      if (! reg_not_set_p (reg_used, insn))
-       continue;
+      /* We may win even when propagating constants into notes.  */
+      note = find_reg_equal_equiv_note (insn);
+      if (note)
+       find_used_regs (&XEXP (note, 0), NULL);
 
-      /* Find an assignment that sets reg_used and is available
-        at the start of the block.  */
-      set = find_avail_set (regno, insn);
-      if (! set)
-       continue;
+      for (i = 0; i < reg_use_count; i++)
+       {
+         rtx reg_used = reg_use_table[i];
+         unsigned int regno = REGNO (reg_used);
+         rtx src_cst = NULL, src_reg = NULL;
+         struct cprop_expr *set[2];
 
-      src = set->src;
+         /* If the register has already been set in this block, there's
+            nothing we can do.  */
+         if (! reg_not_set_p (reg_used, insn))
+           continue;
 
-      /* Constant propagation.  */
-      if (cprop_constant_p (src))
-       {
-          if (constprop_register (reg_used, src, insn))
+         /* Find an assignment that sets reg_used and is available
+            at the start of the block.  */
+         find_avail_set (regno, insn, set);
+         if (set[0])
+           src_reg = set[0]->src;
+         if (set[1])
+           src_cst = set[1]->src;
+
+         /* Constant propagation.  */
+         if (src_cst && cprop_constant_p (src_cst)
+             && constprop_register (reg_used, src_cst, insn))
            {
              changed_this_round = changed = 1;
              global_const_prop_count++;
@@ -1091,18 +1096,16 @@ retry:
                           "GLOBAL CONST-PROP: Replacing reg %d in ", regno);
                  fprintf (dump_file, "insn %d with constant ",
                           INSN_UID (insn));
-                 print_rtl (dump_file, src);
+                 print_rtl (dump_file, src_cst);
                  fprintf (dump_file, "\n");
                }
              if (insn->deleted ())
                return 1;
            }
-       }
-      else if (REG_P (src)
-              && REGNO (src) >= FIRST_PSEUDO_REGISTER
-              && REGNO (src) != regno)
-       {
-         if (try_replace_reg (reg_used, src, insn))
+         /* Copy propagation.  */
+         else if (src_reg && cprop_reg_p (src_reg)
+                  && REGNO (src_reg) != regno
+                  && try_replace_reg (reg_used, src_reg, insn))
            {
              changed_this_round = changed = 1;
              global_copy_prop_count++;
@@ -1111,7 +1114,7 @@ retry:
                  fprintf (dump_file,
                           "GLOBAL COPY-PROP: Replacing reg %d in insn %d",
                           regno, INSN_UID (insn));
-                 fprintf (dump_file, " with reg %d\n", REGNO (src));
+                 fprintf (dump_file, " with reg %d\n", REGNO (src_reg));
                }
 
              /* The original insn setting reg_used may or may not now be
@@ -1121,12 +1124,10 @@ retry:
                 and made things worse.  */
            }
        }
-
-      /* If try_replace_reg simplified the insn, the regs found
-        by find_used_regs may not be valid anymore.  Start over.  */
-      if (changed_this_round)
-       goto retry;
     }
+  /* If try_replace_reg simplified the insn, the regs found by find_used_regs
+     may not be valid anymore.  Start over.  */
+  while (changed_this_round);
 
   if (changed && DEBUG_INSN_P (insn))
     return 0;
@@ -1189,7 +1190,7 @@ do_local_cprop (rtx x, rtx_insn *insn)
   /* Rule out USE instructions and ASM statements as we don't want to
      change the hard registers mentioned.  */
   if (REG_P (x)
-      && (REGNO (x) >= FIRST_PSEUDO_REGISTER
+      && (cprop_reg_p (x)
           || (GET_CODE (PATTERN (insn)) != USE
              && asm_noperands (PATTERN (insn)) < 0)))
     {
@@ -1205,7 +1206,7 @@ do_local_cprop (rtx x, rtx_insn *insn)
 
          if (cprop_constant_p (this_rtx))
            newcnst = this_rtx;
-         if (REG_P (this_rtx) && REGNO (this_rtx) >= FIRST_PSEUDO_REGISTER
+         if (cprop_reg_p (this_rtx)
              /* Don't copy propagate if it has attached REG_EQUIV note.
                 At this point this only function parameters should have
                 REG_EQUIV notes and if the argument slot is used somewhere
@@ -1326,9 +1327,8 @@ implicit_set_cond_p (const_rtx cond)
   if (GET_CODE (cond) != EQ && GET_CODE (cond) != NE)
     return false;
 
-  /* The first operand of COND must be a pseudo-reg.  */
-  if (! REG_P (XEXP (cond, 0))
-      || HARD_REGISTER_P (XEXP (cond, 0)))
+  /* The first operand of COND must be a register we can propagate.  */
+  if (!cprop_reg_p (XEXP (cond, 0)))
     return false;
 
   /* The second operand of COND must be a suitable constant.  */
index ba700fc1e92e56e13d17aaff65e104561d167c27..bbc0b24ef5edbd28d208996b00f4d4291e0e9df3 100644 (file)
@@ -1,3 +1,9 @@
+2015-04-24  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+           Steven Bosscher <steven@gcc.gnu.org>
+
+       PR rtl-optimization/34503
+       * gcc.target/arm/pr64616.c: New file.
+
 2015-04-24  Bin Cheng  <bin.cheng@arm.com>
 
        * gcc.target/arm/pr42172-1.c: Check str instead of ldr.
diff --git a/gcc/testsuite/gcc.target/arm/pr64616.c b/gcc/testsuite/gcc.target/arm/pr64616.c
new file mode 100644 (file)
index 0000000..c686ffa
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int f (int);
+unsigned int glob;
+
+void
+g ()
+{
+  while (f (glob));
+  glob = 5;
+}
+
+/* { dg-final { scan-assembler-times "ldr" 2 } } */