92 #define DEBUG_TYPE "nvptx-infer-addrspace"
108 using namespace llvm;
111 const unsigned ADDRESS_SPACE_UNINITIALIZED = (
unsigned)-1;
122 bool runOnFunction(
Function &
F)
override;
127 updateAddressSpace(
const Value &V,
128 const ValueToAddrSpaceMapTy &InferredAddrSpace);
132 void inferAddressSpaces(
const std::vector<Value *> &Postorder,
133 ValueToAddrSpaceMapTy *InferredAddrSpace);
139 rewriteWithNewAddressSpaces(
const std::vector<Value *> &Postorder,
140 const ValueToAddrSpaceMapTy &InferredAddrSpace,
151 "Infer address spaces",
157 static
bool isAddressExpression(
const Value &V) {
158 if (!isa<Operator>(V))
161 switch (cast<Operator>(V).getOpcode()) {
162 case Instruction::PHI:
163 case Instruction::BitCast:
164 case Instruction::AddrSpaceCast:
165 case Instruction::GetElementPtr:
176 assert(isAddressExpression(V));
179 case Instruction::PHI: {
180 auto IncomingValues = cast<PHINode>(
Op).incoming_values();
182 IncomingValues.end());
184 case Instruction::BitCast:
185 case Instruction::AddrSpaceCast:
186 case Instruction::GetElementPtr:
196 Value *V, std::vector<std::pair<Value *, bool>> *PostorderStack,
199 if (isAddressExpression(*V) &&
202 if (Visited->
insert(V).second)
203 PostorderStack->push_back(std::make_pair(V,
false));
212 std::vector<std::pair<Value*, bool>> PostorderStack;
218 if (isa<LoadInst>(
I)) {
220 I.getOperand(0), &PostorderStack, &Visited);
221 }
else if (isa<StoreInst>(
I)) {
223 I.getOperand(1), &PostorderStack, &Visited);
227 std::vector<Value *> Postorder;
228 while (!PostorderStack.empty()) {
231 if (PostorderStack.back().second) {
232 Postorder.push_back(PostorderStack.back().first);
233 PostorderStack.pop_back();
237 PostorderStack.back().second =
true;
240 PtrOperand, &PostorderStack, &Visited);
250 const Use &OperandUse,
unsigned NewAddrSpace,
254 if (
Value *NewOperand = ValueWithNewAddrSpace.
lookup(Operand))
278 if (I->
getOpcode() == Instruction::AddrSpaceCast) {
284 if (Src->
getType() != NewPtrType)
292 if (!OperandUse.get()->getType()->isPointerTy())
296 OperandUse, NewAddrSpace, ValueWithNewAddrSpace, UndefUsesToFix));
300 case Instruction::BitCast:
301 return new BitCastInst(NewPointerOperands[0], NewPtrType);
302 case Instruction::PHI: {
306 for (
unsigned Index = 0; Index < PHI->getNumIncomingValues(); ++Index) {
308 NewPHI->addIncoming(NewPointerOperands[OperandNo],
309 PHI->getIncomingBlock(Index));
313 case Instruction::GetElementPtr: {
335 if (CE->
getOpcode() == Instruction::AddrSpaceCast) {
353 if (
Value *NewOperand = ValueWithNewAddrSpace.
lookup(Operand)) {
354 NewOperands.
push_back(cast<Constant>(NewOperand));
361 if (CE->
getOpcode() == Instruction::GetElementPtr) {
365 NewOperands, TargetType,
false,
366 NewOperands[0]->
getType()->getPointerElementType());
382 assert(isAddressExpression(*V) &&
388 I, NewAddrSpace, ValueWithNewAddrSpace, UndefUsesToFix);
389 if (
Instruction *NewI = dyn_cast<Instruction>(NewV)) {
390 if (NewI->getParent() ==
nullptr) {
391 NewI->insertBefore(
I);
399 cast<ConstantExpr>(V), NewAddrSpace, ValueWithNewAddrSpace);
409 if (AS1 == ADDRESS_SPACE_UNINITIALIZED)
411 if (AS2 == ADDRESS_SPACE_UNINITIALIZED)
418 bool NVPTXInferAddressSpaces::runOnFunction(
Function &
F) {
427 ValueToAddrSpaceMapTy InferredAddrSpace;
428 inferAddressSpaces(Postorder, &InferredAddrSpace);
432 return rewriteWithNewAddressSpaces(Postorder, InferredAddrSpace, &F);
435 void NVPTXInferAddressSpaces::inferAddressSpaces(
436 const std::vector<Value *> &Postorder,
437 ValueToAddrSpaceMapTy *InferredAddrSpace) {
440 for (
Value *V : Postorder)
441 (*InferredAddrSpace)[V] = ADDRESS_SPACE_UNINITIALIZED;
443 while (!Worklist.empty()) {
444 Value* V = Worklist.pop_back_val();
448 DEBUG(
dbgs() <<
"Updating the address space of\n"
449 <<
" " << *V <<
"\n");
456 (*InferredAddrSpace)[V] = NewAS.
getValue();
460 if (Worklist.count(
User))
463 auto Pos = InferredAddrSpace->find(
User);
466 if (Pos == InferredAddrSpace->end())
475 Worklist.insert(
User);
481 const Value &V,
const ValueToAddrSpaceMapTy &InferredAddrSpace) {
482 assert(InferredAddrSpace.count(&V));
486 unsigned NewAS = ADDRESS_SPACE_UNINITIALIZED;
489 if (InferredAddrSpace.count(PtrOperand))
490 OperandAS = InferredAddrSpace.lookup(PtrOperand);
492 OperandAS = PtrOperand->getType()->getPointerAddressSpace();
499 unsigned OldAS = InferredAddrSpace.lookup(&V);
506 bool NVPTXInferAddressSpaces::rewriteWithNewAddressSpaces(
507 const std::vector<Value *> &Postorder,
508 const ValueToAddrSpaceMapTy &InferredAddrSpace,
Function *F) {
515 for (
Value* V : Postorder) {
516 unsigned NewAddrSpace = InferredAddrSpace.lookup(V);
519 V, NewAddrSpace, ValueWithNewAddrSpace, &UndefUsesToFix);
523 if (ValueWithNewAddrSpace.
empty())
527 for (
const Use* UndefUse : UndefUsesToFix) {
528 User *V = UndefUse->getUser();
529 User *NewV = cast<User>(ValueWithNewAddrSpace.
lookup(V));
530 unsigned OperandNo = UndefUse->getOperandNo();
536 for (
Value *V : Postorder) {
544 DEBUG(
dbgs() <<
"Replacing the uses of " << *V <<
"\n to\n " << *NewV
546 for (
Use *U : Uses) {
547 if (isa<LoadInst>(U->getUser()) ||
548 (isa<StoreInst>(U->getUser()) && U->getOperandNo() == 1)) {
553 }
else if (isa<Instruction>(U->getUser())) {
565 while (isa<PHINode>(InsertPos))
582 return new NVPTXInferAddressSpaces();
void push_back(const T &Elt)
iterator_range< use_iterator > uses()
static Value * cloneConstantExprWithNewAddressSpace(ConstantExpr *CE, unsigned NewAddrSpace, const ValueToValueMapTy &ValueWithNewAddrSpace)
Type * getSourceElementType() const
ValueT lookup(const KeyT &Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
unsigned getNumOperands() const
static Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > Tys=None)
Return the function type for an intrinsic.
unsigned getOpcode() const
Return the opcode at the root of this constant expression.
Type * getPointerElementType() const
static unsigned getOperandNumForIncomingValue(unsigned i)
This class represents a conversion between pointers from one address space to another.
A Use represents the edge between a Value definition and its users.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
static std::vector< Value * > collectGenericAddressExpressions(Function &F)
static SmallVector< Value *, 2 > getPointerOperands(const Value &V)
static Value * cloneInstructionWithNewAddressSpace(Instruction *I, unsigned NewAddrSpace, const ValueToValueMapTy &ValueWithNewAddrSpace, SmallVectorImpl< const Use * > *UndefUsesToFix)
A constant value that is initialized with an expression using other constant values.
const T & getValue() const LLVM_LVALUE_FUNCTION
This class represents a no-op cast from one type to another.
bool isInBounds() const
Determine whether the GEP has the inbounds flag.
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important base class in LLVM.
std::pair< iterator, bool > insert(const ValueT &V)
INITIALIZE_PASS(NVPTXInferAddressSpaces,"nvptx-infer-addrspace","Infer address spaces", false, false) static bool isAddressExpression(const Value &V)
FunctionPass class - This class is used to implement most global optimizations.
Value * getOperand(unsigned i) const
bool isPointerTy() const
True if this is an instance of PointerType.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr)
If the specified value is a trivially dead instruction, delete it.
FunctionPass * createNVPTXInferAddressSpacesPass()
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static Value * cloneValueWithNewAddressSpace(Value *V, unsigned NewAddrSpace, const ValueToValueMapTy &ValueWithNewAddrSpace, SmallVectorImpl< const Use * > *UndefUsesToFix)
Iterator for intrusive lists based on ilist_node.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
This is a utility class that provides an abstraction for the common functionality between Instruction...
Type * getType() const
All values are typed, get the type of this value.
static unsigned joinAddressSpaces(unsigned AS1, unsigned AS2)
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
void setOperand(unsigned i, Value *Val)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator_range< user_iterator > users()
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
void initializeNVPTXInferAddressSpacesPass(PassRegistry &)
static Value * operandWithNewAddressSpaceOrCreateUndef(const Use &OperandUse, unsigned NewAddrSpace, const ValueToValueMapTy &ValueWithNewAddrSpace, SmallVectorImpl< const Use * > *UndefUsesToFix)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
inst_range instructions(Function *F)
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
static void appendsGenericAddressExpressionToPostorderStack(Value *V, std::vector< std::pair< Value *, bool >> *PostorderStack, DenseSet< Value * > *Visited)
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Constant * getWithOperands(ArrayRef< Constant * > Ops) const
This returns the current constant expression with the operands replaced with the specified values...