On Fri, May 22, 2009 at 05:04:22PM -0700, Jamie Prescott wrote:
>
> > From: Jamie Prescott <[email protected]>
> > To: [email protected]
> > Sent: Friday, May 22, 2009 10:36:47 AM
> > Subject: Seeking suggestion
> >
> >
> > Suppose you're writing the backend for a VM supporting two architectures,
> > in
> > which
> > one of them clobbers the CC registers for certain instructions, while the
> > other
> > does not.
> > The instructions themselves are exactly the same.
> > What is the best/shortest/more-elegant way to write this, possibly w/out
> > duplicating the
> > instructions?
> > I know I can write a define_expand and redirect, based on the TARGET, to
> > two
> > different
> > instructions (one with "clobber", the other w/out), but that's basically
> > three
> > declarations
> > for each insns. Is there a shorter way?
>
> I ended up doing something like this (long way, but the only one I know of).
> Example, for addsi3:
>
> (define_insn "addsi3_xxx2"
> [(set (match_operand:SI 0 "fullreg_operand" "=r,r")
> (plus:SI (match_operand:SI 1 "fullreg_operand" "0,r")
> (match_operand:SI 2 "fullreg_or_imm_operand" "rn,rn")))]
> ""
> "@
> add\t%0,%2,%0
> add\t%1,%2,%0"
> )
>
> (define_insn "addsi3_xxx"
> [(set (match_operand:SI 0 "fullreg_operand" "=r,r")
> (plus:SI (match_operand:SI 1 "fullreg_operand" "0,r")
> (match_operand:SI 2 "fullreg_or_imm_operand" "rn,rn")))
> (clobber (reg:CC CC_REG))]
> ""
> "@
> add\t%0,%2,%0
> add\t%1,%2,%0"
> )
>
> (define_expand "addsi3"
> [(set (match_operand:SI 0 "fullreg_operand" "=r,r")
> (plus:SI (match_operand:SI 1 "fullreg_operand" "0,r")
> (match_operand:SI 2 "fullreg_or_imm_operand" "rn,rn")))]
> ""
> {
> if (!TARGET_XXX2)
> emit_insn(gen_addsi3_xxx(operands[0], operands[1], operands[2]));
> else
> emit_insn(gen_addsi3_xxx2(operands[0], operands[1], operands[2]));
> DONE;
> }
> )
One way is to use match_scratch, and different register classes for the two
cases.
(define_insn "add<mode>3"
[(set (match_operand:SI 0 "register_operand" "=x,y")
(plus:SI (match_operand:SI 1 "register_operand" "%x,y")
(match_operand:SI 2 "register_operand" "x,y")))
(clobber (match_scratch:CC 3 "=X,z"))]
""
"add %0,%1,%2")
(define_register_constraint "x" "TARGET_MACHINE ? GENERAL_REGS : NO_REGS"
"@internal")
(define_register_constraint "y" "!TARGET_MACHINE ? GENERAL_REGS : NO_REGS"
"@internal")
(define_register_constraint "z" CR_REGS "@interal")
This assumes you have a register class for the condition code register. Most
machines however, use the normal define_expand with two different insns.
In theory, you could define a second condition code register that doesn't
actually exist in the machine, and change the clobber from the main CC to the
fake one.
> But now I get and invalid rtx sharing from the push/pop parallels:
>
>
> xxxx.c: In function 'test_dashr':
> xxxx.c:32: error: invalid rtl sharing found in the insn
> (insn 26 3 28 2 xxxx.c:26 (parallel [
> (insn/f 25 0 0 (set (reg/f:SI 51 SP)
> (minus:SI (reg/f:SI 51 SP)
> (const_int 4 [0x4]))) -1 (nil))
> (set/f (mem:SI (reg/f:SI 51 SP) [0 S4 A8])
> (reg:SI 8 r8))
> ]) -1 (nil))
> xxxx.c:32: error: shared rtx
> (insn/f 25 0 0 (set (reg/f:SI 51 SP)
> (minus:SI (reg/f:SI 51 SP)
> (const_int 4 [0x4]))) -1 (nil))
> xxxx.c:32: internal compiler error: internal consistency failure
I suspect you don't have the proper guards on the push/pop insns, and the
combiner is eliminating the clobber. You probably need to have parallel insns
for the push and pop.
--
Michael Meissner, IBM
4 Technology Place Drive, MS 2203A, Westford, MA, 01886, USA
[email protected]