Movatterモバイル変換


[0]ホーム

URL:


LLVM 20.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 "llvm/IR/Constants.h"
17#include "llvm/IR/DerivedTypes.h"
18#include "llvm/IR/GlobalVariable.h"
19#include "llvm/IR/IRBuilder.h"
20#include "llvm/IR/Intrinsics.h"
21#include "llvm/IR/IntrinsicsXCore.h"
22#include "llvm/IR/Module.h"
23#include "llvm/IR/ValueHandle.h"
24#include "llvm/Pass.h"
25#include "llvm/Support/CommandLine.h"
26#include "llvm/Transforms/Utils/BasicBlockUtils.h"
27
28#define DEBUG_TYPE "xcore-lower-thread-local"
29
30using namespacellvm;
31
32staticcl::opt<unsigned>MaxThreads(
33"xcore-max-threads",cl::Optional,
34cl::desc("Maximum number of threads (for emulation thread-local storage)"),
35cl::Hidden,cl::value_desc("number"),cl::init(8));
36
37namespace{
38 /// Lowers thread local variables on the XCore. Each thread local variable is
39 /// expanded to an array of n elements indexed by the thread ID where n is the
40 /// fixed number hardware threads supported by the device.
41structXCoreLowerThreadLocal :publicModulePass {
42staticcharID;
43
44 XCoreLowerThreadLocal() :ModulePass(ID) {
45initializeXCoreLowerThreadLocalPass(*PassRegistry::getPassRegistry());
46 }
47
48bool lowerGlobal(GlobalVariable *GV);
49
50boolrunOnModule(Module &M)override;
51 };
52}
53
54char XCoreLowerThreadLocal::ID = 0;
55
56INITIALIZE_PASS(XCoreLowerThreadLocal,"xcore-lower-thread-local",
57"Lower thread local variables",false,false)
58
59ModulePass *llvm::createXCoreLowerThreadLocalPass() {
60returnnew XCoreLowerThreadLocal();
61}
62
63staticArrayType *createLoweredType(Type *OriginalType) {
64return ArrayType::get(OriginalType,MaxThreads);
65}
66
67staticConstant *
68createLoweredInitializer(ArrayType *NewType,Constant *OriginalInitializer) {
69SmallVector<Constant *, 8> Elements(MaxThreads);
70for (unsigned i = 0; i !=MaxThreads; ++i) {
71 Elements[i] = OriginalInitializer;
72 }
73returnConstantArray::get(NewType, Elements);
74}
75
76
77staticboolreplaceConstantExprOp(ConstantExpr *CE,Pass *P) {
78do {
79SmallVector<WeakTrackingVH, 8> WUsers(CE->users());
80llvm::sort(WUsers);
81 WUsers.erase(llvm::unique(WUsers), WUsers.end());
82while (!WUsers.empty())
83if (WeakTrackingVH WU = WUsers.pop_back_val()) {
84if (PHINode *PN = dyn_cast<PHINode>(WU)) {
85for (intI = 0, E = PN->getNumIncomingValues();I < E; ++I)
86if (PN->getIncomingValue(I) == CE) {
87BasicBlock *PredBB = PN->getIncomingBlock(I);
88if (PredBB->getTerminator()->getNumSuccessors() > 1)
89 PredBB =SplitEdge(PredBB, PN->getParent());
90BasicBlock::iterator InsertPos =
91 PredBB->getTerminator()->getIterator();
92Instruction *NewInst = CE->getAsInstruction();
93 NewInst->insertBefore(*PredBB, InsertPos);
94 PN->setOperand(I, NewInst);
95 }
96 }elseif (Instruction *Instr = dyn_cast<Instruction>(WU)) {
97Instruction *NewInst = CE->getAsInstruction();
98 NewInst->insertBefore(*Instr->getParent(), Instr->getIterator());
99 Instr->replaceUsesOfWith(CE, NewInst);
100 }else {
101ConstantExpr *CExpr = dyn_cast<ConstantExpr>(WU);
102if (!CExpr || !replaceConstantExprOp(CExpr,P))
103returnfalse;
104 }
105 }
106 }while (CE->hasNUsesOrMore(1));// We need to check because a recursive
107// sibling may have used 'CE' when getAsInstruction was called.
108 CE->destroyConstant();
109returntrue;
110}
111
112staticboolrewriteNonInstructionUses(GlobalVariable *GV,Pass *P) {
113SmallVector<WeakTrackingVH, 8> WUsers;
114for (User *U : GV->users())
115if (!isa<Instruction>(U))
116 WUsers.push_back(WeakTrackingVH(U));
117while (!WUsers.empty())
118if (WeakTrackingVH WU = WUsers.pop_back_val()) {
119ConstantExpr *CE = dyn_cast<ConstantExpr>(WU);
120if (!CE || !replaceConstantExprOp(CE,P))
121returnfalse;
122 }
123returntrue;
124}
125
126staticboolisZeroLengthArray(Type *Ty) {
127ArrayType *AT = dyn_cast<ArrayType>(Ty);
128return AT && (AT->getNumElements() == 0);
129}
130
131bool XCoreLowerThreadLocal::lowerGlobal(GlobalVariable *GV) {
132Module *M = GV->getParent();
133if (!GV->isThreadLocal())
134returnfalse;
135
136// Skip globals that we can't lower and leave it for the backend to error.
137if (!rewriteNonInstructionUses(GV,this) ||
138 !GV->getType()->isSized() ||isZeroLengthArray(GV->getType()))
139returnfalse;
140
141// Create replacement global.
142ArrayType *NewType =createLoweredType(GV->getValueType());
143Constant *NewInitializer =nullptr;
144if (GV->hasInitializer())
145 NewInitializer =createLoweredInitializer(NewType,
146 GV->getInitializer());
147GlobalVariable *NewGV =
148newGlobalVariable(*M, NewType, GV->isConstant(), GV->getLinkage(),
149 NewInitializer,"",nullptr,
150 GlobalVariable::NotThreadLocal,
151 GV->getType()->getAddressSpace(),
152 GV->isExternallyInitialized());
153
154// Update uses.
155SmallVector<User *, 16>Users(GV->users());
156for (User *U :Users) {
157Instruction *Inst = cast<Instruction>(U);
158IRBuilder<> Builder(Inst);
159Value *ThreadID = Builder.CreateIntrinsic(Intrinsic::xcore_getid, {}, {});
160Value *Addr = Builder.CreateInBoundsGEP(NewGV->getValueType(), NewGV,
161 {Builder.getInt64(0), ThreadID});
162U->replaceUsesOfWith(GV,Addr);
163 }
164
165// Remove old global.
166 NewGV->takeName(GV);
167 GV->eraseFromParent();
168returntrue;
169}
170
171bool XCoreLowerThreadLocal::runOnModule(Module &M) {
172// Find thread local globals.
173bool MadeChange =false;
174SmallVector<GlobalVariable *, 16> ThreadLocalGlobals;
175for (GlobalVariable &GV :M.globals())
176if (GV.isThreadLocal())
177 ThreadLocalGlobals.push_back(&GV);
178for (GlobalVariable *GV : ThreadLocalGlobals)
179 MadeChange |= lowerGlobal(GV);
180return MadeChange;
181}
BasicBlockUtils.h
CommandLine.h
Constants.h
This file contains the declarations for the subclasses of Constant, which represent the different fla...
DerivedTypes.h
Addr
uint64_t Addr
Definition:ELFObjHandler.cpp:79
GlobalVariable.h
IRBuilder.h
Module.h
Module.h This file contains the declarations for the Module class.
Users
iv Induction Variable Users
Definition:IVUsers.cpp:48
Intrinsics.h
I
#define I(x, y, z)
Definition:MD5.cpp:58
P
#define P(N)
INITIALIZE_PASS
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition:PassSupport.h:38
Pass.h
ValueHandle.h
replaceConstantExprOp
static bool replaceConstantExprOp(ConstantExpr *CE, Pass *P)
Definition:XCoreLowerThreadLocal.cpp:77
isZeroLengthArray
static bool isZeroLengthArray(Type *Ty)
Definition:XCoreLowerThreadLocal.cpp:126
createLoweredInitializer
static Constant * createLoweredInitializer(ArrayType *NewType, Constant *OriginalInitializer)
Definition:XCoreLowerThreadLocal.cpp:68
MaxThreads
static cl::opt< unsigned > MaxThreads("xcore-max-threads", cl::Optional, cl::desc("Maximum number of threads (for emulation thread-local storage)"), cl::Hidden, cl::value_desc("number"), cl::init(8))
rewriteNonInstructionUses
static bool rewriteNonInstructionUses(GlobalVariable *GV, Pass *P)
Definition:XCoreLowerThreadLocal.cpp:112
createLoweredType
static ArrayType * createLoweredType(Type *OriginalType)
Definition:XCoreLowerThreadLocal.cpp:63
XCore.h
ArrayType
Definition:ItaniumDemangle.h:785
llvm::BasicBlock
LLVM Basic Block Representation.
Definition:BasicBlock.h:61
llvm::BasicBlock::getParent
const Function * getParent() const
Return the enclosing method, or null if none.
Definition:BasicBlock.h:220
llvm::BasicBlock::iterator
InstListType::iterator iterator
Instruction iterators...
Definition:BasicBlock.h:177
llvm::BasicBlock::getTerminator
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition:BasicBlock.h:240
llvm::ConstantArray::get
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
Definition:Constants.cpp:1312
llvm::ConstantExpr
A constant value that is initialized with an expression using other constant values.
Definition:Constants.h:1108
llvm::Constant
This is an important base class in LLVM.
Definition:Constant.h:42
llvm::GlobalValue::isThreadLocal
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
Definition:GlobalValue.h:264
llvm::GlobalValue::getLinkage
LinkageTypes getLinkage() const
Definition:GlobalValue.h:547
llvm::GlobalValue::getParent
Module * getParent()
Get the module that this global value is contained inside of...
Definition:GlobalValue.h:657
llvm::GlobalValue::getType
PointerType * getType() const
Global values are always pointers.
Definition:GlobalValue.h:295
llvm::GlobalValue::getValueType
Type * getValueType() const
Definition:GlobalValue.h:297
llvm::GlobalVariable
Definition:GlobalVariable.h:39
llvm::GlobalVariable::getInitializer
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
Definition:GlobalVariable.h:150
llvm::GlobalVariable::isExternallyInitialized
bool isExternallyInitialized() const
Definition:GlobalVariable.h:176
llvm::GlobalVariable::hasInitializer
bool hasInitializer() const
Definitions have initializers, declarations don't.
Definition:GlobalVariable.h:106
llvm::GlobalVariable::isConstant
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
Definition:GlobalVariable.h:173
llvm::GlobalVariable::eraseFromParent
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition:Globals.cpp:488
llvm::IRBuilder
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition:IRBuilder.h:2705
llvm::Instruction
Definition:Instruction.h:68
llvm::Instruction::getNumSuccessors
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
Definition:Instruction.cpp:1275
llvm::Instruction::insertBefore
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
Definition:Instruction.cpp:99
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition:Pass.h:251
llvm::ModulePass::runOnModule
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition:Module.h:65
llvm::PHINode
Definition:Instructions.h:2600
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition:PassRegistry.cpp:24
llvm::Pass
Pass interface - Implemented by all 'passes'.
Definition:Pass.h:94
llvm::PointerType::getAddressSpace
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition:DerivedTypes.h:703
llvm::SmallVectorBase::empty
bool empty() const
Definition:SmallVector.h:81
llvm::SmallVectorImpl::pop_back_val
T pop_back_val()
Definition:SmallVector.h:673
llvm::SmallVectorImpl::erase
iterator erase(const_iterator CI)
Definition:SmallVector.h:737
llvm::SmallVectorTemplateBase::push_back
void push_back(const T &Elt)
Definition:SmallVector.h:413
llvm::SmallVectorTemplateCommon::end
iterator end()
Definition:SmallVector.h:269
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition:SmallVector.h:1196
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition:Type.h:45
llvm::Type::isSized
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Definition:Type.h:310
llvm::User
Definition:User.h:44
llvm::Value
LLVM Value Representation.
Definition:Value.h:74
llvm::Value::users
iterator_range< user_iterator > users()
Definition:Value.h:421
llvm::Value::takeName
void takeName(Value *V)
Transfer the name from V to this value.
Definition:Value.cpp:383
llvm::WeakTrackingVH
Value handle that is nullable, but tries to track the Value.
Definition:ValueHandle.h:204
llvm::cl::opt
Definition:CommandLine.h:1423
llvm::ilist_node_impl::getIterator
self_iterator getIterator()
Definition:ilist_node.h:132
unsigned
llvm::ARM::ProfileKind::M
@ M
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition:CallingConv.h:24
llvm::M68k::MemAddrModeKind::U
@ U
llvm::cl::Optional
@ Optional
Definition:CommandLine.h:113
llvm::cl::Hidden
@ Hidden
Definition:CommandLine.h:137
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition:CommandLine.h:443
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition:AddressRanges.h:18
llvm::unique
auto unique(Range &&R, Predicate P)
Definition:STLExtras.h:2055
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition:STLExtras.h:1664
llvm::initializeXCoreLowerThreadLocalPass
void initializeXCoreLowerThreadLocalPass(PassRegistry &p)
llvm::createXCoreLowerThreadLocalPass
ModulePass * createXCoreLowerThreadLocalPass()
llvm::SplitEdge
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...
Definition:BasicBlockUtils.cpp:762
llvm::cl::desc
Definition:CommandLine.h:409
llvm::cl::value_desc
Definition:CommandLine.h:418

Generated on Fri Jul 18 2025 15:09:44 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp