diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -5973,6 +5973,47 @@ AA::ValueScope Scope = AA::Interprocedural) const = 0; }; +/// An abstract interface for address space information. +struct AAAddressSpaceInfo + : public StateWrapper { + AAAddressSpaceInfo(const IRPosition &IRP, Attributor &A) + : StateWrapper(IRP) {} + + /// See AbstractAttribute::isValidIRPositionForInit + static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) { + if (!IRP.getAssociatedType()->isPtrOrPtrVectorTy()) + return false; + return AbstractAttribute::isValidIRPositionForInit(A, IRP); + } + + /// Return the address space of the associated value. \p NoAddressSpace is + /// returned if the associated value is dead. This functions is not supposed + /// to be called if the AA is invalid. + virtual int32_t getAddressSpace() const = 0; + + /// Create an abstract attribute view for the position \p IRP. + static AAAddressSpaceInfo &createForPosition(const IRPosition &IRP, + Attributor &A); + + /// See AbstractAttribute::getName() + const std::string getName() const override { return "AAAddressSpaceInfo"; } + + /// See AbstractAttribute::getIdAddr() + const char *getIdAddr() const override { return &ID; } + + /// This function should return true if the type of the \p AA is + /// AAAssumptionInfo + static bool classof(const AbstractAttribute *AA) { + return (AA->getIdAddr() == &ID); + } + + // No address space which indicates the associated value is dead. + static const int32_t NoAddressSpace = -1; + + /// Unique ID (due to the unique address) + static const char ID; +}; + raw_ostream &operator<<(raw_ostream &, const AAPointerInfo::Access &); /// Run options, used by the pass manager. diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -3502,18 +3502,21 @@ assert(Success && "Expected the check call to be successful!"); auto LoadStorePred = [&](Instruction &I) -> bool { - if (isa(I)) { - getOrCreateAAFor( - IRPosition::value(*cast(I).getPointerOperand())); + if (auto *LI = dyn_cast(&I)) { + getOrCreateAAFor(IRPosition::value(*LI->getPointerOperand())); if (SimplifyAllLoads) getAssumedSimplified(IRPosition::value(I), nullptr, UsedAssumedInformation, AA::Intraprocedural); + getOrCreateAAFor( + IRPosition::value(*LI->getPointerOperand())); } else { auto &SI = cast(I); getOrCreateAAFor(IRPosition::inst(I)); getAssumedSimplified(IRPosition::value(*SI.getValueOperand()), nullptr, UsedAssumedInformation, AA::Intraprocedural); getOrCreateAAFor(IRPosition::value(*SI.getPointerOperand())); + getOrCreateAAFor( + IRPosition::value(*SI.getPointerOperand())); } return true; }; diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -187,6 +187,7 @@ PIPE_OPERATOR(AAPointerInfo) PIPE_OPERATOR(AAAssumptionInfo) PIPE_OPERATOR(AAUnderlyingObjects) +PIPE_OPERATOR(AAAddressSpaceInfo) #undef PIPE_OPERATOR @@ -11856,6 +11857,149 @@ }; } +/// ------------------------ Address Space Propagation ------------------------- +namespace { +struct AAAddressSpaceInfoImpl : public AAAddressSpaceInfo { + AAAddressSpaceInfoImpl(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfo(IRP, A) {} + + int32_t getAddressSpace() const override { + assert(isValidState() && "the AA is invalid"); + return AssumedAddressSpace; + } + + /// See AbstractAttribute::initialize(...). + void initialize(Attributor &A) override { + assert(getAssociatedType()->isPtrOrPtrVectorTy() && + "Associated value is not a pointer"); + } + + ChangeStatus updateImpl(Attributor &A) override { + int32_t OldAddressSpace = AssumedAddressSpace; + auto *AUO = A.getOrCreateAAFor(getIRPosition(), this, + DepClassTy::OPTIONAL); + auto Pred = [&](Value &Obj) { + if (isa(&Obj)) + return true; + return takeAddressSpace(Obj.getType()->getPointerAddressSpace()); + }; + + if (!AUO->forallUnderlyingObjects(Pred)) + return indicatePessimisticFixpoint(); + + return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED + : ChangeStatus::CHANGED; + } + + /// See AbstractAttribute::manifest(...). + ChangeStatus manifest(Attributor &A) override { + Value *AssociatedValue = &getAssociatedValue(); + if (getAddressSpace() == NoAddressSpace || + static_cast(getAddressSpace()) == + getAssociatedType()->getPointerAddressSpace()) + return ChangeStatus::UNCHANGED; + + Type *NewPtrTy = PointerType::getWithSamePointeeType( + cast(getAssociatedType()), + static_cast(getAddressSpace())); + + bool Changed = false; + + auto Pred = [&](const Use &U, bool &) { + if (U.get() != AssociatedValue) + return true; + User *Usr = U.getUser(); + if (isa(Usr) || isa(Usr)) { + Instruction *CastInst = new AddrSpaceCastInst(AssociatedValue, NewPtrTy); + CastInst->insertBefore(cast(Usr)); + A.changeUseAfterManifest(const_cast(U), *CastInst); + Changed = true; + } + return true; + }; + + // It doesn't matter if we can't check all uses as we can simply + // conservatively ignore those that can not be visited. + (void)A.checkForAllUses(Pred, *this, getAssociatedValue(), + /* CheckBBLivenessOnly */ true); + + return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED; + } + + /// See AbstractAttribute::getAsStr(). + const std::string getAsStr() const override { + if (!isValidState()) + return "addrspace()"; + return "addrspace(" + + (AssumedAddressSpace == NoAddressSpace + ? "none" + : std::to_string(AssumedAddressSpace)) + + ")"; + } + +private: + int32_t AssumedAddressSpace = NoAddressSpace; + + bool takeAddressSpace(uint32_t AS) { + int32_t Cast = static_cast(AS); + if (AssumedAddressSpace == NoAddressSpace) { + AssumedAddressSpace = Cast; + return true; + } + return AssumedAddressSpace == Cast; + } +}; + +struct AAAddressSpaceInfoFloating final : AAAddressSpaceInfoImpl { + AAAddressSpaceInfoFloating(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfoImpl(IRP, A) {} + + void trackStatistics() const override { + STATS_DECLTRACK_FLOATING_ATTR(addrspace); + } +}; + +struct AAAddressSpaceInfoReturned final : AAAddressSpaceInfoImpl { + AAAddressSpaceInfoReturned(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfoImpl(IRP, A) {} + + void trackStatistics() const override { + STATS_DECLTRACK_FNRET_ATTR(addrspace); + } +}; + +struct AAAddressSpaceInfoCallSiteReturned final : AAAddressSpaceInfoImpl { + AAAddressSpaceInfoCallSiteReturned(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfoImpl(IRP, A) {} + + void trackStatistics() const override { + STATS_DECLTRACK_CSRET_ATTR(addrspace); + } +}; + +struct AAAddressSpaceInfoArgument final : AAAddressSpaceInfoImpl { + AAAddressSpaceInfoArgument(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfoImpl(IRP, A) {} + + void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(addrspace); } +}; + +struct AAAddressSpaceInfoCallSiteArgument final : AAAddressSpaceInfoImpl { + AAAddressSpaceInfoCallSiteArgument(const IRPosition &IRP, Attributor &A) + : AAAddressSpaceInfoImpl(IRP, A) {} + + // We don't rewrite call site argument for now because it will need to rewrite + // the function signature of the callee. + ChangeStatus updateImpl(Attributor &A) override { + return indicatePessimisticFixpoint(); + }; + + void trackStatistics() const override { + STATS_DECLTRACK_CSARG_ATTR(addrspace); + } +}; +} // namespace + const char AAReturnedValues::ID = 0; const char AANoUnwind::ID = 0; const char AANoSync::ID = 0; @@ -11889,6 +12033,7 @@ const char AAPointerInfo::ID = 0; const char AAAssumptionInfo::ID = 0; const char AAUnderlyingObjects::ID = 0; +const char AAAddressSpaceInfo::ID = 0; // Macro magic to create the static generator function for attributes that // follow the naming scheme. @@ -12007,6 +12152,7 @@ CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUndef) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFPClass) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPointerInfo) +CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAddressSpaceInfo) CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify) CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead) diff --git a/llvm/test/Transforms/Attributor/address_space_info.ll b/llvm/test/Transforms/Attributor/address_space_info.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Attributor/address_space_info.ll @@ -0,0 +1,159 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals --prefix-filecheck-ir-name true +; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK + +@dst = dso_local addrspace(1) externally_initialized global i32 0, align 4 +@g1 = dso_local addrspace(1) externally_initialized global i32 0, align 4 +@g2 = dso_local addrspace(1) externally_initialized global i32 0, align 4 +@s1 = dso_local addrspace(3) global i32 undef, align 4 +@s2 = dso_local addrspace(3) global i32 undef, align 4 +@llvm.compiler.used = appending global [3 x ptr] [ptr addrspacecast (ptr addrspace(1) @dst to ptr), ptr addrspacecast (ptr addrspace(1) @g1 to ptr), ptr addrspacecast (ptr addrspace(1) @g2 to ptr)], section "llvm.metadata" + +; Function Attrs: convergent mustprogress noinline nounwind +;. +; CHECK: @[[DST:[a-zA-Z0-9_$"\\.-]+]] = dso_local addrspace(1) externally_initialized global i32 0, align 4 +; CHECK: @[[G1:[a-zA-Z0-9_$"\\.-]+]] = dso_local addrspace(1) externally_initialized global i32 0, align 4 +; CHECK: @[[G2:[a-zA-Z0-9_$"\\.-]+]] = dso_local addrspace(1) externally_initialized global i32 0, align 4 +; CHECK: @[[S1:[a-zA-Z0-9_$"\\.-]+]] = dso_local addrspace(3) global i32 undef, align 4 +; CHECK: @[[S2:[a-zA-Z0-9_$"\\.-]+]] = dso_local addrspace(3) global i32 undef, align 4 +; CHECK: @[[LLVM_COMPILER_USED:[a-zA-Z0-9_$"\\.-]+]] = appending global [3 x ptr] [ptr addrspacecast (ptr addrspace(1) @dst to ptr), ptr addrspacecast (ptr addrspace(1) @g1 to ptr), ptr addrspacecast (ptr addrspace(1) @g2 to ptr)], section "llvm.metadata" +;. +define internal void @_Z12global_writePi(ptr noundef %p) #0 { +; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write) +; CHECK-LABEL: define {{[^@]+}}@_Z12global_writePi +; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[P]] to ptr addrspace(1) +; CHECK-NEXT: store i32 1, ptr addrspace(1) [[TMP0]], align 4 +; CHECK-NEXT: ret void +; +entry: + store i32 1, ptr %p, align 4 + ret void +} + +; Function Attrs: convergent mustprogress noinline nounwind +define internal void @_Z13unknown_writePi(ptr noundef %p) #0 { +; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write) +; CHECK-LABEL: define {{[^@]+}}@_Z13unknown_writePi +; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: store i32 2, ptr [[P]], align 4 +; CHECK-NEXT: ret void +; +entry: + store i32 2, ptr %p, align 4 + ret void +} + +; Function Attrs: convergent mustprogress noinline nounwind +define internal void @_Z12shared_writePi(ptr noundef %p) #0 { +; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write) +; CHECK-LABEL: define {{[^@]+}}@_Z12shared_writePi +; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[P]] to ptr addrspace(3) +; CHECK-NEXT: store i32 3, ptr addrspace(3) [[TMP0]], align 4 +; CHECK-NEXT: ret void +; +entry: + store i32 3, ptr %p, align 4 + ret void +} + +; Function Attrs: convergent mustprogress noinline nounwind +define internal void @_Z11global_readPi(ptr noundef %p) #0 { +; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@_Z11global_readPi +; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[P]] to ptr addrspace(1) +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(1) [[TMP0]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = addrspacecast ptr addrspacecast (ptr addrspace(1) @dst to ptr) to ptr addrspace(1) +; CHECK-NEXT: store i32 [[TMP1]], ptr addrspace(1) [[TMP2]], align 4 +; CHECK-NEXT: ret void +; +entry: + %0 = load i32, ptr %p, align 4 + store i32 %0, ptr addrspacecast (ptr addrspace(1) @dst to ptr), align 4 + ret void +} + +; Function Attrs: convergent mustprogress noinline nounwind +define internal void @_Z12unknown_readPi(ptr noundef %p) #0 { +; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@_Z12unknown_readPi +; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[P]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspacecast (ptr addrspace(1) @dst to ptr) to ptr addrspace(1) +; CHECK-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[TMP1]], align 4 +; CHECK-NEXT: ret void +; +entry: + %0 = load i32, ptr %p, align 4 + store i32 %0, ptr addrspacecast (ptr addrspace(1) @dst to ptr), align 4 + ret void +} + +; Function Attrs: convergent mustprogress noinline nounwind +define internal void @_Z11shared_readPi(ptr noundef %p) #0 { +; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@_Z11shared_readPi +; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[P]] to ptr addrspace(3) +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(3) [[TMP0]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = addrspacecast ptr addrspacecast (ptr addrspace(1) @dst to ptr) to ptr addrspace(1) +; CHECK-NEXT: store i32 [[TMP1]], ptr addrspace(1) [[TMP2]], align 4 +; CHECK-NEXT: ret void +; +entry: + %0 = load i32, ptr %p, align 4 + store i32 %0, ptr addrspacecast (ptr addrspace(1) @dst to ptr), align 4 + ret void +} + +; Function Attrs: convergent mustprogress noinline nounwind +define dso_local void @_Z3bazv() #0 { +; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@_Z3bazv +; CHECK-SAME: () #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @_Z12global_writePi(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(1) @g1 to ptr)) #[[ATTR2:[0-9]+]] +; CHECK-NEXT: call void @_Z12global_writePi(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(1) @g2 to ptr)) #[[ATTR2]] +; CHECK-NEXT: call void @_Z13unknown_writePi(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(1) @g1 to ptr)) #[[ATTR2]] +; CHECK-NEXT: call void @_Z13unknown_writePi(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(3) @s1 to ptr)) #[[ATTR2]] +; CHECK-NEXT: call void @_Z12shared_writePi(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(3) @s1 to ptr)) #[[ATTR2]] +; CHECK-NEXT: call void @_Z12shared_writePi(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(3) @s2 to ptr)) #[[ATTR2]] +; CHECK-NEXT: call void @_Z11global_readPi(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(1) @g1 to ptr)) #[[ATTR3:[0-9]+]] +; CHECK-NEXT: call void @_Z11global_readPi(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(1) @g2 to ptr)) #[[ATTR3]] +; CHECK-NEXT: call void @_Z12unknown_readPi(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(1) @g1 to ptr)) #[[ATTR3]] +; CHECK-NEXT: call void @_Z12unknown_readPi(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(3) @s1 to ptr)) #[[ATTR3]] +; CHECK-NEXT: call void @_Z11shared_readPi(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(3) @s1 to ptr)) #[[ATTR3]] +; CHECK-NEXT: call void @_Z11shared_readPi(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) addrspacecast (ptr addrspace(3) @s2 to ptr)) #[[ATTR3]] +; CHECK-NEXT: ret void +; +entry: + call void @_Z12global_writePi(ptr noundef addrspacecast (ptr addrspace(1) @g1 to ptr)) #1 + call void @_Z12global_writePi(ptr noundef addrspacecast (ptr addrspace(1) @g2 to ptr)) #1 + call void @_Z13unknown_writePi(ptr noundef addrspacecast (ptr addrspace(1) @g1 to ptr)) #1 + call void @_Z13unknown_writePi(ptr noundef addrspacecast (ptr addrspace(3) @s1 to ptr)) #1 + call void @_Z12shared_writePi(ptr noundef addrspacecast (ptr addrspace(3) @s1 to ptr)) #1 + call void @_Z12shared_writePi(ptr noundef addrspacecast (ptr addrspace(3) @s2 to ptr)) #1 + call void @_Z11global_readPi(ptr noundef addrspacecast (ptr addrspace(1) @g1 to ptr)) #1 + call void @_Z11global_readPi(ptr noundef addrspacecast (ptr addrspace(1) @g2 to ptr)) #1 + call void @_Z12unknown_readPi(ptr noundef addrspacecast (ptr addrspace(1) @g1 to ptr)) #1 + call void @_Z12unknown_readPi(ptr noundef addrspacecast (ptr addrspace(3) @s1 to ptr)) #1 + call void @_Z11shared_readPi(ptr noundef addrspacecast (ptr addrspace(3) @s1 to ptr)) #1 + call void @_Z11shared_readPi(ptr noundef addrspacecast (ptr addrspace(3) @s2 to ptr)) #1 + ret void +} + +attributes #0 = { convergent mustprogress noinline nounwind } +attributes #1 = { convergent nounwind } +;. +; CHECK: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write) } +; CHECK: attributes #[[ATTR1]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn } +; CHECK: attributes #[[ATTR2]] = { convergent nofree nosync nounwind willreturn memory(write) } +; CHECK: attributes #[[ATTR3]] = { convergent nofree nosync nounwind willreturn } +;. diff --git a/llvm/test/Transforms/Attributor/depgraph.ll b/llvm/test/Transforms/Attributor/depgraph.ll --- a/llvm/test/Transforms/Attributor/depgraph.ll +++ b/llvm/test/Transforms/Attributor/depgraph.ll @@ -239,6 +239,8 @@ ; GRAPH-EMPTY: ; GRAPH-NEXT: [AANoFree] for CtxI ' %6 = call ptr @checkAndAdvance(ptr %5)' at position {cs_arg: [@0]} with state nofree ; GRAPH-EMPTY: +; GRAPH-NEXT: [AAAddressSpaceInfo] for CtxI ' %2 = load i32, ptr %0, align 4' at position {arg: [@0]} with state addrspace(0) +; GRAPH-EMPTY: ; GRAPH-NEXT: [AADereferenceable] for CtxI ' %5 = getelementptr inbounds i32, ptr %0, i64 4' at position {flt: [@-1]} with state unknown-dereferenceable ; GRAPH-NOT: update @@ -320,6 +322,7 @@ ; DOT-DAG: Node[[Node71:0x[a-z0-9]+]] [shape=record,label="{[AANoAlias] ; DOT-DAG: Node[[Node72:0x[a-z0-9]+]] [shape=record,label="{[AANoAlias] ; DOT-DAG: Node[[Node73:0x[a-z0-9]+]] [shape=record,label="{[AANoFree] +; DOT-DAG: Node[[Node75:0x[a-z0-9]+]] [shape=record,label="{[AAAddressSpaceInfo] ; DOT-DAG: Node[[Node74:0x[a-z0-9]+]] [shape=record,label="{[AADereferenceable] ; DOT-DAG: Node[[Node20]] -> Node[[Node19]]; diff --git a/llvm/test/Transforms/Attributor/memory_locations_gpu.ll b/llvm/test/Transforms/Attributor/memory_locations_gpu.ll --- a/llvm/test/Transforms/Attributor/memory_locations_gpu.ll +++ b/llvm/test/Transforms/Attributor/memory_locations_gpu.ll @@ -29,7 +29,8 @@ ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define {{[^@]+}}@test_const_as_global2 ; CHECK-SAME: () #[[ATTR1]] { -; CHECK-NEXT: [[L2:%.*]] = load i32, ptr addrspacecast (ptr addrspace(4) @G to ptr), align 4 +; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspacecast (ptr addrspace(4) @G to ptr) to ptr addrspace(4) +; CHECK-NEXT: [[L2:%.*]] = load i32, ptr addrspace(4) [[TMP1]], align 4 ; CHECK-NEXT: ret i32 [[L2]] ; %l2 = load i32, ptr addrspacecast (ptr addrspace(4) @G to ptr) @@ -42,7 +43,8 @@ ; CHECK-SAME: () #[[ATTR2:[0-9]+]] { ; CHECK-NEXT: [[P1:%.*]] = call ptr addrspace(4) @ptr_to_const() ; CHECK-NEXT: [[C1:%.*]] = addrspacecast ptr addrspace(4) [[P1]] to ptr -; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[C1]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr [[C1]] to ptr addrspace(4) +; CHECK-NEXT: [[L1:%.*]] = load i32, ptr addrspace(4) [[TMP1]], align 4 ; CHECK-NEXT: ret i32 [[L1]] ; %p1 = call ptr addrspace(4) @ptr_to_const() @@ -57,7 +59,8 @@ ; CHECK-SAME: () #[[ATTR3:[0-9]+]] { ; CHECK-NEXT: [[P2:%.*]] = call ptr @ptr() ; CHECK-NEXT: [[C2:%.*]] = addrspacecast ptr [[P2]] to ptr addrspace(4) -; CHECK-NEXT: [[L2:%.*]] = load i32, ptr addrspace(4) [[C2]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(4) [[C2]] to ptr +; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[TMP1]], align 4 ; CHECK-NEXT: ret i32 [[L2]] ; %p2 = call ptr @ptr() @@ -73,7 +76,8 @@ ; CHECK-SAME: () #[[ATTR2]] { ; CHECK-NEXT: [[P1:%.*]] = call ptr addrspace(3) @ptr_to_shared() ; CHECK-NEXT: [[C1:%.*]] = addrspacecast ptr addrspace(3) [[P1]] to ptr -; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[C1]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr [[C1]] to ptr addrspace(3) +; CHECK-NEXT: [[L1:%.*]] = load i32, ptr addrspace(3) [[TMP1]], align 4 ; CHECK-NEXT: ret i32 [[L1]] ; %p1 = call ptr addrspace(3) @ptr_to_shared() @@ -88,7 +92,8 @@ ; CHECK-SAME: () #[[ATTR2]] { ; CHECK-NEXT: [[P2:%.*]] = call ptr @ptr() ; CHECK-NEXT: [[C2:%.*]] = addrspacecast ptr [[P2]] to ptr addrspace(3) -; CHECK-NEXT: [[L2:%.*]] = load i32, ptr addrspace(3) [[C2]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(3) [[C2]] to ptr +; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[TMP1]], align 4 ; CHECK-NEXT: ret i32 [[L2]] ; %p2 = call ptr @ptr() diff --git a/llvm/test/Transforms/Attributor/nocapture-1.ll b/llvm/test/Transforms/Attributor/nocapture-1.ll --- a/llvm/test/Transforms/Attributor/nocapture-1.ll +++ b/llvm/test/Transforms/Attributor/nocapture-1.ll @@ -257,7 +257,8 @@ ; TUNIT-NEXT: [[TMP:%.*]] = addrspacecast ptr addrspace(1) [[P]] to ptr ; TUNIT-NEXT: [[TMP2:%.*]] = select i1 [[B]], ptr [[TMP]], ptr [[Q]] ; TUNIT-NEXT: [[VAL:%.*]] = load i32, ptr [[TMP2]], align 4 -; TUNIT-NEXT: store i32 0, ptr [[TMP]], align 4 +; TUNIT-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[TMP]] to ptr addrspace(1) +; TUNIT-NEXT: store i32 0, ptr addrspace(1) [[TMP0]], align 4 ; TUNIT-NEXT: store ptr [[Q]], ptr @g, align 8 ; TUNIT-NEXT: ret i32 [[VAL]] ; @@ -272,7 +273,8 @@ ; CGSCC-NEXT: [[TMP:%.*]] = addrspacecast ptr addrspace(1) [[P]] to ptr ; CGSCC-NEXT: [[TMP2:%.*]] = select i1 [[B]], ptr [[TMP]], ptr [[Q]] ; CGSCC-NEXT: [[VAL:%.*]] = load i32, ptr [[TMP2]], align 4 -; CGSCC-NEXT: store i32 0, ptr [[TMP]], align 4 +; CGSCC-NEXT: [[TMP0:%.*]] = addrspacecast ptr [[TMP]] to ptr addrspace(1) +; CGSCC-NEXT: store i32 0, ptr addrspace(1) [[TMP0]], align 4 ; CGSCC-NEXT: store ptr [[Q]], ptr @g, align 8 ; CGSCC-NEXT: ret i32 [[VAL]] ; diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll --- a/llvm/test/Transforms/Attributor/value-simplify.ll +++ b/llvm/test/Transforms/Attributor/value-simplify.ll @@ -11,11 +11,11 @@ @ConstAS3Ptr = addrspace(3) global i32 0, align 4 ;. -; CHECK: @[[STR:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr addrspace(4) constant [1 x i8] zeroinitializer, align 1 -; CHECK: @[[CONSTAS3PTR:[a-zA-Z0-9_$"\\.-]+]] = addrspace(3) global i32 0, align 4 -; CHECK: @[[S:[a-zA-Z0-9_$"\\.-]+]] = external global [[STRUCT_X:%.*]] -; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = internal constant { [2 x ptr] } { [2 x ptr] [ptr @f1, ptr @f2] } -; CHECK: @[[X:[a-zA-Z0-9_$"\\.-]+]] = external global i32 +; CHECK: @str = private unnamed_addr addrspace(4) constant [1 x i8] zeroinitializer, align 1 +; CHECK: @ConstAS3Ptr = addrspace(3) global i32 0, align 4 +; CHECK: @S = external global %struct.X +; CHECK: @g = internal constant { [2 x ptr] } { [2 x ptr] [ptr @f1, ptr @f2] } +; CHECK: @x = external global i32 ;. define internal ptr addrspace(3) @const_ptr_return_as3() { ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) @@ -794,7 +794,8 @@ ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) ; TUNIT-LABEL: define {{[^@]+}}@user ; TUNIT-SAME: () #[[ATTR4]] { -; TUNIT-NEXT: store i32 0, ptr addrspacecast (ptr addrspace(3) @ConstAS3Ptr to ptr), align 4 +; TUNIT-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspacecast (ptr addrspace(3) @ConstAS3Ptr to ptr) to ptr addrspace(3) +; TUNIT-NEXT: store i32 0, ptr addrspace(3) [[TMP1]], align 4 ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)