Skip to content

Commit f439f08

Browse files
[SYCL][ESIMD] Handle scalar loads of SPIRV global vector in LowerESIMD (#8454)
As an optimization of accesses of the first element for vector SPIRV globals sometimes the load will return a scalar and the uses can be of any pattern. In this case, generate GenX calls to access the first element and update the use to instead use the GenX call result rather than the load result. With this last remaining issue fixed, enable VectorCombine for SYCL. --------- Signed-off-by: Sarnie, Nick <[email protected]> Co-authored-by: Alexey Sachkov <[email protected]>
1 parent 1520ebf commit f439f08

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -634,9 +634,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
634634

635635
// Try vectorization/scalarization transforms that are both improvements
636636
// themselves and can allow further folds with GVN and InstCombine.
637-
// Disable for SYCL until SPIR-V reader is updated for all drivers.
638-
if (!SYCLOptimizationMode)
639-
FPM.addPass(VectorCombinePass(/*TryEarlyFoldsOnly=*/true));
637+
FPM.addPass(VectorCombinePass(/*TryEarlyFoldsOnly=*/true));
640638

641639
// Eliminate redundancies.
642640
FPM.addPass(MergedLoadStoreMotionPass());

llvm/lib/SYCLLowerIR/ESIMD/LowerESIMD.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,25 @@ translateSpirvGlobalUses(LoadInst *LI, StringRef SpirvGlobalName,
11951195
return;
11961196
}
11971197

1198+
// As an optimization of accesses of the first element for vector SPIRV
1199+
// globals sometimes the load will return a scalar and the uses can be of any
1200+
// pattern. In this case, generate GenX calls to access the first element and
1201+
// update the use to instead use the GenX call result rather than the load
1202+
// result.
1203+
if (!LI->getType()->isVectorTy()) {
1204+
// Copy users to seperate container for safe modification
1205+
// during iteration.
1206+
SmallVector<User *> Users(LI->users());
1207+
for (User *LU : Users) {
1208+
Instruction *Inst = cast<Instruction>(LU);
1209+
NewInst =
1210+
generateSpirvGlobalGenX(Inst, SpirvGlobalName, /*IndexValue=*/0);
1211+
LU->replaceUsesOfWith(LI, NewInst);
1212+
}
1213+
InstsToErase.push_back(LI);
1214+
return;
1215+
}
1216+
11981217
// Only loads from _vector_ SPIRV globals reach here now. Their users are
11991218
// expected to be ExtractElementInst only, and they are
12001219
// replaced in this loop. When loads from _scalar_ SPIRV globals are handled
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
; RUN: opt -opaque-pointers < %s -passes=LowerESIMD -S | FileCheck %s
2+
3+
; This test checks we lower vector SPIRV globals correctly if
4+
; it is accessed as a scalar as an optimization to get the first element
5+
6+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
7+
target triple = "spir64-unknown-unknown"
8+
9+
@__spirv_BuiltInGlobalInvocationId = external dso_local local_unnamed_addr addrspace(1) constant <3 x i64>, align 32
10+
11+
define spir_kernel void @"__spirv_GlobalInvocationId_xyz"(i64 addrspace(1)* %_arg_) {
12+
; CHECK-LABEL: @__spirv_GlobalInvocationId_xyz(
13+
; CHECK-NEXT: entry:
14+
; CHECK-NEXT: [[DOTESIMD6:%.*]] = call <3 x i32> @llvm.genx.local.id.v3i32()
15+
; CHECK-NEXT: [[LOCAL_ID_X:%.*]] = extractelement <3 x i32> [[DOTESIMD6]], i32 0
16+
; CHECK-NEXT: [[LOCAL_ID_X_CAST_TY:%.*]] = zext i32 [[LOCAL_ID_X]] to i64
17+
; CHECK-NEXT: [[DOTESIMD7:%.*]] = call <3 x i32> @llvm.genx.local.size.v3i32()
18+
; CHECK-NEXT: [[WGSIZE_X:%.*]] = extractelement <3 x i32> [[DOTESIMD7]], i32 0
19+
; CHECK-NEXT: [[WGSIZE_X_CAST_TY:%.*]] = zext i32 [[WGSIZE_X]] to i64
20+
; CHECK-NEXT: [[GROUP_ID_X:%.*]] = call i32 @llvm.genx.group.id.x()
21+
; CHECK-NEXT: [[GROUP_ID_X_CAST_TY:%.*]] = zext i32 [[GROUP_ID_X]] to i64
22+
; CHECK-NEXT: [[MUL8:%.*]] = mul i64 [[WGSIZE_X_CAST_TY]], [[GROUP_ID_X_CAST_TY]]
23+
; CHECK-NEXT: [[ADD9:%.*]] = add i64 [[LOCAL_ID_X_CAST_TY]], [[MUL8]]
24+
; CHECK-NEXT: [[MUL10:%.*]] = shl nuw nsw i64 [[ADD9]], 5
25+
26+
; Verify that the attribute is deleted from GenX declaration
27+
; CHECK-NOT: readnone
28+
entry:
29+
%0 = load i64, ptr addrspace(1) @__spirv_BuiltInGlobalInvocationId, align 32
30+
%mul.i = shl nuw nsw i64 %0, 5
31+
ret void
32+
}

0 commit comments

Comments
 (0)