[LLVMdev] splitting a branch within a pseudo

Reed Kotler rkotler at mips.com
Wed Feb 20 13:04:30 PST 2013


I looked at this code more carefully and I think it will do for what I 
need and is a fairly clean solution.

It's from Mips I which we deprecated and it also does not have 
conditional moves as is the case with Mips 16.

On 02/17/2013 04:53 PM, Reed Kotler wrote:
> Some stuff did not get pasted in properly.
>
> static MachineBasicBlock* ExpandCondMov(MachineInstr *MI,
> MachineBasicBlock *BB,
>                                          DebugLoc dl,
>                                          const MipsSubtarget *Subtarget,
>                                          const TargetInstrInfo *TII,
>                                          bool isFPCmp, unsigned Opc) {
>    // There is no need to expand CMov instructions if target has
>    // conditional moves.
>    if (Subtarget->hasCondMov())
>      return BB;
>
>    // To "insert" a SELECT_CC instruction, we actually have to insert the
>    // diamond control-flow pattern.  The incoming instruction knows the
>    // destination vreg to set, the condition code register to branch on,
> the
>    // true/false values to select between, and a branch opcode to use.
>    const BasicBlock *LLVM_BB = BB->getBasicBlock();
>    MachineFunction::iterator It = BB;
>    ++It;
>
>    //  thisMBB:
>    //  ...
>    //   TrueVal = ...
>    //   setcc r1, r2, r3
>    //   bNE   r1, r0, copy1MBB
>    //   fallthrough --> copy0MBB
>    MachineBasicBlock *thisMBB  = BB;
>    MachineFunction *F = BB->getParent();
>    MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
>    MachineBasicBlock *sinkMBB  = F->CreateMachineBasicBlock(LLVM_BB);
>    F->insert(It, copy0MBB);
>    F->insert(It, sinkMBB);
>
>    // Transfer the remainder of BB and its successor edges to sinkMBB.
>    sinkMBB->splice(sinkMBB->begin(), BB,
>                    llvm::next(MachineBasicBlock::iterator(MI)),
>                    BB->end());
>    sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
>
>    // Next, add the true and fallthrough blocks as its successors.
>    BB->addSuccessor(copy0MBB);
>    BB->addSuccessor(sinkMBB);
>
>    // Emit the right instruction according to the type of the operands
> compared
>    if (isFPCmp)
>      BuildMI(BB, dl, TII->get(Opc)).addMBB(sinkMBB);
>    else
>      BuildMI(BB, dl, TII->get(Opc)).addReg(MI->getOperand(2).getReg())
>        .addReg(Mips::ZERO).addMBB(sinkMBB);
>
>    //  copy0MBB:
>    //   %FalseValue = ...
>    //   # fallthrough to sinkMBB
>    BB = copy0MBB;
>
>    // Update machine-CFG edges
>    BB->addSuccessor(sinkMBB);
>
>    //  sinkMBB:
>    //   %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
>    //  ...
>    BB = sinkMBB;
>
>    if (isFPCmp)
>      BuildMI(*BB, BB->begin(), dl,
>              TII->get(Mips::PHI), MI->getOperand(0).getReg())
>        .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB)
>        .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB);
>    else
>      BuildMI(*BB, BB->begin(), dl,
>              TII->get(Mips::PHI), MI->getOperand(0).getReg())
>        .addReg(MI->getOperand(3).getReg()).addMBB(thisMBB)
>        .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB);
>
>    MI->eraseFromParent();   // The pseudo instruction is gone now.
>    return BB;
> }
> On 02/17/2013 04:45 PM, Reed Kotler wrote:
>> This is the old MIPS I code that sort of does what I need to do. This
>> seems really involved to do such a simple thing.
>>
>> Maybe there are now helper classes for this or some better example I can
>> look at. I suppose I can mimick this if people say this just the correct
>> way to do this in LLVM.
>>
>> static MachineBasicBlock* ExpandCondMov(MachineInstr *MI,
>> MachineBasicBlock *BB,
>>                                          DebugLoc dl,
>>                                          const MipsSubtarget *Subtarget,
>>                                          const TargetInstrInfo *TII,
>>                                          bool isFPCmp, unsigned Opc) {
>>    // There is no need to expand CMov instructions if target has
>>    // conditional moves.
>>    if (Subtarget->hasCondMov())
>>      return BB;
>>
>>    // To "insert" a SELECT_CC instruction, we actually have to insert the
>>    // diamond control-flow pattern.  The incoming instruction knows the
>>    // destination vreg to set, the condition code register to branch on,
>> the
>>    // true/false values to select between, and a branch opcode to use.
>>    const BasicBlock *LLVM_BB = BB->getBasicBlock();
>>    MachineFunction::iterator It = BB;
>>    ++It;
>>
>>    //  thisMBB:
>>    //  ...
>>    //   TrueVal = ...
>>    //   setcc r1, r2, r3
>>    //   bNE   r1, r0, copy1MBB
>>    //   fallthrough --> copy0MBB
>>    MachineBasicBlock *thisMBB  = BB;
>>    MachineFunction *F = BB->getParent();
>>    MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
>>    MachineBasicBlock *sinkMBB  = F->CreateMachineBasicBlock(LLVM_BB);
>>    F->insert(It, copy0MBB);
>>    F->insert(It, sinkMBB);
>>
>>    // Transfer the remainder of BB and its successor edges to sinkMBB.
>>    sinkMBB->splice(sinkMBB->begin(), BB,
>>                    llvm::next(MachineBasicBlock::iterator(MI)),
>>                    BB->end());
>>    sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
>>
>>    // Next, add the true and fallthrough blocks as its successors.
>>    BB->addSuccessor(copy0MBB);
>>    BB->a
>> On 02/17/2013 12:51 PM, Reed Kotler wrote:
>>> After discussions last night, I'm leaning towards going legit with all
>>> my pseudo expansions in Mips 16.
>>>
>>> Some I think I can clearly do by just putting in the proper side effects
>>> of implicit registers (T8 the condition code register as used by mips
>>> 16).
>>>
>>> But I'm still left with some pseudos that have jmp .+4 type instructions
>>> in them.
>>>
>>> The original Mips port was to Mips I and Mips I, like Mips 16, has no
>>> conditional store instructions.
>>>
>>> There was some super ugly code there to do a test and then branch around
>>> the store instruction if the test was not matched. It was quite a large
>>> amount of code and I'm not sure I even believe it works. It's long been
>>> commented out since we don't even support Mips I anymore.
>>>
>>> I avoided that in Mips 16 by writing some patterns that translate to
>>> something like:
>>>
>>> cmp rx, ry  ; implicitly set T8
>>> btnez foo:  ; branch if T8 not zero
>>> mov ra, rb
>>> foo:....
>>>
>>> There is a way to do this in Mips asembler without needing to really
>>> create a label. There are builtin forward and backward labels you can
>>> use for this and that's what I do in some cases and in other cases I
>>> think I just do a .+4 or something.
>>>
>>> SOmething like that. You can see the mips 16 patterns if you want to
>>> know the details but they are not important here IMO.
>>>
>>> In principle I should really make machine basic blocks and do all that
>>> book keeping but at least the original way is way too complicated and as
>>> I said, I'm not sure I believe it even works in all cases. Too many
>>> complex assumptions about the optimizer and such.
>>>
>>> Any ideas or code pointers for creating the kind of machine basic blocks
>>> I would need to do the above without resorting to bundles?
>>>
>>> I like simple.
>>>
>>> Simple usually works always and complex always has at least one more
>>> bug. :)
>>>
>>> Tia.
>>>
>>> Reed





More information about the llvm-dev mailing list