https://github.com/farzonl updated https://github.com/llvm/llvm-project/pull/121598
>From 74f86806bbdf1397973f70043ce0856bc6a4a4a7 Mon Sep 17 00:00:00 2001 From: Farzon Lotfi <farzonlo...@microsoft.com> Date: Fri, 3 Jan 2025 14:52:31 -0500 Subject: [PATCH 1/2] [SPIRV] Add Target Builtins using Distance ext as an example - Update pr labeler so new SPIRV files get properly labeled. - Add distance target builtin to BuiltinsSPIRV.td. - Update TargetBuiltins.h to account for spirv builtins. - Update clang basic CMakeLists.txt to build spirv builtin tablegen. - Hook up sema for SPIRV in Sema.h|cpp, SemaSPIRV.h|cpp, and SemaChecking.cpp. - Hookup sprv target builtins to SPIR.h|SPIR.cpp target. - Update GBuiltin.cpp to emit spirv intrinsics when we get the expected spirv target builtin. - --- .github/new-prs-labeler.yml | 5 ++ clang/include/clang/Basic/BuiltinsSPIRV.td | 15 +++++ clang/include/clang/Basic/CMakeLists.txt | 4 ++ clang/include/clang/Basic/TargetBuiltins.h | 10 ++++ clang/include/clang/Sema/Sema.h | 7 +++ clang/include/clang/Sema/SemaSPIRV.h | 29 +++++++++ clang/lib/Basic/Targets/SPIR.cpp | 13 ++++ clang/lib/Basic/Targets/SPIR.h | 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 22 +++++++ clang/lib/CodeGen/CodeGenFunction.h | 1 + clang/lib/Sema/CMakeLists.txt | 1 + clang/lib/Sema/Sema.cpp | 2 + clang/lib/Sema/SemaChecking.cpp | 3 + clang/lib/Sema/SemaSPIRV.cpp | 59 +++++++++++++++++++ clang/test/CodeGenSPIRV/Builtins/distance.c | 31 ++++++++++ .../test/SemaSPIRV/BuiltIns/distance-errors.c | 23 ++++++++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 + .../CodeGen/SPIRV/hlsl-intrinsics/distance.ll | 33 +++++++++++ llvm/test/CodeGen/SPIRV/opencl/distance.ll | 34 +++++++++++ .../gn/secondary/clang/lib/Sema/BUILD.gn | 1 + 21 files changed, 297 insertions(+), 1 deletion(-) create mode 100644 clang/include/clang/Basic/BuiltinsSPIRV.td create mode 100644 clang/include/clang/Sema/SemaSPIRV.h create mode 100644 clang/lib/Sema/SemaSPIRV.cpp create mode 100644 clang/test/CodeGenSPIRV/Builtins/distance.c create mode 100644 clang/test/SemaSPIRV/BuiltIns/distance-errors.c create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/distance.ll create mode 100644 llvm/test/CodeGen/SPIRV/opencl/distance.ll diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml index 0aa05cd027a47f..566308bb3df8d6 100644 --- a/.github/new-prs-labeler.yml +++ b/.github/new-prs-labeler.yml @@ -661,6 +661,11 @@ backend:DirectX: backend:SPIR-V: - clang/lib/Driver/ToolChains/SPIRV.* + - clang/lib/Sema/SemaSPIRV.cpp + - clang/include/clang/Sema/SemaSPIRV.h + - clang/include/clang/Basic/BuiltinsSPIRV.td + - clang/test/CodeGenSPIRV/** + - clang/test/SemaSPIRV/** - llvm/lib/Target/SPIRV/** - llvm/test/CodeGen/SPIRV/** - llvm/test/Frontend/HLSL/** diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td b/clang/include/clang/Basic/BuiltinsSPIRV.td new file mode 100644 index 00000000000000..195c13573d047f --- /dev/null +++ b/clang/include/clang/Basic/BuiltinsSPIRV.td @@ -0,0 +1,15 @@ +//===--- BuiltinsSPIRV.td - SPIRV Builtin function database ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +include "clang/Basic/BuiltinsBase.td" + +def HLSLDistance : Builtin { + let Spellings = ["__builtin_spirv_distance"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt index 76ac3367e23a66..a53f537fc171a9 100644 --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -60,6 +60,10 @@ clang_tablegen(BuiltinsRISCV.inc -gen-clang-builtins SOURCE BuiltinsRISCV.td TARGET ClangBuiltinsRISCV) +clang_tablegen(BuiltinsSPIRV.inc -gen-clang-builtins + SOURCE BuiltinsSPIRV.td + TARGET ClangBuiltinsSPIRV) + clang_tablegen(BuiltinsX86.inc -gen-clang-builtins SOURCE BuiltinsX86.td TARGET ClangBuiltinsX86) diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h index a14fd2c4b224d8..81b8895622a4b1 100644 --- a/clang/include/clang/Basic/TargetBuiltins.h +++ b/clang/include/clang/Basic/TargetBuiltins.h @@ -119,6 +119,16 @@ namespace clang { }; } + /// SPIRV builtins + namespace SPIRV { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsSPIRV.inc" + LastTSBuiltin + }; + } // namespace SPIRV + /// X86 builtins namespace X86 { enum { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5ee7ea48cc983c..a41f16f6dc8c9b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -173,6 +173,7 @@ class SemaOpenMP; class SemaPPC; class SemaPseudoObject; class SemaRISCV; +class SemaSPIRV; class SemaSYCL; class SemaSwift; class SemaSystemZ; @@ -1142,6 +1143,11 @@ class Sema final : public SemaBase { return *RISCVPtr; } + SemaSPIRV &SPIRV() { + assert(SPIRVPtr); + return *SPIRVPtr; + } + SemaSYCL &SYCL() { assert(SYCLPtr); return *SYCLPtr; @@ -1219,6 +1225,7 @@ class Sema final : public SemaBase { std::unique_ptr<SemaPPC> PPCPtr; std::unique_ptr<SemaPseudoObject> PseudoObjectPtr; std::unique_ptr<SemaRISCV> RISCVPtr; + std::unique_ptr<SemaSPIRV> SPIRVPtr; std::unique_ptr<SemaSYCL> SYCLPtr; std::unique_ptr<SemaSwift> SwiftPtr; std::unique_ptr<SemaSystemZ> SystemZPtr; diff --git a/clang/include/clang/Sema/SemaSPIRV.h b/clang/include/clang/Sema/SemaSPIRV.h new file mode 100644 index 00000000000000..4b59f7e11c00f7 --- /dev/null +++ b/clang/include/clang/Sema/SemaSPIRV.h @@ -0,0 +1,29 @@ +//===----- SemaSPIRV.h ----- Semantic Analysis for SPIRV constructs +//---------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares semantic analysis for SPIRV constructs. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMASPIRV_H +#define LLVM_CLANG_SEMA_SEMASPIRV_H + +#include "clang/AST/ASTFwd.h" +#include "clang/Sema/SemaBase.h" + +namespace clang { +class SemaSPIRV : public SemaBase { +public: + SemaSPIRV(Sema &S); + + bool CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); +}; +} // namespace clang + +#endif // LLVM_CLANG_SEMA_SEMASPIRV_H diff --git a/clang/lib/Basic/Targets/SPIR.cpp b/clang/lib/Basic/Targets/SPIR.cpp index 040303983594f8..f242fedc1ad661 100644 --- a/clang/lib/Basic/Targets/SPIR.cpp +++ b/clang/lib/Basic/Targets/SPIR.cpp @@ -13,11 +13,24 @@ #include "SPIR.h" #include "AMDGPU.h" #include "Targets.h" +#include "clang/Basic/MacroBuilder.h" +#include "clang/Basic/TargetBuiltins.h" #include "llvm/TargetParser/TargetParser.h" using namespace clang; using namespace clang::targets; +static constexpr Builtin::Info BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) \ + {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, +#include "clang/Basic/BuiltinsSPIRV.inc" +}; + +ArrayRef<Builtin::Info> SPIRVTargetInfo::getTargetBuiltins() const { + return llvm::ArrayRef(BuiltinInfo, + clang::SPIRV::LastTSBuiltin - Builtin::FirstTSBuiltin); +} + void SPIRTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { DefineStd(Builder, "SPIR", Opts); diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 85e4bd920d8535..5a328b9ceeb1d1 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -313,7 +313,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRVTargetInfo { resetDataLayout("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"); } - + ArrayRef<Builtin::Info> getTargetBuiltins() const override; void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; }; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 4d4b7428abd505..befc1cfa959241 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -6757,6 +6757,8 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF, case llvm::Triple::riscv32: case llvm::Triple::riscv64: return CGF->EmitRISCVBuiltinExpr(BuiltinID, E, ReturnValue); + case llvm::Triple::spirv: + return CGF->EmitSPIRVBuiltinExpr(BuiltinID, E); case llvm::Triple::spirv64: if (CGF->getTarget().getTriple().getOS() != llvm::Triple::OSType::AMDHSA) return nullptr; @@ -20440,6 +20442,26 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, } } +Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, + const CallExpr *E) { + switch (BuiltinID) { + case SPIRV::BI__builtin_spirv_distance: { + Value *X = EmitScalarExpr(E->getArg(0)); + Value *Y = EmitScalarExpr(E->getArg(1)); + assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + "Distance operands must have a float representation"); + assert(E->getArg(0)->getType()->isVectorType() && + E->getArg(1)->getType()->isVectorType() && + "Distance operands must be a vector"); + return Builder.CreateIntrinsic( + /*ReturnType=*/X->getType()->getScalarType(), Intrinsic::spv_distance, + ArrayRef<Value *>{X, Y}, nullptr, "spv.distance"); + } + } + return nullptr; +} + /// Handle a SystemZ function in which the final argument is a pointer /// to an int that receives the post-instruction CC value. At the LLVM level /// this is represented as a function that returns a {result, cc} pair. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 1a5c42f8f974d0..fd9f2b70059b1a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4756,6 +4756,7 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue); + llvm::Value *EmitSPIRVBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitScalarOrConstFoldImmArg(unsigned ICEArguments, unsigned Idx, const CallExpr *E); llvm::Value *EmitSystemZBuiltinExpr(unsigned BuiltinID, const CallExpr *E); diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 719c3a9312ec15..3241cb53f004ce 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -79,6 +79,7 @@ add_clang_library(clangSema SemaStmt.cpp SemaStmtAsm.cpp SemaStmtAttr.cpp + SemaSPIRV.cpp SemaSYCL.cpp SemaSwift.cpp SemaSystemZ.cpp diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index d6517511d7db4d..abb46d3a84e74e 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -61,6 +61,7 @@ #include "clang/Sema/SemaPPC.h" #include "clang/Sema/SemaPseudoObject.h" #include "clang/Sema/SemaRISCV.h" +#include "clang/Sema/SemaSPIRV.h" #include "clang/Sema/SemaSYCL.h" #include "clang/Sema/SemaSwift.h" #include "clang/Sema/SemaSystemZ.h" @@ -239,6 +240,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, PPCPtr(std::make_unique<SemaPPC>(*this)), PseudoObjectPtr(std::make_unique<SemaPseudoObject>(*this)), RISCVPtr(std::make_unique<SemaRISCV>(*this)), + SPIRVPtr(std::make_unique<SemaSPIRV>(*this)), SYCLPtr(std::make_unique<SemaSYCL>(*this)), SwiftPtr(std::make_unique<SemaSwift>(*this)), SystemZPtr(std::make_unique<SemaSystemZ>(*this)), diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index ce846ae88c38b4..28dcfaac2e84f5 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -70,6 +70,7 @@ #include "clang/Sema/SemaOpenCL.h" #include "clang/Sema/SemaPPC.h" #include "clang/Sema/SemaRISCV.h" +#include "clang/Sema/SemaSPIRV.h" #include "clang/Sema/SemaSystemZ.h" #include "clang/Sema/SemaWasm.h" #include "clang/Sema/SemaX86.h" @@ -1934,6 +1935,8 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, case llvm::Triple::mips64: case llvm::Triple::mips64el: return MIPS().CheckMipsBuiltinFunctionCall(TI, BuiltinID, TheCall); + case llvm::Triple::spirv: + return SPIRV().CheckSPIRVBuiltinFunctionCall(BuiltinID, TheCall); case llvm::Triple::systemz: return SystemZ().CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall); case llvm::Triple::x86: diff --git a/clang/lib/Sema/SemaSPIRV.cpp b/clang/lib/Sema/SemaSPIRV.cpp new file mode 100644 index 00000000000000..05e5c6b0577766 --- /dev/null +++ b/clang/lib/Sema/SemaSPIRV.cpp @@ -0,0 +1,59 @@ +//===- SemaSPIRV.cpp - Semantic Analysis for SPIRV constructs +//---------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// This implements Semantic Analysis for SPIRV constructs. +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaSPIRV.h" +#include "clang/Basic/TargetBuiltins.h" +#include "clang/Sema/Sema.h" + +namespace clang { + +SemaSPIRV::SemaSPIRV(Sema &S) : SemaBase(S) {} + +bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID, + CallExpr *TheCall) { + // position of memory order and scope arguments in the builtin + switch (BuiltinID) { + case SPIRV::BI__builtin_spirv_distance: { + if (SemaRef.checkArgCount(TheCall, 2)) + return true; + + ExprResult A = TheCall->getArg(0); + QualType ArgTyA = A.get()->getType(); + auto *VTyA = ArgTyA->getAs<VectorType>(); + if (VTyA == nullptr) { + SemaRef.Diag(A.get()->getBeginLoc(), + diag::err_typecheck_convert_incompatible) + << ArgTyA + << SemaRef.Context.getVectorType(ArgTyA, 2, VectorKind::Generic) << 1 + << 0 << 0; + return true; + } + + ExprResult B = TheCall->getArg(1); + QualType ArgTyB = B.get()->getType(); + auto *VTyB = ArgTyB->getAs<VectorType>(); + if (VTyB == nullptr) { + SemaRef.Diag(A.get()->getBeginLoc(), + diag::err_typecheck_convert_incompatible) + << ArgTyB + << SemaRef.Context.getVectorType(ArgTyB, 2, VectorKind::Generic) << 1 + << 0 << 0; + return true; + } + + QualType RetTy = VTyA->getElementType(); + TheCall->setType(RetTy); + break; + } + } + return false; +} +} // namespace clang diff --git a/clang/test/CodeGenSPIRV/Builtins/distance.c b/clang/test/CodeGenSPIRV/Builtins/distance.c new file mode 100644 index 00000000000000..76c684b932c1d9 --- /dev/null +++ b/clang/test/CodeGenSPIRV/Builtins/distance.c @@ -0,0 +1,31 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 + +// RUN: %clang_cc1 -O1 -triple spirv-pc-vulkan-compute %s -emit-llvm -o - | FileCheck %s + +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float3 __attribute__((ext_vector_type(3))); +typedef float float4 __attribute__((ext_vector_type(4))); + +// CHECK-LABEL: define spir_func float @test_distance_float2( +// CHECK-SAME: <2 x float> noundef [[X:%.*]], <2 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SPV_DISTANCE:%.*]] = tail call float @llvm.spv.distance.v2f32(<2 x float> [[X]], <2 x float> [[Y]]) +// CHECK-NEXT: ret float [[SPV_DISTANCE]] +// +float test_distance_float2(float2 X, float2 Y) { return __builtin_spirv_distance(X, Y); } + +// CHECK-LABEL: define spir_func float @test_distance_float3( +// CHECK-SAME: <3 x float> noundef [[X:%.*]], <3 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SPV_DISTANCE:%.*]] = tail call float @llvm.spv.distance.v3f32(<3 x float> [[X]], <3 x float> [[Y]]) +// CHECK-NEXT: ret float [[SPV_DISTANCE]] +// +float test_distance_float3(float3 X, float3 Y) { return __builtin_spirv_distance(X, Y); } + +// CHECK-LABEL: define spir_func float @test_distance_float4( +// CHECK-SAME: <4 x float> noundef [[X:%.*]], <4 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SPV_DISTANCE:%.*]] = tail call float @llvm.spv.distance.v4f32(<4 x float> [[X]], <4 x float> [[Y]]) +// CHECK-NEXT: ret float [[SPV_DISTANCE]] +// +float test_distance_float4(float4 X, float4 Y) { return __builtin_spirv_distance(X, Y); } diff --git a/clang/test/SemaSPIRV/BuiltIns/distance-errors.c b/clang/test/SemaSPIRV/BuiltIns/distance-errors.c new file mode 100644 index 00000000000000..17ea25d507895d --- /dev/null +++ b/clang/test/SemaSPIRV/BuiltIns/distance-errors.c @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 %s -triple spirv-pc-vulkan-compute -verify + +typedef float float2 __attribute__((ext_vector_type(2))); + +float test_no_second_arg(float2 p0) { + return __builtin_spirv_distance(p0); + // expected-error@-1 {{too few arguments to function call, expected 2, have 1}} +} + +float test_too_many_arg(float2 p0) { + return __builtin_spirv_distance(p0, p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} +} + +float test_double_scalar_inputs(double p0, double p1) { + return __builtin_spirv_distance(p0, p1); + // expected-error@-1 {{passing 'double' to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(double)))) double' (vector of 2 'double' values)}} +} + +float test_int_scalar_inputs(int p0, int p1) { + return __builtin_spirv_distance(p0, p1); + // expected-error@-1 {{passing 'int' to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} +} diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index bcff0f20b985d4..97bf76f6ae38ff 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -64,6 +64,7 @@ let TargetPrefix = "spv" in { def int_spv_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>; def int_spv_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_spv_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; + def int_spv_distance : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>; def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; def int_spv_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>], [IntrNoMem] >; diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 289d5f31664872..53ee33c6b9d930 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -2906,6 +2906,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, return selectAny(ResVReg, ResType, I); case Intrinsic::spv_cross: return selectExtInst(ResVReg, ResType, I, CL::cross, GL::Cross); + case Intrinsic::spv_distance: + return selectExtInst(ResVReg, ResType, I, CL::distance, GL::Distance); case Intrinsic::spv_lerp: return selectExtInst(ResVReg, ResType, I, CL::mix, GL::FMix); case Intrinsic::spv_length: diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/distance.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/distance.ll new file mode 100644 index 00000000000000..85a24a0127ae04 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/distance.ll @@ -0,0 +1,33 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; Make sure SPIRV operation function calls for distance are lowered correctly. + +; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450" +; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16 +; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4 +; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32 +; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4 + +define noundef half @distance_half4(<4 x half> noundef %a, <4 x half> noundef %b) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#float_16]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_16]] + ; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] Distance %[[#arg0]] %[[#arg1]] + %spv.distance = call half @llvm.spv.distance.f16(<4 x half> %a, <4 x half> %b) + ret half %spv.distance +} + +define noundef float @distance_float4(<4 x float> noundef %a, <4 x float> noundef %b) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#float_32]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_32]] + ; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] Distance %[[#arg0]] %[[#arg1]] + %spv.distance = call float @llvm.spv.distance.f32(<4 x float> %a, <4 x float> %b) + ret float %spv.distance +} + +declare half @llvm.spv.distance.f16(<4 x half>, <4 x half>) +declare float @llvm.spv.distance.f32(<4 x float>, <4 x float>) diff --git a/llvm/test/CodeGen/SPIRV/opencl/distance.ll b/llvm/test/CodeGen/SPIRV/opencl/distance.ll new file mode 100644 index 00000000000000..ac18804c00c9ab --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/opencl/distance.ll @@ -0,0 +1,34 @@ +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: %[[#op_ext_cl:]] = OpExtInstImport "OpenCL.std" + +; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16 +; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4 +; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32 +; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4 + +define noundef half @distance_half4(<4 x half> noundef %a, <4 x half> noundef %b) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#float_16]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_16]] + ; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_cl]] distance %[[#arg0]] %[[#arg1]] + %spv.distance = call half @llvm.spv.distance.f16(<4 x half> %a, <4 x half> %b) + ret half %spv.distance +} + +define noundef float @distance_float4(<4 x float> noundef %a, <4 x float> noundef %b) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#float_32]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_32]] + ; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_cl]] distance %[[#arg0]] %[[#arg1]] + %spv.distance = call float @llvm.spv.distance.f32(<4 x float> %a, <4 x float> %b) + ret float %spv.distance +} + +declare half @llvm.spv.distance.f16(<4 x half>, <4 x half>) +declare float @llvm.spv.distance.f32(<4 x float>, <4 x float>) diff --git a/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn index bcd36779b85ef7..fd2ac587146646 100644 --- a/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/lib/Sema/BUILD.gn @@ -100,6 +100,7 @@ static_library("Sema") { "SemaPPC.cpp", "SemaPseudoObject.cpp", "SemaRISCV.cpp", + "SemaSPIRV.cpp", "SemaSYCL.cpp", "SemaStmt.cpp", "SemaStmtAsm.cpp", >From 756957a0d58c7d9bd85d6459e05c267e8bf7cb7a Mon Sep 17 00:00:00 2001 From: Farzon Lotfi <far...@farzon.org> Date: Mon, 6 Jan 2025 10:58:03 -0500 Subject: [PATCH 2/2] address pr comments --- clang/include/clang/Sema/SemaSPIRV.h | 3 +-- clang/lib/Sema/SemaSPIRV.cpp | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Sema/SemaSPIRV.h b/clang/include/clang/Sema/SemaSPIRV.h index 4b59f7e11c00f7..b26b861a6f47b1 100644 --- a/clang/include/clang/Sema/SemaSPIRV.h +++ b/clang/include/clang/Sema/SemaSPIRV.h @@ -1,5 +1,4 @@ -//===----- SemaSPIRV.h ----- Semantic Analysis for SPIRV constructs -//---------===// +//===----- SemaSPIRV.h ----- Semantic Analysis for SPIRV constructs--------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/lib/Sema/SemaSPIRV.cpp b/clang/lib/Sema/SemaSPIRV.cpp index 05e5c6b0577766..d2de64826c6eb3 100644 --- a/clang/lib/Sema/SemaSPIRV.cpp +++ b/clang/lib/Sema/SemaSPIRV.cpp @@ -1,5 +1,4 @@ -//===- SemaSPIRV.cpp - Semantic Analysis for SPIRV constructs -//---------------===// +//===- SemaSPIRV.cpp - Semantic Analysis for SPIRV constructs--------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -19,7 +18,6 @@ SemaSPIRV::SemaSPIRV(Sema &S) : SemaBase(S) {} bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { - // position of memory order and scope arguments in the builtin switch (BuiltinID) { case SPIRV::BI__builtin_spirv_distance: { if (SemaRef.checkArgCount(TheCall, 2)) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits