LLVM 24.0.0git
XCoreLowerThreadLocal.cpp
Go to the documentation of this file.
1//===-- XCoreLowerThreadLocal - Lower thread local variables --------------===//
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///
9/// \file
10/// This file contains a pass that lowers thread local variables on the
11/// XCore.
12///
13//===----------------------------------------------------------------------===//
14
15#include "XCore.h"
16#include "XCoreSubtarget.h"
17#include "llvm/IR/Analysis.h"
18#include "llvm/IR/Constants.h"
21#include "llvm/IR/IRBuilder.h"
22#include "llvm/IR/Intrinsics.h"
23#include "llvm/IR/IntrinsicsXCore.h"
24#include "llvm/IR/Module.h"
25#include "llvm/IR/PassManager.h"
26#include "llvm/IR/ValueHandle.h"
27#include "llvm/Pass.h"
30
31#define DEBUG_TYPE "xcore-lower-thread-local"
32
33using namespace llvm;
34
35namespace {
36 /// Lowers thread local variables on the XCore. Each thread local variable is
37 /// expanded to an array of n elements indexed by the thread ID where n is the
38 /// fixed number hardware threads supported by the device.
39struct XCoreLowerThreadLocalLegacy : public ModulePass {
40 static char ID;
41
42 XCoreLowerThreadLocalLegacy() : ModulePass(ID) {}
43
44 bool runOnModule(Module &M) override;
45};
46}
47
48char XCoreLowerThreadLocalLegacy::ID = 0;
49
50INITIALIZE_PASS(XCoreLowerThreadLocalLegacy, "xcore-lower-thread-local",
51 "Lower thread local variables", false, false)
52
54 return new XCoreLowerThreadLocalLegacy();
55}
56
57static ArrayType *createLoweredType(Type *OriginalType, unsigned MaxThreads) {
58 return ArrayType::get(OriginalType, MaxThreads);
59}
60
61static Constant *
62createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer) {
63 SmallVector<Constant *, 8> Elements(NewType->getNumElements());
64 for (unsigned i = 0; i != NewType->getNumElements(); ++i) {
65 Elements[i] = OriginalInitializer;
66 }
67 return ConstantArray::get(NewType, Elements);
68}
69
71 do {
72 SmallVector<WeakTrackingVH, 8> WUsers(CE->users());
73 llvm::sort(WUsers);
74 WUsers.erase(llvm::unique(WUsers), WUsers.end());
75 while (!WUsers.empty())
76 if (WeakTrackingVH WU = WUsers.pop_back_val()) {
77 if (PHINode *PN = dyn_cast<PHINode>(WU)) {
78 for (int I = 0, E = PN->getNumIncomingValues(); I < E; ++I)
79 if (PN->getIncomingValue(I) == CE) {
80 BasicBlock *PredBB = PN->getIncomingBlock(I);
81 if (PredBB->getTerminator()->getNumSuccessors() > 1)
82 PredBB = SplitEdge(PredBB, PN->getParent());
83 BasicBlock::iterator InsertPos =
84 PredBB->getTerminator()->getIterator();
85 Instruction *NewInst = CE->getAsInstruction();
86 NewInst->insertBefore(*PredBB, InsertPos);
87 PN->setOperand(I, NewInst);
88 }
89 } else if (Instruction *Instr = dyn_cast<Instruction>(WU)) {
90 Instruction *NewInst = CE->getAsInstruction();
91 NewInst->insertBefore(*Instr->getParent(), Instr->getIterator());
92 Instr->replaceUsesOfWith(CE, NewInst);
93 } else {
95 if (!CExpr || !replaceConstantExprOp(CExpr))
96 return false;
97 }
98 }
99 } while (CE->hasNUsesOrMore(1)); // We need to check because a recursive
100 // sibling may have used 'CE' when getAsInstruction was called.
101 CE->destroyConstant();
102 return true;
103}
104
107 for (User *U : GV->users())
108 if (!isa<Instruction>(U))
109 WUsers.push_back(WeakTrackingVH(U));
110 while (!WUsers.empty())
111 if (WeakTrackingVH WU = WUsers.pop_back_val()) {
113 if (!CE || !replaceConstantExprOp(CE))
114 return false;
115 }
116 return true;
117}
118
119static bool lowerGlobal(GlobalVariable *GV, unsigned MaxThreads) {
120 Module *M = GV->getParent();
121 if (!GV->isThreadLocal())
122 return false;
123
125 return false;
126
127 // The lowered representation needs an ArrayType of the value type, which
128 // requires a known per-element stride: reject anything that can't provide
129 // one now, with a clear diagnostic, rather than emitting a malformed GEP
130 // that only fails much later (and much less clearly) in instruction
131 // selection.
132 if (!GV->getValueType()->isSized() ||
133 GV->getGlobalSize(M->getDataLayout()) == 0)
134 reportFatalUsageError("Size of thread local object '" + GV->getName() +
135 "' is unknown");
136
137 // Create replacement global.
138 ArrayType *NewType = createLoweredType(GV->getValueType(), MaxThreads);
139 Constant *NewInitializer = nullptr;
140 if (GV->hasInitializer())
141 NewInitializer = createLoweredInitializer(NewType,
142 GV->getInitializer());
143 GlobalVariable *NewGV =
144 new GlobalVariable(*M, NewType, GV->isConstant(), GV->getLinkage(),
145 NewInitializer, "", nullptr,
147 GV->getType()->getAddressSpace(),
149
150 // Update uses.
152 for (User *U : Users) {
154 IRBuilder<> Builder(Inst);
155 Value *ThreadID = Builder.CreateIntrinsic(Intrinsic::xcore_getid, {});
156 Value *Addr = Builder.CreateInBoundsGEP(NewGV->getValueType(), NewGV,
157 {Builder.getInt64(0), ThreadID});
158 U->replaceUsesOfWith(GV, Addr);
159 }
160
161 // Remove old global.
162 NewGV->takeName(GV);
163 GV->eraseFromParent();
164 return true;
165}
166
168 unsigned MaxThreads =
169 M.getContext().getLibraryOptions().get<XCoreOptions>().max_threads;
170 // Find thread local globals.
171 bool MadeChange = false;
172 SmallVector<GlobalVariable *, 16> ThreadLocalGlobals;
173 for (GlobalVariable &GV : M.globals())
174 if (GV.isThreadLocal())
175 ThreadLocalGlobals.push_back(&GV);
176 for (GlobalVariable *GV : ThreadLocalGlobals)
177 MadeChange |= lowerGlobal(GV, MaxThreads);
178 return MadeChange;
179}
180
181bool XCoreLowerThreadLocalLegacy::runOnModule(Module &M) {
182 return lowerGlobalsInModule(M);
183}
184
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
iv Induction Variable Users
Definition IVUsers.cpp:48
#define I(x, y, z)
Definition MD5.cpp:57
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool rewriteNonInstructionUses(GlobalVariable *GV)
static bool replaceConstantExprOp(ConstantExpr *CE)
static Constant * createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer)
static bool lowerGlobal(GlobalVariable *GV, unsigned MaxThreads)
static bool lowerGlobalsInModule(Module &M)
static ArrayType * createLoweredType(Type *OriginalType, unsigned MaxThreads)
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
A constant value that is initialized with an expression using other constant values.
Definition Constants.h:1316
This is an important base class in LLVM.
Definition Constant.h:44
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
LinkageTypes getLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool isExternallyInitialized() const
bool hasInitializer() const
Definitions have initializers, declarations don't.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition Globals.cpp:609
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2909
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:253
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
unsigned getAddressSpace() const
Return the address space of the Pointer type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isSized() const
Return true if it makes sense to take the size of this type.
Definition Type.h:321
LLVM Value Representation.
Definition Value.h:75
iterator_range< user_iterator > users()
Definition Value.h:428
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:396
Value handle that is nullable, but tries to track the Value.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
self_iterator getIterator()
Definition ilist_node.h:123
Pass manager infrastructure for declaring and invalidating analyses.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto unique(Range &&R, Predicate P)
Definition STLExtras.h:2150
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
ModulePass * createXCoreLowerThreadLocalLegacyPass()
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the edge connecting the specified blocks, and return the newly created basic block between From...
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177