diff --git a/llvm/include/llvm/CodeGen/FastISel.h b/llvm/include/llvm/CodeGen/FastISel.h index 763d7029e662..589e8e41bb14 100644 --- a/llvm/include/llvm/CodeGen/FastISel.h +++ b/llvm/include/llvm/CodeGen/FastISel.h @@ -258,6 +258,8 @@ private: bool SelectGetElementPtr(User *I); + bool SelectCall(User *I); + bool SelectBitCast(User *I); bool SelectCast(User *I, ISD::NodeType Opcode); diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index dd7e95294f11..254b1fe42ccd 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -11,9 +11,13 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" @@ -260,6 +264,93 @@ bool FastISel::SelectGetElementPtr(User *I) { return true; } +bool FastISel::SelectCall(User *I) { + Function *F = cast(I)->getCalledFunction(); + if (!F) return false; + + unsigned IID = F->getIntrinsicID(); + switch (IID) { + default: break; + case Intrinsic::dbg_stoppoint: { + DbgStopPointInst *SPI = cast(I); + if (MMI && SPI->getContext() && MMI->Verify(SPI->getContext())) { + DebugInfoDesc *DD = MMI->getDescFor(SPI->getContext()); + assert(DD && "Not a debug information descriptor"); + const CompileUnitDesc *CompileUnit = cast(DD); + unsigned SrcFile = MMI->RecordSource(CompileUnit); + unsigned Line = SPI->getLine(); + unsigned Col = SPI->getColumn(); + unsigned ID = MMI->RecordSourceLine(Line, Col, SrcFile); + const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); + BuildMI(MBB, II).addImm(ID); + } + return true; + } + case Intrinsic::dbg_region_start: { + DbgRegionStartInst *RSI = cast(I); + if (MMI && RSI->getContext() && MMI->Verify(RSI->getContext())) { + unsigned ID = MMI->RecordRegionStart(RSI->getContext()); + const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); + BuildMI(MBB, II).addImm(ID); + } + return true; + } + case Intrinsic::dbg_region_end: { + DbgRegionEndInst *REI = cast(I); + if (MMI && REI->getContext() && MMI->Verify(REI->getContext())) { + unsigned ID = MMI->RecordRegionEnd(REI->getContext()); + const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL); + BuildMI(MBB, II).addImm(ID); + } + return true; + } + case Intrinsic::dbg_func_start: { + if (!MMI) return true; + DbgFuncStartInst *FSI = cast(I); + Value *SP = FSI->getSubprogram(); + if (SP && MMI->Verify(SP)) { + // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is + // what (most?) gdb expects. + DebugInfoDesc *DD = MMI->getDescFor(SP); + assert(DD && "Not a debug information descriptor"); + SubprogramDesc *Subprogram = cast(DD); + const CompileUnitDesc *CompileUnit = Subprogram->getFile(); + unsigned SrcFile = MMI->RecordSource(CompileUnit); + // Record the source line but does create a label. It will be emitted + // at asm emission time. + MMI->RecordSourceLine(Subprogram->getLine(), 0, SrcFile); + } + return true; + } + case Intrinsic::dbg_declare: { + DbgDeclareInst *DI = cast(I); + Value *Variable = DI->getVariable(); + if (MMI && Variable && MMI->Verify(Variable)) { + // Determine the address of the declared object. + Value *Address = DI->getAddress(); + if (BitCastInst *BCI = dyn_cast(Address)) + Address = BCI->getOperand(0); + AllocaInst *AI = dyn_cast(Address); + // Don't handle byval struct arguments, for example. + if (!AI) break; + DenseMap::iterator SI = + StaticAllocaMap.find(AI); + assert(SI != StaticAllocaMap.end() && "Invalid dbg.declare!"); + int FI = SI->second; + + // Determine the debug globalvariable. + GlobalValue *GV = cast(Variable); + + // Build the DECLARE instruction. + const TargetInstrDesc &II = TII.get(TargetInstrInfo::DECLARE); + BuildMI(MBB, II).addFrameIndex(FI).addGlobalAddress(GV); + } + return true; + } + } + return false; +} + bool FastISel::SelectCast(User *I, ISD::NodeType Opcode) { MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); MVT DstVT = TLI.getValueType(I->getType()); @@ -424,6 +515,9 @@ FastISel::SelectOperator(User *I, unsigned Opcode) { // Dynamic-sized alloca is not handled yet. return false; + case Instruction::Call: + return SelectCall(I); + case Instruction::BitCast: return SelectBitCast(I); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index ac4a639ea31b..b9f1aa45078e 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -246,7 +246,9 @@ static bool isUsedOutsideOfDefiningBlock(Instruction *I) { static bool isOnlyUsedInEntryBlock(Argument *A, bool EnableFastISel) { // With FastISel active, we may be splitting blocks, so force creation // of virtual registers for all non-dead arguments. - if (EnableFastISel) + // Don't force virtual registers for byval arguments though, because + // fast-isel can't handle those in all cases. + if (EnableFastISel && !A->hasByValAttr()) return A->use_empty(); BasicBlock *Entry = A->getParent()->begin(); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 9e12a272ad6e..cbb1762e26b0 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -718,12 +718,27 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF, BasicBlock::iterator BI = Begin; // Lower any arguments needed in this block if this is the entry block. - if (LLVMBB == &Fn.getEntryBlock()) + bool SuppressFastISel = false; + if (LLVMBB == &Fn.getEntryBlock()) { LowerArguments(LLVMBB); + // If any of the arguments has the byval attribute, forgo + // fast-isel in the entry block. + if (EnableFastISel) { + unsigned j = 1; + for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(); + I != E; ++I, ++j) + if (Fn.paramHasAttr(j, ParamAttr::ByVal)) { + cerr << "FastISel skips entry block due to byval argument"; + SuppressFastISel = true; + break; + } + } + } + // Before doing SelectionDAG ISel, see if FastISel has been requested. // FastISel doesn't support EH landing pads, which require special handling. - if (EnableFastISel && !BB->isLandingPad()) { + if (EnableFastISel && !SuppressFastISel && !BB->isLandingPad()) { if (FastISel *F = TLI.createFastISel(*FuncInfo->MF, MMI, FuncInfo->ValueMap, FuncInfo->MBBMap, @@ -761,6 +776,9 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF, // Then handle certain instructions as single-LLVM-Instruction blocks. if (isa(BI)) { + cerr << "FastISel missed call: "; + BI->dump(); + if (BI->getType() != Type::VoidTy) { unsigned &R = FuncInfo->ValueMap[BI]; if (!R)