https://gcc.gnu.org/g:a7cce1afee8ba28c524a4a43f0081e36e5501cf2
commit r16-7880-ga7cce1afee8ba28c524a4a43f0081e36e5501cf2 Author: H.J. Lu <[email protected]> Date: Sun Feb 22 10:32:30 2026 +0800 x86: Call ix86_access_stack_p only with symbolic constant load ix86_access_stack_p can be quite expensive. Cache the result and call it only if there are symbolic constant loads. This reduces the compile time of PR target/124165 test from 202 seconds to 55 seconds. gcc/ PR target/124165 * config/i386/i386-protos.h (symbolic_reference_mentioned_p): Change the argument type from rtx to const_rtx. * config/i386/i386.cc (symbolic_reference_mentioned_p): Likewise. (ix86_access_stack_p): Add 2 auto_bitmap[] arguments. Cache the register BB domination result. (ix86_symbolic_const_load_p_1): New. (ix86_symbolic_const_load_p): Likewise. (ix86_find_max_used_stack_alignment): If there is no symbolic constant load into the register, don't call ix86_access_stack_p. Signed-off-by: H.J. Lu <[email protected]> Diff: --- gcc/config/i386/i386-protos.h | 2 +- gcc/config/i386/i386.cc | 144 +++++++++++++++++++++++++++++++++++------- 2 files changed, 123 insertions(+), 23 deletions(-) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 20b964748581..4ba4fb08556e 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -60,7 +60,7 @@ extern int standard_sse_constant_p (rtx, machine_mode); extern const char *standard_sse_constant_opcode (rtx_insn *, rtx *); extern bool ix86_standard_x87sse_constant_load_p (const rtx_insn *, rtx); extern bool ix86_pre_reload_split (void); -extern bool symbolic_reference_mentioned_p (rtx); +extern bool symbolic_reference_mentioned_p (const_rtx); extern bool extended_reg_mentioned_p (rtx); extern bool x86_extended_QIreg_mentioned_p (rtx_insn *); extern bool x86_extended_reg_mentioned_p (rtx); diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 428b68aff471..c43c3ac18acf 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -5990,7 +5990,7 @@ ix86_output_ssemov (rtx_insn *insn, rtx *operands) /* Returns true if OP contains a symbol reference */ bool -symbolic_reference_mentioned_p (rtx op) +symbolic_reference_mentioned_p (const_rtx op) { const char *fmt; int i; @@ -8717,8 +8717,15 @@ ix86_find_all_reg_uses (HARD_REG_SET ®set, static bool ix86_access_stack_p (unsigned int regno, basic_block bb, HARD_REG_SET &set_up_by_prologue, - HARD_REG_SET &prologue_used) + HARD_REG_SET &prologue_used, + auto_bitmap reg_dominate_bbs_known[], + auto_bitmap reg_dominate_bbs[]) { + if (bitmap_bit_p (reg_dominate_bbs_known[regno], bb->index)) + return bitmap_bit_p (reg_dominate_bbs[regno], bb->index); + + bitmap_set_bit (reg_dominate_bbs_known[regno], bb->index); + /* Get all BBs which set REGNO and dominate the current BB from all DEFs of REGNO. */ for (df_ref def = DF_REG_DEF_CHAIN (regno); @@ -8735,10 +8742,76 @@ ix86_access_stack_p (unsigned int regno, basic_block bb, /* Return true if INSN requires stack. */ if (requires_stack_frame_p (insn, prologue_used, set_up_by_prologue)) - return true; + { + bitmap_set_bit (reg_dominate_bbs[regno], bb->index); + return true; + } } } + /* When we get here, REGNO used in the current BB doesn't access + stack. */ + return false; +} + +/* Helper function for ix86_symbolic_const_load_p. */ + +static bool +ix86_symbolic_const_load_p_1 (rtx set) +{ + rtx dest = SET_DEST (set); + + if (!REG_P (dest)) + return false; + + /* Reject non-Pmode modes. */ + if (GET_MODE (dest) != Pmode) + return false; + + const_rtx src = SET_SRC (set); + + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, src, ALL) + { + auto op = *iter; + + if (MEM_P (op)) + iter.skip_subrtxes (); + else if (SYMBOLIC_CONST (op)) + return true; + } + + return false; +} + +/* Return true if INSN loads a symbolic constant into register REGNO. */ + +static bool +ix86_symbolic_const_load_p (rtx_insn *insn, unsigned int regno) +{ + rtx set = single_set (insn); + if (set) + return ix86_symbolic_const_load_p_1 (set); + + rtx pat = PATTERN (insn); + if (GET_CODE (pat) != PARALLEL) + return false; + + for (int i = 0; i < XVECLEN (pat, 0); i++) + { + rtx exp = XVECEXP (pat, 0, i); + + if (GET_CODE (exp) == SET) + { + rtx dest = SET_DEST (exp); + if (REG_P (dest) + && GET_MODE (dest) == Pmode + && REGNO (dest) == regno + && ix86_symbolic_const_load_p_1 (exp)) + return true; + } + } + return false; } @@ -8818,32 +8891,59 @@ ix86_find_max_used_stack_alignment (unsigned int &stack_alignment, hard_reg_set_iterator hrsi; stack_access_data data; + auto_bitmap reg_dominate_bbs_known[FIRST_PSEUDO_REGISTER]; + auto_bitmap reg_dominate_bbs[FIRST_PSEUDO_REGISTER]; + data.stack_alignment = &stack_alignment; EXECUTE_IF_SET_IN_HARD_REG_SET (stack_slot_access, 0, regno, hrsi) - for (df_ref ref = DF_REG_USE_CHAIN (regno); - ref != NULL; - ref = DF_REF_NEXT_REG (ref)) - { - if (DF_REF_IS_ARTIFICIAL (ref)) - continue; + { + /* Set to true if there is a symbolic constant load into REGNO. */ + bool symbolic_const_load_p = false; - rtx_insn *insn = DF_REF_INSN (ref); + if (!TEST_HARD_REG_BIT (hard_stack_slot_access, regno)) + for (df_ref def = DF_REG_DEF_CHAIN (regno); + def; + def = DF_REF_NEXT_REG (def)) + if (!DF_REF_IS_ARTIFICIAL (def) + && !DF_REF_FLAGS_IS_SET (def, DF_REF_MAY_CLOBBER) + && !DF_REF_FLAGS_IS_SET (def, DF_REF_MUST_CLOBBER)) + { + rtx_insn *insn = DF_REF_INSN (def); + if (ix86_symbolic_const_load_p (insn, regno)) + { + symbolic_const_load_p = true; + break; + } + } - if (!NONJUMP_INSN_P (insn)) - continue; + for (df_ref ref = DF_REG_USE_CHAIN (regno); + ref != NULL; + ref = DF_REF_NEXT_REG (ref)) + { + if (DF_REF_IS_ARTIFICIAL (ref)) + continue; - if (TEST_HARD_REG_BIT (hard_stack_slot_access, regno) - || ix86_access_stack_p (regno, BLOCK_FOR_INSN (insn), - set_up_by_prologue, prologue_used)) - { - /* Update stack alignment if REGNO is used for stack - access. */ - data.reg = DF_REF_REG (ref); - note_stores (insn, ix86_update_stack_alignment, &data); + rtx_insn *insn = DF_REF_INSN (ref); + + if (!NONJUMP_INSN_P (insn)) continue; - } - } + + /* If there is no symbolic constant load into the register, + don't call ix86_access_stack_p. */ + if (!symbolic_const_load_p + || ix86_access_stack_p (regno, BLOCK_FOR_INSN (insn), + set_up_by_prologue, prologue_used, + reg_dominate_bbs_known, + reg_dominate_bbs)) + { + /* Update stack alignment if REGNO is used for stack + access. */ + data.reg = DF_REF_REG (ref); + note_stores (insn, ix86_update_stack_alignment, &data); + } + } + } free_dominance_info (CDI_DOMINATORS); }
