llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-hlsl @llvm/pr-subscribers-backend-directx @llvm/pr-subscribers-backend-x86 Author: None (joaosaffran) <details> <summary>Changes</summary> Adding HLSL `clip` function. - adding llvm intrinsic - adding sema checks - adding dxil lowering - ading spirv lowering - adding sema tests - adding codegen tests - adding lowering tests Closes #<!-- -->99093 --- Patch is 22.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/114588.diff 16 Files Affected: - (modified) clang/include/clang/Basic/Builtins.td (+6) - (modified) clang/lib/CodeGen/CGBuiltin.cpp (+41) - (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+17) - (modified) clang/lib/Sema/SemaHLSL.cpp (+8) - (added) clang/test/CodeGenHLSL/builtins/clip.hlsl (+39) - (added) clang/test/SemaHLSL/BuiltIns/clip-errors.hlsl (+22) - (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+1) - (modified) llvm/include/llvm/IR/IntrinsicsSPIRV.td (+1) - (modified) llvm/lib/Target/DirectX/DXIL.td (+30-21) - (modified) llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp (+3-1) - (modified) llvm/lib/Target/SPIRV/SPIRVInstrInfo.td (+1) - (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (+32) - (modified) llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp (+11) - (modified) llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td (+1) - (added) llvm/test/CodeGen/DirectX/clip.ll (+29) - (added) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll (+77) ``````````diff diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 9bd67e0cefebc3..13ba369e323f72 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4877,6 +4877,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(...)"; +} + // 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 34fedd67114751..8177b144639180 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -99,6 +99,42 @@ 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)); + + 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); + 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); + + 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); + + CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::spv_clip, {}, + nullptr); + + auto *BrCall = CGF->Builder.CreateBr(End); + + CGF->Builder.SetInsertPoint(End); + return BrCall; +} + static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) { Value *Op0 = CGF->EmitScalarExpr(E->getArg(0)); const auto *OutArg1 = dyn_cast<HLSLOutArgExpr>(E->getArg(1)); @@ -19093,6 +19129,11 @@ 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"); + return handleHlslClip(E, this); } return nullptr; } diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index d9f3a17ea23d8e..424c2f7e7c23ee 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 a472538236e2d9..e360c54dc0760e 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -2110,6 +2110,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..81976839bbe7d9 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/clip.hlsl @@ -0,0 +1,39 @@ +// 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 --check-prefix=SPIRV + + +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-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-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: [[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: [[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/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index e30d37f69f781e..0d8dc4ead02c8a 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -92,4 +92,5 @@ 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]>; } diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index ddb47390537412..9d2f85315f63e0 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -88,6 +88,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 : Intrinsic<[], [], []>; // Create resource handle given the binding information. Returns a // type appropriate for the kind of resource given the set id, binding id, diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index 1e8dc63ffa257e..94b1f6ff9cc088 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -739,6 +739,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; @@ -788,20 +797,6 @@ def SplitDouble : DXILOp<102, splitDouble> { 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 WaveIsFirstLane : DXILOp<110, waveIsFirstLane> { let Doc = "returns 1 for the first lane in the wave"; let LLVMIntrinsic = int_dx_wave_is_first_lane; @@ -811,6 +806,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; @@ -821,11 +825,16 @@ 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 = []; - let result = Int32Ty; - let stages = [Stages<DXIL1_0, [all_stages]>]; - 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]>]; } diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp index dbfc133864bba4..23221cacca7df3 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -73,7 +73,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/SPIRVInstrInfo.td b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td index ee6b70a16417f4..d8e27153bd7d24 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td +++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.td @@ -636,6 +636,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 892912a5680113..be3852ed482c83 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -147,6 +147,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, @@ -1966,6 +1969,32 @@ bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg, return MIB.constrainAllUses(TII, TRI, RBI); } +bool SPIRVInstructionSelector::selectClip(Register ResVReg, + const SPIRVType *ResType, + MachineInstr &I) const { + + 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)) + .constrainAllUses(TII, TRI, RBI); +} + bool SPIRVInstructionSelector::selectCmp(Register ResVReg, const SPIRVType *ResType, unsigned CmpOpc, @@ -2599,6 +2628,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/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 29ce60d9983e38..bc41ee96f2af66 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -1376,6 +1376,17 @@ void addInstrRequirements(const MachineInstr &MI, Reqs.addCapability(SPIRV::Capability::SplitBarrierINTEL); } 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 d63438baca7e76..edf6e5547631a1 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 new file mode 100644 index 00000000000000..71789e7048363a --- /dev/null +++ b/llvm/test/CodeGen/DirectX/clip.ll @@ -0,0 +1,29 @@ +; 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_scalar +; CHECK: call void @dx.op.discard(i32 82, i1 %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 new file mode 100644 index 00000000000000..89db4be3494ebd --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/clip.ll @@ -0,0 +1,77 @@ +; 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 %} + + +; Make sure lowering is ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/114588 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits