-
Notifications
You must be signed in to change notification settings - Fork 11.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Lint][AMDGPU] No store to const addrspace #109181
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-support @llvm/pr-subscribers-backend-amdgpu Author: None (jofrn) ChangesFull diff: https://github.com/llvm/llvm-project/pull/109181.diff 2 Files Affected:
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 06a67346fbf959..805c9ef7b72729 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -4224,6 +4224,19 @@ void Verifier::visitLoadInst(LoadInst &LI) {
visitInstruction(LI);
}
+static bool isConstantAddressSpace(unsigned AS) {
+ switch (AS) {
+ using namespace AMDGPUAS;
+ case CONSTANT_ADDRESS: case CONSTANT_ADDRESS_32BIT:
+ case CONSTANT_BUFFER_0: case CONSTANT_BUFFER_1: case CONSTANT_BUFFER_2: case CONSTANT_BUFFER_3:
+ case CONSTANT_BUFFER_4: case CONSTANT_BUFFER_5: case CONSTANT_BUFFER_6: case CONSTANT_BUFFER_7:
+ case CONSTANT_BUFFER_8: case CONSTANT_BUFFER_9: case CONSTANT_BUFFER_10: case CONSTANT_BUFFER_11:
+ case CONSTANT_BUFFER_12: case CONSTANT_BUFFER_13: case CONSTANT_BUFFER_14: case CONSTANT_BUFFER_15:
+ return true;
+ default: return false;
+ }
+}
+
void Verifier::visitStoreInst(StoreInst &SI) {
PointerType *PTy = dyn_cast<PointerType>(SI.getOperand(1)->getType());
Check(PTy, "Store operand must be a pointer.", &SI);
@@ -4246,6 +4259,10 @@ void Verifier::visitStoreInst(StoreInst &SI) {
Check(SI.getSyncScopeID() == SyncScope::System,
"Non-atomic store cannot have SynchronizationScope specified", &SI);
}
+ if (TT.isAMDGPU()) {
+ Check(!isConstantAddressSpace(SI.getPointerAddressSpace()),
+ "Store cannot be to constant addrspace", &SI);
+ }
visitInstruction(SI);
}
diff --git a/llvm/test/CodeGen/AMDGPU/const-store.ll b/llvm/test/CodeGen/AMDGPU/const-store.ll
new file mode 100644
index 00000000000000..9447ef9db59986
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/const-store.ll
@@ -0,0 +1,9 @@
+; RUN: not llc -mtriple=amdgcn < %s |& FileCheck %s
+
+define amdgpu_kernel void @store_const(ptr addrspace(4) %out, i32 %a, i32 %b) {
+; CHECK: Store cannot be to constant addrspace
+; CHECK-NEXT: store i32 %r, ptr addrspace(4) %out
+ %r = add i32 %a, %b
+ store i32 %r, ptr addrspace(4) %out
+ ret void
+}
|
You can test this locally with the following command:git-clang-format --diff 5f02558d820fdc9aa8ac7d3d887e72526574e1d9 393311ca3330fd9ed7baa598e032fc8ee1ebaa66 --extensions cpp,h -- llvm/include/llvm/Support/AMDGPUAddrSpace.h llvm/lib/Analysis/Lint.cpp View the diff from clang-format here.diff --git a/llvm/include/llvm/Support/AMDGPUAddrSpace.h b/llvm/include/llvm/Support/AMDGPUAddrSpace.h
index 6f03c3fca3..a7533b99a8 100644
--- a/llvm/include/llvm/Support/AMDGPUAddrSpace.h
+++ b/llvm/include/llvm/Support/AMDGPUAddrSpace.h
@@ -95,7 +95,7 @@ inline bool isExtendedGlobalAddrSpace(unsigned AS) {
}
inline bool isConstantAddressSpace(unsigned AS) {
- switch(AS) {
+ switch (AS) {
using namespace AMDGPUAS;
case CONSTANT_ADDRESS:
case CONSTANT_ADDRESS_32BIT:
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index 3503b6980c..d76e77cd0e 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -122,6 +122,7 @@ class Lint : public InstVisitor<Lint> {
Value *findValue(Value *V, bool OffsetOk) const;
Value *findValueImpl(Value *V, bool OffsetOk,
SmallPtrSetImpl<Value *> &Visited) const;
+
public:
Module *Mod;
Triple TT;
@@ -136,9 +137,8 @@ public:
Lint(Module *Mod, const DataLayout *DL, AliasAnalysis *AA,
AssumptionCache *AC, DominatorTree *DT, TargetLibraryInfo *TLI)
- : Mod(Mod), TT(Triple::normalize(Mod->getTargetTriple())),
- DL(DL), AA(AA), AC(AC), DT(DT), TLI(TLI),
- MessagesStr(Messages) {}
+ : Mod(Mod), TT(Triple::normalize(Mod->getTargetTriple())), DL(DL), AA(AA),
+ AC(AC), DT(DT), TLI(TLI), MessagesStr(Messages) {}
void WriteValues(ArrayRef<const Value *> Vs) {
for (const Value *V : Vs) {
@@ -404,8 +404,9 @@ void Lint::visitMemoryReference(Instruction &I, const MemoryLocation &Loc,
if (Flags & MemRef::Write) {
if (TT.isAMDGPU())
- Check(!AMDGPU::isConstantAddressSpace(UnderlyingObject->getType()->getPointerAddressSpace()),
- "Undefined behavior: Write to const memory", &I);
+ Check(!AMDGPU::isConstantAddressSpace(
+ UnderlyingObject->getType()->getPointerAddressSpace()),
+ "Undefined behavior: Write to const memory", &I);
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(UnderlyingObject))
Check(!GV->isConstant(), "Undefined behavior: Write to read-only memory",
|
7a77ede
to
5469cf1
Compare
Ensure store to const addrspace is not allowed by IR Verifier.
5469cf1
to
a099028
Compare
llvm/lib/IR/Verifier.cpp
Outdated
@@ -4224,6 +4224,33 @@ void Verifier::visitLoadInst(LoadInst &LI) { | |||
visitInstruction(LI); | |||
} | |||
|
|||
static bool isConstantAddressSpace(unsigned AS) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
constant address space is not an AMD only thing. I'm thinking probably we can split this function into target dependent (for example, to query whether an AS is a constant AS) and independent part.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would the independent part contain if we do not have a use case for it yet?
Was there any discussion about this? I'm not sure if it should be a verifier error or just undefined behaviour at run time. Also there are other instructions that write to memory, like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This must be UB, and not a verifier error. For example, we allow constant->flat casts. We do not want to have to consider the address spaces involved when folding something like store (addrspacecast ptr addrspace(4) %val to ptr)
Plus long term I don't think we should have a constant address space at all. |
It can be guarded with a flag perhaps. There was discussion to catch this in some way or another since it leads to more confusing error messages later on. Alternatively, we can have these checks go in a separate pass. |
The addrspace in |
These kinds of checks should go into the Lint pass instead of the Verifier pass. |
You're reading the example too literally. It should be valid for a pass to strip away the cast, and store directly to the original address space of the pointer without considering any special information. It would be a target specific burden placed on any IR transformation, which is not OK. This type of check belongs in Lint, which hardly ever gets used and I'm not sure is worth the effort |
a82bcdc
to
b3fea0b
Compare
%r = add i32 %a, %b | ||
store i32 %r, ptr addrspace(4) %out | ||
ret void | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test atomicrmw, cmpxchg, and a memset, memcpy? Also at least the addrspace(6) case
@@ -0,0 +1,9 @@ | |||
; RUN: not opt -mtriple=amdgcn --passes=lint --lint-abort-on-error %s -o - |& FileCheck %s | |||
|
|||
define amdgpu_kernel void @store_const(ptr addrspace(4) %out, i32 %a, i32 %b) addrspace(4) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no reason to set the address space of the function
@@ -0,0 +1,9 @@ | |||
; RUN: not opt -mtriple=amdgcn --passes=lint --lint-abort-on-error %s -o - |& FileCheck %s | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
negative test with a different target
@@ -0,0 +1,9 @@ | |||
; RUN: not opt -mtriple=amdgcn --passes=lint --lint-abort-on-error %s -o - |& FileCheck %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should move this to test/Analysis/Lint
0b69206
to
b1c3d38
Compare
b1c3d38
to
4553484
Compare
14a876d
to
2c640e5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New approach looks reasonable to me.
llvm/lib/Analysis/Lint.cpp
Outdated
if (TT.isAMDGPU()) { | ||
switch(AS) { | ||
using namespace AMDGPUAS; | ||
case CONSTANT_ADDRESS: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be a helper in AMDGPUAddrSpace.h? I'd expect this logic to already exist somewhere, but it looks like AMDGPUAA is only looking for CONSTANT_ADDRESS and nothing else:
if (LI->getPointerAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS) |
2c640e5
to
393311c
Compare
@@ -401,6 +403,10 @@ void Lint::visitMemoryReference(Instruction &I, const MemoryLocation &Loc, | |||
"Unusual: Address one pointer dereference", &I); | |||
|
|||
if (Flags & MemRef::Write) { | |||
if (TT.isAMDGPU()) | |||
Check(!AMDGPU::isConstantAddressSpace(UnderlyingObject->getType()->getPointerAddressSpace()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible or better to do the check via TTI? I'm not sure if it's a good idea to do the check based on triple.
; RUN: opt --mtriple=amdgcn --mcpu=gfx1030 --passes=lint %s -o /dev/null |& FileCheck %s --check-prefixes=CHECK,CHECK0 | ||
; RUN: opt --mtriple=x86_64 --passes=lint --lint-abort-on-error %s -o /dev/null |& FileCheck %s --allow-empty --check-prefix=NOERR | ||
; NOERR: {{^$}} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you will need ; REQUIRES: amdgpu-registered-target
as well as other targets that you want to test.
Ensure store to const addrspace is not allowed by IR Verifier.