Vincent Lejeune
2012-Aug-06 17:29 UTC
[LLVMdev] Register Coalescer does not preserve TargetFlag
Hi, R600 hardware (Radeon gfx card) does neither have a NEG nor an ABS instruction ; however any sources operand can be negated/abs'd by setting a bit for every source operand in the final bytecode (but not DST). A good way of modeling this behavior in LLVM is by using TargetFlag on operand. Currently the R600 LLVM backend in Mesa lower NEG and ABS DAG instruction to a MOV + TargetFlag using customEmitter pass. This emulates the existence of a NEG/ABS instruction, but is not optimal as it costs an extra (often uneeded) MOV instruction. I'm trying to rework this : I'd like that a "DST = FNEG SRC" custom Emitter lowering pass replaces every occurence of DST by SRC and set the corresponding TargetFlag in the process. Something like this : MachineOperand *MO = &(MI->getOperand(0)); while(MO) { MachineOperand *next_MO = MO->getNextOperandForReg(); MO->addTargetFlag(MO_FLAG_NEG); MO->setReg(MI->getOperand(1).getReg()); MO = next_MO; } As far as I can tell, this works as every register are still virtual when lowering custom Emitter instructions. However the RegisterCoalescer pass does not preserve TargetFlag in the JoinCopy() member function. For instance, here is some output of the regalloc pass (TF=2 corresponds to a Neg TargetFlag) : 352B %vreg20:sel_x<def,undef> = COPY %vreg16<kill>[TF=2], %vreg20<imp-def>; R600_Reg128:%vreg20 R600_Reg32:%vreg16 Considering merging %vreg16 with %vreg20:sel_x Cross-class to R600_Reg128. RHS = %vreg16 = [304r,352r:0) 0 at 304r LHS = %vreg20 = [352r,400r:0) 0 at 352r updated: 304B %vreg20:sel_x<def,undef> = MUL %vreg3:sel_x<kill>, %vreg15; R600_Reg128:%vreg20,%vreg3 R600_Reg32:%vreg15 Joined. Result = %vreg20 = [304r,400r:0) 0 at 304r I'd like to prevent this specific join from occuring, because DST register cannot be negated. Is there a way to control the JoinCopy function from RegisterCoalescer ? Or is there any way to do that otherwise ? Regards, Vincent Lejeune.
Jakob Stoklund Olesen
2012-Aug-06 17:36 UTC
[LLVMdev] Register Coalescer does not preserve TargetFlag
On Aug 6, 2012, at 10:29 AM, Vincent Lejeune <vljn at ovi.com> wrote:> > > Hi, > > R600 hardware (Radeon gfx card) does neither have a NEG nor an ABS instruction ; however any sources operand can be negated/abs'd by setting a bit for every source operand in the final bytecode (but not DST). > A good way of modeling this behavior in LLVM is by using TargetFlag on operand.Hi Vincent, TargetFlags are not a good way of modeling semantic information about machine instructions. They are not preserved by any passes in the backend. Use immediate operands instead. /jakob
Jakob Stoklund Olesen
2012-Aug-06 17:51 UTC
[LLVMdev] Register Coalescer does not preserve TargetFlag
On Aug 6, 2012, at 10:45 AM, Vincent Lejeune <vljn at ovi.com> wrote:> Is it possible to "customise" INSERT_SUBREG and COPY instructions to add them an immediate operands ? > I know that COPY is lowered using copyPhysReg() function in MachineTargetInstrInfo, but I'm not sure there is something equivalent for INSERT_SUBREG.No, these instructions must be pure register copies. They can't have additional target-specific semantics. You would need to insert target-specific NEG and ABS instructions instead. /jakob
Jakob Stoklund Olesen
2012-Aug-06 18:06 UTC
[LLVMdev] Register Coalescer does not preserve TargetFlag
On Aug 6, 2012, at 11:00 AM, Vincent Lejeune <vljn at ovi.com> wrote:> Ok. > > I tried to do it using a pass after register allocation, lowering NEG/ABS instructions. > However I met a problem : apparently getNextOperandForReg() can returns a MachineOperand before the one I'm processing. > > The following code snippet : > > > void R600ModifiersPropagation::substituteReg(MachineOperand &def_MO, unsigned new_reg, unsigned char flag) { > MachineOperand * MO = def_MO.getNextOperandForReg(); > while (MO && MO->isUse()) { > MachineOperand *next_MO = MO->getNextOperandForReg(); > MO->dump(); > > MO = next_MO; > } > } > > displays instructions that are before the one I'm passing as def_MO. I'm not sure if I should call some Analysis pass to enforce MachineOperand order or not.We make no guarantees about the order of operands in the use-def chains, and there are no analyses that can reorder them. I would suggest that you read the code in other targets to see how things are usually done. /jakob
Vincent Lejeune
2012-Aug-06 18:12 UTC
[LLVMdev] Register Coalescer does not preserve TargetFlag
Do you know any backend that implement instructions as a flag modifier in instruction ? Thank, Vincent Lejeune ----- Mail original -----> De : Jakob Stoklund Olesen <stoklund at 2pi.dk> > À : Vincent Lejeune <vljn at ovi.com> > Cc : "llvmdev at cs.uiuc.edu (LLVMdev at cs.uiuc.edu)" <llvmdev at cs.uiuc.edu> > Envoyé le : Lundi 6 août 2012 20h06 > Objet : Re: [LLVMdev] Register Coalescer does not preserve TargetFlag > > > On Aug 6, 2012, at 11:00 AM, Vincent Lejeune <vljn at ovi.com> wrote: > >> Ok. >> >> I tried to do it using a pass after register allocation, lowering NEG/ABS > instructions. >> However I met a problem : apparently getNextOperandForReg() can returns a > MachineOperand before the one I'm processing. >> >> The following code snippet : >> >> >> void R600ModifiersPropagation::substituteReg(MachineOperand &def_MO, > unsigned new_reg, unsigned char flag) { >> MachineOperand * MO = def_MO.getNextOperandForReg(); >> while (MO && MO->isUse()) { >> MachineOperand *next_MO = MO->getNextOperandForReg(); >> MO->dump(); >> >> MO = next_MO; >> } >> } >> >> displays instructions that are before the one I'm passing as def_MO. > I'm not sure if I should call some Analysis pass to enforce MachineOperand > order or not. > > We make no guarantees about the order of operands in the use-def chains, and > there are no analyses that can reorder them. > > I would suggest that you read the code in other targets to see how things are > usually done. > > /jakob >
Maybe Matching Threads
- [LLVMdev] Register Coalescer does not preserve TargetFlag
- [LLVMdev] Register Coalescer does not preserve TargetFlag
- [LLVMdev] Register Coalescer does not preserve TargetFlag
- [LLVMdev] Register Coalescer does not preserve TargetFlag
- [LLVMdev] RegisterCoalescing pass crashes with ImplicitDef registers