mirror of
https://github.com/opnsense/src.git
synced 2026-03-30 22:45:13 -04:00
all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: <http://llvm.org/releases/3.4/docs/ReleaseNotes.html> <http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html> MFC after: 1 month
295 lines
9.4 KiB
C++
295 lines
9.4 KiB
C++
//===-- MipsInstrInfo.cpp - Mips Instruction Information ------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains the Mips implementation of the TargetInstrInfo class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MipsInstrInfo.h"
|
|
#include "InstPrinter/MipsInstPrinter.h"
|
|
#include "MipsAnalyzeImmediate.h"
|
|
#include "MipsMachineFunction.h"
|
|
#include "MipsTargetMachine.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
|
|
#define GET_INSTRINFO_CTOR_DTOR
|
|
#include "MipsGenInstrInfo.inc"
|
|
|
|
using namespace llvm;
|
|
|
|
// Pin the vtable to this file.
|
|
void MipsInstrInfo::anchor() {}
|
|
|
|
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;
|
|
}
|
|
|
|
/// insertNoop - If data hazard condition is found insert the target nop
|
|
/// instruction.
|
|
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);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Branch Analysis
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
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();
|
|
|
|
// for both int and fp branches, the last explicit operand is the
|
|
// MBB.
|
|
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 {
|
|
SmallVector<MachineInstr*, 2> 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,
|
|
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 {
|
|
// Shouldn't be a fall through.
|
|
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
|
|
|
|
// # of condition operands:
|
|
// Unconditional branches: 0
|
|
// Floating point branches: 1 (opc)
|
|
// Int BranchZero: 2 (opc, reg)
|
|
// Int Branch: 3 (opc, reg0, reg1)
|
|
assert((Cond.size() <= 3) &&
|
|
"# of Mips branch conditions must be <= 3!");
|
|
|
|
// Two-way Conditional branch.
|
|
if (FBB) {
|
|
BuildCondBr(MBB, TBB, DL, Cond);
|
|
BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(FBB);
|
|
return 2;
|
|
}
|
|
|
|
// One way branch.
|
|
// Unconditional branch.
|
|
if (Cond.empty())
|
|
BuildMI(&MBB, DL, get(UncondBrOpc)).addMBB(TBB);
|
|
else // Conditional branch.
|
|
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;
|
|
|
|
// Skip all the debug instructions.
|
|
while (I != REnd && I->isDebugValue())
|
|
++I;
|
|
|
|
FirstBr = I;
|
|
|
|
// Up to 2 branches are removed.
|
|
// Note that indirect branches are not removed.
|
|
for(removed = 0; I != REnd && removed < 2; ++I, ++removed)
|
|
if (!getAnalyzableBrOpc(I->getOpcode()))
|
|
break;
|
|
|
|
MBB.erase(I.base(), FirstBr.base());
|
|
|
|
return removed;
|
|
}
|
|
|
|
/// ReverseBranchCondition - Return the inverse opcode of the
|
|
/// specified Branch instruction.
|
|
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;
|
|
}
|
|
|
|
MipsInstrInfo::BranchType MipsInstrInfo::
|
|
AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
|
MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond,
|
|
bool AllowModify,
|
|
SmallVectorImpl<MachineInstr*> &BranchInstrs) const {
|
|
|
|
MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend();
|
|
|
|
// Skip all the debug instructions.
|
|
while (I != REnd && I->isDebugValue())
|
|
++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 = NULL;
|
|
return BT_NoBranch;
|
|
}
|
|
|
|
MachineInstr *LastInst = &*I;
|
|
unsigned LastOpc = LastInst->getOpcode();
|
|
BranchInstrs.push_back(LastInst);
|
|
|
|
// Not an analyzable branch (e.g., indirect jump).
|
|
if (!getAnalyzableBrOpc(LastOpc))
|
|
return LastInst->isIndirectBranch() ? BT_Indirect : BT_None;
|
|
|
|
// Get the second to last instruction in the block.
|
|
unsigned SecondLastOpc = 0;
|
|
MachineInstr *SecondLastInst = NULL;
|
|
|
|
if (++I != REnd) {
|
|
SecondLastInst = &*I;
|
|
SecondLastOpc = getAnalyzableBrOpc(SecondLastInst->getOpcode());
|
|
|
|
// Not an analyzable branch (must be an indirect jump).
|
|
if (isUnpredicatedTerminator(SecondLastInst) && !SecondLastOpc)
|
|
return BT_None;
|
|
}
|
|
|
|
// If there is only one terminator instruction, process it.
|
|
if (!SecondLastOpc) {
|
|
// Unconditional branch.
|
|
if (LastOpc == UncondBrOpc) {
|
|
TBB = LastInst->getOperand(0).getMBB();
|
|
return BT_Uncond;
|
|
}
|
|
|
|
// Conditional branch
|
|
AnalyzeCondBr(LastInst, LastOpc, TBB, Cond);
|
|
return BT_Cond;
|
|
}
|
|
|
|
// 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))
|
|
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) {
|
|
// Return if the last instruction cannot be removed.
|
|
if (!AllowModify)
|
|
return BT_None;
|
|
|
|
TBB = SecondLastInst->getOperand(0).getMBB();
|
|
LastInst->eraseFromParent();
|
|
BranchInstrs.pop_back();
|
|
return BT_Uncond;
|
|
}
|
|
|
|
// Conditional branch followed by an unconditional branch.
|
|
// The last one must be unconditional.
|
|
if (LastOpc != UncondBrOpc)
|
|
return BT_None;
|
|
|
|
AnalyzeCondBr(SecondLastInst, SecondLastOpc, TBB, Cond);
|
|
FBB = LastInst->getOperand(0).getMBB();
|
|
|
|
return BT_CondUncond;
|
|
}
|
|
|
|
/// Return the number of bytes of code the specified instruction may be.
|
|
unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
|
|
switch (MI->getOpcode()) {
|
|
default:
|
|
return MI->getDesc().getSize();
|
|
case TargetOpcode::INLINEASM: { // Inline Asm: Variable size.
|
|
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();
|
|
}
|
|
}
|
|
|
|
MachineInstrBuilder
|
|
MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,
|
|
MachineBasicBlock::iterator I) const {
|
|
MachineInstrBuilder MIB;
|
|
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));
|
|
|
|
MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end());
|
|
return MIB;
|
|
}
|