splitting a branch within a pseudo

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. :slight_smile:

Tia.

Reed

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

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;
}

Reed,

Have a look at custom inserters. In particular, how they're used for atomics in the ARM backend.

-Jim

Reed,

Have a look at custom inserters. In particular, how they're used for atomics in the ARM backend.

-Jim

Nice. I see that we are using them in the Mips backend (probably copied from the Arm backend) but I did not work on that code so never paid attention to what that was about.

I think I can insert my expansions right there and not have to put them into any post isel phases and such.

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.