diff options
Diffstat (limited to 'llvm/lib/Transforms/IPO/AttributorAttributes.cpp')
| -rw-r--r-- | llvm/lib/Transforms/IPO/AttributorAttributes.cpp | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index 45e2a0d0b933..5d17ffa61272 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -12583,16 +12583,36 @@ struct AAAddressSpaceImpl : public AAAddressSpace { } ChangeStatus updateImpl(Attributor &A) override { + unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value(); uint32_t OldAddressSpace = AssumedAddressSpace; - auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(), this, - DepClassTy::REQUIRED); - auto Pred = [&](Value &Obj) { + + auto CheckAddressSpace = [&](Value &Obj) { if (isa<UndefValue>(&Obj)) return true; + // If an argument in flat address space only has addrspace cast uses, and + // those casts are same, then we take the dst addrspace. + if (auto *Arg = dyn_cast<Argument>(&Obj)) { + if (Arg->getType()->getPointerAddressSpace() == FlatAS) { + unsigned CastAddrSpace = FlatAS; + for (auto *U : Arg->users()) { + auto *ASCI = dyn_cast<AddrSpaceCastInst>(U); + if (!ASCI) + return takeAddressSpace(Obj.getType()->getPointerAddressSpace()); + if (CastAddrSpace != FlatAS && + CastAddrSpace != ASCI->getDestAddressSpace()) + return false; + CastAddrSpace = ASCI->getDestAddressSpace(); + } + if (CastAddrSpace != FlatAS) + return takeAddressSpace(CastAddrSpace); + } + } return takeAddressSpace(Obj.getType()->getPointerAddressSpace()); }; - if (!AUO->forallUnderlyingObjects(Pred)) + auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(), this, + DepClassTy::REQUIRED); + if (!AUO->forallUnderlyingObjects(CheckAddressSpace)) return indicatePessimisticFixpoint(); return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED @@ -12601,17 +12621,21 @@ struct AAAddressSpaceImpl : public AAAddressSpace { /// See AbstractAttribute::manifest(...). ChangeStatus manifest(Attributor &A) override { - if (getAddressSpace() == InvalidAddressSpace || - getAddressSpace() == getAssociatedType()->getPointerAddressSpace()) + unsigned NewAS = getAddressSpace(); + + if (NewAS == InvalidAddressSpace || + NewAS == getAssociatedType()->getPointerAddressSpace()) return ChangeStatus::UNCHANGED; + unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value(); + Value *AssociatedValue = &getAssociatedValue(); - Value *OriginalValue = peelAddrspacecast(AssociatedValue); + Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS); PointerType *NewPtrTy = - PointerType::get(getAssociatedType()->getContext(), getAddressSpace()); + PointerType::get(getAssociatedType()->getContext(), NewAS); bool UseOriginalValue = - OriginalValue->getType()->getPointerAddressSpace() == getAddressSpace(); + OriginalValue->getType()->getPointerAddressSpace() == NewAS; bool Changed = false; @@ -12671,12 +12695,19 @@ private: return AssumedAddressSpace == AS; } - static Value *peelAddrspacecast(Value *V) { - if (auto *I = dyn_cast<AddrSpaceCastInst>(V)) - return peelAddrspacecast(I->getPointerOperand()); + static Value *peelAddrspacecast(Value *V, unsigned FlatAS) { + if (auto *I = dyn_cast<AddrSpaceCastInst>(V)) { + assert(I->getSrcAddressSpace() != FlatAS && + "there should not be flat AS -> non-flat AS"); + return I->getPointerOperand(); + } if (auto *C = dyn_cast<ConstantExpr>(V)) - if (C->getOpcode() == Instruction::AddrSpaceCast) - return peelAddrspacecast(C->getOperand(0)); + if (C->getOpcode() == Instruction::AddrSpaceCast) { + assert(C->getOperand(0)->getType()->getPointerAddressSpace() != + FlatAS && + "there should not be flat AS -> non-flat AS X"); + return C->getOperand(0); + } return V; } }; |
