Hi Alfie, > On 9 Jul 2026, at 10:24, Alfie Richards <[email protected]> wrote: > > On 06/07/2026 09:40, Kyrylo Tkachov wrote: >>> On 3 Jul 2026, at 13:56, Kyrylo Tkachov <[email protected]> wrote: >>> >>> >>> >>>> On 2 Jul 2026, at 10:56, Richard Biener <[email protected]> wrote: >>>> >>>> On Thu, 2 Jul 2026, [email protected] wrote: >>>> >>>>> From: Kyrylo Tkachov <[email protected]> >>>>> >>>>> pass_split_paths duplicates the join block of an IF-THEN-ELSE that feeds a >>>>> loop latch, splitting the two paths to the backedge. It runs only at -O3. >>>>> In practice it interacts badly with later optimizations: it duplicates the >>>>> loop body before loads have been commoned and before if-conversion runs, >>>>> so >>>>> it can block both loop unrolling (PR120892) and if-conversion of the >>>>> duplicated diamond, while its own heuristic already declines about half of >>>>> all candidate blocks, most often to avoid spoiling if-conversion. >>>>> >>>>> Remove the pass and deprecate the -fsplit-paths option. The option is >>>>> kept >>>>> accepted for backward compatibility via the Ignore flag and now does >>>>> nothing, >>>>> matching how other optimization options have been retired (for example >>>>> -ftree-lrs). param_max_jump_thread_duplication_stmts is retained as it is >>>>> shared with the jump-threading passes. >>>>> >>>>> Statistics from the pass on SPEC CPU 2026 (intrate + fprate, counted from >>>>> the >>>>> split-paths dump): >>>>> >>>>> candidates splits declined to protect >>>>> if-conversion >>>>> -O3 122894 62050 60844 37166 >>>>> -O3 -flto=auto 52423 21257 31166 21822 >>>>> >>>>> The pass splits about half of the blocks it considers and declines the >>>>> rest, >>>>> most often to avoid spoiling if-conversion. The duplication grows .text >>>>> by >>>>> 0.32% at -O3 and 0.24% at -O3 -flto=auto. >>>>> >>>>> Andrea and Jeff indicated in PR120892 that removing -fsplit-paths may be >>>>> the way to go there. >>>>> >>>>> -fsplit-paths also complicates the control-flow and defeats the >>>>> load-commoning necessary to get good if-conversion of the hot loop from >>>>> Snappy from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125557#c13 . >>>>> >>>>> Bootstrapped and tested on aarch64-none-linux-gnu and x86_64-linux. >>>> >>>> OK. >>>> >>>> Please leave others a day or so to chime in. >>> >>> Thanks, I’ll push next wee once the USA have had their holidays. >>> Kyrill >> Pushed now as g:5c23bb074af23f00dd3fe1745b9dd99245fa4bba > Hi, > > Just to note we see about a 3% regression on spec2006.intrate.462.libquantum > from this change on Neoverse-V1.
I’m having a look. I don’t have access to a Neoverse V1 but I’ll try to reproduce it on the machines that I have access to and see if I can raise a GCC PR to record whatever missed optimisation this may be exposing so that we can decide if we want to implement it in some other way. Thanks, Kyrill > > Thanks, > Alfie >>> >>>> >>>> Thanks, >>>> Richard. >>>> >>>>> gcc/ChangeLog: >>>>> >>>>> PR tree-optimization/120892 >>>>> * gimple-ssa-split-paths.cc: Remove. >>>>> * passes.def (pass_split_paths): Remove. >>>>> * tree-pass.h (make_pass_split_paths): Remove. >>>>> * Makefile.in (OBJS): Remove gimple-ssa-split-paths.o. >>>>> * timevar.def (TV_SPLIT_PATHS): Remove. >>>>> * opts.cc (default_options_table): Remove the OPT_LEVELS_3_PLUS entry >>>>> for OPT_fsplit_paths. >>>>> * common.opt (fsplit-paths): Make it a deprecated no-op using Ignore. >>>>> * doc/invoke.texi (-fsplit-paths): Document as deprecated and remove it >>>>> from the option summary and the -O3 list. >>>>> >>>>> gcc/testsuite/ChangeLog: >>>>> >>>>> PR tree-optimization/120892 >>>>> * gcc.dg/tree-ssa/split-path-1.c: Move to... >>>>> * gcc.c-torture/execute/split-path-1.c: ...here. Adjust to a plain >>>>> compile and run test without the split-paths dump scan. >>>>> * gcc.dg/tree-ssa/split-path-2.c: Move to... >>>>> * gcc.c-torture/compile/split-path-2.c: ...here. Adjust to a >>>>> compile-only test without the split-paths dump scan. >>>>> * gcc.dg/tree-ssa/split-path-3.c: Move to... >>>>> * gcc.c-torture/compile/split-path-3.c: ...here. Likewise. >>>>> * gcc.dg/tree-ssa/split-path-4.c: Move to... >>>>> * gcc.c-torture/compile/split-path-4.c: ...here. Likewise. >>>>> * gcc.dg/tree-ssa/split-path-5.c: Move to... >>>>> * gcc.c-torture/compile/split-path-5.c: ...here. Likewise. >>>>> * gcc.dg/tree-ssa/split-path-6.c: Move to... >>>>> * gcc.c-torture/compile/split-path-6.c: ...here. Likewise. >>>>> * gcc.dg/tree-ssa/split-path-7.c: Move to... >>>>> * gcc.c-torture/compile/split-path-7.c: ...here. Likewise. >>>>> * gcc.dg/tree-ssa/split-path-8.c: Move to... >>>>> * gcc.c-torture/compile/split-path-8.c: ...here. Likewise. >>>>> * gcc.dg/tree-ssa/split-path-9.c: Move to... >>>>> * gcc.c-torture/compile/split-path-9.c: ...here. Likewise. >>>>> * gcc.dg/tree-ssa/split-path-10.c: Move to... >>>>> * gcc.c-torture/compile/split-path-10.c: ...here. Likewise. >>>>> * gcc.dg/tree-ssa/split-path-11.c: Move to... >>>>> * gcc.c-torture/compile/split-path-11.c: ...here. Likewise. >>>>> * gcc.dg/tree-ssa/split-path-12.c: Move to... >>>>> * gcc.c-torture/compile/split-path-12.c: ...here. Likewise. >>>>> * gcc.dg/tree-ssa/split-path-13.c: Move to... >>>>> * gcc.c-torture/compile/split-path-13.c: ...here. Likewise. >>>>> * gcc.dg/tree-ssa/pr69270.c: Move to... >>>>> * gcc.c-torture/compile/pr69270.c: ...here. Likewise. >>>>> * g++.dg/tree-ssa/pr88797.C: Move to... >>>>> * g++.dg/torture/pr88797.C: ...here. Adjust to a compile-only test. >>>>> * gcc.target/i386/pr106450.c: Remove -fsplit-paths from dg-options. >>>>> >>>>> Signed-off-by: Kyrylo Tkachov <[email protected]> >>>>> --- >>>>> gcc/Makefile.in | 1 - >>>>> gcc/common.opt | 4 +- >>>>> gcc/doc/invoke.texi | 8 +- >>>>> gcc/gimple-ssa-split-paths.cc | 545 ------------------ >>>>> gcc/opts.cc | 1 - >>>>> gcc/passes.def | 1 - >>>>> gcc/testsuite/g++.dg/torture/pr88797.C | 13 + >>>>> gcc/testsuite/g++.dg/tree-ssa/pr88797.C | 16 - >>>>> .../compile}/pr69270.c | 7 - >>>>> .../compile}/split-path-10.c | 3 - >>>>> .../compile}/split-path-11.c | 3 - >>>>> .../compile}/split-path-12.c | 3 - >>>>> .../compile}/split-path-13.c | 3 - >>>>> .../gcc.c-torture/compile/split-path-2.c | 18 + >>>>> .../compile}/split-path-3.c | 3 - >>>>> .../compile}/split-path-4.c | 3 - >>>>> .../compile}/split-path-5.c | 3 - >>>>> .../compile}/split-path-6.c | 3 - >>>>> .../compile}/split-path-7.c | 3 - >>>>> .../gcc.c-torture/compile/split-path-8.c | 11 + >>>>> .../gcc.c-torture/compile/split-path-9.c | 14 + >>>>> .../execute}/split-path-1.c | 3 - >>>>> gcc/testsuite/gcc.dg/tree-ssa/split-path-2.c | 21 - >>>>> gcc/testsuite/gcc.dg/tree-ssa/split-path-8.c | 14 - >>>>> gcc/testsuite/gcc.dg/tree-ssa/split-path-9.c | 17 - >>>>> gcc/testsuite/gcc.target/i386/pr106450.c | 2 +- >>>>> gcc/timevar.def | 1 - >>>>> gcc/tree-pass.h | 1 - >>>>> 28 files changed, 62 insertions(+), 663 deletions(-) >>>>> delete mode 100644 gcc/gimple-ssa-split-paths.cc >>>>> create mode 100644 gcc/testsuite/g++.dg/torture/pr88797.C >>>>> delete mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr88797.C >>>>> rename gcc/testsuite/{gcc.dg/tree-ssa => gcc.c-torture/compile}/pr69270.c >>>>> (57%) >>>>> rename gcc/testsuite/{gcc.dg/tree-ssa => >>>>> gcc.c-torture/compile}/split-path-10.c (81%) >>>>> rename gcc/testsuite/{gcc.dg/tree-ssa => >>>>> gcc.c-torture/compile}/split-path-11.c (55%) >>>>> rename gcc/testsuite/{gcc.dg/tree-ssa => >>>>> gcc.c-torture/compile}/split-path-12.c (70%) >>>>> rename gcc/testsuite/{gcc.dg/tree-ssa => >>>>> gcc.c-torture/compile}/split-path-13.c (62%) >>>>> create mode 100644 gcc/testsuite/gcc.c-torture/compile/split-path-2.c >>>>> rename gcc/testsuite/{gcc.dg/tree-ssa => >>>>> gcc.c-torture/compile}/split-path-3.c (93%) >>>>> rename gcc/testsuite/{gcc.dg/tree-ssa => >>>>> gcc.c-torture/compile}/split-path-4.c (62%) >>>>> rename gcc/testsuite/{gcc.dg/tree-ssa => >>>>> gcc.c-torture/compile}/split-path-5.c (84%) >>>>> rename gcc/testsuite/{gcc.dg/tree-ssa => >>>>> gcc.c-torture/compile}/split-path-6.c (82%) >>>>> rename gcc/testsuite/{gcc.dg/tree-ssa => >>>>> gcc.c-torture/compile}/split-path-7.c (87%) >>>>> create mode 100644 gcc/testsuite/gcc.c-torture/compile/split-path-8.c >>>>> create mode 100644 gcc/testsuite/gcc.c-torture/compile/split-path-9.c >>>>> rename gcc/testsuite/{gcc.dg/tree-ssa => >>>>> gcc.c-torture/execute}/split-path-1.c (83%) >>>>> delete mode 100644 gcc/testsuite/gcc.dg/tree-ssa/split-path-2.c >>>>> delete mode 100644 gcc/testsuite/gcc.dg/tree-ssa/split-path-8.c >>>>> delete mode 100644 gcc/testsuite/gcc.dg/tree-ssa/split-path-9.c >>>>> >>>>> diff --git a/gcc/Makefile.in b/gcc/Makefile.in >>>>> index 536e2faaaf8..06e711094ef 100644 >>>>> --- a/gcc/Makefile.in >>>>> +++ b/gcc/Makefile.in >>>>> @@ -1542,7 +1542,6 @@ OBJS = \ >>>>> gimple-ssa-isolate-paths.o \ >>>>> gimple-ssa-nonnull-compare.o \ >>>>> gimple-ssa-sccopy.o \ >>>>> - gimple-ssa-split-paths.o \ >>>>> gimple-ssa-store-merging.o \ >>>>> gimple-ssa-strength-reduction.o \ >>>>> gimple-ssa-sprintf.o \ >>>>> diff --git a/gcc/common.opt b/gcc/common.opt >>>>> index 218dddf5dfe..0055578ccf6 100644 >>>>> --- a/gcc/common.opt >>>>> +++ b/gcc/common.opt >>>>> @@ -3388,8 +3388,8 @@ Common Var(flag_tree_vrp) Init(0) Optimization >>>>> Perform Value Range Propagation on trees. >>>>> >>>>> fsplit-paths >>>>> -Common Var(flag_split_paths) Init(0) Optimization >>>>> -Split paths leading to loop backedges. >>>>> +Common Ignore >>>>> +Does nothing. Preserved for backward compatibility. >>>>> >>>>> funconstrained-commons >>>>> Common Var(flag_unconstrained_commons) Optimization >>>>> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi >>>>> index 8da5f03ccbd..932def96d8f 100644 >>>>> --- a/gcc/doc/invoke.texi >>>>> +++ b/gcc/doc/invoke.texi >>>>> @@ -676,7 +676,7 @@ Objective-C and Objective-C++ Dialects}. >>>>> -fsemantic-interposition -fshrink-wrap -fshrink-wrap-separate >>>>> -fsignaling-nans >>>>> -fsingle-precision-constant -fsplit-ivs-in-unroller -fsplit-loops >>>>> --fspeculatively-call-stored-functions -fsplit-paths >>>>> +-fspeculatively-call-stored-functions >>>>> -fsplit-wide-types -fsplit-wide-types-early -fssa-backprop -fssa-phiopt >>>>> -fstdarg-opt -fstore-merging -fstrict-aliasing -fipa-strict-aliasing >>>>> -fthread-jumps -ftracer -ftree-bit-ccp >>>>> @@ -13619,7 +13619,6 @@ by @option{-O2} and also turns on the following >>>>> optimization flags: >>>>> -fpeel-loops >>>>> -fpredictive-commoning >>>>> -fsplit-loops >>>>> --fsplit-paths >>>>> -ftree-loop-distribution >>>>> -ftree-partial-pre >>>>> -funswitch-loops >>>>> @@ -15462,9 +15461,8 @@ enabled. >>>>> @opindex fsplit-paths >>>>> @opindex fno-split-paths >>>>> @item -fsplit-paths >>>>> -Split paths leading to loop backedges. This can improve dead code >>>>> -elimination and common subexpression elimination. This is enabled by >>>>> -default at @option{-O3} and above. >>>>> +This option is deprecated and does nothing. It is accepted only for >>>>> +backward compatibility. >>>>> >>>>> @opindex fsplit-ivs-in-unroller >>>>> @opindex fno-split-ivs-in-unroller >>>>> diff --git a/gcc/gimple-ssa-split-paths.cc b/gcc/gimple-ssa-split-paths.cc >>>>> deleted file mode 100644 >>>>> index 171a581e8f8..00000000000 >>>>> --- a/gcc/gimple-ssa-split-paths.cc >>>>> +++ /dev/null >>>>> @@ -1,545 +0,0 @@ >>>>> -/* Support routines for Splitting Paths to loop backedges >>>>> - Copyright (C) 2015-2026 Free Software Foundation, Inc. >>>>> - Contributed by Ajit Kumar Agarwal <[email protected]>. >>>>> - >>>>> - This file is part of GCC. >>>>> - >>>>> - GCC is free software; you can redistribute it and/or modify >>>>> - it under the terms of the GNU General Public License as published by >>>>> - the Free Software Foundation; either version 3, or (at your option) >>>>> - any later version. >>>>> - >>>>> -GCC is distributed in the hope that it will be useful, >>>>> -but WITHOUT ANY WARRANTY; without even the implied warranty of >>>>> -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>>>> -GNU General Public License for more details. >>>>> - >>>>> -You should have received a copy of the GNU General Public License >>>>> -along with GCC; see the file COPYING3. If not see >>>>> -<http://www.gnu.org/licenses/>. */ >>>>> - >>>>> -#include "config.h" >>>>> -#include "system.h" >>>>> -#include "coretypes.h" >>>>> -#include "backend.h" >>>>> -#include "tree.h" >>>>> -#include "gimple.h" >>>>> -#include "tree-pass.h" >>>>> -#include "tree-cfg.h" >>>>> -#include "cfganal.h" >>>>> -#include "cfgloop.h" >>>>> -#include "gimple-iterator.h" >>>>> -#include "tracer.h" >>>>> -#include "predict.h" >>>>> -#include "gimple-ssa.h" >>>>> -#include "tree-phinodes.h" >>>>> -#include "ssa-iterators.h" >>>>> -#include "fold-const.h" >>>>> -#include "cfghooks.h" >>>>> - >>>>> -/* Given LATCH, the latch block in a loop, see if the shape of the >>>>> - path reaching LATCH is suitable for being split by duplication. >>>>> - If so, return the block that will be duplicated into its predecessor >>>>> - paths. Else return NULL. */ >>>>> - >>>>> -static basic_block >>>>> -find_block_to_duplicate_for_splitting_paths (basic_block latch) >>>>> -{ >>>>> - /* We should have simple latches at this point. So the latch should >>>>> - have a single successor. This implies the predecessor of the latch >>>>> - likely has the loop exit. And it's that predecessor we're most >>>>> - interested in. To keep things simple, we're going to require that >>>>> - the latch have a single predecessor too. */ >>>>> - if (single_succ_p (latch) && single_pred_p (latch)) >>>>> - { >>>>> - basic_block bb = get_immediate_dominator (CDI_DOMINATORS, latch); >>>>> - gcc_assert (single_pred_edge (latch)->src == bb); >>>>> - >>>>> - /* If BB has been marked as not to be duplicated, then honor that >>>>> - request. */ >>>>> - if (ignore_bb_p (bb)) >>>>> - return NULL; >>>>> - >>>>> - gimple *last = gsi_stmt (gsi_last_nondebug_bb (bb)); >>>>> - /* The immediate dominator of the latch must end in a conditional. >>>>> */ >>>>> - if (!last || gimple_code (last) != GIMPLE_COND) >>>>> - return NULL; >>>>> - >>>>> - /* We're hoping that BB is a join point for an IF-THEN-ELSE diamond >>>>> - region. Verify that it is. >>>>> - >>>>> - First, verify that BB has two predecessors (each arm of the >>>>> - IF-THEN-ELSE) and two successors (the latch and exit) and that >>>>> - all edges are normal. */ >>>>> - if (EDGE_COUNT (bb->preds) == 2 >>>>> - && !(EDGE_PRED (bb, 0)->flags & EDGE_COMPLEX) >>>>> - && !(EDGE_PRED (bb, 1)->flags & EDGE_COMPLEX) >>>>> - && EDGE_COUNT (bb->succs) == 2 >>>>> - && !(EDGE_SUCC (bb, 0)->flags & EDGE_COMPLEX) >>>>> - && !(EDGE_SUCC (bb, 1)->flags & EDGE_COMPLEX)) >>>>> - { >>>>> - /* Now verify that BB's immediate dominator ends in a >>>>> - conditional as well. */ >>>>> - basic_block bb_idom = get_immediate_dominator (CDI_DOMINATORS, bb); >>>>> - gimple *last = gsi_stmt (gsi_last_nondebug_bb (bb_idom)); >>>>> - if (!last || gimple_code (last) != GIMPLE_COND) >>>>> - return NULL; >>>>> - >>>>> - /* And that BB's immediate dominator's successors are the >>>>> - predecessors of BB or BB itself. */ >>>>> - if (!(EDGE_PRED (bb, 0)->src == bb_idom >>>>> - || find_edge (bb_idom, EDGE_PRED (bb, 0)->src)) >>>>> - || !(EDGE_PRED (bb, 1)->src == bb_idom >>>>> - || find_edge (bb_idom, EDGE_PRED (bb, 1)->src))) >>>>> - return NULL; >>>>> - >>>>> - /* And that the predecessors of BB each have a single successor >>>>> - or are BB's immediate domiator itself. */ >>>>> - if (!(EDGE_PRED (bb, 0)->src == bb_idom >>>>> - || single_succ_p (EDGE_PRED (bb, 0)->src)) >>>>> - || !(EDGE_PRED (bb, 1)->src == bb_idom >>>>> - || single_succ_p (EDGE_PRED (bb, 1)->src))) >>>>> - return NULL; >>>>> - >>>>> - /* So at this point we have a simple diamond for an IF-THEN-ELSE >>>>> - construct starting at BB_IDOM, with a join point at BB. BB >>>>> - pass control outside the loop or to the loop latch. >>>>> - >>>>> - We're going to want to create two duplicates of BB, one for >>>>> - each successor of BB_IDOM. */ >>>>> - return bb; >>>>> - } >>>>> - } >>>>> - return NULL; >>>>> -} >>>>> - >>>>> -/* Return the number of non-debug statements in a block. */ >>>>> -static unsigned int >>>>> -count_stmts_in_block (basic_block bb) >>>>> -{ >>>>> - gimple_stmt_iterator gsi; >>>>> - unsigned int num_stmts = 0; >>>>> - >>>>> - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) >>>>> - { >>>>> - gimple *stmt = gsi_stmt (gsi); >>>>> - if (!is_gimple_debug (stmt)) >>>>> - num_stmts++; >>>>> - } >>>>> - return num_stmts; >>>>> -} >>>>> - >>>>> -/* Return TRUE if CODE represents a tree code that is not likely to >>>>> - be easily if-convertible because it likely expands into multiple >>>>> - insns, FALSE otherwise. */ >>>>> -static bool >>>>> -poor_ifcvt_candidate_code (enum tree_code code) >>>>> -{ >>>>> - return (code == MIN_EXPR >>>>> - || code == MAX_EXPR >>>>> - || code == ABS_EXPR >>>>> - || code == COND_EXPR); >>>>> -} >>>>> - >>>>> -/* Return TRUE if PRED of BB is an poor ifcvt candidate. */ >>>>> -static bool >>>>> -poor_ifcvt_pred (basic_block pred, basic_block bb) >>>>> -{ >>>>> - /* If the edge count of the pred is not 1, then >>>>> - this is the predecessor from the if rather >>>>> - than middle one. */ >>>>> - if (EDGE_COUNT (pred->succs) != 1) >>>>> - return false; >>>>> - >>>>> - /* Empty middle bb are never a poor ifcvt candidate. */ >>>>> - if (empty_block_p (pred)) >>>>> - return false; >>>>> - /* If BB's predecessors are single statement blocks where >>>>> - the output of that statement feed the same PHI in BB, >>>>> - it an ifcvt candidate. */ >>>>> - gimple *stmt = last_and_only_stmt (pred); >>>>> - if (!stmt || gimple_code (stmt) != GIMPLE_ASSIGN) >>>>> - return true; >>>>> - >>>>> - /* If the statement could trap, then this is a poor ifcvt candidate. */ >>>>> - if (gimple_could_trap_p (stmt)) >>>>> - return true; >>>>> - >>>>> - tree_code code = gimple_assign_rhs_code (stmt); >>>>> - if (poor_ifcvt_candidate_code (code)) >>>>> - return true; >>>>> - tree lhs = gimple_assign_lhs (stmt); >>>>> - gimple_stmt_iterator gsi; >>>>> - for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) >>>>> - { >>>>> - gimple *phi = gsi_stmt (gsi); >>>>> - if (gimple_phi_arg_def (phi, 0) == lhs >>>>> - || gimple_phi_arg_def (phi, 1) == lhs) >>>>> - return false; >>>>> - } >>>>> - return true; >>>>> -} >>>>> - >>>>> -/* Return TRUE if BB is a reasonable block to duplicate by examining >>>>> - its size, false otherwise. BB will always be a loop latch block. >>>>> - >>>>> - Things to consider: >>>>> - >>>>> - We do not want to spoil if-conversion if at all possible. >>>>> - >>>>> - Most of the benefit seems to be from eliminating the unconditional >>>>> - jump rather than CSE/DCE opportunities. So favor duplicating >>>>> - small latches. A latch with just a conditional branch is ideal. >>>>> - >>>>> - CSE/DCE opportunities crop up when statements from the predecessors >>>>> - feed statements in the latch and allow statements in the latch to >>>>> - simplify. */ >>>>> - >>>>> -static bool >>>>> -is_feasible_trace (basic_block bb) >>>>> -{ >>>>> - basic_block pred1 = EDGE_PRED (bb, 0)->src; >>>>> - basic_block pred2 = EDGE_PRED (bb, 1)->src; >>>>> - int num_stmts_in_join = count_stmts_in_block (bb); >>>>> - int num_stmts_in_pred1 >>>>> - = EDGE_COUNT (pred1->succs) == 1 ? count_stmts_in_block (pred1) : 0; >>>>> - int num_stmts_in_pred2 >>>>> - = EDGE_COUNT (pred2->succs) == 1 ? count_stmts_in_block (pred2) : 0; >>>>> - >>>>> - /* Upper Hard limit on the number statements to copy. */ >>>>> - if (num_stmts_in_join >>>>> - >= param_max_jump_thread_duplication_stmts) >>>>> - { >>>>> - if (dump_file && (dump_flags & TDF_DETAILS)) >>>>> - fprintf (dump_file, >>>>> - "Duplicating block %d would duplicate " >>>>> - "too many statements: %d >= %d\n", >>>>> - bb->index, num_stmts_in_join, >>>>> - param_max_jump_thread_duplication_stmts); >>>>> - return false; >>>>> - } >>>>> - >>>>> - /* This is meant to catch cases that are likely opportunities for >>>>> - if-conversion. */ >>>>> - if (num_stmts_in_pred1 <= 1 && num_stmts_in_pred2 <= 1) >>>>> - { >>>>> - int num_phis = 0; >>>>> - /* The max number of PHIs that should be considered for an ifcvt >>>>> - candidate. */ >>>>> - const int max_num_phis = 3; >>>>> - for (gphi_iterator si = gsi_start_phis (bb); ! gsi_end_p (si); >>>>> - gsi_next (&si)) >>>>> - { >>>>> - num_phis++; >>>>> - if (num_phis > max_num_phis) >>>>> - break; >>>>> - } >>>>> - if (num_phis <= max_num_phis >>>>> - && !poor_ifcvt_pred (pred1, bb) >>>>> - && !poor_ifcvt_pred (pred2, bb)) >>>>> - { >>>>> - if (dump_file && (dump_flags & TDF_DETAILS)) >>>>> - fprintf (dump_file, >>>>> - "Block %d appears to be a join point for " >>>>> - "if-convertible bbs.\n", >>>>> - bb->index); >>>>> - return false; >>>>> - } >>>>> - } >>>>> - >>>>> - /* If the joiner has no PHIs with useful uses there is zero chance >>>>> - of CSE/DCE/jump-threading possibilities exposed by duplicating it. >>>>> */ >>>>> - bool found_useful_phi = false; >>>>> - for (gphi_iterator si = gsi_start_phis (bb); ! gsi_end_p (si); >>>>> - gsi_next (&si)) >>>>> - { >>>>> - gphi *phi = si.phi (); >>>>> - use_operand_p use_p; >>>>> - imm_use_iterator iter; >>>>> - FOR_EACH_IMM_USE_FAST (use_p, iter, gimple_phi_result (phi)) >>>>> - { >>>>> - gimple *stmt = USE_STMT (use_p); >>>>> - if (is_gimple_debug (stmt)) >>>>> - continue; >>>>> - /* If there's a use in the joiner this might be a CSE/DCE >>>>> - opportunity, but not if the use is in a conditional >>>>> - which makes this a likely if-conversion candidate. */ >>>>> - if (gimple_bb (stmt) == bb >>>>> - && (!is_gimple_assign (stmt) >>>>> - || (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) >>>>> - != tcc_comparison))) >>>>> - { >>>>> - found_useful_phi = true; >>>>> - break; >>>>> - } >>>>> - /* If the use is on a loop header PHI and on one path the >>>>> - value is unchanged this might expose a jump threading >>>>> - opportunity. */ >>>>> - if (gimple_code (stmt) == GIMPLE_PHI >>>>> - && gimple_bb (stmt) == bb->loop_father->header >>>>> - /* But for memory the PHI alone isn't good enough. */ >>>>> - && ! virtual_operand_p (gimple_phi_result (stmt))) >>>>> - { >>>>> - bool found_unchanged_path = false; >>>>> - for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) >>>>> - if (gimple_phi_arg_def (phi, i) == gimple_phi_result (stmt)) >>>>> - { >>>>> - found_unchanged_path = true; >>>>> - break; >>>>> - } >>>>> - /* If we found an unchanged path this can only be a threading >>>>> - opportunity if we have uses of the loop header PHI result >>>>> - in a stmt dominating the merge block. Otherwise the >>>>> - splitting may prevent if-conversion. */ >>>>> - if (found_unchanged_path) >>>>> - { >>>>> - use_operand_p use2_p; >>>>> - imm_use_iterator iter2; >>>>> - FOR_EACH_IMM_USE_FAST (use2_p, iter2, gimple_phi_result (stmt)) >>>>> - { >>>>> - gimple *use_stmt = USE_STMT (use2_p); >>>>> - if (is_gimple_debug (use_stmt)) >>>>> - continue; >>>>> - basic_block use_bb = gimple_bb (use_stmt); >>>>> - if (use_bb != bb >>>>> - && dominated_by_p (CDI_DOMINATORS, bb, use_bb)) >>>>> - { >>>>> - if (gcond *cond = dyn_cast <gcond *> (use_stmt)) >>>>> - if (gimple_cond_code (cond) == EQ_EXPR >>>>> - || gimple_cond_code (cond) == NE_EXPR) >>>>> - found_useful_phi = true; >>>>> - break; >>>>> - } >>>>> - } >>>>> - } >>>>> - if (found_useful_phi) >>>>> - break; >>>>> - } >>>>> - } >>>>> - if (found_useful_phi) >>>>> - break; >>>>> - } >>>>> - /* There is one exception namely a controlling condition we can >>>>> propagate >>>>> - an equivalence from to the joiner. */ >>>>> - bool found_cprop_opportunity = false; >>>>> - basic_block dom = get_immediate_dominator (CDI_DOMINATORS, bb); >>>>> - gcond *cond = as_a <gcond *> (*gsi_last_bb (dom)); >>>>> - if (gimple_cond_code (cond) == EQ_EXPR >>>>> - || gimple_cond_code (cond) == NE_EXPR) >>>>> - for (unsigned i = 0; i < 2; ++i) >>>>> - { >>>>> - tree op = gimple_op (cond, i); >>>>> - if (TREE_CODE (op) == SSA_NAME) >>>>> - { >>>>> - use_operand_p use_p; >>>>> - imm_use_iterator iter; >>>>> - FOR_EACH_IMM_USE_FAST (use_p, iter, op) >>>>> - { >>>>> - if (is_gimple_debug (USE_STMT (use_p))) >>>>> - continue; >>>>> - if (gimple_bb (USE_STMT (use_p)) == bb) >>>>> - { >>>>> - found_cprop_opportunity = true; >>>>> - break; >>>>> - } >>>>> - } >>>>> - } >>>>> - if (found_cprop_opportunity) >>>>> - break; >>>>> - } >>>>> - >>>>> - if (! found_useful_phi && ! found_cprop_opportunity) >>>>> - { >>>>> - if (dump_file && (dump_flags & TDF_DETAILS)) >>>>> - fprintf (dump_file, >>>>> - "Block %d is a join that does not expose CSE/DCE/jump-thread " >>>>> - "opportunities when duplicated.\n", >>>>> - bb->index); >>>>> - return false; >>>>> - } >>>>> - >>>>> - /* We may want something here which looks at dataflow and tries >>>>> - to guess if duplication of BB is likely to result in simplification >>>>> - of instructions in BB in either the original or the duplicate. */ >>>>> - return true; >>>>> -} >>>>> - >>>>> -/* If the immediate dominator of the latch of the loop is >>>>> - block with conditional branch, then the loop latch is >>>>> - duplicated to its predecessors path preserving the SSA >>>>> - semantics. >>>>> - >>>>> - CFG before transformation. >>>>> - >>>>> - 2 >>>>> - | >>>>> - | >>>>> - +---->3 >>>>> - | / \ >>>>> - | / \ >>>>> - | 4 5 >>>>> - | \ / >>>>> - | \ / >>>>> - | 6 >>>>> - | / \ >>>>> - | / \ >>>>> - | 8 7 >>>>> - | | | >>>>> - ---+ E >>>>> - >>>>> - >>>>> - >>>>> - Block 8 is the latch. We're going to make copies of block 6 (9 & 10) >>>>> - and wire things up so they look like this: >>>>> - >>>>> - 2 >>>>> - | >>>>> - | >>>>> - +---->3 >>>>> - | / \ >>>>> - | / \ >>>>> - | 4 5 >>>>> - | | | >>>>> - | | | >>>>> - | 9 10 >>>>> - | |\ /| >>>>> - | | \ / | >>>>> - | | 7 | >>>>> - | | | | >>>>> - | | E | >>>>> - | | | >>>>> - | \ / >>>>> - | \ / >>>>> - +-----8 >>>>> - >>>>> - >>>>> - Blocks 9 and 10 will get merged into blocks 4 & 5 respectively which >>>>> - enables CSE, DCE and other optimizations to occur on a larger block >>>>> - of code. */ >>>>> - >>>>> -static bool >>>>> -split_paths () >>>>> -{ >>>>> - bool changed = false; >>>>> - >>>>> - loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS); >>>>> - initialize_original_copy_tables (); >>>>> - calculate_dominance_info (CDI_DOMINATORS); >>>>> - >>>>> - for (auto loop : loops_list (cfun, LI_FROM_INNERMOST)) >>>>> - { >>>>> - /* Only split paths if we are optimizing this loop for speed. */ >>>>> - if (!optimize_loop_for_speed_p (loop)) >>>>> - continue; >>>>> - >>>>> - /* See if there is a block that we can duplicate to split the >>>>> - path to the loop latch. */ >>>>> - basic_block bb >>>>> - = find_block_to_duplicate_for_splitting_paths (loop->latch); >>>>> - >>>>> - /* BB is the merge point for an IF-THEN-ELSE we want to transform. >>>>> - >>>>> - Essentially we want to create a duplicate of bb and redirect the >>>>> - first predecessor of BB to the duplicate (leaving the second >>>>> - predecessor as is. This will split the path leading to the latch >>>>> - re-using BB to avoid useless copying. */ >>>>> - if (bb && is_feasible_trace (bb)) >>>>> - { >>>>> - if (dump_file && (dump_flags & TDF_DETAILS)) >>>>> - fprintf (dump_file, >>>>> - "Duplicating join block %d into predecessor paths\n", >>>>> - bb->index); >>>>> - basic_block pred0 = EDGE_PRED (bb, 0)->src; >>>>> - if (EDGE_COUNT (pred0->succs) != 1) >>>>> - pred0 = EDGE_PRED (bb, 1)->src; >>>>> - transform_duplicate (pred0, bb); >>>>> - changed = true; >>>>> - >>>>> - /* If BB has an outgoing edge marked as IRREDUCIBLE, then >>>>> - duplicating BB may result in an irreducible region turning >>>>> - into a natural loop. >>>>> - >>>>> - Long term we might want to hook this into the block >>>>> - duplication code, but as we've seen with similar changes >>>>> - for edge removal, that can be somewhat risky. */ >>>>> - if (EDGE_SUCC (bb, 0)->flags & EDGE_IRREDUCIBLE_LOOP >>>>> - || EDGE_SUCC (bb, 1)->flags & EDGE_IRREDUCIBLE_LOOP) >>>>> - { >>>>> - if (dump_file && (dump_flags & TDF_DETAILS)) >>>>> - fprintf (dump_file, >>>>> - "Join block %d has EDGE_IRREDUCIBLE_LOOP set. " >>>>> - "Scheduling loop fixups.\n", >>>>> - bb->index); >>>>> - loops_state_set (LOOPS_NEED_FIXUP); >>>>> - } >>>>> - } >>>>> - } >>>>> - >>>>> - loop_optimizer_finalize (); >>>>> - free_original_copy_tables (); >>>>> - return changed; >>>>> -} >>>>> - >>>>> -/* Main entry point for splitting paths. Returns TODO_cleanup_cfg if any >>>>> - paths where split, otherwise return zero. */ >>>>> - >>>>> -static unsigned int >>>>> -execute_split_paths () >>>>> -{ >>>>> - /* If we don't have at least 2 real blocks and backedges in the >>>>> - CFG, then there's no point in trying to perform path splitting. */ >>>>> - if (n_basic_blocks_for_fn (cfun) <= NUM_FIXED_BLOCKS + 1 >>>>> - || !mark_dfs_back_edges ()) >>>>> - return 0; >>>>> - >>>>> - bool changed = split_paths(); >>>>> - if (changed) >>>>> - free_dominance_info (CDI_DOMINATORS); >>>>> - >>>>> - return changed ? TODO_cleanup_cfg : 0; >>>>> -} >>>>> - >>>>> -static bool >>>>> -gate_split_paths () >>>>> -{ >>>>> - return flag_split_paths; >>>>> -} >>>>> - >>>>> -namespace { >>>>> - >>>>> -const pass_data pass_data_split_paths = >>>>> -{ >>>>> - GIMPLE_PASS, /* type */ >>>>> - "split-paths", /* name */ >>>>> - OPTGROUP_NONE, /* optinfo_flags */ >>>>> - TV_SPLIT_PATHS, /* tv_id */ >>>>> - PROP_ssa, /* properties_required */ >>>>> - 0, /* properties_provided */ >>>>> - 0, /* properties_destroyed */ >>>>> - 0, /* todo_flags_start */ >>>>> - TODO_update_ssa, /* todo_flags_finish */ >>>>> -}; >>>>> - >>>>> -class pass_split_paths : public gimple_opt_pass >>>>> -{ >>>>> - public: >>>>> - pass_split_paths (gcc::context *ctxt) >>>>> - : gimple_opt_pass (pass_data_split_paths, ctxt) >>>>> - {} >>>>> - /* opt_pass methods: */ >>>>> - opt_pass * clone () final override { return new pass_split_paths >>>>> (m_ctxt); } >>>>> - bool gate (function *) final override { return gate_split_paths (); } >>>>> - unsigned int execute (function *) final override >>>>> - { >>>>> - return execute_split_paths (); >>>>> - } >>>>> - >>>>> -}; // class pass_split_paths >>>>> - >>>>> -} // anon namespace >>>>> - >>>>> -gimple_opt_pass * >>>>> -make_pass_split_paths (gcc::context *ctxt) >>>>> -{ >>>>> - return new pass_split_paths (ctxt); >>>>> -} >>>>> diff --git a/gcc/opts.cc b/gcc/opts.cc >>>>> index 342517528e8..5522f41f906 100644 >>>>> --- a/gcc/opts.cc >>>>> +++ b/gcc/opts.cc >>>>> @@ -707,7 +707,6 @@ static const struct default_options >>>>> default_options_table[] = >>>>> { OPT_LEVELS_3_PLUS, OPT_fpeel_loops, NULL, 1 }, >>>>> { OPT_LEVELS_3_PLUS, OPT_fpredictive_commoning, NULL, 1 }, >>>>> { OPT_LEVELS_3_PLUS, OPT_fsplit_loops, NULL, 1 }, >>>>> - { OPT_LEVELS_3_PLUS, OPT_fsplit_paths, NULL, 1 }, >>>>> { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribution, NULL, 1 }, >>>>> { OPT_LEVELS_3_PLUS, OPT_ftree_partial_pre, NULL, 1 }, >>>>> { OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 }, >>>>> diff --git a/gcc/passes.def b/gcc/passes.def >>>>> index 1fc867fae51..9095c134f49 100644 >>>>> --- a/gcc/passes.def >>>>> +++ b/gcc/passes.def >>>>> @@ -351,7 +351,6 @@ along with GCC; see the file COPYING3. If not see >>>>> NEXT_PASS (pass_cse_reciprocals); >>>>> NEXT_PASS (pass_reassoc, false /* early_p */); >>>>> NEXT_PASS (pass_strength_reduction); >>>>> - NEXT_PASS (pass_split_paths); >>>>> NEXT_PASS (pass_tracer); >>>>> NEXT_PASS (pass_fre, false /* may_iterate */); >>>>> /* After late FRE we rewrite no longer addressed locals into SSA >>>>> diff --git a/gcc/testsuite/g++.dg/torture/pr88797.C >>>>> b/gcc/testsuite/g++.dg/torture/pr88797.C >>>>> new file mode 100644 >>>>> index 00000000000..3dd00fcb7a9 >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/g++.dg/torture/pr88797.C >>>>> @@ -0,0 +1,13 @@ >>>>> +/* { dg-do compile } */ >>>>> + >>>>> + >>>>> +void use(unsigned); >>>>> +bool f(unsigned x, unsigned y) { >>>>> + return x < 1111 + (y <= 2222); >>>>> +} >>>>> +void test_f(unsigned x, unsigned y) { >>>>> + for (unsigned i = 0; i < 3333; ++i) >>>>> + use(f(x++, y++)); >>>>> +} >>>>> + >>>>> + >>>>> diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr88797.C >>>>> b/gcc/testsuite/g++.dg/tree-ssa/pr88797.C >>>>> deleted file mode 100644 >>>>> index 541ae8e71e1..00000000000 >>>>> --- a/gcc/testsuite/g++.dg/tree-ssa/pr88797.C >>>>> +++ /dev/null >>>>> @@ -1,16 +0,0 @@ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O3 -fdump-tree-split-paths-details" } */ >>>>> - >>>>> - >>>>> -void use(unsigned); >>>>> -bool f(unsigned x, unsigned y) { >>>>> - return x < 1111 + (y <= 2222); >>>>> -} >>>>> -void test_f(unsigned x, unsigned y) { >>>>> - for (unsigned i = 0; i < 3333; ++i) >>>>> - use(f(x++, y++)); >>>>> -} >>>>> - >>>>> -/* { dg-final { scan-tree-dump-not "Duplicating join block" >>>>> "split-paths" } } */ >>>>> -/* { dg-final { scan-tree-dump-times "appears to be a join point for >>>>> if-convertible bbs." 1 "split-paths" } } */ >>>>> - >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr69270.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/pr69270.c >>>>> similarity index 57% >>>>> rename from gcc/testsuite/gcc.dg/tree-ssa/pr69270.c >>>>> rename to gcc/testsuite/gcc.c-torture/compile/pr69270.c >>>>> index b08ec9d6ddb..daed456ec60 100644 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/pr69270.c >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/pr69270.c >>>>> @@ -1,17 +1,10 @@ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O2 -fsplit-paths -fdump-tree-dom3-details" } */ >>>>> >>>>> /* There should be two references to bufferstep that turn into >>>>> constants. */ >>>>> -/* { dg-final { scan-tree-dump-times "Replaced .bufferstep_\[0-9\]+. >>>>> with constant .0." 1 "dom3"} } */ >>>>> -/* { dg-final { scan-tree-dump-times "Replaced .bufferstep_\[0-9\]+. >>>>> with constant .1." 1 "dom3"} } */ >>>>> >>>>> /* And some assignments ought to fold down to constants. */ >>>>> -/* { dg-final { scan-tree-dump-times "Folded to: >>>>> (?:bufferstep)?_\[0-9\]+ = 1;" 1 "dom3"} } */ >>>>> -/* { dg-final { scan-tree-dump-times "Folded to: >>>>> (?:bufferstep)?_\[0-9\]+ = 0;" 1 "dom3"} } */ >>>>> >>>>> /* The XOR operations should have been optimized to constants. */ >>>>> -/* { dg-final { scan-tree-dump-not "bit_xor" "dom3"} } */ >>>>> >>>>> >>>>> extern int *stepsizeTable; >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-10.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-10.c >>>>> similarity index 81% >>>>> rename from gcc/testsuite/gcc.dg/tree-ssa/split-path-10.c >>>>> rename to gcc/testsuite/gcc.c-torture/compile/split-path-10.c >>>>> index ed208795488..336b11893b6 100644 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-10.c >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-10.c >>>>> @@ -1,6 +1,4 @@ >>>>> /* PR tree-optimization/79389 */ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O3 -fdump-tree-split-paths-details" } */ >>>>> >>>>> typedef struct >>>>> { >>>>> @@ -46,4 +44,3 @@ double MonteCarlo_integrate(int Num_samples) >>>>> return ((double) under_curve / Num_samples) * 4.0; >>>>> } >>>>> >>>>> -/* { dg-final { scan-tree-dump-times "Duplicating join block" 0 >>>>> "split-paths" } } */ >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-11.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-11.c >>>>> similarity index 55% >>>>> rename from gcc/testsuite/gcc.dg/tree-ssa/split-path-11.c >>>>> rename to gcc/testsuite/gcc.c-torture/compile/split-path-11.c >>>>> index fa33367feaa..44b8b059481 100644 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-11.c >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-11.c >>>>> @@ -1,5 +1,3 @@ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O2 -fno-tree-vectorize -fsplit-paths >>>>> -fdump-tree-split-paths-details -w" } */ >>>>> >>>>> void foo(unsigned long long *M) >>>>> { >>>>> @@ -11,4 +9,3 @@ void foo(unsigned long long *M) >>>>> } >>>>> } >>>>> >>>>> -/* { dg-final { scan-tree-dump-times "join point for if-convertible" 1 >>>>> "split-paths" } } */ >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-12.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-12.c >>>>> similarity index 70% >>>>> rename from gcc/testsuite/gcc.dg/tree-ssa/split-path-12.c >>>>> rename to gcc/testsuite/gcc.c-torture/compile/split-path-12.c >>>>> index da00f795ef0..dc9da4e90ef 100644 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-12.c >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-12.c >>>>> @@ -1,5 +1,3 @@ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details " } */ >>>>> >>>>> double >>>>> foo(double *d1, double *d2, double *d3, int num, double *ip) >>>>> @@ -18,4 +16,3 @@ foo(double *d1, double *d2, double *d3, int num, double >>>>> *ip) >>>>> >>>>> /* Split-paths shouldn't do anything here, if there's a diamond it would >>>>> be if-convertible. */ >>>>> -/* { dg-final { scan-tree-dump-not "Duplicating join block" >>>>> "split-paths" } } */ >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-13.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-13.c >>>>> similarity index 62% >>>>> rename from gcc/testsuite/gcc.dg/tree-ssa/split-path-13.c >>>>> rename to gcc/testsuite/gcc.c-torture/compile/split-path-13.c >>>>> index d24e23bc59d..554ae4d8f39 100644 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-13.c >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-13.c >>>>> @@ -1,5 +1,3 @@ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details " } */ >>>>> /* PR tree-optimization/112402 */ >>>>> /* This is similar to split-path-2.c but instead of the add >>>>> being inside both sides, we have a constant. */ >>>>> @@ -22,5 +20,4 @@ foo(signed char *p, int n) >>>>> return s; >>>>> } >>>>> >>>>> -/* { dg-final { scan-tree-dump "appears to be a join point for >>>>> if-convertible" "split-paths" } } */ >>>>> >>>>> diff --git a/gcc/testsuite/gcc.c-torture/compile/split-path-2.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-2.c >>>>> new file mode 100644 >>>>> index 00000000000..9418c9488d4 >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-2.c >>>>> @@ -0,0 +1,18 @@ >>>>> + >>>>> +int >>>>> +foo(signed char *p, int n) >>>>> +{ >>>>> + int s = 0; >>>>> + int i; >>>>> + >>>>> + for (i = 0; i < n; i++) { >>>>> + if (p[i] >= 0) >>>>> + s++; >>>>> + else >>>>> + s--; >>>>> + } >>>>> + >>>>> + return s; >>>>> +} >>>>> + >>>>> + >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-3.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-3.c >>>>> similarity index 93% >>>>> rename from gcc/testsuite/gcc.dg/tree-ssa/split-path-3.c >>>>> rename to gcc/testsuite/gcc.c-torture/compile/split-path-3.c >>>>> index f6a29f628a2..9ea9fb2fed1 100644 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-3.c >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-3.c >>>>> @@ -1,5 +1,3 @@ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details -w" } >>>>> */ >>>>> >>>>> typedef struct bitmap_head_def *bitmap; >>>>> extern void vec_assert_fail (const char *, const char *, const char >>>>> *file_, >>>>> @@ -94,4 +92,3 @@ compute_idf (bitmap_head * dfs) >>>>> (VEC_int_heap_free (&work_stack)); >>>>> } >>>>> >>>>> -/* { dg-final { scan-tree-dump-not "Duplicating join block" >>>>> "split-paths" } } */ >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-4.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-4.c >>>>> similarity index 62% >>>>> rename from gcc/testsuite/gcc.dg/tree-ssa/split-path-4.c >>>>> rename to gcc/testsuite/gcc.c-torture/compile/split-path-4.c >>>>> index cbee6fce4b7..6705f9e8426 100644 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-4.c >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-4.c >>>>> @@ -1,5 +1,3 @@ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details -w >>>>> -fdisable-tree-thread1 -fdisable-tree-thread2" } */ >>>>> >>>>> /* Note: Threader causes the infinite loop in val & 1 sooner. */ >>>>> >>>>> @@ -25,5 +23,4 @@ powi_cost (long n) >>>>> } >>>>> } >>>>> >>>>> -/* { dg-final { scan-tree-dump-times "Duplicating join block" 1 >>>>> "split-paths" } } */ >>>>> >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-5.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-5.c >>>>> similarity index 84% >>>>> rename from gcc/testsuite/gcc.dg/tree-ssa/split-path-5.c >>>>> rename to gcc/testsuite/gcc.c-torture/compile/split-path-5.c >>>>> index 2f5e7edcfa8..aff1f038195 100644 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-5.c >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-5.c >>>>> @@ -1,5 +1,3 @@ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details -w" } >>>>> */ >>>>> >>>>> const extern signed char *__ctype_ptr__; >>>>> typedef unsigned char uchar; >>>>> @@ -41,4 +39,3 @@ bmhi_init (const signed char *pattern) >>>>> } >>>>> } >>>>> >>>>> -/* { dg-final { scan-tree-dump-times "join point for if-convertible" 1 >>>>> "split-paths" } } */ >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-6.c >>>>> similarity index 82% >>>>> rename from gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c >>>>> rename to gcc/testsuite/gcc.c-torture/compile/split-path-6.c >>>>> index e2b0a9571f0..9c32c813b60 100644 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-6.c >>>>> @@ -1,5 +1,3 @@ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O2 -fsplit-paths -fno-tree-cselim -fno-ssa-phiopt >>>>> -fdump-tree-split-paths-details -fno-finite-loops >>>>> -fno-tree-dominator-opts -fno-tree-vrp -w" } */ >>>>> >>>>> struct __sFILE >>>>> { >>>>> @@ -75,4 +73,3 @@ lookharder (char *string) >>>>> } >>>>> } >>>>> >>>>> -/* { dg-final { scan-tree-dump-times "Duplicating join block" 2 >>>>> "split-paths" } } */ >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-7.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-7.c >>>>> similarity index 87% >>>>> rename from gcc/testsuite/gcc.dg/tree-ssa/split-path-7.c >>>>> rename to gcc/testsuite/gcc.c-torture/compile/split-path-7.c >>>>> index 35634ab3bd8..33d04b4ff7d 100644 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-7.c >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-7.c >>>>> @@ -1,5 +1,3 @@ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O2 -fsplit-paths -fno-tree-cselim -fno-ssa-phiopt >>>>> -fno-tree-sink -fdump-tree-split-paths-details -w" } */ >>>>> >>>>> >>>>> struct _reent >>>>> @@ -91,4 +89,3 @@ linit () >>>>> } >>>>> } >>>>> } >>>>> -/* { dg-final { scan-tree-dump-times "Duplicating join block" 0 >>>>> "split-paths" } } */ >>>>> diff --git a/gcc/testsuite/gcc.c-torture/compile/split-path-8.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-8.c >>>>> new file mode 100644 >>>>> index 00000000000..cccbf0ca0a3 >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-8.c >>>>> @@ -0,0 +1,11 @@ >>>>> +/* PR77283 */ >>>>> + >>>>> +void >>>>> +foo (double *x, double *a, double *b, long n, double limit) >>>>> +{ >>>>> + long i; >>>>> + for (i=0; i < n; i++) >>>>> + if (a[i] < limit) >>>>> + x[i] = b[i]; >>>>> +} >>>>> + >>>>> diff --git a/gcc/testsuite/gcc.c-torture/compile/split-path-9.c >>>>> b/gcc/testsuite/gcc.c-torture/compile/split-path-9.c >>>>> new file mode 100644 >>>>> index 00000000000..4eacad2978a >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.c-torture/compile/split-path-9.c >>>>> @@ -0,0 +1,14 @@ >>>>> +/* PR77366 */ >>>>> + >>>>> +void >>>>> +foo(unsigned int size, unsigned int *state) >>>>> +{ >>>>> + unsigned int i; >>>>> + >>>>> + for(i = 0; i < size; i++) >>>>> + { >>>>> + if(state[i] & 1) >>>>> + state[i] ^= 1; >>>>> + } >>>>> +} >>>>> + >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c >>>>> b/gcc/testsuite/gcc.c-torture/execute/split-path-1.c >>>>> similarity index 83% >>>>> rename from gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c >>>>> rename to gcc/testsuite/gcc.c-torture/execute/split-path-1.c >>>>> index b670dee8d10..e0ca386b4ea 100644 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c >>>>> +++ b/gcc/testsuite/gcc.c-torture/execute/split-path-1.c >>>>> @@ -1,6 +1,4 @@ >>>>> -/* { dg-do run } */ >>>>> /* Note both PHI-OPT and the loop if conversion pass converts the inner >>>>> if to be branchless using min/max. */ >>>>> -/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details >>>>> --param max-jump-thread-duplication-stmts=20 -fno-ssa-phiopt >>>>> -fno-tree-loop-if-convert" } */ >>>>> >>>>> #include <stdio.h> >>>>> #include <stdlib.h> >>>>> @@ -67,4 +65,3 @@ main() >>>>> return 0; >>>>> } >>>>> >>>>> -/* { dg-final { scan-tree-dump "Duplicating join block" "split-paths" } >>>>> } */ >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-2.c >>>>> b/gcc/testsuite/gcc.dg/tree-ssa/split-path-2.c >>>>> deleted file mode 100644 >>>>> index 61697a35e56..00000000000 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-2.c >>>>> +++ /dev/null >>>>> @@ -1,21 +0,0 @@ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O2 -fsplit-paths -fdump-tree-split-paths-details " } */ >>>>> - >>>>> -int >>>>> -foo(signed char *p, int n) >>>>> -{ >>>>> - int s = 0; >>>>> - int i; >>>>> - >>>>> - for (i = 0; i < n; i++) { >>>>> - if (p[i] >= 0) >>>>> - s++; >>>>> - else >>>>> - s--; >>>>> - } >>>>> - >>>>> - return s; >>>>> -} >>>>> - >>>>> -/* { dg-final { scan-tree-dump "appears to be a join point for >>>>> if-convertible" "split-paths" } } */ >>>>> - >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-8.c >>>>> b/gcc/testsuite/gcc.dg/tree-ssa/split-path-8.c >>>>> deleted file mode 100644 >>>>> index fb54f5dc512..00000000000 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-8.c >>>>> +++ /dev/null >>>>> @@ -1,14 +0,0 @@ >>>>> -/* PR77283 */ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O3 -fdump-tree-split-paths-details" } */ >>>>> - >>>>> -void >>>>> -foo (double *x, double *a, double *b, long n, double limit) >>>>> -{ >>>>> - long i; >>>>> - for (i=0; i < n; i++) >>>>> - if (a[i] < limit) >>>>> - x[i] = b[i]; >>>>> -} >>>>> - >>>>> -/* { dg-final { scan-tree-dump-times "Duplicating join block" 0 >>>>> "split-paths" } } */ >>>>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-9.c >>>>> b/gcc/testsuite/gcc.dg/tree-ssa/split-path-9.c >>>>> deleted file mode 100644 >>>>> index 8be0cd01201..00000000000 >>>>> --- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-9.c >>>>> +++ /dev/null >>>>> @@ -1,17 +0,0 @@ >>>>> -/* PR77366 */ >>>>> -/* { dg-do compile } */ >>>>> -/* { dg-options "-O3 -fdump-tree-split-paths-details" } */ >>>>> - >>>>> -void >>>>> -foo(unsigned int size, unsigned int *state) >>>>> -{ >>>>> - unsigned int i; >>>>> - >>>>> - for(i = 0; i < size; i++) >>>>> - { >>>>> - if(state[i] & 1) >>>>> - state[i] ^= 1; >>>>> - } >>>>> -} >>>>> - >>>>> -/* { dg-final { scan-tree-dump-times "Duplicating join block" 0 >>>>> "split-paths" } } */ >>>>> diff --git a/gcc/testsuite/gcc.target/i386/pr106450.c >>>>> b/gcc/testsuite/gcc.target/i386/pr106450.c >>>>> index d16231f6abd..009e3eb8c74 100644 >>>>> --- a/gcc/testsuite/gcc.target/i386/pr106450.c >>>>> +++ b/gcc/testsuite/gcc.target/i386/pr106450.c >>>>> @@ -1,5 +1,5 @@ >>>>> /* { dg-do compile { target int128 } } */ >>>>> -/* { dg-options "-O2 -fsplit-paths" } */ >>>>> +/* { dg-options "-O2" } */ >>>>> >>>>> __int128 n; >>>>> >>>>> diff --git a/gcc/timevar.def b/gcc/timevar.def >>>>> index 588d987ec35..c7020997609 100644 >>>>> --- a/gcc/timevar.def >>>>> +++ b/gcc/timevar.def >>>>> @@ -287,7 +287,6 @@ DEFTIMEVAR (TV_GCSE_AFTER_RELOAD , "load CSE >>>>> after reload") >>>>> DEFTIMEVAR (TV_REE , "ree") >>>>> DEFTIMEVAR (TV_THREAD_PROLOGUE_AND_EPILOGUE, "thread pro- & epilogue") >>>>> DEFTIMEVAR (TV_IFCVT2 , "if-conversion 2") >>>>> -DEFTIMEVAR (TV_SPLIT_PATHS , "split paths") >>>>> DEFTIMEVAR (TV_COMBINE_STACK_ADJUST , "combine stack adjustments") >>>>> DEFTIMEVAR (TV_PEEPHOLE2 , "peephole 2") >>>>> DEFTIMEVAR (TV_RENAME_REGISTERS , "rename registers") >>>>> diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h >>>>> index b3c97658a8f..a3b35e009e0 100644 >>>>> --- a/gcc/tree-pass.h >>>>> +++ b/gcc/tree-pass.h >>>>> @@ -404,7 +404,6 @@ extern gimple_opt_pass *make_pass_ch (gcc::context >>>>> *ctxt); >>>>> extern gimple_opt_pass *make_pass_ch_vect (gcc::context *ctxt); >>>>> extern gimple_opt_pass *make_pass_sccopy (gcc::context *ctxt); >>>>> extern gimple_opt_pass *make_pass_ccp (gcc::context *ctxt); >>>>> -extern gimple_opt_pass *make_pass_split_paths (gcc::context *ctxt); >>>>> extern gimple_opt_pass *make_pass_build_ssa (gcc::context *ctxt); >>>>> extern gimple_opt_pass *make_pass_build_alias (gcc::context *ctxt); >>>>> extern gimple_opt_pass *make_pass_build_ealias (gcc::context *ctxt); >>>>> >>>> >>>> -- >>>> Richard Biener <[email protected]> >>>> SUSE Software Solutions Germany GmbH, >>>> Frankenstrasse 146, 90461 Nuernberg, Germany; >>>> GF: Jochen Jaser, Andrew McDonald; (HRB 36809, AG Nuernberg)
