Skip to content

Commit 6da407f

Browse files
michalpaszkowskiigcbot
authored andcommitted
Migrate ProcessFuncAttributes to TargetExtTy
This commit adds support for recognizing OpenCL/SPIR-V builtins represented as TargetExtTy to ProcessFuncAttributes pass.
1 parent c2d9ec0 commit 6da407f

File tree

6 files changed

+237
-56
lines changed

6 files changed

+237
-56
lines changed

Diff for: IGC/AdaptorCommon/ProcessFuncAttributes.cpp

+22-32
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ SPDX-License-Identifier: MIT
1515
#include "Compiler/CISACodeGen/OpenCLKernelCodeGen.hpp"
1616
#include "Compiler/CodeGenContextWrapper.hpp"
1717
#include "Compiler/Optimizer/OpenCLPasses/StackOverflowDetection/StackOverflowDetection.hpp"
18+
#include "common/BuiltinTypes.h"
1819

1920
#include "common/LLVMWarningsPush.hpp"
2021

@@ -148,55 +149,46 @@ extern bool isSupportedAggregateArgument(Argument* arg);
148149

149150
// Only pointer, struct and array types are considered. E.g. vector type
150151
// cannot contain opaque subtypes, function type may contain but ignored.
151-
static void getContainedStructType(Type *T, SmallPtrSetImpl<StructType *> &Tys)
152+
static void getBuiltinType(Type *T, SmallPtrSetImpl<Type *> &BuiltinTypes)
152153
{
153154
if (StructType *ST = dyn_cast<llvm::StructType>(T))
154155
{
155156
// Check if this has been checked, to avoid spinning on %T = { %T *}.
156-
if (!Tys.count(ST))
157+
if (!BuiltinTypes.count(ST))
157158
{
158-
Tys.insert(ST);
159+
BuiltinTypes.insert(ST);
159160
for (auto I = ST->element_begin(), E = ST->element_end(); I != E; ++I)
160161
{
161-
getContainedStructType(*I, Tys);
162+
getBuiltinType(*I, BuiltinTypes);
162163
}
163164
}
164165
}
165-
else if (auto PT = dyn_cast<PointerType>(T))
166+
else if (T->isPointerTy() && !T->isOpaquePointerTy())
166167
{
167-
return getContainedStructType(IGCLLVM::getNonOpaquePtrEltTy(PT), Tys);
168+
return getBuiltinType(IGCLLVM::getNonOpaquePtrEltTy(cast<PointerType>(T)), BuiltinTypes);
168169
}
169-
else if (auto AT = dyn_cast<ArrayType>(T))
170+
#if LLVM_VERSION_MAJOR >= 16
171+
else if (isa<TargetExtType>(T))
170172
{
171-
return getContainedStructType(AT->getElementType(), Tys);
173+
BuiltinTypes.insert(T);
172174
}
173-
}
174-
175-
static bool isImageType(llvm::Type *Ty)
176-
{
177-
if (auto *STy = dyn_cast<StructType>(Ty); STy && STy->isOpaque())
175+
#endif
176+
else if (auto AT = dyn_cast<ArrayType>(T))
178177
{
179-
auto typeName = STy->getName();
180-
llvm::SmallVector<llvm::StringRef, 3> buf;
181-
typeName.split(buf, ".");
182-
if (buf.size() < 2) return false;
183-
bool isOpenCLImage = buf[0].equals("opencl") && buf[1].startswith("image") && buf[1].endswith("_t");
184-
bool isSPIRVImage = buf[0].equals("spirv") && (buf[1].startswith("Image") || buf[1].startswith("SampledImage"));
185-
186-
if (isOpenCLImage || isSPIRVImage)
187-
return true;
178+
return getBuiltinType(AT->getElementType(), BuiltinTypes);
188179
}
189-
return false;
190180
}
191181

192182
// Check the existence of an image type.
193183
static bool containsImageType(llvm::Type *T)
194184
{
195-
// All (nested) struct types in T.
196-
SmallPtrSet<StructType *, 8> StructTys;
197-
getContainedStructType(T, StructTys);
185+
// Get the builtin type of T. This can be either TargetExtTy (LLVM 16+) or
186+
// "pointer to opaque struct" (can be nested) representing a builtin type.
187+
SmallPtrSet<Type *, 8> BuiltinTypes;
188+
getBuiltinType(T, BuiltinTypes);
198189

199-
return llvm::any_of(StructTys, [](StructType *STy) { return isImageType(STy); });
190+
return llvm::any_of(BuiltinTypes,
191+
[](Type *Ty) { return isImageBuiltinType(Ty); });
200192
}
201193

202194
static bool isOptNoneBuiltin(StringRef name)
@@ -316,13 +308,11 @@ static void addAlwaysInlineForImageBuiltinUserFunctions(Module &M)
316308
{
317309
continue;
318310
}
311+
319312
// Check if return type is image.
320-
if (auto *PTy = dyn_cast<PointerType>(F.getReturnType()))
313+
if (isImageBuiltinType(F.getReturnType()))
321314
{
322-
if (isImageType(IGCLLVM::getNonOpaquePtrEltTy(PTy)))
323-
{
324-
SampledImageFunctions.push_back(&F);
325-
}
315+
SampledImageFunctions.push_back(&F);
326316
}
327317
}
328318

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
;=========================== begin_copyright_notice ============================
2+
;
3+
; Copyright (C) 2023 Intel Corporation
4+
;
5+
; This software and the related documents are Intel copyrighted materials,
6+
; and your use of them is governed by the express license under which they were
7+
; provided to you ("License"). Unless the License provides otherwise,
8+
; you may not use, modify, copy, publish, distribute, disclose or transmit this
9+
; software or the related documents without Intel's prior written permission.
10+
;
11+
; This software and the related documents are provided as is, with no express or
12+
; implied warranties, other than those that are expressly stated in the License.
13+
;
14+
;============================ end_copyright_notice =============================
15+
16+
; Check alwaysinline attribute is added to following functions:
17+
; 1. function that is returning an image type and its' users, e.g. _ZN4sycl3_V13ext6oneapi12experimental6detail31convert_handle_to_sampled_imageI14ocl_image3d_roNS3_17spirv_handle_typeEEEDaT0_
18+
19+
; RUN: igc_opt --typed-pointers -igc-process-func-attributes -S %s -o - | FileCheck %s
20+
21+
; CHECK: define internal spir_func void @_ZZZ4mainENKUlRN4sycl3_V17handlerEE_clES2_ENKUlNS0_7nd_itemILi3EEEE_clES5_() [[MD0:#[0-9]+]]
22+
; CHECK: define internal spir_func void @_ZN4sycl3_V13ext6oneapi12experimental10read_imageINS0_3vecIfLi4EEES6_S6_EET_RKNS3_20sampled_image_handleERKT1_({{.*}}) [[MD0]]
23+
; CHECK: define internal spir_func {{.*}} @_ZN4sycl3_V13ext6oneapi12experimental6detail31convert_handle_to_sampled_imageI14ocl_image3d_roNS3_17spirv_handle_typeEEEDaT0_({{.*}}) [[MD1:#[0-9]+]]
24+
; CHECK: define internal spir_func void @_ZL19__invoke__ImageReadIN4sycl3_V13vecIfLi4EEE32__spirv_SampledImage__image3d_roS3_ET_T0_T1_({{.*}}) [[MD1]]
25+
; CHECK: define internal spir_func {{.*}} @_Z25__spirv_ImageRead_Rfloat4PU3AS140__spirv_SampledImage__void_2_0_0_0_0_0_0Dv4_f({{.*}}) [[MD2:#[0-9]+]]
26+
; CHECK: attributes [[MD0]] = {{.*}} noinline
27+
; CHECK: attributes [[MD1]] = {{.*}} alwaysinline
28+
; CHECK: attributes [[MD2]] = {{.*}} alwaysinline
29+
30+
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024-n8:16:32"
31+
target triple = "spir64-unknown-unknown"
32+
33+
%"class.sycl::_V1::vec" = type { <4 x float> }
34+
%"struct.sycl::_V1::ext::oneapi::experimental::sampled_image_handle" = type { %"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type" }
35+
%"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type" = type { i64, i64 }
36+
%spirv.SampledImage._void_2_0_0_0_0_0_0 = type opaque
37+
%spirv.Image._void_2_0_0_0_0_0_0 = type opaque
38+
%spirv.Sampler = type opaque
39+
40+
; Function Attrs: noinline nounwind optnone
41+
define internal spir_func void @_ZZZ4mainENKUlRN4sycl3_V17handlerEE_clES2_ENKUlNS0_7nd_itemILi3EEEE_clES5_() #0 {
42+
entry:
43+
call spir_func void @_ZN4sycl3_V13ext6oneapi12experimental10read_imageINS0_3vecIfLi4EEES6_S6_EET_RKNS3_20sampled_image_handleERKT1_(%"class.sycl::_V1::vec" addrspace(4)* noalias align 16 null, %"struct.sycl::_V1::ext::oneapi::experimental::sampled_image_handle" addrspace(4)* align 8 null, %"class.sycl::_V1::vec" addrspace(4)* align 16 null)
44+
ret void
45+
}
46+
47+
; Function Attrs: noinline nounwind optnone
48+
define weak_odr spir_func void @_ZN4sycl3_V13ext6oneapi12experimental10read_imageINS0_3vecIfLi4EEES6_S6_EET_RKNS3_20sampled_image_handleERKT1_(%"class.sycl::_V1::vec" addrspace(4)* noalias align 16 %agg.result, %"struct.sycl::_V1::ext::oneapi::experimental::sampled_image_handle" addrspace(4)* align 8 dereferenceable(16) %imageHandle, %"class.sycl::_V1::vec" addrspace(4)* align 16 dereferenceable(16) %coords) #0 {
49+
entry:
50+
%call = call spir_func %spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)* @_ZN4sycl3_V13ext6oneapi12experimental6detail31convert_handle_to_sampled_imageI14ocl_image3d_roNS3_17spirv_handle_typeEEEDaT0_(%"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type"* byval(%"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type") align 8 null) #0
51+
call spir_func void @_ZL19__invoke__ImageReadIN4sycl3_V13vecIfLi4EEE32__spirv_SampledImage__image3d_roS3_ET_T0_T1_(%"class.sycl::_V1::vec" addrspace(4)* noalias align 16 %agg.result, %spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)* %call, %"class.sycl::_V1::vec"* byval(%"class.sycl::_V1::vec") align 16 null) #0
52+
ret void
53+
}
54+
55+
; Function Attrs: noinline nounwind optnone
56+
define linkonce_odr spir_func %spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)* @_ZN4sycl3_V13ext6oneapi12experimental6detail31convert_handle_to_sampled_imageI14ocl_image3d_roNS3_17spirv_handle_typeEEEDaT0_(%"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type"* byval(%"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type") align 8 %raw_handle) #0 {
57+
entry:
58+
%retval = alloca %spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)*, align 8
59+
%retval.ascast = addrspacecast %spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)** %retval to %spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)* addrspace(4)*
60+
%raw_handle.ascast = addrspacecast %"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type"* %raw_handle to %"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type" addrspace(4)*
61+
%image = getelementptr inbounds %"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type", %"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type" addrspace(4)* %raw_handle.ascast, i32 0, i32 0
62+
%0 = load i64, i64 addrspace(4)* %image, align 8
63+
%call = call spir_func %spirv.Image._void_2_0_0_0_0_0_0 addrspace(1)* @_Z76__spirv_ConvertHandleToImageINTEL_RPU3AS133__spirv_Image__void_2_0_0_0_0_0_0m(i64 %0)
64+
%sampler = getelementptr inbounds %"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type", %"struct.sycl::_V1::ext::oneapi::experimental::spirv_handle_type" addrspace(4)* %raw_handle.ascast, i32 0, i32 1
65+
%1 = load i64, i64 addrspace(4)* %sampler, align 8
66+
%call1 = call spir_func %spirv.Sampler addrspace(2)* @_Z35__spirv_ConvertHandleToSamplerINTELm(i64 %1)
67+
%call2 = call spir_func %spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)* @_Z20__spirv_SampledImagePU3AS133__spirv_Image__void_2_0_0_0_0_0_0PU3AS215__spirv_Sampler(%spirv.Image._void_2_0_0_0_0_0_0 addrspace(1)* %call, %spirv.Sampler addrspace(2)* %call1)
68+
ret %spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)* %call2
69+
}
70+
71+
; Function Attrs: noinline nounwind optnone
72+
define hidden spir_func void @_ZL19__invoke__ImageReadIN4sycl3_V13vecIfLi4EEE32__spirv_SampledImage__image3d_roS3_ET_T0_T1_(%"class.sycl::_V1::vec" addrspace(4)* noalias align 16 %agg.result, %spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)* %Img, %"class.sycl::_V1::vec"* byval(%"class.sycl::_V1::vec") align 16 %Coords) #0 {
73+
entry:
74+
%call1 = call spir_func <4 x float> @_Z25__spirv_ImageRead_Rfloat4PU3AS140__spirv_SampledImage__void_2_0_0_0_0_0_0Dv4_f(%spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)* %Img, <4 x float> zeroinitializer)
75+
ret void
76+
}
77+
78+
; Function Attrs: convergent
79+
define dso_local spir_func <4 x float> @_Z25__spirv_ImageRead_Rfloat4PU3AS140__spirv_SampledImage__void_2_0_0_0_0_0_0Dv4_f(%spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)* %Image, <4 x float> %Coordinate) #1 {
80+
entry:
81+
%0 = bitcast %spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)* %Image to i8 addrspace(1)*
82+
%call.i.i = tail call spir_func i64 @__builtin_IB_get_image(i8 addrspace(1)* %0)
83+
%call1.i.i = tail call spir_func i64 @__builtin_IB_get_sampler(i8 addrspace(1)* %0)
84+
%conv2.i.i = trunc i64 %call1.i.i to i32
85+
%call3.i.i = tail call spir_func i32 @__builtin_IB_get_snap_wa_reqd(i32 %conv2.i.i)
86+
%call19.i.i = tail call spir_func <4 x float> @__builtin_IB_OCL_3d_sample_l(i32 0, i32 %conv2.i.i, <4 x float> zeroinitializer, float 0.000000e+00)
87+
ret <4 x float> %call19.i.i
88+
}
89+
90+
declare spir_func %spirv.SampledImage._void_2_0_0_0_0_0_0 addrspace(1)* @_Z20__spirv_SampledImagePU3AS133__spirv_Image__void_2_0_0_0_0_0_0PU3AS215__spirv_Sampler(%spirv.Image._void_2_0_0_0_0_0_0 addrspace(1)*, %spirv.Sampler addrspace(2)*)
91+
92+
declare spir_func %spirv.Sampler addrspace(2)* @_Z35__spirv_ConvertHandleToSamplerINTELm(i64)
93+
94+
declare spir_func %spirv.Image._void_2_0_0_0_0_0_0 addrspace(1)* @_Z76__spirv_ConvertHandleToImageINTEL_RPU3AS133__spirv_Image__void_2_0_0_0_0_0_0m(i64)
95+
96+
declare spir_func i64 @__builtin_IB_get_image(i8 addrspace(1)*)
97+
98+
declare spir_func i64 @__builtin_IB_get_sampler(i8 addrspace(1)*)
99+
100+
declare spir_func i32 @__builtin_IB_get_snap_wa_reqd(i32)
101+
102+
declare spir_func <4 x float> @__builtin_IB_OCL_3d_sample_l(i32, i32, <4 x float>, float)
103+
104+
attributes #0 = { noinline nounwind optnone }
105+
attributes #1 = { convergent }
106+
107+
!spirv.MemoryModel = !{!0}
108+
!spirv.Source = !{!1}
109+
!spirv.Generator = !{!2}
110+
!igc.functions = !{!3}
111+
!IGCMetadata = !{!4}
112+
!opencl.ocl.version = !{!5}
113+
!opencl.spir.version = !{!5}
114+
115+
!0 = !{i32 2, i32 2}
116+
!1 = !{i32 4, i32 100000}
117+
!2 = !{i16 6, i16 14}
118+
!3 = distinct !{null, null}
119+
!4 = !{!"ModuleMD"}
120+
!5 = !{i32 2, i32 0}

0 commit comments

Comments
 (0)