From 13a43a90aea368a25da50762eba4873bafb4e448 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 1 Sep 2021 11:49:39 +0200 Subject: [PATCH] tree-optimization/93491 - avoid PRE of trapping calls across exits This makes us avoid PREing calls that could trap across other calls that might not return. The PR88087 testcase has exactly such case so I've refactored the testcase to contain a valid PRE. I've also adjusted PRE to not consider pure calls possibly not returning in line with what we do elsewhere. Note we don't have a good idea whether a function always returns normally or whether its body is known to never trap. That's something IPA could compute. 2021-09-01 Richard Biener PR tree-optimization/93491 * tree-ssa-pre.c (compute_avail): Set BB_MAY_NOTRETURN after processing the stmt itself. Do not consider pure functions possibly not returning. Properly avoid adding possibly trapping calls to EXP_GEN when there's a preceeding possibly not returning call. * tree-ssa-sccvn.c (vn_reference_may_trap): Conservatively not handle calls. * gcc.dg/torture/pr93491.c: New testcase. * gcc.dg/tree-ssa/pr88087.c: Change to valid PRE opportunity. --- gcc/testsuite/gcc.dg/torture/pr93491.c | 24 ++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr88087.c | 18 +++++++------- gcc/tree-ssa-pre.c | 33 +++++++++++++++++++------ gcc/tree-ssa-sccvn.c | 1 + 4 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr93491.c diff --git a/gcc/testsuite/gcc.dg/torture/pr93491.c b/gcc/testsuite/gcc.dg/torture/pr93491.c new file mode 100644 index 00000000000..2cb4c0ca7af --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr93491.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ + +extern void exit (int); + +__attribute__((noipa)) +void f(int i) +{ + exit(i); +} + +__attribute__((const,noipa)) +int g(int i) +{ + return 1 / i; +} + +int main() +{ + while (1) + { + f(0); + f(g(0)); + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88087.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88087.c index d0061b61aed..c48dba5bf21 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr88087.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr88087.c @@ -1,17 +1,17 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +/* { dg-options "-O2 -fno-code-hoisting -fdump-tree-pre-stats" } */ int f(); int d; -void c() +void c(int x) { - for (;;) - { - f(); - int (*fp)() __attribute__((const)) = (void *)f; - d = fp(); - } + int (*fp)() __attribute__((const)) = (void *)f; + if (x) + d = fp (); + int tem = fp (); + f(); + d = tem; } -/* We shouldn't ICE and hoist the const call of fp out of the loop. */ +/* We shouldn't ICE and PRE the const call. */ /* { dg-final { scan-tree-dump "Eliminated: 1" "pre" } } */ diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index ebe95cc6c73..769aadb2315 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -3957,6 +3957,7 @@ compute_avail (function *fun) /* Now compute value numbers and populate value sets with all the expressions computed in BLOCK. */ + bool set_bb_may_notreturn = false; for (gimple_stmt_iterator gsi = gsi_start_bb (block); !gsi_end_p (gsi); gsi_next (&gsi)) { @@ -3965,6 +3966,12 @@ compute_avail (function *fun) stmt = gsi_stmt (gsi); + if (set_bb_may_notreturn) + { + BB_MAY_NOTRETURN (block) = 1; + set_bb_may_notreturn = false; + } + /* Cache whether the basic-block has any non-visible side-effect or control flow. If this isn't a call or it is the last stmt in the @@ -3976,10 +3983,12 @@ compute_avail (function *fun) that forbids hoisting possibly trapping expressions before it. */ int flags = gimple_call_flags (stmt); - if (!(flags & ECF_CONST) + if (!(flags & (ECF_CONST|ECF_PURE)) || (flags & ECF_LOOPING_CONST_OR_PURE) || stmt_can_throw_external (fun, stmt)) - BB_MAY_NOTRETURN (block) = 1; + /* Defer setting of BB_MAY_NOTRETURN to avoid it + influencing the processing of the call itself. */ + set_bb_may_notreturn = true; } FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF) @@ -4030,11 +4039,16 @@ compute_avail (function *fun) /* If the value of the call is not invalidated in this block until it is computed, add the expression to EXP_GEN. */ - if (!gimple_vuse (stmt) - || gimple_code - (SSA_NAME_DEF_STMT (gimple_vuse (stmt))) == GIMPLE_PHI - || gimple_bb (SSA_NAME_DEF_STMT - (gimple_vuse (stmt))) != block) + if ((!gimple_vuse (stmt) + || gimple_code + (SSA_NAME_DEF_STMT (gimple_vuse (stmt))) == GIMPLE_PHI + || gimple_bb (SSA_NAME_DEF_STMT + (gimple_vuse (stmt))) != block) + /* If the REFERENCE traps and there was a preceding + point in the block that might not return avoid + adding the reference to EXP_GEN. */ + && (!BB_MAY_NOTRETURN (block) + || !vn_reference_may_trap (ref))) { result = get_or_alloc_expr_for_reference (ref, gimple_location (stmt)); @@ -4220,6 +4234,11 @@ compute_avail (function *fun) break; } } + if (set_bb_may_notreturn) + { + BB_MAY_NOTRETURN (block) = 1; + set_bb_may_notreturn = false; + } if (dump_file && (dump_flags & TDF_DETAILS)) { diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index bf87cee3857..2357bbdbf90 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -5851,6 +5851,7 @@ vn_reference_may_trap (vn_reference_t ref) case MODIFY_EXPR: case CALL_EXPR: /* We do not handle calls. */ + return true; case ADDR_EXPR: /* And toplevel address computations never trap. */ return false;