aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-ccp.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-03-03 20:32:01 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2017-03-03 20:32:01 +0100
commitcc195d46a3368f3ac333709040fd5055061c663f (patch)
tree850d9624575d4fb7c5cae0530b162295dd6d438e /gcc/tree-ssa-ccp.c
parentf325c4567336a2e5c9643e7adb3a152d22022d7d (diff)
downloadgcc-cc195d46a3368f3ac333709040fd5055061c663f.zip
gcc-cc195d46a3368f3ac333709040fd5055061c663f.tar.gz
gcc-cc195d46a3368f3ac333709040fd5055061c663f.tar.bz2
re PR middle-end/79805 (ICE (verify_flow_info failed) with -fnon-call-exceptions -O)
PR middle-end/79805 * internal-fn.def (ATOMIC_BIT_TEST_AND_SET, ATOMIC_BIT_TEST_AND_RESET, ATOMIC_BIT_TEST_AND_COMPLEMENT, ATOMIC_COMPARE_EXCHANGE): Remove ECF_NOTHROW. * gimple-fold.c (fold_builtin_atomic_compare_exchange): Set gimple_call_nothrow_p flag based on whether original builtin can throw. If it can, emit following stmts on the fallthrough edge. * tree-ssa-ccp.c (optimize_atomic_bit_test_and): Similarly, except don't create new bb if inserting just debug stmts on the edge, try to insert them on the fallthru bb or just reset debug stmts. * g++.dg/opt/pr79805.C: New test. From-SVN: r245882
Diffstat (limited to 'gcc/tree-ssa-ccp.c')
-rw-r--r--gcc/tree-ssa-ccp.c49
1 files changed, 39 insertions, 10 deletions
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 47ca204..cd23824 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -2890,9 +2890,19 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
gimple_set_location (g, gimple_location (call));
gimple_set_vuse (g, gimple_vuse (call));
gimple_set_vdef (g, gimple_vdef (call));
+ bool throws = stmt_can_throw_internal (call);
+ gimple_call_set_nothrow (as_a <gcall *> (g),
+ gimple_call_nothrow_p (as_a <gcall *> (call)));
SSA_NAME_DEF_STMT (gimple_vdef (call)) = g;
gimple_stmt_iterator gsi = *gsip;
gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+ edge e = NULL;
+ if (throws)
+ {
+ maybe_clean_or_replace_eh_stmt (call, g);
+ if (after || (use_bool && has_debug_uses))
+ e = find_fallthru_edge (gsi_bb (gsi)->succs);
+ }
if (after)
{
/* The internal function returns the value of the specified bit
@@ -2905,23 +2915,42 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
use_bool ? build_int_cst (TREE_TYPE (lhs), 1)
: mask);
new_lhs = gimple_assign_lhs (g);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+ if (throws)
+ {
+ gsi_insert_on_edge_immediate (e, g);
+ gsi = gsi_for_stmt (g);
+ }
+ else
+ gsi_insert_after (&gsi, g, GSI_NEW_STMT);
}
if (use_bool && has_debug_uses)
{
- tree temp = make_node (DEBUG_EXPR_DECL);
- DECL_ARTIFICIAL (temp) = 1;
- TREE_TYPE (temp) = TREE_TYPE (lhs);
- SET_DECL_MODE (temp, TYPE_MODE (TREE_TYPE (lhs)));
- tree t = build2 (LSHIFT_EXPR, TREE_TYPE (lhs), new_lhs, bit);
- g = gimple_build_debug_bind (temp, t, g);
- gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+ tree temp = NULL_TREE;
+ if (!throws || after || single_pred_p (e->dest))
+ {
+ temp = make_node (DEBUG_EXPR_DECL);
+ DECL_ARTIFICIAL (temp) = 1;
+ TREE_TYPE (temp) = TREE_TYPE (lhs);
+ SET_DECL_MODE (temp, TYPE_MODE (TREE_TYPE (lhs)));
+ tree t = build2 (LSHIFT_EXPR, TREE_TYPE (lhs), new_lhs, bit);
+ g = gimple_build_debug_bind (temp, t, g);
+ if (throws && !after)
+ {
+ gsi = gsi_after_labels (e->dest);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+ else
+ gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+ }
FOR_EACH_IMM_USE_STMT (g, iter, use_lhs)
if (is_gimple_debug (g))
{
use_operand_p use_p;
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, temp);
+ if (temp == NULL_TREE)
+ gimple_debug_bind_reset_value (g);
+ else
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, temp);
update_stmt (g);
}
}