The following prevents expand_cond_expr_using_cmove from going berzerk
with a large TER tree containing several cond-exprs that eventually
end up failing expansion as cmove.  The attempt to re-do TER failed
somehow earlier this year so the following is a simple stop-gap solution.

Bootstrap & regtest ongoing on x86_64-unknown-linux-gnu.

Richard.

2016-12-14  Richard Biener  <rguent...@suse.de>

        PR middle-end/71632
        * expr.c (expand_cond_expr_using_cmove): Bail out early if
        we end up recursing via TER.

        * gcc.dg/pr71632.c: New testcase.

Index: gcc/expr.c
===================================================================
--- gcc/expr.c  (revision 243632)
+++ gcc/expr.c  (working copy)
@@ -8096,6 +8098,15 @@ expand_cond_expr_using_cmove (tree treeo
   int unsignedp = TYPE_UNSIGNED (type);
   machine_mode mode = TYPE_MODE (type);
   machine_mode orig_mode = mode;
+  static bool expanding_cond_expr_using_cmove = false;
+
+  /* Conditional move expansion can end up TERing two operands which,
+     when recursively hitting conditional expressions can result in
+     exponential behavior if the cmove expansion ultimatively fails.
+     It's hardly profitable to TER a cmove into a cmove so avoid doing
+     that by failing early if we end up recursing.  */
+  if (expanding_cond_expr_using_cmove)
+    return NULL_RTX;
 
   /* If we cannot do a conditional move on the mode, try doing it
      with the promoted mode. */
@@ -8109,6 +8120,7 @@ expand_cond_expr_using_cmove (tree treeo
   else
     temp = assign_temp (type, 0, 1);
 
+  expanding_cond_expr_using_cmove = true;
   start_sequence ();
   expand_operands (treeop1, treeop2,
                   temp, &op1, &op2, EXPAND_NORMAL);
@@ -8143,6 +8155,7 @@ expand_cond_expr_using_cmove (tree treeo
       if (comparison_mode == VOIDmode)
        comparison_mode = TYPE_MODE (TREE_TYPE (treeop0));
     }
+  expanding_cond_expr_using_cmove = false;
 
   if (GET_MODE (op1) != mode)
     op1 = gen_lowpart (mode, op1);
Index: gcc/testsuite/gcc.dg/pr71632.c
===================================================================
--- gcc/testsuite/gcc.dg/pr71632.c      (revision 0)
+++ gcc/testsuite/gcc.dg/pr71632.c      (working copy)
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-loop-if-convert" } */
+
+void
+foo (double d, double *p, double *q)
+{
+  int i;
+  for (i = 0; i < 64; i++)
+    {
+      double t1 = d > p[0] ? 1.0 : 0.0;
+      double t2 = t1 > p[1] ? 1.0 : 0.0;
+      double t3 = t2 > p[2] ? 1.0 : 0.0;
+      double t4 = t3 > p[3] ? 1.0 : 0.0;
+      double t5 = t4 > p[4] ? 1.0 : 0.0;
+      double t6 = t5 > p[5] ? 1.0 : 0.0;
+      double t7 = t6 > p[6] ? 1.0 : 0.0;
+      double t8 = t7 > p[7] ? 1.0 : 0.0;
+      double t9 = t8 > p[8] ? 1.0 : 0.0;
+      double t10 = t9 > p[9] ? 1.0 : 0.0;
+      double t11 = t10 > p[10] ? 1.0 : 0.0;
+      double t12 = t11 > p[11] ? 1.0 : 0.0;
+      double t13 = t12 > p[12] ? 1.0 : 0.0;
+      double t14 = t13 > p[13] ? 1.0 : 0.0;
+      double t15 = t14 > p[14] ? 1.0 : 0.0;
+      double t16 = t15 > p[15] ? 1.0 : 0.0;
+      double t17 = t16 > p[16] ? 1.0 : 0.0;
+      double t18 = t17 > p[17] ? 1.0 : 0.0;
+      double t19 = t18 > p[18] ? 1.0 : 0.0;
+      double t20 = t19 > p[19] ? 1.0 : 0.0;
+      double t21 = t20 > p[20] ? 1.0 : 0.0;
+      double t22 = t21 > p[21] ? 1.0 : 0.0;
+      double t23 = t22 > p[22] ? 1.0 : 0.0;
+      double t24 = t23 > p[23] ? 1.0 : 0.0;
+      double t25 = t24 > p[24] ? 1.0 : 0.0;
+      double t26 = t25 > p[25] ? 1.0 : 0.0;
+      double t27 = t26 > p[26] ? 1.0 : 0.0;
+      double t28 = t27 > p[27] ? 1.0 : 0.0;
+      double t29 = t28 > p[28] ? 1.0 : 0.0;
+      double t30 = t29 > p[29] ? 1.0 : 0.0;
+      double t31 = t30 > p[30] ? 1.0 : 0.0;
+      double t32 = t31 > p[31] ? 1.0 : 0.0;
+      double t33 = t32 > p[32] ? 1.0 : 0.0;
+      double t34 = t33 > p[33] ? 1.0 : 0.0;
+      double t35 = t34 > p[34] ? 1.0 : 0.0;
+      double t36 = t35 > p[35] ? 1.0 : 0.0;
+      double t37 = t36 > p[36] ? 1.0 : 0.0;
+      double t38 = t37 > p[37] ? 1.0 : 0.0;
+      double t39 = t38 > p[38] ? 1.0 : 0.0;
+      *q = t39;
+      p += 39;
+      q++;
+    }
+}

Reply via email to