Skip to content

Commit

Permalink
[ESIMD] Fix the ambiguous call error for a corner case of gather() (#…
Browse files Browse the repository at this point in the history
…12506)

Some corner cases with interger scalar operands of gather() may cause
ambiguous call error. Examples of such calls:
  // 0 may be treated as vector `simd_mask` or scalar 'global_offset'
  auto res1 = gather<T, N>(acc, offsets_simd, 0);
  // This case is more tricky, but also can confuse C++ FE.
  auto res2 = gather<T, N>(acc, offsets_simd, 0, mask);

Signed-off-by: Klochkov, Vyacheslav N <vyacheslav.n.klochkov@intel.com>
  • Loading branch information
v-klochkov authored Jan 26, 2024
1 parent 8d0fa98 commit c1c9184
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 4 deletions.
16 changes: 13 additions & 3 deletions sycl/include/sycl/ext/intel/esimd/memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2934,15 +2934,21 @@ gather(AccessorT acc, simd<OffsetT, N / VS> byte_offsets,
/// to 1. This variant is added for convenience and let user omit the template
/// arguments and call the function as
/// 'gather(acc, byte_offsets, mask, pass_thru);'.
// Dev note: the mask type was turned into template parameter `MaskT` to
// avoid the conflicts of this prototype with the old gather() function
// accepting a 'global_offset' parameter and avoid 'ambiguous call' errors
// for calls like this: gather(acc, byte_offsets_simd, 0, mask);
template <typename T, int N, typename AccessorT, typename OffsetT,
typename MaskT,
typename PropertyListT =
ext::oneapi::experimental::detail::empty_properties_t>
__ESIMD_API std::enable_if_t<
(detail::is_device_accessor_with_v<AccessorT,
detail::accessor_mode_cap::can_read> &&
std::is_same_v<MaskT, simd_mask<N>> &&
ext::oneapi::experimental::is_property_list_v<PropertyListT>),
simd<T, N>>
gather(AccessorT acc, simd<OffsetT, N> byte_offsets, simd_mask<N> mask,
gather(AccessorT acc, simd<OffsetT, N> byte_offsets, MaskT mask,
simd<T, N> pass_thru, PropertyListT props = {}) {
return gather<T, N, 1>(acc, byte_offsets, mask, pass_thru, props);
}
Expand All @@ -2954,15 +2960,19 @@ gather(AccessorT acc, simd<OffsetT, N> byte_offsets, simd_mask<N> mask,
/// This function is identical to (acc-ga-2) except that vector size is fixed
/// to 1. This variant is added for convenience and let user omit the template
/// arguments and call the function as 'gather(acc, byte_offsets, mask);'.
// Dev note: the mask type was turned into template parameter `MaskT` to
// avoid the conflicts of this prototype with the old gather() function
// accepting a 'global_offset' parameter and avoid 'ambiguous call' errors
// for calls like this: gather(acc, byte_offsets_simd, 0);
template <typename T, int N, typename AccessorT, typename OffsetT,
typename MaskT,
typename PropertyListT =
ext::oneapi::experimental::detail::empty_properties_t>
__ESIMD_API std::enable_if_t<
(detail::is_device_accessor_with_v<AccessorT,
detail::accessor_mode_cap::can_read> &&
ext::oneapi::experimental::is_property_list_v<PropertyListT> &&
std::is_same_v<MaskT, simd_mask<N>>),
std::is_same_v<MaskT, simd_mask<N>> &&
ext::oneapi::experimental::is_property_list_v<PropertyListT>),
simd<T, N>>
gather(AccessorT acc, simd<OffsetT, N> byte_offsets, MaskT mask,
PropertyListT props = {}) {
Expand Down
14 changes: 13 additions & 1 deletion sycl/test/esimd/intrins_trans.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,14 +304,26 @@ SYCL_ESIMD_FUNCTION SYCL_EXTERNAL simd<float, 16> foo() {
// CHECK-STATEFUL: call void @llvm.genx.scatter.scaled.v8i1.v8i32.v8i32(<8 x i1> %{{[0-9a-zA-Z_.]+}}, i32 2, i16 0, i32 %[[SI4]], i32 %{{[0-9a-zA-Z_.]+}}, <8 x i32> %{{[0-9a-zA-Z_.]+}}, <8 x i32> %{{[0-9a-zA-Z_.]+}})
// CHECK-STATELESS: call void @llvm.genx.svm.scatter.v8i1.v8i64.v8i32(<8 x i1> %{{[0-9a-zA-Z_.]+}}, i32 0, <8 x i64> %{{[0-9a-zA-Z_.]+}}, <8 x i32> %{{[0-9a-zA-Z_.]+}})

// 1-byte element gather
// 1-byte element gather: same code with and without mask
simd<unsigned char, 8> v1 = gather<unsigned char, 8>(acc, offsets, 100);
// CHECK-STATEFUL: %[[SI5_VAL:[0-9a-zA-Z_.]+]] = call spir_func noundef i32 @_Z21__spirv_ConvertPtrToU{{.*}}(ptr addrspace(1) noundef %{{[0-9a-zA-Z_.]+}})
// CHECK-STATEFUL: store i32 %[[SI5_VAL]], ptr addrspace(4) %[[SI5_ADDR:[0-9a-zA-Z_.]+]]
// CHECK-STATEFUL: %[[SI5:[0-9a-zA-Z_.]+]] = load i32, ptr addrspace(4) %[[SI5_ADDR]]
// CHECK-STATEFUL: call <8 x i32> @llvm.genx.gather.masked.scaled2.v8i32.v8i32.v8i1(i32 0, i16 0, i32 %[[SI5]], i32 %{{[0-9a-zA-Z_.]+}}, <8 x i32> %{{[0-9a-zA-Z_.]+}}, <8 x i1> %{{[0-9a-zA-Z_.]+}})
// CHECK-STATELESS: call <32 x i8> @llvm.genx.svm.gather.v32i8.v8i1.v8i64(<8 x i1> %{{[0-9a-zA-Z_.]+}}, i32 0, <8 x i64> %{{[0-9a-zA-Z_.]+}}, <32 x i8> undef)

// 1-byte element gather using the mask
v1 = gather<unsigned char, 8>(acc, offsets, 100, pred);
// CHECK-STATEFUL: call <8 x i32> @llvm.genx.gather.masked.scaled2.v8i32.v8i32.v8i1(i32 0, i16 0, i32 {{[^)]+}}, i32 {{[^)]+}}, <8 x i32> {{[^)]+}}, <8 x i1> {{[^)]+}})
// CHECK-STATELESS: call <32 x i8> @llvm.genx.svm.gather.v32i8.v8i1.v8i64(<8 x i1> {{[^)]+}}, i32 0, <8 x i64> {{[^)]+}}, <32 x i8> undef)

// 1-byte element gather using the mask - the mask is signed, which may
// expose different issues/conflicts in gather API.
simd<int32_t, 8> ioffsets = 1;
v1 = gather<unsigned char, 8>(acc, ioffsets, 0, pred);
// CHECK-STATEFUL: call <8 x i32> @llvm.genx.gather.masked.scaled2.v8i32.v8i32.v8i1(i32 0, i16 0, i32 {{[^)]+}}, i32 {{[^)]+}}, <8 x i32> {{[^)]+}}, <8 x i1> {{[^)]+}})
// CHECK-STATELESS: call <32 x i8> @llvm.genx.svm.gather.v32i8.v8i1.v8i64(<8 x i1> {{[^)]+}}, i32 0, <8 x i64> {{[^)]+}}, <32 x i8> undef)

// 1-byte element scatter
scatter<unsigned char, 8>(acc, offsets, v1, 100, pred);
// CHECK-STATEFUL: %[[SI6_VAL:[0-9a-zA-Z_.]+]] = call spir_func noundef i32 @_Z21__spirv_ConvertPtrToU{{.*}}(ptr addrspace(1) noundef %{{[0-9a-zA-Z_.]+}})
Expand Down

0 comments on commit c1c9184

Please sign in to comment.