From 62f7888d6d9d98481a1373db1d7804b49c69ec12 Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Thu, 19 May 2022 17:20:48 -0500 Subject: [PATCH] [Attributor] Dominating must-write accesses allow unknown initial values If we have a dominating must-write access we do not need to know the initial value of some object to perform reasoning about the potential values. The dominating must-write has overwritten the initial value. --- llvm/include/llvm/Transforms/IPO/Attributor.h | 51 ++++-- llvm/lib/Transforms/IPO/Attributor.cpp | 34 ++-- .../Transforms/IPO/AttributorAttributes.cpp | 72 +++++--- .../ArgumentPromotion/aggregate-promote.ll | 4 +- .../Attributor/ArgumentPromotion/alignment.ll | 4 +- .../Attributor/ArgumentPromotion/attrs.ll | 2 +- .../Attributor/ArgumentPromotion/basictest.ll | 4 +- .../Attributor/ArgumentPromotion/byval-2.ll | 2 +- .../Attributor/ArgumentPromotion/byval.ll | 4 +- .../ArgumentPromotion/control-flow2.ll | 2 +- .../Attributor/ArgumentPromotion/profile.ll | 2 +- .../Transforms/Attributor/internal-noalias.ll | 2 +- .../Attributor/value-simplify-pointer-info.ll | 164 ++++++++++-------- llvm/test/Transforms/Attributor/wrapper.ll | 2 +- 14 files changed, 220 insertions(+), 129 deletions(-) diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h index adfd0bc0556ca..d8b671f45bca4 100644 --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -4913,19 +4913,36 @@ struct AAPointerInfo : public AbstractAttribute { AAPointerInfo(const IRPosition &IRP) : AbstractAttribute(IRP) {} enum AccessKind { - AK_READ = 1 << 0, - AK_WRITE = 1 << 1, - AK_READ_WRITE = AK_READ | AK_WRITE, + // First two bits to distinguish may and must accesses + AK_MUST = 1 << 0, + AK_MAY = 1 << 1, + + // Then two bits for read and write. These are not exclusive. + AK_R = 1 << 2, + AK_W = 1 << 3, + AK_RW = AK_R | AK_W, + + // Helper for easy access. + AK_MAY_READ = AK_MAY | AK_R, + AK_MAY_WRITE = AK_MAY | AK_W, + AK_MAY_READ_WRITE = AK_MAY | AK_R | AK_W, + AK_MUST_READ = AK_MUST | AK_R, + AK_MUST_WRITE = AK_MUST | AK_W, + AK_MUST_READ_WRITE = AK_MUST | AK_R | AK_W, }; /// An access description. struct Access { Access(Instruction *I, Optional Content, AccessKind Kind, Type *Ty) - : LocalI(I), RemoteI(I), Content(Content), Kind(Kind), Ty(Ty) {} + : LocalI(I), RemoteI(I), Content(Content), Kind(Kind), Ty(Ty) { + verify(); + } Access(Instruction *LocalI, Instruction *RemoteI, Optional Content, AccessKind Kind, Type *Ty) : LocalI(LocalI), RemoteI(RemoteI), Content(Content), Kind(Kind), - Ty(Ty) {} + Ty(Ty) { + verify(); + } Access(const Access &Other) = default; Access(const Access &&Other) : LocalI(Other.LocalI), RemoteI(Other.RemoteI), Content(Other.Content), @@ -4946,14 +4963,22 @@ struct AAPointerInfo : public AbstractAttribute { return *this; } + void verify() { + assert(isMustAccess() + isMayAccess() == 1 && + "Expect must or may access, not both."); + } + /// Return the access kind. AccessKind getKind() const { return Kind; } /// Return true if this is a read access. - bool isRead() const { return Kind & AK_READ; } + bool isRead() const { return Kind & AK_R; } /// Return true if this is a write access. - bool isWrite() const { return Kind & AK_WRITE; } + bool isWrite() const { return Kind & AK_W; } + + bool isMustAccess() const { return Kind & AK_MUST; } + bool isMayAccess() const { return Kind & AK_MAY; } /// Return the instruction that causes the access with respect to the local /// scope of the associated attribute. @@ -5057,10 +5082,14 @@ struct AAPointerInfo : public AbstractAttribute { /// return true if all such accesses were known and the callback returned true /// for all of them, false otherwise. In contrast to forallInterferingAccesses /// this function will perform reasoning to exclude write accesses that cannot - /// affect the load even if they on the surface look as if they would. - virtual bool forallInterferingAccesses( - Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I, - function_ref CB) const = 0; + /// affect the load even if they on the surface look as if they would. The + /// flag \p HasBeenWrittenTo will be set to true if we know that \p I does not + /// read the intial value of the underlying memory. + virtual bool + forallInterferingAccesses(Attributor &A, const AbstractAttribute &QueryingAA, + Instruction &I, + function_ref CB, + bool &HasBeenWrittenTo) const = 0; /// This function should return true if the type of the \p AA is AAPointerInfo static bool classof(const AbstractAttribute *AA) { diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 952c188a582d0..83029cf1b8949 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -389,17 +389,6 @@ static bool getPotentialCopiesOfMemoryValue( NullOnly = false; }; - if (IsLoad) { - Value *InitialValue = AA::getInitialValueForObj(*Obj, *I.getType(), TLI); - if (!InitialValue) { - LLVM_DEBUG(dbgs() << "Failed to get initial value: " << *Obj << "\n"); - return false; - } - CheckForNullOnlyAndUndef(InitialValue, /* IsExact */ true); - NewCopies.push_back(InitialValue); - NewCopyOrigins.push_back(nullptr); - } - auto CheckAccess = [&](const AAPointerInfo::Access &Acc, bool IsExact) { if ((IsLoad && !Acc.isWrite()) || (!IsLoad && !Acc.isRead())) return true; @@ -448,15 +437,36 @@ static bool getPotentialCopiesOfMemoryValue( return true; }; + // If the value has been written to we don't need the initial value of the + // object. + bool HasBeenWrittenTo = false; + auto &PI = A.getAAFor(QueryingAA, IRPosition::value(*Obj), DepClassTy::NONE); - if (!PI.forallInterferingAccesses(A, QueryingAA, I, CheckAccess)) { + if (!PI.forallInterferingAccesses(A, QueryingAA, I, CheckAccess, + HasBeenWrittenTo)) { LLVM_DEBUG( dbgs() << "Failed to verify all interfering accesses for underlying object: " << *Obj << "\n"); return false; } + + if (IsLoad && !HasBeenWrittenTo) { + Value *InitialValue = AA::getInitialValueForObj(*Obj, *I.getType(), TLI); + if (!InitialValue) + return false; + CheckForNullOnlyAndUndef(InitialValue, /* IsExact */ true); + if (NullRequired && !NullOnly) { + LLVM_DEBUG(dbgs() << "Non exact access but initial value that is not " + "null or undef, abort!\n"); + return false; + } + + NewCopies.push_back(InitialValue); + NewCopyOrigins.push_back(nullptr); + } + PIs.push_back(&PI); } diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index e9c928c28c7e9..e478c543f8bad 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -961,9 +961,14 @@ struct AAPointerInfoImpl const override { return State::forallInterferingAccesses(OAS, CB); } - bool forallInterferingAccesses( - Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I, - function_ref UserCB) const override { + + bool + forallInterferingAccesses(Attributor &A, const AbstractAttribute &QueryingAA, + Instruction &I, + function_ref UserCB, + bool &HasBeenWrittenTo) const override { + HasBeenWrittenTo = false; + SmallPtrSet DominatingWrites; SmallVector, 8> InterferingAccesses; @@ -999,14 +1004,12 @@ struct AAPointerInfoImpl const bool FindInterferingWrites = I.mayReadFromMemory(); const bool FindInterferingReads = I.mayWriteToMemory(); - const bool UseDominanceReasoning = FindInterferingWrites; + const bool UseDominanceReasoning = + FindInterferingWrites && NoRecurseAA.isKnownNoRecurse(); const bool CanUseCFGResoning = CanIgnoreThreading(I); InformationCache &InfoCache = A.getInfoCache(); const DominatorTree *DT = - NoRecurseAA.isKnownNoRecurse() && UseDominanceReasoning - ? InfoCache.getAnalysisResultForFunction( - Scope) - : nullptr; + InfoCache.getAnalysisResultForFunction(Scope); enum GPUAddressSpace : unsigned { Generic = 0, @@ -1063,6 +1066,12 @@ struct AAPointerInfoImpl (!FindInterferingReads || !Acc.isRead())) return true; + bool Dominates = DT && Exact && Acc.isMustAccess() && + (Acc.getLocalInst()->getFunction() == &Scope) && + DT->dominates(Acc.getRemoteInst(), &I); + if (Dominates) + HasBeenWrittenTo = true; + // For now we only filter accesses based on CFG reasoning which does not // work yet if we have threading effects, or the access is complicated. if (CanUseCFGResoning) { @@ -1073,11 +1082,8 @@ struct AAPointerInfoImpl !AA::isPotentiallyReachable(A, I, *Acc.getLocalInst(), QueryingAA, IsLiveInCalleeCB))) return true; - if (DT && Exact && (Acc.getLocalInst()->getFunction() == &Scope) && - IsSameThreadAsLoad(Acc)) { - if (DT->dominates(Acc.getLocalInst(), &I)) - DominatingWrites.insert(&Acc); - } + if (Dominates && UseDominanceReasoning && IsSameThreadAsLoad(Acc)) + DominatingWrites.insert(&Acc); } InterferingAccesses.push_back({&Acc, Exact}); @@ -1120,7 +1126,8 @@ struct AAPointerInfoImpl // succeeded for all or not. unsigned NumInterferingAccesses = InterferingAccesses.size(); for (auto &It : InterferingAccesses) { - if (!DT || NumInterferingAccesses > MaxInterferingAccesses || + if (!DT || !UseDominanceReasoning || + NumInterferingAccesses > MaxInterferingAccesses || !CanSkipAccess(*It.first, It.second)) { if (!UserCB(*It.first, It.second)) return false; @@ -1156,8 +1163,9 @@ struct AAPointerInfoImpl if (FromCallee) { Content = A.translateArgumentToCallSiteContent( RAcc.getContent(), CB, *this, UsedAssumedInformation); - AK = AccessKind( - AK & (IsByval ? AccessKind::AK_READ : AccessKind::AK_READ_WRITE)); + AK = + AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW)); + AK = AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST)); } Changed = Changed | addAccess(A, OAS.getOffset(), OAS.getSize(), CB, Content, @@ -1345,21 +1353,37 @@ struct AAPointerInfoFloating : public AAPointerInfoImpl { return true; } - if (auto *LoadI = dyn_cast(Usr)) - return handleAccess(A, *LoadI, *CurPtr, /* Content */ nullptr, - AccessKind::AK_READ, OffsetInfoMap[CurPtr].Offset, - Changed, LoadI->getType()); + if (auto *LoadI = dyn_cast(Usr)) { + // If the access is to a pointer that may or may not be the associated + // value, e.g. due to a PHI, we cannot assume it will be read. + AccessKind AK = AccessKind::AK_R; + if (getUnderlyingObject(CurPtr) == &AssociatedValue) + AK = AccessKind(AK | AccessKind::AK_MUST); + else + AK = AccessKind(AK | AccessKind::AK_MAY); + return handleAccess(A, *LoadI, *CurPtr, /* Content */ nullptr, AK, + OffsetInfoMap[CurPtr].Offset, Changed, + LoadI->getType()); + } + if (auto *StoreI = dyn_cast(Usr)) { if (StoreI->getValueOperand() == CurPtr) { LLVM_DEBUG(dbgs() << "[AAPointerInfo] Escaping use in store " << *StoreI << "\n"); return false; } + // If the access is to a pointer that may or may not be the associated + // value, e.g. due to a PHI, we cannot assume it will be written. + AccessKind AK = AccessKind::AK_W; + if (getUnderlyingObject(CurPtr) == &AssociatedValue) + AK = AccessKind(AK | AccessKind::AK_MUST); + else + AK = AccessKind(AK | AccessKind::AK_MAY); bool UsedAssumedInformation = false; Optional Content = A.getAssumedSimplified(*StoreI->getValueOperand(), *this, UsedAssumedInformation, AA::Interprocedural); - return handleAccess(A, *StoreI, *CurPtr, Content, AccessKind::AK_WRITE, + return handleAccess(A, *StoreI, *CurPtr, Content, AK, OffsetInfoMap[CurPtr].Offset, Changed, StoreI->getValueOperand()->getType()); } @@ -1474,10 +1498,10 @@ struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating { unsigned ArgNo = getIRPosition().getCallSiteArgNo(); ChangeStatus Changed = ChangeStatus::UNCHANGED; if (ArgNo == 0) { - handleAccess(A, *MI, Ptr, nullptr, AccessKind::AK_WRITE, 0, Changed, - nullptr, LengthVal); + handleAccess(A, *MI, Ptr, nullptr, AccessKind::AK_MUST_WRITE, 0, + Changed, nullptr, LengthVal); } else if (ArgNo == 1) { - handleAccess(A, *MI, Ptr, nullptr, AccessKind::AK_READ, 0, Changed, + handleAccess(A, *MI, Ptr, nullptr, AccessKind::AK_MUST_READ, 0, Changed, nullptr, LengthVal); } else { LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled memory intrinsic " diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll index e49e90a0388e2..5eea4d2aa00ea 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals -; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM -; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM +; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM +; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll index 023bdc7b31294..d4e6dc1486a0c 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll @@ -110,7 +110,7 @@ define internal i32 @caller(i32* %A) { ; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: [[A_PRIV:%.*]] = alloca i32, align 4 ; IS__CGSCC_NPM-NEXT: store i32 [[TMP0]], i32* [[A_PRIV]], align 4 -; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A_PRIV]], i64 1) #[[ATTR3:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A_PRIV]], i64 noundef 1) #[[ATTR3:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 [[C]] ; %B = alloca i64 @@ -137,7 +137,7 @@ define i32 @callercaller() { ; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@callercaller ; IS__CGSCC_NPM-SAME: () #[[ATTR2:[0-9]+]] { -; IS__CGSCC_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32 2) #[[ATTR4:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32 noundef 2) #[[ATTR4:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 [[X]] ; %B = alloca i32 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll index 31295fc3f73f0..95cba52ea1977 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll @@ -105,7 +105,7 @@ define i32 @test(i32* %X) { ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 ; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 ; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[X]], align 4 -; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @f(i32 1, i64 2, i32 [[TMP0]]) #[[ATTR2:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @f(i32 noundef 1, i64 noundef 2, i32 [[TMP0]]) #[[ATTR2:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 [[C]] ; entry: diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll index 28f621500ed5c..ba1e3668403b5 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll @@ -44,7 +44,7 @@ define internal i32 @caller(i32* %B) { ; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__CGSCC_NPM-NEXT: [[B_PRIV:%.*]] = alloca i32, align 4 ; IS__CGSCC_NPM-NEXT: store i32 [[TMP0]], i32* [[B_PRIV]], align 4 -; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @test(i32 1, i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B_PRIV]]) #[[ATTR3:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @test(i32 noundef 1, i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B_PRIV]]) #[[ATTR3:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 [[C]] ; %A = alloca i32 @@ -71,7 +71,7 @@ define i32 @callercaller() { ; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@callercaller ; IS__CGSCC_NPM-SAME: () #[[ATTR2:[0-9]+]] { -; IS__CGSCC_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32 2) #[[ATTR4:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32 noundef 2) #[[ATTR4:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 [[X]] ; %B = alloca i32 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll index 9ae184452d773..e0966f97eac34 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll @@ -95,7 +95,7 @@ define i32 @test(i32* %X) { ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 ; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 ; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[X]], align 4 -; IS__CGSCC_NPM-NEXT: call void @f(i32 1, i64 2, i32 [[TMP0]]) #[[ATTR2:[0-9]+]] +; IS__CGSCC_NPM-NEXT: call void @f(i32 noundef 1, i64 noundef 2, i32 [[TMP0]]) #[[ATTR2:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 0 ; entry: diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll index f49d30b8ee522..063acfbf2121a 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll @@ -134,8 +134,8 @@ define i32 @main() nounwind { ; IS__CGSCC_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 ; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; IS__CGSCC_NPM-NEXT: [[C0:%.*]] = call i32 @f(i32 1, i64 2) #[[ATTR2:[0-9]+]] -; IS__CGSCC_NPM-NEXT: [[C1:%.*]] = call i32 @g(i32 1, i64 2) #[[ATTR2]] +; IS__CGSCC_NPM-NEXT: [[C0:%.*]] = call i32 @f(i32 noundef 1, i64 noundef 2) #[[ATTR2:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[C1:%.*]] = call i32 @g(i32 noundef 1, i64 noundef 2) #[[ATTR2]] ; IS__CGSCC_NPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] ; IS__CGSCC_NPM-NEXT: ret i32 [[A]] ; diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll index 0dac5c3195a33..112f70c824d48 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll @@ -57,7 +57,7 @@ define i32 @foo() { ; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@foo ; IS__CGSCC_NPM-SAME: () #[[ATTR1:[0-9]+]] { -; IS__CGSCC_NPM-NEXT: [[X:%.*]] = call i32 @callee(i32 17) #[[ATTR2:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[X:%.*]] = call i32 @callee(i32 noundef 17) #[[ATTR2:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 [[X]] ; %A = alloca i32 ; [#uses=2] diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll index 20f7d0dd65378..2b5829e759d4b 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll @@ -22,7 +22,7 @@ define void @caller() #0 { ; IS__TUNIT_NPM-NEXT: ret void ; ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@caller() { -; IS__CGSCC_NPM-NEXT: call void @promote_i32_ptr(i32 42), !prof [[PROF0:![0-9]+]] +; IS__CGSCC_NPM-NEXT: call void @promote_i32_ptr(i32 noundef 42), !prof [[PROF0:![0-9]+]] ; IS__CGSCC_NPM-NEXT: ret void ; %x = alloca i32 diff --git a/llvm/test/Transforms/Attributor/internal-noalias.ll b/llvm/test/Transforms/Attributor/internal-noalias.ll index a9b4bb4d178c5..60df30cd37705 100644 --- a/llvm/test/Transforms/Attributor/internal-noalias.ll +++ b/llvm/test/Transforms/Attributor/internal-noalias.ll @@ -166,7 +166,7 @@ define i32 @visible_local_2() { ; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@visible_local_2 ; IS__CGSCC_NPM-SAME: () #[[ATTR3:[0-9]+]] { -; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_ro(i32 5, i32 5) #[[ATTR6:[0-9]+]] +; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_ro(i32 noundef 5, i32 noundef 5) #[[ATTR6:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret i32 [[CALL]] ; %B = alloca i32, align 4 diff --git a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll index e99886f8b3b46..eb5d3fa78bc72 100644 --- a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll +++ b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll @@ -1599,19 +1599,24 @@ for.end35: ; preds = %for.cond.cleanup27 ; return Flag3; ; } define i32 @static_global_simplifiable_3() { -; NOT_TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn -; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@static_global_simplifiable_3 -; NOT_TUNIT_NPM-SAME: () #[[ATTR5:[0-9]+]] { -; NOT_TUNIT_NPM-NEXT: store i32 1, i32* @Flag3, align 4, !tbaa [[TBAA3]] -; NOT_TUNIT_NPM-NEXT: [[I:%.*]] = load i32, i32* @Flag3, align 4, !tbaa [[TBAA3]] -; NOT_TUNIT_NPM-NEXT: ret i32 [[I]] +; IS________OPM: Function Attrs: nofree norecurse nosync nounwind willreturn +; IS________OPM-LABEL: define {{[^@]+}}@static_global_simplifiable_3 +; IS________OPM-SAME: () #[[ATTR5:[0-9]+]] { +; IS________OPM-NEXT: store i32 1, i32* @Flag3, align 4, !tbaa [[TBAA3]] +; IS________OPM-NEXT: [[I:%.*]] = load i32, i32* @Flag3, align 4, !tbaa [[TBAA3]] +; IS________OPM-NEXT: ret i32 [[I]] ; -; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn +; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@static_global_simplifiable_3 -; IS__TUNIT_NPM-SAME: () #[[ATTR3]] { +; IS__TUNIT_NPM-SAME: () #[[ATTR5]] { ; IS__TUNIT_NPM-NEXT: store i32 1, i32* @Flag3, align 4, !tbaa [[TBAA3]] -; IS__TUNIT_NPM-NEXT: [[I:%.*]] = load i32, i32* @Flag3, align 4, !tbaa [[TBAA3]] -; IS__TUNIT_NPM-NEXT: ret i32 [[I]] +; IS__TUNIT_NPM-NEXT: ret i32 1 +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@static_global_simplifiable_3 +; IS__CGSCC_NPM-SAME: () #[[ATTR6:[0-9]+]] { +; IS__CGSCC_NPM-NEXT: store i32 1, i32* @Flag3, align 4, !tbaa [[TBAA3]] +; IS__CGSCC_NPM-NEXT: ret i32 1 ; store i32 1, i32* @Flag3, align 4, !tbaa !3 %i = load i32, i32* @Flag3, align 4, !tbaa !3 @@ -2555,19 +2560,19 @@ define i32 @global_not_simplifiable_1(i32 %cnd) { ; IS__TUNIT_OPM-NEXT: [[I:%.*]] = load i32, i32* @Flag0, align 4, !tbaa [[TBAA3]] ; IS__TUNIT_OPM-NEXT: ret i32 [[I]] ; -; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn -; IS________NPM-LABEL: define {{[^@]+}}@global_not_simplifiable_1 -; IS________NPM-SAME: (i32 [[CND:%.*]]) #[[ATTR6:[0-9]+]] { -; IS________NPM-NEXT: entry: -; IS________NPM-NEXT: [[I:%.*]] = load i32, i32* @Flag0, align 4, !tbaa [[TBAA3]] -; IS________NPM-NEXT: ret i32 [[I]] +; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@global_not_simplifiable_1 +; IS__TUNIT_NPM-SAME: (i32 [[CND:%.*]]) #[[ATTR6:[0-9]+]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[I:%.*]] = load i32, i32* @Flag0, align 4, !tbaa [[TBAA3]] +; IS__TUNIT_NPM-NEXT: ret i32 [[I]] ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn -; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@global_not_simplifiable_1 -; IS__CGSCC_OPM-SAME: (i32 [[CND:%.*]]) #[[ATTR7:[0-9]+]] { -; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[I:%.*]] = load i32, i32* @Flag0, align 4, !tbaa [[TBAA3]] -; IS__CGSCC_OPM-NEXT: ret i32 [[I]] +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@global_not_simplifiable_1 +; IS__CGSCC____-SAME: (i32 [[CND:%.*]]) #[[ATTR7:[0-9]+]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[I:%.*]] = load i32, i32* @Flag0, align 4, !tbaa [[TBAA3]] +; IS__CGSCC____-NEXT: ret i32 [[I]] ; entry: %i = load i32, i32* @Flag0, align 4, !tbaa !3 @@ -2637,6 +2642,31 @@ entry: ret i32 %i } +; Similiar to static_global_simplifiable_3 but with a may-store. +define i32 @static_global_not_simplifiable_3(i1 %c, i32* %p) { +; NOT_TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@static_global_not_simplifiable_3 +; NOT_TUNIT_NPM-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR5:[0-9]+]] { +; NOT_TUNIT_NPM-NEXT: [[SEL:%.*]] = select i1 [[C]], i32* @Flag3, i32* [[P]] +; NOT_TUNIT_NPM-NEXT: store i32 1, i32* [[SEL]], align 4, !tbaa [[TBAA3]] +; NOT_TUNIT_NPM-NEXT: [[I:%.*]] = load i32, i32* @Flag3, align 4, !tbaa [[TBAA3]] +; NOT_TUNIT_NPM-NEXT: ret i32 [[I]] +; +; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@static_global_not_simplifiable_3 +; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR3]] { +; IS__TUNIT_NPM-NEXT: [[SEL:%.*]] = select i1 [[C]], i32* @Flag3, i32* [[P]] +; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[SEL]], align 4, !tbaa [[TBAA3]] +; IS__TUNIT_NPM-NEXT: [[I:%.*]] = load i32, i32* @Flag3, align 4, !tbaa [[TBAA3]] +; IS__TUNIT_NPM-NEXT: ret i32 [[I]] +; + %sel = select i1 %c, i32* @Flag3, i32* %p + store i32 1, i32* %sel, align 4, !tbaa !3 + %i = load i32, i32* @Flag3, align 4, !tbaa !3 + ret i32 %i +} + + ; int write_read{,_static,_static_undef}_global(void) { ; Gint{,static,_static_undef}1 = 7; ; return Gint1; @@ -2689,7 +2719,7 @@ define void @write_global() { ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@write_global -; IS__CGSCC_NPM-SAME: () #[[ATTR7:[0-9]+]] { +; IS__CGSCC_NPM-SAME: () #[[ATTR6]] { ; IS__CGSCC_NPM-NEXT: store i32 7, i32* @Gint2, align 4 ; IS__CGSCC_NPM-NEXT: ret void ; @@ -2703,36 +2733,38 @@ define i32 @read_global() { ; IS__TUNIT_OPM-NEXT: [[L:%.*]] = load i32, i32* @Gint2, align 4 ; IS__TUNIT_OPM-NEXT: ret i32 [[L]] ; -; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn -; IS________NPM-LABEL: define {{[^@]+}}@read_global -; IS________NPM-SAME: () #[[ATTR6]] { -; IS________NPM-NEXT: [[L:%.*]] = load i32, i32* @Gint2, align 4 -; IS________NPM-NEXT: ret i32 [[L]] +; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@read_global +; IS__TUNIT_NPM-SAME: () #[[ATTR6]] { +; IS__TUNIT_NPM-NEXT: [[L:%.*]] = load i32, i32* @Gint2, align 4 +; IS__TUNIT_NPM-NEXT: ret i32 [[L]] ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn -; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@read_global -; IS__CGSCC_OPM-SAME: () #[[ATTR7]] { -; IS__CGSCC_OPM-NEXT: [[L:%.*]] = load i32, i32* @Gint2, align 4 -; IS__CGSCC_OPM-NEXT: ret i32 [[L]] +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@read_global +; IS__CGSCC____-SAME: () #[[ATTR7]] { +; IS__CGSCC____-NEXT: [[L:%.*]] = load i32, i32* @Gint2, align 4 +; IS__CGSCC____-NEXT: ret i32 [[L]] ; %l = load i32, i32* @Gint2 ret i32 %l } -; FIXME: We could replace these loads. define i32 @write_read_static_global() { -; NOT_TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn -; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@write_read_static_global -; NOT_TUNIT_NPM-SAME: () #[[ATTR5]] { -; NOT_TUNIT_NPM-NEXT: store i32 7, i32* @Gstatic_int1, align 4 -; NOT_TUNIT_NPM-NEXT: [[L:%.*]] = load i32, i32* @Gstatic_int1, align 4 -; NOT_TUNIT_NPM-NEXT: ret i32 [[L]] +; IS________OPM: Function Attrs: nofree norecurse nosync nounwind willreturn +; IS________OPM-LABEL: define {{[^@]+}}@write_read_static_global +; IS________OPM-SAME: () #[[ATTR5]] { +; IS________OPM-NEXT: store i32 7, i32* @Gstatic_int1, align 4 +; IS________OPM-NEXT: [[L:%.*]] = load i32, i32* @Gstatic_int1, align 4 +; IS________OPM-NEXT: ret i32 [[L]] ; -; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn +; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@write_read_static_global -; IS__TUNIT_NPM-SAME: () #[[ATTR3]] { -; IS__TUNIT_NPM-NEXT: store i32 7, i32* @Gstatic_int1, align 4 -; IS__TUNIT_NPM-NEXT: [[L:%.*]] = load i32, i32* @Gstatic_int1, align 4 -; IS__TUNIT_NPM-NEXT: ret i32 [[L]] +; IS__TUNIT_NPM-SAME: () #[[ATTR5]] { +; IS__TUNIT_NPM-NEXT: ret i32 7 +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@write_read_static_global +; IS__CGSCC_NPM-SAME: () #[[ATTR6]] { +; IS__CGSCC_NPM-NEXT: ret i32 7 ; store i32 7, i32* @Gstatic_int1 %l = load i32, i32* @Gstatic_int1 @@ -2759,7 +2791,7 @@ define void @write_static_global() { ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@write_static_global -; IS__CGSCC_NPM-SAME: () #[[ATTR7]] { +; IS__CGSCC_NPM-SAME: () #[[ATTR6]] { ; IS__CGSCC_NPM-NEXT: store i32 7, i32* @Gstatic_int2, align 4 ; IS__CGSCC_NPM-NEXT: ret void ; @@ -2773,17 +2805,17 @@ define i32 @read_static_global() { ; IS__TUNIT_OPM-NEXT: [[L:%.*]] = load i32, i32* @Gstatic_int2, align 4 ; IS__TUNIT_OPM-NEXT: ret i32 [[L]] ; -; IS________NPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn -; IS________NPM-LABEL: define {{[^@]+}}@read_static_global -; IS________NPM-SAME: () #[[ATTR6]] { -; IS________NPM-NEXT: [[L:%.*]] = load i32, i32* @Gstatic_int2, align 4 -; IS________NPM-NEXT: ret i32 [[L]] +; IS__TUNIT_NPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@read_static_global +; IS__TUNIT_NPM-SAME: () #[[ATTR6]] { +; IS__TUNIT_NPM-NEXT: [[L:%.*]] = load i32, i32* @Gstatic_int2, align 4 +; IS__TUNIT_NPM-NEXT: ret i32 [[L]] ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn -; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@read_static_global -; IS__CGSCC_OPM-SAME: () #[[ATTR7]] { -; IS__CGSCC_OPM-NEXT: [[L:%.*]] = load i32, i32* @Gstatic_int2, align 4 -; IS__CGSCC_OPM-NEXT: ret i32 [[L]] +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@read_static_global +; IS__CGSCC____-SAME: () #[[ATTR7]] { +; IS__CGSCC____-NEXT: [[L:%.*]] = load i32, i32* @Gstatic_int2, align 4 +; IS__CGSCC____-NEXT: ret i32 [[L]] ; %l = load i32, i32* @Gstatic_int2 ret i32 %l @@ -2806,7 +2838,7 @@ define i32 @write_read_static_undef_global() { ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@write_read_static_undef_global -; IS__CGSCC_NPM-SAME: () #[[ATTR7]] { +; IS__CGSCC_NPM-SAME: () #[[ATTR6]] { ; IS__CGSCC_NPM-NEXT: ret i32 7 ; store i32 7, i32* @Gstatic_undef_int1 @@ -2832,7 +2864,7 @@ define void @write_static_undef_global() { ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@write_static_undef_global -; IS__CGSCC_NPM-SAME: () #[[ATTR7]] { +; IS__CGSCC_NPM-SAME: () #[[ATTR6]] { ; IS__CGSCC_NPM-NEXT: store i32 7, i32* @Gstatic_undef_int2, align 4 ; IS__CGSCC_NPM-NEXT: ret void ; @@ -3516,14 +3548,13 @@ define dso_local i32 @round_trip_calloc(i32 %x) { ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] ; ; IS________NPM-LABEL: define {{[^@]+}}@round_trip_calloc -; IS________NPM-SAME: (i32 [[X:%.*]]) { +; IS________NPM-SAME: (i32 returned [[X:%.*]]) { ; IS________NPM-NEXT: entry: ; IS________NPM-NEXT: [[CALL_H2S:%.*]] = alloca i8, i64 4, align 1 ; IS________NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALL_H2S]], i8 0, i64 4, i1 false) ; IS________NPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL_H2S]] to i32* ; IS________NPM-NEXT: store i32 [[X]], i32* [[TMP0]], align 4 -; IS________NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS________NPM-NEXT: ret i32 [[TMP1]] +; IS________NPM-NEXT: ret i32 [[X]] ; ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@round_trip_calloc ; IS__CGSCC_OPM-SAME: (i32 [[X:%.*]]) { @@ -3555,10 +3586,7 @@ define dso_local i32 @round_trip_calloc_constant() { ; IS________NPM-NEXT: entry: ; IS________NPM-NEXT: [[CALL_H2S:%.*]] = alloca i8, i64 4, align 1 ; IS________NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALL_H2S]], i8 0, i64 4, i1 false) -; IS________NPM-NEXT: [[TMP0:%.*]] = bitcast i8* [[CALL_H2S]] to i32* -; IS________NPM-NEXT: store i32 11, i32* [[TMP0]], align 4 -; IS________NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS________NPM-NEXT: ret i32 [[TMP1]] +; IS________NPM-NEXT: ret i32 11 ; ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@round_trip_calloc_constant() { ; IS__CGSCC_OPM-NEXT: entry: @@ -3994,7 +4022,7 @@ define dso_local void @test_nested_memory(float* %dst, double* %src) { ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = bitcast i8* [[SRC2]] to double** ; IS__CGSCC_NPM-NEXT: store double* [[SRC]], double** [[TMP1]], align 8 ; IS__CGSCC_NPM-NEXT: store i8* [[CALL]], i8** bitcast (%struct.STy** getelementptr inbounds ([[STRUCT_STY]], %struct.STy* @global, i64 0, i32 2) to i8**), align 8 -; IS__CGSCC_NPM-NEXT: call fastcc void @nested_memory_callee(float* nofree nonnull align 4294967296 undef, double* nofree nonnull align 4294967296 undef, %struct.STy* nofree nonnull align 8 @global) #[[ATTR17:[0-9]+]] +; IS__CGSCC_NPM-NEXT: call fastcc void @nested_memory_callee(float* nofree nonnull align 4294967296 undef, double* nofree nonnull align 4294967296 undef, %struct.STy* nofree noundef nonnull align 8 dereferenceable(24) @global) #[[ATTR17:[0-9]+]] ; IS__CGSCC_NPM-NEXT: ret void ; entry: @@ -4534,8 +4562,8 @@ define i1 @alloca_non_unique_caller(i32 %in, i1 %c) { ; IS__CGSCC_NPM: attributes #[[ATTR3]] = { nofree nosync nounwind willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR4]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR5]] = { nofree norecurse nosync nounwind willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR6]] = { nofree norecurse nosync nounwind readonly willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR7]] = { nofree norecurse nosync nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR6]] = { nofree norecurse nosync nounwind willreturn writeonly } +; IS__CGSCC_NPM: attributes #[[ATTR7]] = { nofree norecurse nosync nounwind readonly willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind writeonly } ; IS__CGSCC_NPM: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind willreturn uwtable } ; IS__CGSCC_NPM: attributes #[[ATTR10]] = { argmemonly nofree norecurse nosync nounwind willreturn } diff --git a/llvm/test/Transforms/Attributor/wrapper.ll b/llvm/test/Transforms/Attributor/wrapper.ll index 5a0f68f507537..85bf78a69d2ea 100644 --- a/llvm/test/Transforms/Attributor/wrapper.ll +++ b/llvm/test/Transforms/Attributor/wrapper.ll @@ -9,7 +9,7 @@ ; ; Check the original function, which is wrapped and becomes anonymous ; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; CHECK: define internal i32 @0() +; CHECK: define internal noundef i32 @0() ; CHECK: ret i32 1 define linkonce i32 @inner1() { entry: