From 9b4bf7c690300fa8a3b4e796ef5950d43df21a0d Mon Sep 17 00:00:00 2001 From: LU-JOHN Date: Wed, 22 May 2024 18:42:03 -0500 Subject: [PATCH] [SYCL][E2E] Ensure lowering of llvm.bitreverse for 2/4-bit scalars is functionally correct (#13359) Ensure that lowering of llvm.bitreverse.i2/i4 by llvm-spirv is functionally correct. --------- Signed-off-by: Lu, John --- .../sub_byte_bitreverse.cpp | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 sycl/test-e2e/LLVMIntrinsicLowering/sub_byte_bitreverse.cpp diff --git a/sycl/test-e2e/LLVMIntrinsicLowering/sub_byte_bitreverse.cpp b/sycl/test-e2e/LLVMIntrinsicLowering/sub_byte_bitreverse.cpp new file mode 100644 index 0000000000000..b576e5bd5db1b --- /dev/null +++ b/sycl/test-e2e/LLVMIntrinsicLowering/sub_byte_bitreverse.cpp @@ -0,0 +1,121 @@ +// Test that llvm.bitreverse is lowered correctly by llvm-spirv for 2/4-bit +// types. + +// UNSUPPORTED: hip || cuda + +// TODO: Remove XFAIL after fixing +// https://github.com/intel/intel-graphics-compiler/issues/330 +// XFAIL: gpu + +// Make dump directory. +// RUN: rm -rf %t.spvdir && mkdir %t.spvdir + +// Ensure that SPV_KHR_bit_instructions is disabled so that translator +// will lower llvm.bitreverse.* intrinsics instead of relying on SPIRV +// BitReverse instruction. +// Also build executable with SPV dump. +// RUN: %{build} -o %t.out -O2 -Xspirv-translator --spirv-ext=-SPV_KHR_bit_instructions -fsycl-dump-device-code=%t.spvdir + +// Rename SPV file to explictly known filename. +// RUN: mv %t.spvdir/*.spv %t.spvdir/dump.spv + +// Convert to text. +// RUN: llvm-spirv -to-text %t.spvdir/dump.spv + +// Check that all lowerings are done by llvm-spirv. +// RUN: cat %t.spvdir/dump.spt | FileCheck %s --check-prefix CHECK-SPV --implicit-check-not=BitReverse + +// Execute to ensure lowering has correct functionality. +// RUN: %{run} %t.out + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Build without lowering explicitly disabled. +// RUN: %{build} -o %t.bitinstructions.out + +// Execution should still be correct. +// RUN: %{run} %t.bitinstructions.out + +// CHECK-SPV: Name {{[0-9]+}} "llvm_bitreverse_i2" +// CHECK-SPV: Name {{[0-9]+}} "llvm_bitreverse_i4" + +// CHECK-SPV: LinkageAttributes "llvm_bitreverse_i2" Export +// CHECK-SPV: LinkageAttributes "llvm_bitreverse_i4" Export + +#include "common.hpp" +#include +#include +#include + +using namespace sycl; + +template +__attribute__((optnone, noinline)) TYPE reference_reverse(TYPE a, + const int bitlength) { + TYPE ret = 0; + for (auto i = 0; i < bitlength; i++) { + ret <<= 1; + ret |= a & 0x1; + a >>= 1; + } + return ret; +} + +template +__attribute__((noinline)) TYPE reverse(TYPE a, int bitlength) { + return __builtin_elementwise_bitreverse(a); +} + +template class BitreverseTest; + +#define NUM_TESTS 1024 + +template void do_scalar_bitreverse_test() { + queue q; + + // calculate bitlength + int bitlength = 0; + TYPE t = 1; + do { + ++bitlength; + t <<= 1; + } while (t); + + TYPE *Input = (TYPE *)malloc_shared(sizeof(TYPE) * NUM_TESTS, q.get_device(), + q.get_context()); + TYPE *Output = (TYPE *)malloc_shared(sizeof(TYPE) * NUM_TESTS, q.get_device(), + q.get_context()); + + for (unsigned i = 0; i < NUM_TESTS; i++) + Input[i] = get_rand(); + q.submit([=](handler &cgh) { + cgh.single_task>([=]() { + for (unsigned i = 0; i < NUM_TESTS; i++) + Output[i] = reverse(Input[i], sizeof(TYPE) * 8); + }); + }); + q.wait(); + for (unsigned i = 0; i < NUM_TESTS; i++) + if (Output[i] != reference_reverse(Input[i], bitlength)) { + std::cerr << "Failed for scalar " << std::hex + << static_cast(Input[i]) << " bitlength=" << bitlength + << "\n"; + + exit(-1); + } + + free(Input, q.get_context()); + free(Output, q.get_context()); +} + +using uint2_t = _BitInt(2); +using uint4_t = _BitInt(4); + +int main() { + srand(2024); + + do_scalar_bitreverse_test(); + do_scalar_bitreverse_test(); + + return 0; +}