private:
bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
+ Iter replaceWithCompactBranch(MachineBasicBlock &MBB,
+ Iter Branch, DebugLoc DL);
+
/// This function checks if it is valid to move Candidate to the delay slot
/// and returns true if it isn't. It also updates memory and register
/// dependence information.
return true;
}
+// Replace Branch with the compact branch instruction.
+Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB,
+ Iter Branch, DebugLoc DL) {
+ const MipsInstrInfo *TII= static_cast<const MipsInstrInfo *>(
+ TM.getSubtargetImpl()->getInstrInfo());
+
+ unsigned NewOpcode =
+ (((unsigned) Branch->getOpcode()) == Mips::BEQ) ? Mips::BEQZC_MM
+ : Mips::BNEZC_MM;
+
+ const MCInstrDesc &NewDesc = TII->get(NewOpcode);
+ MachineInstrBuilder MIB = BuildMI(MBB, Branch, DL, NewDesc);
+
+ MIB.addReg(Branch->getOperand(0).getReg());
+ MIB.addMBB(Branch->getOperand(2).getMBB());
+
+ Iter tmpIter = Branch;
+ Branch = std::prev(Branch);
+ MBB.erase(tmpIter);
+
+ return Branch;
+}
+
/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
/// We assume there is only one delay slot per delayed instruction.
bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
}
}
- // Bundle the NOP to the instruction with the delay slot.
- const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>(
- TM.getSubtargetImpl()->getInstrInfo());
- BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP));
- MIBundleBuilder(MBB, I, std::next(I, 2));
+ // If instruction is BEQ or BNE with one ZERO register, then instead of
+ // adding NOP replace this instruction with the corresponding compact
+ // branch instruction, i.e. BEQZC or BNEZC.
+ unsigned Opcode = I->getOpcode();
+ if (InMicroMipsMode &&
+ (Opcode == Mips::BEQ || Opcode == Mips::BNE) &&
+ ((unsigned) I->getOperand(1).getReg()) == Mips::ZERO) {
+
+ I = replaceWithCompactBranch(MBB, I, I->getDebugLoc());
+
+ } else {
+ // Bundle the NOP to the instruction with the delay slot.
+ const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>(
+ TM.getSubtargetImpl()->getInstrInfo());
+ BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP));
+ MIBundleBuilder(MBB, I, std::next(I, 2));
+ }
}
return Changed;
MIB.addMBB(MBBOpnd);
- // Bundle the instruction in the delay slot to the newly created branch
- // and erase the original branch.
- assert(Br->isBundledWithSucc());
- MachineBasicBlock::instr_iterator II(Br);
- MIBundleBuilder(&*MIB).append((++II)->removeFromBundle());
+ if (Br->hasDelaySlot()) {
+ // Bundle the instruction in the delay slot to the newly created branch
+ // and erase the original branch.
+ assert(Br->isBundledWithSucc());
+ MachineBasicBlock::instr_iterator II(Br);
+ MIBundleBuilder(&*MIB).append((++II)->removeFromBundle());
+ }
Br->eraseFromParent();
}
case Mips::BLEZ64: return Mips::BGTZ64;
case Mips::BC1T: return Mips::BC1F;
case Mips::BC1F: return Mips::BC1T;
+ case Mips::BEQZC_MM: return Mips::BNEZC_MM;
+ case Mips::BNEZC_MM: return Mips::BEQZC_MM;
}
}
Opc == Mips::BEQ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 ||
Opc == Mips::BGEZ64 || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 ||
Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::B ||
- Opc == Mips::J) ?
+ Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM) ?
Opc : 0;
}
--- /dev/null
+; RUN: llc %s -march=mipsel -mattr=micromips -filetype=asm -O3 \
+; RUN: -disable-mips-delay-filler -relocation-model=pic -o - | FileCheck %s
+
+define void @main() nounwind uwtable {
+entry:
+ %x = alloca i32, align 4
+ %0 = load i32* %x, align 4
+ %cmp = icmp eq i32 %0, 0
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+ store i32 10, i32* %x, align 4
+ br label %if.end
+
+if.end:
+ ret void
+}
+
+; CHECK: bnezc