Karl Meakin <karl.mea...@arm.com> writes:
>>> +  else
>>> +    {
>>> +      operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]),
>>> +                                        operands[1], operands[2]);
>>> +      operands[2] = const0_rtx;
>>> +    }
>>> +  }
>>> +)
>>> +
>>> @@ -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")))]
>>> +)
>>> +
>> The patch defines cmpbr_suffix to handle :GPI as well as :SHORT.
>> It looks like the main remaining difference between these two
>> patterns is the predicate (and as Kyrill says, the constraint)
>> on operand 2.  It would be possible to handle that difference
>> using mode attributes too, such as:
>>
>>    "aarch64_<cb_operand>" "r<cb_imm>"
>>
>> with cb_operand defined to cb_short_operand for :SHORT and
>> cb_operand for :GPI.  Similarly <cb_imm> would map to Z for
>> :SHORT and a new constraint for :GPI.  I don't know that that's
>> better, just though I'd mention it in case.
>>
>> 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.
>
> I think that will be handled for us by the assembler: `CBLE x0 42` will 
> be rewritten to `CBLT x0 43` etc

Ah, ok, so we can just emit the natural asm.  But I think the rest still
stands.  We'd need to use different constraints, since the lower and upper
bounds of CBLE are one less than the corresponding bounds of CBLT.

It would also be good to make the tests accept both the alias and
non-alias forms.

Richard

Reply via email to