This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH RFC: With -fnon-call-exceptions don't eliminate division by zero
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 11 Oct 2010 14:16:19 -0700
- Subject: 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