diff options
author | Jakub Jelinek <jakub@redhat.com> | 2017-03-03 20:32:01 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2017-03-03 20:32:01 +0100 |
commit | cc195d46a3368f3ac333709040fd5055061c663f (patch) | |
tree | 850d9624575d4fb7c5cae0530b162295dd6d438e /gcc/gimple-fold.c | |
parent | f325c4567336a2e5c9643e7adb3a152d22022d7d (diff) | |
download | gcc-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.c | 36 |
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)), |