aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSegher Boessenkool <segher@kernel.crashing.org>2017-04-01 00:49:53 +0200
committerJeff Law <law@gcc.gnu.org>2017-03-31 16:49:53 -0600
commita5a9046deb1a43c09e53b7e406319ac7936c2e07 (patch)
treebf4be001d4d273f6547bada534c9faa1206afa85
parenteee3756de395ab6220f78b471a7cd877301455a2 (diff)
downloadgcc-a5a9046deb1a43c09e53b7e406319ac7936c2e07.zip
gcc-a5a9046deb1a43c09e53b7e406319ac7936c2e07.tar.gz
gcc-a5a9046deb1a43c09e53b7e406319ac7936c2e07.tar.bz2
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
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/fwprop.c17
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr79405.c45
4 files changed, 76 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 012d8f8..d4096c9 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 285fb1a..0ab25ef 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 d88e067..7f236ac 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 0000000..c17baff
--- /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;
+}