llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen Author: Joseph Huber (jhuber6) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/174655.diff 5 Files Affected: - (modified) clang/include/clang/Basic/BuiltinsSPIRVCommon.td (+2) - (modified) clang/lib/CodeGen/TargetBuiltins/SPIR.cpp (+9) - (modified) clang/lib/Sema/SemaSPIRV.cpp (+26) - (modified) clang/test/CodeGenSPIRV/Builtins/ids_and_ranges.c (+8) - (modified) clang/test/SemaSPIRV/BuiltIns/ids_and_ranges.c (+6) ``````````diff 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}} +} `````````` </details> https://github.com/llvm/llvm-project/pull/174655 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
