From a5a9046deb1a43c09e53b7e406319ac7936c2e07 Mon Sep 17 00:00:00 2001
From: Segher Boessenkool <segher@kernel.crashing.org>
Date: Sat, 1 Apr 2017 00:49:53 +0200
Subject: [PATCH] re PR rtl-optimization/79405 (Infinite loop in fwprop)

	PR rtl-optimization/79405
	* fwprop.c (propagations_left): New variable.
	(forward_propagate_into): Decrement it.
	(fwprop_init): Initialize it.
	(fw_prop): If the variable has reached zero, stop propagating.
	(fwprop_addr): Ditto.

gcc/testsuite/
	PR rtl-optimization/79405
	gcc.dg/pr79405.c: New testcase.

From-SVN: r246627
---
 gcc/ChangeLog                  |  9 +++++++
 gcc/fwprop.c                   | 17 +++++++++++++
 gcc/testsuite/ChangeLog        |  5 ++++
 gcc/testsuite/gcc.dg/pr79405.c | 45 ++++++++++++++++++++++++++++++++++
 4 files changed, 76 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/pr79405.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 012d8f825f02..d4096c9a64a0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2017-03-31  Segher Boessenkool  <segher@kernel.crashing.org>
+
+	PR rtl-optimization/79405
+	* fwprop.c (propagations_left): New variable.
+	(forward_propagate_into): Decrement it.
+	(fwprop_init): Initialize it.
+	(fw_prop): If the variable has reached zero, stop propagating.
+	(fwprop_addr): Ditto.
+
 2017-03-31  Jakub Jelinek  <jakub@redhat.com>
 
 	PR debug/79255
diff --git a/gcc/fwprop.c b/gcc/fwprop.c
index 285fb1ab78a2..0ab25efdb856 100644
--- a/gcc/fwprop.c
+++ b/gcc/fwprop.c
@@ -120,6 +120,13 @@ static vec<df_ref> use_def_ref;
 static vec<df_ref> reg_defs;
 static vec<df_ref> reg_defs_stack;
 
+/* The maximum number of propagations that are still allowed.  If we do
+   more propagations than originally we had uses, we must have ended up
+   in a propagation loop, as in PR79405.  Until the algorithm fwprop
+   uses can obviously not get into such loops we need a workaround like
+   this.  */
+static int propagations_left;
+
 /* The MD bitmaps are trimmed to include only live registers to cut
    memory usage on testcases like insn-recog.c.  Track live registers
    in the basic block and do not perform forward propagation if the
@@ -1407,6 +1414,8 @@ forward_propagate_into (df_ref use)
   if (forward_propagate_and_simplify (use, def_insn, def_set)
       || forward_propagate_subreg (use, def_insn, def_set))
     {
+      propagations_left--;
+
       if (cfun->can_throw_non_call_exceptions
 	  && find_reg_note (use_insn, REG_EH_REGION, NULL_RTX)
 	  && purge_dead_edges (DF_REF_BB (use)))
@@ -1434,6 +1443,8 @@ fwprop_init (void)
   active_defs = XNEWVEC (df_ref, max_reg_num ());
   if (flag_checking)
     active_defs_check = sparseset_alloc (max_reg_num ());
+
+  propagations_left = DF_USES_TABLE_SIZE ();
 }
 
 static void
@@ -1480,6 +1491,9 @@ fwprop (void)
 
   for (i = 0; i < DF_USES_TABLE_SIZE (); i++)
     {
+      if (!propagations_left)
+	break;
+
       df_ref use = DF_USES_GET (i);
       if (use)
 	if (DF_REF_TYPE (use) == DF_REF_REG_USE
@@ -1540,6 +1554,9 @@ fwprop_addr (void)
      end, and we'll go through them as well.  */
   for (i = 0; i < DF_USES_TABLE_SIZE (); i++)
     {
+      if (!propagations_left)
+	break;
+
       df_ref use = DF_USES_GET (i);
       if (use)
 	if (DF_REF_TYPE (use) != DF_REF_REG_USE
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d88e067d8405..7f236ac742e5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-03-31  Segher Boessenkool  <segher@kernel.crashing.org>
+
+	PR rtl-optimization/79405
+	gcc.dg/pr79405.c: New testcase.
+
 2017-03-31  Jakub Jelinek  <jakub@redhat.com>
 
 	PR debug/79255
diff --git a/gcc/testsuite/gcc.dg/pr79405.c b/gcc/testsuite/gcc.dg/pr79405.c
new file mode 100644
index 000000000000..c17baff71354
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr79405.c
@@ -0,0 +1,45 @@
+/* PR rtl-optimization/79405 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+char cz;
+long long int xx, u2;
+
+void
+qv (int js, int wl)
+{
+  if (js != 0)
+    {
+      short int sc;
+      int *at = (int *)&sc;
+      long long int gx = 0;
+
+      for (;;)
+	{
+	  *at = 0;
+	  js /= sc;
+
+	  for (wl = 0; wl < 2; ++wl)
+	    {
+	      xx = gx;
+	      u2 %= xx > 0;
+	      cz /= u2;
+
+ fa:
+	      if (cz != u2)
+		{
+		  gx |= js;
+		  cz = gx / js;
+		}
+	    }
+	}
+
+ yq:
+      wl /= 0x80000000;
+      u2 = wl;
+      u2 |= (wl != 0) | (wl != 0 && gx != 0);
+      js = u2;
+      goto fa;
+    }
+  goto yq;
+}
-- 
GitLab