On 04/08/2025 22:18, Richard Henderson wrote:
Some of the compare-and-branch patterns rely on CC for scratch in some
of the alternative expansions. This is fine, because when the combined
compare-and-branch patterns are formed by combine, we will be eliminating
a write to CC, so CC is dead anyway.
Standardize on the cc clobber for all such patterns, so that we don't
wind up with conflicts on pnum_clobbers. This fixes an assert:
0xa1fffe fancy_abort(char const*, int, char const*)
../../gcc/diagnostics/context.cc:1640
0x81340e patch_jump_insn
../../gcc/cfgrtl.cc:1303
0xc0eafe redirect_branch_edge
../../gcc/cfgrtl.cc:1330
0xc0f372 cfg_layout_redirect_edge_and_branch
../../gcc/cfgrtl.cc:4736
0xbfb6b9 redirect_edge_and_branch(edge_def*, basic_block_def*)
../../gcc/cfghooks.cc:391
0x1fa9310 try_forward_edges
../../gcc/cfgcleanup.cc:561
0x1fa9310 try_optimize_cfg
../../gcc/cfgcleanup.cc:2931
0x1fa9310 cleanup_cfg(int)
../../gcc/cfgcleanup.cc:3143
0x1fe11e8 rest_of_handle_cse
../../gcc/cse.cc:7591
0x1fe11e8 execute
../../gcc/cse.cc:7622
where the choice between aarch64_tbzltdi1 and aarch64_cbltdi
resulted in a recog failure.
Because this removes the direct expansion of TARGET_CMPBR, and
because rtx costing is wrong, the CMPBR patterns won't be used.
To be fixed in a subsequent patch.
gcc:
PR target/121385
* config/aarch64/aarch64.cc (aarch64_gen_compare_zero_and_branch):
Add cc clobber when expanding to CB<EQL>.
* config/aarch64/aarch64.md (cbranch<GPI>4): Don't directly
expand to TARGET_CMPBR patterns.
(*aarch64_cbz<EQL><GPI>): Add cc clobber.
("aarch64_cb<INT_CMP><GPI>): Likewise.
("aarch64_cb<INT_CMP><SHORT>): Likewise.
---
gcc/config/aarch64/aarch64.cc | 11 ++++++++++-
gcc/config/aarch64/aarch64.md | 23 ++++++++++-------------
2 files changed, 20 insertions(+), 14 deletions(-)
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index b7d26cded8b..ff9243ea732 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -2901,7 +2901,16 @@ aarch64_gen_compare_zero_and_branch (rtx_code code, rtx
x,
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
gen_rtx_LABEL_REF (Pmode, label), pc_rtx);
- return gen_rtx_SET (pc_rtx, x);
+ x = gen_rtx_SET (pc_rtx, x);
+
+ if (!aarch64_track_speculation)
+ {
+ rtx c = gen_rtx_REG (CCmode, CC_REGNUM);
+ c = gen_rtx_CLOBBER (VOIDmode, c);
+ x = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x, c));
+ }
+
+ return x;
}
/* Return an rtx that branches to LABEL based on the value of bit BITNUM of X.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 7def6d3ff36..b947da977c3 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -755,16 +755,9 @@
(pc)))]
""
{
- if (TARGET_CMPBR && aarch64_cb_rhs (GET_CODE (operands[0]), operands[2]))
- {
- /* The branch is supported natively. */
- }
- else
- {
- operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]),
- operands[1], operands[2]);
- operands[2] = const0_rtx;
- }
+ operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]),
+ operands[1], operands[2]);
+ operands[2] = const0_rtx;
}
)
Now that the body of `cbranch<GPI>` and `cbranch<GPF_F16>` are the same,
could we merge them into one rule?
@@ -794,11 +787,13 @@
)
;; For an EQ/NE comparison against zero, emit `CBZ`/`CBNZ`
+;; The clobber is present to coordinate with other branches.
(define_insn "*aarch64_cbz<optab><mode>"
[(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
(const_int 0))
(label_ref (match_operand 1))
- (pc)))]
+ (pc)))
+ (clobber (reg:CC CC_REGNUM))]
"!aarch64_track_speculation"
{
if (get_attr_length (insn) == 8)
@@ -877,7 +872,8 @@
(match_operand:GPI 1 "nonmemory_operand"
"r<INT_CMP:cmpbr_imm_constraint>"))
(label_ref (match_operand 2))
- (pc)))]
+ (pc)))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_CMPBR && aarch64_cb_rhs (<INT_CMP:CODE>, operands[1])"
{
return (get_attr_far_branch (insn) == FAR_BRANCH_NO)
@@ -908,7 +904,8 @@
(match_operand:SHORT 0 "register_operand" "r")
(match_operand:SHORT 1 "aarch64_reg_or_zero" "rZ"))
(label_ref (match_operand 2))
- (pc)))]
+ (pc)))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_CMPBR"
{
return (get_attr_far_branch (insn) == FAR_BRANCH_NO)