#include "MipsAnalyzeImmediate.h"
#include "MipsInstrInfo.h"
#include "MipsTargetMachine.h"
#include "MipsMachineFunction.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/ADT/STLExtras.h"
#define GET_INSTRINFO_CTOR
#include "MipsGenInstrInfo.inc"
using namespace llvm;
MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm, unsigned UncondBr)
: MipsGenInstrInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP),
TM(tm), UncondBrOpc(UncondBr) {}
const MipsInstrInfo *MipsInstrInfo::create(MipsTargetMachine &TM) {
if (TM.getSubtargetImpl()->inMips16Mode())
return llvm::createMips16InstrInfo(TM);
return llvm::createMipsSEInstrInfo(TM);
}
bool MipsInstrInfo::isZeroImm(const MachineOperand &op) const {
return op.isImm() && op.getImm() == 0;
}
void MipsInstrInfo::
insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const
{
DebugLoc DL;
BuildMI(MBB, MI, DL, get(Mips::NOP));
}
MachineMemOperand *MipsInstrInfo::GetMemOperand(MachineBasicBlock &MBB, int FI,
unsigned Flag) const {
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = *MF.getFrameInfo();
unsigned Align = MFI.getObjectAlignment(FI);
return MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FI), Flag,
MFI.getObjectSize(FI), Align);
}
MachineInstr*
MipsInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx,
uint64_t Offset, const MDNode *MDPtr,
DebugLoc DL) const {
MachineInstrBuilder MIB = BuildMI(MF, DL, get(Mips::DBG_VALUE))
.addFrameIndex(FrameIx).addImm(0).addImm(Offset).addMetadata(MDPtr);
return &*MIB;
}
void MipsInstrInfo::AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc,
MachineBasicBlock *&BB,
SmallVectorImpl<MachineOperand> &Cond) const {
assert(GetAnalyzableBrOpc(Opc) && "Not an analyzable branch");
int NumOp = Inst->getNumExplicitOperands();
BB = Inst->getOperand(NumOp-1).getMBB();
Cond.push_back(MachineOperand::CreateImm(Opc));
for (int i=0; i<NumOp-1; i++)
Cond.push_back(Inst->getOperand(i));
}
bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
bool AllowModify) const
{
MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend();
while (I != REnd && I->isDebugValue())
++I;
if (I == REnd || !isUnpredicatedTerminator(&*I)) {
TBB = FBB = NULL;
return false;
}
MachineInstr *LastInst = &*I;
unsigned LastOpc = LastInst->getOpcode();
if (!GetAnalyzableBrOpc(LastOpc))
return true;
unsigned SecondLastOpc = 0;
MachineInstr *SecondLastInst = NULL;
if (++I != REnd) {
SecondLastInst = &*I;
SecondLastOpc = GetAnalyzableBrOpc(SecondLastInst->getOpcode());
if (isUnpredicatedTerminator(SecondLastInst) && !SecondLastOpc)
return true;
}
if (!SecondLastOpc) {
if (LastOpc == UncondBrOpc) {
TBB = LastInst->getOperand(0).getMBB();
return false;
}
AnalyzeCondBr(LastInst, LastOpc, TBB, Cond);
return false;
}
if (++I != REnd && isUnpredicatedTerminator(&*I))
return true;
if (SecondLastOpc == UncondBrOpc) {
if (!AllowModify)
return true;
TBB = SecondLastInst->getOperand(0).getMBB();
LastInst->eraseFromParent();
return false;
}
if (LastOpc != UncondBrOpc)
return true;
AnalyzeCondBr(SecondLastInst, SecondLastOpc, TBB, Cond);
FBB = LastInst->getOperand(0).getMBB();
return false;
}
void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB,
MachineBasicBlock *TBB, DebugLoc DL,
const SmallVectorImpl<MachineOperand>& Cond)
const {
unsigned Opc = Cond[0].getImm();
const MCInstrDesc &MCID = get(Opc);
MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID);
for (unsigned i = 1; i < Cond.size(); ++i) {
if (Cond[i].isReg())
MIB.addReg(Cond[i].getReg());
else if (Cond[i].isImm())
MIB.addImm(Cond[i].getImm());
else
assert(true && "Cannot copy operand");
}
MIB.addMBB(TBB);
}
unsigned MipsInstrInfo::
InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
const SmallVectorImpl<MachineOperand> &Cond,
DebugLoc DL) const {
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
assert((Cond.size() <= 3) &&
"# of Mips branch conditions must be <= 3!");
if (FBB) {
BuildCondBr(MBB, TBB, DL, Cond);
BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(FBB);
return 2;
}
if (Cond.empty())
BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(TBB);
else BuildCondBr(MBB, TBB, DL, Cond);
return 1;
}
unsigned MipsInstrInfo::
RemoveBranch(MachineBasicBlock &MBB) const
{
MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend();
MachineBasicBlock::reverse_iterator FirstBr;
unsigned removed;
while (I != REnd && I->isDebugValue())
++I;
FirstBr = I;
for(removed = 0; I != REnd && removed < 2; ++I, ++removed)
if (!GetAnalyzableBrOpc(I->getOpcode()))
break;
MBB.erase(I.base(), FirstBr.base());
return removed;
}
bool MipsInstrInfo::
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const
{
assert( (Cond.size() && Cond.size() <= 3) &&
"Invalid Mips branch condition!");
Cond[0].setImm(GetOppositeBranchOpc(Cond[0].getImm()));
return false;
}
unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
switch (MI->getOpcode()) {
default:
return MI->getDesc().getSize();
case TargetOpcode::INLINEASM: { const MachineFunction *MF = MI->getParent()->getParent();
const char *AsmStr = MI->getOperand(0).getSymbolName();
return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
}
}
}