Loading llvm/include/llvm/Transforms/Tapir/LoweringUtils.h +2 −0 Original line number Diff line number Diff line Loading @@ -253,6 +253,8 @@ public: /// Returns true if Function F should be processed. virtual bool shouldProcessFunction(const Function &F) const; virtual void prepareModule() {} /// Returns true if tasks in Function F should be outlined into their own /// functions. Such outlining is a common step for many Tapir backends. virtual bool shouldDoOutlining(const Function &F) const { return true; } Loading llvm/include/llvm/Transforms/Tapir/OpenCilkABI.h +9 −13 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ class TapirLoopInfo; class OpenCilkABI : public TapirTarget { ValueToValueMapTy DetachCtxToStackFrame; SmallPtrSet<CallBase *, 8> CallsToInline; LoopOutlineProcessor *LOP = nullptr; // Cilk RTS data types StructType *StackFrameTy = nullptr; Loading Loading @@ -66,6 +65,7 @@ class OpenCilkABI : public TapirTarget { Function *Get__cilkrts_enter_frame(); Function *Get__cilkrts_enter_frame_fast(); Function *Get__cilkrts_detach(); Function *Get__cilkrts_save_fp_ctrl_state(); Function *Get__cilkrts_pop_frame(); // Helper functions for implementing the Cilk ABI protocol Loading @@ -73,7 +73,6 @@ class OpenCilkABI : public TapirTarget { Function *GetCilkSyncNoThrowFn(); Function *GetCilkPauseFrameFn(); Function *GetCilkParentEpilogueFn(); void EmitSaveFloatingPointState(IRBuilder<> &B, Value *SF); AllocaInst *CreateStackFrame(Function &F); Value *GetOrCreateCilkStackFrame(Function &F); Loading @@ -92,11 +91,8 @@ class OpenCilkABI : public TapirTarget { public: OpenCilkABI(Module &M); ~OpenCilkABI() { DetachCtxToStackFrame.clear(); if (LOP) delete LOP; } ~OpenCilkABI() { DetachCtxToStackFrame.clear(); } void prepareModule() override final; Value *lowerGrainsizeCall(CallInst *GrainsizeCall) override final; void lowerSync(SyncInst &SI) override final; Loading @@ -106,9 +102,9 @@ public: void addHelperAttributes(Function &F) override final; void preProcessFunction(Function &F, TaskInfo &TI, bool OutliningTapirLoops) override final; void postProcessFunction(Function &F, bool OutliningTapirLoops) override final; bool ProcessingTapirLoops) override final; void postProcessFunction(Function &F, bool ProcessingTapirLoops) override final; void postProcessHelper(Function &F) override final; void preProcessOutlinedTask(Function &F, Instruction *DetachPt, Loading @@ -119,12 +115,12 @@ public: bool IsSpawner) override final; void preProcessRootSpawner(Function &F) override final; void postProcessRootSpawner(Function &F) override final; void processSubTaskCall(TaskOutlineInfo &TOI, DominatorTree &DT) override final; void processSubTaskCall(TaskOutlineInfo &TOI, DominatorTree &DT) override final; LoopOutlineProcessor * getLoopOutlineProcessor(const TapirLoopInfo *TL) override final; }; } // end of llvm namespace } // namespace llvm #endif llvm/lib/Transforms/Tapir/OpenCilkABI.cpp +166 −67 Original line number Diff line number Diff line Loading @@ -12,21 +12,26 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Tapir/OpenCilkABI.h" #include "llvm/IRReader/IRReader.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Verifier.h" #include "llvm/Linker/Linker.h" #include "llvm/Transforms/Tapir/CilkRTSCilkFor.h" #include "llvm/Transforms/Tapir/Outline.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/EscapeEnumerator.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/TapirUtils.h" #include "llvm/Support/Process.h" using namespace llvm; Loading @@ -35,6 +40,14 @@ using namespace llvm; extern cl::opt<bool> DebugABICalls; extern cl::opt<bool> UseExternalABIFunctions; static cl::opt<bool> UseOpenCilkRuntimeBC( "use-opencilk-runtime-bc", cl::init(true), cl::desc("Use a bitcode file for the OpenCilk runtime ABI"), cl::Hidden); static cl::opt<std::string> OpenCilkRuntimeBCPath( "opencilk-runtime-bc-path", cl::init(""), cl::desc("Path to the bitcode file for the OpenCilk runtime ABI"), cl::Hidden); enum { __CILKRTS_ABI_VERSION_OPENCILK = 3 }; Loading Loading @@ -66,13 +79,56 @@ enum { #define CILKRTS_FUNC(name) Get__cilkrts_##name() OpenCilkABI::OpenCilkABI(Module &M) : TapirTarget(M) { OpenCilkABI::OpenCilkABI(Module &M) : TapirTarget(M) {} void OpenCilkABI::prepareModule() { LLVMContext &C = M.getContext(); Type *VoidPtrTy = Type::getInt8PtrTy(C); Type *Int32Ty = Type::getInt32Ty(C); if (UseOpenCilkRuntimeBC) { Optional<std::string> path; if("" == OpenCilkRuntimeBCPath){ path = sys::Process::FindInEnvPath("LD_LIBRARY_PATH", "libopencilk-abi.bc"); assert(path.hasValue() && "Couldn't find OpenCilk runtime bitcode file in LD_LIBRARY_PATH."); } else { path = OpenCilkRuntimeBCPath.getValue(); } LLVM_DEBUG(dbgs() << "Using external bitcode file for OpenCilk ABI: " << OpenCilkRuntimeBCPath << "\n"); SMDiagnostic SMD; // Parse the bitcode file. This call imports structure definitions, but not // function definitions. std::unique_ptr<Module> ExternalModule = parseIRFile(*path, SMD, C); // Strip any debug info from the external module. For convenience, this // Tapir target synthesizes some helper functions, like // __cilk_parent_epilogue, that contain calls to these functions, but don't // necessarily have debug info. As a result, debug info in the external // module causes failures during subsequent inlining. StripDebugInfo(*ExternalModule); // Link the external module into the current module, copying over global // values. // // TODO: Consider restructuring the import process to use // Linker::Flags::LinkOnlyNeeded to copy over only the necessary contents // from the external module. bool Fail = Linker::linkModules(M, std::move(ExternalModule), Linker::Flags::None, [](Module &M, const StringSet<> &GVS) { LLVM_DEBUG({ for (StringRef GVName : GVS.keys()) dbgs() << "Linking global value " << GVName << "\n"; }); }); assert(!Fail && "Failed to link OpenCilk runtime bitcode module.\n"); } // Get or create local definitions of Cilk RTS structure types. const char *StackFrameName = "struct.__cilkrts_stack_frame"; StackFrameTy = StructType::lookupOrCreate(C, StackFrameName); Loading Loading @@ -359,22 +415,6 @@ static Value *LoadSTyField( return L; } /// Emit inline assembly code to save the floating point state, for x86 Only. void OpenCilkABI::EmitSaveFloatingPointState(IRBuilder<> &B, Value *SF) { LLVMContext &C = B.getContext(); if (StackFrameFieldMXCSR >= 0) { FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), {PointerType::getUnqual(Type::getInt32Ty(C))}, false); Value *Asm = InlineAsm::get(FTy, "stmxcsr $0", "*m", /*sideeffects*/ true); Value *Args[1] = { GEP(B, SF, StackFrameFieldMXCSR), }; B.CreateCall(Asm, Args); } } /// Helper to find a function with the given name, creating it if it doesn't /// already exist. Returns false if the function was inserted, indicating that /// the body of the function has yet to be defined. Loading @@ -397,9 +437,7 @@ CallInst *OpenCilkABI::EmitCilkSetJmp(IRBuilder<> &B, Value *SF) { LLVMContext &Ctx = M.getContext(); // We always want to save the floating point state too Triple T(M.getTargetTriple()); if (T.getArch() == Triple::x86 || T.getArch() == Triple::x86_64) EmitSaveFloatingPointState(B, SF); B.CreateCall(CILKRTS_FUNC(save_fp_ctrl_state), SF); Type *Int32Ty = Type::getInt32Ty(Ctx); Type *Int8PtrTy = Type::getInt8PtrTy(Ctx); Loading Loading @@ -449,8 +487,13 @@ Function *OpenCilkABI::Get__cilkrts_pop_frame() { Function *Fn = nullptr; if (GetOrCreateFunction(M, "__cilkrts_pop_frame", FunctionType::get(VoidTy, {StackFramePtrTy}, false), Fn)) Fn)) { Fn->setLinkage(Function::AvailableExternallyLinkage); Fn->setDoesNotThrow(); if (!DebugABICalls && !UseExternalABIFunctions) Fn->addFnAttr(Attribute::AlwaysInline); return Fn; } // Create the body of __cilkrts_pop_frame. const DataLayout &DL = M.getDataLayout(); Loading Loading @@ -520,8 +563,13 @@ Function *OpenCilkABI::Get__cilkrts_detach() { Function *Fn = nullptr; if (GetOrCreateFunction(M, "__cilkrts_detach", FunctionType::get(VoidTy, {StackFramePtrTy}, false), Fn)) Fn)) { Fn->setLinkage(Function::AvailableExternallyLinkage); Fn->setDoesNotThrow(); if (!DebugABICalls && !UseExternalABIFunctions) Fn->addFnAttr(Attribute::AlwaysInline); return Fn; } // Create the body of __cilkrts_detach. const DataLayout &DL = M.getDataLayout(); Loading Loading @@ -581,6 +629,43 @@ Function *OpenCilkABI::Get__cilkrts_detach() { return Fn; } // Call system-dependent function to save floating-point state Function *OpenCilkABI::Get__cilkrts_save_fp_ctrl_state() { LLVMContext &Ctx = M.getContext(); Type *VoidTy = Type::getVoidTy(Ctx); PointerType *StackFramePtrTy = PointerType::getUnqual(StackFrameTy); Function *Fn = nullptr; if (GetOrCreateFunction(M, "__cilkrts_save_fp_ctrl_state", FunctionType::get(VoidTy, {StackFramePtrTy}, false), Fn)) { Fn->setLinkage(Function::AvailableExternallyLinkage); Fn->setDoesNotThrow(); if (!DebugABICalls && !UseExternalABIFunctions) Fn->addFnAttr(Attribute::AlwaysInline); return Fn; } Function::arg_iterator Args = Fn->arg_begin(); Value *SF = &*Args; BasicBlock *Entry = BasicBlock::Create(Ctx, "entry", Fn); IRBuilder<> B(Entry); if (StackFrameFieldMXCSR >= 0) { FunctionType *FTy = FunctionType::get( VoidTy, {PointerType::getUnqual(Type::getInt32Ty(Ctx))}, false); Value *Asm = InlineAsm::get(FTy, "stmxcsr $0", "*m", /*sideeffects*/ true); Value *Args[1] = { GEP(B, SF, StackFrameFieldMXCSR), }; B.CreateCall(Asm, Args); } B.CreateRetVoid(); return Fn; } /// Get or create a LLVM function for __cilk_sync. Calls to this function are /// always inlined, as it saves the current stack/frame pointer values. This /// function must be marked as returns_twice to allow it to be inlined, since Loading Loading @@ -888,10 +973,19 @@ Function *OpenCilkABI::Get__cilkrts_enter_frame() { Type *VoidTy = Type::getVoidTy(Ctx); PointerType *StackFramePtrTy = PointerType::getUnqual(StackFrameTy); Function *Fn = nullptr; // NOTE(TFK): If the function was imported from the opencilk bitcode file // then it will not have the requisite attributes. It is perhaps // better to set these attributes when creating the opencilk bitcode // file... for now I set them here. if (GetOrCreateFunction(M, "__cilkrts_enter_frame", FunctionType::get(VoidTy, {StackFramePtrTy}, false), Fn)) Fn)) { Fn->setLinkage(Function::AvailableExternallyLinkage); Fn->setDoesNotThrow(); if (!DebugABICalls && !UseExternalABIFunctions) Fn->addFnAttr(Attribute::AlwaysInline); return Fn; } // Create the body of __cilkrts_enter_frame. const DataLayout &DL = M.getDataLayout(); Loading Loading @@ -1005,10 +1099,19 @@ Function *OpenCilkABI::Get__cilkrts_enter_frame_fast() { Type *VoidTy = Type::getVoidTy(Ctx); PointerType *StackFramePtrTy = PointerType::getUnqual(StackFrameTy); Function *Fn = nullptr; // NOTE(TFK): If the function was imported from the opencilk bitcode file // then it will not have the requisite attributes. It is perhaps // better to set these attributes when creating the opencilk bitcode // file... for now I set them here. if (GetOrCreateFunction(M, "__cilkrts_enter_frame_fast", FunctionType::get(VoidTy, {StackFramePtrTy}, false), Fn)) Fn)) { Fn->setLinkage(Function::AvailableExternallyLinkage); Fn->setDoesNotThrow(); if (!DebugABICalls && !UseExternalABIFunctions) Fn->addFnAttr(Attribute::AlwaysInline); return Fn; } // Create the body of __cilkrts_enter_frame_fast. const DataLayout &DL = M.getDataLayout(); Loading Loading @@ -1195,15 +1298,15 @@ CallInst *OpenCilkABI::InsertStackFramePush(Function &F, AllocaInst *SF = cast<AllocaInst>(GetOrCreateCilkStackFrame(F)); BasicBlock::iterator InsertPt = ++SF->getIterator(); IRBuilder<> IRB(&(F.getEntryBlock()), InsertPt); IRBuilder<> B(&(F.getEntryBlock()), InsertPt); if (TaskFrameCreate) IRB.SetInsertPoint(TaskFrameCreate); B.SetInsertPoint(TaskFrameCreate); Value *Args[1] = {SF}; if (Helper) return IRB.CreateCall(CILKRTS_FUNC(enter_frame_fast), Args); return B.CreateCall(CILKRTS_FUNC(enter_frame_fast), Args); else return IRB.CreateCall(CILKRTS_FUNC(enter_frame), Args); return B.CreateCall(CILKRTS_FUNC(enter_frame), Args); } void OpenCilkABI::InsertStackFramePop(Function &F, bool PromoteCallsToInvokes, Loading @@ -1215,12 +1318,11 @@ void OpenCilkABI::InsertStackFramePop(Function &F, bool PromoteCallsToInvokes, // Add eh cleanup that returns control to the runtime EscapeEnumerator EE(F, "cilkrabi_cleanup", PromoteCallsToInvokes); while (IRBuilder<> *Builder = EE.Next()) { if (ResumeInst *RI = dyn_cast<ResumeInst>(Builder->GetInsertPoint())) { if (ResumeInst *RI = dyn_cast<ResumeInst>(Builder->GetInsertPoint())) Resumes.insert(RI); } else if (ReturnInst *RI = dyn_cast<ReturnInst>(Builder->GetInsertPoint())) { else if (ReturnInst *RI = dyn_cast<ReturnInst>(Builder->GetInsertPoint())) Returns.insert(RI); } } for (ReturnInst *RI : Returns) { if (Helper) { Loading Loading @@ -1358,7 +1460,7 @@ void OpenCilkABI::preProcessOutlinedTask(Function &F, Instruction *DetachPt, MarkSpawner(F); CallInst *EnterFrame = InsertStackFramePush(F, TaskFrameCreate, /*Helper*/false); InsertStackFramePush(F, TaskFrameCreate, /*Helper*/ true); InsertDetach(F, (DetachPt ? DetachPt : &*(++EnterFrame->getIterator()))); } Loading Loading @@ -1459,17 +1561,14 @@ static inline void inlineCilkFunctions( } void OpenCilkABI::preProcessFunction(Function &F, TaskInfo &TI, bool OutliningTapirLoops) { if (OutliningTapirLoops) bool ProcessingTapirLoops) { if (ProcessingTapirLoops) // Don't do any preprocessing when outlining Tapir loops. return; if (F.getName() == "main") F.setName("cilk_main"); } void OpenCilkABI::postProcessFunction(Function &F, bool OutliningTapirLoops) { if (OutliningTapirLoops) void OpenCilkABI::postProcessFunction(Function &F, bool ProcessingTapirLoops) { if (ProcessingTapirLoops) // Don't do any postprocessing when outlining Tapir loops. return; Loading @@ -1479,9 +1578,9 @@ void OpenCilkABI::postProcessFunction(Function &F, bool OutliningTapirLoops) { void OpenCilkABI::postProcessHelper(Function &F) {} LoopOutlineProcessor * OpenCilkABI::getLoopOutlineProcessor(const TapirLoopInfo *TL) { if (UseRuntimeCilkFor && !LOP) LOP = new RuntimeCilkFor(M); return LOP; LoopOutlineProcessor *OpenCilkABI::getLoopOutlineProcessor( const TapirLoopInfo *TL) { if (UseRuntimeCilkFor) return new RuntimeCilkFor(M); return nullptr; } llvm/lib/Transforms/Tapir/TapirToTarget.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -475,6 +475,8 @@ bool TapirToTargetImpl::run() { if (WorkList.empty()) return false; Target->prepareModule(); bool Changed = false; while (!WorkList.empty()) { // Process the next function. Loading Loading
llvm/include/llvm/Transforms/Tapir/LoweringUtils.h +2 −0 Original line number Diff line number Diff line Loading @@ -253,6 +253,8 @@ public: /// Returns true if Function F should be processed. virtual bool shouldProcessFunction(const Function &F) const; virtual void prepareModule() {} /// Returns true if tasks in Function F should be outlined into their own /// functions. Such outlining is a common step for many Tapir backends. virtual bool shouldDoOutlining(const Function &F) const { return true; } Loading
llvm/include/llvm/Transforms/Tapir/OpenCilkABI.h +9 −13 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ class TapirLoopInfo; class OpenCilkABI : public TapirTarget { ValueToValueMapTy DetachCtxToStackFrame; SmallPtrSet<CallBase *, 8> CallsToInline; LoopOutlineProcessor *LOP = nullptr; // Cilk RTS data types StructType *StackFrameTy = nullptr; Loading Loading @@ -66,6 +65,7 @@ class OpenCilkABI : public TapirTarget { Function *Get__cilkrts_enter_frame(); Function *Get__cilkrts_enter_frame_fast(); Function *Get__cilkrts_detach(); Function *Get__cilkrts_save_fp_ctrl_state(); Function *Get__cilkrts_pop_frame(); // Helper functions for implementing the Cilk ABI protocol Loading @@ -73,7 +73,6 @@ class OpenCilkABI : public TapirTarget { Function *GetCilkSyncNoThrowFn(); Function *GetCilkPauseFrameFn(); Function *GetCilkParentEpilogueFn(); void EmitSaveFloatingPointState(IRBuilder<> &B, Value *SF); AllocaInst *CreateStackFrame(Function &F); Value *GetOrCreateCilkStackFrame(Function &F); Loading @@ -92,11 +91,8 @@ class OpenCilkABI : public TapirTarget { public: OpenCilkABI(Module &M); ~OpenCilkABI() { DetachCtxToStackFrame.clear(); if (LOP) delete LOP; } ~OpenCilkABI() { DetachCtxToStackFrame.clear(); } void prepareModule() override final; Value *lowerGrainsizeCall(CallInst *GrainsizeCall) override final; void lowerSync(SyncInst &SI) override final; Loading @@ -106,9 +102,9 @@ public: void addHelperAttributes(Function &F) override final; void preProcessFunction(Function &F, TaskInfo &TI, bool OutliningTapirLoops) override final; void postProcessFunction(Function &F, bool OutliningTapirLoops) override final; bool ProcessingTapirLoops) override final; void postProcessFunction(Function &F, bool ProcessingTapirLoops) override final; void postProcessHelper(Function &F) override final; void preProcessOutlinedTask(Function &F, Instruction *DetachPt, Loading @@ -119,12 +115,12 @@ public: bool IsSpawner) override final; void preProcessRootSpawner(Function &F) override final; void postProcessRootSpawner(Function &F) override final; void processSubTaskCall(TaskOutlineInfo &TOI, DominatorTree &DT) override final; void processSubTaskCall(TaskOutlineInfo &TOI, DominatorTree &DT) override final; LoopOutlineProcessor * getLoopOutlineProcessor(const TapirLoopInfo *TL) override final; }; } // end of llvm namespace } // namespace llvm #endif
llvm/lib/Transforms/Tapir/OpenCilkABI.cpp +166 −67 Original line number Diff line number Diff line Loading @@ -12,21 +12,26 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Tapir/OpenCilkABI.h" #include "llvm/IRReader/IRReader.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Verifier.h" #include "llvm/Linker/Linker.h" #include "llvm/Transforms/Tapir/CilkRTSCilkFor.h" #include "llvm/Transforms/Tapir/Outline.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/EscapeEnumerator.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/TapirUtils.h" #include "llvm/Support/Process.h" using namespace llvm; Loading @@ -35,6 +40,14 @@ using namespace llvm; extern cl::opt<bool> DebugABICalls; extern cl::opt<bool> UseExternalABIFunctions; static cl::opt<bool> UseOpenCilkRuntimeBC( "use-opencilk-runtime-bc", cl::init(true), cl::desc("Use a bitcode file for the OpenCilk runtime ABI"), cl::Hidden); static cl::opt<std::string> OpenCilkRuntimeBCPath( "opencilk-runtime-bc-path", cl::init(""), cl::desc("Path to the bitcode file for the OpenCilk runtime ABI"), cl::Hidden); enum { __CILKRTS_ABI_VERSION_OPENCILK = 3 }; Loading Loading @@ -66,13 +79,56 @@ enum { #define CILKRTS_FUNC(name) Get__cilkrts_##name() OpenCilkABI::OpenCilkABI(Module &M) : TapirTarget(M) { OpenCilkABI::OpenCilkABI(Module &M) : TapirTarget(M) {} void OpenCilkABI::prepareModule() { LLVMContext &C = M.getContext(); Type *VoidPtrTy = Type::getInt8PtrTy(C); Type *Int32Ty = Type::getInt32Ty(C); if (UseOpenCilkRuntimeBC) { Optional<std::string> path; if("" == OpenCilkRuntimeBCPath){ path = sys::Process::FindInEnvPath("LD_LIBRARY_PATH", "libopencilk-abi.bc"); assert(path.hasValue() && "Couldn't find OpenCilk runtime bitcode file in LD_LIBRARY_PATH."); } else { path = OpenCilkRuntimeBCPath.getValue(); } LLVM_DEBUG(dbgs() << "Using external bitcode file for OpenCilk ABI: " << OpenCilkRuntimeBCPath << "\n"); SMDiagnostic SMD; // Parse the bitcode file. This call imports structure definitions, but not // function definitions. std::unique_ptr<Module> ExternalModule = parseIRFile(*path, SMD, C); // Strip any debug info from the external module. For convenience, this // Tapir target synthesizes some helper functions, like // __cilk_parent_epilogue, that contain calls to these functions, but don't // necessarily have debug info. As a result, debug info in the external // module causes failures during subsequent inlining. StripDebugInfo(*ExternalModule); // Link the external module into the current module, copying over global // values. // // TODO: Consider restructuring the import process to use // Linker::Flags::LinkOnlyNeeded to copy over only the necessary contents // from the external module. bool Fail = Linker::linkModules(M, std::move(ExternalModule), Linker::Flags::None, [](Module &M, const StringSet<> &GVS) { LLVM_DEBUG({ for (StringRef GVName : GVS.keys()) dbgs() << "Linking global value " << GVName << "\n"; }); }); assert(!Fail && "Failed to link OpenCilk runtime bitcode module.\n"); } // Get or create local definitions of Cilk RTS structure types. const char *StackFrameName = "struct.__cilkrts_stack_frame"; StackFrameTy = StructType::lookupOrCreate(C, StackFrameName); Loading Loading @@ -359,22 +415,6 @@ static Value *LoadSTyField( return L; } /// Emit inline assembly code to save the floating point state, for x86 Only. void OpenCilkABI::EmitSaveFloatingPointState(IRBuilder<> &B, Value *SF) { LLVMContext &C = B.getContext(); if (StackFrameFieldMXCSR >= 0) { FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), {PointerType::getUnqual(Type::getInt32Ty(C))}, false); Value *Asm = InlineAsm::get(FTy, "stmxcsr $0", "*m", /*sideeffects*/ true); Value *Args[1] = { GEP(B, SF, StackFrameFieldMXCSR), }; B.CreateCall(Asm, Args); } } /// Helper to find a function with the given name, creating it if it doesn't /// already exist. Returns false if the function was inserted, indicating that /// the body of the function has yet to be defined. Loading @@ -397,9 +437,7 @@ CallInst *OpenCilkABI::EmitCilkSetJmp(IRBuilder<> &B, Value *SF) { LLVMContext &Ctx = M.getContext(); // We always want to save the floating point state too Triple T(M.getTargetTriple()); if (T.getArch() == Triple::x86 || T.getArch() == Triple::x86_64) EmitSaveFloatingPointState(B, SF); B.CreateCall(CILKRTS_FUNC(save_fp_ctrl_state), SF); Type *Int32Ty = Type::getInt32Ty(Ctx); Type *Int8PtrTy = Type::getInt8PtrTy(Ctx); Loading Loading @@ -449,8 +487,13 @@ Function *OpenCilkABI::Get__cilkrts_pop_frame() { Function *Fn = nullptr; if (GetOrCreateFunction(M, "__cilkrts_pop_frame", FunctionType::get(VoidTy, {StackFramePtrTy}, false), Fn)) Fn)) { Fn->setLinkage(Function::AvailableExternallyLinkage); Fn->setDoesNotThrow(); if (!DebugABICalls && !UseExternalABIFunctions) Fn->addFnAttr(Attribute::AlwaysInline); return Fn; } // Create the body of __cilkrts_pop_frame. const DataLayout &DL = M.getDataLayout(); Loading Loading @@ -520,8 +563,13 @@ Function *OpenCilkABI::Get__cilkrts_detach() { Function *Fn = nullptr; if (GetOrCreateFunction(M, "__cilkrts_detach", FunctionType::get(VoidTy, {StackFramePtrTy}, false), Fn)) Fn)) { Fn->setLinkage(Function::AvailableExternallyLinkage); Fn->setDoesNotThrow(); if (!DebugABICalls && !UseExternalABIFunctions) Fn->addFnAttr(Attribute::AlwaysInline); return Fn; } // Create the body of __cilkrts_detach. const DataLayout &DL = M.getDataLayout(); Loading Loading @@ -581,6 +629,43 @@ Function *OpenCilkABI::Get__cilkrts_detach() { return Fn; } // Call system-dependent function to save floating-point state Function *OpenCilkABI::Get__cilkrts_save_fp_ctrl_state() { LLVMContext &Ctx = M.getContext(); Type *VoidTy = Type::getVoidTy(Ctx); PointerType *StackFramePtrTy = PointerType::getUnqual(StackFrameTy); Function *Fn = nullptr; if (GetOrCreateFunction(M, "__cilkrts_save_fp_ctrl_state", FunctionType::get(VoidTy, {StackFramePtrTy}, false), Fn)) { Fn->setLinkage(Function::AvailableExternallyLinkage); Fn->setDoesNotThrow(); if (!DebugABICalls && !UseExternalABIFunctions) Fn->addFnAttr(Attribute::AlwaysInline); return Fn; } Function::arg_iterator Args = Fn->arg_begin(); Value *SF = &*Args; BasicBlock *Entry = BasicBlock::Create(Ctx, "entry", Fn); IRBuilder<> B(Entry); if (StackFrameFieldMXCSR >= 0) { FunctionType *FTy = FunctionType::get( VoidTy, {PointerType::getUnqual(Type::getInt32Ty(Ctx))}, false); Value *Asm = InlineAsm::get(FTy, "stmxcsr $0", "*m", /*sideeffects*/ true); Value *Args[1] = { GEP(B, SF, StackFrameFieldMXCSR), }; B.CreateCall(Asm, Args); } B.CreateRetVoid(); return Fn; } /// Get or create a LLVM function for __cilk_sync. Calls to this function are /// always inlined, as it saves the current stack/frame pointer values. This /// function must be marked as returns_twice to allow it to be inlined, since Loading Loading @@ -888,10 +973,19 @@ Function *OpenCilkABI::Get__cilkrts_enter_frame() { Type *VoidTy = Type::getVoidTy(Ctx); PointerType *StackFramePtrTy = PointerType::getUnqual(StackFrameTy); Function *Fn = nullptr; // NOTE(TFK): If the function was imported from the opencilk bitcode file // then it will not have the requisite attributes. It is perhaps // better to set these attributes when creating the opencilk bitcode // file... for now I set them here. if (GetOrCreateFunction(M, "__cilkrts_enter_frame", FunctionType::get(VoidTy, {StackFramePtrTy}, false), Fn)) Fn)) { Fn->setLinkage(Function::AvailableExternallyLinkage); Fn->setDoesNotThrow(); if (!DebugABICalls && !UseExternalABIFunctions) Fn->addFnAttr(Attribute::AlwaysInline); return Fn; } // Create the body of __cilkrts_enter_frame. const DataLayout &DL = M.getDataLayout(); Loading Loading @@ -1005,10 +1099,19 @@ Function *OpenCilkABI::Get__cilkrts_enter_frame_fast() { Type *VoidTy = Type::getVoidTy(Ctx); PointerType *StackFramePtrTy = PointerType::getUnqual(StackFrameTy); Function *Fn = nullptr; // NOTE(TFK): If the function was imported from the opencilk bitcode file // then it will not have the requisite attributes. It is perhaps // better to set these attributes when creating the opencilk bitcode // file... for now I set them here. if (GetOrCreateFunction(M, "__cilkrts_enter_frame_fast", FunctionType::get(VoidTy, {StackFramePtrTy}, false), Fn)) Fn)) { Fn->setLinkage(Function::AvailableExternallyLinkage); Fn->setDoesNotThrow(); if (!DebugABICalls && !UseExternalABIFunctions) Fn->addFnAttr(Attribute::AlwaysInline); return Fn; } // Create the body of __cilkrts_enter_frame_fast. const DataLayout &DL = M.getDataLayout(); Loading Loading @@ -1195,15 +1298,15 @@ CallInst *OpenCilkABI::InsertStackFramePush(Function &F, AllocaInst *SF = cast<AllocaInst>(GetOrCreateCilkStackFrame(F)); BasicBlock::iterator InsertPt = ++SF->getIterator(); IRBuilder<> IRB(&(F.getEntryBlock()), InsertPt); IRBuilder<> B(&(F.getEntryBlock()), InsertPt); if (TaskFrameCreate) IRB.SetInsertPoint(TaskFrameCreate); B.SetInsertPoint(TaskFrameCreate); Value *Args[1] = {SF}; if (Helper) return IRB.CreateCall(CILKRTS_FUNC(enter_frame_fast), Args); return B.CreateCall(CILKRTS_FUNC(enter_frame_fast), Args); else return IRB.CreateCall(CILKRTS_FUNC(enter_frame), Args); return B.CreateCall(CILKRTS_FUNC(enter_frame), Args); } void OpenCilkABI::InsertStackFramePop(Function &F, bool PromoteCallsToInvokes, Loading @@ -1215,12 +1318,11 @@ void OpenCilkABI::InsertStackFramePop(Function &F, bool PromoteCallsToInvokes, // Add eh cleanup that returns control to the runtime EscapeEnumerator EE(F, "cilkrabi_cleanup", PromoteCallsToInvokes); while (IRBuilder<> *Builder = EE.Next()) { if (ResumeInst *RI = dyn_cast<ResumeInst>(Builder->GetInsertPoint())) { if (ResumeInst *RI = dyn_cast<ResumeInst>(Builder->GetInsertPoint())) Resumes.insert(RI); } else if (ReturnInst *RI = dyn_cast<ReturnInst>(Builder->GetInsertPoint())) { else if (ReturnInst *RI = dyn_cast<ReturnInst>(Builder->GetInsertPoint())) Returns.insert(RI); } } for (ReturnInst *RI : Returns) { if (Helper) { Loading Loading @@ -1358,7 +1460,7 @@ void OpenCilkABI::preProcessOutlinedTask(Function &F, Instruction *DetachPt, MarkSpawner(F); CallInst *EnterFrame = InsertStackFramePush(F, TaskFrameCreate, /*Helper*/false); InsertStackFramePush(F, TaskFrameCreate, /*Helper*/ true); InsertDetach(F, (DetachPt ? DetachPt : &*(++EnterFrame->getIterator()))); } Loading Loading @@ -1459,17 +1561,14 @@ static inline void inlineCilkFunctions( } void OpenCilkABI::preProcessFunction(Function &F, TaskInfo &TI, bool OutliningTapirLoops) { if (OutliningTapirLoops) bool ProcessingTapirLoops) { if (ProcessingTapirLoops) // Don't do any preprocessing when outlining Tapir loops. return; if (F.getName() == "main") F.setName("cilk_main"); } void OpenCilkABI::postProcessFunction(Function &F, bool OutliningTapirLoops) { if (OutliningTapirLoops) void OpenCilkABI::postProcessFunction(Function &F, bool ProcessingTapirLoops) { if (ProcessingTapirLoops) // Don't do any postprocessing when outlining Tapir loops. return; Loading @@ -1479,9 +1578,9 @@ void OpenCilkABI::postProcessFunction(Function &F, bool OutliningTapirLoops) { void OpenCilkABI::postProcessHelper(Function &F) {} LoopOutlineProcessor * OpenCilkABI::getLoopOutlineProcessor(const TapirLoopInfo *TL) { if (UseRuntimeCilkFor && !LOP) LOP = new RuntimeCilkFor(M); return LOP; LoopOutlineProcessor *OpenCilkABI::getLoopOutlineProcessor( const TapirLoopInfo *TL) { if (UseRuntimeCilkFor) return new RuntimeCilkFor(M); return nullptr; }
llvm/lib/Transforms/Tapir/TapirToTarget.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -475,6 +475,8 @@ bool TapirToTargetImpl::run() { if (WorkList.empty()) return false; Target->prepareModule(); bool Changed = false; while (!WorkList.empty()) { // Process the next function. Loading