Skip to content

Commit 6aed43f

Browse files
vsemenov368igcbot
authored andcommitted
Add support for SPIRV MulExtended instructions in VC
Enable SPIRV UMulExtended and SMulExtended instructions
1 parent 84c5faa commit 6aed43f

File tree

2 files changed

+118
-1
lines changed

2 files changed

+118
-1
lines changed

IGC/VectorCompiler/lib/GenXOpts/CMTrans/GenXTranslateSPIRVBuiltins.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*========================== begin_copyright_notice ============================
22
3-
Copyright (C) 2021-2024 Intel Corporation
3+
Copyright (C) 2021-2025 Intel Corporation
44
55
SPDX-License-Identifier: MIT
66
@@ -69,6 +69,7 @@ class SPIRVExpander : public InstVisitor<SPIRVExpander, Value *> {
6969
ArrayRef<Value *> Args, bool AFN = false);
7070
Value *emitFDiv(IRBuilder<> &Builder, Value *L, Value *R, bool ARCP = false);
7171
Value *emitAddcSubb(IRBuilder<> &Builder, unsigned IID, CallInst &CI);
72+
Value *emitMulExtended(IRBuilder<> &Builder, unsigned IID, CallInst &CI);
7273
Value *emitDot(IRBuilder<> &Builder, unsigned IID, CallInst &CI);
7374

7475
Module *M;
@@ -117,6 +118,7 @@ Value *SPIRVExpander::emitAddcSubb(IRBuilder<> &Builder, unsigned IID,
117118
if (ArgTy->getScalarType()->getPrimitiveSizeInBits() < 32) {
118119
vc::diagnose(CI.getFunction()->getContext(), "GenXTranslateSPIRV",
119120
"only 32/64-bit addc/subb supported", &CI);
121+
return nullptr;
120122
}
121123
auto *Instr = emitIntrinsic(Builder, IID, {ArgTy, ArgTy},
122124
{CI.getArgOperand(1), CI.getArgOperand(2)});
@@ -144,6 +146,34 @@ Value *SPIRVExpander::emitAddcSubb(IRBuilder<> &Builder, unsigned IID,
144146
Builder.CreateStore(ExtRes, ResPtr);
145147
return Builder.CreateStore(Carry, CarryPtr);
146148
}
149+
150+
Value *SPIRVExpander::emitMulExtended(IRBuilder<> &Builder, unsigned IID,
151+
CallInst &CI) {
152+
auto *Res = CI.getArgOperand(0);
153+
154+
auto *Ty = CI.getArgOperand(1)->getType();
155+
if (Ty->getScalarType()->getPrimitiveSizeInBits() != 32) {
156+
vc::diagnose(CI.getFunction()->getContext(), "GenXTranslateSPIRV",
157+
"only 32 MulExtended supported", &CI);
158+
return nullptr;
159+
}
160+
161+
auto *Zero = Constant::getNullValue(Ty);
162+
auto *Instr = emitIntrinsic(Builder, IID, {Ty, Ty},
163+
{CI.getArgOperand(1), CI.getArgOperand(2), Zero});
164+
165+
auto *Lo = Builder.CreateExtractValue(Instr, {0});
166+
auto *Hi = Builder.CreateExtractValue(Instr, {1});
167+
168+
unsigned int AddrSpace = cast<PointerType>(Res->getType())->getAddressSpace();
169+
Res = Builder.CreateBitCast(Res, PointerType::get(Ty, AddrSpace));
170+
auto *LoPtr = Builder.CreateGEP(Ty, Res, Builder.getInt32(0));
171+
auto *HiPtr = Builder.CreateGEP(Ty, Res, Builder.getInt32(1));
172+
173+
Builder.CreateStore(Lo, LoPtr);
174+
return Builder.CreateStore(Hi, HiPtr);
175+
}
176+
147177
Value *SPIRVExpander::emitDot(IRBuilder<> &Builder, unsigned IID,
148178
CallInst &CI) {
149179
auto *Ty = CI.getType();
@@ -248,6 +278,14 @@ Value *SPIRVExpander::visitCallInst(CallInst &CI) {
248278
if (IID != Intrinsic::not_intrinsic)
249279
return emitAddcSubb(Builder, IID, CI);
250280

281+
IID = StringSwitch<unsigned>(CalleeName)
282+
.StartsWith("UMulExtended", GenXIntrinsic::genx_uimad)
283+
.StartsWith("SMulExtended", GenXIntrinsic::genx_simad)
284+
.Default(Intrinsic::not_intrinsic);
285+
286+
if (IID != Intrinsic::not_intrinsic)
287+
return emitMulExtended(Builder, IID, CI);
288+
251289
if (CalleeName.startswith("Dot")) {
252290
return emitDot(Builder, IID, CI);
253291
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
;=========================== begin_copyright_notice ============================
2+
;
3+
; Copyright (C) 2025 Intel Corporation
4+
;
5+
; SPDX-License-Identifier: MIT
6+
;
7+
;============================ end_copyright_notice =============================
8+
;
9+
; RUN: %opt_legacy_typed %use_old_pass_manager% -GenXTranslateSPIRVBuiltins \
10+
; RUN: -vc-spirv-builtins-bif-path=%VC_SPIRV_OCL_BIF% -march=genx64 \
11+
; RUN: -mtriple=spir64-unknown-unknown -mcpu=XeHPC -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-TYPED-PTRS
12+
; RUN: %opt_legacy_opaque %use_old_pass_manager% -GenXTranslateSPIRVBuiltins \
13+
; RUN: -vc-spirv-builtins-bif-path=%VC_SPIRV_OCL_BIF% -march=genx64 \
14+
; RUN: -mtriple=spir64-unknown-unknown -mcpu=XeHPC -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-OPAQUE-PTRS
15+
; RUN: %opt_new_pm_typed -passes=GenXTranslateSPIRVBuiltins \
16+
; RUN: -vc-spirv-builtins-bif-path=%VC_SPIRV_OCL_BIF% -march=genx64 \
17+
; RUN: -mtriple=spir64-unknown-unknown -mcpu=XeHPC -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-TYPED-PTRS
18+
; RUN: %opt_new_pm_opaque -passes=GenXTranslateSPIRVBuiltins \
19+
; RUN: -vc-spirv-builtins-bif-path=%VC_SPIRV_OCL_BIF% -march=genx64 \
20+
; RUN: -mtriple=spir64-unknown-unknown -mcpu=XeHPC -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-OPAQUE-PTRS
21+
; ------------------------------------------------
22+
; GenXTranslateSPIRVBuiltins
23+
; ------------------------------------------------
24+
; This test checks that GenXTranslateSPIRVBuiltins translates addc
25+
26+
%struct_pair = type { <16 x i32>, <16 x i32> }
27+
28+
; CHECK: [[UIMAD:%[^ ]*]] = call { <16 x i32>, <16 x i32> } @llvm.genx.uimad.v16i32.v16i32(<16 x i32> {{.*}}, <16 x i32> {{.*}})
29+
; CHECK: [[LO:%[^ ]*]] = extractvalue { <16 x i32>, <16 x i32> } [[UIMAD]], 0
30+
; CHECK: [[HI:%[^ ]*]] = extractvalue { <16 x i32>, <16 x i32> } [[UIMAD]], 1
31+
; CHECK-TYPED-PTRS: [[PTR_CAST:%[^ ]*]] = bitcast %struct_pair addrspace(4)* {{.*}} to <16 x i32> addrspace(4)*
32+
; CHECK-TYPED-PTRS: [[PTR_LO:%[^ ]*]] = getelementptr <16 x i32>, <16 x i32> addrspace(4)* [[PTR_CAST]], i32 0
33+
; CHECK-TYPED-PTRS: [[PTR_HI:%[^ ]*]] = getelementptr <16 x i32>, <16 x i32> addrspace(4)* [[PTR_CAST]], i32 1
34+
; CHECK-TYPED-PTRS: store <16 x i32> [[LO]], <16 x i32> addrspace(4)* [[PTR_LO]], align 64
35+
; CHECK-TYPED-PTRS: store <16 x i32> [[HI]], <16 x i32> addrspace(4)* [[PTR_HI]], align 64
36+
; CHECK-OPAQUE-PTRS: [[PTR_LO:%[^ ]*]] = getelementptr <16 x i32>, ptr addrspace(4) {{.*}}, i32 0
37+
; CHECK-OPAQUE-PTRS: [[PTR_HI:%[^ ]*]] = getelementptr <16 x i32>, ptr addrspace(4) {{.*}}, i32 1
38+
; CHECK-OPAQUE-PTRS: store <16 x i32> [[LO]], ptr addrspace(4) [[PTR_LO]], align 64
39+
; CHECK-OPAQUE-PTRS: store <16 x i32> [[HI]], ptr addrspace(4) [[PTR_HI]], align 64
40+
41+
; Function Attrs: nounwind
42+
define dllexport spir_kernel void @test_umul() #0 {
43+
entry:
44+
%alloca1 = alloca %struct_pair, align 64
45+
%alloca2 = addrspacecast %struct_pair* %alloca1 to %struct_pair addrspace(4)*
46+
%first = add <16 x i32> zeroinitializer, <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
47+
%second = add <16 x i32> zeroinitializer, <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
48+
call spir_func void @_Z20__spirv_UMulExtendedDv16_iS_(%struct_pair addrspace(4)* sret(%struct_pair) %alloca2, <16 x i32> %first, <16 x i32> %second)
49+
ret void
50+
}
51+
declare spir_func void @_Z20__spirv_UMulExtendedDv16_iS_(%struct_pair addrspace(4)* sret(%struct_pair), <16 x i32>, <16 x i32>)
52+
53+
; CHECK: [[SIMAD:%[^ ]*]] = call { <16 x i32>, <16 x i32> } @llvm.genx.simad.v16i32.v16i32(<16 x i32> {{.*}}, <16 x i32> {{.*}})
54+
; CHECK: [[LO:%[^ ]*]] = extractvalue { <16 x i32>, <16 x i32> } [[SIMAD]], 0
55+
; CHECK: [[HI:%[^ ]*]] = extractvalue { <16 x i32>, <16 x i32> } [[SIMAD]], 1
56+
; CHECK-TYPED-PTRS: [[PTR_CAST:%[^ ]*]] = bitcast %struct_pair addrspace(4)* {{.*}} to <16 x i32> addrspace(4)*
57+
; CHECK-TYPED-PTRS: [[PTR_LO:%[^ ]*]] = getelementptr <16 x i32>, <16 x i32> addrspace(4)* [[PTR_CAST]], i32 0
58+
; CHECK-TYPED-PTRS: [[PTR_HI:%[^ ]*]] = getelementptr <16 x i32>, <16 x i32> addrspace(4)* [[PTR_CAST]], i32 1
59+
; CHECK-TYPED-PTRS: store <16 x i32> [[LO]], <16 x i32> addrspace(4)* [[PTR_LO]], align 64
60+
; CHECK-TYPED-PTRS: store <16 x i32> [[HI]], <16 x i32> addrspace(4)* [[PTR_HI]], align 64
61+
; CHECK-OPAQUE-PTRS: [[PTR_LO:%[^ ]*]] = getelementptr <16 x i32>, ptr addrspace(4) {{.*}}, i32 0
62+
; CHECK-OPAQUE-PTRS: [[PTR_HI:%[^ ]*]] = getelementptr <16 x i32>, ptr addrspace(4) {{.*}}, i32 1
63+
; CHECK-OPAQUE-PTRS: store <16 x i32> [[LO]], ptr addrspace(4) [[PTR_LO]], align 64
64+
; CHECK-OPAQUE-PTRS: store <16 x i32> [[HI]], ptr addrspace(4) [[PTR_HI]], align 64
65+
66+
; Function Attrs: nounwind
67+
define dllexport spir_kernel void @test_smul() #0 {
68+
entry:
69+
%alloca1 = alloca %struct_pair, align 64
70+
%alloca2 = addrspacecast %struct_pair* %alloca1 to %struct_pair addrspace(4)*
71+
%first = add <16 x i32> zeroinitializer, <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
72+
%second = add <16 x i32> zeroinitializer, <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
73+
call spir_func void @_Z20__spirv_SMulExtendedDv16_iS_(%struct_pair addrspace(4)* sret(%struct_pair) %alloca2, <16 x i32> %first, <16 x i32> %second)
74+
ret void
75+
}
76+
declare spir_func void @_Z20__spirv_SMulExtendedDv16_iS_(%struct_pair addrspace(4)* sret(%struct_pair), <16 x i32>, <16 x i32>)
77+
78+
attributes #0 = { nounwind "CMGenxMain" "oclrt"="1" }
79+

0 commit comments

Comments
 (0)