aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2014-01-13 20:14:03 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2014-01-13 20:14:03 +0100
commit19e51b409e89cb13f388bf2442e3d00b904dddde (patch)
tree3287f7d4ff23c203c29bc715bc7a4141b0081b4c /gcc/gimple-fold.c
parentcd794ed4c2424b3381a5fb09c6f08e53ae919a8a (diff)
downloadgcc-19e51b409e89cb13f388bf2442e3d00b904dddde.zip
gcc-19e51b409e89cb13f388bf2442e3d00b904dddde.tar.gz
gcc-19e51b409e89cb13f388bf2442e3d00b904dddde.tar.bz2
re PR tree-optimization/59387 (wrong code (hangs) at -Os on x86_64-linux-gnu)
PR tree-optimization/59387 * tree-scalar-evolution.c: Include gimple-fold.h and gimplify-me.h. (scev_const_prop): If folded_casts and type has undefined overflow, use force_gimple_operand instead of force_gimple_operand_gsi and for each added stmt if it is assign with arith_code_with_undefined_signed_overflow, call rewrite_to_defined_overflow. * tree-ssa-loop-im.c: Don't include gimplify-me.h, include gimple-fold.h instead. (arith_code_with_undefined_signed_overflow, rewrite_to_defined_overflow): Moved to ... * gimple-fold.c (arith_code_with_undefined_signed_overflow, rewrite_to_defined_overflow): ... here. No longer static. Include gimplify-me.h. * gimple-fold.h (arith_code_with_undefined_signed_overflow, rewrite_to_defined_overflow): New prototypes. * gcc.c-torture/execute/pr59387.c: New test. From-SVN: r206583
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index b2b3876..5dc27e1 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-pretty-print.h"
#include "tree-ssa-address.h"
#include "langhooks.h"
+#include "gimplify-me.h"
/* Return true when DECL can be referenced from current unit.
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@@ -3548,3 +3549,64 @@ gimple_fold_indirect_ref (tree t)
return NULL_TREE;
}
+
+/* Return true if CODE is an operation that when operating on signed
+ integer types involves undefined behavior on overflow and the
+ operation can be expressed with unsigned arithmetic. */
+
+bool
+arith_code_with_undefined_signed_overflow (tree_code code)
+{
+ switch (code)
+ {
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case NEGATE_EXPR:
+ case POINTER_PLUS_EXPR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Rewrite STMT, an assignment with a signed integer or pointer arithmetic
+ operation that can be transformed to unsigned arithmetic by converting
+ its operand, carrying out the operation in the corresponding unsigned
+ type and converting the result back to the original type.
+
+ Returns a sequence of statements that replace STMT and also contain
+ a modified form of STMT itself. */
+
+gimple_seq
+rewrite_to_defined_overflow (gimple stmt)
+{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "rewriting stmt with undefined signed "
+ "overflow ");
+ print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+ }
+
+ tree lhs = gimple_assign_lhs (stmt);
+ tree type = unsigned_type_for (TREE_TYPE (lhs));
+ gimple_seq stmts = NULL;
+ for (unsigned i = 1; i < gimple_num_ops (stmt); ++i)
+ {
+ gimple_seq stmts2 = NULL;
+ gimple_set_op (stmt, i,
+ force_gimple_operand (fold_convert (type,
+ gimple_op (stmt, i)),
+ &stmts2, true, NULL_TREE));
+ gimple_seq_add_seq (&stmts, stmts2);
+ }
+ gimple_assign_set_lhs (stmt, make_ssa_name (type, stmt));
+ if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
+ gimple_assign_set_rhs_code (stmt, PLUS_EXPR);
+ gimple_seq_add_stmt (&stmts, stmt);
+ gimple cvt = gimple_build_assign_with_ops
+ (NOP_EXPR, lhs, gimple_assign_lhs (stmt), NULL_TREE);
+ gimple_seq_add_stmt (&stmts, cvt);
+
+ return stmts;
+}