From eef0346476ff3b67512c2dfa9c820211e6ad64a6 Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Wed, 26 Feb 2025 14:27:40 -0800 Subject: [PATCH 1/2] [SYCL] Update spec constant handling for struct hierarchies --- llvm/lib/SYCLLowerIR/SpecConstants.cpp | 133 +++++++++--------- .../spec-constants/hierarchy.ll | 81 +++++++++++ .../test-e2e/SpecConstants/2020/hierarchy.cpp | 88 ++++++++++++ .../SpecConstants/2020/marray_vec.cpp | 51 +++++++ 4 files changed, 290 insertions(+), 63 deletions(-) create mode 100644 llvm/test/tools/sycl-post-link/spec-constants/hierarchy.ll create mode 100644 sycl/test-e2e/SpecConstants/2020/hierarchy.cpp create mode 100644 sycl/test-e2e/SpecConstants/2020/marray_vec.cpp diff --git a/llvm/lib/SYCLLowerIR/SpecConstants.cpp b/llvm/lib/SYCLLowerIR/SpecConstants.cpp index 08be340512f9b..0b5097d2fa551 100644 --- a/llvm/lib/SYCLLowerIR/SpecConstants.cpp +++ b/llvm/lib/SYCLLowerIR/SpecConstants.cpp @@ -568,51 +568,6 @@ Instruction *emitSpecConstantComposite(Type *Ty, ArrayRef Elements, return emitCall(Ty, SPIRV_GET_SPEC_CONST_COMPOSITE, Elements, InsertBefore); } -// Select corresponding element of the default value. For a -// struct, we getting the corresponding default value is a little -// tricky. There are potentially distinct two types: the type of -// the default value, which comes from the initializer of the -// global spec constant value, and the return type of the call to -// getComposite2020SpecConstValue. The return type can be a -// version of the default value type, with padding fields -// potentially inserted at the top level and within nested -// structs. - -// Examples: (RT = Return Type, DVT = Default Value Type) -// RT: { i8, [3 x i8], i32 }, DVT = { i8, i32 } -// RT: { { i32, i8, [3 x i8] }, i32 } DVT = { { i32, i8 }, i32 } - -// For a given element of the default value type we are -// trying to initialize, we will initialize that element with -// the element of the default value type that has the same offset -// as the element we are trying to initialize. If no such element -// exists, we used undef as the initializer. -Constant *getElemDefaultValue(Type *Ty, Type *ElTy, Constant *DefaultValue, - size_t ElemIndex, const DataLayout &DL) { - if (auto *StructTy = dyn_cast(Ty)) { - auto *DefaultValueType = cast(DefaultValue->getType()); - const auto &DefaultValueTypeSL = DL.getStructLayout(DefaultValueType); - // The struct has padding, so we have to adjust ElemIndex - if (DefaultValueTypeSL->hasPadding()) { - const auto &ReturnTypeSL = DL.getStructLayout(StructTy); - ArrayRef DefaultValueOffsets = - DefaultValueTypeSL->getMemberOffsets(); - TypeSize CurrentIterationOffset = - ReturnTypeSL->getElementOffset(ElemIndex); - const auto It = - std::find(DefaultValueOffsets.begin(), DefaultValueOffsets.end(), - CurrentIterationOffset); - - // The element we are looking at is a padding field - if (It == DefaultValueOffsets.end()) - return UndefValue::get(ElTy); - // Select the index with the same offset - ElemIndex = It - DefaultValueOffsets.begin(); - } - } - return DefaultValue->getAggregateElement(ElemIndex); -} - /// For specified specialization constant type emits LLVM IR which is required /// in order to correctly handle it later during LLVM IR -> SPIR-V translation. /// @@ -636,12 +591,19 @@ Constant *getElemDefaultValue(Type *Ty, Type *ElTy, Constant *DefaultValue, /// __spirvSpecConstantComposite calls for each composite member of the /// composite (plus for the top-level composite). Also enumerates all /// encountered scalars and assigns them IDs (or re-uses existing ones). -Instruction *emitSpecConstantRecursiveImpl(Type *Ty, Instruction *InsertBefore, - SmallVectorImpl &IDs, - unsigned &Index, - Constant *DefaultValue) { +Instruction *emitSpecConstantRecursiveImpl( + Type *Ty, Instruction *InsertBefore, SmallVectorImpl &IDs, + unsigned &Index, unsigned CurrentOffset, + const SmallVectorImpl> &DefinedElements) { const Module &M = *InsertBefore->getModule(); + auto DL = M.getDataLayout(); if (!Ty->isArrayTy() && !Ty->isStructTy() && !Ty->isVectorTy()) { // Scalar + auto It = llvm::lower_bound(DefinedElements, CurrentOffset, + [](const std::pair &LHS, + uint64_t RHS) { return LHS.first < RHS; }); + assert(It != DefinedElements.end() && It->first == CurrentOffset); + Constant *DefaultValue = It->second; + if (Index >= IDs.size()) { // If it is a new specialization constant, we need to generate IDs for // scalar elements, starting with the second one. @@ -649,6 +611,7 @@ Instruction *emitSpecConstantRecursiveImpl(Type *Ty, Instruction *InsertBefore, "All scalar values should be defined"); IDs.push_back({IDs.back().ID + 1, false}); } + return emitSpecConstant(IDs[Index++].ID, Ty, InsertBefore, DefaultValue); } @@ -662,30 +625,34 @@ Instruction *emitSpecConstantRecursiveImpl(Type *Ty, Instruction *InsertBefore, Elements.push_back(Def); Index++; }; - auto LoopIteration = [&](Type *ElTy, unsigned LocalIndex) { - const auto ElemDefaultValue = getElemDefaultValue( - Ty, ElTy, DefaultValue, LocalIndex, M.getDataLayout()); - + auto LoopIteration = [&](Type *ElTy, unsigned LocalOffset) { + auto ElOffset = CurrentOffset + LocalOffset; + auto It = llvm::lower_bound(DefinedElements, ElOffset, + [](const std::pair &LHS, + uint64_t RHS) { return LHS.first < RHS; }); // If the default value is a composite and has the value 'undef', we should // not generate a bunch of __spirv_SpecConstant for its elements but // pass it into __spirv_SpecConstantComposite as is. - if (isa(ElemDefaultValue)) - HandleUndef(ElemDefaultValue); + if (It == DefinedElements.end() || It->first != ElOffset) + HandleUndef(UndefValue::get(ElTy)); else Elements.push_back(emitSpecConstantRecursiveImpl( - ElTy, InsertBefore, IDs, Index, ElemDefaultValue)); + ElTy, InsertBefore, IDs, Index, ElOffset, DefinedElements)); }; if (auto *ArrTy = dyn_cast(Ty)) { + uint64_t ElSize = DL.getTypeAllocSize(ArrTy->getElementType()); for (size_t I = 0; I < ArrTy->getNumElements(); ++I) - LoopIteration(ArrTy->getElementType(), I); + LoopIteration(ArrTy->getElementType(), I * ElSize); } else if (auto *StructTy = dyn_cast(Ty)) { - size_t I = 0; - for (Type *ElTy : StructTy->elements()) - LoopIteration(ElTy, I++); + const StructLayout *SL = M.getDataLayout().getStructLayout(StructTy); + for (auto [ElTy, Offset] : + zip_equal(StructTy->elements(), SL->getMemberOffsets())) + LoopIteration(ElTy, Offset); } else if (auto *VecTy = dyn_cast(Ty)) { + uint64_t ElSize = DL.getTypeAllocSize(VecTy->getElementType()); for (size_t I = 0; I < VecTy->getNumElements(); ++I) - LoopIteration(VecTy->getElementType(), I); + LoopIteration(VecTy->getElementType(), I * ElSize); } else { llvm_unreachable("Unexpected spec constant type"); } @@ -693,13 +660,53 @@ Instruction *emitSpecConstantRecursiveImpl(Type *Ty, Instruction *InsertBefore, return emitSpecConstantComposite(Ty, Elements, InsertBefore); } +/// Recursively iterates over a composite type in order to collect information +/// about the offsets of its scalar elements. +void collectDefinedElements( + Constant *C, const DataLayout &DL, + SmallVectorImpl> &Result, + uint64_t CurrentOffset) { + if (isa(C)) { + return; + } + + if (auto *StructTy = dyn_cast(C->getType())) { + const StructLayout *SL = DL.getStructLayout(StructTy); + for (auto [I, MemberOffset] : enumerate(SL->getMemberOffsets())) + collectDefinedElements(C->getAggregateElement(I), DL, Result, + CurrentOffset + MemberOffset); + } + + else if (auto *ArrTy = dyn_cast(C->getType())) { + uint64_t ElSize = DL.getTypeAllocSize(ArrTy->getElementType()); + for (size_t I = 0; I < ArrTy->getNumElements(); ++I) + collectDefinedElements(C->getAggregateElement(I), DL, Result, + CurrentOffset + I * ElSize); + } + + else if (auto *VecTy = dyn_cast(C->getType())) { + uint64_t ElSize = DL.getTypeAllocSize(VecTy->getElementType()); + for (size_t I = 0; I < VecTy->getNumElements(); ++I) + collectDefinedElements(C->getAggregateElement(I), DL, Result, + CurrentOffset + I * ElSize); + } + + else { + Result.push_back({CurrentOffset, C}); + } +} + /// Wrapper intended to hide IsFirstElement argument from the caller Instruction *emitSpecConstantRecursive(Type *Ty, Instruction *InsertBefore, SmallVectorImpl &IDs, Constant *DefaultValue) { unsigned Index = 0; - return emitSpecConstantRecursiveImpl(Ty, InsertBefore, IDs, Index, - DefaultValue); + SmallVector, 32> DefinedElements; + collectDefinedElements(DefaultValue, + InsertBefore->getModule()->getDataLayout(), + DefinedElements, 0); + return emitSpecConstantRecursiveImpl(Ty, InsertBefore, IDs, Index, 0, + DefinedElements); } /// Function creates load instruction from the given Buffer by the given Offset. diff --git a/llvm/test/tools/sycl-post-link/spec-constants/hierarchy.ll b/llvm/test/tools/sycl-post-link/spec-constants/hierarchy.ll new file mode 100644 index 0000000000000..27cb262e81054 --- /dev/null +++ b/llvm/test/tools/sycl-post-link/spec-constants/hierarchy.ll @@ -0,0 +1,81 @@ +; For C++ types that come from nested class hierarchy, the LLVM type corresponding +; to that type seems to match the nested structure. However, it also seems that +; when defining a constant for that type, the LLVM value defining the constant has a type +; that is different, and is esssentially a flattened out version of the C++ type. +; For example, this test is IR generated from getting the value of a spec constant +; of a struct `scary` that has a deep nested hierarchy, but the specialization_id holding +; the default value of `scary` is a flat struct with all the fields of `scary` flattened out. +; (compare %struct.scary and @_ZL16scary_spec_const) +; This test makes that the spec constant pass can handle such cases. +; (note: IR generated from sycl/test-e2e/SpecConstants/2020/hierarchy.cpp) +; RUN: sycl-post-link -properties --spec-const=native -S %s -o %t.table +; RUN: FileCheck %s -input-file=%t_0.ll + +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1" +target triple = "spir64-unknown-unknown" + +%struct.anon = type { i32, i32 } +%struct.anon.0 = type { i32 } +%struct.scary = type { %struct.layer4.base, [15 x i8] } +%struct.layer4.base = type { %struct.layer3.base } +%struct.layer3.base = type <{ %struct.layer2, [4 x i8], %struct.foo.base }> +%struct.layer2 = type { %struct.layer1 } +%struct.layer1 = type { %struct.base } +%struct.base = type { float, i8, i32, %struct.anon } +%struct.foo.base = type <{ i32, [4 x i8], [5 x i64], [5 x %struct.anon.0], [5 x i8] }> + +@__usid_str = private unnamed_addr constant [44 x i8] c"uid52dfb70f8b72bae7____ZL16scary_spec_const\00", align 1 +@_ZL16scary_spec_const = internal addrspace(1) constant { { float, i8, i32, %struct.anon, [4 x i8], i32, [5 x i64], [5 x %struct.anon.0], [5 x i8], [15 x i8] } } { { float, i8, i32, %struct.anon, [4 x i8], i32, [5 x i64], [5 x %struct.anon.0], [5 x i8], [15 x i8] } { float 0.000000e+00, i8 98, i32 0, %struct.anon zeroinitializer, [4 x i8] undef, i32 3, [5 x i64] [i64 5, i64 0, i64 0, i64 0, i64 0], [5 x %struct.anon.0] [%struct.anon.0 { i32 1 }, %struct.anon.0 { i32 2 }, %struct.anon.0 zeroinitializer, %struct.anon.0 zeroinitializer, %struct.anon.0 zeroinitializer], [5 x i8] c"abc\00\00", [15 x i8] undef } }, align 16 + +define weak_odr dso_local spir_kernel void @_ZTSZ4mainEUlN4sycl3_V114kernel_handlerEE_(ptr addrspace(1) noundef align 16 %_arg_p) { +entry: + %ref.tmp.i = alloca %struct.scary, align 16 + %ref.tmp.ascast.i = addrspacecast ptr %ref.tmp.i to ptr addrspace(4) + call spir_func void @_Z40__sycl_getComposite2020SpecConstantValueI5scaryET_PKcPKvS5_(ptr addrspace(4) dead_on_unwind writable sret(%struct.scary) align 16 %ref.tmp.ascast.i, ptr addrspace(4) noundef addrspacecast (ptr @__usid_str to ptr addrspace(4)), ptr addrspace(4) noundef addrspacecast (ptr addrspace(1) @_ZL16scary_spec_const to ptr addrspace(4)), ptr addrspace(4) noundef null) + call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) align 16 %_arg_p, ptr align 16 %ref.tmp.i, i64 97, i1 false) + ret void +} + +declare dso_local spir_func void @_Z40__sycl_getComposite2020SpecConstantValueI5scaryET_PKcPKvS5_(ptr addrspace(4) dead_on_unwind writable sret(%struct.scary) align 16, ptr addrspace(4) noundef, ptr addrspace(4) noundef, ptr addrspace(4) noundef) + + +;CHECK: %[[#SCV0:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 0, float 0.000000e+00) +;CHECK: %[[#SCV1:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 1, i8 98) +;CHECK: %[[#SCV2:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 2, i32 0) +;CHECK: %[[#SCV3:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 3, i32 0) +;CHECK: %[[#SCV4:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 4, i32 0) +;CHECK: %[[#SCV5:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV3]], i32 %[[#SCV4]]) +;CHECK: %[[#SCV6:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(float %[[#SCV0]], i8 %[[#SCV1]], i32 %[[#SCV2]], %struct.anon %[[#SCV5]]) +;CHECK: %[[#SCV7:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.base %[[#SCV6]]) +;CHECK: %[[#SCV8:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer1 %[[#SCV7]]) +;CHECK: %[[#SCV9:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 6, i32 3) +;CHECK: %[[#SCV10:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 8, i64 5) +;CHECK: %[[#SCV11:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 9, i64 0) +;CHECK: %[[#SCV12:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 10, i64 0) +;CHECK: %[[#SCV13:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 11, i64 0) +;CHECK: %[[#SCV14:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 12, i64 0) +;CHECK: %[[#SCV15:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i64 %[[#SCV10]], i64 %[[#SCV11]], i64 %[[#SCV12]], i64 %[[#SCV13]], i64 %[[#SCV14]]) +;CHECK: %[[#SCV16:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 13, i32 1) +;CHECK: %[[#SCV17:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV16]]) +;CHECK: %[[#SCV18:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 14, i32 2) +;CHECK: %[[#SCV19:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV18]]) +;CHECK: %[[#SCV20:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 15, i32 0) +;CHECK: %[[#SCV21:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV20]]) +;CHECK: %[[#SCV22:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 16, i32 0) +;CHECK: %[[#SCV23:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV22]]) +;CHECK: %[[#SCV24:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 17, i32 0) +;CHECK: %[[#SCV25:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV24]]) +;CHECK: %[[#SCV26:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.anon.0 %[[#SCV17]], %struct.anon.0 %[[#SCV19]], %struct.anon.0 %[[#SCV21]], %struct.anon.0 %[[#SCV23]], %struct.anon.0 %[[#SCV25]]) +;CHECK: %[[#SCV27:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 18, i8 97) +;CHECK: %[[#SCV28:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 19, i8 98) +;CHECK: %[[#SCV29:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 20, i8 99) +;CHECK: %[[#SCV30:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 21, i8 0) +;CHECK: %[[#SCV31:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 22, i8 0) +;CHECK: %[[#SCV32:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i8 %[[#SCV27]], i8 %[[#SCV28]], i8 %[[#SCV29]], i8 %[[#SCV30]], i8 %[[#SCV31]]) +;CHECK: %[[#SCV33:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV9]], [4 x i8] undef, [5 x i64] %[[#SCV15]], [5 x %struct.anon.0] %[[#SCV26]], [5 x i8] %[[#SCV32]]) +;CHECK: %[[#SCV34:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer2 %[[#SCV8]], [4 x i8] undef, %struct.foo.base %[[#SCV33]]) +;CHECK: %[[#SCV35:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer3.base %[[#SCV34]]) +;CHECK: %[[#SCV36:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer4.base %[[#SCV35]], [15 x i8] undef) + +; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite) +declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) diff --git a/sycl/test-e2e/SpecConstants/2020/hierarchy.cpp b/sycl/test-e2e/SpecConstants/2020/hierarchy.cpp new file mode 100644 index 0000000000000..108cbe06a5ea5 --- /dev/null +++ b/sycl/test-e2e/SpecConstants/2020/hierarchy.cpp @@ -0,0 +1,88 @@ +// RUN: %{build} -o %t.out +// RUN: %{run} %t.out +#include +#include +#include + +using namespace sycl; +struct base { + float a; + char b = 'b'; + int c; + struct { + int x; + int y; + } d; +}; +struct layer1 : base {}; +struct layer2 : layer1 {}; +struct foo { + int e = 3; + long long f[5] = {5}; + struct { + int value; + } g[5] = {1, 2}; + char h[5] = {'a', 'b', 'c'}; +}; +struct alignas(16) layer3 : layer2, foo {}; +struct layer4 : layer3 {}; +struct scary : layer4 {}; + +constexpr scary default_scary{}; +constexpr scary zero_scary{base{0, 0, 0, {0, 0}}, foo{0, {}, {}, {}}}; +constexpr specialization_id scary_spec_const(default_scary); + +int main() { + queue Q; + auto *p = malloc_shared(1, Q); + new (p) scary{zero_scary}; + + Q.single_task([=](kernel_handler h) { + *p = h.get_specialization_constant(); + }).wait(); + + int nfails = 0; +#define EXPECT_EQ(a, b, ...) \ + if (a != b) { \ + nfails++; \ + std::cout << "FAIL: " << #a << " != " << #b << " (" << (int)a \ + << " != " << (int)b << ")\n"; \ + } + + // base + EXPECT_EQ(p->a, 0, ); + EXPECT_EQ(p->b, 'b'); + EXPECT_EQ(p->c, 0); + EXPECT_EQ(p->d.x, 0); + EXPECT_EQ(p->d.y, 0); + + // foo + EXPECT_EQ(p->e, 3); + + EXPECT_EQ(p->f[0], 5); + EXPECT_EQ(p->f[1], 0); + EXPECT_EQ(p->f[2], 0); + EXPECT_EQ(p->f[3], 0); + EXPECT_EQ(p->f[4], 0); + + EXPECT_EQ(p->g[0].value, 1); + EXPECT_EQ(p->g[1].value, 2); + EXPECT_EQ(p->g[2].value, 0); + EXPECT_EQ(p->g[3].value, 0); + EXPECT_EQ(p->g[4].value, 0); + + EXPECT_EQ(p->h[0], 'a'); + EXPECT_EQ(p->h[1], 'b'); + EXPECT_EQ(p->h[2], 'c'); + EXPECT_EQ(p->h[3], 0); + EXPECT_EQ(p->h[4], 0); + + if (nfails == 0) { + std::cout << "PASS\n"; + } else { + std::cout << "FAIL\n"; + } + + free(p, Q); + return nfails; +} diff --git a/sycl/test-e2e/SpecConstants/2020/marray_vec.cpp b/sycl/test-e2e/SpecConstants/2020/marray_vec.cpp new file mode 100644 index 0000000000000..b3a24efc80b49 --- /dev/null +++ b/sycl/test-e2e/SpecConstants/2020/marray_vec.cpp @@ -0,0 +1,51 @@ +// RUN: %{build} -o %t.out +// RUN: %{run} %t.out +#include +#include +#include + +using namespace sycl; + +constexpr specialization_id> vec_spec_const(1.f, 2.f, 3.f); +constexpr specialization_id> marray_spec_const(1.f, 2.f, 3.f); + +int main() { + queue Q; + auto *v = malloc_shared>(1, Q); + auto *m = malloc_shared>(1, Q); + new (v) vec{0.f, 0.f, 0.f}; + new (m) marray{0.f, 0.f, 0.f}; + + Q.single_task([=](kernel_handler h) { + *v = h.get_specialization_constant(); + *m = h.get_specialization_constant(); + }).wait(); + + int nfails = 0; +#define EXPECT_EQ(a, b, ...) \ + if (a != b) { \ + nfails++; \ + std::cout << "FAIL: " << #a << " != " << #b << " (" << (int)a \ + << " != " << (int)b << ")\n"; \ + } + + // vec + EXPECT_EQ(v->x(), 1.f); + EXPECT_EQ(v->y(), 2.f); + EXPECT_EQ(v->z(), 3.f); + + // marray + EXPECT_EQ((*m)[0], 1.f); + EXPECT_EQ((*m)[1], 2.f); + EXPECT_EQ((*m)[2], 3.f); + + if (nfails == 0) { + std::cout << "PASS\n"; + } else { + std::cout << "FAIL\n"; + } + + free(v, Q); + free(m, Q); + return nfails; +} From 65997edd7a3e0235120f0e390ac2be1b3bb8ff42 Mon Sep 17 00:00:00 2001 From: "Cai, Justin" Date: Mon, 3 Mar 2025 07:44:52 -0800 Subject: [PATCH 2/2] formatting --- llvm/lib/SYCLLowerIR/SpecConstants.cpp | 2 +- .../spec-constants/hierarchy.ll | 74 +++++++++---------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/llvm/lib/SYCLLowerIR/SpecConstants.cpp b/llvm/lib/SYCLLowerIR/SpecConstants.cpp index 0b5097d2fa551..287a0aabca359 100644 --- a/llvm/lib/SYCLLowerIR/SpecConstants.cpp +++ b/llvm/lib/SYCLLowerIR/SpecConstants.cpp @@ -596,7 +596,6 @@ Instruction *emitSpecConstantRecursiveImpl( unsigned &Index, unsigned CurrentOffset, const SmallVectorImpl> &DefinedElements) { const Module &M = *InsertBefore->getModule(); - auto DL = M.getDataLayout(); if (!Ty->isArrayTy() && !Ty->isStructTy() && !Ty->isVectorTy()) { // Scalar auto It = llvm::lower_bound(DefinedElements, CurrentOffset, [](const std::pair &LHS, @@ -640,6 +639,7 @@ Instruction *emitSpecConstantRecursiveImpl( ElTy, InsertBefore, IDs, Index, ElOffset, DefinedElements)); }; + auto DL = M.getDataLayout(); if (auto *ArrTy = dyn_cast(Ty)) { uint64_t ElSize = DL.getTypeAllocSize(ArrTy->getElementType()); for (size_t I = 0; I < ArrTy->getNumElements(); ++I) diff --git a/llvm/test/tools/sycl-post-link/spec-constants/hierarchy.ll b/llvm/test/tools/sycl-post-link/spec-constants/hierarchy.ll index 27cb262e81054..04ca51be21c96 100644 --- a/llvm/test/tools/sycl-post-link/spec-constants/hierarchy.ll +++ b/llvm/test/tools/sycl-post-link/spec-constants/hierarchy.ll @@ -39,43 +39,43 @@ entry: declare dso_local spir_func void @_Z40__sycl_getComposite2020SpecConstantValueI5scaryET_PKcPKvS5_(ptr addrspace(4) dead_on_unwind writable sret(%struct.scary) align 16, ptr addrspace(4) noundef, ptr addrspace(4) noundef, ptr addrspace(4) noundef) -;CHECK: %[[#SCV0:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 0, float 0.000000e+00) -;CHECK: %[[#SCV1:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 1, i8 98) -;CHECK: %[[#SCV2:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 2, i32 0) -;CHECK: %[[#SCV3:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 3, i32 0) -;CHECK: %[[#SCV4:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 4, i32 0) -;CHECK: %[[#SCV5:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV3]], i32 %[[#SCV4]]) -;CHECK: %[[#SCV6:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(float %[[#SCV0]], i8 %[[#SCV1]], i32 %[[#SCV2]], %struct.anon %[[#SCV5]]) -;CHECK: %[[#SCV7:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.base %[[#SCV6]]) -;CHECK: %[[#SCV8:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer1 %[[#SCV7]]) -;CHECK: %[[#SCV9:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 6, i32 3) -;CHECK: %[[#SCV10:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 8, i64 5) -;CHECK: %[[#SCV11:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 9, i64 0) -;CHECK: %[[#SCV12:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 10, i64 0) -;CHECK: %[[#SCV13:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 11, i64 0) -;CHECK: %[[#SCV14:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 12, i64 0) -;CHECK: %[[#SCV15:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i64 %[[#SCV10]], i64 %[[#SCV11]], i64 %[[#SCV12]], i64 %[[#SCV13]], i64 %[[#SCV14]]) -;CHECK: %[[#SCV16:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 13, i32 1) -;CHECK: %[[#SCV17:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV16]]) -;CHECK: %[[#SCV18:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 14, i32 2) -;CHECK: %[[#SCV19:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV18]]) -;CHECK: %[[#SCV20:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 15, i32 0) -;CHECK: %[[#SCV21:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV20]]) -;CHECK: %[[#SCV22:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 16, i32 0) -;CHECK: %[[#SCV23:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV22]]) -;CHECK: %[[#SCV24:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 17, i32 0) -;CHECK: %[[#SCV25:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV24]]) -;CHECK: %[[#SCV26:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.anon.0 %[[#SCV17]], %struct.anon.0 %[[#SCV19]], %struct.anon.0 %[[#SCV21]], %struct.anon.0 %[[#SCV23]], %struct.anon.0 %[[#SCV25]]) -;CHECK: %[[#SCV27:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 18, i8 97) -;CHECK: %[[#SCV28:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 19, i8 98) -;CHECK: %[[#SCV29:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 20, i8 99) -;CHECK: %[[#SCV30:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 21, i8 0) -;CHECK: %[[#SCV31:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 22, i8 0) -;CHECK: %[[#SCV32:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i8 %[[#SCV27]], i8 %[[#SCV28]], i8 %[[#SCV29]], i8 %[[#SCV30]], i8 %[[#SCV31]]) -;CHECK: %[[#SCV33:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV9]], [4 x i8] undef, [5 x i64] %[[#SCV15]], [5 x %struct.anon.0] %[[#SCV26]], [5 x i8] %[[#SCV32]]) -;CHECK: %[[#SCV34:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer2 %[[#SCV8]], [4 x i8] undef, %struct.foo.base %[[#SCV33]]) -;CHECK: %[[#SCV35:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer3.base %[[#SCV34]]) -;CHECK: %[[#SCV36:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer4.base %[[#SCV35]], [15 x i8] undef) +; CHECK: %[[#SCV0:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 0, float 0.000000e+00) +; CHECK: %[[#SCV1:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 1, i8 98) +; CHECK: %[[#SCV2:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 2, i32 0) +; CHECK: %[[#SCV3:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 3, i32 0) +; CHECK: %[[#SCV4:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 4, i32 0) +; CHECK: %[[#SCV5:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV3]], i32 %[[#SCV4]]) +; CHECK: %[[#SCV6:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(float %[[#SCV0]], i8 %[[#SCV1]], i32 %[[#SCV2]], %struct.anon %[[#SCV5]]) +; CHECK: %[[#SCV7:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.base %[[#SCV6]]) +; CHECK: %[[#SCV8:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer1 %[[#SCV7]]) +; CHECK: %[[#SCV9:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 6, i32 3) +; CHECK: %[[#SCV10:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 8, i64 5) +; CHECK: %[[#SCV11:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 9, i64 0) +; CHECK: %[[#SCV12:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 10, i64 0) +; CHECK: %[[#SCV13:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 11, i64 0) +; CHECK: %[[#SCV14:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 12, i64 0) +; CHECK: %[[#SCV15:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i64 %[[#SCV10]], i64 %[[#SCV11]], i64 %[[#SCV12]], i64 %[[#SCV13]], i64 %[[#SCV14]]) +; CHECK: %[[#SCV16:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 13, i32 1) +; CHECK: %[[#SCV17:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV16]]) +; CHECK: %[[#SCV18:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 14, i32 2) +; CHECK: %[[#SCV19:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV18]]) +; CHECK: %[[#SCV20:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 15, i32 0) +; CHECK: %[[#SCV21:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV20]]) +; CHECK: %[[#SCV22:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 16, i32 0) +; CHECK: %[[#SCV23:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV22]]) +; CHECK: %[[#SCV24:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 17, i32 0) +; CHECK: %[[#SCV25:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV24]]) +; CHECK: %[[#SCV26:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.anon.0 %[[#SCV17]], %struct.anon.0 %[[#SCV19]], %struct.anon.0 %[[#SCV21]], %struct.anon.0 %[[#SCV23]], %struct.anon.0 %[[#SCV25]]) +; CHECK: %[[#SCV27:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 18, i8 97) +; CHECK: %[[#SCV28:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 19, i8 98) +; CHECK: %[[#SCV29:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 20, i8 99) +; CHECK: %[[#SCV30:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 21, i8 0) +; CHECK: %[[#SCV31:]] = {{.*}}@{{.*}}SpecConstant{{.*}}(i32 22, i8 0) +; CHECK: %[[#SCV32:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i8 %[[#SCV27]], i8 %[[#SCV28]], i8 %[[#SCV29]], i8 %[[#SCV30]], i8 %[[#SCV31]]) +; CHECK: %[[#SCV33:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(i32 %[[#SCV9]], [4 x i8] undef, [5 x i64] %[[#SCV15]], [5 x %struct.anon.0] %[[#SCV26]], [5 x i8] %[[#SCV32]]) +; CHECK: %[[#SCV34:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer2 %[[#SCV8]], [4 x i8] undef, %struct.foo.base %[[#SCV33]]) +; CHECK: %[[#SCV35:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer3.base %[[#SCV34]]) +; CHECK: %[[#SCV36:]] = {{.*}}@{{.*}}SpecConstantComposite{{.*}}(%struct.layer4.base %[[#SCV35]], [15 x i8] undef) ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite) declare void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)