On Fri, May 22, 2009 at 05:04:22PM -0700, Jamie Prescott wrote: > > > From: Jamie Prescott <jpre...@yahoo.com> > > To: gcc@gcc.gnu.org > > 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 meiss...@linux.vnet.ibm.com