diff options
Diffstat (limited to 'lib/Target/Mips/MipsInstrInfo.cpp')
-rw-r--r-- | lib/Target/Mips/MipsInstrInfo.cpp | 236 |
1 files changed, 208 insertions, 28 deletions
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index b1d69506c16f2..800d834e0ab8e 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -13,7 +13,6 @@ #include "MipsInstrInfo.h" #include "InstPrinter/MipsInstPrinter.h" -#include "MipsAnalyzeImmediate.h" #include "MipsMachineFunction.h" #include "MipsSubtarget.h" #include "llvm/ADT/STLExtras.h" @@ -47,6 +46,7 @@ bool MipsInstrInfo::isZeroImm(const MachineOperand &op) const { /// insertNoop - If data hazard condition is found insert the target nop /// instruction. +// FIXME: This appears to be dead code. void MipsInstrInfo:: insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const { @@ -54,14 +54,15 @@ insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const BuildMI(MBB, MI, DL, get(Mips::NOP)); } -MachineMemOperand *MipsInstrInfo::GetMemOperand(MachineBasicBlock &MBB, int FI, - unsigned Flag) const { +MachineMemOperand * +MipsInstrInfo::GetMemOperand(MachineBasicBlock &MBB, int FI, + MachineMemOperand::Flags Flags) const { MachineFunction &MF = *MBB.getParent(); MachineFrameInfo &MFI = *MF.getFrameInfo(); unsigned Align = MFI.getObjectAlignment(FI); return MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI), - Flag, MFI.getObjectSize(FI), Align); + Flags, MFI.getObjectSize(FI), Align); } //===----------------------------------------------------------------------===// @@ -83,20 +84,20 @@ void MipsInstrInfo::AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, Cond.push_back(Inst->getOperand(i)); } -bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, +bool MipsInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { SmallVector<MachineInstr*, 2> BranchInstrs; - BranchType BT = AnalyzeBranch(MBB, TBB, FBB, Cond, AllowModify, BranchInstrs); + BranchType BT = analyzeBranch(MBB, TBB, FBB, Cond, AllowModify, BranchInstrs); return (BT == BT_None) || (BT == BT_Indirect); } -void -MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, - DebugLoc DL, ArrayRef<MachineOperand> Cond) const { +void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + const DebugLoc &DL, + ArrayRef<MachineOperand> Cond) const { unsigned Opc = Cond[0].getImm(); const MCInstrDesc &MCID = get(Opc); MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID); @@ -107,14 +108,16 @@ MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, else if (Cond[i].isImm()) MIB.addImm(Cond[i].getImm()); else - assert(true && "Cannot copy operand"); + assert(false && "Cannot copy operand"); } MIB.addMBB(TBB); } -unsigned MipsInstrInfo::InsertBranch( - MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, - ArrayRef<MachineOperand> Cond, DebugLoc DL) const { +unsigned MipsInstrInfo::InsertBranch(MachineBasicBlock &MBB, + MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + ArrayRef<MachineOperand> Cond, + const DebugLoc &DL) const { // Shouldn't be a fall through. assert(TBB && "InsertBranch must not be told to insert a fallthrough"); @@ -174,7 +177,7 @@ bool MipsInstrInfo::ReverseBranchCondition( return false; } -MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( +MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch( MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify, SmallVectorImpl<MachineInstr *> &BranchInstrs) const { @@ -185,7 +188,7 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( while (I != REnd && I->isDebugValue()) ++I; - if (I == REnd || !isUnpredicatedTerminator(&*I)) { + if (I == REnd || !isUnpredicatedTerminator(*I)) { // This block ends with no branches (it just falls through to its succ). // Leave TBB/FBB null. TBB = FBB = nullptr; @@ -209,14 +212,14 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( SecondLastOpc = getAnalyzableBrOpc(SecondLastInst->getOpcode()); // Not an analyzable branch (must be an indirect jump). - if (isUnpredicatedTerminator(SecondLastInst) && !SecondLastOpc) + if (isUnpredicatedTerminator(*SecondLastInst) && !SecondLastOpc) return BT_None; } // If there is only one terminator instruction, process it. if (!SecondLastOpc) { // Unconditional branch. - if (LastOpc == UncondBrOpc) { + if (LastInst->isUnconditionalBranch()) { TBB = LastInst->getOperand(0).getMBB(); return BT_Uncond; } @@ -228,14 +231,14 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( // If we reached here, there are two branches. // If there are three terminators, we don't know what sort of block this is. - if (++I != REnd && isUnpredicatedTerminator(&*I)) + if (++I != REnd && isUnpredicatedTerminator(*I)) return BT_None; BranchInstrs.insert(BranchInstrs.begin(), SecondLastInst); // If second to last instruction is an unconditional branch, // analyze it and remove the last instruction. - if (SecondLastOpc == UncondBrOpc) { + if (SecondLastInst->isUnconditionalBranch()) { // Return if the last instruction cannot be removed. if (!AllowModify) return BT_None; @@ -248,7 +251,7 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( // Conditional branch followed by an unconditional branch. // The last one must be unconditional. - if (LastOpc != UncondBrOpc) + if (!LastInst->isUnconditionalBranch()) return BT_None; AnalyzeCondBr(SecondLastInst, SecondLastOpc, TBB, Cond); @@ -257,20 +260,137 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( return BT_CondUncond; } +/// Return the corresponding compact (no delay slot) form of a branch. +unsigned MipsInstrInfo::getEquivalentCompactForm( + const MachineBasicBlock::iterator I) const { + unsigned Opcode = I->getOpcode(); + bool canUseShortMicroMipsCTI = false; + + if (Subtarget.inMicroMipsMode()) { + switch (Opcode) { + case Mips::BNE: + case Mips::BEQ: + // microMIPS has NE,EQ branches that do not have delay slots provided one + // of the operands is zero. + if (I->getOperand(1).getReg() == Subtarget.getABI().GetZeroReg()) + canUseShortMicroMipsCTI = true; + break; + // For microMIPS the PseudoReturn and PseudoIndirectBranch are always + // expanded to JR_MM, so they can be replaced with JRC16_MM. + case Mips::JR: + case Mips::PseudoReturn: + case Mips::PseudoIndirectBranch: + canUseShortMicroMipsCTI = true; + break; + } + } + + // MIPSR6 forbids both operands being the zero register. + if (Subtarget.hasMips32r6() && (I->getNumOperands() > 1) && + (I->getOperand(0).isReg() && + (I->getOperand(0).getReg() == Mips::ZERO || + I->getOperand(0).getReg() == Mips::ZERO_64)) && + (I->getOperand(1).isReg() && + (I->getOperand(1).getReg() == Mips::ZERO || + I->getOperand(1).getReg() == Mips::ZERO_64))) + return 0; + + if (Subtarget.hasMips32r6() || canUseShortMicroMipsCTI) { + switch (Opcode) { + case Mips::B: + return Mips::BC; + case Mips::BAL: + return Mips::BALC; + case Mips::BEQ: + if (canUseShortMicroMipsCTI) + return Mips::BEQZC_MM; + else if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BEQC; + case Mips::BNE: + if (canUseShortMicroMipsCTI) + return Mips::BNEZC_MM; + else if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BNEC; + case Mips::BGE: + if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BGEC; + case Mips::BGEU: + if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BGEUC; + case Mips::BGEZ: + return Mips::BGEZC; + case Mips::BGTZ: + return Mips::BGTZC; + case Mips::BLEZ: + return Mips::BLEZC; + case Mips::BLT: + if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BLTC; + case Mips::BLTU: + if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BLTUC; + case Mips::BLTZ: + return Mips::BLTZC; + // For MIPSR6, the instruction 'jic' can be used for these cases. Some + // tools will accept 'jrc reg' as an alias for 'jic 0, $reg'. + case Mips::JR: + case Mips::PseudoReturn: + case Mips::PseudoIndirectBranch: + if (canUseShortMicroMipsCTI) + return Mips::JRC16_MM; + return Mips::JIC; + case Mips::JALRPseudo: + return Mips::JIALC; + case Mips::JR64: + case Mips::PseudoReturn64: + case Mips::PseudoIndirectBranch64: + return Mips::JIC64; + case Mips::JALR64Pseudo: + return Mips::JIALC64; + default: + return 0; + } + } + + return 0; +} + +/// Predicate for distingushing between control transfer instructions and all +/// other instructions for handling forbidden slots. Consider inline assembly +/// as unsafe as well. +bool MipsInstrInfo::SafeInForbiddenSlot(const MachineInstr &MI) const { + if (MI.isInlineAsm()) + return false; + + return (MI.getDesc().TSFlags & MipsII::IsCTI) == 0; + +} + +/// Predicate for distingushing instructions that have forbidden slots. +bool MipsInstrInfo::HasForbiddenSlot(const MachineInstr &MI) const { + return (MI.getDesc().TSFlags & MipsII::HasForbiddenSlot) != 0; +} + /// Return the number of bytes of code the specified instruction may be. -unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { - switch (MI->getOpcode()) { +unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr &MI) const { + switch (MI.getOpcode()) { default: - return MI->getDesc().getSize(); + return MI.getDesc().getSize(); case TargetOpcode::INLINEASM: { // Inline Asm: Variable size. - const MachineFunction *MF = MI->getParent()->getParent(); - const char *AsmStr = MI->getOperand(0).getSymbolName(); + const MachineFunction *MF = MI.getParent()->getParent(); + const char *AsmStr = MI.getOperand(0).getSymbolName(); return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); } case Mips::CONSTPOOL_ENTRY: // If this machine instr is a constant pool entry, its size is recorded as // operand #2. - return MI->getOperand(2).getImm(); + return MI.getOperand(2).getImm(); } } @@ -278,10 +398,70 @@ MachineInstrBuilder MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, MachineBasicBlock::iterator I) const { MachineInstrBuilder MIB; + + // Certain branches have two forms: e.g beq $1, $zero, dst vs beqz $1, dest + // Pick the zero form of the branch for readable assembly and for greater + // branch distance in non-microMIPS mode. + // FIXME: Certain atomic sequences on mips64 generate 32bit references to + // Mips::ZERO, which is incorrect. This test should be updated to use + // Subtarget.getABI().GetZeroReg() when those atomic sequences and others + // are fixed. + bool BranchWithZeroOperand = + (I->isBranch() && !I->isPseudo() && I->getOperand(1).isReg() && + (I->getOperand(1).getReg() == Mips::ZERO || + I->getOperand(1).getReg() == Mips::ZERO_64)); + + if (BranchWithZeroOperand) { + switch (NewOpc) { + case Mips::BEQC: + NewOpc = Mips::BEQZC; + break; + case Mips::BNEC: + NewOpc = Mips::BNEZC; + break; + case Mips::BGEC: + NewOpc = Mips::BGEZC; + break; + case Mips::BLTC: + NewOpc = Mips::BLTZC; + break; + } + } + MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc)); - for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) - MIB.addOperand(I->getOperand(J)); + // For MIPSR6 JI*C requires an immediate 0 as an operand, JIALC(64) an + // immediate 0 as an operand and requires the removal of it's %RA<imp-def> + // implicit operand as copying the implicit operations of the instructio we're + // looking at will give us the correct flags. + if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 || + NewOpc == Mips::JIALC64) { + + if (NewOpc == Mips::JIALC || NewOpc == Mips::JIALC64) + MIB->RemoveOperand(0); + + for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { + MIB.addOperand(I->getOperand(J)); + } + + MIB.addImm(0); + + } else if (BranchWithZeroOperand) { + // For MIPSR6 and microMIPS branches with an explicit zero operand, copy + // everything after the zero. + MIB.addOperand(I->getOperand(0)); + + for (unsigned J = 2, E = I->getDesc().getNumOperands(); J < E; ++J) { + MIB.addOperand(I->getOperand(J)); + } + } else { + // All other cases copy all other operands. + for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { + MIB.addOperand(I->getOperand(J)); + } + } + + MIB.copyImplicitOps(*I); MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end()); return MIB; |