Skip to content

[AMDGPU] Change handling of unsupported non-compute shaders with HSA #126798

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

Merged
merged 4 commits into from
Feb 13, 2025

Conversation

ro-i
Copy link
Contributor

@ro-i ro-i commented Feb 11, 2025

Previous handling in SITargetLowering::LowerFormalArguments only reported a diagnostic message and continued execution by returning a non-usable SDValue. This results in llvm crashing later with an unrelated error. This commit changes the detection of an unsupported non-compute shader to be a fatal error right away.

As an example situation, take the usage of an amdgpu_ps function and the amdgcn-unknown-amdhsa target triple.

define amdgpu_ps void @foo(ptr %p, i32 %i) {
        store i32 %i, ptr %p
        ret void
}

Compiling this code (with llc -mtriple=amdgcn-unknown-amdhsa -mcpu=gfx942, for example) fails with:

error: <unknown>:0:0: in function foo void (ptr, i32): unsupported non-compute shaders with HSA

llc:
[...]/git/trunk21.0/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:11790:
void llvm::SelectionDAGISel::LowerArguments(const llvm::Function&):
Assertion `InVals.size() == Ins.size() && "LowerFormalArguments didn't emit the correct number of values!"' failed.
[...]

Previous handling in `SITargetLowering::LowerFormalArguments` only
reported a diagnostic message and continued execution by returning a
non-usable `SDValue`. This results in llvm crashing later with an
unrelated error.  This commit changes the detection of an unsupported
non-compute shader to be a fatal error right away.
@llvmbot
Copy link
Member

llvmbot commented Feb 11, 2025

@llvm/pr-subscribers-backend-amdgpu

Author: Robert Imschweiler (ro-i)

Changes

Previous handling in SITargetLowering::LowerFormalArguments only reported a diagnostic message and continued execution by returning a non-usable SDValue. This results in llvm crashing later with an unrelated error. This commit changes the detection of an unsupported non-compute shader to be a fatal error right away.

As an example situation, take the usage of an amdgpu_ps function and the amdgcn-unknown-amdhsa target triple.

define amdgpu_ps void @<!-- -->foo(ptr %p, i32 %i) {
        store i32 %i, ptr %p
        ret void
}

Compiling this code (with llc -mtriple=amdgcn-unknown-amdhsa -mcpu=gfx942, for example) fails with:

error: &lt;unknown&gt;:0:0: in function foo void (ptr, i32): unsupported non-compute shaders with HSA

llc:
[...]/git/trunk21.0/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:11790:
void llvm::SelectionDAGISel::LowerArguments(const llvm::Function&amp;):
Assertion `InVals.size() == Ins.size() &amp;&amp; "LowerFormalArguments didn't emit the correct number of values!"' failed.
[...]

Full diff: https://github.com/llvm/llvm-project/pull/126798.diff

2 Files Affected:

  • (modified) llvm/lib/Target/AMDGPU/SIISelLowering.cpp (+1-4)
  • (removed) llvm/test/CodeGen/AMDGPU/no-hsa-graphics-shaders.ll (-19)
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index b632c50dae0e3..746bde4de5e9f 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -2824,10 +2824,7 @@ SDValue SITargetLowering::LowerFormalArguments(
   SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
 
   if (Subtarget->isAmdHsaOS() && AMDGPU::isGraphics(CallConv)) {
-    DiagnosticInfoUnsupported NoGraphicsHSA(
-        Fn, "unsupported non-compute shaders with HSA", DL.getDebugLoc());
-    DAG.getContext()->diagnose(NoGraphicsHSA);
-    return DAG.getEntryNode();
+    report_fatal_error("unsupported non-compute shaders with HSA");
   }
 
   SmallVector<ISD::InputArg, 16> Splits;
diff --git a/llvm/test/CodeGen/AMDGPU/no-hsa-graphics-shaders.ll b/llvm/test/CodeGen/AMDGPU/no-hsa-graphics-shaders.ll
deleted file mode 100644
index ee6a578c72859..0000000000000
--- a/llvm/test/CodeGen/AMDGPU/no-hsa-graphics-shaders.ll
+++ /dev/null
@@ -1,19 +0,0 @@
-; RUN: not llc -mtriple=amdgcn-unknown-amdhsa < %s 2>&1 | FileCheck %s
-
-; CHECK: in function pixel_s{{.*}}: unsupported non-compute shaders with HSA
-define amdgpu_ps void @pixel_shader() #0 {
-  ret void
-}
-
-; CHECK: in function vertex_s{{.*}}: unsupported non-compute shaders with HSA
-define amdgpu_vs void @vertex_shader() #0 {
-  ret void
-}
-
-; CHECK: in function geometry_s{{.*}}: unsupported non-compute shaders with HSA
-define amdgpu_gs void @geometry_shader() #0 {
-  ret void
-}
-
-!llvm.module.flags = !{!0}
-!0 = !{i32 1, !"amdhsa_code_object_version", i32 400}

Fn, "unsupported non-compute shaders with HSA", DL.getDebugLoc());
DAG.getContext()->diagnose(NoGraphicsHSA);
return DAG.getEntryNode();
report_fatal_error("unsupported non-compute shaders with HSA");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be a fatal error. You should adjust the return value to be the correct type by using the correct set of undef values

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the point? There will be no valid output anyways. Trying to validate even invalid output takes a lot of effort and will ityself be fragile because that code is rarely executed/tested.

@@ -1,19 +0,0 @@
; RUN: not llc -mtriple=amdgcn-unknown-amdhsa < %s 2>&1 | FileCheck %s

; CHECK: in function pixel_s{{.*}}: unsupported non-compute shaders with HSA
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must maintain test coverage for error cases

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to adapt the test, but FileCheck didn't seem to be able to check for the LLVM ERROR ... line (first line of output/stderr). So I assumed that it may not be possible to check for fatal errors. But now the situation is different anyway :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you try not --crash?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, in the meantime, I found this by searching through similar tests (basically grep -rl "LLVM ERROR" ^^). However, it still somehow skipped the first line, even though stderr was redirected to stdout. But this is no longer an issue since I removed the fatal error again, based on the feedback I received here.

@shiltian
Copy link
Contributor

My .02 is, we should not fix all fuzzer issues, even though they might crash the compiler. When we run certain pass, it is safe to assume certain things, but fuzzer breaks these assumptions on purpose by directly feeding the pass with broken input. Those errors can't reach the pass if the input runs through a pipeline. For them, I think we should capture them in verifier instead of making every single pass to do certain jobs of the verifier, which doesn't make too much sense to me.

@arsenm
Copy link
Contributor

arsenm commented Feb 12, 2025

My .02 is, we should not fix all fuzzer issues, even though they might crash the compiler. When we run certain pass, it is safe to assume certain things, but fuzzer breaks these assumptions on purpose by directly feeding the pass with broken input. Those errors can't reach the pass if the input runs through a pipeline. For them, I think we should capture them in verifier instead of making every single pass to do certain jobs of the verifier, which doesn't make too much sense to me.

This one is actually really super annoying and we should fix it properly. This also doesn't really belong in the IR verifier.

@ro-i
Copy link
Contributor Author

ro-i commented Feb 12, 2025

This one is actually really super annoying and we should fix it properly.

I pushed some changes. Do you think they are going in the right direction?

Edit: annoying because it shouldn't be fixed? Or annoying because it is worth fixing but tricky?

Copy link

github-actions bot commented Feb 12, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@shiltian
Copy link
Contributor

This one is actually really super annoying and we should fix it properly. This also doesn't really belong in the IR verifier.

My reading is, amdgpu_ps functions should not exist for amdhsa OS. If it does, the input IR is broken for amdhsa. The IR itself might not be really invalid, but just under certain circumstances. I'm not very sure that whether IR verifier is supposed to be target agnostic. For example, is the IR still valid (from the verifier's perspective) if I invoke opt or llc with a x86 IR (assume the IR has some x86 dedicated stuff) but the target triple is amdgcn?

@@ -2933,7 +2937,7 @@ SDValue SITargetLowering::LowerFormalArguments(

for (unsigned i = 0, e = Ins.size(), ArgIdx = 0; i != e; ++i) {
const ISD::InputArg &Arg = Ins[i];
if (Arg.isOrigArg() && Skipped[Arg.getOrigArgIndex()]) {
if ((Arg.isOrigArg() && Skipped[Arg.getOrigArgIndex()]) || IsUnsupportedHsa) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to keep this as it is with the separated handling down here, I'd go with a broader IsError or something.
However, I think it would be cleaner to just have a separate loop populating InVals in the error case with the undefs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, I think it would be cleaner to just have a separate loop populating InVals in the error case with the undefs

When I do this:

  if (Subtarget->isAmdHsaOS() && AMDGPU::isGraphics(CallConv)) {
    DiagnosticInfoUnsupported NoGraphicsHSA(
        Fn, "unsupported non-compute shaders with HSA", DL.getDebugLoc());
    DAG.getContext()->diagnose(NoGraphicsHSA);
    for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
      const ISD::InputArg &Arg = Ins[i];
      InVals.push_back(DAG.getUNDEF(Arg.VT));
    }
    return Chain;
  }

I get the following error later:
llc: ~/git/trunk21.0/llvm-project/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h:945: void llvm::SIMachineFunctionInfo::setScratchRSrcReg(llvm::Register): Assertion `Reg != 0 && "Should never be unset"' failed.
I suspect the problem is that the other initialization stuff isn't done because of the early return.

Or are you thinking about something else?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, the other special input setup stuff still needs to happen. I suppose you can rename the variable

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although in that case we should stop requiring the CC lowering to set up the scratch resource. It's really a fixed constant

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, the other special input setup stuff still needs to happen. I suppose you can rename the variable

Already done :)

Although in that case we should stop requiring the CC lowering to set up the scratch resource. It's really a fixed constant

Hm, the function seems to do a lot of things (which I don't fully understand yet) in the case of IsGraphics and IsEntryFunc. Is it possible to pull all this into the error handling without too much code duplication?

@arsenm arsenm merged commit 0da8d0f into llvm:main Feb 13, 2025
8 checks passed
joaosaffran pushed a commit to joaosaffran/llvm-project that referenced this pull request Feb 14, 2025
…lvm#126798)

Previous handling in `SITargetLowering::LowerFormalArguments` only
reported a diagnostic message and continued execution by returning a
non-usable `SDValue`. This results in llvm crashing later with an
unrelated error. This commit changes the detection of an unsupported
non-compute shader to be a fatal error right away.

As an example situation, take the usage of an `amdgpu_ps` function and
the `amdgcn-unknown-amdhsa` target triple.
```
define amdgpu_ps void @foo(ptr %p, i32 %i) {
        store i32 %i, ptr %p
        ret void
}
```
Compiling this code (with `llc -mtriple=amdgcn-unknown-amdhsa
-mcpu=gfx942`, for example) fails with:
```
error: <unknown>:0:0: in function foo void (ptr, i32): unsupported non-compute shaders with HSA

llc:
[...]/git/trunk21.0/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:11790:
void llvm::SelectionDAGISel::LowerArguments(const llvm::Function&):
Assertion `InVals.size() == Ins.size() && "LowerFormalArguments didn't emit the correct number of values!"' failed.
[...]
```
@ro-i ro-i deleted the unsupported-hsa-fatal branch February 21, 2025 20:10
sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Feb 24, 2025
…lvm#126798)

Previous handling in `SITargetLowering::LowerFormalArguments` only
reported a diagnostic message and continued execution by returning a
non-usable `SDValue`. This results in llvm crashing later with an
unrelated error. This commit changes the detection of an unsupported
non-compute shader to be a fatal error right away.

As an example situation, take the usage of an `amdgpu_ps` function and
the `amdgcn-unknown-amdhsa` target triple.
```
define amdgpu_ps void @foo(ptr %p, i32 %i) {
        store i32 %i, ptr %p
        ret void
}
```
Compiling this code (with `llc -mtriple=amdgcn-unknown-amdhsa
-mcpu=gfx942`, for example) fails with:
```
error: <unknown>:0:0: in function foo void (ptr, i32): unsupported non-compute shaders with HSA

llc:
[...]/git/trunk21.0/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp:11790:
void llvm::SelectionDAGISel::LowerArguments(const llvm::Function&):
Assertion `InVals.size() == Ins.size() && "LowerFormalArguments didn't emit the correct number of values!"' failed.
[...]
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants