public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* How to implement compare and branch instruction
@ 2009-09-24 12:41 Mohamed Shafi
  2009-09-24 14:26 ` Paolo Bonzini
  2009-09-24 16:28 ` Richard Henderson
  0 siblings, 2 replies; 3+ messages in thread
From: Mohamed Shafi @ 2009-09-24 12:41 UTC (permalink / raw)
  To: GCC

Hello all,

I am porting a 32bit target in GCC 4.4.0
The target has have distinct signed and unsigned compare instructions,
and only one set of conditional branch instructions. Moreover the
operands cannot be immediate values if the comparison is unsigned. I
have implemented this using compare-and-branch instruction. This gets
split after reload. The pattern that i have written are as follows:

(define_expand "cmp<mode>"
 [(set (reg:CC CC_REGNUM)
       (compare (match_operand:INT 0 "register_operand" "")
                (match_operand:INT 1 "nonmemory_operand" "")))]
 ""
 "
  {
   compare_op0 = operands[0];
   compare_op1 = operands[1];
   DONE;
  }
 "
)


(define_expand "b<code>"
 [(set (reg:CC CC_REGNUM)
       (compare:CC (match_dup 1)
                   (match_dup 2)))
  (set (pc)
       (if_then_else (comp_op:CC (reg:CC CC_REGNUM)(const_int 0))
                     (label_ref (match_operand 0 "" ""))
                     (pc)))]
  ""
  "{
    operands[1] = compare_op0;
    operands[2] = compare_op1;

    if (CONSTANT_P (operands[2])
        && (<CODE> == LTU || <CODE> == GTU || <CODE> == LEU || <CODE> == GEU))
      operands[2] = force_reg (GET_MODE (operands[1]), operands[2]);

    operands[3] = gen_rtx_fmt_ee (<CODE>, CCmode,
                                  gen_rtx_REG (CCmode,CC_REGNUM), const0_rtx);
    emit_jump_insn (gen_compare_and_branch_insn (operands[0], operands[1],
                                                 operands[2], operands[3]));
    DONE;
  }"
)

(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;
  }"
)

In the function "expand_compare_insn" i am asserting that operand[2]
is not a immediate value if the comparison is unsigned. I am getting a
assertion failure in this function. The problem is that reload pass
will replace operand[2]  with its equiv_constant. This breaks the
pattern after reload pass.

Before reload pass

(jump_insn 58 56 59 10 20070129.c:73 (set (pc)
        (if_then_else (leu:CC (reg:QI 84)
                (reg:QI 91))
            (label_ref 87)
            (pc))) 77 {compare_and_branch_insn} (expr_list:REG_DEAD (reg:QI 84)
        (expr_list:REG_BR_PROB (const_int 200 [0xc8])
            (nil))))

After reload pass:

(jump_insn 58 56 59 10 20070129.c:73 (set (pc)
        (if_then_else (leu:CC (reg:QI 17 r1 [84])
                (const_int 1 [0x1]))
            (label_ref 87)
            (pc))) 77 {compare_and_branch_insn} (expr_list:REG_BR_PROB
(const_int 200 [0xc8])
        (nil)))


How can i overcome this error?
Thanks for your help.

Regards,
Shafi

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: How to implement compare and branch instruction
  2009-09-24 12:41 How to implement compare and branch instruction Mohamed Shafi
@ 2009-09-24 14:26 ` Paolo Bonzini
  2009-09-24 16:28 ` Richard Henderson
  1 sibling, 0 replies; 3+ messages in thread
From: Paolo Bonzini @ 2009-09-24 14:26 UTC (permalink / raw)
  To: Mohamed Shafi; +Cc: GCC

On 09/24/2009 02:41 PM, Mohamed Shafi wrote:
> How can i overcome this error?

Remove the guilty alternatives, for example the d/L alternative, and 
make operand 2 a register_operand.

Paolo

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: How to implement compare and branch instruction
  2009-09-24 12:41 How to implement compare and branch instruction Mohamed Shafi
  2009-09-24 14:26 ` Paolo Bonzini
@ 2009-09-24 16:28 ` Richard Henderson
  1 sibling, 0 replies; 3+ messages in thread
From: Richard Henderson @ 2009-09-24 16:28 UTC (permalink / raw)
  To: Mohamed Shafi; +Cc: GCC

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~

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-09-24 16:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-24 12:41 How to implement compare and branch instruction Mohamed Shafi
2009-09-24 14:26 ` Paolo Bonzini
2009-09-24 16:28 ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).