LLVM  10.0.0svn
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 #include "llvm/Support/Debug.h"
20 
21 #include <vector>
22 
23 namespace llvm {
24 
25 namespace orc {
26 
27 // ImplSymbolMap methods
29  assert(SrcJD && "Tracking on Null Source .impl dylib");
30  std::lock_guard<std::mutex> Lockit(ConcurrentAccess);
31  for (auto &I : ImplMaps) {
32  auto It = Maps.insert({I.first, {I.second.Aliasee, SrcJD}});
33  // check rationale when independent dylibs have same symbol name?
34  assert(It.second && "ImplSymbols are already tracked for this Symbol?");
35  (void)(It);
36  }
37 }
38 
39 // Trigger Speculative Compiles.
40 void Speculator::speculateForEntryPoint(Speculator *Ptr, uint64_t StubId) {
41  assert(Ptr && " Null Address Received in orc_speculate_for ");
42  Ptr->speculateFor(StubId);
43 }
44 
46  MangleAndInterner &Mangle) {
49  JITEvaluatedSymbol SpeculateForEntryPtr(
50  pointerToJITTargetAddress(&speculateForEntryPoint),
52  return JD.define(absoluteSymbols({
53  {Mangle("__orc_speculator"), ThisPtr}, // Data Symbol
54  {Mangle("__orc_speculate_for"), SpeculateForEntryPtr} // Callable Symbol
55  }));
56 }
57 
58 // If two modules, share the same LLVMContext, different threads must
59 // not access them concurrently without locking the associated LLVMContext
60 // this implementation follows this contract.
62  ThreadSafeModule TSM) {
63 
64  assert(TSM && "Speculation Layer received Null Module ?");
65  assert(TSM.getContext().getContext() != nullptr &&
66  "Module with null LLVMContext?");
67 
68  // Instrumentation of runtime calls, lock the Module
69  TSM.withModuleDo([this, &R](Module &M) {
70  auto &MContext = M.getContext();
71  auto SpeculatorVTy = StructType::create(MContext, "Class.Speculator");
72  auto RuntimeCallTy = FunctionType::get(
73  Type::getVoidTy(MContext),
74  {SpeculatorVTy->getPointerTo(), Type::getInt64Ty(MContext)}, false);
75  auto RuntimeCall =
76  Function::Create(RuntimeCallTy, Function::LinkageTypes::ExternalLinkage,
77  "__orc_speculate_for", &M);
78  auto SpeclAddr = new GlobalVariable(
79  M, SpeculatorVTy, false, GlobalValue::LinkageTypes::ExternalLinkage,
80  nullptr, "__orc_speculator");
81 
82  IRBuilder<> Mutator(MContext);
83 
84  // QueryAnalysis allowed to transform the IR source, one such example is
85  // Simplify CFG helps the static branch prediction heuristics!
86  for (auto &Fn : M.getFunctionList()) {
87  if (!Fn.isDeclaration()) {
88 
89  auto IRNames = QueryAnalysis(Fn);
90  // Instrument and register if Query has result
91  if (IRNames.hasValue()) {
92 
93  // Emit globals for each function.
94  auto LoadValueTy = Type::getInt8Ty(MContext);
95  auto SpeculatorGuard = new GlobalVariable(
96  M, LoadValueTy, false, GlobalValue::LinkageTypes::InternalLinkage,
97  ConstantInt::get(LoadValueTy, 0),
98  "__orc_speculate.guard.for." + Fn.getName());
99  SpeculatorGuard->setAlignment(1);
100  SpeculatorGuard->setUnnamedAddr(GlobalValue::UnnamedAddr::Local);
101 
102  BasicBlock &ProgramEntry = Fn.getEntryBlock();
103  // Create BasicBlocks before the program's entry basicblock
104  BasicBlock *SpeculateBlock = BasicBlock::Create(
105  MContext, "__orc_speculate.block", &Fn, &ProgramEntry);
106  BasicBlock *SpeculateDecisionBlock = BasicBlock::Create(
107  MContext, "__orc_speculate.decision.block", &Fn, SpeculateBlock);
108 
109  assert(SpeculateDecisionBlock == &Fn.getEntryBlock() &&
110  "SpeculateDecisionBlock not updated?");
111  Mutator.SetInsertPoint(SpeculateDecisionBlock);
112 
113  auto LoadGuard =
114  Mutator.CreateLoad(LoadValueTy, SpeculatorGuard, "guard.value");
115  // if just loaded value equal to 0,return true.
116  auto CanSpeculate =
117  Mutator.CreateICmpEQ(LoadGuard, ConstantInt::get(LoadValueTy, 0),
118  "compare.to.speculate");
119  Mutator.CreateCondBr(CanSpeculate, SpeculateBlock, &ProgramEntry);
120 
121  Mutator.SetInsertPoint(SpeculateBlock);
122  auto ImplAddrToUint =
123  Mutator.CreatePtrToInt(&Fn, Type::getInt64Ty(MContext));
124  Mutator.CreateCall(RuntimeCallTy, RuntimeCall,
125  {SpeclAddr, ImplAddrToUint});
126  Mutator.CreateStore(ConstantInt::get(LoadValueTy, 1),
127  SpeculatorGuard);
128  Mutator.CreateBr(&ProgramEntry);
129 
130  assert(Mutator.GetInsertBlock()->getParent() == &Fn &&
131  "IR builder association mismatch?");
132  S.registerSymbols(internToJITSymbols(IRNames.getValue()),
133  &R.getTargetJITDylib());
134  }
135  }
136  }
137  });
138 
139  assert(!TSM.withModuleDo([](const Module &M) { return verifyModule(M); }) &&
140  "Speculation Instrumentation breaks IR?");
141 
142  NextLayer.emit(std::move(R), std::move(TSM));
143 }
144 
145 } // namespace orc
146 } // namespace llvm
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional &#39;br Cond, TrueDest, FalseDest&#39; instruction.
Definition: IRBuilder.h:890
This class represents lattice values for constants.
Definition: AllocatorList.h:23
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve &#39;CreateLoad(Ty, Ptr, "...")&#39; correctly, instead of converting the string to &#39;bool...
Definition: IRBuilder.h:1576
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
auto withModuleDo(Func &&F) -> decltype(F(std::declval< Module &>()))
Locks the associated ThreadSafeContext and calls the given function on the contained Module...
Error addSpeculationRuntime(JITDylib &JD, MangleAndInterner &Mangle)
Define symbols for this Speculator object (__orc_speculator) and the speculation runtime entry point ...
Definition: Speculation.cpp:45
static IntegerType * getInt64Ty(LLVMContext &C)
Definition: Type.cpp:176
void setAlignment(unsigned Align)
FIXME: Remove this setter once the migration to MaybeAlign is over.
Definition: Globals.cpp:116
void emit(MaterializationResponsibility R, ThreadSafeModule TSM)
Emit should materialize the given IR.
Definition: Speculation.cpp:61
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:195
std::unique_ptr< AbsoluteSymbolsMaterializationUnit > absoluteSymbols(SymbolMap Symbols, VModuleKey K=VModuleKey())
Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
Definition: Core.h:362
LLVMContext & getContext() const
Get the global data context.
Definition: Module.h:244
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
Definition: Type.cpp:654
Error define(std::unique_ptr< MaterializationUnitType > &&MU)
Define all symbols provided by the materialization unit to be part of this JITDylib.
Definition: Core.h:959
Mangles symbol names then uniques them in the context of an ExecutionSession.
Definition: Core.h:1014
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:779
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition: Core.h:171
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition: IRBuilder.h:1605
BasicBlock * GetInsertBlock() const
Definition: IRBuilder.h:126
void speculateFor(TargetFAddr StubAddr)
Definition: Speculation.h:137
JITDylib & getTargetJITDylib() const
Returns the target JITDylib that these symbols are being materialized into.
Definition: Core.h:185
void trackImpls(SymbolAliasMap ImplMaps, JITDylib *SrcJD)
Definition: Speculation.cpp:28
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block...
Definition: IRBuilder.h:132
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition: Function.h:135
LLVM Basic Block Representation.
Definition: BasicBlock.h:57
const FunctionListType & getFunctionList() const
Get the Module&#39;s list of functions (constant).
Definition: Module.h:533
LLVMContext * getContext()
Returns a pointer to the LLVMContext that was used to construct this instance, or null if the instanc...
JITTargetAddress pointerToJITTargetAddress(T *Ptr)
Definition: JITSymbol.h:51
ThreadSafeContext getContext() const
Returns the context for this ThreadSafeModule.
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:160
static FunctionType * get(Type *Result, ArrayRef< Type *> Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:296
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:99
An LLVM Module together with a shared ThreadSafeContext.
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2102
Module.h This file contains the declarations for the Module class.
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:653
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:190
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:214
#define I(x, y, z)
Definition: MD5.cpp:58
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value *> Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition: IRBuilder.h:2237
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Definition: IRBuilder.h:1954
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional &#39;br label X&#39; instruction.
Definition: IRBuilder.h:884
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition: Type.cpp:436
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:173
A symbol table that supports asynchoronous symbol queries.
Definition: Core.h:495