[llvm] 00b09a7 - Revert "[AAPointerInfo] refactor how offsets and Access objects are tracked"
Ye Luo via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 2 22:03:44 PDT 2022
Author: Ye Luo
Date: 2022-11-03T00:01:51-05:00
New Revision: 00b09a7b18abb253d36b3d3e1c546007288f6e89
URL: https://github.com/llvm/llvm-project/commit/00b09a7b18abb253d36b3d3e1c546007288f6e89
DIFF: https://github.com/llvm/llvm-project/commit/00b09a7b18abb253d36b3d3e1c546007288f6e89.diff
LOG: Revert "[AAPointerInfo] refactor how offsets and Access objects are tracked"
This reverts commit b756096b0cbef0918394851644649b3c28a886e2.
See regression https://github.com/llvm/llvm-project/issues/58774
Added:
Modified:
llvm/include/llvm/Transforms/IPO/Attributor.h
llvm/lib/Transforms/IPO/Attributor.cpp
llvm/lib/Transforms/IPO/AttributorAttributes.cpp
llvm/test/Transforms/Attributor/call-simplify-pointer-info.ll
llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index 69e52581e1d9..61c26dfabed0 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -250,22 +250,6 @@ struct OffsetAndSize {
return OAS.Offset + OAS.Size > Offset && OAS.Offset < Offset + Size;
}
- OffsetAndSize &operator&=(const OffsetAndSize &R) {
- if (Offset == Unassigned)
- Offset = R.Offset;
- else if (R.Offset != Unassigned && R.Offset != Offset)
- Offset = Unknown;
-
- if (Size == Unassigned)
- Size = R.Size;
- else if (Size == Unknown || R.Size == Unknown)
- Size = Unknown;
- else if (R.Size != Unassigned)
- Size = std::max(Size, R.Size);
-
- return *this;
- }
-
/// Constants used to represent special offsets or sizes.
/// - This assumes that Offset and Size are non-negative.
/// - The constants should not clash with DenseMapInfo, such as EmptyKey
@@ -5008,47 +4992,33 @@ struct AAPointerInfo : public AbstractAttribute {
/// An access description.
struct Access {
- Access(Instruction *I, int64_t Offset, int64_t Size,
- Optional<Value *> Content, AccessKind Kind, Type *Ty)
- : LocalI(I), RemoteI(I), Content(Content), OAS(Offset, Size),
- Kind(Kind), Ty(Ty) {
+ Access(Instruction *I, Optional<Value *> Content, AccessKind Kind, Type *Ty)
+ : LocalI(I), RemoteI(I), Content(Content), Kind(Kind), Ty(Ty) {
verify();
}
- Access(Instruction *LocalI, Instruction *RemoteI, int64_t Offset,
- int64_t Size, Optional<Value *> Content, AccessKind Kind, Type *Ty)
- : LocalI(LocalI), RemoteI(RemoteI), Content(Content), OAS(Offset, Size),
- Kind(Kind), Ty(Ty) {
+ Access(Instruction *LocalI, Instruction *RemoteI, Optional<Value *> Content,
+ AccessKind Kind, Type *Ty)
+ : LocalI(LocalI), RemoteI(RemoteI), Content(Content), Kind(Kind),
+ Ty(Ty) {
verify();
}
Access(const Access &Other) = default;
Access(const Access &&Other)
: LocalI(Other.LocalI), RemoteI(Other.RemoteI), Content(Other.Content),
- OAS(Other.OAS), Kind(Other.Kind), Ty(Other.Ty) {}
+ Kind(Other.Kind), Ty(Other.Ty) {}
Access &operator=(const Access &Other) = default;
bool operator==(const Access &R) const {
- return LocalI == R.LocalI && RemoteI == R.RemoteI && OAS == R.OAS &&
+ return LocalI == R.LocalI && RemoteI == R.RemoteI &&
Content == R.Content && Kind == R.Kind;
}
bool operator!=(const Access &R) const { return !(*this == R); }
Access &operator&=(const Access &R) {
assert(RemoteI == R.RemoteI && "Expected same instruction!");
- assert(LocalI == R.LocalI && "Expected same instruction!");
+ Content =
+ AA::combineOptionalValuesInAAValueLatice(Content, R.Content, Ty);
Kind = AccessKind(Kind | R.Kind);
- auto Before = OAS;
- OAS &= R.OAS;
- if (Before.isUnassigned() || Before == OAS) {
- Content =
- AA::combineOptionalValuesInAAValueLatice(Content, R.Content, Ty);
- } else {
- // Since the OAS information changed, set a conservative state -- drop
- // the contents, and assume MayAccess rather than MustAccess.
- Content.reset();
- Kind = AccessKind(Kind | AK_MAY);
- Kind = AccessKind(Kind & ~AK_MUST);
- }
- verify();
return *this;
}
@@ -5096,12 +5066,6 @@ struct AAPointerInfo : public AbstractAttribute {
/// determined.
Optional<Value *> getContent() const { return Content; }
- /// Return the offset for this access.
- int64_t getOffset() const { return OAS.Offset; }
-
- /// Return the size for this access.
- int64_t getSize() const { return OAS.Size; }
-
private:
/// The instruction responsible for the access with respect to the local
/// scope of the associated attribute.
@@ -5114,9 +5078,6 @@ struct AAPointerInfo : public AbstractAttribute {
/// cannot be determined.
Optional<Value *> Content;
- /// The object accessed, in terms of an offset and size in bytes.
- AA::OffsetAndSize OAS;
-
/// The access kind, e.g., READ, as bitset (could be more than one).
AccessKind Kind;
@@ -5152,7 +5113,7 @@ struct AAPointerInfo : public AbstractAttribute {
virtual bool forallInterferingAccesses(
Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,
function_ref<bool(const Access &, bool)> CB, bool &HasBeenWrittenTo,
- AA::OffsetAndSize &OAS) const = 0;
+ AA::OffsetAndSize *OASPtr = nullptr) 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 2935127dcbc4..e8d7fe221225 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -457,7 +457,7 @@ static bool getPotentialCopiesOfMemoryValue(
auto &PI = A.getAAFor<AAPointerInfo>(QueryingAA, IRPosition::value(*Obj),
DepClassTy::NONE);
if (!PI.forallInterferingAccesses(A, QueryingAA, I, CheckAccess,
- HasBeenWrittenTo, OAS)) {
+ HasBeenWrittenTo, &OAS)) {
LLVM_DEBUG(
dbgs()
<< "Failed to verify all interfering accesses for underlying object: "
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index cbc1f8b77c02..c1850f737812 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -757,6 +757,13 @@ struct AccessAsInstructionInfo : DenseMapInfo<Instruction *> {
/// A type to track pointer/struct usage and accesses for AAPointerInfo.
struct AA::PointerInfo::State : public AbstractState {
+
+ ~State() {
+ // We do not delete the Accesses objects but need to destroy them still.
+ for (auto &It : AccessBins)
+ It.second->~Accesses();
+ }
+
/// Return the best possible representable state.
static State getBestState(const State &SIS) { return State(); }
@@ -768,7 +775,9 @@ struct AA::PointerInfo::State : public AbstractState {
}
State() = default;
- State(State &&SIS) = default;
+ State(State &&SIS) : AccessBins(std::move(SIS.AccessBins)) {
+ SIS.AccessBins.clear();
+ }
const State &getAssumed() const { return *this; }
@@ -794,9 +803,7 @@ struct AA::PointerInfo::State : public AbstractState {
if (this == &R)
return *this;
BS = R.BS;
- AccessList = R.AccessList;
- OffsetBins = R.OffsetBins;
- RemoteIMap = R.RemoteIMap;
+ AccessBins = R.AccessBins;
return *this;
}
@@ -804,52 +811,99 @@ struct AA::PointerInfo::State : public AbstractState {
if (this == &R)
return *this;
std::swap(BS, R.BS);
- std::swap(AccessList, R.AccessList);
- std::swap(OffsetBins, R.OffsetBins);
- std::swap(RemoteIMap, R.RemoteIMap);
+ std::swap(AccessBins, R.AccessBins);
return *this;
}
- /// Add a new Access to the state at offset \p Offset and with size \p Size.
+ bool operator==(const State &R) const {
+ if (BS != R.BS)
+ return false;
+ if (AccessBins.size() != R.AccessBins.size())
+ return false;
+ auto It = begin(), RIt = R.begin(), E = end();
+ while (It != E) {
+ if (It->getFirst() != RIt->getFirst())
+ return false;
+ auto &Accs = It->getSecond();
+ auto &RAccs = RIt->getSecond();
+ if (Accs->size() != RAccs->size())
+ return false;
+ for (const auto &ZipIt : llvm::zip(*Accs, *RAccs))
+ if (std::get<0>(ZipIt) != std::get<1>(ZipIt))
+ return false;
+ ++It;
+ ++RIt;
+ }
+ return true;
+ }
+ bool operator!=(const State &R) const { return !(*this == R); }
+
+ /// We store accesses in a set with the instruction as key.
+ struct Accesses {
+ SmallVector<AAPointerInfo::Access, 4> Accesses;
+ DenseMap<const Instruction *, unsigned> Map;
+
+ unsigned size() const { return Accesses.size(); }
+
+ using vec_iterator = decltype(Accesses)::iterator;
+ vec_iterator begin() { return Accesses.begin(); }
+ vec_iterator end() { return Accesses.end(); }
+
+ using iterator = decltype(Map)::const_iterator;
+ iterator find(AAPointerInfo::Access &Acc) {
+ return Map.find(Acc.getRemoteInst());
+ }
+ iterator find_end() { return Map.end(); }
+
+ AAPointerInfo::Access &get(iterator &It) {
+ return Accesses[It->getSecond()];
+ }
+
+ void insert(AAPointerInfo::Access &Acc) {
+ Map[Acc.getRemoteInst()] = Accesses.size();
+ Accesses.push_back(Acc);
+ }
+ };
+
+ /// We store all accesses in bins denoted by their offset and size.
+ using AccessBinsTy = DenseMap<AA::OffsetAndSize, Accesses *>;
+
+ AccessBinsTy::const_iterator begin() const { return AccessBins.begin(); }
+ AccessBinsTy::const_iterator end() const { return AccessBins.end(); }
+
+protected:
+ /// The bins with all the accesses for the associated pointer.
+ AccessBinsTy AccessBins;
+
+ /// Add a new access to the state at offset \p Offset and with size \p Size.
/// The access is associated with \p I, writes \p Content (if anything), and
- /// is of kind \p Kind. If an Access already exists for the same \p I and same
- /// \p RemoteI, the two are combined, potentially losing information about
- /// offset and size. The resulting access must now be moved from its original
- /// OffsetBin to the bin for its new offset.
- ///
+ /// is of kind \p Kind.
/// \Returns CHANGED, if the state changed, UNCHANGED otherwise.
ChangeStatus addAccess(Attributor &A, int64_t Offset, int64_t Size,
Instruction &I, Optional<Value *> Content,
AAPointerInfo::AccessKind Kind, Type *Ty,
- Instruction *RemoteI = nullptr);
-
- using OffsetBinsTy = DenseMap<OffsetAndSize, SmallSet<unsigned, 4>>;
-
- using const_bin_iterator = OffsetBinsTy::const_iterator;
- const_bin_iterator begin() const { return OffsetBins.begin(); }
- const_bin_iterator end() const { return OffsetBins.end(); }
-
- const AAPointerInfo::Access &getAccess(unsigned Index) const {
- return AccessList[Index];
+ Instruction *RemoteI = nullptr,
+ Accesses *BinPtr = nullptr) {
+ AA::OffsetAndSize Key{Offset, Size};
+ Accesses *&Bin = BinPtr ? BinPtr : AccessBins[Key];
+ if (!Bin)
+ Bin = new (A.Allocator) Accesses;
+ AAPointerInfo::Access Acc(&I, RemoteI ? RemoteI : &I, Content, Kind, Ty);
+ // Check if we have an access for this instruction in this bin, if not,
+ // simply add it.
+ auto It = Bin->find(Acc);
+ if (It == Bin->find_end()) {
+ Bin->insert(Acc);
+ return ChangeStatus::CHANGED;
+ }
+ // If the existing access is the same as then new one, nothing changed.
+ AAPointerInfo::Access &Current = Bin->get(It);
+ AAPointerInfo::Access Before = Current;
+ // The new one will be combined with the existing one.
+ Current &= Acc;
+ return Current == Before ? ChangeStatus::UNCHANGED : ChangeStatus::CHANGED;
}
-protected:
- // Every memory instruction results in an Access object. We maintain a list of
- // all Access objects that we own, along with the following maps:
- //
- // - OffsetBins: OffsetAndSize -> { Access }
- // - RemoteIMap: RemoteI x LocalI -> Access
- //
- // A RemoteI is any instruction that accesses memory. RemoteI is
diff erent
- // from LocalI if and only if LocalI is a call; then RemoteI is some
- // instruction in the callgraph starting from LocalI. Multiple paths in the
- // callgraph from LocalI to RemoteI may produce multiple accesses, but these
- // are all combined into a single Access object. This may result in loss of
- // information in OffsetAndSize in the Access object.
- SmallVector<AAPointerInfo::Access> AccessList;
- OffsetBinsTy OffsetBins;
- DenseMap<const Instruction *, SmallVector<unsigned>> RemoteIMap;
-
/// See AAPointerInfo::forallInterferingAccesses.
bool forallInterferingAccesses(
AA::OffsetAndSize OAS,
@@ -857,16 +911,14 @@ struct AA::PointerInfo::State : public AbstractState {
if (!isValidState())
return false;
- for (const auto &It : OffsetBins) {
+ for (const auto &It : AccessBins) {
AA::OffsetAndSize ItOAS = It.getFirst();
if (!OAS.mayOverlap(ItOAS))
continue;
bool IsExact = OAS == ItOAS && !OAS.offsetOrSizeAreUnknown();
- for (auto Index : It.getSecond()) {
- auto &Access = AccessList[Index];
+ for (auto &Access : *It.getSecond())
if (!CB(Access, IsExact))
return false;
- }
}
return true;
}
@@ -875,19 +927,32 @@ struct AA::PointerInfo::State : public AbstractState {
bool forallInterferingAccesses(
Instruction &I,
function_ref<bool(const AAPointerInfo::Access &, bool)> CB,
- AA::OffsetAndSize &OAS) const {
+ AA::OffsetAndSize *OASPtr) const {
if (!isValidState())
return false;
- auto LocalList = RemoteIMap.find(&I);
- if (LocalList == RemoteIMap.end()) {
- return true;
+ // First find the offset and size of I.
+ AA::OffsetAndSize OAS;
+ for (const auto &It : AccessBins) {
+ for (auto &Access : *It.getSecond()) {
+ if (Access.getRemoteInst() == &I) {
+ OAS = It.getFirst();
+ break;
+ }
+ }
+ if (OAS.Size != AA::OffsetAndSize::Unassigned)
+ break;
}
- for (auto LI : LocalList->getSecond()) {
- auto &Access = AccessList[LI];
- OAS &= {Access.getOffset(), Access.getSize()};
- }
+ if (OASPtr)
+ *OASPtr = OAS;
+
+ // No access for I was found, we are done.
+ if (OAS.Size == AA::OffsetAndSize::Unassigned)
+ return true;
+
+ // Now that we have an offset and size, find all overlapping ones and use
+ // the callback on the accesses.
return forallInterferingAccesses(OAS, CB);
}
@@ -896,56 +961,6 @@ struct AA::PointerInfo::State : public AbstractState {
BooleanState BS;
};
-ChangeStatus AA::PointerInfo::State::addAccess(Attributor &A, int64_t Offset,
- int64_t Size, Instruction &I,
- Optional<Value *> Content,
- AAPointerInfo::AccessKind Kind,
- Type *Ty, Instruction *RemoteI) {
- RemoteI = RemoteI ? RemoteI : &I;
- AAPointerInfo::Access Acc(&I, RemoteI, Offset, Size, Content, Kind, Ty);
-
- // Check if we have an access for this instruction, if not, simply add it.
- auto &LocalList = RemoteIMap[RemoteI];
- bool AccExists = false;
- unsigned AccIndex = AccessList.size();
- for (auto Index : LocalList) {
- auto &A = AccessList[Index];
- if (A.getLocalInst() == &I) {
- AccExists = true;
- AccIndex = Index;
- break;
- }
- }
- if (!AccExists) {
- AccessList.push_back(Acc);
- LocalList.push_back(AccIndex);
- } else {
- // The new one will be combined with the existing one.
- auto &Current = AccessList[AccIndex];
- auto Before = Current;
- Current &= Acc;
- if (Current == Before)
- return ChangeStatus::UNCHANGED;
-
- Acc = Current;
- AA::OffsetAndSize Key{Before.getOffset(), Before.getSize()};
- assert(OffsetBins.count(Key) && "Existing Access must be in some bin.");
- auto &Bin = OffsetBins[Key];
- assert(Bin.count(AccIndex) &&
- "Expected bin to actually contain the Access.");
- LLVM_DEBUG(dbgs() << "[AAPointerInfo] Removing Access "
- << AccessList[AccIndex] << " with key {" << Key.Offset
- << ',' << Key.Size << "}\n");
- Bin.erase(AccIndex);
- }
-
- AA::OffsetAndSize Key{Acc.getOffset(), Acc.getSize()};
- LLVM_DEBUG(dbgs() << "[AAPointerInfo] Inserting Access " << Acc
- << " with key {" << Key.Offset << ',' << Key.Size << "}\n");
- OffsetBins[Key].insert(AccIndex);
- return ChangeStatus::CHANGED;
-}
-
namespace {
struct AAPointerInfoImpl
: public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
@@ -956,7 +971,7 @@ struct AAPointerInfoImpl
const std::string getAsStr() const override {
return std::string("PointerInfo ") +
(isValidState() ? (std::string("#") +
- std::to_string(OffsetBins.size()) + " bins")
+ std::to_string(AccessBins.size()) + " bins")
: "<invalid>");
}
@@ -975,7 +990,7 @@ struct AAPointerInfoImpl
bool forallInterferingAccesses(
Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,
function_ref<bool(const Access &, bool)> UserCB, bool &HasBeenWrittenTo,
- AA::OffsetAndSize &OAS) const override {
+ AA::OffsetAndSize *OASPtr = nullptr) const override {
HasBeenWrittenTo = false;
SmallPtrSet<const Access *, 8> DominatingWrites;
@@ -1090,7 +1105,7 @@ struct AAPointerInfoImpl
InterferingAccesses.push_back({&Acc, Exact});
return true;
};
- if (!State::forallInterferingAccesses(I, AccessCB, OAS))
+ if (!State::forallInterferingAccesses(I, AccessCB, OASPtr))
return false;
if (HasBeenWrittenTo) {
@@ -1157,15 +1172,14 @@ struct AAPointerInfoImpl
// Combine the accesses bin by bin.
ChangeStatus Changed = ChangeStatus::UNCHANGED;
- const auto &State = OtherAAImpl.getState();
- for (const auto &It : State) {
+ for (const auto &It : OtherAAImpl.getState()) {
AA::OffsetAndSize OAS = AA::OffsetAndSize::getUnknown();
if (Offset != AA::OffsetAndSize::Unknown &&
!It.first.offsetOrSizeAreUnknown()) {
OAS = AA::OffsetAndSize(It.first.Offset + Offset, It.first.Size);
}
- for (auto Index : It.getSecond()) {
- const auto &RAcc = State.getAccess(Index);
+ Accesses *Bin = AccessBins.lookup(OAS);
+ for (const AAPointerInfo::Access &RAcc : *It.second) {
if (IsByval && !RAcc.isRead())
continue;
bool UsedAssumedInformation = false;
@@ -1178,8 +1192,9 @@ struct AAPointerInfoImpl
AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
AK = AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
}
- Changed = Changed | addAccess(A, OAS.Offset, OAS.Size, CB, Content, AK,
- RAcc.getType(), RAcc.getRemoteInst());
+ Changed =
+ Changed | addAccess(A, OAS.Offset, OAS.Size, CB, Content, AK,
+ RAcc.getType(), RAcc.getRemoteInst(), Bin);
}
}
return Changed;
@@ -1191,11 +1206,10 @@ struct AAPointerInfoImpl
/// Dump the state into \p O.
void dumpState(raw_ostream &O) {
- for (auto &It : OffsetBins) {
+ for (auto &It : AccessBins) {
O << "[" << It.first.Offset << "-" << It.first.Offset + It.first.Size
- << "] : " << It.getSecond().size() << "\n";
- for (auto AccIndex : It.getSecond()) {
- auto &Acc = AccessList[AccIndex];
+ << "] : " << It.getSecond()->size() << "\n";
+ for (auto &Acc : *It.getSecond()) {
O << " - " << Acc.getKind() << " - " << *Acc.getLocalInst() << "\n";
if (Acc.getLocalInst() != Acc.getRemoteInst())
O << " --> " << *Acc.getRemoteInst()
diff --git a/llvm/test/Transforms/Attributor/call-simplify-pointer-info.ll b/llvm/test/Transforms/Attributor/call-simplify-pointer-info.ll
index 30a828347517..e75489a03cea 100644
--- a/llvm/test/Transforms/Attributor/call-simplify-pointer-info.ll
+++ b/llvm/test/Transforms/Attributor/call-simplify-pointer-info.ll
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
-; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=TUNIT
+; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=TUNIT
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CGSCC
;
@@ -53,7 +53,7 @@ define i8 @call_simplifiable_1() {
; CGSCC-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
; CGSCC-NEXT: [[I0:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 2
; CGSCC-NEXT: store i8 2, i8* [[I0]], align 2
-; CGSCC-NEXT: [[R:%.*]] = call i8 @read_arg(i8* nocapture nofree noundef nonnull readonly align 2 dereferenceable(1022) [[I0]]) #[[ATTR3:[0-9]+]]
+; CGSCC-NEXT: [[R:%.*]] = call i8 @read_arg(i8* nocapture nofree noundef nonnull readonly align 2 dereferenceable(1022) [[I0]]) #[[ATTR2:[0-9]+]]
; CGSCC-NEXT: ret i8 [[R]]
;
entry:
@@ -64,68 +64,6 @@ entry:
ret i8 %r
}
-;;; Same as read_arg, but we need a copy to form distinct leaves in the callgraph.
-
-define internal i8 @read_arg_1(i8* %p) {
-; CGSCC: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
-; CGSCC-LABEL: define {{[^@]+}}@read_arg_1
-; CGSCC-SAME: (i8* nocapture nofree noundef nonnull readonly dereferenceable(1) [[P:%.*]]) #[[ATTR0]] {
-; CGSCC-NEXT: entry:
-; CGSCC-NEXT: [[L:%.*]] = load i8, i8* [[P]], align 1
-; CGSCC-NEXT: ret i8 [[L]]
-;
-entry:
- %l = load i8, i8* %p, align 1
- ret i8 %l
-}
-
-define internal i8 @sum_two_same_loads(i8* %p) {
-; CGSCC: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn
-; CGSCC-LABEL: define {{[^@]+}}@sum_two_same_loads
-; CGSCC-SAME: (i8* nocapture nofree noundef nonnull readonly dereferenceable(1022) [[P:%.*]]) #[[ATTR2:[0-9]+]] {
-; CGSCC-NEXT: [[X:%.*]] = call i8 @read_arg_1(i8* nocapture nofree noundef nonnull readonly dereferenceable(1022) [[P]]) #[[ATTR3]]
-; CGSCC-NEXT: [[Y:%.*]] = call i8 @read_arg_1(i8* nocapture nofree noundef nonnull readonly dereferenceable(1022) [[P]]) #[[ATTR3]]
-; CGSCC-NEXT: [[Z:%.*]] = add nsw i8 [[X]], [[Y]]
-; CGSCC-NEXT: ret i8 [[Z]]
-;
- %x = call i8 @read_arg_1(i8* %p)
- %y = call i8 @read_arg_1(i8* %p)
- %z = add nsw i8 %x, %y
- ret i8 %z
-}
-
-define i8 @call_simplifiable_2() {
-; TUNIT: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
-; TUNIT-LABEL: define {{[^@]+}}@call_simplifiable_2
-; TUNIT-SAME: () #[[ATTR1]] {
-; TUNIT-NEXT: entry:
-; TUNIT-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
-; TUNIT-NEXT: [[I0:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 2
-; TUNIT-NEXT: [[I1:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 3
-; TUNIT-NEXT: ret i8 4
-;
-; CGSCC: Function Attrs: nofree nosync nounwind readnone willreturn
-; CGSCC-LABEL: define {{[^@]+}}@call_simplifiable_2
-; CGSCC-SAME: () #[[ATTR1]] {
-; CGSCC-NEXT: entry:
-; CGSCC-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
-; CGSCC-NEXT: [[I0:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 2
-; CGSCC-NEXT: store i8 2, i8* [[I0]], align 2
-; CGSCC-NEXT: [[I1:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 3
-; CGSCC-NEXT: store i8 3, i8* [[I1]], align 1
-; CGSCC-NEXT: [[R:%.*]] = call i8 @sum_two_same_loads(i8* nocapture nofree noundef nonnull readonly align 2 dereferenceable(1022) [[I0]]) #[[ATTR3]]
-; CGSCC-NEXT: ret i8 [[R]]
-;
-entry:
- %Bytes = alloca [1024 x i8], align 16
- %i0 = getelementptr inbounds [1024 x i8], [1024 x i8]* %Bytes, i64 0, i64 2
- store i8 2, i8* %i0
- %i1 = getelementptr inbounds [1024 x i8], [1024 x i8]* %Bytes, i64 0, i64 3
- store i8 3, i8* %i1
- %r = call i8 @sum_two_same_loads(i8* %i0)
- ret i8 %r
-}
-
define i8 @call_not_simplifiable_1() {
; TUNIT: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; TUNIT-LABEL: define {{[^@]+}}@call_not_simplifiable_1
@@ -144,7 +82,7 @@ define i8 @call_not_simplifiable_1() {
; CGSCC-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
; CGSCC-NEXT: [[I0:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 2
; CGSCC-NEXT: store i8 2, i8* [[I0]], align 2
-; CGSCC-NEXT: [[R:%.*]] = call i8 @read_arg_index(i8* nocapture nofree noundef nonnull readonly align 2 dereferenceable(1022) [[I0]]) #[[ATTR3]]
+; CGSCC-NEXT: [[R:%.*]] = call i8 @read_arg_index(i8* nocapture nofree noundef nonnull readonly align 2 dereferenceable(1022) [[I0]]) #[[ATTR2]]
; CGSCC-NEXT: ret i8 [[R]]
;
entry:
@@ -155,89 +93,6 @@ entry:
ret i8 %r
}
-;;; Same as read_arg, but we need a copy to form distinct leaves in the callgraph.
-
-define internal i8 @read_arg_2(i8* %p) {
-; TUNIT: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
-; TUNIT-LABEL: define {{[^@]+}}@read_arg_2
-; TUNIT-SAME: (i8* nocapture nofree noundef nonnull readonly dereferenceable(1021) [[P:%.*]]) #[[ATTR0]] {
-; TUNIT-NEXT: entry:
-; TUNIT-NEXT: [[L:%.*]] = load i8, i8* [[P]], align 1
-; TUNIT-NEXT: ret i8 [[L]]
-;
-; CGSCC: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
-; CGSCC-LABEL: define {{[^@]+}}@read_arg_2
-; CGSCC-SAME: (i8* nocapture nofree noundef nonnull readonly dereferenceable(1) [[P:%.*]]) #[[ATTR0]] {
-; CGSCC-NEXT: entry:
-; CGSCC-NEXT: [[L:%.*]] = load i8, i8* [[P]], align 1
-; CGSCC-NEXT: ret i8 [[L]]
-;
-entry:
- %l = load i8, i8* %p, align 1
- ret i8 %l
-}
-
-define internal i8 @sum_two_
diff erent_loads(i8* %p, i8* %q) {
-; TUNIT: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
-; TUNIT-LABEL: define {{[^@]+}}@sum_two_
diff erent_loads
-; TUNIT-SAME: (i8* nocapture nofree noundef nonnull readonly align 2 dereferenceable(1022) [[P:%.*]], i8* nocapture nofree noundef nonnull readonly dereferenceable(1021) [[Q:%.*]]) #[[ATTR0]] {
-; TUNIT-NEXT: [[X:%.*]] = call i8 @read_arg_2(i8* nocapture nofree noundef nonnull readonly align 2 dereferenceable(1022) [[P]]) #[[ATTR2]]
-; TUNIT-NEXT: [[Y:%.*]] = call i8 @read_arg_2(i8* nocapture nofree noundef nonnull readonly dereferenceable(1021) [[Q]]) #[[ATTR2]]
-; TUNIT-NEXT: [[Z:%.*]] = add nsw i8 [[X]], [[Y]]
-; TUNIT-NEXT: ret i8 [[Z]]
-;
-; CGSCC: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn
-; CGSCC-LABEL: define {{[^@]+}}@sum_two_
diff erent_loads
-; CGSCC-SAME: (i8* nocapture nofree noundef nonnull readonly dereferenceable(1022) [[P:%.*]], i8* nocapture nofree noundef nonnull readonly dereferenceable(1021) [[Q:%.*]]) #[[ATTR2]] {
-; CGSCC-NEXT: [[X:%.*]] = call i8 @read_arg_2(i8* nocapture nofree noundef nonnull readonly dereferenceable(1022) [[P]]) #[[ATTR3]]
-; CGSCC-NEXT: [[Y:%.*]] = call i8 @read_arg_2(i8* nocapture nofree noundef nonnull readonly dereferenceable(1021) [[Q]]) #[[ATTR3]]
-; CGSCC-NEXT: [[Z:%.*]] = add nsw i8 [[X]], [[Y]]
-; CGSCC-NEXT: ret i8 [[Z]]
-;
- %x = call i8 @read_arg_2(i8* %p)
- %y = call i8 @read_arg_2(i8* %q)
- %z = add nsw i8 %x, %y
- ret i8 %z
-}
-
-define i8 @call_not_simplifiable_2() {
-; TUNIT: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
-; TUNIT-LABEL: define {{[^@]+}}@call_not_simplifiable_2
-; TUNIT-SAME: () #[[ATTR1]] {
-; TUNIT-NEXT: entry:
-; TUNIT-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
-; TUNIT-NEXT: [[I0:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 2
-; TUNIT-NEXT: store i8 2, i8* [[I0]], align 2
-; TUNIT-NEXT: [[I1:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 3
-; TUNIT-NEXT: store i8 3, i8* [[I1]], align 1
-; TUNIT-NEXT: [[BASE:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 0
-; TUNIT-NEXT: [[R:%.*]] = call i8 @sum_two_
diff erent_loads(i8* nocapture nofree noundef nonnull readonly align 2 dereferenceable(1022) [[I0]], i8* nocapture nofree noundef nonnull readonly dereferenceable(1021) [[I1]]) #[[ATTR2]]
-; TUNIT-NEXT: ret i8 [[R]]
-;
-; CGSCC: Function Attrs: nofree nosync nounwind readnone willreturn
-; CGSCC-LABEL: define {{[^@]+}}@call_not_simplifiable_2
-; CGSCC-SAME: () #[[ATTR1]] {
-; CGSCC-NEXT: entry:
-; CGSCC-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
-; CGSCC-NEXT: [[I0:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 2
-; CGSCC-NEXT: store i8 2, i8* [[I0]], align 2
-; CGSCC-NEXT: [[I1:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 3
-; CGSCC-NEXT: store i8 3, i8* [[I1]], align 1
-; CGSCC-NEXT: [[BASE:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BYTES]], i64 0, i64 0
-; CGSCC-NEXT: [[R:%.*]] = call i8 @sum_two_
diff erent_loads(i8* nocapture nofree noundef nonnull readonly align 2 dereferenceable(1022) [[I0]], i8* nocapture nofree noundef nonnull readonly dereferenceable(1021) [[I1]]) #[[ATTR3]]
-; CGSCC-NEXT: ret i8 [[R]]
-;
-entry:
- %Bytes = alloca [1024 x i8], align 16
- %i0 = getelementptr inbounds [1024 x i8], [1024 x i8]* %Bytes, i64 0, i64 2
- store i8 2, i8* %i0
- %i1 = getelementptr inbounds [1024 x i8], [1024 x i8]* %Bytes, i64 0, i64 3
- store i8 3, i8* %i1
- %base = getelementptr inbounds [1024 x i8], [1024 x i8]* %Bytes, i64 0, i64 0
- %r = call i8 @sum_two_
diff erent_loads(i8* %i0, i8* %i1)
- ret i8 %r
-}
-
;.
; TUNIT: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn }
; TUNIT: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
@@ -245,6 +100,5 @@ entry:
;.
; CGSCC: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn }
; CGSCC: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
-; CGSCC: attributes #[[ATTR2]] = { argmemonly nofree nosync nounwind readonly willreturn }
-; CGSCC: attributes #[[ATTR3]] = { readonly willreturn }
+; CGSCC: attributes #[[ATTR2]] = { readonly willreturn }
;.
diff --git a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll
index a8d1f549dfed..cd992da4c9f9 100644
--- a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll
@@ -2223,7 +2223,6 @@ define i8 @phi_no_store_2() {
; TUNIT: loop:
; TUNIT-NEXT: [[P:%.*]] = phi i8* [ bitcast (i32* @a2 to i8*), [[ENTRY:%.*]] ], [ [[G:%.*]], [[LOOP]] ]
; TUNIT-NEXT: [[I:%.*]] = phi i8 [ 0, [[ENTRY]] ], [ [[O:%.*]], [[LOOP]] ]
-; TUNIT-NEXT: store i8 1, i8* [[P]], align 2
; TUNIT-NEXT: [[G]] = getelementptr i8, i8* bitcast (i32* @a2 to i8*), i64 2
; TUNIT-NEXT: [[O]] = add nsw i8 [[I]], 1
; TUNIT-NEXT: [[C:%.*]] = icmp eq i8 [[O]], 7
@@ -2242,7 +2241,6 @@ define i8 @phi_no_store_2() {
; CGSCC: loop:
; CGSCC-NEXT: [[P:%.*]] = phi i8* [ bitcast (i32* @a2 to i8*), [[ENTRY:%.*]] ], [ [[G:%.*]], [[LOOP]] ]
; CGSCC-NEXT: [[I:%.*]] = phi i8 [ 0, [[ENTRY]] ], [ [[O:%.*]], [[LOOP]] ]
-; CGSCC-NEXT: store i8 1, i8* [[P]], align 2
; CGSCC-NEXT: [[G]] = getelementptr i8, i8* bitcast (i32* @a2 to i8*), i64 2
; CGSCC-NEXT: [[O]] = add nsw i8 [[I]], 1
; CGSCC-NEXT: [[C:%.*]] = icmp eq i8 [[O]], 7
@@ -2283,7 +2281,6 @@ define i8 @phi_no_store_3() {
; TUNIT: loop:
; TUNIT-NEXT: [[P:%.*]] = phi i8* [ bitcast (i32* @a3 to i8*), [[ENTRY:%.*]] ], [ [[G:%.*]], [[LOOP]] ]
; TUNIT-NEXT: [[I:%.*]] = phi i8 [ 0, [[ENTRY]] ], [ [[O:%.*]], [[LOOP]] ]
-; TUNIT-NEXT: store i8 1, i8* [[P]], align 2
; TUNIT-NEXT: [[G]] = getelementptr i8, i8* bitcast (i32* @a3 to i8*), i64 2
; TUNIT-NEXT: [[O]] = add nsw i8 [[I]], 1
; TUNIT-NEXT: [[C:%.*]] = icmp eq i8 [[O]], 7
@@ -2305,7 +2302,6 @@ define i8 @phi_no_store_3() {
; CGSCC: loop:
; CGSCC-NEXT: [[P:%.*]] = phi i8* [ bitcast (i32* @a3 to i8*), [[ENTRY:%.*]] ], [ [[G:%.*]], [[LOOP]] ]
; CGSCC-NEXT: [[I:%.*]] = phi i8 [ 0, [[ENTRY]] ], [ [[O:%.*]], [[LOOP]] ]
-; CGSCC-NEXT: store i8 1, i8* [[P]], align 2
; CGSCC-NEXT: [[G]] = getelementptr i8, i8* bitcast (i32* @a3 to i8*), i64 2
; CGSCC-NEXT: [[O]] = add nsw i8 [[I]], 1
; CGSCC-NEXT: [[C:%.*]] = icmp eq i8 [[O]], 7
More information about the llvm-commits
mailing list