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 RFC: With -fnon-call-exceptions don't eliminate division by zero


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.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Ian


gcc/ChangeLog:

2010-10-11  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-11  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.


Index: tree-vrp.c
===================================================================
--- tree-vrp.c	(revision 165319)
+++ 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)
+	  && flag_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 165319)
+++ simplify-rtx.c	(working copy)
@@ -2751,7 +2751,7 @@ 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) && !flag_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,33 @@
+/* With -fnon-call-exceptions 0 / 0 should not be eliminated.  The .x
+   file sets the option.  */
+
+#ifndef SIGNAL_SUPPRESS
+
+#include <signal.h>
+
+void
+sigfpe (int signum __attribute__ ((unused)))
+{
+  exit (0);
+}
+
+#endif /* !defined (SIGNAL_SUPPRESS) */
+
+/* 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 ()
+{
+#ifndef SIGNAL_SUPPRESS
+  signal (SIGFPE, sigfpe);
+  k = i / j;
+  abort ();
+#else /* defined (SIGNAL_SUPPRESS) */
+  exit (0);
+#endif /* defined (SIGNAL_SUPPRESS) */
+}
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

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