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] Fix (or work around?) strength reduction reducing potentially trapping giv computation (PR rtl-optimization/24899)


Hi!

GCC miscompiles the testcase below (distilled from libgnomecanvas)
on at least i386 and x86_64.  Strength reduction transforms
  a = b = 0;
  for (d = 0; d < y; d++)
    {
      if (z)
        b = d * *z;
      for (c = 0; c < x; c++)
        a += b;
    }
to essentially:
  a = b = 0;
  for (d = 0; d < y; d++)
    {
      for (c = 0; c < x; c++)
        a += b;
      b += *z;
    }
which is fine only if z is guaranteed to be non-NULL, but in the testcase
it is NULL and therefore segfaults.
giv discovery in old-loop notices that the giv is not always computable
(and might not be executed every loop), but it seems strength reduction
doesn't care about that.
I have added a debugging printout to loop_givs_reduce and while
GCC reduces a huge number of givs that has !v->always_computable,
those where add_val resp. mult_val also may trap are very rare, in
particular in i386 build only:
gcc/tree-ssa-live.c
gcc/java/constants.c
gcc/ada/fmap.adb
gcc/ada/g-regexp.adb
gcc/ada/xref_lib.adb
gcc/testsuite/gfortran.dg/array_constructor_9.f90
libgfortran/io/write.c
triggered it.  When {mult,add}_val can't trap, I think it is fine to
reduce the giv, it might be computed uselessly, but will not do any harm.
But if it can trap, we can't do it unless we duplicate the condition for it
and I don't think strength reduction attempts to do anything like that.

Is this the right fix or do we need to fix it elsewhere?

2005-12-15  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/24899
	* loop.c (strength_reduce): Don't reduce giv that is not always
	computable and where add_val or mult_val can trap.

	* gcc.c-torture/execute/20051215-1.c: New test.

--- gcc/loop.c.jj	2005-11-21 22:21:41.000000000 +0100
+++ gcc/loop.c	2005-12-15 17:09:56.000000000 +0100
@@ -6486,6 +6486,17 @@ strength_reduce (struct loop *loop, int 
 	      v->ignore = 1;
 	      bl->all_reduced = 0;
 	    }
+	  else if (!v->always_computable
+		   && (may_trap_or_fault_p (v->add_val)
+		       || may_trap_or_fault_p (v->mult_val)))
+	    {
+	      if (loop_dump_stream)
+		fprintf (loop_dump_stream,
+			 "giv of insn %d: not always computable.\n",
+			 INSN_UID (v->insn));
+	      v->ignore = 1;
+	      bl->all_reduced = 0;
+	    }
 	  else
 	    {
 	      /* Check that we can increment the reduced giv without a
--- gcc/testsuite/gcc.c-torture/execute/20051215-1.c.jj	2005-12-15 17:08:00.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/execute/20051215-1.c	2005-12-15 17:07:16.000000000 +0100
@@ -0,0 +1,28 @@
+/* PR rtl-optimization/24899 */
+
+extern void abort (void);
+
+__attribute__ ((noinline)) int
+foo (int x, int y, int *z)
+{
+  int a, b, c, d;
+
+  a = b = 0;
+  for (d = 0; d < y; d++)
+    {
+      if (z)
+	b = d * *z;
+      for (c = 0; c < x; c++)
+	a += b;
+    }
+
+  return a;
+}
+
+int
+main (void)
+{
+  if (foo (3, 2, 0) != 0)
+    abort ();
+  return 0;
+}

	Jakub


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