Skip to content

Commit dd75c0e

Browse files
committed
[Attributor][NFC] Expose new API in AAPointerInfo
New users might want to check bins without a load or store instruction at hand. Since we use those instructions only to find the offset and size of the access anyway, we can expose an offset and size interface to the outside world as well. This commit mainly moves code around and exposes a class (OffsetAndSize) as well as a method forallInterferingAccesses in AAPointerInfo. Differential Revision: https://reviews.llvm.org/D119249
1 parent d1387a2 commit dd75c0e

File tree

2 files changed

+77
-52
lines changed

2 files changed

+77
-52
lines changed

llvm/include/llvm/Transforms/IPO/Attributor.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4792,6 +4792,48 @@ struct AAPointerInfo : public AbstractAttribute {
47924792
/// See AbstractAttribute::getIdAddr()
47934793
const char *getIdAddr() const override { return &ID; }
47944794

4795+
/// Helper to represent an access offset and size, with logic to deal with
4796+
/// uncertainty and check for overlapping accesses.
4797+
struct OffsetAndSize : public std::pair<int64_t, int64_t> {
4798+
using BaseTy = std::pair<int64_t, int64_t>;
4799+
OffsetAndSize(int64_t Offset, int64_t Size) : BaseTy(Offset, Size) {}
4800+
OffsetAndSize(const BaseTy &P) : BaseTy(P) {}
4801+
int64_t getOffset() const { return first; }
4802+
int64_t getSize() const { return second; }
4803+
static OffsetAndSize getUnknown() {
4804+
return OffsetAndSize(Unknown, Unknown);
4805+
}
4806+
4807+
/// Return true if offset or size are unknown.
4808+
bool offsetOrSizeAreUnknown() const {
4809+
return getOffset() == OffsetAndSize::Unknown ||
4810+
getSize() == OffsetAndSize::Unknown;
4811+
}
4812+
4813+
/// Return true if this offset and size pair might describe an address that
4814+
/// overlaps with \p OAS.
4815+
bool mayOverlap(const OffsetAndSize &OAS) const {
4816+
// Any unknown value and we are giving up -> overlap.
4817+
if (offsetOrSizeAreUnknown() || OAS.offsetOrSizeAreUnknown())
4818+
return true;
4819+
4820+
// Check if one offset point is in the other interval [offset,
4821+
// offset+size].
4822+
return OAS.getOffset() + OAS.getSize() > getOffset() &&
4823+
OAS.getOffset() < getOffset() + getSize();
4824+
}
4825+
4826+
/// Constant used to represent unknown offset or sizes.
4827+
static constexpr int64_t Unknown = 1 << 31;
4828+
};
4829+
4830+
/// Call \p CB on all accesses that might interfere with \p OAS and return
4831+
/// true if all such accesses were known and the callback returned true for
4832+
/// all of them, false otherwise. An access interferes with an offset-size
4833+
/// pair if it might read or write that memory region.
4834+
virtual bool forallInterferingAccesses(
4835+
OffsetAndSize OAS, function_ref<bool(const Access &, bool)> CB) const = 0;
4836+
47954837
/// Call \p CB on all accesses that might interfere with \p LI and return true
47964838
/// if all such accesses were known and the callback returned true for all of
47974839
/// them, false otherwise.

llvm/lib/Transforms/IPO/AttributorAttributes.cpp

Lines changed: 35 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -787,9 +787,6 @@ namespace llvm {
787787
namespace AA {
788788
namespace PointerInfo {
789789

790-
/// An access kind description as used by AAPointerInfo.
791-
struct OffsetAndSize;
792-
793790
struct State;
794791

795792
} // namespace PointerInfo
@@ -807,7 +804,7 @@ struct DenseMapInfo<AAPointerInfo::Access> : DenseMapInfo<Instruction *> {
807804

808805
/// Helper that allows OffsetAndSize as a key in a DenseMap.
809806
template <>
810-
struct DenseMapInfo<AA::PointerInfo ::OffsetAndSize>
807+
struct DenseMapInfo<AAPointerInfo ::OffsetAndSize>
811808
: DenseMapInfo<std::pair<int64_t, int64_t>> {};
812809

813810
/// Helper for AA::PointerInfo::Acccess DenseMap/Set usage ignoring everythign
@@ -823,38 +820,6 @@ struct AccessAsInstructionInfo : DenseMapInfo<Instruction *> {
823820

824821
} // namespace llvm
825822

826-
/// Helper to represent an access offset and size, with logic to deal with
827-
/// uncertainty and check for overlapping accesses.
828-
struct AA::PointerInfo::OffsetAndSize : public std::pair<int64_t, int64_t> {
829-
using BaseTy = std::pair<int64_t, int64_t>;
830-
OffsetAndSize(int64_t Offset, int64_t Size) : BaseTy(Offset, Size) {}
831-
OffsetAndSize(const BaseTy &P) : BaseTy(P) {}
832-
int64_t getOffset() const { return first; }
833-
int64_t getSize() const { return second; }
834-
static OffsetAndSize getUnknown() { return OffsetAndSize(Unknown, Unknown); }
835-
836-
/// Return true if offset or size are unknown.
837-
bool offsetOrSizeAreUnknown() const {
838-
return getOffset() == OffsetAndSize::Unknown ||
839-
getSize() == OffsetAndSize::Unknown;
840-
}
841-
842-
/// Return true if this offset and size pair might describe an address that
843-
/// overlaps with \p OAS.
844-
bool mayOverlap(const OffsetAndSize &OAS) const {
845-
// Any unknown value and we are giving up -> overlap.
846-
if (offsetOrSizeAreUnknown() || OAS.offsetOrSizeAreUnknown())
847-
return true;
848-
849-
// Check if one offset point is in the other interval [offset, offset+size].
850-
return OAS.getOffset() + OAS.getSize() > getOffset() &&
851-
OAS.getOffset() < getOffset() + getSize();
852-
}
853-
854-
/// Constant used to represent unknown offset or sizes.
855-
static constexpr int64_t Unknown = 1 << 31;
856-
};
857-
858823
/// Implementation of the DenseMapInfo.
859824
///
860825
///{
@@ -988,14 +953,14 @@ struct AA::PointerInfo::State : public AbstractState {
988953
using Accesses = DenseSet<AAPointerInfo::Access, AccessAsInstructionInfo>;
989954

990955
/// We store all accesses in bins denoted by their offset and size.
991-
using AccessBinsTy = DenseMap<OffsetAndSize, Accesses>;
956+
using AccessBinsTy = DenseMap<AAPointerInfo::OffsetAndSize, Accesses>;
992957

993958
AccessBinsTy::const_iterator begin() const { return AccessBins.begin(); }
994959
AccessBinsTy::const_iterator end() const { return AccessBins.end(); }
995960

996961
protected:
997962
/// The bins with all the accesses for the associated pointer.
998-
DenseMap<OffsetAndSize, Accesses> AccessBins;
963+
DenseMap<AAPointerInfo::OffsetAndSize, Accesses> AccessBins;
999964

1000965
/// Add a new access to the state at offset \p Offset and with size \p Size.
1001966
/// The access is associated with \p I, writes \p Content (if anything), and
@@ -1006,7 +971,7 @@ struct AA::PointerInfo::State : public AbstractState {
1006971
AAPointerInfo::AccessKind Kind, Type *Ty,
1007972
Instruction *RemoteI = nullptr,
1008973
Accesses *BinPtr = nullptr) {
1009-
OffsetAndSize Key{Offset, Size};
974+
AAPointerInfo::OffsetAndSize Key{Offset, Size};
1010975
Accesses &Bin = BinPtr ? *BinPtr : AccessBins[Key];
1011976
AAPointerInfo::Access Acc(&I, RemoteI ? RemoteI : &I, Content, Kind, Ty);
1012977
// Check if we have an access for this instruction in this bin, if not,
@@ -1023,14 +988,34 @@ struct AA::PointerInfo::State : public AbstractState {
1023988
return *It == Before ? ChangeStatus::UNCHANGED : ChangeStatus::CHANGED;
1024989
}
1025990

991+
/// See AAPointerInfo::forallInterferingAccesses.
992+
bool forallInterferingAccesses(
993+
AAPointerInfo::OffsetAndSize OAS,
994+
function_ref<bool(const AAPointerInfo::Access &, bool)> CB) const {
995+
if (!isValidState())
996+
return false;
997+
998+
for (auto &It : AccessBins) {
999+
AAPointerInfo::OffsetAndSize ItOAS = It.getFirst();
1000+
if (!OAS.mayOverlap(ItOAS))
1001+
continue;
1002+
bool IsExact = OAS == ItOAS && !OAS.offsetOrSizeAreUnknown();
1003+
for (auto &Access : It.getSecond())
1004+
if (!CB(Access, IsExact))
1005+
return false;
1006+
}
1007+
return true;
1008+
}
1009+
10261010
/// See AAPointerInfo::forallInterferingAccesses.
10271011
bool forallInterferingAccesses(
10281012
Instruction &I,
10291013
function_ref<bool(const AAPointerInfo::Access &, bool)> CB) const {
10301014
if (!isValidState())
10311015
return false;
1016+
10321017
// First find the offset and size of I.
1033-
OffsetAndSize OAS(-1, -1);
1018+
AAPointerInfo::OffsetAndSize OAS(-1, -1);
10341019
for (auto &It : AccessBins) {
10351020
for (auto &Access : It.getSecond()) {
10361021
if (Access.getRemoteInst() == &I) {
@@ -1041,21 +1026,13 @@ struct AA::PointerInfo::State : public AbstractState {
10411026
if (OAS.getSize() != -1)
10421027
break;
10431028
}
1029+
// No access for I was found, we are done.
10441030
if (OAS.getSize() == -1)
10451031
return true;
10461032

10471033
// Now that we have an offset and size, find all overlapping ones and use
10481034
// the callback on the accesses.
1049-
for (auto &It : AccessBins) {
1050-
OffsetAndSize ItOAS = It.getFirst();
1051-
if (!OAS.mayOverlap(ItOAS))
1052-
continue;
1053-
bool IsExact = OAS == ItOAS && !OAS.offsetOrSizeAreUnknown();
1054-
for (auto &Access : It.getSecond())
1055-
if (!CB(Access, IsExact))
1056-
return false;
1057-
}
1058-
return true;
1035+
return forallInterferingAccesses(OAS, CB);
10591036
}
10601037

10611038
private:
@@ -1084,6 +1061,12 @@ struct AAPointerInfoImpl
10841061
return AAPointerInfo::manifest(A);
10851062
}
10861063

1064+
bool forallInterferingAccesses(
1065+
OffsetAndSize OAS,
1066+
function_ref<bool(const AAPointerInfo::Access &, bool)> CB)
1067+
const override {
1068+
return State::forallInterferingAccesses(OAS, CB);
1069+
}
10871070
bool forallInterferingAccesses(
10881071
LoadInst &LI, function_ref<bool(const AAPointerInfo::Access &, bool)> CB)
10891072
const override {
@@ -1306,7 +1289,7 @@ struct AAPointerInfoFloating : public AAPointerInfoImpl {
13061289
bool handleAccess(Attributor &A, Instruction &I, Value &Ptr,
13071290
Optional<Value *> Content, AccessKind Kind, int64_t Offset,
13081291
ChangeStatus &Changed, Type *Ty,
1309-
int64_t Size = AA::PointerInfo::OffsetAndSize::Unknown) {
1292+
int64_t Size = OffsetAndSize::Unknown) {
13101293
using namespace AA::PointerInfo;
13111294
// No need to find a size if one is given or the offset is unknown.
13121295
if (Offset != OffsetAndSize::Unknown && Size == OffsetAndSize::Unknown &&
@@ -1322,7 +1305,7 @@ struct AAPointerInfoFloating : public AAPointerInfoImpl {
13221305

13231306
/// Helper struct, will support ranges eventually.
13241307
struct OffsetInfo {
1325-
int64_t Offset = AA::PointerInfo::OffsetAndSize::Unknown;
1308+
int64_t Offset = OffsetAndSize::Unknown;
13261309

13271310
bool operator==(const OffsetInfo &OI) const { return Offset == OI.Offset; }
13281311
};

0 commit comments

Comments
 (0)