From 19e51b409e89cb13f388bf2442e3d00b904dddde Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 13 Jan 2014 20:14:03 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 19 +++++++++++ gcc/gimple-fold.c | 62 ++++++++++++++++++++++++++++++++++++ gcc/gimple-fold.h | 2 ++ gcc/testsuite/ChangeLog | 5 +++ gcc/tree-scalar-evolution.c | 43 +++++++++++++++++++++---- gcc/tree-ssa-loop-im.c | 63 +------------------------------------ 6 files changed, 126 insertions(+), 68 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 01b10357fb9..4f040a72cb3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2014-01-13 Jakub Jelinek + + 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. + 2014-01-13 Kyrylo Tkachov * config/arm/arm.h (MAX_CONDITIONAL_EXECUTE): Fix typo in description. diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index b2b38765dd6..5dc27e172d9 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; +} diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h index a96be6329ce..886cd02c4dd 100644 --- a/gcc/gimple-fold.h +++ b/gcc/gimple-fold.h @@ -40,5 +40,7 @@ extern tree fold_const_aggregate_ref (tree); extern tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree); extern bool gimple_val_nonnegative_real_p (tree); extern tree gimple_fold_indirect_ref (tree); +extern bool arith_code_with_undefined_signed_overflow (tree_code); +extern gimple_seq rewrite_to_defined_overflow (gimple); #endif /* GCC_GIMPLE_FOLD_H */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 126e6f03727..459e3659005 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-01-13 Jakub Jelinek + + PR tree-optimization/59387 + * gcc.c-torture/execute/pr59387.c: New test. + 2014-01-13 Richard Biener * g++.dg/lto/lto.exp: Do check_effective_target_lto check before diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index 3f4d1cfc917..f1ddc24b1a2 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -286,6 +286,8 @@ along with GCC; see the file COPYING3. If not see #include "dumpfile.h" #include "params.h" #include "tree-ssa-propagate.h" +#include "gimple-fold.h" +#include "gimplify-me.h" static tree analyze_scalar_evolution_1 (struct loop *, tree, tree); static tree analyze_scalar_evolution_for_address_of (struct loop *loop, @@ -3409,7 +3411,7 @@ scev_const_prop (void) { edge exit; tree def, rslt, niter; - gimple_stmt_iterator bsi; + gimple_stmt_iterator gsi; /* If we do not know exact number of iterations of the loop, we cannot replace the final value. */ @@ -3424,7 +3426,7 @@ scev_const_prop (void) /* Ensure that it is possible to insert new statements somewhere. */ if (!single_pred_p (exit->dest)) split_loop_exit_edge (exit); - bsi = gsi_after_labels (exit->dest); + gsi = gsi_after_labels (exit->dest); ex_loop = superloop_at_depth (loop, loop_depth (exit->dest->loop_father) + 1); @@ -3447,7 +3449,9 @@ scev_const_prop (void) continue; } - def = analyze_scalar_evolution_in_loop (ex_loop, loop, def, NULL); + bool folded_casts; + def = analyze_scalar_evolution_in_loop (ex_loop, loop, def, + &folded_casts); def = compute_overall_effect_of_inner_loop (ex_loop, def); if (!tree_does_not_contain_chrecs (def) || chrec_contains_symbols_defined_in_loop (def, ex_loop->num) @@ -3485,10 +3489,37 @@ scev_const_prop (void) def = unshare_expr (def); remove_phi_node (&psi, false); - def = force_gimple_operand_gsi (&bsi, def, false, NULL_TREE, - true, GSI_SAME_STMT); + /* If def's type has undefined overflow and there were folded + casts, rewrite all stmts added for def into arithmetics + with defined overflow behavior. */ + if (folded_casts && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (def))) + { + gimple_seq stmts; + gimple_stmt_iterator gsi2; + def = force_gimple_operand (def, &stmts, true, NULL_TREE); + gsi2 = gsi_start (stmts); + while (!gsi_end_p (gsi2)) + { + gimple stmt = gsi_stmt (gsi2); + gimple_stmt_iterator gsi3 = gsi2; + gsi_next (&gsi2); + gsi_remove (&gsi3, false); + if (is_gimple_assign (stmt) + && arith_code_with_undefined_signed_overflow + (gimple_assign_rhs_code (stmt))) + gsi_insert_seq_before (&gsi, + rewrite_to_defined_overflow (stmt), + GSI_SAME_STMT); + else + gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); + } + } + else + def = force_gimple_operand_gsi (&gsi, def, false, NULL_TREE, + true, GSI_SAME_STMT); + ass = gimple_build_assign (rslt, def); - gsi_insert_before (&bsi, ass, GSI_SAME_STMT); + gsi_insert_before (&gsi, ass, GSI_SAME_STMT); if (dump_file) { print_gimple_stmt (dump_file, ass, 0, 0); diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 7bd0605551c..c5455025b6c 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -35,7 +35,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" -#include "gimplify-me.h" #include "gimple-ssa.h" #include "tree-cfg.h" #include "tree-phinodes.h" @@ -53,6 +52,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-affine.h" #include "tree-ssa-propagate.h" #include "trans-mem.h" +#include "gimple-fold.h" /* TODO: Support for predicated code motion. I.e. @@ -1135,67 +1135,6 @@ public: unsigned int todo_; }; -/* 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. */ - -static 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. */ - -static 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; -} - /* Hoist the statements in basic block BB out of the loops prescribed by data stored in LIM_DATA structures associated with each statement. Callback for walk_dominator_tree. */