aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgexpand.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2021-05-03 15:11:28 +0200
committerRichard Biener <rguenther@suse.de>2021-05-05 09:11:23 +0200
commit8ebf6b99952ada09bf9ea0144dcd1d46363b0464 (patch)
tree4c5614950602b44572548fc6f3e1be9e85584664 /gcc/cfgexpand.c
parent61d48b1e2b5bae1e0e5e48af296facd61617139c (diff)
downloadgcc-8ebf6b99952ada09bf9ea0144dcd1d46363b0464.zip
gcc-8ebf6b99952ada09bf9ea0144dcd1d46363b0464.tar.gz
gcc-8ebf6b99952ada09bf9ea0144dcd1d46363b0464.tar.bz2
middle-end/100394 - avoid DSE/DCE of pure call that throws
There is -fdelete-dead-exceptions now and we're tracking nothrow and const/pure bits separately and I do remember that const or pure does _not_ imply nothrow. Now, in the light of the PR100382 fix which added a stmt_unremovable_because_of_non_call_eh_p guard to DSEs "DCE" I wondered how -fdelete-dead-exceptions applies to calls and whether stmt_unremovable_because_of_non_call_eh_p doing return (fun->can_throw_non_call_exceptions && !fun->can_delete_dead_exceptions && stmt_could_throw_p (fun, stmt)); really should conditionalize itself on fun->can_throw_non_call_exceptions. In fact DCE happily elides pure function calls that throw without a LHS (probably a consistency bug). The following testcase shows this: int x, y; int __attribute__((pure,noinline)) foo () { if (x) throw 1; return y; } int main() { int a[2]; x = 1; try { int res = foo (); a[0] = res; } catch (...) { return 0; } return 1; } note that if you wrap foo () into another noinline wrap_foo () { foo (); return 1; } function then we need to make sure to not DCE this call either even though it only throws externally. 2021-05-03 Richard Biener <rguenther@suse.de> PR middle-end/100394 * calls.c (expand_call): Preserve possibly throwing calls. * cfgexpand.c (expand_call_stmt): When a call can throw signal RTL expansion there are side-effects. * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Simplify, mark all possibly throwing stmts necessary unless we can elide dead EH. * tree-ssa-dse.c (pass_dse::execute): Preserve exceptions unless -fdelete-dead-exceptions. * tree.h (DECL_PURE_P): Add note about exceptions. * g++.dg/torture/pr100382.C: New testcase.
Diffstat (limited to 'gcc/cfgexpand.c')
-rw-r--r--gcc/cfgexpand.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index a6b48d3..556a0b2 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2795,7 +2795,10 @@ expand_call_stmt (gcall *stmt)
CALL_EXPR_ARG (exp, i) = arg;
}
- if (gimple_has_side_effects (stmt))
+ if (gimple_has_side_effects (stmt)
+ /* ??? Downstream in expand_expr_real_1 we assume that expressions
+ w/o side-effects do not throw so work around this here. */
+ || stmt_could_throw_p (cfun, stmt))
TREE_SIDE_EFFECTS (exp) = 1;
if (gimple_call_nothrow_p (stmt))