https://gcc.gnu.org/g:6bae0c37c95565171657a15ab4dcfd13a6898769
commit r17-387-g6bae0c37c95565171657a15ab4dcfd13a6898769 Author: Richard Sandiford <[email protected]> Date: Thu May 7 20:16:37 2026 +0100 Add post_ra_split_completed and use it for the RX port Some targets need to be able to introduce new clobbers of the condition-code register during register allocation. The main approach for handling that situation is to ensure that the CC register is never live before or during RA. This allows new clobbers to be introduced at any time when !reload_completed. This works well. However: (a) Explicit uses and sets of the CC register are usually introduced by the first post-reload split, rather than directly after RA. (b) If the CC register is never live before and during RA, there is no real need for patterns to have an explicit clobber of the CC register at that point. Not having a CC clobber would allow more recog attempts to succeed, both before and during RA. (AFAIK, only combine and RTL-SSA keep tabs on when new CC clobbers can be introduced as part of a recog attempt.) (c) If a clobber of the CC register is hidden, it would need to be made explicit before, or at the same time as, the explicit uses and sets from (a). The idea of this patch is therefore to allow the boundary between "CC is never live" and "CC might be live" to be moved from reload_completed to the first post-RA split. It converts the RX port to this form. gcc/ * rtl.h (post_ra_split_completed): Declare. * final.cc (rest_of_clean_state): Set it to false. * recog.cc (post_ra_split_completed): New variable. (split_insn): Temporarily set post_ra_split_completed while walking the new instructions. (split_all_insns, split_all_insns_noflow): Set post_ra_split_completed after completing a post-reload split. * config/rx/rx.md (*cmpsi, *tstsi, *cmpsf, *conditional_branch) (*sccc, *stcc, *stcc_reg, *abssi2_flags, *addsi3_flags, adc_internal) (*adc_flags, *andsi3_flags, *negsi2_flags, *one_cmplsi2_flags) (*iorsi3_flags, *rotlsi3_flags, *rotrsi3_flags, *ashrsi3_flags) (*lshrsi3_flags, *ashlsi3_flags, *sat, *subsi3_flags, sbb_internal) (*sbb_flags, *xorsi3_flags, *bmcc): Require post_ra_split_completed rather than reload_completed. (comparesi3_<extend_types:code><small_int_modes:mode>, addsi3_flags) (subsi3_flags): Require post_ra_split_completed. Diff: --- gcc/config/rx/rx.md | 56 ++++++++++++++++++++++++++------------------------ gcc/final.cc | 1 + gcc/recog.cc | 11 ++++++++++ gcc/rtl.h | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 27 deletions(-) diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index 808dfc8b35aa..83aab0f14b25 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -191,7 +191,7 @@ [(set (reg:CC CC_REG) (compare:CC (match_operand:SI 0 "register_operand" "r,r,r,r,r,r,r") (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))] - "reload_completed" + "post_ra_split_completed" "cmp\t%Q1, %0" [(set_attr "timings" "11,11,11,11,11,11,33") (set_attr "length" "2,2,3,4,5,6,5")] @@ -255,7 +255,7 @@ (and:SI (match_operand:SI 0 "register_operand" "r,r,r") (match_operand:SI 1 "rx_source_operand" "r,i,Q")) (const_int 0)))] - "reload_completed" + "post_ra_split_completed" "tst\t%Q1, %0" [(set_attr "timings" "11,11,33") (set_attr "length" "3,7,6")] @@ -295,7 +295,7 @@ (compare:CC_F (match_operand:SF 0 "register_operand" "r,r,r") (match_operand:SF 1 "rx_source_operand" "r,F,Q")))] - "ALLOW_RX_FPU_INSNS && reload_completed" + "ALLOW_RX_FPU_INSNS && post_ra_split_completed" "fcmp\t%1, %0" [(set_attr "timings" "11,11,33") (set_attr "length" "3,7,5")] @@ -310,7 +310,7 @@ [(reg CC_REG) (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc)))] - "reload_completed" + "post_ra_split_completed" "b%B1\t%0" [(set_attr "length" "8") ;; This length is wrong, but it is ;; too hard to compute statically. @@ -702,7 +702,7 @@ [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "comparison_operator" [(reg CC_REG) (const_int 0)]))] - "reload_completed" + "post_ra_split_completed" "sc%B1.L\t%0" [(set_attr "length" "3")] ) @@ -807,7 +807,7 @@ [(reg CC_REG) (const_int 0)]) (match_operand:SI 1 "immediate_operand" "Sint08,Sint16,Sint24,i") (match_dup 0)))] - "reload_completed + "post_ra_split_completed && ((GET_CODE (operands[2]) == EQ) || (GET_CODE (operands[2]) == NE))" { if (GET_CODE (operands[2]) == EQ) @@ -826,7 +826,7 @@ (match_operand:SI 1 "nonmemory_operand" "r,Uint04,Sint08,Sint16,Sint24,i") (match_dup 0)))] - "reload_completed" + "post_ra_split_completed" { PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2]))); return "b%B2 1f\n\tmov %1, %0\n1:"; @@ -856,7 +856,7 @@ ;; Note - although the ABS instruction does set the O bit in the processor ;; status word, it does not do so in a way that is comparable with the CMP ;; instruction. Hence we use CC_ZSmode rather than CC_ZSOmode. - "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ abs\t%0 abs\t%1, %0" @@ -908,7 +908,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r") (plus:SI (match_dup 1) (match_dup 2)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSCmode)" "@ add\t%2, %0 add\t%2, %0 @@ -937,6 +937,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand") (plus:SI (match_dup 1) (match_dup 2)))])] + "post_ra_split_completed" ) (define_insn "adc_internal" @@ -947,7 +948,7 @@ (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")) (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))) (clobber (reg:CC CC_REG))] - "reload_completed" + "post_ra_split_completed" "adc\t%2, %0" [(set_attr "timings" "11,11,11,11,11,33") (set_attr "length" "3,4,5,6,7,6")] @@ -968,7 +969,7 @@ (ltu:SI (reg:CC CC_REG) (const_int 0)) (match_dup 1)) (match_dup 2)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSCmode)" "adc\t%2, %0" [(set_attr "timings" "11,11,11,11,11,33") (set_attr "length" "3,4,5,6,7,6")] @@ -1136,7 +1137,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") (and:SI (match_dup 1) (match_dup 2)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ and\t%2, %0 and\t%2, %0 @@ -1367,7 +1368,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r,r") (neg:SI (match_dup 1)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ neg\t%0 neg\t%1, %0" @@ -1391,7 +1392,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r,r") (not:SI (match_dup 1)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ not\t%0 not\t%1, %0" @@ -1440,7 +1441,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") (ior:SI (match_dup 1) (match_dup 2)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ or\t%2, %0 or\t%2, %0 @@ -1472,7 +1473,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r") (rotate:SI (match_dup 1) (match_dup 2)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSmode)" "rotl\t%2, %0" [(set_attr "length" "3")] ) @@ -1494,7 +1495,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r") (rotatert:SI (match_dup 1) (match_dup 2)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSmode)" "rotr\t%2, %0" [(set_attr "length" "3")] ) @@ -1519,7 +1520,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r,r,r") (ashiftrt:SI (match_dup 1) (match_dup 2)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ shar\t%2, %0 shar\t%2, %0 @@ -1547,7 +1548,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r,r,r") (lshiftrt:SI (match_dup 1) (match_dup 2)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ shlr\t%2, %0 shlr\t%2, %0 @@ -1575,7 +1576,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r,r,r") (ashift:SI (match_dup 1) (match_dup 2)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ shll\t%2, %0 shll\t%2, %0 @@ -1609,7 +1610,7 @@ (unspec:SI [(match_operand:SI 1 "register_operand" "0") (reg:CC CC_REG)] UNSPEC_BUILTIN_SAT))] - "reload_completed" + "post_ra_split_completed" "sat\t%0" [(set_attr "length" "2")] ) @@ -1639,7 +1640,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") (minus:SI (match_dup 1) (match_dup 2)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSCmode)" "@ sub\t%2, %0 sub\t%2, %0 @@ -1659,6 +1660,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand") (minus:SI (match_dup 1) (match_dup 2)))])] + "post_ra_split_completed" ) (define_insn "sbb_internal" @@ -1669,7 +1671,7 @@ (match_operand:SI 2 "rx_compare_operand" " r,Q")) (geu:SI (reg:CC CC_REG) (const_int 0)))) (clobber (reg:CC CC_REG))] - "reload_completed" + "post_ra_split_completed" "sbb\t%2, %0" [(set_attr "timings" "11,33") (set_attr "length" "3,6")] @@ -1688,7 +1690,7 @@ (minus:SI (minus:SI (match_dup 1) (match_dup 2)) (geu:SI (reg:CC CC_REG) (const_int 0))))] - "reload_completed" + "post_ra_split_completed" "sbb\t%2, %0" [(set_attr "timings" "11,33") (set_attr "length" "3,6")] @@ -1769,7 +1771,7 @@ (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") (xor:SI (match_dup 1) (match_dup 2)))] - "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "post_ra_split_completed && rx_match_ccmode (insn, CC_ZSmode)" "xor\t%Q2, %0" [(set_attr "timings" "11,11,11,11,11,33") (set_attr "length" "3,4,5,6,7,6")] @@ -1931,7 +1933,7 @@ [(set (reg:CC CC_REG) (compare:CC (match_operand:SI 0 "register_operand" "r") (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand" "Q"))))] - "(optimize < 3 || optimize_size)" + "post_ra_split_completed && (optimize < 3 || optimize_size)" "cmp\t%<extend_types:letter>1, %0" [(set_attr "timings" "33") (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length @@ -2180,7 +2182,7 @@ (match_operand:SI 1 "const_int_operand" "")) (match_operator:SI 2 "comparison_operator" [(reg CC_REG) (const_int 0)]))] - "reload_completed" + "post_ra_split_completed" "bm%B2\t%1, %0" [(set_attr "length" "3")] ) diff --git a/gcc/final.cc b/gcc/final.cc index b5e8c6e2efde..0152be59fc85 100644 --- a/gcc/final.cc +++ b/gcc/final.cc @@ -4498,6 +4498,7 @@ rest_of_clean_state (void) flag_rerun_cse_after_global_opts = 0; reload_completed = 0; + post_ra_split_completed = false; epilogue_completed = 0; #ifdef STACK_REGS regstack_completed = 0; diff --git a/gcc/recog.cc b/gcc/recog.cc index f37e548d6ab1..4cae276f1f70 100644 --- a/gcc/recog.cc +++ b/gcc/recog.cc @@ -96,6 +96,8 @@ bool raw_constraint_p; int reload_completed; +bool post_ra_split_completed; + /* Nonzero after thread_prologue_and_epilogue_insns has run. */ int epilogue_completed; @@ -3525,6 +3527,8 @@ split_insn (rtx_insn *insn) splitters instead of computing the proper hard register. */ if (reload_completed && first != last) { + auto old_post_ra_split_completed = post_ra_split_completed; + post_ra_split_completed = true; first = NEXT_INSN (first); for (;;) { @@ -3534,6 +3538,7 @@ split_insn (rtx_insn *insn) break; first = NEXT_INSN (first); } + post_ra_split_completed = old_post_ra_split_completed; } return last; @@ -3609,6 +3614,9 @@ split_all_insns (void) } } + if (reload_completed) + post_ra_split_completed = true; + default_rtl_profile (); if (changed) { @@ -3658,6 +3666,9 @@ split_all_insns_noflow (void) split_insn (insn); } } + + if (reload_completed) + post_ra_split_completed = true; } struct peep2_insn_data diff --git a/gcc/rtl.h b/gcc/rtl.h index eebcc18a4f1a..c1051f48984d 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -4170,6 +4170,65 @@ extern int reload_completed; /* Nonzero after thread_prologue_and_epilogue_insns has run. */ extern int epilogue_completed; +/* Set to true once the first split pass after register allocation has + been run. Ports can treat that split pass as a "lowering" pass, + with some instructions only being valid before the lowering + and others only being valid after the lowering. + + One use of this variable is to cope with address calculations during + register allocation. The register allocator needs to be able to perform + address arithmetic (such as addition) at arbitrary points in the program, + regardless of whether the condition-code flags are live at that point. + If a target cannot add without clobbering the condition-code flags, + it must either (1) hide the condition-code flags entirely from RTL + or (2) ensure that the condition-code flags are never live before + or during register allocation. + + (2) requires a boundary between "the condition-code flags are never live" + and "the condition-code flags might be live". reload_completed can be + used for this purpose, provided that all clobbers of the CC register + are explicit before and during register allocation. + + However, if the condition-code flags are never live before or during + register allocation, there is no real need for patterns to have an explicit + clobber of the flags at that point. Not having a clobber would allow more + recog attempts to succeed, both before and during register allocation. + + post_ra_split_completed is an alternative boundary to reload_completed. + It allows sets and uses of the condition-code flags, such as individual + comparison and jump instructions, to be introduced in the first split pass + after register allocation, while also allowing new implicit clobbers of + the condition-code flags to be introduced at any time before that point. + + Ports that use post_ra_split_completed for this purpose would have an + "unlowered" form with the following properties: + + (a) The condition-code flags are never live between instructions. + (That is, they are never defined by one instruction and used + by another instruction.) + + (b) As a consequence, new clobbers of the condition-code flags + can be introduced at any time. + + (c) RTL instruction patterns (such as addition) can omit clobbers of the + condition-code flags even if the flags are in fact clobbered. + + In contrast, the "lowered" form would have these properties: + + (d) The condition-code flags can be live between instructions. + That is, RTL instruction patterns can set the condition-code flags + or use the condition-code flags. + + (e) All clobbers of the condition-code flags must be explicit in the RTL + instruction patterns. + + Instructions covered by (c) would require !post_ra_split_completed + and would need to be split into instructions that satisfy (d) or (e). + Instructions covered by (d) would require post_ra_split_completed, + so that they are not accidentally matched before lowering has taken + place. */ +extern bool post_ra_split_completed; + /* Set to 1 while reload_as_needed is operating. Required by some machines to handle any generated moves differently. */
