This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Condition branch on least significant bit
- From: Michael Meissner <gcc-mail at the-meissners dot org>
- To: gcc at gcc dot gnu dot org
- Date: Fri, 20 Jun 2003 11:59:43 -0400
- Subject: Re: Condition branch on least significant bit
- References: <Law9-F42A6aEdHyCUV90000ee37@hotmail.com>
On Fri, Jun 20, 2003 at 04:18:38PM +0200, Jan Hoogerbrugge wrote:
> Hi,
>
> Our target architecture, to which we are porting gcc, has the compare
> instructions which produce a boolean and conditional jump instructions
> which test the boolean and jump if the boolean is true. For code
> generation I:
>
> - wrote a `define_expand "cmpsi"' the collects the operands
> - wrote a `define_expand "beq"' that generates
>
> tmp = operand1 relop operand2
> pc = (tmp != 0) ? label_ref : pc
>
> - wrote a pattern that matches the conditional jump
>
> (define_insn "branch_true"
> [(set (pc) (if_then_else
> (ne (match_operand:SI 1 "register_operand"
> "r")
> (const_int 0))
> (label_ref (match_operand 0 "" ""))
> (pc)))]
> ""
> "cjump %1 %0")
>
> The problem that we are facing is that the semantics of the cjump
> instruction
> does not corresponds to the semantics of the RTL pattern. The problem is
> that
> our cjump instruction does not test whether its first operand is zero or
> non-zero. Instead it tests whether the least-significant bit of the first
> operand is zero or one. With the code above, gcc translates
>
> if(x != 0)
> goto label
>
> to
>
> cjump x, label
>
> while it should be
>
> equal x, 0 -> tmp
> cjump tmp, label
>
> My question is how to achieve this? I changed the RTL pattern of the
> branch_true define_insn into:
>
> pc = (tmp & 1) != 0 ? label_ref : pc /* change pc if LSB == 1 */
>
> and changed the `define_expand "beq"' accordingly so that RTL template
> and the output template of branch_true correspond. However this does not
> work. The compiler can't match the code generated by `define_expand "beq"'.
> It seems that the `& 1' is optimised away and therefore branch_true will
> not be matched.
>
> Any idea how to deal with this problem?
My inclination would be to use the mode CCmode or BImode (probably BImode).
Since BImode is a type that holds 1 bit, it shouldn't matter whether the other
bits are 0 or 1. Since the type that cjmp operates on is not SImode, the
optimizer won't fold the (x != 0) into the test.
So the RTL generated would look something like:
(set (reg:BI tmp)
(eq:BI (reg:SI operand1)
(reg:SI operand2)))
(set (pc)
(if_then_else (ne:BI (reg:BI tmp)
(const_int 0))
(label_ref ...)
(pc)))
or
(set (reg:CC tmp)
(eq:CC (reg:SI operand1)
(reg:SI operand2)))
(set (pc)
(if_then_else (ne:CC (reg:BI tmp)
(const_int 0))
(label_ref ...)
(pc)))
Note, historically CCmode originally meant it had all of the comparison flags
(less than, equal, greater than, unsigned less than, unsigned greater than),
and I've had some challenges mapping that to machines that only have equal,
less than, and unsigned less than operations (this was before BI got added).
--
Michael Meissner
email: gnu@the-meissners.org
http://www.the-meissners.org