* 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).