On Wed, Sep 24, 2025 at 11:17 AM Andrew Pinski
<[email protected]> wrote:
>
> This moves the optimize_unreachable to forwprop from fab.
> There is a slightly optimization here in that the first
> statement is checked and outside of the main fold loop. And if
> the statement is __builtin_unreachable, then call optimize_unreachable.
>
> Bootstrapped and tested on x86_64-linux-gnu.
>
> PR tree-optimization/121762
> gcc/ChangeLog:
>
> * tree-ssa-ccp.cc (optimize_unreachable): Move to tree-ssa-forwprop.cc
> (pass_fold_builtins::execute): Remove handling of
> __builtin_unreachable.
> * tree-ssa-forwprop.cc (optimize_unreachable): New function from
> tree-ssa-ccp.cc. Change argument to bb. Remove check on first
> statement
> being the __builtin_unreachable since it is handled already.
> (pass_forwprop::execute): Handle first statement as being
> __builtin_unreachable
> by calling optimize_unreachable.
>
> Signed-off-by: Andrew Pinski <[email protected]>
> ---
> gcc/tree-ssa-ccp.cc | 58 -------------------------------------
> gcc/tree-ssa-forwprop.cc | 62 ++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 62 insertions(+), 58 deletions(-)
>
> diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
> index 739d3be9129..b69a8b64a61 100644
> --- a/gcc/tree-ssa-ccp.cc
> +++ b/gcc/tree-ssa-ccp.cc
> @@ -3202,58 +3202,6 @@ optimize_stdarg_builtin (gimple_stmt_iterator *gsi,
> gimple *call)
> }
> }
>
> -/* Attemp to make the block of __builtin_unreachable I unreachable by
> changing
> - the incoming jumps. Return true if at least one jump was changed. */
> -
> -static bool
> -optimize_unreachable (gimple_stmt_iterator i)
> -{
> - basic_block bb = gsi_bb (i);
> - gimple_stmt_iterator gsi;
> - gimple *stmt;
> - edge_iterator ei;
> - edge e;
> - bool ret;
> -
> - if (flag_sanitize & SANITIZE_UNREACHABLE)
> - return false;
> - gsi = gsi_start_nondebug_after_labels_bb (bb);
> - /* Only handle the case that __builtin_unreachable is the first
> - statement in the block. We rely on DCE to remove stmts
> - without side-effects before __builtin_unreachable. */
> - if (*gsi != *i)
> - return false;
> -
> - ret = false;
> - FOR_EACH_EDGE (e, ei, bb->preds)
> - {
> - gsi = gsi_last_bb (e->src);
> - if (gsi_end_p (gsi))
> - continue;
> -
> - stmt = gsi_stmt (gsi);
> - if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
> - {
> - if (e->flags & EDGE_TRUE_VALUE)
> - gimple_cond_make_false (cond_stmt);
> - else if (e->flags & EDGE_FALSE_VALUE)
> - gimple_cond_make_true (cond_stmt);
> - else
> - gcc_unreachable ();
> - update_stmt (cond_stmt);
> - }
> - else
> - {
> - /* Todo: handle other cases. Note that unreachable switch case
> - statements have already been removed. */
> - continue;
> - }
> -
> - ret = true;
> - }
> -
> - return ret;
> -}
>
> /* Convert
> _1 = __atomic_fetch_or_* (ptr_6, 1, _3);
> @@ -4235,12 +4183,6 @@ pass_fold_builtins::execute (function *fun)
> tree result = NULL_TREE;
> switch (DECL_FUNCTION_CODE (callee))
> {
> -
> - case BUILT_IN_UNREACHABLE:
> - if (optimize_unreachable (i))
> - cfg_changed = true;
> - break;
> -
> case BUILT_IN_ATOMIC_ADD_FETCH_1:
> case BUILT_IN_ATOMIC_ADD_FETCH_2:
> case BUILT_IN_ATOMIC_ADD_FETCH_4:
> diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
> index 06ce34c6782..c7ac96a28aa 100644
> --- a/gcc/tree-ssa-forwprop.cc
> +++ b/gcc/tree-ssa-forwprop.cc
> @@ -4903,6 +4903,49 @@ public:
> bool m_full_walk = false;
> }; // class pass_forwprop
>
> +/* Attemp to make the BB block of __builtin_unreachable unreachable by
> changing
> + the incoming jumps. Return true if at least one jump was changed. */
> +
> +static bool
> +optimize_unreachable (basic_block bb)
> +{
> + gimple_stmt_iterator gsi;
> + gimple *stmt;
> + edge_iterator ei;
> + edge e;
> + bool ret;
> +
> + ret = false;
> + FOR_EACH_EDGE (e, ei, bb->preds)
> + {
> + gsi = gsi_last_bb (e->src);
> + if (gsi_end_p (gsi))
> + continue;
> +
> + stmt = gsi_stmt (gsi);
> + if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
> + {
> + if (e->flags & EDGE_TRUE_VALUE)
> + gimple_cond_make_false (cond_stmt);
> + else if (e->flags & EDGE_FALSE_VALUE)
> + gimple_cond_make_true (cond_stmt);
> + else
> + gcc_unreachable ();
> + update_stmt (cond_stmt);
> + }
> + else
> + {
> + /* Todo: handle other cases. Note that unreachable switch case
> + statements have already been removed. */
> + continue;
> + }
> +
> + ret = true;
> + }
> +
> + return ret;
> +}
> +
> unsigned int
> pass_forwprop::execute (function *fun)
> {
> @@ -4949,6 +4992,25 @@ pass_forwprop::execute (function *fun)
> edge_iterator ei;
> edge e;
>
> + if (last_p
> + && !(flag_sanitize & SANITIZE_UNREACHABLE))
> + {
> + gimple_stmt_iterator gsi;
> + gsi = gsi_start_nondebug_after_labels_bb (bb);
> + if (!gsi_end_p (gsi))
> + if (gcall *call = dyn_cast<gcall*>(*gsi))
> + {
> + tree callee = gimple_call_fndecl (call);
> + if (callee
> + && fndecl_built_in_p (callee, BUILT_IN_UNREACHABLE)
> + && optimize_unreachable (bb))
this can be simplified using gimple_call_builtin_p (*gsi, BUILT_IN_UNREACHABLE)
> + {
> + cfg_changed = true;
> + continue;
> + }
> + }
> + }
> +
Please do this after processing not executable blocks.
OK with these changes.
Richard.
> /* Skip processing not executable blocks. We could improve
> single_use tracking by at least unlinking uses from unreachable
> blocks but since blocks with uses are not processed in a
> --
> 2.43.0
>