-///===-- FastISel.cpp - Implementation of the FastISel class --------------===//
+//===-- FastISel.cpp - Implementation of the FastISel class ---------------===//
//
// The LLVM Compiler Infrastructure
//
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetMachine.h"
-#include "SelectionDAGBuild.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "FunctionLoweringInfo.h"
using namespace llvm;
-unsigned FastISel::getRegForValue(Value *V) {
- MVT RealVT = TLI.getValueType(V->getType(), /*AllowUnknown=*/true);
+bool FastISel::hasTrivialKill(const Value *V) const {
+ // Don't consider constants or arguments to have trivial kills.
+ const Instruction *I = dyn_cast<Instruction>(V);
+ if (!I)
+ return false;
+
+ // No-op casts are trivially coalesced by fast-isel.
+ if (const CastInst *Cast = dyn_cast<CastInst>(I))
+ if (Cast->isNoopCast(TD.getIntPtrType(Cast->getContext())) &&
+ !hasTrivialKill(Cast->getOperand(0)))
+ return false;
+
+ // Only instructions with a single use in the same basic block are considered
+ // to have trivial kills.
+ return I->hasOneUse() &&
+ !(I->getOpcode() == Instruction::BitCast ||
+ I->getOpcode() == Instruction::PtrToInt ||
+ I->getOpcode() == Instruction::IntToPtr) &&
+ cast<Instruction>(I->use_begin())->getParent() == I->getParent();
+}
+
+unsigned FastISel::getRegForValue(const Value *V) {
+ EVT RealVT = TLI.getValueType(V->getType(), /*AllowUnknown=*/true);
// Don't handle non-simple values in FastISel.
if (!RealVT.isSimple())
return 0;
// Ignore illegal types. We must do this before looking up the value
// in ValueMap because Arguments are given virtual registers regardless
// of whether FastISel can handle them.
- MVT::SimpleValueType VT = RealVT.getSimpleVT();
+ MVT VT = RealVT.getSimpleVT();
if (!TLI.isTypeLegal(VT)) {
// Promote MVT::i1 to a legal type though, because it's common and easy.
if (VT == MVT::i1)
- VT = TLI.getTypeToTransformTo(VT).getSimpleVT();
+ VT = TLI.getTypeToTransformTo(V->getContext(), VT).getSimpleVT();
else
return 0;
}
// Look up the value to see if we already have a register for it. We
// cache values defined by Instructions across blocks, and other values
// only locally. This is because Instructions already have the SSA
- // def-dominatess-use requirement enforced.
+ // def-dominates-use requirement enforced.
if (ValueMap.count(V))
return ValueMap[V];
unsigned Reg = LocalValueMap[V];
if (Reg != 0)
return Reg;
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+ // In bottom-up mode, just create the virtual register which will be used
+ // to hold the value. It will be materialized later.
+ if (IsBottomUp) {
+ Reg = createResultReg(TLI.getRegClassFor(VT));
+ if (isa<Instruction>(V))
+ ValueMap[V] = Reg;
+ else
+ LocalValueMap[V] = Reg;
+ return Reg;
+ }
+
+ return materializeRegForValue(V, VT);
+}
+
+/// materializeRegForValue - Helper for getRegForVale. This function is
+/// called when the value isn't already available in a register and must
+/// be materialized with new instructions.
+unsigned FastISel::materializeRegForValue(const Value *V, MVT VT) {
+ unsigned Reg = 0;
+
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
if (CI->getValue().getActiveBits() <= 64)
Reg = FastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue());
} else if (isa<AllocaInst>(V)) {
} else if (isa<ConstantPointerNull>(V)) {
// Translate this as an integer zero so that it can be
// local-CSE'd with actual integer zeros.
- Reg = getRegForValue(Constant::getNullValue(TD.getIntPtrType()));
- } else if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
+ Reg =
+ getRegForValue(Constant::getNullValue(TD.getIntPtrType(V->getContext())));
+ } else if (const ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
+ // Try to emit the constant directly.
Reg = FastEmit_f(VT, VT, ISD::ConstantFP, CF);
if (!Reg) {
+ // Try to emit the constant by using an integer constant with a cast.
const APFloat &Flt = CF->getValueAPF();
- MVT IntVT = TLI.getPointerTy();
+ EVT IntVT = TLI.getPointerTy();
uint64_t x[2];
uint32_t IntBitWidth = IntVT.getSizeInBits();
if (isExact) {
APInt IntVal(IntBitWidth, 2, x);
- unsigned IntegerReg = getRegForValue(ConstantInt::get(IntVal));
+ unsigned IntegerReg =
+ getRegForValue(ConstantInt::get(V->getContext(), IntVal));
if (IntegerReg != 0)
- Reg = FastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP, IntegerReg);
+ Reg = FastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP,
+ IntegerReg, /*Kill=*/false);
}
}
- } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
- if (!SelectOperator(CE, CE->getOpcode())) return 0;
- Reg = LocalValueMap[CE];
+ } else if (const Operator *Op = dyn_cast<Operator>(V)) {
+ if (!SelectOperator(Op, Op->getOpcode())) return 0;
+ Reg = LocalValueMap[Op];
} else if (isa<UndefValue>(V)) {
Reg = createResultReg(TLI.getRegClassFor(VT));
- BuildMI(MBB, DL, TII.get(TargetInstrInfo::IMPLICIT_DEF), Reg);
+ BuildMI(MBB, DL, TII.get(TargetOpcode::IMPLICIT_DEF), Reg);
}
// If target-independent code couldn't handle the value, give target-specific
return Reg;
}
-unsigned FastISel::lookUpRegForValue(Value *V) {
+unsigned FastISel::lookUpRegForValue(const Value *V) {
// Look up the value to see if we already have a register for it. We
// cache values defined by Instructions across blocks, and other values
// only locally. This is because Instructions already have the SSA
- // def-dominatess-use requirement enforced.
+ // def-dominates-use requirement enforced.
if (ValueMap.count(V))
return ValueMap[V];
return LocalValueMap[V];
/// NOTE: This is only necessary because we might select a block that uses
/// a value before we select the block that defines the value. It might be
/// possible to fix this by selecting blocks in reverse postorder.
-unsigned FastISel::UpdateValueMap(Value* I, unsigned Reg) {
+unsigned FastISel::UpdateValueMap(const Value *I, unsigned Reg) {
if (!isa<Instruction>(I)) {
LocalValueMap[I] = Reg;
return Reg;
else if (Reg != AssignedReg) {
const TargetRegisterClass *RegClass = MRI.getRegClass(Reg);
TII.copyRegToReg(*MBB, MBB->end(), AssignedReg,
- Reg, RegClass, RegClass);
+ Reg, RegClass, RegClass, DL);
}
return AssignedReg;
}
-unsigned FastISel::getRegForGEPIndex(Value *Idx) {
+std::pair<unsigned, bool> FastISel::getRegForGEPIndex(const Value *Idx) {
unsigned IdxN = getRegForValue(Idx);
if (IdxN == 0)
// Unhandled operand. Halt "fast" selection and bail.
- return 0;
+ return std::pair<unsigned, bool>(0, false);
+
+ bool IdxNIsKill = hasTrivialKill(Idx);
// If the index is smaller or larger than intptr_t, truncate or extend it.
MVT PtrVT = TLI.getPointerTy();
- MVT IdxVT = MVT::getMVT(Idx->getType(), /*HandleUnknown=*/false);
- if (IdxVT.bitsLT(PtrVT))
- IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT.getSimpleVT(),
- ISD::SIGN_EXTEND, IdxN);
- else if (IdxVT.bitsGT(PtrVT))
- IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT.getSimpleVT(),
- ISD::TRUNCATE, IdxN);
- return IdxN;
+ EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false);
+ if (IdxVT.bitsLT(PtrVT)) {
+ IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::SIGN_EXTEND,
+ IdxN, IdxNIsKill);
+ IdxNIsKill = true;
+ }
+ else if (IdxVT.bitsGT(PtrVT)) {
+ IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::TRUNCATE,
+ IdxN, IdxNIsKill);
+ IdxNIsKill = true;
+ }
+ return std::pair<unsigned, bool>(IdxN, IdxNIsKill);
}
/// SelectBinaryOp - Select and emit code for a binary operator instruction,
/// which has an opcode which directly corresponds to the given ISD opcode.
///
-bool FastISel::SelectBinaryOp(User *I, ISD::NodeType ISDOpcode) {
- MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
+bool FastISel::SelectBinaryOp(const User *I, unsigned ISDOpcode) {
+ EVT VT = EVT::getEVT(I->getType(), /*HandleUnknown=*/true);
if (VT == MVT::Other || !VT.isSimple())
// Unhandled type. Halt "fast" selection and bail.
return false;
if (VT == MVT::i1 &&
(ISDOpcode == ISD::AND || ISDOpcode == ISD::OR ||
ISDOpcode == ISD::XOR))
- VT = TLI.getTypeToTransformTo(VT);
+ VT = TLI.getTypeToTransformTo(I->getContext(), VT);
else
return false;
}
// Unhandled operand. Halt "fast" selection and bail.
return false;
+ bool Op0IsKill = hasTrivialKill(I->getOperand(0));
+
// Check if the second operand is a constant and handle it appropriately.
if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
unsigned ResultReg = FastEmit_ri(VT.getSimpleVT(), VT.getSimpleVT(),
- ISDOpcode, Op0, CI->getZExtValue());
+ ISDOpcode, Op0, Op0IsKill,
+ CI->getZExtValue());
if (ResultReg != 0) {
// We successfully emitted code for the given LLVM Instruction.
UpdateValueMap(I, ResultReg);
// Check if the second operand is a constant float.
if (ConstantFP *CF = dyn_cast<ConstantFP>(I->getOperand(1))) {
unsigned ResultReg = FastEmit_rf(VT.getSimpleVT(), VT.getSimpleVT(),
- ISDOpcode, Op0, CF);
+ ISDOpcode, Op0, Op0IsKill, CF);
if (ResultReg != 0) {
// We successfully emitted code for the given LLVM Instruction.
UpdateValueMap(I, ResultReg);
// Unhandled operand. Halt "fast" selection and bail.
return false;
+ bool Op1IsKill = hasTrivialKill(I->getOperand(1));
+
// Now we have both operands in registers. Emit the instruction.
unsigned ResultReg = FastEmit_rr(VT.getSimpleVT(), VT.getSimpleVT(),
- ISDOpcode, Op0, Op1);
+ ISDOpcode,
+ Op0, Op0IsKill,
+ Op1, Op1IsKill);
if (ResultReg == 0)
// Target-specific code wasn't able to find a machine opcode for
// the given ISD opcode and type. Halt "fast" selection and bail.
return true;
}
-bool FastISel::SelectGetElementPtr(User *I) {
+bool FastISel::SelectGetElementPtr(const User *I) {
unsigned N = getRegForValue(I->getOperand(0));
if (N == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
+ bool NIsKill = hasTrivialKill(I->getOperand(0));
+
const Type *Ty = I->getOperand(0)->getType();
- MVT::SimpleValueType VT = TLI.getPointerTy().getSimpleVT();
- for (GetElementPtrInst::op_iterator OI = I->op_begin()+1, E = I->op_end();
- OI != E; ++OI) {
- Value *Idx = *OI;
+ MVT VT = TLI.getPointerTy();
+ for (GetElementPtrInst::const_op_iterator OI = I->op_begin()+1,
+ E = I->op_end(); OI != E; ++OI) {
+ const Value *Idx = *OI;
if (const StructType *StTy = dyn_cast<StructType>(Ty)) {
unsigned Field = cast<ConstantInt>(Idx)->getZExtValue();
if (Field) {
uint64_t Offs = TD.getStructLayout(StTy)->getElementOffset(Field);
// FIXME: This can be optimized by combining the add with a
// subsequent one.
- N = FastEmit_ri_(VT, ISD::ADD, N, Offs, VT);
+ N = FastEmit_ri_(VT, ISD::ADD, N, NIsKill, Offs, VT);
if (N == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
+ NIsKill = true;
}
Ty = StTy->getElementType(Field);
} else {
Ty = cast<SequentialType>(Ty)->getElementType();
// If this is a constant subscript, handle it quickly.
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Idx)) {
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(Idx)) {
if (CI->getZExtValue() == 0) continue;
uint64_t Offs =
- TD.getTypePaddedSize(Ty)*cast<ConstantInt>(CI)->getSExtValue();
- N = FastEmit_ri_(VT, ISD::ADD, N, Offs, VT);
+ TD.getTypeAllocSize(Ty)*cast<ConstantInt>(CI)->getSExtValue();
+ N = FastEmit_ri_(VT, ISD::ADD, N, NIsKill, Offs, VT);
if (N == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
+ NIsKill = true;
continue;
}
// N = N + Idx * ElementSize;
- uint64_t ElementSize = TD.getTypePaddedSize(Ty);
- unsigned IdxN = getRegForGEPIndex(Idx);
+ uint64_t ElementSize = TD.getTypeAllocSize(Ty);
+ std::pair<unsigned, bool> Pair = getRegForGEPIndex(Idx);
+ unsigned IdxN = Pair.first;
+ bool IdxNIsKill = Pair.second;
if (IdxN == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
if (ElementSize != 1) {
- IdxN = FastEmit_ri_(VT, ISD::MUL, IdxN, ElementSize, VT);
+ IdxN = FastEmit_ri_(VT, ISD::MUL, IdxN, IdxNIsKill, ElementSize, VT);
if (IdxN == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
+ IdxNIsKill = true;
}
- N = FastEmit_rr(VT, VT, ISD::ADD, N, IdxN);
+ N = FastEmit_rr(VT, VT, ISD::ADD, N, NIsKill, IdxN, IdxNIsKill);
if (N == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
return true;
}
-bool FastISel::SelectCall(User *I) {
- Function *F = cast<CallInst>(I)->getCalledFunction();
+bool FastISel::SelectCall(const User *I) {
+ const Function *F = cast<CallInst>(I)->getCalledFunction();
if (!F) return false;
+ // Handle selected intrinsic function calls.
unsigned IID = F->getIntrinsicID();
switch (IID) {
default: break;
- case Intrinsic::dbg_stoppoint: {
- DbgStopPointInst *SPI = cast<DbgStopPointInst>(I);
- if (DW && DW->ValidDebugInfo(SPI->getContext(), true)) {
- DICompileUnit CU(cast<GlobalVariable>(SPI->getContext()));
- std::string Dir, FN;
- unsigned SrcFile = DW->getOrCreateSourceID(CU.getDirectory(Dir),
- CU.getFilename(FN));
- unsigned Line = SPI->getLine();
- unsigned Col = SPI->getColumn();
- unsigned ID = DW->RecordSourceLine(Line, Col, SrcFile);
- unsigned Idx = MF.getOrCreateDebugLocID(SrcFile, Line, Col);
- setCurDebugLoc(DebugLoc::get(Idx));
- const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
- BuildMI(MBB, DL, II).addImm(ID);
- }
- return true;
- }
- case Intrinsic::dbg_region_start: {
- DbgRegionStartInst *RSI = cast<DbgRegionStartInst>(I);
- if (DW && DW->ValidDebugInfo(RSI->getContext(), true)) {
- unsigned ID =
- DW->RecordRegionStart(cast<GlobalVariable>(RSI->getContext()));
- const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
- BuildMI(MBB, DL, II).addImm(ID);
- }
- return true;
- }
- case Intrinsic::dbg_region_end: {
- DbgRegionEndInst *REI = cast<DbgRegionEndInst>(I);
- if (DW && DW->ValidDebugInfo(REI->getContext(), true)) {
- unsigned ID =
- DW->RecordRegionEnd(cast<GlobalVariable>(REI->getContext()));
- const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
- BuildMI(MBB, DL, II).addImm(ID);
- }
- return true;
- }
- case Intrinsic::dbg_func_start: {
- if (!DW) return true;
- DbgFuncStartInst *FSI = cast<DbgFuncStartInst>(I);
- Value *SP = FSI->getSubprogram();
-
- if (DW->ValidDebugInfo(SP, true)) {
- // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is what
- // (most?) gdb expects.
- DISubprogram Subprogram(cast<GlobalVariable>(SP));
- DICompileUnit CompileUnit = Subprogram.getCompileUnit();
- std::string Dir, FN;
- unsigned SrcFile = DW->getOrCreateSourceID(CompileUnit.getDirectory(Dir),
- CompileUnit.getFilename(FN));
-
- // Record the source line.
- unsigned Line = Subprogram.getLineNumber();
- unsigned LabelID = DW->RecordSourceLine(Line, 0, SrcFile);
- setCurDebugLoc(DebugLoc::get(MF.getOrCreateDebugLocID(SrcFile, Line, 0)));
-
- std::string SPName;
- Subprogram.getLinkageName(SPName);
- if (!SPName.empty()
- && strcmp(SPName.c_str(), MF.getFunction()->getNameStart())) {
- // This is a beginning of inlined function.
- DW->RecordRegionStart(cast<GlobalVariable>(FSI->getSubprogram()),
- LabelID);
- const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
- BuildMI(MBB, DL, II).addImm(LabelID);
- DW->RecordInlineInfo(Subprogram.getGV(), LabelID);
- } else {
- // llvm.dbg.func_start also defines beginning of function scope.
- DW->RecordRegionStart(cast<GlobalVariable>(FSI->getSubprogram()));
- }
- }
-
- return true;
- }
case Intrinsic::dbg_declare: {
- DbgDeclareInst *DI = cast<DbgDeclareInst>(I);
- Value *Variable = DI->getVariable();
- if (DW && DW->ValidDebugInfo(Variable, true)) {
- // Determine the address of the declared object.
- Value *Address = DI->getAddress();
- if (BitCastInst *BCI = dyn_cast<BitCastInst>(Address))
- Address = BCI->getOperand(0);
- AllocaInst *AI = dyn_cast<AllocaInst>(Address);
- // Don't handle byval struct arguments or VLAs, for example.
- if (!AI) break;
+ const DbgDeclareInst *DI = cast<DbgDeclareInst>(I);
+ if (!DIVariable(DI->getVariable()).Verify() ||
+ !MF.getMMI().hasDebugInfo())
+ return true;
+
+ const Value *Address = DI->getAddress();
+ if (!Address)
+ return true;
+ if (isa<UndefValue>(Address))
+ return true;
+ const AllocaInst *AI = dyn_cast<AllocaInst>(Address);
+ // Don't handle byval struct arguments or VLAs, for example.
+ // Note that if we have a byval struct argument, fast ISel is turned off;
+ // those are handled in SelectionDAGBuilder.
+ if (AI) {
DenseMap<const AllocaInst*, int>::iterator SI =
StaticAllocaMap.find(AI);
if (SI == StaticAllocaMap.end()) break; // VLAs.
int FI = SI->second;
-
- // Determine the debug globalvariable.
- GlobalValue *GV = cast<GlobalVariable>(Variable);
-
- // Build the DECLARE instruction.
- const TargetInstrDesc &II = TII.get(TargetInstrInfo::DECLARE);
- BuildMI(MBB, DL, II).addFrameIndex(FI).addGlobalAddress(GV);
- }
+ if (!DI->getDebugLoc().isUnknown())
+ MF.getMMI().setVariableDbgInfo(DI->getVariable(), FI, DI->getDebugLoc());
+ } else
+ // Building the map above is target independent. Generating DBG_VALUE
+ // inline is target dependent; do this now.
+ (void)TargetSelectInstruction(cast<Instruction>(I));
+ return true;
+ }
+ case Intrinsic::dbg_value: {
+ // This form of DBG_VALUE is target-independent.
+ const DbgValueInst *DI = cast<DbgValueInst>(I);
+ const TargetInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE);
+ const Value *V = DI->getValue();
+ if (!V) {
+ // Currently the optimizer can produce this; insert an undef to
+ // help debugging. Probably the optimizer should not do this.
+ BuildMI(MBB, DL, II).addReg(0U).addImm(DI->getOffset()).
+ addMetadata(DI->getVariable());
+ } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+ BuildMI(MBB, DL, II).addImm(CI->getZExtValue()).addImm(DI->getOffset()).
+ addMetadata(DI->getVariable());
+ } else if (const ConstantFP *CF = dyn_cast<ConstantFP>(V)) {
+ BuildMI(MBB, DL, II).addFPImm(CF).addImm(DI->getOffset()).
+ addMetadata(DI->getVariable());
+ } else if (unsigned Reg = lookUpRegForValue(V)) {
+ BuildMI(MBB, DL, II).addReg(Reg, RegState::Debug).addImm(DI->getOffset()).
+ addMetadata(DI->getVariable());
+ } else {
+ // We can't yet handle anything else here because it would require
+ // generating code, thus altering codegen because of debug info.
+ // Insert an undef so we can see what we dropped.
+ BuildMI(MBB, DL, II).addReg(0U).addImm(DI->getOffset()).
+ addMetadata(DI->getVariable());
+ }
return true;
}
case Intrinsic::eh_exception: {
- MVT VT = TLI.getValueType(I->getType());
+ EVT VT = TLI.getValueType(I->getType());
switch (TLI.getOperationAction(ISD::EXCEPTIONADDR, VT)) {
default: break;
case TargetLowering::Expand: {
- if (!MBB->isLandingPad()) {
- // FIXME: Mark exception register as live in. Hack for PR1508.
- unsigned Reg = TLI.getExceptionAddressRegister();
- if (Reg) MBB->addLiveIn(Reg);
- }
+ assert(MBB->isLandingPad() && "Call to eh.exception not in landing pad!");
unsigned Reg = TLI.getExceptionAddressRegister();
const TargetRegisterClass *RC = TLI.getRegClassFor(VT);
unsigned ResultReg = createResultReg(RC);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
- Reg, RC, RC);
+ Reg, RC, RC, DL);
assert(InsertedCopy && "Can't copy address registers!");
InsertedCopy = InsertedCopy;
UpdateValueMap(I, ResultReg);
}
break;
}
- case Intrinsic::eh_selector_i32:
- case Intrinsic::eh_selector_i64: {
- MVT VT = TLI.getValueType(I->getType());
+ case Intrinsic::eh_selector: {
+ EVT VT = TLI.getValueType(I->getType());
switch (TLI.getOperationAction(ISD::EHSELECTION, VT)) {
default: break;
case TargetLowering::Expand: {
- MVT VT = (IID == Intrinsic::eh_selector_i32 ?
- MVT::i32 : MVT::i64);
-
- if (MMI) {
- if (MBB->isLandingPad())
- AddCatchInfo(*cast<CallInst>(I), MMI, MBB);
- else {
+ if (MBB->isLandingPad())
+ AddCatchInfo(*cast<CallInst>(I), &MF.getMMI(), MBB);
+ else {
#ifndef NDEBUG
- CatchInfoLost.insert(cast<CallInst>(I));
+ CatchInfoLost.insert(cast<CallInst>(I));
#endif
- // FIXME: Mark exception selector register as live in. Hack for PR1508.
- unsigned Reg = TLI.getExceptionSelectorRegister();
- if (Reg) MBB->addLiveIn(Reg);
- }
-
+ // FIXME: Mark exception selector register as live in. Hack for PR1508.
unsigned Reg = TLI.getExceptionSelectorRegister();
- const TargetRegisterClass *RC = TLI.getRegClassFor(VT);
- unsigned ResultReg = createResultReg(RC);
- bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
- Reg, RC, RC);
- assert(InsertedCopy && "Can't copy address registers!");
- InsertedCopy = InsertedCopy;
- UpdateValueMap(I, ResultReg);
- } else {
- unsigned ResultReg =
- getRegForValue(Constant::getNullValue(I->getType()));
- UpdateValueMap(I, ResultReg);
+ if (Reg) MBB->addLiveIn(Reg);
}
+
+ unsigned Reg = TLI.getExceptionSelectorRegister();
+ EVT SrcVT = TLI.getPointerTy();
+ const TargetRegisterClass *RC = TLI.getRegClassFor(SrcVT);
+ unsigned ResultReg = createResultReg(RC);
+ bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, Reg,
+ RC, RC, DL);
+ assert(InsertedCopy && "Can't copy address registers!");
+ InsertedCopy = InsertedCopy;
+
+ bool ResultRegIsKill = hasTrivialKill(I);
+
+ // Cast the register to the type of the selector.
+ if (SrcVT.bitsGT(MVT::i32))
+ ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE,
+ ResultReg, ResultRegIsKill);
+ else if (SrcVT.bitsLT(MVT::i32))
+ ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32,
+ ISD::SIGN_EXTEND, ResultReg, ResultRegIsKill);
+ if (ResultReg == 0)
+ // Unhandled operand. Halt "fast" selection and bail.
+ return false;
+
+ UpdateValueMap(I, ResultReg);
+
return true;
}
}
break;
}
}
+
+ // An arbitrary call. Bail.
return false;
}
-bool FastISel::SelectCast(User *I, ISD::NodeType Opcode) {
- MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
- MVT DstVT = TLI.getValueType(I->getType());
+bool FastISel::SelectCast(const User *I, unsigned Opcode) {
+ EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
+ EVT DstVT = TLI.getValueType(I->getType());
if (SrcVT == MVT::Other || !SrcVT.isSimple() ||
DstVT == MVT::Other || !DstVT.isSimple())
// Unhandled operand. Halt "fast" selection and bail.
return false;
+ bool InputRegIsKill = hasTrivialKill(I->getOperand(0));
+
// If the operand is i1, arrange for the high bits in the register to be zero.
if (SrcVT == MVT::i1) {
- SrcVT = TLI.getTypeToTransformTo(SrcVT);
- InputReg = FastEmitZExtFromI1(SrcVT.getSimpleVT(), InputReg);
+ SrcVT = TLI.getTypeToTransformTo(I->getContext(), SrcVT);
+ InputReg = FastEmitZExtFromI1(SrcVT.getSimpleVT(), InputReg, InputRegIsKill);
if (!InputReg)
return false;
+ InputRegIsKill = true;
}
// If the result is i1, truncate to the target's type for i1 first.
if (DstVT == MVT::i1)
- DstVT = TLI.getTypeToTransformTo(DstVT);
+ DstVT = TLI.getTypeToTransformTo(I->getContext(), DstVT);
unsigned ResultReg = FastEmit_r(SrcVT.getSimpleVT(),
DstVT.getSimpleVT(),
Opcode,
- InputReg);
+ InputReg, InputRegIsKill);
if (!ResultReg)
return false;
return true;
}
-bool FastISel::SelectBitCast(User *I) {
+bool FastISel::SelectBitCast(const User *I) {
// If the bitcast doesn't change the type, just use the operand value.
if (I->getType() == I->getOperand(0)->getType()) {
unsigned Reg = getRegForValue(I->getOperand(0));
}
// Bitcasts of other values become reg-reg copies or BIT_CONVERT operators.
- MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
- MVT DstVT = TLI.getValueType(I->getType());
+ EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
+ EVT DstVT = TLI.getValueType(I->getType());
if (SrcVT == MVT::Other || !SrcVT.isSimple() ||
DstVT == MVT::Other || !DstVT.isSimple() ||
if (Op0 == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
+
+ bool Op0IsKill = hasTrivialKill(I->getOperand(0));
// First, try to perform the bitcast by inserting a reg-reg copy.
unsigned ResultReg = 0;
ResultReg = createResultReg(DstClass);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
- Op0, DstClass, SrcClass);
+ Op0, DstClass, SrcClass, DL);
if (!InsertedCopy)
ResultReg = 0;
}
// If the reg-reg copy failed, select a BIT_CONVERT opcode.
if (!ResultReg)
ResultReg = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(),
- ISD::BIT_CONVERT, Op0);
+ ISD::BIT_CONVERT, Op0, Op0IsKill);
if (!ResultReg)
return false;
}
bool
-FastISel::SelectInstruction(Instruction *I) {
- return SelectOperator(I, I->getOpcode());
+FastISel::SelectInstruction(const Instruction *I) {
+ // Just before the terminator instruction, insert instructions to
+ // feed PHI nodes in successor blocks.
+ if (isa<TerminatorInst>(I))
+ if (!HandlePHINodesInSuccessorBlocks(I->getParent()))
+ return false;
+
+ DL = I->getDebugLoc();
+
+ // First, try doing target-independent selection.
+ if (SelectOperator(I, I->getOpcode())) {
+ DL = DebugLoc();
+ return true;
+ }
+
+ // Next, try calling the target to attempt to handle the instruction.
+ if (TargetSelectInstruction(I)) {
+ DL = DebugLoc();
+ return true;
+ }
+
+ DL = DebugLoc();
+ return false;
}
/// FastEmitBranch - Emit an unconditional branch to the given block,
/// the CFG.
void
FastISel::FastEmitBranch(MachineBasicBlock *MSucc) {
- MachineFunction::iterator NextMBB =
- next(MachineFunction::iterator(MBB));
-
if (MBB->isLayoutSuccessor(MSucc)) {
// The unconditional fall-through case, which needs no instructions.
} else {
MBB->addSuccessor(MSucc);
}
+/// SelectFNeg - Emit an FNeg operation.
+///
bool
-FastISel::SelectOperator(User *I, unsigned Opcode) {
- switch (Opcode) {
- case Instruction::Add: {
- ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FADD : ISD::ADD;
- return SelectBinaryOp(I, Opc);
- }
- case Instruction::Sub: {
- ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FSUB : ISD::SUB;
- return SelectBinaryOp(I, Opc);
- }
- case Instruction::Mul: {
- ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FMUL : ISD::MUL;
- return SelectBinaryOp(I, Opc);
+FastISel::SelectFNeg(const User *I) {
+ unsigned OpReg = getRegForValue(BinaryOperator::getFNegArgument(I));
+ if (OpReg == 0) return false;
+
+ bool OpRegIsKill = hasTrivialKill(I);
+
+ // If the target has ISD::FNEG, use it.
+ EVT VT = TLI.getValueType(I->getType());
+ unsigned ResultReg = FastEmit_r(VT.getSimpleVT(), VT.getSimpleVT(),
+ ISD::FNEG, OpReg, OpRegIsKill);
+ if (ResultReg != 0) {
+ UpdateValueMap(I, ResultReg);
+ return true;
}
+
+ // Bitcast the value to integer, twiddle the sign bit with xor,
+ // and then bitcast it back to floating-point.
+ if (VT.getSizeInBits() > 64) return false;
+ EVT IntVT = EVT::getIntegerVT(I->getContext(), VT.getSizeInBits());
+ if (!TLI.isTypeLegal(IntVT))
+ return false;
+
+ unsigned IntReg = FastEmit_r(VT.getSimpleVT(), IntVT.getSimpleVT(),
+ ISD::BIT_CONVERT, OpReg, OpRegIsKill);
+ if (IntReg == 0)
+ return false;
+
+ unsigned IntResultReg = FastEmit_ri_(IntVT.getSimpleVT(), ISD::XOR,
+ IntReg, /*Kill=*/true,
+ UINT64_C(1) << (VT.getSizeInBits()-1),
+ IntVT.getSimpleVT());
+ if (IntResultReg == 0)
+ return false;
+
+ ResultReg = FastEmit_r(IntVT.getSimpleVT(), VT.getSimpleVT(),
+ ISD::BIT_CONVERT, IntResultReg, /*Kill=*/true);
+ if (ResultReg == 0)
+ return false;
+
+ UpdateValueMap(I, ResultReg);
+ return true;
+}
+
+bool
+FastISel::SelectOperator(const User *I, unsigned Opcode) {
+ switch (Opcode) {
+ case Instruction::Add:
+ return SelectBinaryOp(I, ISD::ADD);
+ case Instruction::FAdd:
+ return SelectBinaryOp(I, ISD::FADD);
+ case Instruction::Sub:
+ return SelectBinaryOp(I, ISD::SUB);
+ case Instruction::FSub:
+ // FNeg is currently represented in LLVM IR as a special case of FSub.
+ if (BinaryOperator::isFNeg(I))
+ return SelectFNeg(I);
+ return SelectBinaryOp(I, ISD::FSUB);
+ case Instruction::Mul:
+ return SelectBinaryOp(I, ISD::MUL);
+ case Instruction::FMul:
+ return SelectBinaryOp(I, ISD::FMUL);
case Instruction::SDiv:
return SelectBinaryOp(I, ISD::SDIV);
case Instruction::UDiv:
return SelectGetElementPtr(I);
case Instruction::Br: {
- BranchInst *BI = cast<BranchInst>(I);
+ const BranchInst *BI = cast<BranchInst>(I);
if (BI->isUnconditional()) {
- BasicBlock *LLVMSucc = BI->getSuccessor(0);
+ const BasicBlock *LLVMSucc = BI->getSuccessor(0);
MachineBasicBlock *MSucc = MBBMap[LLVMSucc];
FastEmitBranch(MSucc);
return true;
// Nothing to emit.
return true;
- case Instruction::PHI:
- // PHI nodes are already emitted.
- return true;
-
case Instruction::Alloca:
// FunctionLowering has the static-sized case covered.
if (StaticAllocaMap.count(cast<AllocaInst>(I)))
case Instruction::IntToPtr: // Deliberate fall-through.
case Instruction::PtrToInt: {
- MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
- MVT DstVT = TLI.getValueType(I->getType());
+ EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
+ EVT DstVT = TLI.getValueType(I->getType());
if (DstVT.bitsGT(SrcVT))
return SelectCast(I, ISD::ZERO_EXTEND);
if (DstVT.bitsLT(SrcVT))
return true;
}
+ case Instruction::PHI:
+ llvm_unreachable("FastISel shouldn't visit PHI nodes!");
+
default:
// Unhandled instruction. Halt "fast" selection and bail.
return false;
}
FastISel::FastISel(MachineFunction &mf,
- MachineModuleInfo *mmi,
- DwarfWriter *dw,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
- DenseMap<const AllocaInst *, int> &am
+ DenseMap<const AllocaInst *, int> &am,
+ std::vector<std::pair<MachineInstr*, unsigned> > &pn
#ifndef NDEBUG
- , SmallSet<Instruction*, 8> &cil
+ , SmallSet<const Instruction *, 8> &cil
#endif
)
: MBB(0),
ValueMap(vm),
MBBMap(bm),
StaticAllocaMap(am),
+ PHINodesToUpdate(pn),
#ifndef NDEBUG
CatchInfoLost(cil),
#endif
MF(mf),
- MMI(mmi),
- DW(dw),
MRI(MF.getRegInfo()),
MFI(*MF.getFrameInfo()),
MCP(*MF.getConstantPool()),
TM(MF.getTarget()),
TD(*TM.getTargetData()),
TII(*TM.getInstrInfo()),
- TLI(*TM.getTargetLowering()) {
+ TLI(*TM.getTargetLowering()),
+ IsBottomUp(false) {
}
FastISel::~FastISel() {}
-unsigned FastISel::FastEmit_(MVT::SimpleValueType, MVT::SimpleValueType,
- ISD::NodeType) {
+unsigned FastISel::FastEmit_(MVT, MVT,
+ unsigned) {
return 0;
}
-unsigned FastISel::FastEmit_r(MVT::SimpleValueType, MVT::SimpleValueType,
- ISD::NodeType, unsigned /*Op0*/) {
+unsigned FastISel::FastEmit_r(MVT, MVT,
+ unsigned,
+ unsigned /*Op0*/, bool /*Op0IsKill*/) {
return 0;
}
-unsigned FastISel::FastEmit_rr(MVT::SimpleValueType, MVT::SimpleValueType,
- ISD::NodeType, unsigned /*Op0*/,
- unsigned /*Op0*/) {
+unsigned FastISel::FastEmit_rr(MVT, MVT,
+ unsigned,
+ unsigned /*Op0*/, bool /*Op0IsKill*/,
+ unsigned /*Op1*/, bool /*Op1IsKill*/) {
return 0;
}
-unsigned FastISel::FastEmit_i(MVT::SimpleValueType, MVT::SimpleValueType,
- ISD::NodeType, uint64_t /*Imm*/) {
+unsigned FastISel::FastEmit_i(MVT, MVT, unsigned, uint64_t /*Imm*/) {
return 0;
}
-unsigned FastISel::FastEmit_f(MVT::SimpleValueType, MVT::SimpleValueType,
- ISD::NodeType, ConstantFP * /*FPImm*/) {
+unsigned FastISel::FastEmit_f(MVT, MVT,
+ unsigned, const ConstantFP * /*FPImm*/) {
return 0;
}
-unsigned FastISel::FastEmit_ri(MVT::SimpleValueType, MVT::SimpleValueType,
- ISD::NodeType, unsigned /*Op0*/,
+unsigned FastISel::FastEmit_ri(MVT, MVT,
+ unsigned,
+ unsigned /*Op0*/, bool /*Op0IsKill*/,
uint64_t /*Imm*/) {
return 0;
}
-unsigned FastISel::FastEmit_rf(MVT::SimpleValueType, MVT::SimpleValueType,
- ISD::NodeType, unsigned /*Op0*/,
- ConstantFP * /*FPImm*/) {
+unsigned FastISel::FastEmit_rf(MVT, MVT,
+ unsigned,
+ unsigned /*Op0*/, bool /*Op0IsKill*/,
+ const ConstantFP * /*FPImm*/) {
return 0;
}
-unsigned FastISel::FastEmit_rri(MVT::SimpleValueType, MVT::SimpleValueType,
- ISD::NodeType,
- unsigned /*Op0*/, unsigned /*Op1*/,
+unsigned FastISel::FastEmit_rri(MVT, MVT,
+ unsigned,
+ unsigned /*Op0*/, bool /*Op0IsKill*/,
+ unsigned /*Op1*/, bool /*Op1IsKill*/,
uint64_t /*Imm*/) {
return 0;
}
/// to emit an instruction with an immediate operand using FastEmit_ri.
/// If that fails, it materializes the immediate into a register and try
/// FastEmit_rr instead.
-unsigned FastISel::FastEmit_ri_(MVT::SimpleValueType VT, ISD::NodeType Opcode,
- unsigned Op0, uint64_t Imm,
- MVT::SimpleValueType ImmType) {
+unsigned FastISel::FastEmit_ri_(MVT VT, unsigned Opcode,
+ unsigned Op0, bool Op0IsKill,
+ uint64_t Imm, MVT ImmType) {
// First check if immediate type is legal. If not, we can't use the ri form.
- unsigned ResultReg = FastEmit_ri(VT, VT, Opcode, Op0, Imm);
+ unsigned ResultReg = FastEmit_ri(VT, VT, Opcode, Op0, Op0IsKill, Imm);
if (ResultReg != 0)
return ResultReg;
unsigned MaterialReg = FastEmit_i(ImmType, ImmType, ISD::Constant, Imm);
if (MaterialReg == 0)
return 0;
- return FastEmit_rr(VT, VT, Opcode, Op0, MaterialReg);
+ return FastEmit_rr(VT, VT, Opcode,
+ Op0, Op0IsKill,
+ MaterialReg, /*Kill=*/true);
}
/// FastEmit_rf_ - This method is a wrapper of FastEmit_ri. It first tries
/// to emit an instruction with a floating-point immediate operand using
/// FastEmit_rf. If that fails, it materializes the immediate into a register
/// and try FastEmit_rr instead.
-unsigned FastISel::FastEmit_rf_(MVT::SimpleValueType VT, ISD::NodeType Opcode,
- unsigned Op0, ConstantFP *FPImm,
- MVT::SimpleValueType ImmType) {
+unsigned FastISel::FastEmit_rf_(MVT VT, unsigned Opcode,
+ unsigned Op0, bool Op0IsKill,
+ const ConstantFP *FPImm, MVT ImmType) {
// First check if immediate type is legal. If not, we can't use the rf form.
- unsigned ResultReg = FastEmit_rf(VT, VT, Opcode, Op0, FPImm);
+ unsigned ResultReg = FastEmit_rf(VT, VT, Opcode, Op0, Op0IsKill, FPImm);
if (ResultReg != 0)
return ResultReg;
// be replaced by code that creates a load from a constant-pool entry,
// which will require some target-specific work.
const APFloat &Flt = FPImm->getValueAPF();
- MVT IntVT = TLI.getPointerTy();
+ EVT IntVT = TLI.getPointerTy();
uint64_t x[2];
uint32_t IntBitWidth = IntVT.getSizeInBits();
if (IntegerReg == 0)
return 0;
MaterialReg = FastEmit_r(IntVT.getSimpleVT(), VT,
- ISD::SINT_TO_FP, IntegerReg);
+ ISD::SINT_TO_FP, IntegerReg, /*Kill=*/true);
if (MaterialReg == 0)
return 0;
}
- return FastEmit_rr(VT, VT, Opcode, Op0, MaterialReg);
+ return FastEmit_rr(VT, VT, Opcode,
+ Op0, Op0IsKill,
+ MaterialReg, /*Kill=*/true);
}
unsigned FastISel::createResultReg(const TargetRegisterClass* RC) {
unsigned FastISel::FastEmitInst_r(unsigned MachineInstOpcode,
const TargetRegisterClass *RC,
- unsigned Op0) {
+ unsigned Op0, bool Op0IsKill) {
unsigned ResultReg = createResultReg(RC);
const TargetInstrDesc &II = TII.get(MachineInstOpcode);
if (II.getNumDefs() >= 1)
- BuildMI(MBB, DL, II, ResultReg).addReg(Op0);
+ BuildMI(MBB, DL, II, ResultReg).addReg(Op0, Op0IsKill * RegState::Kill);
else {
- BuildMI(MBB, DL, II).addReg(Op0);
+ BuildMI(MBB, DL, II).addReg(Op0, Op0IsKill * RegState::Kill);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
- II.ImplicitDefs[0], RC, RC);
+ II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy)
ResultReg = 0;
}
unsigned FastISel::FastEmitInst_rr(unsigned MachineInstOpcode,
const TargetRegisterClass *RC,
- unsigned Op0, unsigned Op1) {
+ unsigned Op0, bool Op0IsKill,
+ unsigned Op1, bool Op1IsKill) {
unsigned ResultReg = createResultReg(RC);
const TargetInstrDesc &II = TII.get(MachineInstOpcode);
if (II.getNumDefs() >= 1)
- BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addReg(Op1);
+ BuildMI(MBB, DL, II, ResultReg)
+ .addReg(Op0, Op0IsKill * RegState::Kill)
+ .addReg(Op1, Op1IsKill * RegState::Kill);
else {
- BuildMI(MBB, DL, II).addReg(Op0).addReg(Op1);
+ BuildMI(MBB, DL, II)
+ .addReg(Op0, Op0IsKill * RegState::Kill)
+ .addReg(Op1, Op1IsKill * RegState::Kill);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
- II.ImplicitDefs[0], RC, RC);
+ II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy)
ResultReg = 0;
}
unsigned FastISel::FastEmitInst_ri(unsigned MachineInstOpcode,
const TargetRegisterClass *RC,
- unsigned Op0, uint64_t Imm) {
+ unsigned Op0, bool Op0IsKill,
+ uint64_t Imm) {
unsigned ResultReg = createResultReg(RC);
const TargetInstrDesc &II = TII.get(MachineInstOpcode);
if (II.getNumDefs() >= 1)
- BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addImm(Imm);
+ BuildMI(MBB, DL, II, ResultReg)
+ .addReg(Op0, Op0IsKill * RegState::Kill)
+ .addImm(Imm);
else {
- BuildMI(MBB, DL, II).addReg(Op0).addImm(Imm);
+ BuildMI(MBB, DL, II)
+ .addReg(Op0, Op0IsKill * RegState::Kill)
+ .addImm(Imm);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
- II.ImplicitDefs[0], RC, RC);
+ II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy)
ResultReg = 0;
}
unsigned FastISel::FastEmitInst_rf(unsigned MachineInstOpcode,
const TargetRegisterClass *RC,
- unsigned Op0, ConstantFP *FPImm) {
+ unsigned Op0, bool Op0IsKill,
+ const ConstantFP *FPImm) {
unsigned ResultReg = createResultReg(RC);
const TargetInstrDesc &II = TII.get(MachineInstOpcode);
if (II.getNumDefs() >= 1)
- BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addFPImm(FPImm);
+ BuildMI(MBB, DL, II, ResultReg)
+ .addReg(Op0, Op0IsKill * RegState::Kill)
+ .addFPImm(FPImm);
else {
- BuildMI(MBB, DL, II).addReg(Op0).addFPImm(FPImm);
+ BuildMI(MBB, DL, II)
+ .addReg(Op0, Op0IsKill * RegState::Kill)
+ .addFPImm(FPImm);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
- II.ImplicitDefs[0], RC, RC);
+ II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy)
ResultReg = 0;
}
unsigned FastISel::FastEmitInst_rri(unsigned MachineInstOpcode,
const TargetRegisterClass *RC,
- unsigned Op0, unsigned Op1, uint64_t Imm) {
+ unsigned Op0, bool Op0IsKill,
+ unsigned Op1, bool Op1IsKill,
+ uint64_t Imm) {
unsigned ResultReg = createResultReg(RC);
const TargetInstrDesc &II = TII.get(MachineInstOpcode);
if (II.getNumDefs() >= 1)
- BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addReg(Op1).addImm(Imm);
+ BuildMI(MBB, DL, II, ResultReg)
+ .addReg(Op0, Op0IsKill * RegState::Kill)
+ .addReg(Op1, Op1IsKill * RegState::Kill)
+ .addImm(Imm);
else {
- BuildMI(MBB, DL, II).addReg(Op0).addReg(Op1).addImm(Imm);
+ BuildMI(MBB, DL, II)
+ .addReg(Op0, Op0IsKill * RegState::Kill)
+ .addReg(Op1, Op1IsKill * RegState::Kill)
+ .addImm(Imm);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
- II.ImplicitDefs[0], RC, RC);
+ II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy)
ResultReg = 0;
}
else {
BuildMI(MBB, DL, II).addImm(Imm);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
- II.ImplicitDefs[0], RC, RC);
+ II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy)
ResultReg = 0;
}
return ResultReg;
}
-unsigned FastISel::FastEmitInst_extractsubreg(MVT::SimpleValueType RetVT,
- unsigned Op0, uint32_t Idx) {
+unsigned FastISel::FastEmitInst_extractsubreg(MVT RetVT,
+ unsigned Op0, bool Op0IsKill,
+ uint32_t Idx) {
const TargetRegisterClass* RC = MRI.getRegClass(Op0);
unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT));
- const TargetInstrDesc &II = TII.get(TargetInstrInfo::EXTRACT_SUBREG);
+ const TargetInstrDesc &II = TII.get(TargetOpcode::EXTRACT_SUBREG);
if (II.getNumDefs() >= 1)
- BuildMI(MBB, DL, II, ResultReg).addReg(Op0).addImm(Idx);
+ BuildMI(MBB, DL, II, ResultReg)
+ .addReg(Op0, Op0IsKill * RegState::Kill)
+ .addImm(Idx);
else {
- BuildMI(MBB, DL, II).addReg(Op0).addImm(Idx);
+ BuildMI(MBB, DL, II)
+ .addReg(Op0, Op0IsKill * RegState::Kill)
+ .addImm(Idx);
bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
- II.ImplicitDefs[0], RC, RC);
+ II.ImplicitDefs[0], RC, RC, DL);
if (!InsertedCopy)
ResultReg = 0;
}
/// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op
/// with all but the least significant bit set to zero.
-unsigned FastISel::FastEmitZExtFromI1(MVT::SimpleValueType VT, unsigned Op) {
- return FastEmit_ri(VT, VT, ISD::AND, Op, 1);
+unsigned FastISel::FastEmitZExtFromI1(MVT VT, unsigned Op0, bool Op0IsKill) {
+ return FastEmit_ri(VT, VT, ISD::AND, Op0, Op0IsKill, 1);
+}
+
+/// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks.
+/// Emit code to ensure constants are copied into registers when needed.
+/// Remember the virtual registers that need to be added to the Machine PHI
+/// nodes as input. We cannot just directly add them, because expansion
+/// might result in multiple MBB's for one BB. As such, the start of the
+/// BB might correspond to a different MBB than the end.
+bool FastISel::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
+ const TerminatorInst *TI = LLVMBB->getTerminator();
+
+ SmallPtrSet<MachineBasicBlock *, 4> SuccsHandled;
+ unsigned OrigNumPHINodesToUpdate = PHINodesToUpdate.size();
+
+ // Check successor nodes' PHI nodes that expect a constant to be available
+ // from this block.
+ for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) {
+ const BasicBlock *SuccBB = TI->getSuccessor(succ);
+ if (!isa<PHINode>(SuccBB->begin())) continue;
+ MachineBasicBlock *SuccMBB = MBBMap[SuccBB];
+
+ // If this terminator has multiple identical successors (common for
+ // switches), only handle each succ once.
+ if (!SuccsHandled.insert(SuccMBB)) continue;
+
+ MachineBasicBlock::iterator MBBI = SuccMBB->begin();
+
+ // At this point we know that there is a 1-1 correspondence between LLVM PHI
+ // nodes and Machine PHI nodes, but the incoming operands have not been
+ // emitted yet.
+ for (BasicBlock::const_iterator I = SuccBB->begin();
+ const PHINode *PN = dyn_cast<PHINode>(I); ++I) {
+
+ // Ignore dead phi's.
+ if (PN->use_empty()) continue;
+
+ // Only handle legal types. Two interesting things to note here. First,
+ // by bailing out early, we may leave behind some dead instructions,
+ // since SelectionDAG's HandlePHINodesInSuccessorBlocks will insert its
+ // own moves. Second, this check is necessary becuase FastISel doesn't
+ // use CreateRegForValue to create registers, so it always creates
+ // exactly one register for each non-void instruction.
+ EVT VT = TLI.getValueType(PN->getType(), /*AllowUnknown=*/true);
+ if (VT == MVT::Other || !TLI.isTypeLegal(VT)) {
+ // Promote MVT::i1.
+ if (VT == MVT::i1)
+ VT = TLI.getTypeToTransformTo(LLVMBB->getContext(), VT);
+ else {
+ PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
+ return false;
+ }
+ }
+
+ const Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB);
+
+ // Set the DebugLoc for the copy. Prefer the location of the operand
+ // if there is one; use the location of the PHI otherwise.
+ DL = PN->getDebugLoc();
+ if (const Instruction *Inst = dyn_cast<Instruction>(PHIOp))
+ DL = Inst->getDebugLoc();
+
+ unsigned Reg = getRegForValue(PHIOp);
+ if (Reg == 0) {
+ PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
+ return false;
+ }
+ PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg));
+ DL = DebugLoc();
+ }
+ }
+
+ return true;
}