This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR69619: Fix exponential issue in ccmp.c


This patch fixes an exponential issue in ccmp.c.  When deciding which ccmp
expansion to use, the tree nodes gs0 and gs1 are fully expanded twice.  If
they contain more CCMP opportunities, their subtrees are also expanded twice.
When the trees are complex the expansion takes exponential time and memory.
As a workaround in GCC6 compute the cost of the first expansion early, and
only try the alternative expansion if the cost is low enough.  This rarely
affects real code, eg. SPECINT2006 has identical codesize.

For GCC7 we should improve the way this works and simplify the backend
interface.  I don't see why the backend should expand tree expressions,
especially when they are not part of the CCMP sequence.

OK for commit?

ChangeLog:
2016-02-03  Wilco Dijkstra  <wdijkstr@arm.com>

    gcc/
	PR target/69619
	* ccmp.c (expand_ccmp_expr_1): Avoid evaluating gs0/gs1
	twice when complex.

    gcc/testsuite/

	* gcc.dg/pr69619.c: Add new test.

diff --git a/gcc/ccmp.c b/gcc/ccmp.c
index 9f1ce295554d17c0c3e39676632a07cabe7d5493..dce610488f2d13d6983f3752fb884c8af7ed3bc8 100644
--- a/gcc/ccmp.c
+++ b/gcc/ccmp.c
@@ -183,19 +183,25 @@ expand_ccmp_expr_1 (gimple *g, rtx *prep_seq, rtx *gen_seq)
 					gimple_assign_rhs1 (gs0),
 					gimple_assign_rhs2 (gs0));
 
-	  tmp2 = targetm.gen_ccmp_first (&prep_seq_2, &gen_seq_2, rcode1,
-					 gimple_assign_rhs1 (gs1),
-					 gimple_assign_rhs2 (gs1));
-
-	  if (!tmp && !tmp2)
-	    return NULL_RTX;
-
 	  if (tmp != NULL)
 	    {
 	      ret = expand_ccmp_next (gs1, code, tmp, &prep_seq_1, &gen_seq_1);
 	      cost1 = seq_cost (safe_as_a <rtx_insn *> (prep_seq_1), speed_p);
 	      cost1 += seq_cost (safe_as_a <rtx_insn *> (gen_seq_1), speed_p);
 	    }
+
+	  /* FIXME: Temporary workaround for PR69619.
+	     Avoid exponential compile time due to expanding gs0 and gs1 twice.
+	     If gs0 and gs1 are complex, the cost will be high, so avoid
+	     reevaluation if above an arbitrary threshold.  */
+	  if ((tmp == NULL) || (cost1 < 100))
+	    tmp2 = targetm.gen_ccmp_first (&prep_seq_2, &gen_seq_2, rcode1,
+					   gimple_assign_rhs1 (gs1),
+					   gimple_assign_rhs2 (gs1));
+
+	  if (!tmp && !tmp2)
+	    return NULL_RTX;
+
 	  if (tmp2 != NULL)
 	    {
 	      ret2 = expand_ccmp_next (gs0, code, tmp2, &prep_seq_2,
diff --git a/gcc/testsuite/gcc.dg/pr69619.c b/gcc/testsuite/gcc.dg/pr69619.c
new file mode 100644
index 0000000000000000000000000000000000000000..a200bdf310fc2c02b008e0c13fb9c917784423f8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr69619.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+int a, b, c, d;
+int e[100];
+void
+fn1 ()
+{
+  int *f = &d;
+  c = 6;
+  for (; c; c--)
+    {
+      b = 0;
+      for (; b <= 5; b++)
+	{
+	  short g = e[(b + 2) * 9 + c];
+	  *f = *f == a && e[(b + 2) * 9 + c];
+	}
+    }
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]