Skip to content

Commit 42d801d

Browse files
[SPIR-V] Account for zext in a llvm intrinsic call (#88903)
This PR addresses an issue that may arise when an integer argument size differs from a machine word size for the target in a call to llvm intrinsic. The following example demonstrates the issue: ``` @__const.test.arr = private unnamed_addr addrspace(2) constant [3 x i32] [i32 1, i32 2, i32 3] define spir_func void @test() { entry: %arr = alloca [3 x i32], align 4 %dest = bitcast ptr %arr to ptr call void @llvm.memcpy.p0.p2.i32(ptr align 4 %dest, ptr addrspace(2) align 4 @__const.test.arr, i32 1024, i1 false) ret void } declare void @llvm.memcpy.p0.p2.i32(ptr nocapture writeonly, ptr addrspace(2) nocapture readonly, i32, i1) ``` Depending on the target this code may work or may fail without this PR due to the fact that IR Translation step introduces additional `zext` when type of the 3rd argument of `@llvm.memcpy.p0.p2.i32` differs from machine word. This PR addresses the issue by adding type deduction for a newly inserted G_ZEXT generic opcode.
1 parent b512df6 commit 42d801d

File tree

3 files changed

+99
-20
lines changed

3 files changed

+99
-20
lines changed

llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR,
171171
// %1 = G_GLOBAL_VALUE
172172
// %2 = COPY %1
173173
// %3 = G_ADDRSPACE_CAST %2
174+
//
175+
// or
176+
//
177+
// %1 = G_ZEXT %2
178+
// G_MEMCPY ... %2 ...
179+
//
174180
// New registers have no SPIRVType and no register class info.
175181
//
176182
// Set SPIRVType for GV, propagate it from GV to other instructions,
@@ -200,6 +206,24 @@ static SPIRVType *propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR,
200206
SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB);
201207
break;
202208
}
209+
case TargetOpcode::G_ZEXT: {
210+
if (MI->getOperand(1).isReg()) {
211+
if (MachineInstr *DefInstr =
212+
MRI.getVRegDef(MI->getOperand(1).getReg())) {
213+
if (SPIRVType *Def = propagateSPIRVType(DefInstr, GR, MRI, MIB)) {
214+
unsigned CurrentBW = GR->getScalarOrVectorBitWidth(Def);
215+
unsigned ExpectedBW =
216+
std::max(MRI.getType(Reg).getScalarSizeInBits(), CurrentBW);
217+
unsigned NumElements = GR->getScalarOrVectorComponentCount(Def);
218+
SpirvTy = GR->getOrCreateSPIRVIntegerType(ExpectedBW, MIB);
219+
if (NumElements > 1)
220+
SpirvTy =
221+
GR->getOrCreateSPIRVVectorType(SpirvTy, NumElements, MIB);
222+
}
223+
}
224+
}
225+
break;
226+
}
203227
case TargetOpcode::G_TRUNC:
204228
case TargetOpcode::G_ADDRSPACE_CAST:
205229
case TargetOpcode::G_PTR_ADD:
@@ -415,6 +439,7 @@ static void generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
415439
}
416440
insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MRI);
417441
} else if (MI.getOpcode() == TargetOpcode::G_TRUNC ||
442+
MI.getOpcode() == TargetOpcode::G_ZEXT ||
418443
MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
419444
MI.getOpcode() == TargetOpcode::COPY ||
420445
MI.getOpcode() == TargetOpcode::G_ADDRSPACE_CAST) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-32
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-64
4+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
5+
6+
; CHECK-64-DAG: %[[#i64:]] = OpTypeInt 64 0
7+
8+
; CHECK-DAG: %[[#i8:]] = OpTypeInt 8 0
9+
; CHECK-DAG: %[[#i32:]] = OpTypeInt 32 0
10+
; CHECK-DAG: %[[#one:]] = OpConstant %[[#i32]] 1
11+
; CHECK-DAG: %[[#two:]] = OpConstant %[[#i32]] 2
12+
; CHECK-DAG: %[[#three:]] = OpConstant %[[#i32]] 3
13+
; CHECK-DAG: %[[#i32x3:]] = OpTypeArray %[[#i32]] %[[#three]]
14+
; CHECK-DAG: %[[#test_arr_init:]] = OpConstantComposite %[[#i32x3]] %[[#one]] %[[#two]] %[[#three]]
15+
; CHECK-DAG: %[[#szconst1024:]] = OpConstant %[[#i32]] 1024
16+
; CHECK-DAG: %[[#szconst42:]] = OpConstant %[[#i8]] 42
17+
; CHECK-DAG: %[[#const_i32x3_ptr:]] = OpTypePointer UniformConstant %[[#i32x3]]
18+
; CHECK-DAG: %[[#test_arr:]] = OpVariable %[[#const_i32x3_ptr]] UniformConstant %[[#test_arr_init]]
19+
; CHECK-DAG: %[[#i32x3_ptr:]] = OpTypePointer Function %[[#i32x3]]
20+
; CHECK: %[[#arr:]] = OpVariable %[[#i32x3_ptr]] Function
21+
22+
; CHECK-32: OpCopyMemorySized %[[#arr]] %[[#test_arr]] %[[#szconst1024]]
23+
; CHECK-64: %[[#szconstext1024:]] = OpUConvert %[[#i64:]] %[[#szconst1024:]]
24+
; CHECK-64: OpCopyMemorySized %[[#arr]] %[[#test_arr]] %[[#szconstext1024]]
25+
26+
; CHECK-32: %[[#szconstext42:]] = OpUConvert %[[#i32:]] %[[#szconst42:]]
27+
; CHECK-32: OpCopyMemorySized %[[#arr]] %[[#test_arr]] %[[#szconstext42]]
28+
; CHECK-64: %[[#szconstext42:]] = OpUConvert %[[#i64:]] %[[#szconst42:]]
29+
; CHECK-64: OpCopyMemorySized %[[#arr]] %[[#test_arr]] %[[#szconstext42]]
30+
31+
@__const.test.arr = private unnamed_addr addrspace(2) constant [3 x i32] [i32 1, i32 2, i32 3]
32+
33+
define spir_func void @test() {
34+
entry:
35+
%arr = alloca [3 x i32], align 4
36+
%dest = bitcast ptr %arr to ptr
37+
call void @llvm.memcpy.p0.p2.i32(ptr align 4 %dest, ptr addrspace(2) align 4 @__const.test.arr, i32 1024, i1 false)
38+
call void @llvm.memcpy.p0.p2.i8(ptr align 4 %dest, ptr addrspace(2) align 4 @__const.test.arr, i8 42, i1 false)
39+
ret void
40+
}
41+
42+
declare void @llvm.memcpy.p0.p2.i32(ptr nocapture writeonly, ptr addrspace(2) nocapture readonly, i32, i1)
43+
declare void @llvm.memcpy.p0.p2.i8(ptr nocapture writeonly, ptr addrspace(2) nocapture readonly, i8, i1)

llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
1-
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
2-
;
3-
; CHECK-SPIRV-DAG: %[[#i32:]] = OpTypeInt 32 0
4-
; CHECK-SPIRV-DAG: %[[#one:]] = OpConstant %[[#i32]] 1
5-
; CHECK-SPIRV-DAG: %[[#two:]] = OpConstant %[[#i32]] 2
6-
; CHECK-SPIRV-DAG: %[[#three:]] = OpConstant %[[#i32]] 3
7-
; CHECK-SPIRV-DAG: %[[#i32x3:]] = OpTypeArray %[[#i32]] %[[#three]]
8-
; CHECK-SPIRV-DAG: %[[#test_arr_init:]] = OpConstantComposite %[[#i32x3]] %[[#one]] %[[#two]] %[[#three]]
9-
; CHECK-SPIRV-DAG: %[[#twelve:]] = OpConstant %[[#i32]] 12
10-
; CHECK-SPIRV-DAG: %[[#const_i32x3_ptr:]] = OpTypePointer UniformConstant %[[#i32x3]]
11-
12-
; CHECK-SPIRV: %[[#test_arr2:]] = OpVariable %[[#const_i32x3_ptr]] UniformConstant %[[#test_arr_init]]
13-
; CHECK-SPIRV: %[[#test_arr:]] = OpVariable %[[#const_i32x3_ptr]] UniformConstant %[[#test_arr_init]]
14-
15-
; CHECK-SPIRV-DAG: %[[#i32x3_ptr:]] = OpTypePointer Function %[[#i32x3]]
16-
17-
; CHECK-SPIRV: %[[#arr:]] = OpVariable %[[#i32x3_ptr]] Function
18-
; CHECK-SPIRV: %[[#arr2:]] = OpVariable %[[#i32x3_ptr]] Function
19-
; CHECK-SPIRV: OpCopyMemorySized %[[#arr]] %[[#test_arr]] %[[#twelve]] Aligned 4
20-
; CHECK-SPIRV: OpCopyMemorySized %[[#arr2]] %[[#test_arr2]] %[[#twelve]] Aligned 4
1+
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-32
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-64
4+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
5+
6+
; CHECK-SPIRV-64-DAG: %[[#i64:]] = OpTypeInt 64 0
7+
8+
; CHECK-SPIRV-DAG: %[[#i32:]] = OpTypeInt 32 0
9+
; CHECK-SPIRV-DAG: %[[#one:]] = OpConstant %[[#i32]] 1
10+
; CHECK-SPIRV-DAG: %[[#two:]] = OpConstant %[[#i32]] 2
11+
; CHECK-SPIRV-DAG: %[[#three:]] = OpConstant %[[#i32]] 3
12+
; CHECK-SPIRV-DAG: %[[#i32x3:]] = OpTypeArray %[[#i32]] %[[#three]]
13+
; CHECK-SPIRV-DAG: %[[#test_arr_init:]] = OpConstantComposite %[[#i32x3]] %[[#one]] %[[#two]] %[[#three]]
14+
; CHECK-SPIRV-DAG: %[[#twelve:]] = OpConstant %[[#i32]] 12
15+
; CHECK-SPIRV-DAG: %[[#const_i32x3_ptr:]] = OpTypePointer UniformConstant %[[#i32x3]]
16+
17+
; CHECK-SPIRV: %[[#test_arr2:]] = OpVariable %[[#const_i32x3_ptr]] UniformConstant %[[#test_arr_init]]
18+
; CHECK-SPIRV: %[[#test_arr:]] = OpVariable %[[#const_i32x3_ptr]] UniformConstant %[[#test_arr_init]]
19+
20+
; CHECK-SPIRV-DAG: %[[#i32x3_ptr:]] = OpTypePointer Function %[[#i32x3]]
21+
22+
; CHECK-SPIRV: %[[#arr:]] = OpVariable %[[#i32x3_ptr]] Function
23+
; CHECK-SPIRV: %[[#arr2:]] = OpVariable %[[#i32x3_ptr]] Function
24+
25+
; CHECK-SPIRV-32: OpCopyMemorySized %[[#arr]] %[[#test_arr]] %[[#twelve]] Aligned 4
26+
; CHECK-SPIRV-32: OpCopyMemorySized %[[#arr2]] %[[#test_arr2]] %[[#twelve]] Aligned 4
27+
28+
; CHECK-SPIRV-64: %[[#twelvezext1:]] = OpUConvert %[[#i64:]] %[[#twelve:]]
29+
; CHECK-SPIRV-64: OpCopyMemorySized %[[#arr]] %[[#test_arr]] %[[#twelvezext1]] Aligned 4
30+
; CHECK-SPIRV-64: %[[#twelvezext2:]] = OpUConvert %[[#i64:]] %[[#twelve:]]
31+
; CHECK-SPIRV-64: OpCopyMemorySized %[[#arr2]] %[[#test_arr2]] %[[#twelvezext2]] Aligned 4
2132

2233

2334
@__const.test.arr = private unnamed_addr addrspace(2) constant [3 x i32] [i32 1, i32 2, i32 3], align 4

0 commit comments

Comments
 (0)