https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120434
--- Comment #13 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jakub Jelinek <ja...@gcc.gnu.org>: https://gcc.gnu.org/g:8154fc95f097a146f9c80edcaafb2baff73065b5 commit r16-1398-g8154fc95f097a146f9c80edcaafb2baff73065b5 Author: Jakub Jelinek <ja...@redhat.com> Date: Tue Jun 10 20:04:52 2025 +0200 expand, ranger: Use ranger during expansion [PR120434] As the following testcase shows, during expansion we use value range info in lots of places, but sadly currently use only the global ranges. It is mostly through get_range_pos_neg function, which uses get_global_range_query ()->range_of_expr (arg1, arg2) but other spots use it directly. On the testcase at the end of the patch, in foo we don't know range of x, so emit the at least on x86_64 less efficient signed division in that case. In bar, the default def SSA_NAME has global range and we try to expand the division both as signed and unsigned because the range proves they will have the same result and choose the cheaper one. And finally in baz, we have VARYING in global range, but can do better if we ask for range at the statement we're expanding. The main problem of using the ranger during expansion is that things are in flux, the already expanded basic blocks switch their IL from gimple to RTL (bb->flags & BB_RTL) and the gimple stmts are gone, PHI nodes even earlier, etc. The patch attempts to make the ranger usable by keeping (bb->flags & BB_RTL) == 0 on basic blocks for longer, in particular until the last expand_gimple_basic_block call for the function. Instead of changing the IL right away, it uses a vector indexed by bb->index to hold the future BB_HEAD/BB_END. I had to do a few changes on the ranger side and maybe testing in the wild will show a few extra cases, but I think those are tolerable and can be guarded with currently_expanding_to_rtl so that we don't punt on consistency checks on normal GIMPLE. In particular, even with the patch there will still be some BB_RTL bbs in the IL, e.g. the initial block after ENTRY, ENTRY and EXIT blocks and from time to time others as well, but those should never contain anything intreresting from the ranger POV. And switch expansion can drop the default edge if it is __builtin_unreachable. Also, had to change the internal call TER expansion, the current way of temporarily changing gimple_call_lhs ICEd badly in the ranger, so I'm instead temporarily changing SSA_NAME_VAR of the SSA_NAME. 2025-06-10 Jakub Jelinek <ja...@redhat.com> PR middle-end/120434 * cfgrtl.h (update_bb_for_insn_chain): Declare. * cfgrtl.cc (update_bb_for_insn_chain): No longer static. * cfgexpand.h (expand_remove_edge): Declare. * cfgexpand.cc: Include "gimple-range.h". (head_end_for_bb): New variable. (label_rtx_for_bb): Drop ATTRIBUTE_UNUSED from bb argument. Use head_end_for_bb if possible for non-BB_RTL bbs. (expand_remove_edge): New function. (maybe_cleanup_end_of_block): Use it instead of remove_edge. (expand_gimple_cond): Don't clear EDGE_TRUE_VALUE and EDGE_FALSE_VALUE just yet. Use head_end_for_bb elts instead of BB_END and update_bb_for_insn_chain instead of update_bb_for_insn. (expand_gimple_tailcall): Use expand_remove_edge instead of remove_edge. Use head_end_for_bb elts instead of BB_END and update_bb_for_insn_chain instead of update_bb_for_insn. (expand_gimple_basic_block): Don't change bb to BB_RTL here, instead use head_end_for_bb elts instead of BB_HEAD and BB_END. Use update_bb_for_insn_chain instead of update_bb_for_insn. (pass_expand::execute): Enable ranger before expand_gimple_basic_block calls and create head_end_for_bb vector. Disable ranger after those calls, turn still non-BB_RTL blocks into BB_RTL and set their BB_HEAD and BB_END from head_end_for_bb elts, and clear EDGE_TRUE_VALUE and EDGE_FALSE_VALUE flags on edges. Release head_end_for_bb vector. * tree-outof-ssa.cc (expand_phi_nodes): Don't clear phi nodes here. * tree.h (get_range_pos_neg): Add gimple * argument defaulted to NULL. * tree.cc (get_range_pos_neg): Add stmt argument. Use get_range_query (cfun) instead of get_global_range_query () and pass stmt as third argument to range_of_expr. * expr.cc (expand_expr_divmod): Pass currently_expanding_gimple_stmt to get_range_pos_neg. (expand_expr_real_1) <case SSA_NAME>: Change internal fn handling to avoid temporarily overwriting gimple_call_lhs of ifn, instead temporarily overwrite SSA_NAME_VAR of its lhs. (maybe_optimize_pow2p_mod_cmp): Pass currently_expanding_gimple_stmt to get_range_pos_neg. (maybe_optimize_mod_cmp): Likewise. * internal-fn.cc (get_min_precision): Likewise. Use get_range_query (cfun) instead of get_global_range_query () and pass currently_expanding_gimple_stmt as third argument to range_of_expr. Pass g to get_range_pos_neg. (expand_addsub_overflow): Pass currently_expanding_gimple_stmt to get_range_pos_neg. (expand_mul_overflow): Likewise. (expand_arith_overflow): Pass stmt to get_range_pos_neg. * gimple-range-edge.cc: Include rtl.h. (gimple_outgoing_range_stmt_p): Return NULL for BB_RTL bbs. (gimple_outgoing_range::calc_switch_range): If default_edge is NULL, assert currently_expanding_to_rtl and return before trying to set range on that edge. * builtins.cc (expand_builtin_strnlen): Use get_range_query (cfun) instead of get_global_range_query () and pass currently_expanding_gimple_stmt as third argument to range_of_expr. (determine_block_size): Likewise. * gimple-range.cc (gimple_ranger::range_on_exit): Set s to NULL instead of last_nondebug_stmt for BB_RTL bbs. * stmt.cc: Include cfgexpand.h. (expand_case): Use expand_remove_edge instead of remove_edge. * gcc.target/i386/pr120434-1.c: New test.