https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/174655
>From 06a34c860273e0db966e2e8b31203f3cb179702e Mon Sep 17 00:00:00 2001 From: Joseph Huber <[email protected]> Date: Tue, 6 Jan 2026 15:36:15 -0600 Subject: [PATCH 1/2] [SPIR-V] Add clang builtin for subgroup shuffles Summary: This is an attempt to begin filling out some missing pieces to allow more generic compute code to use SPIR-V flavored builtins. This should provide the basic shuffle operation. The next most important one is the ballot, but I don't think we have an IR intrinsic for that yet. I don't know SPIR-V very well so let me know if this is the proper function with the proper semantic checks. --- .../clang/Basic/BuiltinsSPIRVCommon.td | 2 ++ clang/lib/CodeGen/TargetBuiltins/SPIR.cpp | 9 +++++++ clang/lib/Sema/SemaSPIRV.cpp | 26 +++++++++++++++++++ .../CodeGenSPIRV/Builtins/ids_and_ranges.c | 8 ++++++ .../test/SemaSPIRV/BuiltIns/ids_and_ranges.c | 6 +++++ 5 files changed, 51 insertions(+) diff --git a/clang/include/clang/Basic/BuiltinsSPIRVCommon.td b/clang/include/clang/Basic/BuiltinsSPIRVCommon.td index d2ef6f99a0502..e31758b889d3d 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRVCommon.td +++ b/clang/include/clang/Basic/BuiltinsSPIRVCommon.td @@ -21,3 +21,5 @@ def subgroup_local_invocation_id : SPIRVBuiltin<"uint32_t()", [NoThrow, Const]>; def distance : SPIRVBuiltin<"void(...)", [NoThrow, Const]>; def length : SPIRVBuiltin<"void(...)", [NoThrow, Const]>; def smoothstep : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>; + +def subgroup_shuffle : SPIRVBuiltin<"void(...)", [NoThrow, Const, CustomTypeChecking]>; diff --git a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp index 9b0ca3eb0035a..1ea23e8c2195f 100644 --- a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp @@ -109,6 +109,15 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, Call->addRetAttr(llvm::Attribute::AttrKind::NoUndef); return Call; } + case SPIRV::BI__builtin_spirv_subgroup_shuffle: { + Value *X = EmitScalarExpr(E->getArg(0)); + Value *Y = EmitScalarExpr(E->getArg(1)); + assert(E->getArg(1)->getType()->hasIntegerRepresentation()); + return Builder.CreateIntrinsic( + /*ReturnType=*/getTypes().ConvertType(E->getArg(0)->getType()), + Intrinsic::spv_wave_readlane, ArrayRef<Value *>{X, Y}, nullptr, + "spv.shuffle"); + } case SPIRV::BI__builtin_spirv_num_workgroups: return Builder.CreateIntrinsic( /*ReturnType=*/getTypes().ConvertType(E->getType()), diff --git a/clang/lib/Sema/SemaSPIRV.cpp b/clang/lib/Sema/SemaSPIRV.cpp index fa30e149c209a..5f3dd71f28c67 100644 --- a/clang/lib/Sema/SemaSPIRV.cpp +++ b/clang/lib/Sema/SemaSPIRV.cpp @@ -380,6 +380,32 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(const TargetInfo &TI, TheCall->setType(RetTy); break; } + case SPIRV::BI__builtin_spirv_subgroup_shuffle: { + if (SemaRef.checkArgCount(TheCall, 2)) + return true; + + ExprResult A = TheCall->getArg(0); + QualType ArgTyA = A.get()->getType(); + if (!ArgTyA->isIntegerType() && !ArgTyA->isFloatingType()) { + SemaRef.Diag(A.get()->getBeginLoc(), diag::err_builtin_invalid_arg_type) + << /* ordinal */ 1 << /* scalar */ 1 << /* no int */ 0 + << /* no fp */ 0 << ArgTyA; + return true; + } + + ExprResult B = TheCall->getArg(1); + QualType ArgTyB = B.get()->getType(); + if (!ArgTyB->isIntegerType()) { + SemaRef.Diag(B.get()->getBeginLoc(), diag::err_builtin_invalid_arg_type) + << /* ordinal */ 2 << /* scalar */ 1 << /* int */ 1 << /* no fp */ 0 + << ArgTyB; + return true; + } + + QualType RetTy = ArgTyA; + TheCall->setType(RetTy); + break; + } } return false; } diff --git a/clang/test/CodeGenSPIRV/Builtins/ids_and_ranges.c b/clang/test/CodeGenSPIRV/Builtins/ids_and_ranges.c index bff850b3622b9..7142dbbc2be73 100644 --- a/clang/test/CodeGenSPIRV/Builtins/ids_and_ranges.c +++ b/clang/test/CodeGenSPIRV/Builtins/ids_and_ranges.c @@ -104,3 +104,11 @@ [[clang::sycl_external]] unsigned int test_subgroup_local_invocation_id() { return __builtin_spirv_subgroup_local_invocation_id(); } + +// CHECK: @{{.*}}test_subgroup_shuffle{{.*}}( +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: tail call float @llvm.spv.wave.readlane.f32(float %f, i32 %i) +// +[[clang::sycl_external]] float test_subgroup_shuffle(float f, int i) { + return __builtin_spirv_subgroup_shuffle(f, i); +} diff --git a/clang/test/SemaSPIRV/BuiltIns/ids_and_ranges.c b/clang/test/SemaSPIRV/BuiltIns/ids_and_ranges.c index 0d98a552bb1b9..43b2de4e31485 100644 --- a/clang/test/SemaSPIRV/BuiltIns/ids_and_ranges.c +++ b/clang/test/SemaSPIRV/BuiltIns/ids_and_ranges.c @@ -75,3 +75,9 @@ void test_subgroup_local_invocation_id() { __builtin_spirv_subgroup_local_invocation_id(); __builtin_spirv_subgroup_local_invocation_id(0); // expected-error{{too many arguments to function call, expected 0, have 1}} } + +void test_subgroup_shuffle(int i, float f, int *p) { + __builtin_spirv_subgroup_shuffle(f, i); + __builtin_spirv_subgroup_shuffle(p, i); // expected-error{{1st argument must be a scalar type}} + __builtin_spirv_subgroup_shuffle(i, f); // expected-error{{2nd argument must be a scalar integer}} +} >From fc35ecc4c9982782ff98b1b524714580426ff5e4 Mon Sep 17 00:00:00 2001 From: Joseph Huber <[email protected]> Date: Wed, 7 Jan 2026 08:50:27 -0600 Subject: [PATCH 2/2] Sema test --- clang/test/SemaSPIRV/BuiltIns/ids_and_ranges.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/test/SemaSPIRV/BuiltIns/ids_and_ranges.c b/clang/test/SemaSPIRV/BuiltIns/ids_and_ranges.c index 43b2de4e31485..89c582c87c2b5 100644 --- a/clang/test/SemaSPIRV/BuiltIns/ids_and_ranges.c +++ b/clang/test/SemaSPIRV/BuiltIns/ids_and_ranges.c @@ -76,8 +76,10 @@ void test_subgroup_local_invocation_id() { __builtin_spirv_subgroup_local_invocation_id(0); // expected-error{{too many arguments to function call, expected 0, have 1}} } -void test_subgroup_shuffle(int i, float f, int *p) { +void test_subgroup_shuffle(int i, float f, int *p, int [[clang::ext_vector_type(1)]] v) { __builtin_spirv_subgroup_shuffle(f, i); __builtin_spirv_subgroup_shuffle(p, i); // expected-error{{1st argument must be a scalar type}} + __builtin_spirv_subgroup_shuffle(p, f); // expected-error{{1st argument must be a scalar type}} __builtin_spirv_subgroup_shuffle(i, f); // expected-error{{2nd argument must be a scalar integer}} + __builtin_spirv_subgroup_shuffle(i, v); // expected-error{{2nd argument must be a scalar integer}} } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
