This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

How to implement compare and branch instruction


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]