aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.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/gimple-fold.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/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index a75dd91..9fd45d1 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -3533,6 +3533,8 @@ fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *gsi)
tree itype = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (parmt)));
tree ctype = build_complex_type (itype);
tree expected = TREE_OPERAND (gimple_call_arg (stmt, 1), 0);
+ bool throws = false;
+ edge e = NULL;
gimple *g = gimple_build_assign (make_ssa_name (TREE_TYPE (expected)),
expected);
gsi_insert_before (gsi, g, GSI_SAME_STMT);
@@ -3558,19 +3560,39 @@ fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *gsi)
gimple_set_vdef (g, gimple_vdef (stmt));
gimple_set_vuse (g, gimple_vuse (stmt));
SSA_NAME_DEF_STMT (gimple_vdef (g)) = g;
- if (gimple_call_lhs (stmt))
+ tree oldlhs = gimple_call_lhs (stmt);
+ if (stmt_can_throw_internal (stmt))
+ {
+ throws = true;
+ e = find_fallthru_edge (gsi_bb (*gsi)->succs);
+ }
+ gimple_call_set_nothrow (as_a <gcall *> (g),
+ gimple_call_nothrow_p (as_a <gcall *> (stmt)));
+ gimple_call_set_lhs (stmt, NULL_TREE);
+ gsi_replace (gsi, g, true);
+ if (oldlhs)
{
- gsi_insert_before (gsi, g, GSI_SAME_STMT);
g = gimple_build_assign (make_ssa_name (itype), IMAGPART_EXPR,
build1 (IMAGPART_EXPR, itype, lhs));
- gsi_insert_before (gsi, g, GSI_SAME_STMT);
- g = gimple_build_assign (gimple_call_lhs (stmt), NOP_EXPR,
- gimple_assign_lhs (g));
+ if (throws)
+ {
+ gsi_insert_on_edge_immediate (e, g);
+ *gsi = gsi_for_stmt (g);
+ }
+ else
+ gsi_insert_after (gsi, g, GSI_NEW_STMT);
+ g = gimple_build_assign (oldlhs, NOP_EXPR, gimple_assign_lhs (g));
+ gsi_insert_after (gsi, g, GSI_NEW_STMT);
}
- gsi_replace (gsi, g, true);
g = gimple_build_assign (make_ssa_name (itype), REALPART_EXPR,
build1 (REALPART_EXPR, itype, lhs));
- gsi_insert_after (gsi, g, GSI_NEW_STMT);
+ if (throws && oldlhs == NULL_TREE)
+ {
+ gsi_insert_on_edge_immediate (e, g);
+ *gsi = gsi_for_stmt (g);
+ }
+ else
+ gsi_insert_after (gsi, g, GSI_NEW_STMT);
if (!useless_type_conversion_p (TREE_TYPE (expected), itype))
{
g = gimple_build_assign (make_ssa_name (TREE_TYPE (expected)),