LLVM 20.0.0git
Speculation.cpp
Go to the documentation of this file.
1//===---------- speculation.cpp - Utilities for Speculation ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
12#include "llvm/IR/BasicBlock.h"
13#include "llvm/IR/Function.h"
14#include "llvm/IR/IRBuilder.h"
15#include "llvm/IR/Instruction.h"
17#include "llvm/IR/LLVMContext.h"
18#include "llvm/IR/Module.h"
19#include "llvm/IR/Type.h"
20#include "llvm/IR/Verifier.h"
21
22namespace llvm {
23
24namespace orc {
25
26// ImplSymbolMap methods
28 assert(SrcJD && "Tracking on Null Source .impl dylib");
29 std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
30 for (auto &I : ImplMaps) {
31 auto It = Maps.insert({I.first, {I.second.Aliasee, SrcJD}});
32 // check rationale when independent dylibs have same symbol name?
33 assert(It.second && "ImplSymbols are already tracked for this Symbol?");
34 (void)(It);
35 }
36}
37
38// Trigger Speculative Compiles.
39void Speculator::speculateForEntryPoint(Speculator *Ptr, uint64_t StubId) {
40 assert(Ptr && " Null Address Received in orc_speculate_for ");
41 Ptr->speculateFor(ExecutorAddr(StubId));
42}
43
45 MangleAndInterner &Mangle) {
48 ExecutorSymbolDef SpeculateForEntryPtr(
49 ExecutorAddr::fromPtr(&speculateForEntryPoint), JITSymbolFlags::Exported);
50 return JD.define(absoluteSymbols({
51 {Mangle("__orc_speculator"), ThisPtr}, // Data Symbol
52 {Mangle("__orc_speculate_for"), SpeculateForEntryPtr} // Callable Symbol
53 }));
54}
55
56// If two modules, share the same LLVMContext, different threads must
57// not access them concurrently without locking the associated LLVMContext
58// this implementation follows this contract.
59void IRSpeculationLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
60 ThreadSafeModule TSM) {
61
62 assert(TSM && "Speculation Layer received Null Module ?");
63 assert(TSM.getContext().getContext() != nullptr &&
64 "Module with null LLVMContext?");
65
66 // Instrumentation of runtime calls, lock the Module
67 TSM.withModuleDo([this, &R](Module &M) {
68 auto &MContext = M.getContext();
69 auto SpeculatorVTy = StructType::create(MContext, "Class.Speculator");
70 auto RuntimeCallTy = FunctionType::get(
71 Type::getVoidTy(MContext),
72 {PointerType::getUnqual(MContext), Type::getInt64Ty(MContext)}, false);
73 auto RuntimeCall =
75 "__orc_speculate_for", &M);
76 auto SpeclAddr = new GlobalVariable(
77 M, SpeculatorVTy, false, GlobalValue::LinkageTypes::ExternalLinkage,
78 nullptr, "__orc_speculator");
79
80 IRBuilder<> Mutator(MContext);
81
82 // QueryAnalysis allowed to transform the IR source, one such example is
83 // Simplify CFG helps the static branch prediction heuristics!
84 for (auto &Fn : M.getFunctionList()) {
85 if (!Fn.isDeclaration()) {
86
87 auto IRNames = QueryAnalysis(Fn);
88 // Instrument and register if Query has result
89 if (IRNames) {
90
91 // Emit globals for each function.
92 auto LoadValueTy = Type::getInt8Ty(MContext);
93 auto SpeculatorGuard = new GlobalVariable(
94 M, LoadValueTy, false, GlobalValue::LinkageTypes::InternalLinkage,
95 ConstantInt::get(LoadValueTy, 0),
96 "__orc_speculate.guard.for." + Fn.getName());
97 SpeculatorGuard->setAlignment(Align(1));
98 SpeculatorGuard->setUnnamedAddr(GlobalValue::UnnamedAddr::Local);
99
100 BasicBlock &ProgramEntry = Fn.getEntryBlock();
101 // Create BasicBlocks before the program's entry basicblock
102 BasicBlock *SpeculateBlock = BasicBlock::Create(
103 MContext, "__orc_speculate.block", &Fn, &ProgramEntry);
104 BasicBlock *SpeculateDecisionBlock = BasicBlock::Create(
105 MContext, "__orc_speculate.decision.block", &Fn, SpeculateBlock);
106
107 assert(SpeculateDecisionBlock == &Fn.getEntryBlock() &&
108 "SpeculateDecisionBlock not updated?");
109 Mutator.SetInsertPoint(SpeculateDecisionBlock);
110
111 auto LoadGuard =
112 Mutator.CreateLoad(LoadValueTy, SpeculatorGuard, "guard.value");
113 // if just loaded value equal to 0,return true.
114 auto CanSpeculate =
115 Mutator.CreateICmpEQ(LoadGuard, ConstantInt::get(LoadValueTy, 0),
116 "compare.to.speculate");
117 Mutator.CreateCondBr(CanSpeculate, SpeculateBlock, &ProgramEntry);
118
119 Mutator.SetInsertPoint(SpeculateBlock);
120 auto ImplAddrToUint =
121 Mutator.CreatePtrToInt(&Fn, Type::getInt64Ty(MContext));
122 Mutator.CreateCall(RuntimeCallTy, RuntimeCall,
123 {SpeclAddr, ImplAddrToUint});
124 Mutator.CreateStore(ConstantInt::get(LoadValueTy, 1),
125 SpeculatorGuard);
126 Mutator.CreateBr(&ProgramEntry);
127
128 assert(Mutator.GetInsertBlock()->getParent() == &Fn &&
129 "IR builder association mismatch?");
130 S.registerSymbols(internToJITSymbols(*IRNames),
131 &R->getTargetJITDylib());
132 }
133 }
134 }
135 });
136
137 assert(!TSM.withModuleDo([](const Module &M) { return verifyModule(M); }) &&
138 "Speculation Instrumentation breaks IR?");
139
140 NextLayer.emit(std::move(R), std::move(TSM));
141}
142
143} // namespace orc
144} // namespace llvm
Module.h This file contains the declarations for the Module class.
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:212
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:219
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:211
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:173
@ InternalLinkage
Rename collisions when linking (static functions).
Definition: GlobalValue.h:59
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:52
BasicBlock * GetInsertBlock() const
Definition: IRBuilder.h:171
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2273
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
Definition: IRBuilder.h:1144
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition: IRBuilder.h:1813
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition: IRBuilder.h:1826
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2145
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2444
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
Definition: IRBuilder.h:1138
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition: IRBuilder.h:177
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2697
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Definition: DerivedTypes.h:686
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition: Type.cpp:612
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt8Ty(LLVMContext &C)
static IntegerType * getInt64Ty(LLVMContext &C)
Represents an address in the executor process.
static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap=UnwrapFn())
Create an ExecutorAddr from the given pointer.
Represents a defining location for a JIT symbol.
virtual void emit(std::unique_ptr< MaterializationResponsibility > R, ThreadSafeModule TSM)=0
Emit should materialize the given IR.
void emit(std::unique_ptr< MaterializationResponsibility > R, ThreadSafeModule TSM) override
Emit should materialize the given IR.
Definition: Speculation.cpp:59
void trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD)
Definition: Speculation.cpp:27
Represents a JIT'd dynamic library.
Definition: Core.h:897
Error define(std::unique_ptr< MaterializationUnitType > &&MU, ResourceTrackerSP RT=nullptr)
Define all symbols provided by the materialization unit to be part of this JITDylib.
Definition: Core.h:1822
Mangles symbol names then uniques them in the context of an ExecutionSession.
Definition: Mangling.h:26
Error addSpeculationRuntime(JITDylib &JD, MangleAndInterner &Mangle)
Define symbols for this Speculator object (__orc_speculator) and the speculation runtime entry point ...
Definition: Speculation.cpp:44
void registerSymbols(FunctionCandidatesMap Candidates, JITDylib *JD)
Definition: Speculation.h:139
LLVMContext * getContext()
Returns a pointer to the LLVMContext that was used to construct this instance, or null if the instanc...
An LLVM Module together with a shared ThreadSafeContext.
ThreadSafeContext getContext() const
Returns the context for this ThreadSafeModule.
decltype(auto) withModuleDo(Func &&F)
Locks the associated ThreadSafeContext and calls the given function on the contained Module.
std::unique_ptr< AbsoluteSymbolsMaterializationUnit > absoluteSymbols(SymbolMap Symbols)
Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39