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:
parent
cd794ed4c2
commit
19e51b409e
6 changed files with 126 additions and 68 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue