Skip to content

Commit 181b014

Browse files
authored
Attributor: Infer noalias.addrspace metadata for memory instructions (#136553)
Add noalias.addrspace metadata for store, load and atomic instruction in AMDGPU backend.
1 parent 884f738 commit 181b014

File tree

4 files changed

+896
-14
lines changed

4 files changed

+896
-14
lines changed

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999

100100
#include "llvm/ADT/DenseSet.h"
101101
#include "llvm/ADT/GraphTraits.h"
102+
#include "llvm/ADT/IntervalMap.h"
102103
#include "llvm/ADT/MapVector.h"
103104
#include "llvm/ADT/STLExtras.h"
104105
#include "llvm/ADT/SetOperations.h"
@@ -1355,6 +1356,8 @@ struct InformationCache {
13551356
/// Return the flat address space if the associated target has.
13561357
LLVM_ABI std::optional<unsigned> getFlatAddressSpace() const;
13571358

1359+
virtual unsigned getMaxAddrSpace() const { return ~0U; }
1360+
13581361
private:
13591362
struct FunctionInfo {
13601363
LLVM_ABI ~FunctionInfo();
@@ -6420,6 +6423,47 @@ struct AAAddressSpace : public StateWrapper<BooleanState, AbstractAttribute> {
64206423
static const uint32_t InvalidAddressSpace = ~0U;
64216424
};
64226425

6426+
/// An abstract interface for potential address space information.
6427+
struct AANoAliasAddrSpace
6428+
: public StateWrapper<BooleanState, AbstractAttribute> {
6429+
using Base = StateWrapper<BooleanState, AbstractAttribute>;
6430+
using RangeMap = IntervalMap<unsigned, bool>;
6431+
AANoAliasAddrSpace(const IRPosition &IRP, Attributor &A)
6432+
: Base(IRP), Map(Allocator) {}
6433+
6434+
/// See AbstractAttribute::isValidIRPositionForInit
6435+
static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
6436+
if (!IRP.getAssociatedType()->isPtrOrPtrVectorTy())
6437+
return false;
6438+
return AbstractAttribute::isValidIRPositionForInit(A, IRP);
6439+
}
6440+
6441+
/// See AbstractAttribute::requiresCallersForArgOrFunction
6442+
static bool requiresCallersForArgOrFunction() { return true; }
6443+
6444+
/// Create an abstract attribute view for the position \p IRP.
6445+
LLVM_ABI static AANoAliasAddrSpace &createForPosition(const IRPosition &IRP,
6446+
Attributor &A);
6447+
/// See AbstractAttribute::getName()
6448+
StringRef getName() const override { return "AANoAliasAddrSpace"; }
6449+
6450+
/// See AbstractAttribute::getIdAddr()
6451+
const char *getIdAddr() const override { return &ID; }
6452+
6453+
/// This function should return true if the type of the \p AA is
6454+
/// AAAssumptionInfo
6455+
static bool classof(const AbstractAttribute *AA) {
6456+
return (AA->getIdAddr() == &ID);
6457+
}
6458+
6459+
/// Unique ID (due to the unique address)
6460+
LLVM_ABI static const char ID;
6461+
6462+
protected:
6463+
RangeMap::Allocator Allocator;
6464+
RangeMap Map;
6465+
};
6466+
64236467
struct AAAllocationInfo : public StateWrapper<BooleanState, AbstractAttribute> {
64246468
AAAllocationInfo(const IRPosition &IRP, Attributor &A)
64256469
: StateWrapper<BooleanState, AbstractAttribute>(IRP) {}

llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ class AMDGPUInformationCache : public InformationCache {
235235
return ST.getMaxWavesPerEU();
236236
}
237237

238+
unsigned getMaxAddrSpace() const override {
239+
return AMDGPUAS::MAX_AMDGPU_ADDRESS;
240+
}
241+
238242
private:
239243
/// Check if the ConstantExpr \p CE uses an addrspacecast from private or
240244
/// local to flat. These casts may require the queue pointer.
@@ -1380,8 +1384,8 @@ static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM,
13801384
&AAPotentialValues::ID, &AAAMDFlatWorkGroupSize::ID,
13811385
&AAAMDMaxNumWorkgroups::ID, &AAAMDWavesPerEU::ID, &AAAMDGPUNoAGPR::ID,
13821386
&AACallEdges::ID, &AAPointerInfo::ID, &AAPotentialConstantValues::ID,
1383-
&AAUnderlyingObjects::ID, &AAAddressSpace::ID, &AAIndirectCallInfo::ID,
1384-
&AAInstanceInfo::ID});
1387+
&AAUnderlyingObjects::ID, &AANoAliasAddrSpace::ID, &AAAddressSpace::ID,
1388+
&AAIndirectCallInfo::ID, &AAInstanceInfo::ID});
13851389

13861390
AttributorConfig AC(CGUpdater);
13871391
AC.IsClosedWorldModule = Options.IsClosedWorld;
@@ -1420,18 +1424,19 @@ static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM,
14201424
}
14211425

14221426
for (auto &I : instructions(F)) {
1423-
if (auto *LI = dyn_cast<LoadInst>(&I)) {
1424-
A.getOrCreateAAFor<AAAddressSpace>(
1425-
IRPosition::value(*LI->getPointerOperand()));
1426-
} else if (auto *SI = dyn_cast<StoreInst>(&I)) {
1427-
A.getOrCreateAAFor<AAAddressSpace>(
1428-
IRPosition::value(*SI->getPointerOperand()));
1429-
} else if (auto *RMW = dyn_cast<AtomicRMWInst>(&I)) {
1430-
A.getOrCreateAAFor<AAAddressSpace>(
1431-
IRPosition::value(*RMW->getPointerOperand()));
1432-
} else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(&I)) {
1433-
A.getOrCreateAAFor<AAAddressSpace>(
1434-
IRPosition::value(*CmpX->getPointerOperand()));
1427+
Value *Ptr = nullptr;
1428+
if (auto *LI = dyn_cast<LoadInst>(&I))
1429+
Ptr = LI->getPointerOperand();
1430+
else if (auto *SI = dyn_cast<StoreInst>(&I))
1431+
Ptr = SI->getPointerOperand();
1432+
else if (auto *RMW = dyn_cast<AtomicRMWInst>(&I))
1433+
Ptr = RMW->getPointerOperand();
1434+
else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(&I))
1435+
Ptr = CmpX->getPointerOperand();
1436+
1437+
if (Ptr) {
1438+
A.getOrCreateAAFor<AAAddressSpace>(IRPosition::value(*Ptr));
1439+
A.getOrCreateAAFor<AANoAliasAddrSpace>(IRPosition::value(*Ptr));
14351440
}
14361441
}
14371442
}

llvm/lib/Transforms/IPO/AttributorAttributes.cpp

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ PIPE_OPERATOR(AAAssumptionInfo)
193193
PIPE_OPERATOR(AAUnderlyingObjects)
194194
PIPE_OPERATOR(AAInvariantLoadPointer)
195195
PIPE_OPERATOR(AAAddressSpace)
196+
PIPE_OPERATOR(AANoAliasAddrSpace)
196197
PIPE_OPERATOR(AAAllocationInfo)
197198
PIPE_OPERATOR(AAIndirectCallInfo)
198199
PIPE_OPERATOR(AAGlobalValueInfo)
@@ -13146,6 +13147,197 @@ struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
1314613147
};
1314713148
} // namespace
1314813149

13150+
/// ------------------------ No Alias Address Space ---------------------------
13151+
// This attribute assumes flat address space can alias all other address space
13152+
13153+
// TODO: this is similar to AAAddressSpace, most of the code should be merged.
13154+
// But merging it created failing cased on gateway test that cannot be
13155+
// reproduced locally. So should open a seperated PR to hande the merge of
13156+
// AANoAliasAddrSpace and AAAddressSpace attribute
13157+
13158+
namespace {
13159+
struct AANoAliasAddrSpaceImpl : public AANoAliasAddrSpace {
13160+
AANoAliasAddrSpaceImpl(const IRPosition &IRP, Attributor &A)
13161+
: AANoAliasAddrSpace(IRP, A) {}
13162+
13163+
void initialize(Attributor &A) override {
13164+
assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13165+
"Associated value is not a pointer");
13166+
13167+
resetASRanges(A);
13168+
13169+
std::optional<unsigned> FlatAS = A.getInfoCache().getFlatAddressSpace();
13170+
if (!FlatAS.has_value()) {
13171+
indicatePessimisticFixpoint();
13172+
return;
13173+
}
13174+
13175+
removeAS(*FlatAS);
13176+
13177+
unsigned AS = getAssociatedType()->getPointerAddressSpace();
13178+
if (AS != *FlatAS) {
13179+
removeAS(AS);
13180+
indicateOptimisticFixpoint();
13181+
}
13182+
}
13183+
13184+
ChangeStatus updateImpl(Attributor &A) override {
13185+
unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13186+
uint32_t OldAssumed = getAssumed();
13187+
13188+
auto CheckAddressSpace = [&](Value &Obj) {
13189+
if (isa<PoisonValue>(&Obj))
13190+
return true;
13191+
13192+
unsigned AS = Obj.getType()->getPointerAddressSpace();
13193+
if (AS == FlatAS)
13194+
return false;
13195+
13196+
removeAS(Obj.getType()->getPointerAddressSpace());
13197+
return true;
13198+
};
13199+
13200+
const AAUnderlyingObjects *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
13201+
getIRPosition(), this, DepClassTy::REQUIRED);
13202+
if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13203+
return indicatePessimisticFixpoint();
13204+
13205+
return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13206+
: ChangeStatus::CHANGED;
13207+
}
13208+
13209+
/// See AbstractAttribute::manifest(...).
13210+
ChangeStatus manifest(Attributor &A) override {
13211+
unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13212+
13213+
unsigned AS = getAssociatedType()->getPointerAddressSpace();
13214+
if (AS != FlatAS || Map.empty())
13215+
return ChangeStatus::UNCHANGED;
13216+
13217+
LLVMContext &Ctx = getAssociatedValue().getContext();
13218+
MDNode *NoAliasASNode = nullptr;
13219+
MDBuilder MDB(Ctx);
13220+
// Has to use iterator to get the range info.
13221+
for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13222+
if (!I.value())
13223+
continue;
13224+
unsigned Upper = I.stop();
13225+
unsigned Lower = I.start();
13226+
if (!NoAliasASNode) {
13227+
NoAliasASNode = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13228+
continue;
13229+
}
13230+
MDNode *ASRange = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13231+
NoAliasASNode = MDNode::getMostGenericRange(NoAliasASNode, ASRange);
13232+
}
13233+
13234+
Value *AssociatedValue = &getAssociatedValue();
13235+
bool Changed = false;
13236+
13237+
auto AddNoAliasAttr = [&](const Use &U, bool &) {
13238+
if (U.get() != AssociatedValue)
13239+
return true;
13240+
Instruction *Inst = dyn_cast<Instruction>(U.getUser());
13241+
if (!Inst || Inst->hasMetadata(LLVMContext::MD_noalias_addrspace))
13242+
return true;
13243+
if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst) &&
13244+
!isa<AtomicCmpXchgInst>(Inst) && !isa<AtomicRMWInst>(Inst))
13245+
return true;
13246+
if (!A.isRunOn(Inst->getFunction()))
13247+
return true;
13248+
Inst->setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13249+
Changed = true;
13250+
return true;
13251+
};
13252+
(void)A.checkForAllUses(AddNoAliasAttr, *this, *AssociatedValue,
13253+
/*CheckBBLivenessOnly=*/true);
13254+
return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13255+
}
13256+
13257+
/// See AbstractAttribute::getAsStr().
13258+
const std::string getAsStr(Attributor *A) const override {
13259+
if (!isValidState())
13260+
return "<invalid>";
13261+
std::string Str;
13262+
raw_string_ostream OS(Str);
13263+
OS << "CanNotBeAddrSpace(";
13264+
for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13265+
unsigned Upper = I.stop();
13266+
unsigned Lower = I.start();
13267+
OS << ' ' << '[' << Upper << ',' << Lower + 1 << ')';
13268+
}
13269+
OS << " )";
13270+
return OS.str();
13271+
}
13272+
13273+
private:
13274+
void removeAS(unsigned AS) {
13275+
RangeMap::iterator I = Map.find(AS);
13276+
13277+
if (I != Map.end()) {
13278+
unsigned Upper = I.stop();
13279+
unsigned Lower = I.start();
13280+
I.erase();
13281+
if (Upper == Lower)
13282+
return;
13283+
if (AS != ~((unsigned)0) && AS + 1 <= Upper)
13284+
Map.insert(AS + 1, Upper, /*what ever this variable name is=*/true);
13285+
if (AS != 0 && Lower <= AS - 1)
13286+
Map.insert(Lower, AS - 1, true);
13287+
}
13288+
}
13289+
13290+
void resetASRanges(Attributor &A) {
13291+
Map.clear();
13292+
Map.insert(0, A.getInfoCache().getMaxAddrSpace(), true);
13293+
}
13294+
};
13295+
13296+
struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13297+
AANoAliasAddrSpaceFloating(const IRPosition &IRP, Attributor &A)
13298+
: AANoAliasAddrSpaceImpl(IRP, A) {}
13299+
13300+
void trackStatistics() const override {
13301+
STATS_DECLTRACK_FLOATING_ATTR(noaliasaddrspace);
13302+
}
13303+
};
13304+
13305+
struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13306+
AANoAliasAddrSpaceReturned(const IRPosition &IRP, Attributor &A)
13307+
: AANoAliasAddrSpaceImpl(IRP, A) {}
13308+
13309+
void trackStatistics() const override {
13310+
STATS_DECLTRACK_FNRET_ATTR(noaliasaddrspace);
13311+
}
13312+
};
13313+
13314+
struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13315+
AANoAliasAddrSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13316+
: AANoAliasAddrSpaceImpl(IRP, A) {}
13317+
13318+
void trackStatistics() const override {
13319+
STATS_DECLTRACK_CSRET_ATTR(noaliasaddrspace);
13320+
}
13321+
};
13322+
13323+
struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13324+
AANoAliasAddrSpaceArgument(const IRPosition &IRP, Attributor &A)
13325+
: AANoAliasAddrSpaceImpl(IRP, A) {}
13326+
13327+
void trackStatistics() const override {
13328+
STATS_DECLTRACK_ARG_ATTR(noaliasaddrspace);
13329+
}
13330+
};
13331+
13332+
struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13333+
AANoAliasAddrSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13334+
: AANoAliasAddrSpaceImpl(IRP, A) {}
13335+
13336+
void trackStatistics() const override {
13337+
STATS_DECLTRACK_CSARG_ATTR(noaliasaddrspace);
13338+
}
13339+
};
13340+
} // namespace
1314913341
/// ----------- Allocation Info ----------
1315013342
namespace {
1315113343
struct AAAllocationInfoImpl : public AAAllocationInfo {
@@ -13400,6 +13592,7 @@ const char AAAssumptionInfo::ID = 0;
1340013592
const char AAUnderlyingObjects::ID = 0;
1340113593
const char AAInvariantLoadPointer::ID = 0;
1340213594
const char AAAddressSpace::ID = 0;
13595+
const char AANoAliasAddrSpace::ID = 0;
1340313596
const char AAAllocationInfo::ID = 0;
1340413597
const char AAIndirectCallInfo::ID = 0;
1340513598
const char AAGlobalValueInfo::ID = 0;
@@ -13535,6 +13728,7 @@ CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFPClass)
1353513728
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPointerInfo)
1353613729
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInvariantLoadPointer)
1353713730
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAddressSpace)
13731+
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAliasAddrSpace)
1353813732
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAllocationInfo)
1353913733

1354013734
CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify)

0 commit comments

Comments
 (0)