This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR38819, PREing of trapping expressions
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Daniel Berlin <dberlin at dberlin dot org>
- Date: Sat, 17 Jan 2009 00:36:32 +0100 (CET)
- Subject: [PATCH] Fix PR38819, PREing of trapping expressions
This tries to fix PREing of trapping expressions to a place where
they could be executed when they are not necessarily executed in
their original place. I didn't try to cleverly find out if they
are always executed on the path to the original location but instead
only tried to preserve that phi-translation could make them
non-trapping or that they could be available on all paths.
Any more obvious improvements possible? Can someone SPEC-test this
for me?
Bootstrapped and tested on x86_64-unknown-linux-gnu, Danny, does this
look ok?
Thanks,
Richard.
2009-01-16 Richard Guenther <rguenther@suse.de>
PR tree-optimization/38819
* tree-flow.h (operation_could_trap_helper_p): Declare.
* tree-eh.c (operation_could_trap_helper_p): Export.
* tree-ssa-pre.c (insert_into_preds_of_block): Check if we
are about to insert a possibly trapping instruction and fail
in this case.
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h (revision 143442)
--- gcc/tree-flow.h (working copy)
*************** static inline bool unmodifiable_var_p (c
*** 1071,1076 ****
--- 1071,1078 ----
/* In tree-eh.c */
extern void make_eh_edges (gimple);
extern bool tree_could_trap_p (tree);
+ extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool,
+ bool, tree, bool *);
extern bool operation_could_trap_p (enum tree_code, bool, bool, tree);
extern bool stmt_could_throw_p (gimple);
extern bool tree_could_throw_p (tree);
Index: gcc/tree-eh.c
===================================================================
*** gcc/tree-eh.c (revision 143442)
--- gcc/tree-eh.c (working copy)
*************** verify_eh_edges (gimple stmt)
*** 2067,2073 ****
/* Helper function for operation_could_trap_p and stmt_could_throw_p. */
! static bool
operation_could_trap_helper_p (enum tree_code op,
bool fp_operation,
bool honor_trapv,
--- 2067,2073 ----
/* Helper function for operation_could_trap_p and stmt_could_throw_p. */
! bool
operation_could_trap_helper_p (enum tree_code op,
bool fp_operation,
bool honor_trapv,
Index: gcc/testsuite/gcc.c-torture/execute/pr38819.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/pr38819.c (revision 0)
--- gcc/testsuite/gcc.c-torture/execute/pr38819.c (revision 0)
***************
*** 0 ****
--- 1,29 ----
+ extern void exit (int);
+ extern void abort (void);
+
+ volatile int a = 1;
+ volatile int b = 0;
+ volatile int x = 2;
+ volatile signed int r = 8;
+
+ void __attribute__((noinline))
+ foo (void)
+ {
+ exit (0);
+ }
+
+ int
+ main (void)
+ {
+ int si1 = a;
+ int si2 = b;
+ int i;
+
+ for (i = 0; i < 100; ++i) {
+ foo ();
+ if (x == 8)
+ i++;
+ r += i + si1 % si2;
+ }
+ abort ();
+ }
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c (revision 143442)
--- gcc/tree-ssa-pre.c (working copy)
*************** insert_into_preds_of_block (basic_block
*** 3004,3009 ****
--- 3004,3059 ----
}
}
+ /* Make sure we are not inserting trapping expressions. This is a copy
+ of stmt_could_throw_1_p adjusted to the SCCVN IL. */
+ FOR_EACH_EDGE (pred, ei, block->preds)
+ {
+ vn_nary_op_t nary;
+ tree type;
+ tree rhs2;
+ bool honor_nans = false;
+ bool honor_snans = false;
+ bool fp_operation = false;
+ bool honor_trapv = false;
+ bool handled, ret;
+ unsigned i;
+
+ bprime = pred->src;
+ eprime = avail[bprime->index];
+ if (eprime->kind == NAME
+ || eprime->kind == CONSTANT
+ || eprime->kind == REFERENCE)
+ continue;
+
+ nary = PRE_EXPR_NARY (eprime);
+ if (TREE_CODE_CLASS (nary->opcode) == tcc_comparison
+ || TREE_CODE_CLASS (nary->opcode) == tcc_unary
+ || TREE_CODE_CLASS (nary->opcode) == tcc_binary)
+ {
+ type = nary->type;
+ fp_operation = FLOAT_TYPE_P (type);
+ if (fp_operation)
+ {
+ honor_nans = flag_trapping_math && !flag_finite_math_only;
+ honor_snans = flag_signaling_nans != 0;
+ }
+ else if (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_TRAPS (type))
+ honor_trapv = true;
+ }
+ rhs2 = nary->op[1];
+ ret = operation_could_trap_helper_p (nary->opcode, fp_operation,
+ honor_trapv,
+ honor_nans, honor_snans, rhs2,
+ &handled);
+ if (handled
+ && ret)
+ return false;
+
+ for (i = 0; i < nary->length; ++i)
+ if (tree_could_trap_p (nary->op[i]))
+ return false;
+ }
/* Make the necessary insertions. */
FOR_EACH_EDGE (pred, ei, block->preds)