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
This commit is contained in:
Jakub Jelinek 2014-01-13 20:14:03 +01:00 committed by Jakub Jelinek
parent cd794ed4c2
commit 19e51b409e
6 changed files with 126 additions and 68 deletions

View File

@ -1,3 +1,22 @@
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.

View File

@ -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;
}

View File

@ -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 */

View File

@ -1,3 +1,8 @@
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

View File

@ -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);

View File

@ -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. */