Skip to content

Commit 7c255d7

Browse files
committed
[AMDGCN] Error checking for llvm.amdgcn.init.exec.from.input intrinsic
This patch catches some cases of illegal use of the llvm.amdgcn.init.exec.from.input intrinsic, which is only permitted to take its first parameter from an SGPR argument of the containing function. The intrinsic in question isn't intended to be user-facing, so we don't need to go to extraordinary lengths to make the error handling bulletproof. I made it an error instead of an assertion though so the new test cases work unconditionally.
1 parent 5e26fb1 commit 7c255d7

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed

llvm/lib/Target/AMDGPU/SIWholeQuadMode.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1622,7 +1622,21 @@ void SIWholeQuadMode::lowerInitExec(MachineInstr &MI) {
16221622
MachineInstr *FirstMI = &*MBB->begin();
16231623
if (InputReg.isVirtual()) {
16241624
MachineInstr *DefInstr = MRI->getVRegDef(InputReg);
1625-
assert(DefInstr && DefInstr->isCopy());
1625+
// This condition catches some cases where a
1626+
// llvm.amdgcn.init.exec.from.input intrinsic's first argument comes from
1627+
// somewhere other than a (SGPR) function argument, which is forbidden.
1628+
if (!DefInstr || !DefInstr->isCopy() ||
1629+
(DefInstr->getNumOperands() == 2 && DefInstr->getOperand(1).isReg() &&
1630+
TRI->isVectorRegister(*MRI, DefInstr->getOperand(1).getReg()))) {
1631+
MachineFunction *MF = MBB->getParent();
1632+
DebugLoc DL = DefInstr->getDebugLoc();
1633+
DiagnosticInfoUnsupported IllegalArg(
1634+
MF->getFunction(), "EXEC must be initialized using function argument",
1635+
DL, DS_Error);
1636+
LLVMContext &C = MF->getFunction().getContext();
1637+
C.diagnose(IllegalArg);
1638+
return;
1639+
}
16261640
if (DefInstr->getParent() == MBB) {
16271641
if (DefInstr != FirstMI) {
16281642
// If the `InputReg` is defined in current block, we also need to
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
; RUN: not llc -mtriple=amdgcn -mcpu=gfx942 -O3 -global-isel=true -o - %s 2>&1 | FileCheck -check-prefix=ERR %s
2+
3+
source_filename = "llvm.amdgcn.init.exec.wave32.ll"
4+
5+
@G = global i32 -2147483648
6+
@G.1 = global <32 x i32> splat (i32 1)
7+
@G.2 = global <16 x i64> splat (i64 1)
8+
@G.3 = global <8 x i1> zeroinitializer
9+
10+
define amdgpu_ps float @test_init_exec(float %a, float %b) {
11+
main_body:
12+
%s = fadd float %a, %b
13+
call void @llvm.amdgcn.init.exec(i64 74565)
14+
ret float %s
15+
}
16+
17+
define amdgpu_ps float @test_init_exec_from_input(i32 inreg %0, i32 inreg %1, i32 inreg %2, i32 inreg %count, float %a, float %b) {
18+
main_body:
19+
%LGV2 = load <16 x i64>, ptr @G.2, align 128
20+
%LGV1 = load <32 x i32>, ptr @G.1, align 128
21+
%LGV = load i32, ptr @G, align 4
22+
%C = call <8 x i1> @f(<32 x i32> %LGV1, <16 x i64> %LGV2, <2 x half> splat (half 0xH5140))
23+
%B = or i32 0, %LGV
24+
%s = fadd float %a, %b
25+
call void @llvm.amdgcn.init.exec.from.input(i32 %B, i32 8)
26+
store <8 x i1> %C, ptr @G.3, align 1
27+
ret float %s
28+
}
29+
30+
; Function Attrs: convergent nocallback nofree nounwind willreturn
31+
declare void @llvm.amdgcn.init.exec(i64 immarg) #0
32+
33+
; Function Attrs: convergent nocallback nofree nounwind willreturn
34+
declare void @llvm.amdgcn.init.exec.from.input(i32, i32 immarg) #0
35+
36+
declare <8 x i1> @f(<32 x i32>, <16 x i64>, <2 x half>)
37+
38+
attributes #0 = { convergent nocallback nofree nounwind willreturn }
39+
40+
ERR: error: <unknown>:0:0: in function test_init_exec_from_input float (i32, i32, i32, i32, float, float): EXEC must be initialized using function argument
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
; RUN: not llc -mtriple=amdgcn -mcpu=gfx942 -O3 -global-isel=false -o - %s 2>&1 | FileCheck -check-prefix=ERR %s
2+
3+
source_filename = "llvm.amdgcn.init.exec.wave32.ll"
4+
5+
@G = global i32 -2147483648
6+
@G.1 = global <32 x i32> splat (i32 1)
7+
@G.2 = global <16 x i64> splat (i64 1)
8+
@G.3 = global <8 x i1> zeroinitializer
9+
10+
define amdgpu_ps float @test_init_exec(float %a, float %b) {
11+
main_body:
12+
%s = fadd float %a, %b
13+
call void @llvm.amdgcn.init.exec(i64 74565)
14+
ret float %s
15+
}
16+
17+
define amdgpu_ps float @test_init_exec_from_input(i32 inreg %0, i32 inreg %1, i32 inreg %2, i32 inreg %count, float %a, float %b) {
18+
main_body:
19+
%LGV2 = load <16 x i64>, ptr @G.2, align 128
20+
%LGV1 = load <32 x i32>, ptr @G.1, align 128
21+
%LGV = load i32, ptr @G, align 4
22+
%C = call <8 x i1> @f(<32 x i32> %LGV1, <16 x i64> %LGV2, <2 x half> splat (half 0xH5140))
23+
%B = or i32 0, %LGV
24+
%s = fadd float %a, %b
25+
call void @llvm.amdgcn.init.exec.from.input(i32 %B, i32 8)
26+
store <8 x i1> %C, ptr @G.3, align 1
27+
ret float %s
28+
}
29+
30+
; Function Attrs: convergent nocallback nofree nounwind willreturn
31+
declare void @llvm.amdgcn.init.exec(i64 immarg) #0
32+
33+
; Function Attrs: convergent nocallback nofree nounwind willreturn
34+
declare void @llvm.amdgcn.init.exec.from.input(i32, i32 immarg) #0
35+
36+
declare <8 x i1> @f(<32 x i32>, <16 x i64>, <2 x half>)
37+
38+
attributes #0 = { convergent nocallback nofree nounwind willreturn }
39+
40+
ERR: error: <unknown>:0:0: in function test_init_exec_from_input float (i32, i32, i32, i32, float, float): EXEC must be initialized using function argument

0 commit comments

Comments
 (0)