diff mbox

PATCH RFC: With -fnon-call-exceptions don't eliminate division by zero

Message ID mcrr5fk52nn.fsf@google.com
State New
Headers show

Commit Message

Ian Lance Taylor Oct. 20, 2010, 3:01 p.m. UTC
Ian Lance Taylor <iant@google.com> writes:

> The -fnon-call-exceptions options indicates that certain operations,
> including division by zero, should generate an exception.  This includes
> cases like 0 / 0.  This patch ensures that 0 / 0 and any other division
> by zero is not eliminated when -fnon-call-exceptions is used.  This
> includes a test case which fails without the patch and passes with the
> patch.
>
> This patch is entirely in the middle-end so I don't require approval.
> However, I would like to see if there are any comments before I commit
> this.  Thanks.

I plan to commit this version of the patch tomorrow unless I receive
further comments.

gcc/ChangeLog:

2010-10-20  Ian Lance Taylor  <iant@google.com>

	* tree-vrp.c (extract_range_from_binary_expr): If
	flag_non_call_exceptions don't eliminate division by zero.
	* simplify-rtx.c (simplify_binary_operation_1): Likewise.

gcc/testsuite/ChangeLog:

2010-10-20  Ian Lance Taylor  <iant@google.com>

	* gcc.c-torture/execute/20101011-1.c: New test.
	* gcc.c-torture/execute/20101011-1.x: New test driver.
diff mbox

Patch

Index: tree-vrp.c
===================================================================
--- tree-vrp.c	(revision 165727)
+++ tree-vrp.c	(working copy)
@@ -2464,6 +2464,22 @@  extract_range_from_binary_expr (value_ra
 	    }
 	}
 
+      /* For divisions, if flag_non_call_exceptions is true, we must
+	 not eliminate a division by zero.  */
+      if ((code == TRUNC_DIV_EXPR
+	   || code == FLOOR_DIV_EXPR
+	   || code == CEIL_DIV_EXPR
+	   || code == EXACT_DIV_EXPR
+	   || code == ROUND_DIV_EXPR)
+	  && cfun->can_throw_non_call_exceptions
+	  && (vr1.type != VR_RANGE
+	      || symbolic_range_p (&vr1)
+	      || range_includes_zero_p (&vr1)))
+	{
+	  set_value_range_to_varying (vr);
+	  return;
+	}
+
       /* For divisions, if op0 is VR_RANGE, we can deduce a range
 	 even if op1 is VR_VARYING, VR_ANTI_RANGE, symbolic or can
 	 include 0.  */
Index: simplify-rtx.c
===================================================================
--- simplify-rtx.c	(revision 165727)
+++ simplify-rtx.c	(working copy)
@@ -2755,7 +2755,8 @@  simplify_binary_operation_1 (enum rtx_co
       else
 	{
 	  /* 0/x is 0 (or x&0 if x has side-effects).  */
-	  if (trueop0 == CONST0_RTX (mode))
+	  if (trueop0 == CONST0_RTX (mode)
+	      && !cfun->can_throw_non_call_exceptions)
 	    {
 	      if (side_effects_p (op1))
 		return simplify_gen_binary (AND, mode, op1, trueop0);
Index: testsuite/gcc.c-torture/execute/20101011-1.c
===================================================================
--- testsuite/gcc.c-torture/execute/20101011-1.c	(revision 0)
+++ testsuite/gcc.c-torture/execute/20101011-1.c	(revision 0)
@@ -0,0 +1,45 @@ 
+/* With -fnon-call-exceptions 0 / 0 should not be eliminated.  The .x
+   file sets the option.  */
+
+#ifdef SIGNAL_SUPPRESS
+# define DO_TEST 0
+#elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) || defined (__POWERPC__) || defined (__ppc)
+  /* On PPC division by zero does not trap.  */
+# define DO_TEST 0
+#elif defined (__SPU__)
+  /* On SPU division by zero does not trap.  */
+# define DO_TEST 0
+#else
+# define DO_TEST 1
+#endif
+
+#if DO_TEST
+
+#include <signal.h>
+
+void
+sigfpe (int signum __attribute__ ((unused)))
+{
+  exit (0);
+}
+
+#endif
+
+/* When optimizing, the compiler is smart enough to constant fold the
+   static unset variables i and j to produce 0 / 0, but it can't
+   eliminate the assignment to the global k.  */
+static int i;
+static int j;
+int k;
+
+int
+main ()
+{
+#ifdef DO_TEST
+  signal (SIGFPE, sigfpe);
+  k = i / j;
+  abort ();
+#else
+  exit (0);
+#endif
+}
Index: testsuite/gcc.c-torture/execute/20101011-1.x
===================================================================
--- testsuite/gcc.c-torture/execute/20101011-1.x	(revision 0)
+++ testsuite/gcc.c-torture/execute/20101011-1.x	(revision 0)
@@ -0,0 +1,2 @@ 
+set additional_flags "-fnon-call-exceptions"
+return 0