Richard Sandiford <richard.sandif...@arm.com> writes: >> @@ -758,6 +781,58 @@ (define_expand "cbranchcc4" >> "" >> ) >> >> +;; Emit a `CB<cond> (register)` or `CB<cond> (immediate)` instruction. >> +(define_insn "aarch64_cb<GPI:mode>" >> + [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" >> + [(match_operand:GPI 1 "register_operand") >> + (match_operand:GPI 2 "aarch64_cb_operand")]) >> + (label_ref (match_operand 3)) >> + (pc)))] >> + "TARGET_CMPBR" >> + "cb%m0\\t%<w>1, %<w>2, %l3"; >> + [(set_attr "type" "branch") >> + (set (attr "length") >> + (if_then_else (and (ge (minus (match_dup 3) (pc)) >> + (const_int BRANCH_LEN_N_1Kib)) >> + (lt (minus (match_dup 3) (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 3) (pc)) >> + (const_int BRANCH_LEN_N_1Kib)) >> + (lt (minus (match_dup 3) (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<SHORT:mode>" >> + [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" >> + [(match_operand:SHORT 1 "register_operand") >> + (match_operand:SHORT 2 >> "aarch64_cb_short_operand")]) >> + (label_ref (match_operand 3)) >> + (pc)))] >> + "TARGET_CMPBR" >> + "cb<SHORT:cmpbr_suffix>%m0\\t%<w>1, %<w>2, %l3"; >> + [(set_attr "type" "branch") >> + (set (attr "length") >> + (if_then_else (and (ge (minus (match_dup 3) (pc)) >> + (const_int BRANCH_LEN_N_1Kib)) >> + (lt (minus (match_dup 3) (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 3) (pc)) >> + (const_int BRANCH_LEN_N_1Kib)) >> + (lt (minus (match_dup 3) (pc)) >> + (const_int BRANCH_LEN_P_1Kib))) >> + (const_string "no") >> + (const_string "yes")))] >> +) >> + > > [...] > > A slight wrinkle is that the CB<cc> immediate instruction requires CBLT > rather than CBLE, etc. IIRC, GCC canonicalises in the opposite > direction, preferring LEU over LTU, etc. > > So I think we might need a custom version of aarch64_comparison_operator > that checks whether the immediate is in the range [0, 63] for the "native" > cmoparisons and an appropriate variant for the "non-native" comparisons > (LE, GE, LEU, GEU). The output asm section would then need to adjust > the instruction accordingly before printing it out.
Sorry, I realised later than a match_operator along the lines I suggested wouldn't work well in combination with the constraints. We'd need to use one constraint for the native operations and another constraint for the emulated ones. So perhaps the define_insns will need to use a code iterator instead of a match_operator. With a code iterator, the constraint string can use a code attribute to choose the appropriate range. Thanks, Richard