On 01/07/2025 11:02, Richard Sandiford wrote:
Karl Meakin <karl.mea...@arm.com> writes:
@@ -763,6 +784,68 @@ (define_expand "cbranchcc4"
""
)
+;; Emit a `CB<cond> (register)` or `CB<cond> (immediate)` instruction.
+;; The immediate range depends on the comparison code.
+;; Comparisons against immediates outside this range fall back to
+;; CMP + B<cond>.
+(define_insn "aarch64_cb<INT_CMP:code><GPI:mode>"
+ [(set (pc) (if_then_else (INT_CMP
+ (match_operand:GPI 0 "register_operand" "r")
+ (match_operand:GPI 1 "nonmemory_operand"
+ "r<INT_CMP:cmpbr_imm_constraint>"))
+ (label_ref (match_operand 2))
+ (pc)))]
+ "TARGET_CMPBR && aarch64_cb_rhs (<INT_CMP:CODE>, operands[1])"
+ {
+ if (get_attr_far_branch (insn) == FAR_BRANCH_YES)
+ return aarch64_gen_far_branch (operands, 2, "L",
+ "cb<INT_CMP:inv_cmp_op>\\t%<w>0, %<w>1,
");
+ else
+ return "cb<INT_CMP:cmp_op>\\t%<w>0, %<w>1, %l2";
+ }
+ [(set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_N_1Kib))
+ (lt (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_P_1Kib)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_branch")
+ (if_then_else (and (ge (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_N_1Kib))
+ (lt (minus (match_dup 2) (pc))
+ (const_int BRANCH_LEN_P_1Kib)))
+ (const_string "no")
+ (const_string "yes")))]
+)
+
+;; Emit a `CBB<cond> (register)` or `CBH<cond> (register)` instruction.
+(define_insn "aarch64_cb<INT_CMP:code><SHORT:mode>"
+ [(set (pc) (if_then_else (INT_CMP
+ (match_operand:SHORT 0 "register_operand" "r")
+ (match_operand:SHORT 1 "aarch64_reg_or_zero" "rZ"))
+ (label_ref (match_operand 2))
+ (pc)))]
+ "TARGET_CMPBR"
+ "cb<SHORT:cmpbr_suffix><INT_CMP:cmp_op>\\t%<w>0, %<w>1, %l2"
This instruction also needs to handle far branches, in a similar way
to the GPI one. (It would be good to have a test for that too).
Why does the code for u32_x0_uge_64 etc. not change? I would have
expected 64 to be in range for that, whether it's treated as >= 64
or as > 63.
Because the comparison is normalized to `x0 <= 63` which does not fit in
the range for `CBLS` (-1 to 62)