https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/114588
>From 087c2dfeffbadba4df12d5c429bb1e22e9034a3f Mon Sep 17 00:00:00 2001 From: Joao Saffran <jdereze...@microsoft.com> Date: Tue, 29 Oct 2024 19:39:31 +0000 Subject: [PATCH 1/5] adding llvm intrinsic --- clang/include/clang/Basic/Builtins.td | 6 ++++++ clang/lib/CodeGen/CGBuiltin.cpp | 10 ++++++++++ clang/lib/CodeGen/CGHLSLRuntime.h | 1 + clang/lib/Headers/hlsl/hlsl_intrinsics.h | 17 +++++++++++++++++ clang/lib/Sema/SemaHLSL.cpp | 8 ++++++++ clang/test/CodeGenHLSL/builtins/clip.hlsl | 14 ++++++++++++++ llvm/include/llvm/IR/IntrinsicsDirectX.td | 1 + llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + 8 files changed, 58 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/clip.hlsl diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 4360e0bf9840f1..bbbace6e193e66 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4895,6 +4895,12 @@ def HLSLSplitDouble: LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLClip: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_clip"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(bool)"; +} + // Builtins for XRay. def XRayCustomEvent : Builtin { let Spellings = ["__xray_customevent"]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 430ac5626f89d7..2f3e094e882863 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -19180,6 +19180,16 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { "asuint operands types mismatch"); return handleHlslSplitdouble(E, this); } + case Builtin::BI__builtin_hlsl_elementwise_clip: + + assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + "clip operands types mismatch"); + + Value *Op0 = EmitScalarExpr(E->getArg(0)); + auto *CMP = + Builder.CreateFCmpOLT(Op0, ConstantFP::get(Builder.getFloatTy(), 0.0)); + return Builder.CreateIntrinsic( + VoidTy, CGM.getHLSLRuntime().getClipIntrinsic(), {CMP}, nullptr); } return nullptr; } diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index 381a5959ec098e..a1089595683a3d 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -94,6 +94,7 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane) + GENERATE_HLSL_INTRINSIC_FUNCTION(Clip, clip) GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) GENERATE_HLSL_INTRINSIC_FUNCTION(NClamp, nclamp) diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 2ee3827d720495..f84f48fc1c122d 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -655,6 +655,23 @@ double3 clamp(double3, double3, double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) double4 clamp(double4, double4, double4); +//===----------------------------------------------------------------------===// +// clip builtins +//===----------------------------------------------------------------------===// + +/// \fn void clip(T Val) +/// \brief Discards the current pixel if the specified value is less than zero. +/// \param Val The input value. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip) +void clip(float); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip) +void clip(float2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip) +void clip(float3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip) +void clip(float4); + //===----------------------------------------------------------------------===// // cos builtins //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 65b0d9cd65637f..32efb089ca1714 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -2135,6 +2135,14 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; break; } + case Builtin::BI__builtin_hlsl_elementwise_clip: { + if (SemaRef.checkArgCount(TheCall, 1)) + return true; + + if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.FloatTy, 0)) + return true; + break; + } case Builtin::BI__builtin_elementwise_acos: case Builtin::BI__builtin_elementwise_asin: case Builtin::BI__builtin_elementwise_atan: diff --git a/clang/test/CodeGenHLSL/builtins/clip.hlsl b/clang/test/CodeGenHLSL/builtins/clip.hlsl new file mode 100644 index 00000000000000..426ec8f128436a --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/clip.hlsl @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s + +RWBuffer<float4> Buf; + +//CHECK-LABEL: define void @main() +float4 main( ) { + float4 p1 = Buf[0]; + //CHECK: [[LOAD:%.*]] = load <4 x float>, ptr %p1{{.*}}, align 16 + //CHECK-NEXT: [[EXTR:%.*]] = extractelement <4 x float> [[LOAD]], i32 3 + //CHECK-NEXT: [[FCMP:%.*]] = fcmp olt float [[EXTR]], 0.000000e+00 + //CHECK-NEXT: call void @llvm.dx.clip(i1 [[FCMP]]) + clip(p1.a); + return p1; +} diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index 178cb8e814ddca..f73f1ca5010f27 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -99,6 +99,7 @@ def int_dx_step : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, L def int_dx_splitdouble : DefaultAttrsIntrinsic<[llvm_anyint_ty, LLVMMatchType<0>], [LLVMScalarOrSameVectorWidth<0, llvm_double_ty>], [IntrNoMem]>; def int_dx_radians : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; +def int_dx_clip : DefaultAttrsIntrinsic<[], [llvm_i1_ty], [IntrNoMem]>; def int_dx_firstbituhigh : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_anyint_ty], [IntrNoMem]>; def int_dx_firstbitshigh : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_anyint_ty], [IntrNoMem]>; } diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index 962b25560d7510..5308ffc73bdf95 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -91,6 +91,7 @@ let TargetPrefix = "spv" in { def int_spv_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>; def int_spv_radians : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; def int_spv_group_memory_barrier_with_group_sync : DefaultAttrsIntrinsic<[], [], []>; + def int_spv_clip : DefaultAttrsIntrinsic<[], [llvm_i1_ty], [IntrNoMem]>; def int_spv_uclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_spv_sclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_spv_nclamp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; >From 0f68438c755e73815c2c3db6846070ae1d7214a3 Mon Sep 17 00:00:00 2001 From: Joao Saffran <jdereze...@microsoft.com> Date: Wed, 30 Oct 2024 23:29:44 +0000 Subject: [PATCH 2/5] adding DXIL and SPIRV codegen --- clang/lib/CodeGen/CGBuiltin.cpp | 32 ++++++++++++--- clang/test/CodeGenHLSL/builtins/clip.hlsl | 9 ++--- llvm/lib/Target/DirectX/DXIL.td | 40 +++++++++++++++++-- llvm/lib/Target/SPIRV/SPIRVInstrInfo.td | 1 + .../Target/SPIRV/SPIRVInstructionSelector.cpp | 20 ++++++++++ llvm/test/CodeGen/DirectX/clip.ll | 11 +++++ .../CodeGen/SPIRV/hlsl-intrinsics/clip.ll | 18 +++++++++ 7 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/clip.ll create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 2f3e094e882863..f8244eb412be1b 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -99,6 +99,31 @@ static void initializeAlloca(CodeGenFunction &CGF, AllocaInst *AI, Value *Size, I->addAnnotationMetadata("auto-init"); } +static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) { + Value *Op0 = CGF->EmitScalarExpr(E->getArg(0)); + auto *CMP = CGF->Builder.CreateFCmpOLT( + Op0, ConstantFP::get(CGF->Builder.getFloatTy(), 0.0)); + + if (CGF->CGM.getTarget().getTriple().isDXIL()) + return CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::dx_clip, + {CMP}, nullptr); + + BasicBlock *LT0 = CGF->createBasicBlock("lt0", CGF->CurFn); + BasicBlock *End = CGF->createBasicBlock("end", CGF->CurFn); + + CGF->Builder.CreateCondBr(CMP, LT0, End); + + CGF->Builder.SetInsertPoint(LT0); + + auto *IntrCall = CGF->Builder.CreateIntrinsic( + CGF->VoidTy, llvm::Intrinsic::spv_clip, {}, nullptr); + + CGF->Builder.CreateBr(End); + + CGF->Builder.SetInsertPoint(End); + return IntrCall; +} + static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) { Value *Op0 = CGF->EmitScalarExpr(E->getArg(0)); const auto *OutArg1 = dyn_cast<HLSLOutArgExpr>(E->getArg(1)); @@ -19184,12 +19209,7 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { assert(E->getArg(0)->getType()->hasFloatingRepresentation() && "clip operands types mismatch"); - - Value *Op0 = EmitScalarExpr(E->getArg(0)); - auto *CMP = - Builder.CreateFCmpOLT(Op0, ConstantFP::get(Builder.getFloatTy(), 0.0)); - return Builder.CreateIntrinsic( - VoidTy, CGM.getHLSLRuntime().getClipIntrinsic(), {CMP}, nullptr); + return handleHlslClip(E, this); } return nullptr; } diff --git a/clang/test/CodeGenHLSL/builtins/clip.hlsl b/clang/test/CodeGenHLSL/builtins/clip.hlsl index 426ec8f128436a..994a7c9f3311c3 100644 --- a/clang/test/CodeGenHLSL/builtins/clip.hlsl +++ b/clang/test/CodeGenHLSL/builtins/clip.hlsl @@ -1,14 +1,11 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s - -RWBuffer<float4> Buf; +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-vulkan-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s //CHECK-LABEL: define void @main() -float4 main( ) { - float4 p1 = Buf[0]; +void test(float Buf) { //CHECK: [[LOAD:%.*]] = load <4 x float>, ptr %p1{{.*}}, align 16 //CHECK-NEXT: [[EXTR:%.*]] = extractelement <4 x float> [[LOAD]], i32 3 //CHECK-NEXT: [[FCMP:%.*]] = fcmp olt float [[EXTR]], 0.000000e+00 //CHECK-NEXT: call void @llvm.dx.clip(i1 [[FCMP]]) - clip(p1.a); - return p1; + clip(Buf); } diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index 078f0591a67515..78ccb70bbf3b38 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -770,6 +770,15 @@ def CheckAccessFullyMapped : DXILOp<71, checkAccessFullyMapped> { let stages = [Stages<DXIL1_0, [all_stages]>]; } +def Discard : DXILOp<82, discard> { + let Doc = "discard the current pixel"; + let LLVMIntrinsic = int_dx_clip; + let arguments = [Int1Ty]; + let result = VoidTy; + let stages = [Stages<DXIL1_0, [pixel]>]; + let attributes = [Attributes<DXIL1_0, [ReadNone]>]; +} + def ThreadId : DXILOp<93, threadId> { let Doc = "Reads the thread ID"; let LLVMIntrinsic = int_dx_thread_id; @@ -862,6 +871,15 @@ def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> { let attributes = [Attributes<DXIL1_0, [ReadNone]>]; } +def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> { + let Doc = "returns the index of the current lane in the wave"; + let LLVMIntrinsic = int_dx_wave_getlaneindex; + let arguments = []; + let result = Int32Ty; + let stages = [Stages<DXIL1_0, [all_stages]>]; + let attributes = [Attributes<DXIL1_0, [ReadNone]>]; +} + def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> { let Doc = "returns the value from the specified lane"; let LLVMIntrinsic = int_dx_wave_readlane; @@ -872,10 +890,24 @@ def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> { let attributes = [Attributes<DXIL1_0, [ReadNone]>]; } -def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> { - let Doc = "returns the index of the current lane in the wave"; - let LLVMIntrinsic = int_dx_wave_getlaneindex; - let arguments = []; +def AnnotateHandle : DXILOp<217, annotateHandle> { + let Doc = "annotate handle with resource properties"; + let arguments = [HandleTy, ResPropsTy]; + let result = HandleTy; + let stages = [Stages<DXIL1_6, [all_stages]>]; +} + +def CreateHandleFromBinding : DXILOp<218, createHandleFromBinding> { + let Doc = "create resource handle from binding"; + let arguments = [ResBindTy, Int32Ty, Int1Ty]; + let result = HandleTy; + let stages = [Stages<DXIL1_6, [all_stages]>]; +} + +def WaveAllBitCount : DXILOp<135, waveAllOp> { + let Doc = "returns the count of bits set to 1 across the wave"; + let LLVMIntrinsic = int_dx_wave_active_countbits; + let arguments = [Int1Ty]; let result = Int32Ty; let stages = [Stages<DXIL1_0, [all_stages]>]; let attributes = [Attributes<DXIL1_0, [ReadNone]>]; diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td index 130b557f9e8484..fde23d9d0ca5f0 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td +++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td @@ -639,6 +639,7 @@ let isReturn = 1, hasDelaySlot = 0, isBarrier = 0, isTerminator = 1, isNotDuplic } def OpLifetimeStart: Op<256, (outs), (ins ID:$ptr, i32imm:$sz), "OpLifetimeStart $ptr, $sz">; def OpLifetimeStop: Op<257, (outs), (ins ID:$ptr, i32imm:$sz), "OpLifetimeStop $ptr, $sz">; +def OpDemoteToHelperInvocation: SimpleOp<"OpDemoteToHelperInvocation", 5380>; // 3.42.18 Atomic Instructions diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index a968b65c173067..8e43df58f7a631 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -164,6 +164,9 @@ class SPIRVInstructionSelector : public InstructionSelector { unsigned comparisonOpcode, MachineInstr &I) const; bool selectCross(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const; + bool selectClip(Register ResVReg, const SPIRVType *ResType, + MachineInstr &I) const; + bool selectICmp(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const; bool selectFCmp(Register ResVReg, const SPIRVType *ResType, @@ -2154,6 +2157,20 @@ bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg, return MIB.constrainAllUses(TII, TRI, RBI); } +bool SPIRVInstructionSelector::selectClip(Register ResVReg, + const SPIRVType *ResType, + MachineInstr &I) const { + + const auto Opcode = + STI.getTargetTriple().getVulkanVersion() < llvm::VersionTuple(1, 3) + ? SPIRV::OpKill + : SPIRV::OpDemoteToHelperInvocation; + + MachineBasicBlock &BB = *I.getParent(); + return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode)) + .constrainAllUses(TII, TRI, RBI); +} + bool SPIRVInstructionSelector::selectCmp(Register ResVReg, const SPIRVType *ResType, unsigned CmpOpc, @@ -2809,6 +2826,9 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, selectHandleFromBinding(ResVReg, ResType, I); return true; } + case Intrinsic::spv_clip: { + return selectClip(ResVReg, ResType, I); + } default: { std::string DiagMsg; raw_string_ostream OS(DiagMsg); diff --git a/llvm/test/CodeGen/DirectX/clip.ll b/llvm/test/CodeGen/DirectX/clip.ll new file mode 100644 index 00000000000000..54ff924675dbb3 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/clip.ll @@ -0,0 +1,11 @@ +; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-pixel %s | FileCheck %s + +; CHECK-LABEL: define void @test_dxil_lowering +; CHECK: call void @dx.op.discard(i32 82, i1 %0) +; +define void @test_dxil_lowering(float noundef %p) #0 { +entry: + %0 = fcmp olt float %p, 0.000000e+00 + call void @llvm.dx.clip(i1 %0) + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll new file mode 100644 index 00000000000000..4c133258f69ba2 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll @@ -0,0 +1,18 @@ +; RUN: llc -verify-machineinstrs -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 %} + + +; CHECK-LABEL: define void @test_dxil_lowering +; CHECK: call void @dx.op.discard(i32 82, i1 %0) +; +define spir_func void @test_dxil_lowering(float noundef %Buf) #0 { +entry: + %Buf.addr = alloca float, align 4 + store float %Buf, ptr %Buf.addr, align 4 + %1 = load float, ptr %Buf.addr, align 4 + %2 = fcmp olt float %1, 0.000000e+00 + call void @llvm.spv.clip(i1 %2) + ret void +} + +declare void @llvm.spv.clip(i1) #1 >From b621ea88d0492949e3266686b4e4ea38b3602a75 Mon Sep 17 00:00:00 2001 From: Joao Saffran <jdereze...@microsoft.com> Date: Thu, 31 Oct 2024 19:30:14 +0000 Subject: [PATCH 3/5] adding tests --- clang/include/clang/Basic/Builtins.td | 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 23 ++++++++++- clang/test/CodeGenHLSL/builtins/clip.hlsl | 39 +++++++++++++++---- .../Target/SPIRV/SPIRVInstructionSelector.cpp | 9 ++--- .../CodeGen/SPIRV/hlsl-intrinsics/clip.ll | 39 +++++++++++++++---- 5 files changed, 89 insertions(+), 23 deletions(-) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index bbbace6e193e66..a7197ffa33520b 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4898,7 +4898,7 @@ def HLSLSplitDouble: LangBuiltin<"HLSL_LANG"> { def HLSLClip: LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_elementwise_clip"]; let Attributes = [NoThrow, Const]; - let Prototype = "void(bool)"; + let Prototype = "void(...)"; } // Builtins for XRay. diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f8244eb412be1b..7d3c9c9bd3305a 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -41,8 +41,10 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsAArch64.h" #include "llvm/IR/IntrinsicsAMDGPU.h" @@ -55,12 +57,14 @@ #include "llvm/IR/IntrinsicsR600.h" #include "llvm/IR/IntrinsicsRISCV.h" #include "llvm/IR/IntrinsicsS390.h" +#include "llvm/IR/IntrinsicsSPIRV.h" #include "llvm/IR/IntrinsicsVE.h" #include "llvm/IR/IntrinsicsWebAssembly.h" #include "llvm/IR/IntrinsicsX86.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/MatrixBuilder.h" #include "llvm/IR/MemoryModelRelaxationAnnotations.h" +#include "llvm/IR/Type.h" #include "llvm/Support/AMDGPUAddrSpace.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/MathExtras.h" @@ -101,13 +105,28 @@ static void initializeAlloca(CodeGenFunction &CGF, AllocaInst *AI, Value *Size, static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) { Value *Op0 = CGF->EmitScalarExpr(E->getArg(0)); - auto *CMP = CGF->Builder.CreateFCmpOLT( - Op0, ConstantFP::get(CGF->Builder.getFloatTy(), 0.0)); + + Constant *FZeroConst = ConstantFP::getZero(CGF->FloatTy); + Value *CMP; + + if (const auto *VecTy = E->getArg(0)->getType()->getAs<clang::VectorType>()) { + FZeroConst = ConstantVector::getSplat( + ElementCount::getFixed(VecTy->getNumElements()), FZeroConst); + CMP = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst); + } else + CMP = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst); if (CGF->CGM.getTarget().getTriple().isDXIL()) return CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::dx_clip, {CMP}, nullptr); + if (const auto *VecTy = E->getArg(0)->getType()->getAs<clang::VectorType>()){ + + CMP = CGF->Builder.CreateIntrinsic(CGF->Builder.getInt1Ty(), llvm::Intrinsic::spv_any, + {CMP}, nullptr); + } + + BasicBlock *LT0 = CGF->createBasicBlock("lt0", CGF->CurFn); BasicBlock *End = CGF->createBasicBlock("end", CGF->CurFn); diff --git a/clang/test/CodeGenHLSL/builtins/clip.hlsl b/clang/test/CodeGenHLSL/builtins/clip.hlsl index 994a7c9f3311c3..0445db8a5d3e06 100644 --- a/clang/test/CodeGenHLSL/builtins/clip.hlsl +++ b/clang/test/CodeGenHLSL/builtins/clip.hlsl @@ -1,11 +1,36 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-vulkan-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-vulkan-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s --check-prefix=SPIRV -//CHECK-LABEL: define void @main() -void test(float Buf) { - //CHECK: [[LOAD:%.*]] = load <4 x float>, ptr %p1{{.*}}, align 16 - //CHECK-NEXT: [[EXTR:%.*]] = extractelement <4 x float> [[LOAD]], i32 3 - //CHECK-NEXT: [[FCMP:%.*]] = fcmp olt float [[EXTR]], 0.000000e+00 - //CHECK-NEXT: call void @llvm.dx.clip(i1 [[FCMP]]) + +void test_scalar(float Buf) { + // CHECK: define void @{{.*}}test_scalar{{.*}}(float {{.*}} [[VALP:%.*]]) + // CHECK: [[LOAD:%.*]] = load float, ptr [[VALP]].addr, align 4 + // CHECK-NEXT: [[FCMP:%.*]] = fcmp olt float [[LOAD]], 0.000000e+00 + // CHECK-NEXT: call void @llvm.dx.clip.i1(i1 [[FCMP]]) + // + // SPIRV: define spir_func void @{{.*}}test_scalar{{.*}}(float {{.*}} [[VALP:%.*]]) + // SPIRV: [[LOAD:%.*]] = load float, ptr [[VALP]].addr, align 4 + // SPIRV-NEXT: [[FCMP:%.*]] = fcmp olt float [[LOAD]], 0.000000e+00 + // SPIRV-NEXT: br i1 [[FCMP]], label %[[LTL:.*]], label %[[ENDL:.*]] + // SPIRV: [[LTL]]: ; preds = %entry + // SPIRV-NEXT: call void @llvm.spv.clip() + // SPIRV: br label %[[ENDL]] + clip(Buf); +} + +void test_vector4(float4 Buf) { + // CHECK: define void @{{.*}}test_vector{{.*}}(<4 x float> {{.*}} [[VALP:%.*]]) + // CHECK: [[LOAD:%.*]] = load <4 x float>, ptr [[VALP]].addr, align 16 + // CHECK-NEXT: [[FCMP:%.*]] = fcmp olt <4 x float> [[LOAD]], zeroinitializer + // CHECK-NEXT: call void @llvm.dx.clip.v4i1(<4 x i1> [[FCMP]]) + // + // SPIRV: define spir_func void @{{.*}}test_vector{{.*}}(<4 x float> {{.*}} [[VALP:%.*]]) + // SPIRV: [[LOAD:%.*]] = load <4 x float>, ptr [[VALP]].addr, align 16 + // SPIRV-NEXT: [[FCMP:%.*]] = fcmp olt <4 x float> [[LOAD]], zeroinitializer + // SPIRV-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[FCMP]]) + // SPIRV-NEXT: br i1 [[RED]], label %[[LTL:.*]], label %[[ENDL:.*]] + // SPIRV: [[LTL]]: ; preds = %entry + // SPIRV-NEXT: call void @llvm.spv.clip() + // SPIRV-NEXT: br label %[[ENDL]] clip(Buf); } diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 8e43df58f7a631..c3fcbe77d43f7c 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -32,6 +32,7 @@ #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/IR/IntrinsicsSPIRV.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/VersionTuple.h" #define DEBUG_TYPE "spirv-isel" @@ -2160,11 +2161,9 @@ bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg, bool SPIRVInstructionSelector::selectClip(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const { - - const auto Opcode = - STI.getTargetTriple().getVulkanVersion() < llvm::VersionTuple(1, 3) - ? SPIRV::OpKill - : SPIRV::OpDemoteToHelperInvocation; + const auto Opcode = (STI.isAtLeastSPIRVVer(VersionTuple(1, 6))) + ? SPIRV::OpDemoteToHelperInvocation + : SPIRV::OpKill; MachineBasicBlock &BB = *I.getParent(); return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode)) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll index 4c133258f69ba2..8c1214c9e67cbc 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll @@ -2,17 +2,40 @@ ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} -; CHECK-LABEL: define void @test_dxil_lowering -; CHECK: call void @dx.op.discard(i32 82, i1 %0) -; -define spir_func void @test_dxil_lowering(float noundef %Buf) #0 { +define void @test_scalar_lowering(float noundef %Buf) { entry: %Buf.addr = alloca float, align 4 store float %Buf, ptr %Buf.addr, align 4 - %1 = load float, ptr %Buf.addr, align 4 - %2 = fcmp olt float %1, 0.000000e+00 - call void @llvm.spv.clip(i1 %2) + %0 = load float, ptr %Buf.addr, align 4 + %1 = fcmp olt float %0, 0.000000e+00 + br i1 %1, label %lt0, label %end + +lt0: ; preds = %entry + call void @llvm.spv.clip() + br label %end + +end: ; preds = %lt0, %entry + ret void +} + +declare void @llvm.spv.clip() + + +define void @test_vector(<4 x float> noundef %Buf) { +entry: + %Buf.addr = alloca <4 x float>, align 16 + store <4 x float> %Buf, ptr %Buf.addr, align 16 + %1 = load <4 x float>, ptr %Buf.addr, align 16 + %2 = fcmp olt <4 x float> %1, zeroinitializer + %3 = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> %2) + br i1 %3, label %lt0, label %end + +lt0: ; preds = %entry + call void @llvm.spv.clip() + br label %end + +end: ; preds = %lt0, %entry ret void } -declare void @llvm.spv.clip(i1) #1 +declare i1 @llvm.vector.reduce.or.v4i1(<4 x i1>) #3 >From 2b225101089204285a180be5beef825040d011f8 Mon Sep 17 00:00:00 2001 From: Joao Saffran <jdereze...@microsoft.com> Date: Fri, 1 Nov 2024 18:11:35 +0000 Subject: [PATCH 4/5] adding tests --- clang/lib/CodeGen/CGBuiltin.cpp | 24 +++----- clang/test/CodeGenHLSL/builtins/clip.hlsl | 17 +++--- clang/test/SemaHLSL/BuiltIns/clip-errors.hlsl | 22 ++++++++ llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp | 4 +- .../Target/SPIRV/SPIRVInstructionSelector.cpp | 21 +++++-- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 11 ++++ .../lib/Target/SPIRV/SPIRVSymbolicOperands.td | 1 + llvm/test/CodeGen/DirectX/clip.ll | 24 +++++++- .../CodeGen/SPIRV/hlsl-intrinsics/clip.ll | 56 +++++++++++++++---- 9 files changed, 139 insertions(+), 41 deletions(-) create mode 100644 clang/test/SemaHLSL/BuiltIns/clip-errors.hlsl diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 7d3c9c9bd3305a..85302feb1950ba 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -41,10 +41,8 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/ValueTracking.h" -#include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/InlineAsm.h" -#include "llvm/IR/InstrTypes.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsAArch64.h" #include "llvm/IR/IntrinsicsAMDGPU.h" @@ -57,14 +55,12 @@ #include "llvm/IR/IntrinsicsR600.h" #include "llvm/IR/IntrinsicsRISCV.h" #include "llvm/IR/IntrinsicsS390.h" -#include "llvm/IR/IntrinsicsSPIRV.h" #include "llvm/IR/IntrinsicsVE.h" #include "llvm/IR/IntrinsicsWebAssembly.h" #include "llvm/IR/IntrinsicsX86.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/MatrixBuilder.h" #include "llvm/IR/MemoryModelRelaxationAnnotations.h" -#include "llvm/IR/Type.h" #include "llvm/Support/AMDGPUAddrSpace.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/MathExtras.h" @@ -112,7 +108,10 @@ static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) { if (const auto *VecTy = E->getArg(0)->getType()->getAs<clang::VectorType>()) { FZeroConst = ConstantVector::getSplat( ElementCount::getFixed(VecTy->getNumElements()), FZeroConst); - CMP = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst); + auto *FCompInst = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst); + CMP = CGF->Builder.CreateIntrinsic( + CGF->Builder.getInt1Ty(), CGF->CGM.getHLSLRuntime().getAnyIntrinsic(), + {FCompInst}, nullptr); } else CMP = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst); @@ -120,13 +119,6 @@ static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) { return CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::dx_clip, {CMP}, nullptr); - if (const auto *VecTy = E->getArg(0)->getType()->getAs<clang::VectorType>()){ - - CMP = CGF->Builder.CreateIntrinsic(CGF->Builder.getInt1Ty(), llvm::Intrinsic::spv_any, - {CMP}, nullptr); - } - - BasicBlock *LT0 = CGF->createBasicBlock("lt0", CGF->CurFn); BasicBlock *End = CGF->createBasicBlock("end", CGF->CurFn); @@ -134,13 +126,13 @@ static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) { CGF->Builder.SetInsertPoint(LT0); - auto *IntrCall = CGF->Builder.CreateIntrinsic( - CGF->VoidTy, llvm::Intrinsic::spv_clip, {}, nullptr); + CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::spv_clip, {}, + nullptr); - CGF->Builder.CreateBr(End); + auto *BrCall = CGF->Builder.CreateBr(End); CGF->Builder.SetInsertPoint(End); - return IntrCall; + return BrCall; } static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) { diff --git a/clang/test/CodeGenHLSL/builtins/clip.hlsl b/clang/test/CodeGenHLSL/builtins/clip.hlsl index 0445db8a5d3e06..81976839bbe7d9 100644 --- a/clang/test/CodeGenHLSL/builtins/clip.hlsl +++ b/clang/test/CodeGenHLSL/builtins/clip.hlsl @@ -6,15 +6,17 @@ void test_scalar(float Buf) { // CHECK: define void @{{.*}}test_scalar{{.*}}(float {{.*}} [[VALP:%.*]]) // CHECK: [[LOAD:%.*]] = load float, ptr [[VALP]].addr, align 4 // CHECK-NEXT: [[FCMP:%.*]] = fcmp olt float [[LOAD]], 0.000000e+00 - // CHECK-NEXT: call void @llvm.dx.clip.i1(i1 [[FCMP]]) + // CHECK-NO: call i1 @llvm.dx.any + // CHECK-NEXT: call void @llvm.dx.clip(i1 [[FCMP]]) // // SPIRV: define spir_func void @{{.*}}test_scalar{{.*}}(float {{.*}} [[VALP:%.*]]) // SPIRV: [[LOAD:%.*]] = load float, ptr [[VALP]].addr, align 4 // SPIRV-NEXT: [[FCMP:%.*]] = fcmp olt float [[LOAD]], 0.000000e+00 + // SPIRV-NO: call i1 @llvm.dx.any // SPIRV-NEXT: br i1 [[FCMP]], label %[[LTL:.*]], label %[[ENDL:.*]] - // SPIRV: [[LTL]]: ; preds = %entry + // SPIRV: [[LTL]]: ; preds = %entry // SPIRV-NEXT: call void @llvm.spv.clip() - // SPIRV: br label %[[ENDL]] + // SPIRV: br label %[[ENDL]] clip(Buf); } @@ -22,14 +24,15 @@ void test_vector4(float4 Buf) { // CHECK: define void @{{.*}}test_vector{{.*}}(<4 x float> {{.*}} [[VALP:%.*]]) // CHECK: [[LOAD:%.*]] = load <4 x float>, ptr [[VALP]].addr, align 16 // CHECK-NEXT: [[FCMP:%.*]] = fcmp olt <4 x float> [[LOAD]], zeroinitializer - // CHECK-NEXT: call void @llvm.dx.clip.v4i1(<4 x i1> [[FCMP]]) + // CHECK-NEXT: [[ANYC:%.*]] = call i1 @llvm.dx.any.v4i1(<4 x i1> [[FCMP]]) + // CHECK-NEXT: call void @llvm.dx.clip(i1 [[ANYC]]) // // SPIRV: define spir_func void @{{.*}}test_vector{{.*}}(<4 x float> {{.*}} [[VALP:%.*]]) // SPIRV: [[LOAD:%.*]] = load <4 x float>, ptr [[VALP]].addr, align 16 // SPIRV-NEXT: [[FCMP:%.*]] = fcmp olt <4 x float> [[LOAD]], zeroinitializer - // SPIRV-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[FCMP]]) - // SPIRV-NEXT: br i1 [[RED]], label %[[LTL:.*]], label %[[ENDL:.*]] - // SPIRV: [[LTL]]: ; preds = %entry + // SPIRV-NEXT: [[ANYC:%.*]] = call i1 @llvm.spv.any.v4i1(<4 x i1> [[FCMP]]) + // SPIRV-NEXT: br i1 [[ANYC]], label %[[LTL:.*]], label %[[ENDL:.*]] + // SPIRV: [[LTL]]: ; preds = %entry // SPIRV-NEXT: call void @llvm.spv.clip() // SPIRV-NEXT: br label %[[ENDL]] clip(Buf); diff --git a/clang/test/SemaHLSL/BuiltIns/clip-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/clip-errors.hlsl new file mode 100644 index 00000000000000..570b4bc18dcd4b --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/clip-errors.hlsl @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -verify + + +void test_arg_missing() { + __builtin_hlsl_elementwise_clip(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} +} + +void test_too_many_args(float p1, float p2) { + __builtin_hlsl_elementwise_clip(p1, p2); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} +} + +void test_first_arg_type_mismatch(bool p) { + __builtin_hlsl_elementwise_clip(p); + // expected-error@-1 {{invalid operand of type 'bool' where 'float' or a vector of such type is required}} +} + +void test_first_arg_type_mismatch_2(half p) { + __builtin_hlsl_elementwise_clip(p); + // expected-error@-1 {{invalid operand of type 'double' where 'float' or a vector of such type is required}} +} diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index e58366017966a7..86f9c785b7652e 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -75,7 +75,9 @@ static const std::map<std::string, SPIRV::Extension::Extension> {"SPV_KHR_cooperative_matrix", SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix}, {"SPV_KHR_non_semantic_info", - SPIRV::Extension::Extension::SPV_KHR_non_semantic_info}}; + SPIRV::Extension::Extension::SPV_KHR_non_semantic_info}, + {"SPV_EXT_demote_to_helper_invocation", + SPIRV::Extension::Extension::SPV_EXT_demote_to_helper_invocation}}; bool SPIRVExtensionsParser::parse(cl::Option &O, llvm::StringRef ArgName, llvm::StringRef ArgValue, diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index c3fcbe77d43f7c..13c2e7ed340431 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -32,7 +32,6 @@ #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/IR/IntrinsicsSPIRV.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/VersionTuple.h" #define DEBUG_TYPE "spirv-isel" @@ -2161,9 +2160,23 @@ bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg, bool SPIRVInstructionSelector::selectClip(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const { - const auto Opcode = (STI.isAtLeastSPIRVVer(VersionTuple(1, 6))) - ? SPIRV::OpDemoteToHelperInvocation - : SPIRV::OpKill; + + unsigned Opcode; + + if (STI.isAtLeastSPIRVVer(VersionTuple(1, 6))) { + if (!STI.canUseExtension( + SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) + report_fatal_error( + "llvm.spv.clip intrinsic: this instruction requires the following " + "SPIR-V extension: SPV_EXT_demote_to_helper_invocation", + false); + Opcode = SPIRV::OpDemoteToHelperInvocation; + } else { + Opcode = SPIRV::OpKill; + // OpKill must be the last operation of any basic block. + MachineInstr *NextI = I.getNextNode(); + NextI->removeFromParent(); + } MachineBasicBlock &BB = *I.getParent(); return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode)) diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index e8641b3a105dec..f0aaeb1b60c9bd 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -1411,6 +1411,17 @@ void addInstrRequirements(const MachineInstr &MI, case SPIRV::OpUDot: AddDotProductRequirements(MI, Reqs, ST); break; + + case SPIRV::OpKill: { + Reqs.addCapability(SPIRV::Capability::Shader); + } break; + case SPIRV::OpDemoteToHelperInvocation: + if (ST.canUseExtension( + SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) { + Reqs.addExtension(SPIRV::Extension::SPV_EXT_demote_to_helper_invocation); + Reqs.addCapability(SPIRV::Capability::DemoteToHelperInvocation); + } + break; default: break; } diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index 5a00a7785b7745..4ae247bafb684f 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -456,6 +456,7 @@ defm VulkanMemoryModelDeviceScopeKHR : CapabilityOperand<5346, 0, 0, [], []>; defm ImageFootprintNV : CapabilityOperand<5282, 0, 0, [], []>; defm FragmentBarycentricNV : CapabilityOperand<5284, 0, 0, [], []>; defm ComputeDerivativeGroupQuadsNV : CapabilityOperand<5288, 0, 0, [], []>; +defm DemoteToHelperInvocation : CapabilityOperand<5379, 0, 0, [SPV_EXT_demote_to_helper_invocation], []>; defm ComputeDerivativeGroupLinearNV : CapabilityOperand<5350, 0, 0, [], []>; defm FragmentDensityEXT : CapabilityOperand<5291, 0, 0, [], [Shader]>; defm PhysicalStorageBufferAddressesEXT : CapabilityOperand<5347, 0, 0, [], [Shader]>; diff --git a/llvm/test/CodeGen/DirectX/clip.ll b/llvm/test/CodeGen/DirectX/clip.ll index 54ff924675dbb3..71789e7048363a 100644 --- a/llvm/test/CodeGen/DirectX/clip.ll +++ b/llvm/test/CodeGen/DirectX/clip.ll @@ -1,11 +1,29 @@ -; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-pixel %s | FileCheck %s +; RUN: opt -passes='function(scalarizer),module(dxil-op-lower,dxil-intrinsic-expansion)' -S -mtriple=dxil-pc-shadermodel6.3-pixel %s | FileCheck %s -; CHECK-LABEL: define void @test_dxil_lowering +; CHECK-LABEL: define void @test_scalar ; CHECK: call void @dx.op.discard(i32 82, i1 %0) ; -define void @test_dxil_lowering(float noundef %p) #0 { +define void @test_scalar(float noundef %p) #0 { entry: %0 = fcmp olt float %p, 0.000000e+00 call void @llvm.dx.clip(i1 %0) ret void } + +; CHECK-LABEL: define void @test_vector +; CHECK: [[EXTR0:%.*]] = extractelement <4 x i1> [[INP:%.*]], i64 0 +; CHECK-NEXT: [[EXTR1:%.*]] = extractelement <4 x i1> [[INP:%.*]], i64 1 +; CHECK-NEXT: [[OR1:%.*]] = or i1 [[EXTR0]], [[EXTR1]] +; CHECK-NEXT: [[EXTR2:%.*]] = extractelement <4 x i1> [[INP:%.*]], i64 2 +; CHECK-NEXT: [[OR2:%.*]] = or i1 [[OR1]], [[EXTR2]] +; CHECK-NEXT: [[EXTR3:%.*]] = extractelement <4 x i1> [[INP:%.*]], i64 3 +; CHECK-NEXT: [[OR3:%.*]] = or i1 [[OR2]], [[EXTR3]] +; CHECK-NEXT: call void @dx.op.discard(i32 82, i1 [[OR3]]) +; +define void @test_vector(<4 x float> noundef %p) #0 { +entry: + %0 = fcmp olt <4 x float> %p, zeroinitializer + %1 = call i1 @llvm.dx.any.v4i1(<4 x i1> %0) + call void @llvm.dx.clip(i1 %1) + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll index 8c1214c9e67cbc..89db4be3494ebd 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll @@ -1,14 +1,40 @@ -; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,SPIRV15 +; RUN: llc -verify-machineinstrs -spirv-ext=+SPV_EXT_demote_to_helper_invocation -O0 -mtriple=spirv32v1.6-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,SPIRV16 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} -define void @test_scalar_lowering(float noundef %Buf) { +; Make sure lowering is correctly generating spirv code. + +; CHECK-DAG: %[[#float:]] = OpTypeFloat 32 +; CHECK-DAG: %[[#void:]] = OpTypeVoid +; CHECK-DAG: %[[#bool:]] = OpTypeBool +; CHECK-DAG: %[[#v4bool:]] = OpTypeVector %[[#bool]] 4 +; CHECK-DAG: %[[#v4float:]] = OpTypeVector %[[#float]] 4 +; CHECK-DAG: %[[#fzero:]] = OpConstant %[[#float]] 0 +; CHECK-DAG: %[[#v4fzero:]] = OpConstantNull %[[#v4float]] +; SPIRV16-DAG: %[[#vecfuncopptr:]] = OpTypePointer Function %[[#v4float]] +; SPIRV16-DAG: %[[#funcopptr:]] = OpTypePointer Function %[[#float]] + +define void @test_scalar(float noundef %Buf) { entry: +; CHECK-LABEL: ; -- Begin function test_scalar +; SPIRV16: %[[#param:]] = OpVariable %[[#funcopptr]] Function +; SPIRV16: %[[#load:]] = OpLoad %[[#float]] %[[#param]] Aligned 4 +; SPIRV15: %[[#load:]] = OpFunctionParameter %[[#float]] +; CHECK: %[[#cmplt:]] = OpFOrdLessThan %[[#bool]] %[[#load]] %[[#fzero]] +; CHECK: OpBranchConditional %[[#cmplt]] %[[#truel:]] %[[#endl:]] +; CHECK: %[[#truel]] = OpLabel +; SPIRV15: OpKill +; SPIRV16-NO: OpKill +; SPIRV15-NO: OpBranch %[[#endl]] +; SPIRV16: OpDemoteToHelperInvocation +; SPIRV16: OpBranch %[[#endl]] +; CHECK: %[[#endl]] = OpLabel %Buf.addr = alloca float, align 4 store float %Buf, ptr %Buf.addr, align 4 - %0 = load float, ptr %Buf.addr, align 4 - %1 = fcmp olt float %0, 0.000000e+00 - br i1 %1, label %lt0, label %end + %1 = load float, ptr %Buf.addr, align 4 + %2 = fcmp olt float %1, 0.000000e+00 + br i1 %2, label %lt0, label %end lt0: ; preds = %entry call void @llvm.spv.clip() @@ -17,17 +43,29 @@ lt0: ; preds = %entry end: ; preds = %lt0, %entry ret void } - declare void @llvm.spv.clip() - define void @test_vector(<4 x float> noundef %Buf) { entry: +; CHECK-LABEL: ; -- Begin function test_vector +; SPIRV16: %[[#param:]] = OpVariable %[[#vecfuncopptr]] Function +; SPIRV16: %[[#loadvec:]] = OpLoad %[[#v4float]] %[[#param]] Aligned 16 +; SPIRV15: %[[#loadvec:]] = OpFunctionParameter %[[#v4float]] +; CHECK: %[[#cmplt:]] = OpFOrdLessThan %[[#v4bool]] %[[#loadvec]] %[[#v4fzero]] +; CHECK: %[[#opany:]] = OpAny %[[#bool]] %[[#cmplt]] +; CHECK: OpBranchConditional %[[#opany]] %[[#truel:]] %[[#endl:]] +; CHECK: %[[#truel]] = OpLabel +; SPIRV15: OpKill +; SPIRV16-NO: OpKill +; SPIRV15-NO: OpBranch %[[#endl]] +; SPIRV16: OpDemoteToHelperInvocation +; SPIRV16: OpBranch %[[#endl]] +; CHECK: %[[#endl]] = OpLabel %Buf.addr = alloca <4 x float>, align 16 store <4 x float> %Buf, ptr %Buf.addr, align 16 %1 = load <4 x float>, ptr %Buf.addr, align 16 %2 = fcmp olt <4 x float> %1, zeroinitializer - %3 = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> %2) + %3 = call i1 @llvm.spv.any.v4i1(<4 x i1> %2) br i1 %3, label %lt0, label %end lt0: ; preds = %entry @@ -37,5 +75,3 @@ lt0: ; preds = %entry end: ; preds = %lt0, %entry ret void } - -declare i1 @llvm.vector.reduce.or.v4i1(<4 x i1>) #3 >From 3b7d9e5d104051cb9cee9253e7f5efd967eabb40 Mon Sep 17 00:00:00 2001 From: Joao Saffran <jdereze...@microsoft.com> Date: Fri, 8 Nov 2024 07:06:52 +0000 Subject: [PATCH 5/5] addressing pr comments --- clang/lib/CodeGen/CGBuiltin.cpp | 27 +++++++++------- clang/lib/CodeGen/CGHLSLRuntime.h | 1 - llvm/docs/SPIRVUsage.rst | 2 ++ llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 +- llvm/lib/Target/DirectX/DXIL.td | 31 +++---------------- llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp | 6 ++-- .../Target/SPIRV/SPIRVInstructionSelector.cpp | 10 ++---- llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 19 +++++++----- .../lib/Target/SPIRV/SPIRVSymbolicOperands.td | 2 +- .../CodeGen/SPIRV/hlsl-intrinsics/clip.ll | 22 ++++++------- 10 files changed, 52 insertions(+), 70 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 85302feb1950ba..e59674a8609912 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -104,6 +104,7 @@ static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) { Constant *FZeroConst = ConstantFP::getZero(CGF->FloatTy); Value *CMP; + Value *LastInstr; if (const auto *VecTy = E->getArg(0)->getType()->getAs<clang::VectorType>()) { FZeroConst = ConstantVector::getSplat( @@ -116,23 +117,27 @@ static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) { CMP = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst); if (CGF->CGM.getTarget().getTriple().isDXIL()) - return CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::dx_clip, - {CMP}, nullptr); + LastInstr = CGF->Builder.CreateIntrinsic( + CGF->VoidTy, llvm::Intrinsic::dx_clip, {CMP}, nullptr); + else if (CGF->CGM.getTarget().getTriple().isSPIRV()) { + BasicBlock *LT0 = CGF->createBasicBlock("lt0", CGF->CurFn); + BasicBlock *End = CGF->createBasicBlock("end", CGF->CurFn); - BasicBlock *LT0 = CGF->createBasicBlock("lt0", CGF->CurFn); - BasicBlock *End = CGF->createBasicBlock("end", CGF->CurFn); + CGF->Builder.CreateCondBr(CMP, LT0, End); - CGF->Builder.CreateCondBr(CMP, LT0, End); + CGF->Builder.SetInsertPoint(LT0); - CGF->Builder.SetInsertPoint(LT0); + CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::spv_clip, {}, + nullptr); - CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::spv_clip, {}, - nullptr); + LastInstr = CGF->Builder.CreateBr(End); - auto *BrCall = CGF->Builder.CreateBr(End); + CGF->Builder.SetInsertPoint(End); + } else { + llvm_unreachable("Backend Codegen not supported."); + } - CGF->Builder.SetInsertPoint(End); - return BrCall; + return LastInstr; } static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) { diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index a1089595683a3d..381a5959ec098e 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -94,7 +94,6 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane) GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane) - GENERATE_HLSL_INTRINSIC_FUNCTION(Clip, clip) GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh) GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh) GENERATE_HLSL_INTRINSIC_FUNCTION(NClamp, nclamp) diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst index 0fcaa366c8a3e0..4fe142865df738 100644 --- a/llvm/docs/SPIRVUsage.rst +++ b/llvm/docs/SPIRVUsage.rst @@ -149,6 +149,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na - Adds atomic min and max instruction on floating-point numbers. * - ``SPV_EXT_arithmetic_fence`` - Adds an instruction that prevents fast-math optimizations between its argument and the expression that contains it. + * - ``SPV_EXT_demote_to_helper_invocation`` + - Adds an instruction that demotes a fragment shader invocation to a helper invocation. * - ``SPV_INTEL_arbitrary_precision_integers`` - Allows generating arbitrary width integer types. * - ``SPV_INTEL_bfloat16_conversion`` diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index 5308ffc73bdf95..f0f8b1f9d6437a 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -91,7 +91,7 @@ let TargetPrefix = "spv" in { def int_spv_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>; def int_spv_radians : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; def int_spv_group_memory_barrier_with_group_sync : DefaultAttrsIntrinsic<[], [], []>; - def int_spv_clip : DefaultAttrsIntrinsic<[], [llvm_i1_ty], [IntrNoMem]>; + def int_spv_clip : DefaultAttrsIntrinsic<[], [], []>; def int_spv_uclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_spv_sclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_spv_nclamp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index 78ccb70bbf3b38..bca0234eaefa38 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -871,15 +871,6 @@ def WaveIsFirstLane : DXILOp<110, waveIsFirstLane> { let attributes = [Attributes<DXIL1_0, [ReadNone]>]; } -def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> { - let Doc = "returns the index of the current lane in the wave"; - let LLVMIntrinsic = int_dx_wave_getlaneindex; - let arguments = []; - let result = Int32Ty; - let stages = [Stages<DXIL1_0, [all_stages]>]; - let attributes = [Attributes<DXIL1_0, [ReadNone]>]; -} - def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> { let Doc = "returns the value from the specified lane"; let LLVMIntrinsic = int_dx_wave_readlane; @@ -890,24 +881,10 @@ def WaveReadLaneAt: DXILOp<117, waveReadLaneAt> { let attributes = [Attributes<DXIL1_0, [ReadNone]>]; } -def AnnotateHandle : DXILOp<217, annotateHandle> { - let Doc = "annotate handle with resource properties"; - let arguments = [HandleTy, ResPropsTy]; - let result = HandleTy; - let stages = [Stages<DXIL1_6, [all_stages]>]; -} - -def CreateHandleFromBinding : DXILOp<218, createHandleFromBinding> { - let Doc = "create resource handle from binding"; - let arguments = [ResBindTy, Int32Ty, Int1Ty]; - let result = HandleTy; - let stages = [Stages<DXIL1_6, [all_stages]>]; -} - -def WaveAllBitCount : DXILOp<135, waveAllOp> { - let Doc = "returns the count of bits set to 1 across the wave"; - let LLVMIntrinsic = int_dx_wave_active_countbits; - let arguments = [Int1Ty]; +def WaveGetLaneIndex : DXILOp<111, waveGetLaneIndex> { + let Doc = "returns the index of the current lane in the wave"; + let LLVMIntrinsic = int_dx_wave_getlaneindex; + let arguments = []; let result = Int32Ty; let stages = [Stages<DXIL1_0, [all_stages]>]; let attributes = [Attributes<DXIL1_0, [ReadNone]>]; diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index 86f9c785b7652e..b3510b2c79a425 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -30,6 +30,8 @@ static const std::map<std::string, SPIRV::Extension::Extension> SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_min_max}, {"SPV_EXT_arithmetic_fence", SPIRV::Extension::Extension::SPV_EXT_arithmetic_fence}, + {"SPV_EXT_demote_to_helper_invocation", + SPIRV::Extension::Extension::SPV_EXT_demote_to_helper_invocation}, {"SPV_INTEL_arbitrary_precision_integers", SPIRV::Extension::Extension::SPV_INTEL_arbitrary_precision_integers}, {"SPV_INTEL_cache_controls", @@ -75,9 +77,7 @@ static const std::map<std::string, SPIRV::Extension::Extension> {"SPV_KHR_cooperative_matrix", SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix}, {"SPV_KHR_non_semantic_info", - SPIRV::Extension::Extension::SPV_KHR_non_semantic_info}, - {"SPV_EXT_demote_to_helper_invocation", - SPIRV::Extension::Extension::SPV_EXT_demote_to_helper_invocation}}; + SPIRV::Extension::Extension::SPV_KHR_non_semantic_info}}; bool SPIRVExtensionsParser::parse(cl::Option &O, llvm::StringRef ArgName, llvm::StringRef ArgValue, diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 13c2e7ed340431..96160a08a98567 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -2163,13 +2163,9 @@ bool SPIRVInstructionSelector::selectClip(Register ResVReg, unsigned Opcode; - if (STI.isAtLeastSPIRVVer(VersionTuple(1, 6))) { - if (!STI.canUseExtension( - SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) - report_fatal_error( - "llvm.spv.clip intrinsic: this instruction requires the following " - "SPIR-V extension: SPV_EXT_demote_to_helper_invocation", - false); + if (STI.canUseExtension( + SPIRV::Extension::SPV_EXT_demote_to_helper_invocation) || + STI.isAtLeastSPIRVVer(llvm::VersionTuple(1, 6))) { Opcode = SPIRV::OpDemoteToHelperInvocation; } else { Opcode = SPIRV::OpKill; diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index f0aaeb1b60c9bd..0bfc5138d56e4f 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -633,7 +633,8 @@ void RequirementHandler::initAvailableCapabilities(const SPIRVSubtarget &ST) { if (ST.isAtLeastSPIRVVer(VersionTuple(1, 6))) addAvailableCaps({Capability::DotProduct, Capability::DotProductInputAll, Capability::DotProductInput4x8Bit, - Capability::DotProductInput4x8BitPacked}); + Capability::DotProductInput4x8BitPacked, + Capability::DemoteToHelperInvocation}); // Add capabilities enabled by extensions. for (auto Extension : ST.getAllAvailableExtensions()) { @@ -1407,21 +1408,23 @@ void addInstrRequirements(const MachineInstr &MI, Reqs.addCapability(SPIRV::Capability::SplitBarrierINTEL); } break; - case SPIRV::OpSDot: - case SPIRV::OpUDot: - AddDotProductRequirements(MI, Reqs, ST); - break; - case SPIRV::OpKill: { Reqs.addCapability(SPIRV::Capability::Shader); } break; case SPIRV::OpDemoteToHelperInvocation: + Reqs.addCapability(SPIRV::Capability::DemoteToHelperInvocation); + if (ST.canUseExtension( SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) { - Reqs.addExtension(SPIRV::Extension::SPV_EXT_demote_to_helper_invocation); - Reqs.addCapability(SPIRV::Capability::DemoteToHelperInvocation); + if (!ST.isAtLeastSPIRVVer(llvm::VersionTuple(1, 6))) + Reqs.addExtension( + SPIRV::Extension::SPV_EXT_demote_to_helper_invocation); } break; + case SPIRV::OpSDot: + case SPIRV::OpUDot: + AddDotProductRequirements(MI, Reqs, ST); + break; default: break; } diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index 4ae247bafb684f..b88f6f5766a053 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -456,7 +456,7 @@ defm VulkanMemoryModelDeviceScopeKHR : CapabilityOperand<5346, 0, 0, [], []>; defm ImageFootprintNV : CapabilityOperand<5282, 0, 0, [], []>; defm FragmentBarycentricNV : CapabilityOperand<5284, 0, 0, [], []>; defm ComputeDerivativeGroupQuadsNV : CapabilityOperand<5288, 0, 0, [], []>; -defm DemoteToHelperInvocation : CapabilityOperand<5379, 0, 0, [SPV_EXT_demote_to_helper_invocation], []>; +defm DemoteToHelperInvocation : CapabilityOperand<5379, 0x10600, 0, [SPV_EXT_demote_to_helper_invocation], []>; defm ComputeDerivativeGroupLinearNV : CapabilityOperand<5350, 0, 0, [], []>; defm FragmentDensityEXT : CapabilityOperand<5291, 0, 0, [], [Shader]>; defm PhysicalStorageBufferAddressesEXT : CapabilityOperand<5347, 0, 0, [], [Shader]>; diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll index 89db4be3494ebd..463580bde3f36c 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll @@ -1,10 +1,16 @@ -; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,SPIRV15 -; RUN: llc -verify-machineinstrs -spirv-ext=+SPV_EXT_demote_to_helper_invocation -O0 -mtriple=spirv32v1.6-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,SPIRV16 -; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv1.5-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,SPIRV15 +; RUN: llc -verify-machineinstrs -spirv-ext=+SPV_EXT_demote_to_helper_invocation -O0 -mtriple=spirv1.5-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,SPIRV16,WITH-EXTENSION,WITH-CAPABILITY +; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv1.6-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,SPIRV16,WITH-CAPABILITY +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.5-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; RUN: %if spirv-tools %{ llc -O0 -spirv-ext=+SPV_EXT_demote_to_helper_invocation -mtriple=spirv1.5-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.6-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; Make sure lowering is correctly generating spirv code. +; WITH-CAPABILITY-DAG: OpCapability DemoteToHelperInvocation +; WITH-EXTENSION-DAG: OpExtension "SPV_EXT_demote_to_helper_invocation" + ; CHECK-DAG: %[[#float:]] = OpTypeFloat 32 ; CHECK-DAG: %[[#void:]] = OpTypeVoid ; CHECK-DAG: %[[#bool:]] = OpTypeBool @@ -12,15 +18,11 @@ ; CHECK-DAG: %[[#v4float:]] = OpTypeVector %[[#float]] 4 ; CHECK-DAG: %[[#fzero:]] = OpConstant %[[#float]] 0 ; CHECK-DAG: %[[#v4fzero:]] = OpConstantNull %[[#v4float]] -; SPIRV16-DAG: %[[#vecfuncopptr:]] = OpTypePointer Function %[[#v4float]] -; SPIRV16-DAG: %[[#funcopptr:]] = OpTypePointer Function %[[#float]] define void @test_scalar(float noundef %Buf) { entry: ; CHECK-LABEL: ; -- Begin function test_scalar -; SPIRV16: %[[#param:]] = OpVariable %[[#funcopptr]] Function -; SPIRV16: %[[#load:]] = OpLoad %[[#float]] %[[#param]] Aligned 4 -; SPIRV15: %[[#load:]] = OpFunctionParameter %[[#float]] +; CHECK: %[[#load:]] = OpFunctionParameter %[[#float]] ; CHECK: %[[#cmplt:]] = OpFOrdLessThan %[[#bool]] %[[#load]] %[[#fzero]] ; CHECK: OpBranchConditional %[[#cmplt]] %[[#truel:]] %[[#endl:]] ; CHECK: %[[#truel]] = OpLabel @@ -48,9 +50,7 @@ declare void @llvm.spv.clip() define void @test_vector(<4 x float> noundef %Buf) { entry: ; CHECK-LABEL: ; -- Begin function test_vector -; SPIRV16: %[[#param:]] = OpVariable %[[#vecfuncopptr]] Function -; SPIRV16: %[[#loadvec:]] = OpLoad %[[#v4float]] %[[#param]] Aligned 16 -; SPIRV15: %[[#loadvec:]] = OpFunctionParameter %[[#v4float]] +; CHECK: %[[#loadvec:]] = OpFunctionParameter %[[#v4float]] ; CHECK: %[[#cmplt:]] = OpFOrdLessThan %[[#v4bool]] %[[#loadvec]] %[[#v4fzero]] ; CHECK: %[[#opany:]] = OpAny %[[#bool]] %[[#cmplt]] ; CHECK: OpBranchConditional %[[#opany]] %[[#truel:]] %[[#endl:]] _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits