How to implement compare and branch instruction

Richard Henderson rth@redhat.com
Thu Sep 24 16:28:00 GMT 2009


On 09/24/2009 05:41 AM, Mohamed Shafi wrote:
> (define_expand "cmp<mode>"
...
> (define_expand "b<code>"

For the record, you should be combining these into a cbranch expander, 
so that you don't have to do the "save the cmp operands" trick anymore.

> (define_insn_and_split "compare_and_branch_insn"
>   [(set (pc)
>         (if_then_else (match_operator:CC 3 "comparison_operator"
>                                 [(match_operand 1 "register_operand"
> "d,d,a,a,d,t,k,t")
>                                  (match_operand 2 "nonmemory_operand"
> "J,L,J,L,d,t,t,k")])
>                       (label_ref (match_operand 0 "" ""))
>                       (pc)))]
>   "!unsigned_immediate_compare_p (GET_CODE (operands[3]), operands[2])"
>   "#"
>   "reload_completed"
>   [(set (reg:CC CC_REGNUM)
>         (match_op_dup:CC 3 [(match_dup 1) (match_dup 2)]))
>    (set (pc)
>         (if_then_else (eq (reg:CC CC_REGNUM) (const_int 0))
>                       (label_ref (match_dup 0))
>                       (pc)))]
>    "{
>      if (expand_compare_insn (operands, 0))
>        DONE;
>    }"
> )

The problem is that reload doesn't look at either the operand predicates 
or the extra predicate field (your unsigned_immediate_compare_p call). 
It only looks at the constraint letters.  And your constraint letters 
say that immediates are allowed.

You'll need to split this pattern in two and handle the signed 
comparisons in one pattern (with the immediates) and the unsigned 
comparisons in the other pattern (without the immediates).  You'll just 
need to define two new operator predicates, e.g.

(define_predicate "signed_comparison_operator"
   (match_code "eq,ne,le,lt,ge,gt"))


r~



More information about the Gcc mailing list