Skip to content

Commit c6e9bfa

Browse files
wenju-heigcbot
authored andcommitted
Support implicit args for bindless OpenCL sampler
Similar as in bindful mode, add implicit args for bindless sampler: %smpAddress for __builtin_IB_get_address_mode %smpSnapWA for __builtin_IB_get_snap_wa_reqd %smpNormalized for __builtin_IB_is_normalized_coords They are used in OpenCL read_image{f|i|ui} builtin implementations.
1 parent 053f27d commit c6e9bfa

26 files changed

+472
-219
lines changed

IGC/Compiler/Optimizer/OpenCLPasses/ImageFuncs/ImageFuncResolution.cpp

Lines changed: 63 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -205,141 +205,89 @@ Value* ImageFuncResolution::getImageNumSamples(CallInst& CI)
205205
return arg;
206206
}
207207

208-
Value* ImageFuncResolution::getSamplerAddressMode(CallInst& CI)
208+
template<ImplicitArg::ArgType ArgTy>
209+
Value* ImageFuncResolution::getSamplerProperty(CallInst& CI)
209210
{
210211
MetaDataUtils* pMdUtils = getAnalysis<MetaDataUtilsWrapper>().getMetaDataUtils();
211212
ModuleMetaData* modMD = getAnalysis<MetaDataUtilsWrapper>().getModuleMetaData();
212-
213-
Value* sampler = ValueTracker::track(&CI, 0, pMdUtils, modMD);
214-
if (sampler == nullptr)
215-
{
216-
// TODO: For now disable WA if unable to trace sampler argument.
217-
// Will need to rework WA to add support for indirect sampler case.
218-
return ConstantInt::get(CI.getType(), 0);
219-
}
220-
if (isa<Argument>(sampler))
221-
{
222-
Argument* arg = getImplicitImageArg(CI, ImplicitArg::SAMPLER_ADDRESS);
223-
return arg;
224-
}
225-
else
213+
if (Value* sampler = ValueTracker::track(&CI, 0, pMdUtils, modMD))
226214
{
227-
llvm::Function* pFunc = CI.getParent()->getParent();
228-
229-
IGC_ASSERT_MESSAGE(isa<ConstantInt>(sampler), "Sampler must be a constant integer");
230-
InlineSamplerState samplerStateAddressMode{ cast<ConstantInt>(sampler)->getZExtValue() };
231-
uint64_t samplerVal = 0;
232-
uint samplerValue = int_cast<unsigned int>(cast<ConstantInt>(sampler)->getZExtValue());
233-
if (modMD->FuncMD.find(pFunc) != modMD->FuncMD.end())
215+
if (isa<Argument>(sampler))
234216
{
235-
FunctionMetaData funcMD = modMD->FuncMD[pFunc];
236-
ResourceAllocMD resAllocMD = funcMD.resAllocMD;
237-
for (auto i = resAllocMD.inlineSamplersMD.begin(), e = resAllocMD.inlineSamplersMD.end(); i != e; i++)
217+
if (m_implicitArgs.isImplicitArgExist(ArgTy))
238218
{
239-
IGC::InlineSamplersMD inlineSamplerMD = *i;
240-
if (samplerValue == inlineSamplerMD.m_Value)
241-
{
242-
InlineSamplerState samplerState{ static_cast<uint64_t>(samplerValue) };
243-
samplerVal = inlineSamplerMD.addressMode;
244-
}
219+
Argument* arg = getImplicitImageArg(CI, ArgTy);
220+
return arg;
245221
}
246222
}
247-
return ConstantInt::get(CI.getType(), samplerVal);
248-
}
249-
}
250-
251-
Value* ImageFuncResolution::getSamplerNormalizedCoords(CallInst& CI)
252-
{
253-
MetaDataUtils* pMdUtils = getAnalysis<MetaDataUtilsWrapper>().getMetaDataUtils();
254-
ModuleMetaData* modMD = getAnalysis<MetaDataUtilsWrapper>().getModuleMetaData();
255-
Value* sampler = ValueTracker::track(&CI, 0, pMdUtils, modMD);
256-
if (sampler == nullptr)
257-
{
258-
// TODO: For now disable WA if unable to trace sampler argument.
259-
// Will need to rework WA to add support for indirect sampler case.
260-
return ConstantInt::get(CI.getType(), 0);
261-
}
262-
else if (isa<Argument>(sampler))
263-
{
264-
Argument* arg = getImplicitImageArg(CI, ImplicitArg::SAMPLER_NORMALIZED);
265-
return arg;
266-
}
267-
else
268-
{
269-
llvm::Function* pFunc = CI.getParent()->getParent();
270-
IGC_ASSERT_MESSAGE(isa<ConstantInt>(sampler), "Sampler must be a constant integer");
271-
272-
uint64_t samplerVal = 0;
273-
uint samplerValue = int_cast<unsigned int>(cast<ConstantInt>(sampler)->getZExtValue());
274-
275-
if (modMD->FuncMD.find(pFunc) != modMD->FuncMD.end())
223+
else
276224
{
277-
FunctionMetaData funcMD = modMD->FuncMD[pFunc];
278-
ResourceAllocMD resAllocMD = funcMD.resAllocMD;
279-
for (auto i = resAllocMD.inlineSamplersMD.begin(), e = resAllocMD.inlineSamplersMD.end(); i != e; ++i)
225+
llvm::Function* pFunc = CI.getFunction();
226+
227+
IGC_ASSERT_MESSAGE(isa<ConstantInt>(sampler), "Sampler must be a constant integer");
228+
uint64_t samplerVal = 0;
229+
if (modMD->FuncMD.find(pFunc) != modMD->FuncMD.end())
280230
{
281-
IGC::InlineSamplersMD inlineSamplerMD = *i;
282-
if (samplerValue == inlineSamplerMD.m_Value)
231+
FunctionMetaData funcMD = modMD->FuncMD[pFunc];
232+
ResourceAllocMD resAllocMD = funcMD.resAllocMD;
233+
uint samplerValue = int_cast<unsigned int>(cast<ConstantInt>(sampler)->getZExtValue());
234+
for (auto i = resAllocMD.inlineSamplersMD.begin(), e = resAllocMD.inlineSamplersMD.end(); i != e; i++)
283235
{
284-
InlineSamplerState samplerState{ static_cast<uint64_t>(samplerValue) };
285-
samplerVal = inlineSamplerMD.NormalizedCoords;
236+
IGC::InlineSamplersMD inlineSamplerMD = *i;
237+
if (samplerValue == inlineSamplerMD.m_Value)
238+
{
239+
InlineSamplerState samplerState{ static_cast<uint64_t>(samplerValue) };
240+
if constexpr (ArgTy == ImplicitArg::SAMPLER_ADDRESS)
241+
{
242+
samplerVal = inlineSamplerMD.addressMode;
243+
}
244+
else if constexpr (ArgTy == ImplicitArg::SAMPLER_NORMALIZED)
245+
{
246+
samplerVal = inlineSamplerMD.NormalizedCoords;
247+
}
248+
else if constexpr (ArgTy == ImplicitArg::SAMPLER_SNAP_WA)
249+
{
250+
bool anyAddressModeClamp =
251+
inlineSamplerMD.TCXAddressMode == iOpenCL::SAMPLER_TEXTURE_ADDRESS_MODE_BORDER ||
252+
inlineSamplerMD.TCYAddressMode == iOpenCL::SAMPLER_TEXTURE_ADDRESS_MODE_BORDER ||
253+
inlineSamplerMD.TCZAddressMode == iOpenCL::SAMPLER_TEXTURE_ADDRESS_MODE_BORDER;
254+
bool anyMapFilterModeNearest =
255+
inlineSamplerMD.MagFilterType == iOpenCL::SAMPLER_MAPFILTER_POINT ||
256+
inlineSamplerMD.MinFilterType == iOpenCL::SAMPLER_MAPFILTER_POINT;
257+
bool snapWARequired = anyAddressModeClamp &&
258+
anyMapFilterModeNearest &&
259+
!inlineSamplerMD.NormalizedCoords;
260+
samplerVal = snapWARequired ? -1 : 0;
261+
}
262+
else
263+
{
264+
llvm_unreachable("unexpected sampler property");
265+
}
266+
}
286267
}
287268
}
269+
return ConstantInt::get(CI.getType(), samplerVal);
288270
}
289-
return ConstantInt::get(CI.getType(), samplerVal);
290271
}
272+
273+
// TODO: For now disable WA if unable to trace sampler argument.
274+
// Will need to rework WA to add support for indirect sampler case.
275+
return ConstantInt::get(CI.getType(), 0);
291276
}
292277

293-
Value* ImageFuncResolution::getSamplerSnapWARequired(CallInst& CI)
278+
Value* ImageFuncResolution::getSamplerAddressMode(CallInst& CI)
294279
{
295-
MetaDataUtils* pMdUtils = getAnalysis<MetaDataUtilsWrapper>().getMetaDataUtils();
296-
ModuleMetaData* modMD = getAnalysis<MetaDataUtilsWrapper>().getModuleMetaData();
297-
Value* sampler = ValueTracker::track(&CI, 0, pMdUtils, modMD);
298-
if (sampler == nullptr)
299-
{
300-
// TODO: For now disable WA if unable to trace sampler argument.
301-
// Will need to rework WA to add support for indirect sampler case.
302-
return ConstantInt::get(CI.getType(), 0);
303-
}
304-
else if (isa<Argument>(sampler))
305-
{
306-
Argument* arg = getImplicitImageArg(CI, ImplicitArg::SAMPLER_SNAP_WA);
307-
return arg;
308-
}
309-
else
310-
{
311-
IGC_ASSERT_MESSAGE(isa<ConstantInt>(sampler), "Sampler must be a constant integer");
312-
313-
llvm::Function* pFunc = CI.getParent()->getParent();
280+
return getSamplerProperty<ImplicitArg::SAMPLER_ADDRESS>(CI);
281+
}
314282

315-
bool snapWARequired = false;
316-
uint samplerVal = int_cast<unsigned int>(cast<ConstantInt>(sampler)->getZExtValue());
283+
Value* ImageFuncResolution::getSamplerNormalizedCoords(CallInst& CI)
284+
{
285+
return getSamplerProperty<ImplicitArg::SAMPLER_NORMALIZED>(CI);
286+
}
317287

318-
if (modMD->FuncMD.find(pFunc) != modMD->FuncMD.end())
319-
{
320-
FunctionMetaData funcMD = modMD->FuncMD[pFunc];
321-
ResourceAllocMD resAllocMD = funcMD.resAllocMD;
322-
for (auto i = resAllocMD.inlineSamplersMD.begin(), e = resAllocMD.inlineSamplersMD.end(); i != e; ++i)
323-
{
324-
InlineSamplersMD inlineSamplerMD = *i;
325-
if (samplerVal == inlineSamplerMD.m_Value)
326-
{
327-
InlineSamplerState samplerState{ static_cast<uint64_t>(samplerVal) };
328-
bool anyAddressModeClamp =
329-
inlineSamplerMD.TCXAddressMode == iOpenCL::SAMPLER_TEXTURE_ADDRESS_MODE_BORDER ||
330-
inlineSamplerMD.TCYAddressMode == iOpenCL::SAMPLER_TEXTURE_ADDRESS_MODE_BORDER ||
331-
inlineSamplerMD.TCZAddressMode == iOpenCL::SAMPLER_TEXTURE_ADDRESS_MODE_BORDER;
332-
bool anyMapFilterModeNearest =
333-
inlineSamplerMD.MagFilterType == iOpenCL::SAMPLER_MAPFILTER_POINT ||
334-
inlineSamplerMD.MinFilterType == iOpenCL::SAMPLER_MAPFILTER_POINT;
335-
snapWARequired = anyAddressModeClamp &&
336-
anyMapFilterModeNearest &&
337-
!inlineSamplerMD.NormalizedCoords;
338-
}
339-
}
340-
}
341-
return ConstantInt::get(CI.getType(), snapWARequired ? -1 : 0);
342-
}
288+
Value* ImageFuncResolution::getSamplerSnapWARequired(CallInst& CI)
289+
{
290+
return getSamplerProperty<ImplicitArg::SAMPLER_SNAP_WA>(CI);
343291
}
344292

345293
Argument* ImageFuncResolution::getImplicitImageArg(CallInst& CI, ImplicitArg::ArgType argType) {

IGC/Compiler/Optimizer/OpenCLPasses/ImageFuncs/ImageFuncResolution.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ namespace IGC
107107
/// @return A value representing the image number of samples.
108108
llvm::Value* getImageNumSamples(llvm::CallInst& CI);
109109

110+
/// @brief Resolves sampler pseudo-builtin, e.g. get_sampler_address_mode.
111+
/// @param CI The call instruction.
112+
/// @return A value representing the sampler property, which may either be
113+
/// a ConstantInt or an Argument.
114+
template<ImplicitArg::ArgType ArgTy>
115+
llvm::Value* getSamplerProperty(llvm::CallInst& CI);
116+
110117
/// @brief Resolves the pseudo-builtin get_sampler_address_mode(sampler_t).
111118
/// Adds the approtiate sequence of code before the given call isntruction
112119
/// @param CI The call instruction.

IGC/Compiler/Optimizer/OpenCLPasses/ImageFuncs/ImageFuncsAnalysis.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,19 +177,33 @@ void ImageFuncsAnalysis::visitCallInst(CallInst& CI)
177177
// don't require extra kernel parameters.
178178
Value* callArg = ValueTracker::track(&CI, 0, getAnalysis<MetaDataUtilsWrapper>().getMetaDataUtils(), getAnalysis<MetaDataUtilsWrapper>().getModuleMetaData());
179179

180+
// Return true if v is argument and argument type is %spirv.Sampler.
181+
// Return false when sampler track back to a SYCL bindless image argment,
182+
// since in this case we don't need implicit args.
183+
auto isSamplerArgument = [](Argument *arg) {
184+
// TODO check v has sampler target extension type when switching to opaque pointer.
185+
if (auto *pty = dyn_cast<PointerType>(arg->getType()))
186+
{
187+
if (auto *sty = dyn_cast<StructType>(IGCLLVM::getNonOpaquePtrEltTy(pty)))
188+
{
189+
return sty->isOpaque();
190+
}
191+
}
192+
return false;
193+
};
194+
180195
// TODO: For now assume that we may not trace a sampler/texture for indirect access.
181196
// In this case we provide no WA support for indirect case and all WAs will return 0.
182197
// These WAs need to be reworked to support indirect case in the future.
183198
if (callArg)
184199
{
185-
if (Argument * arg = dyn_cast<Argument>(callArg))
200+
if (Argument * arg = dyn_cast<Argument>(callArg); arg && isSamplerArgument(arg))
186201
{
187202
imageFunc->insert(arg->getArgNo());
203+
return;
188204
}
189205
}
190-
else
191-
{
192-
// Only these args should be hit by the indirect case
193-
IGC_ASSERT(funcName == GET_SAMPLER_ADDRESS_MODE || funcName == GET_SAMPLER_NORMALIZED_COORDS || funcName == GET_SAMPLER_SNAP_WA_REQUIRED);
194-
}
206+
207+
// Only these args should be hit by the indirect case
208+
IGC_ASSERT(funcName == GET_SAMPLER_ADDRESS_MODE || funcName == GET_SAMPLER_NORMALIZED_COORDS || funcName == GET_SAMPLER_SNAP_WA_REQUIRED);
195209
}

IGC/Compiler/Optimizer/ValueTracker.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,12 @@ Value* ValueTracker::trackValue(Value* I)
498498
phiVisited.insert(std::make_pair(I, baseValue));
499499
return baseValue;
500500
}
501+
else if (auto *BO = dyn_cast<BinaryOperator>(baseValue))
502+
{
503+
Value *Op0 = BO->getOperand(0);
504+
Value *Op1 = BO->getOperand(1);
505+
baseValue = isa_and_nonnull<Constant>(Op0) ? Op1 : (isa_and_nonnull<Constant>(Op1) ? Op0 : nullptr);
506+
}
501507
else
502508
{
503509
baseValue = nullptr;

IGC/Compiler/tests/ImageFuncAnalysis/2_image_funcs.ll

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
;=========================== begin_copyright_notice ============================
22
;
3-
; Copyright (C) 2017-2021 Intel Corporation
3+
; Copyright (C) 2017-2024 Intel Corporation
44
;
55
; SPDX-License-Identifier: MIT
66
;
@@ -9,20 +9,22 @@
99
; RUN: igc_opt -igc-image-func-analysis -S %s -o %t.ll
1010
; RUN: FileCheck %s --input-file=%t.ll
1111

12-
%opencl.image2d_t = type opaque
12+
%spirv.Image._void_1_0_0_0_0_0_0 = type opaque
1313

14-
declare i32 @__builtin_IB_get_image_width(i32 %img)
15-
declare i32 @__builtin_IB_get_image_height(i32 %img)
14+
declare i32 @__builtin_IB_get_image_width(i32)
15+
declare i32 @__builtin_IB_get_image_height(i32)
1616

17-
define i32 @foo(i32 %img) nounwind {
18-
%id1 = call i32 @__builtin_IB_get_image_width(i32 %img)
19-
%id2 = call i32 @__builtin_IB_get_image_height(i32 %img)
17+
define i32 @foo(%spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)* %img) nounwind {
18+
%1 = ptrtoint %spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)* %img to i64
19+
%2 = trunc i64 %1 to i32
20+
%id1 = call i32 @__builtin_IB_get_image_width(i32 %2)
21+
%id2 = call i32 @__builtin_IB_get_image_height(i32 %2)
2022
%res = add i32 %id1, %id2
2123
ret i32 %res
2224
}
2325

2426
!igc.functions = !{!0}
25-
!0 = !{i32 (i32)* @foo, !1}
27+
!0 = !{i32 (%spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)*)* @foo, !1}
2628
!1 = !{!2, !3}
2729
!2 = !{!"function_type", i32 0}
2830
!3 = !{!"implicit_arg_desc"}

IGC/Compiler/tests/ImageFuncAnalysis/2_image_funcs_2_images.ll

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
;=========================== begin_copyright_notice ============================
22
;
3-
; Copyright (C) 2017-2021 Intel Corporation
3+
; Copyright (C) 2017-2024 Intel Corporation
44
;
55
; SPDX-License-Identifier: MIT
66
;
@@ -9,20 +9,24 @@
99
; RUN: igc_opt -igc-image-func-analysis -S %s -o %t.ll
1010
; RUN: FileCheck %s --input-file=%t.ll
1111

12-
%opencl.image2d_t = type opaque
12+
%spirv.Image._void_1_0_0_0_0_0_0 = type opaque
1313

14-
declare i32 @__builtin_IB_get_image_height(i32 %img)
15-
declare i32 @__builtin_IB_get_image_width(i32 %img)
14+
declare i32 @__builtin_IB_get_image_height(i32)
15+
declare i32 @__builtin_IB_get_image_width(i32)
1616

17-
define i32 @foo(i32 %img1, i32 %img2) nounwind {
18-
%id1 = call i32 @__builtin_IB_get_image_width(i32 %img1)
19-
%id2 = call i32 @__builtin_IB_get_image_height(i32 %img2)
17+
define i32 @foo(%spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)* %img1, %spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)* %img2) nounwind {
18+
%1 = ptrtoint %spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)* %img1 to i64
19+
%2 = trunc i64 %1 to i32
20+
%3 = ptrtoint %spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)* %img2 to i64
21+
%4 = trunc i64 %3 to i32
22+
%id1 = call i32 @__builtin_IB_get_image_width(i32 %2)
23+
%id2 = call i32 @__builtin_IB_get_image_height(i32 %4)
2024
%res = add i32 %id1, %id2
2125
ret i32 %res
2226
}
2327

2428
!igc.functions = !{!0}
25-
!0 = !{i32 (i32, i32)* @foo, !1}
29+
!0 = !{i32 (%spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)*, %spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)*)* @foo, !1}
2630
!1 = !{!2, !3}
2731
!2 = !{!"function_type", i32 0}
2832
!3 = !{!"implicit_arg_desc"}

IGC/Compiler/tests/ImageFuncAnalysis/2_images.ll

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
;=========================== begin_copyright_notice ============================
22
;
3-
; Copyright (C) 2017-2021 Intel Corporation
3+
; Copyright (C) 2017-2024 Intel Corporation
44
;
55
; SPDX-License-Identifier: MIT
66
;
@@ -9,19 +9,23 @@
99
; RUN: igc_opt -igc-image-func-analysis -S %s -o %t.ll
1010
; RUN: FileCheck %s --input-file=%t.ll
1111

12-
%opencl.image2d_t = type opaque
12+
%spirv.Image._void_1_0_0_0_0_0_0 = type opaque
1313

14-
declare i32 @__builtin_IB_get_image_width(i32 %img)
14+
declare i32 @__builtin_IB_get_image_width(i32)
1515

16-
define i32 @foo(i32 %img1, i32 %img2) nounwind {
17-
%id1 = call i32 @__builtin_IB_get_image_width(i32 %img1)
18-
%id2 = call i32 @__builtin_IB_get_image_width(i32 %img2)
16+
define i32 @foo(%spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)* %img1, %spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)* %img2) nounwind {
17+
%1 = ptrtoint %spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)* %img1 to i64
18+
%2 = trunc i64 %1 to i32
19+
%3 = ptrtoint %spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)* %img2 to i64
20+
%4 = trunc i64 %3 to i32
21+
%id1 = call i32 @__builtin_IB_get_image_width(i32 %2)
22+
%id2 = call i32 @__builtin_IB_get_image_width(i32 %4)
1923
%res = add i32 %id1, %id2
2024
ret i32 %res
2125
}
2226

2327
!igc.functions = !{!0}
24-
!0 = !{i32 (i32, i32)* @foo, !1}
28+
!0 = !{i32 (%spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)*, %spirv.Image._void_1_0_0_0_0_0_0 addrspace(1)*)* @foo, !1}
2529
!1 = !{!2, !3}
2630
!2 = !{!"function_type", i32 0}
2731
!3 = !{!"implicit_arg_desc"}

0 commit comments

Comments
 (0)