Relevant bugzilla: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115220
Patrick On Sun, May 26, 2024 at 2:30 AM Li, Pan2 <pan2...@intel.com> wrote: > > Hi Richard, > > Looks this commit may result one ICE similar as below when build the newlib, > feel free to ping me if you need one PR for this. > > CC RISC-V port for awareness. > > In file included from > /home/pli/gcc/111/riscv-gnu-toolchain/newlib/newlib/libc/stdlib/setenv_r.c:26: > /home/pli/gcc/111/riscv-gnu-toolchain/newlib/newlib/libc/include/stdlib.h: In > function '_setenv_r': > /home/pli/gcc/111/riscv-gnu-toolchain/newlib/newlib/libc/include/stdlib.h:212:9: > error: stmt with wrong VUSE > 212 | int _setenv_r (struct _reent *, const char *__string, const char > *__value, int __overwrite); > | ^~~~~~~~~ > # .MEM_109 = VDEF <.MEM_67> > *C_59 = 61; > expected .MEM_106 > during GIMPLE pass: sink > /home/pli/gcc/111/riscv-gnu-toolchain/newlib/newlib/libc/include/stdlib.h:212:9: > internal compiler error: verify_ssa failed > > Pan > > > -----Original Message----- > From: Richard Biener <rguent...@suse.de> > Sent: Friday, May 24, 2024 7:01 PM > To: gcc-patches@gcc.gnu.org > Subject: [PATCH][v2] tree-optimization/115144 - improve sinking destination > choice > > When sinking code closer to its uses we already try to minimize the > distance we move by inserting at the start of the basic-block. The > following makes sure to sink closest to the control dependence > check of the region we want to sink to as well as make sure to > ignore control dependences that are only guarding exceptional code. > This restores somewhat the old profile check but without requiring > nearly even probabilities. The patch also makes sure to not give > up completely when the best sink location is one we do not want to > sink to but possibly then choose the next best one. > > This addresses fallout observed in building libgo. > > Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. > > PR tree-optimization/115144 > * tree-ssa-sink.cc (do_not_sink): New function, split out > from ... > (select_best_block): Here. First pick valid block to > sink to. From that search for the best valid block, > avoiding sinking across conditions to exceptional code. > (sink_code_in_bb): When updating vuses of stores in > paths we do not sink a store to make sure we didn't > pick a dominating sink location. > > * gcc.dg/tree-ssa/ssa-sink-22.c: New testcase. > --- > gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-22.c | 14 +++ > gcc/tree-ssa-sink.cc | 106 +++++++++++++------- > 2 files changed, 86 insertions(+), 34 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-22.c > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-22.c > b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-22.c > new file mode 100644 > index 00000000000..e35626d4070 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-22.c > @@ -0,0 +1,14 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-sink1-details" } */ > + > +extern void abort (void); > + > +int foo (int x, int y, int f) > +{ > + int tem = x / y; > + if (f) > + abort (); > + return tem; > +} > + > +/* { dg-final { scan-tree-dump-not "Sinking" "sink1" } } */ > diff --git a/gcc/tree-ssa-sink.cc b/gcc/tree-ssa-sink.cc > index 2188b7523c7..b0fe871cf1e 100644 > --- a/gcc/tree-ssa-sink.cc > +++ b/gcc/tree-ssa-sink.cc > @@ -172,6 +172,39 @@ nearest_common_dominator_of_uses (def_operand_p def_p, > bool *debug_stmts) > return commondom; > } > > +/* Return whether sinking STMT from EARLY_BB to BEST_BB should be avoided. > */ > + > +static bool > +do_not_sink (gimple *stmt, basic_block early_bb, basic_block best_bb) > +{ > + /* Placing a statement before a setjmp-like function would be invalid > + (it cannot be reevaluated when execution follows an abnormal edge). > + If we selected a block with abnormal predecessors, just punt. */ > + if (bb_has_abnormal_pred (best_bb)) > + return true; > + > + /* If the latch block is empty, don't make it non-empty by sinking > + something into it. */ > + if (best_bb == early_bb->loop_father->latch > + && empty_block_p (best_bb)) > + return true; > + > + /* Avoid turning an unconditional read into a conditional one when we > + still might want to perform vectorization. */ > + if (best_bb->loop_father == early_bb->loop_father > + && loop_outer (best_bb->loop_father) > + && !best_bb->loop_father->inner > + && gimple_vuse (stmt) > + && !gimple_vdef (stmt) > + && flag_tree_loop_vectorize > + && !(cfun->curr_properties & PROP_loop_opts_done) > + && dominated_by_p (CDI_DOMINATORS, best_bb->loop_father->latch, > early_bb) > + && !dominated_by_p (CDI_DOMINATORS, best_bb->loop_father->latch, > best_bb)) > + return true; > + > + return false; > +} > + > /* Given EARLY_BB and LATE_BB, two blocks in a path through the dominator > tree, return the best basic block between them (inclusive) to place > statements. > @@ -185,54 +218,57 @@ select_best_block (basic_block early_bb, > basic_block late_bb, > gimple *stmt) > { > + /* First pick a block we do not disqualify. */ > + while (late_bb != early_bb > + && do_not_sink (stmt, early_bb, late_bb)) > + late_bb = get_immediate_dominator (CDI_DOMINATORS, late_bb); > + > basic_block best_bb = late_bb; > basic_block temp_bb = late_bb; > - > while (temp_bb != early_bb) > { > /* Walk up the dominator tree, hopefully we'll find a shallower > loop nest. */ > temp_bb = get_immediate_dominator (CDI_DOMINATORS, temp_bb); > > + /* Do not consider blocks we do not want to sink to. */ > + if (temp_bb != early_bb && do_not_sink (stmt, early_bb, temp_bb)) > + ; > + > /* If we've moved into a lower loop nest, then that becomes > our best block. */ > - if (bb_loop_depth (temp_bb) < bb_loop_depth (best_bb)) > + else if (bb_loop_depth (temp_bb) < bb_loop_depth (best_bb)) > best_bb = temp_bb; > - } > > - /* Placing a statement before a setjmp-like function would be invalid > - (it cannot be reevaluated when execution follows an abnormal edge). > - If we selected a block with abnormal predecessors, just punt. */ > - if (bb_has_abnormal_pred (best_bb)) > - return early_bb; > - > - /* If we found a shallower loop nest, then we always consider that > - a win. This will always give us the most control dependent block > - within that loop nest. */ > - if (bb_loop_depth (best_bb) < bb_loop_depth (early_bb)) > - return best_bb; > + /* A higher loop nest is always worse. */ > + else if (bb_loop_depth (temp_bb) > bb_loop_depth (best_bb)) > + ; > > - /* Do not move stmts to post-dominating places on the same loop depth. */ > - if (dominated_by_p (CDI_POST_DOMINATORS, early_bb, best_bb)) > - return early_bb; > + /* But sink the least distance, if the new candidate on the same > + loop depth is post-dominated by the current best block pick > + the new candidate. */ > + else if (dominated_by_p (CDI_POST_DOMINATORS, temp_bb, best_bb)) > + best_bb = temp_bb; > > - /* If the latch block is empty, don't make it non-empty by sinking > - something into it. */ > - if (best_bb == early_bb->loop_father->latch > - && empty_block_p (best_bb)) > - return early_bb; > + /* Avoid sinking across a conditional branching to exceptional > + code. In practice this does not reduce the number of dynamic > + executions of the sunk statement (this includes EH and > + branches leading to abort for example). Treat this case as > + post-dominating. */ > + else if (single_pred_p (best_bb) > + && single_pred_edge (best_bb)->src == temp_bb > + && (single_pred_edge (best_bb)->flags & EDGE_FALLTHRU > + || (single_pred_edge (best_bb)->probability > + >= profile_probability::always ()))) > + best_bb = temp_bb; > + } > > - /* Avoid turning an unconditional read into a conditional one when we > - still might want to perform vectorization. */ > - if (best_bb->loop_father == early_bb->loop_father > - && loop_outer (best_bb->loop_father) > - && !best_bb->loop_father->inner > - && gimple_vuse (stmt) > - && flag_tree_loop_vectorize > - && !(cfun->curr_properties & PROP_loop_opts_done) > - && dominated_by_p (CDI_DOMINATORS, best_bb->loop_father->latch, > early_bb) > - && !dominated_by_p (CDI_DOMINATORS, best_bb->loop_father->latch, > best_bb)) > - return early_bb; > + gcc_checking_assert (best_bb == early_bb > + || (!do_not_sink (stmt, early_bb, best_bb) > + && ((bb_loop_depth (best_bb) > + < bb_loop_depth (early_bb)) > + || !dominated_by_p (CDI_POST_DOMINATORS, > + early_bb, best_bb)))); > > return best_bb; > } > @@ -677,7 +713,9 @@ sink_code_in_bb (basic_block bb, virtual_operand_live > &vop_live) > gimple *vuse_stmt; > > FOR_EACH_IMM_USE_STMT (vuse_stmt, iter, gimple_vdef (stmt)) > - if (gimple_code (vuse_stmt) != GIMPLE_PHI) > + if (gimple_code (vuse_stmt) != GIMPLE_PHI > + && !dominated_by_p (CDI_DOMINATORS, gimple_bb (vuse_stmt), > + gsi_bb (togsi))) > FOR_EACH_IMM_USE_ON_STMT (use_p, iter) > SET_USE (use_p, gimple_vuse (stmt)); > } > -- > 2.35.3