summaryrefslogtreecommitdiffstats
path: root/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ExecutionEngine/Orc/Speculation.cpp')
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Speculation.cpp135
1 files changed, 92 insertions, 43 deletions
diff --git a/llvm/lib/ExecutionEngine/Orc/Speculation.cpp b/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
index 5ab583124fe..4f2ea92706c 100644
--- a/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/Speculation.h"
-
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
@@ -17,6 +16,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Verifier.h"
+#include "llvm/Support/Debug.h"
#include <vector>
@@ -36,11 +36,28 @@ void ImplSymbolMap::trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD) {
}
}
+// Trigger Speculative Compiles.
+void Speculator::speculateForEntryPoint(Speculator *Ptr, uint64_t StubId) {
+ assert(Ptr && " Null Address Received in orc_speculate_for ");
+ Ptr->speculateFor(StubId);
+}
+
+Error Speculator::addSpeculationRuntime(JITDylib &JD,
+ MangleAndInterner &Mangle) {
+ JITEvaluatedSymbol ThisPtr(pointerToJITTargetAddress(this),
+ JITSymbolFlags::Exported);
+ JITEvaluatedSymbol SpeculateForEntryPtr(
+ pointerToJITTargetAddress(&speculateForEntryPoint),
+ JITSymbolFlags::Exported);
+ return JD.define(absoluteSymbols({
+ {Mangle("__orc_speculator"), ThisPtr}, // Data Symbol
+ {Mangle("__orc_speculate_for"), SpeculateForEntryPtr} // Callable Symbol
+ }));
+}
+
// If two modules, share the same LLVMContext, different threads must
-// not access those modules concurrently, doing so leave the
-// LLVMContext in in-consistent state.
-// But here since each TSM has a unique Context associated with it,
-// on locking is necessary!
+// not access them concurrently without locking the associated LLVMContext
+// this implementation follows this contract.
void IRSpeculationLayer::emit(MaterializationResponsibility R,
ThreadSafeModule TSM) {
@@ -48,50 +65,82 @@ void IRSpeculationLayer::emit(MaterializationResponsibility R,
assert(TSM.getContext().getContext() != nullptr &&
"Module with null LLVMContext?");
- // Instrumentation of runtime calls
- auto &InContext = *TSM.getContext().getContext();
- auto SpeculatorVTy = StructType::create(InContext, "Class.Speculator");
- auto RuntimeCallTy = FunctionType::get(
- Type::getVoidTy(InContext),
- {SpeculatorVTy->getPointerTo(), Type::getInt64Ty(InContext)}, false);
- auto RuntimeCall =
- Function::Create(RuntimeCallTy, Function::LinkageTypes::ExternalLinkage,
- "__orc_speculate_for", TSM.getModuleUnlocked());
- auto SpeclAddr = new GlobalVariable(
- *TSM.getModuleUnlocked(), SpeculatorVTy, false,
- GlobalValue::LinkageTypes::ExternalLinkage, nullptr, "__orc_speculator");
-
- IRBuilder<> Mutator(InContext);
-
- // QueryAnalysis allowed to transform the IR source, one such example is
- // Simplify CFG helps the static branch prediction heuristics!
- for (auto &Fn : TSM.getModuleUnlocked()->getFunctionList()) {
- if (!Fn.isDeclaration()) {
- auto IRNames = QueryAnalysis(Fn, FAM);
- // Instrument and register if Query has result
- if (IRNames.hasValue()) {
- Mutator.SetInsertPoint(&(Fn.getEntryBlock().front()));
- auto ImplAddrToUint =
- Mutator.CreatePtrToInt(&Fn, Type::getInt64Ty(InContext));
- Mutator.CreateCall(RuntimeCallTy, RuntimeCall,
- {SpeclAddr, ImplAddrToUint});
- S.registerSymbols(internToJITSymbols(IRNames.getValue()),
- &R.getTargetJITDylib());
+ // Instrumentation of runtime calls, lock the Module
+ TSM.withModuleDo([this, &R](Module &M) {
+ auto &MContext = M.getContext();
+ auto SpeculatorVTy = StructType::create(MContext, "Class.Speculator");
+ auto RuntimeCallTy = FunctionType::get(
+ Type::getVoidTy(MContext),
+ {SpeculatorVTy->getPointerTo(), Type::getInt64Ty(MContext)}, false);
+ auto RuntimeCall =
+ Function::Create(RuntimeCallTy, Function::LinkageTypes::ExternalLinkage,
+ "__orc_speculate_for", &M);
+ auto SpeclAddr = new GlobalVariable(
+ M, SpeculatorVTy, false, GlobalValue::LinkageTypes::ExternalLinkage,
+ nullptr, "__orc_speculator");
+
+ IRBuilder<> Mutator(MContext);
+
+ // QueryAnalysis allowed to transform the IR source, one such example is
+ // Simplify CFG helps the static branch prediction heuristics!
+ for (auto &Fn : M.getFunctionList()) {
+ if (!Fn.isDeclaration()) {
+
+ auto IRNames = QueryAnalysis(Fn);
+ // Instrument and register if Query has result
+ if (IRNames.hasValue()) {
+
+ // Emit globals for each function.
+ auto LoadValueTy = Type::getInt8Ty(MContext);
+ auto SpeculatorGuard = new GlobalVariable(
+ M, LoadValueTy, false, GlobalValue::LinkageTypes::InternalLinkage,
+ ConstantInt::get(LoadValueTy, 0),
+ "__orc_speculate.guard.for." + Fn.getName());
+ SpeculatorGuard->setAlignment(1);
+ SpeculatorGuard->setUnnamedAddr(GlobalValue::UnnamedAddr::Local);
+
+ BasicBlock &ProgramEntry = Fn.getEntryBlock();
+ // Create BasicBlocks before the program's entry basicblock
+ BasicBlock *SpeculateBlock = BasicBlock::Create(
+ MContext, "__orc_speculate.block", &Fn, &ProgramEntry);
+ BasicBlock *SpeculateDecisionBlock = BasicBlock::Create(
+ MContext, "__orc_speculate.decision.block", &Fn, SpeculateBlock);
+
+ assert(SpeculateDecisionBlock == &Fn.getEntryBlock() &&
+ "SpeculateDecisionBlock not updated?");
+ Mutator.SetInsertPoint(SpeculateDecisionBlock);
+
+ auto LoadGuard =
+ Mutator.CreateLoad(LoadValueTy, SpeculatorGuard, "guard.value");
+ // if just loaded value equal to 0,return true.
+ auto CanSpeculate =
+ Mutator.CreateICmpEQ(LoadGuard, ConstantInt::get(LoadValueTy, 0),
+ "compare.to.speculate");
+ Mutator.CreateCondBr(CanSpeculate, SpeculateBlock, &ProgramEntry);
+
+ Mutator.SetInsertPoint(SpeculateBlock);
+ auto ImplAddrToUint =
+ Mutator.CreatePtrToInt(&Fn, Type::getInt64Ty(MContext));
+ Mutator.CreateCall(RuntimeCallTy, RuntimeCall,
+ {SpeclAddr, ImplAddrToUint});
+ Mutator.CreateStore(ConstantInt::get(LoadValueTy, 1),
+ SpeculatorGuard);
+ Mutator.CreateBr(&ProgramEntry);
+
+ assert(Mutator.GetInsertBlock()->getParent() == &Fn &&
+ "IR builder association mismatch?");
+ S.registerSymbols(internToJITSymbols(IRNames.getValue()),
+ &R.getTargetJITDylib());
+ }
}
}
- }
- // No locking needed read only operation.
- assert(!(verifyModule(*TSM.getModuleUnlocked())) &&
+ });
+
+ assert(!TSM.withModuleDo([](const Module &M) { return verifyModule(M); }) &&
"Speculation Instrumentation breaks IR?");
NextLayer.emit(std::move(R), std::move(TSM));
}
-// Runtime Function Implementation
-extern "C" void __orc_speculate_for(Speculator *Ptr, uint64_t StubId) {
- assert(Ptr && " Null Address Received in orc_speculate_for ");
- Ptr->speculateFor(StubId);
-}
-
} // namespace orc
} // namespace llvm
OpenPOWER on IntegriCloud