+2014-01-13 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <kyrylo.tkachov@arm.com>
* config/arm/arm.h (MAX_CONDITIONAL_EXECUTE): Fix typo in description.
#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.
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;
+}
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 */
+2014-01-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/59387
+ * gcc.c-torture/execute/pr59387.c: New test.
+
2014-01-13 Richard Biener <rguenther@suse.de>
* g++.dg/lto/lto.exp: Do check_effective_target_lto check before
#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,
{
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. */
/* 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);
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)
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);
#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"
#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.
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. */