LLVM  14.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 #include "llvm/IR/BasicBlock.h"
11 #include "llvm/IR/Function.h"
12 #include "llvm/IR/IRBuilder.h"
13 #include "llvm/IR/Instruction.h"
14 #include "llvm/IR/Instructions.h"
15 #include "llvm/IR/LLVMContext.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/IR/Type.h"
18 #include "llvm/IR/Verifier.h"
19 
20 namespace llvm {
21 
22 namespace orc {
23 
24 // ImplSymbolMap methods
26  assert(SrcJD && "Tracking on Null Source .impl dylib");
27  std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
28  for (auto &I : ImplMaps) {
29  auto It = Maps.insert({I.first, {I.second.Aliasee, SrcJD}});
30  // check rationale when independent dylibs have same symbol name?
31  assert(It.second && "ImplSymbols are already tracked for this Symbol?");
32  (void)(It);
33  }
34 }
35 
36 // Trigger Speculative Compiles.
37 void Speculator::speculateForEntryPoint(Speculator *Ptr, uint64_t StubId) {
38  assert(Ptr && " Null Address Received in orc_speculate_for ");
39  Ptr->speculateFor(StubId);
40 }
41 
43  MangleAndInterner &Mangle) {
46  JITEvaluatedSymbol SpeculateForEntryPtr(
47  pointerToJITTargetAddress(&speculateForEntryPoint),
49  return JD.define(absoluteSymbols({
50  {Mangle("__orc_speculator"), ThisPtr}, // Data Symbol
51  {Mangle("__orc_speculate_for"), SpeculateForEntryPtr} // Callable Symbol
52  }));
53 }
54 
55 // If two modules, share the same LLVMContext, different threads must
56 // not access them concurrently without locking the associated LLVMContext
57 // this implementation follows this contract.
58 void IRSpeculationLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
59  ThreadSafeModule TSM) {
60 
61  assert(TSM && "Speculation Layer received Null Module ?");
62  assert(TSM.getContext().getContext() != nullptr &&
63  "Module with null LLVMContext?");
64 
65  // Instrumentation of runtime calls, lock the Module
66  TSM.withModuleDo([this, &R](Module &M) {
67  auto &MContext = M.getContext();
68  auto SpeculatorVTy = StructType::create(MContext, "Class.Speculator");
69  auto RuntimeCallTy = FunctionType::get(
70  Type::getVoidTy(MContext),
71  {SpeculatorVTy->getPointerTo(), Type::getInt64Ty(MContext)}, false);
72  auto RuntimeCall =
73  Function::Create(RuntimeCallTy, Function::LinkageTypes::ExternalLinkage,
74  "__orc_speculate_for", &M);
75  auto SpeclAddr = new GlobalVariable(
76  M, SpeculatorVTy, false, GlobalValue::LinkageTypes::ExternalLinkage,
77  nullptr, "__orc_speculator");
78 
79  IRBuilder<> Mutator(MContext);
80 
81  // QueryAnalysis allowed to transform the IR source, one such example is
82  // Simplify CFG helps the static branch prediction heuristics!
83  for (auto &Fn : M.getFunctionList()) {
84  if (!Fn.isDeclaration()) {
85 
86  auto IRNames = QueryAnalysis(Fn);
87  // Instrument and register if Query has result
88  if (IRNames.hasValue()) {
89 
90  // Emit globals for each function.
91  auto LoadValueTy = Type::getInt8Ty(MContext);
92  auto SpeculatorGuard = new GlobalVariable(
93  M, LoadValueTy, false, GlobalValue::LinkageTypes::InternalLinkage,
94  ConstantInt::get(LoadValueTy, 0),
95  "__orc_speculate.guard.for." + Fn.getName());
96  SpeculatorGuard->setAlignment(Align(1));
97  SpeculatorGuard->setUnnamedAddr(GlobalValue::UnnamedAddr::Local);
98 
99  BasicBlock &ProgramEntry = Fn.getEntryBlock();
100  // Create BasicBlocks before the program's entry basicblock
101  BasicBlock *SpeculateBlock = BasicBlock::Create(
102  MContext, "__orc_speculate.block", &Fn, &ProgramEntry);
103  BasicBlock *SpeculateDecisionBlock = BasicBlock::Create(
104  MContext, "__orc_speculate.decision.block", &Fn, SpeculateBlock);
105 
106  assert(SpeculateDecisionBlock == &Fn.getEntryBlock() &&
107  "SpeculateDecisionBlock not updated?");
108  Mutator.SetInsertPoint(SpeculateDecisionBlock);
109 
110  auto LoadGuard =
111  Mutator.CreateLoad(LoadValueTy, SpeculatorGuard, "guard.value");
112  // if just loaded value equal to 0,return true.
113  auto CanSpeculate =
114  Mutator.CreateICmpEQ(LoadGuard, ConstantInt::get(LoadValueTy, 0),
115  "compare.to.speculate");
116  Mutator.CreateCondBr(CanSpeculate, SpeculateBlock, &ProgramEntry);
117 
118  Mutator.SetInsertPoint(SpeculateBlock);
119  auto ImplAddrToUint =
120  Mutator.CreatePtrToInt(&Fn, Type::getInt64Ty(MContext));
121  Mutator.CreateCall(RuntimeCallTy, RuntimeCall,
122  {SpeclAddr, ImplAddrToUint});
123  Mutator.CreateStore(ConstantInt::get(LoadValueTy, 1),
124  SpeculatorGuard);
125  Mutator.CreateBr(&ProgramEntry);
126 
127  assert(Mutator.GetInsertBlock()->getParent() == &Fn &&
128  "IR builder association mismatch?");
129  S.registerSymbols(internToJITSymbols(IRNames.getValue()),
130  &R->getTargetJITDylib());
131  }
132  }
133  }
134  });
135 
136  assert(!TSM.withModuleDo([](const Module &M) { return verifyModule(M); }) &&
137  "Speculation Instrumentation breaks IR?");
138 
139  NextLayer.emit(std::move(R), std::move(TSM));
140 }
141 
142 } // namespace orc
143 } // namespace llvm
llvm::IRBuilderBase::CreateStore
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition: IRBuilder.h:1699
llvm::IRBuilderBase::SetInsertPoint
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition: IRBuilder.h:184
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
llvm::orc::JITDylib
A symbol table that supports asynchoronous symbol queries.
Definition: Core.h:922
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
Speculation.h
llvm::BasicBlock::getParent
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:107
llvm::orc::Speculator::speculateFor
void speculateFor(TargetFAddr StubAddr)
Definition: Speculation.h:137
llvm::IRBuilderBase::CreatePtrToInt
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:2107
llvm::IRBuilder<>
llvm::GlobalVariable
Definition: GlobalVariable.h:40
llvm::FunctionType::get
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:363
llvm::IRBuilderBase::CreateBr
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
Definition: IRBuilder.h:989
Module.h
llvm::orc::ThreadSafeModule::getContext
ThreadSafeContext getContext() const
Returns the context for this ThreadSafeModule.
Definition: ThreadSafeModule.h:153
llvm::StructType::create
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition: Type.cpp:515
llvm::orc::IRCompileLayer::emit
void emit(std::unique_ptr< MaterializationResponsibility > R, ThreadSafeModule TSM) override
Emit should materialize the given IR.
Definition: IRCompileLayer.cpp:28
llvm::Type::getInt8Ty
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:239
llvm::JITEvaluatedSymbol
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:229
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
Instruction.h
llvm::GlobalValue::UnnamedAddr::Local
@ Local
llvm::IRBuilderBase::CreateLoad
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:1660
llvm::orc::Speculator::addSpeculationRuntime
Error addSpeculationRuntime(JITDylib &JD, MangleAndInterner &Mangle)
Define symbols for this Speculator object (__orc_speculator) and the speculation runtime entry point ...
Definition: Speculation.cpp:42
llvm::orc::Speculator
Definition: Speculation.h:61
llvm::ConstantInt::get
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:925
Align
uint64_t Align
Definition: ELFObjHandler.cpp:83
Type.h
BasicBlock.h
llvm::orc::ThreadSafeContext::getContext
LLVMContext * getContext()
Returns a pointer to the LLVMContext that was used to construct this instance, or null if the instanc...
Definition: ThreadSafeModule.h:61
uint64_t
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::DenseMap< SymbolStringPtr, SymbolAliasMapEntry >
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::Function::Create
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:139
IRBuilder.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::orc::Speculator::registerSymbols
void registerSymbols(FunctionCandidatesMap Candidates, JITDylib *JD)
Definition: Speculation.h:140
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::orc::ThreadSafeModule::withModuleDo
decltype(auto) withModuleDo(Func &&F)
Locks the associated ThreadSafeContext and calls the given function on the contained Module.
Definition: ThreadSafeModule.h:133
llvm::IRBuilderBase::CreateICmpEQ
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2231
llvm::BasicBlock::Create
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:100
llvm::IRBuilderBase::CreateCondBr
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:995
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
llvm::DenseMapBase::insert
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:207
llvm::pointerToJITTargetAddress
JITTargetAddress pointerToJITTargetAddress(T *Ptr)
Convert a pointer to a JITTargetAddress.
Definition: JITSymbol.h:69
llvm::orc::MangleAndInterner
Mangles symbol names then uniques them in the context of an ExecutionSession.
Definition: Mangling.h:26
llvm::orc::ImplSymbolMap::trackImpls
void trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD)
Definition: Speculation.cpp:25
Verifier.h
llvm::Type::getInt64Ty
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:242
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::IRBuilderBase::GetInsertBlock
BasicBlock * GetInsertBlock() const
Definition: IRBuilder.h:178
Function.h
llvm::Type::getPointerTo
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:776
llvm::orc::absoluteSymbols
std::unique_ptr< AbsoluteSymbolsMaterializationUnit > absoluteSymbols(SymbolMap Symbols)
Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
Definition: Core.h:747
llvm::Type::getVoidTy
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:224
Instructions.h
llvm::orc::JITDylib::define
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:1698
llvm::orc::ThreadSafeModule
An LLVM Module together with a shared ThreadSafeContext.
Definition: ThreadSafeModule.h:77
LLVMContext.h
llvm::orc::IRSpeculationLayer::emit
void emit(std::unique_ptr< MaterializationResponsibility > R, ThreadSafeModule TSM) override
Emit should materialize the given IR.
Definition: Speculation.cpp:58
llvm::IRBuilderBase::CreateCall
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2395
llvm::JITSymbolFlags::Exported
@ Exported
Definition: JITSymbol.h:85