Skip to content

Commit bc6c068

Browse files
[HLSL] Adding HLSL clip function. (#114588)
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 --------- Co-authored-by: Joao Saffran <[email protected]>
1 parent 942928f commit bc6c068

File tree

18 files changed

+321
-1
lines changed

18 files changed

+321
-1
lines changed

clang/include/clang/Basic/Builtins.td

+6
Original file line numberDiff line numberDiff line change
@@ -4895,6 +4895,12 @@ def HLSLSplitDouble: LangBuiltin<"HLSL_LANG"> {
48954895
let Prototype = "void(...)";
48964896
}
48974897

4898+
def HLSLClip: LangBuiltin<"HLSL_LANG"> {
4899+
let Spellings = ["__builtin_hlsl_elementwise_clip"];
4900+
let Attributes = [NoThrow, Const];
4901+
let Prototype = "void(...)";
4902+
}
4903+
48984904
// Builtins for XRay.
48994905
def XRayCustomEvent : Builtin {
49004906
let Spellings = ["__xray_customevent"];

clang/lib/CodeGen/CGBuiltin.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,47 @@ static void initializeAlloca(CodeGenFunction &CGF, AllocaInst *AI, Value *Size,
9999
I->addAnnotationMetadata("auto-init");
100100
}
101101

102+
static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) {
103+
Value *Op0 = CGF->EmitScalarExpr(E->getArg(0));
104+
105+
Constant *FZeroConst = ConstantFP::getZero(CGF->FloatTy);
106+
Value *CMP;
107+
Value *LastInstr;
108+
109+
if (const auto *VecTy = E->getArg(0)->getType()->getAs<clang::VectorType>()) {
110+
FZeroConst = ConstantVector::getSplat(
111+
ElementCount::getFixed(VecTy->getNumElements()), FZeroConst);
112+
auto *FCompInst = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst);
113+
CMP = CGF->Builder.CreateIntrinsic(
114+
CGF->Builder.getInt1Ty(), CGF->CGM.getHLSLRuntime().getAnyIntrinsic(),
115+
{FCompInst}, nullptr);
116+
} else
117+
CMP = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst);
118+
119+
if (CGF->CGM.getTarget().getTriple().isDXIL())
120+
LastInstr = CGF->Builder.CreateIntrinsic(
121+
CGF->VoidTy, llvm::Intrinsic::dx_discard, {CMP}, nullptr);
122+
else if (CGF->CGM.getTarget().getTriple().isSPIRV()) {
123+
BasicBlock *LT0 = CGF->createBasicBlock("lt0", CGF->CurFn);
124+
BasicBlock *End = CGF->createBasicBlock("end", CGF->CurFn);
125+
126+
CGF->Builder.CreateCondBr(CMP, LT0, End);
127+
128+
CGF->Builder.SetInsertPoint(LT0);
129+
130+
CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::spv_discard, {},
131+
nullptr);
132+
133+
LastInstr = CGF->Builder.CreateBr(End);
134+
135+
CGF->Builder.SetInsertPoint(End);
136+
} else {
137+
llvm_unreachable("Backend Codegen not supported.");
138+
}
139+
140+
return LastInstr;
141+
}
142+
102143
static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) {
103144
Value *Op0 = CGF->EmitScalarExpr(E->getArg(0));
104145
const auto *OutArg1 = dyn_cast<HLSLOutArgExpr>(E->getArg(1));
@@ -19208,6 +19249,10 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
1920819249
"asuint operands types mismatch");
1920919250
return handleHlslSplitdouble(E, this);
1921019251
}
19252+
case Builtin::BI__builtin_hlsl_elementwise_clip:
19253+
assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
19254+
"clip operands types mismatch");
19255+
return handleHlslClip(E, this);
1921119256
}
1921219257
return nullptr;
1921319258
}

clang/lib/Headers/hlsl/hlsl_intrinsics.h

+17
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,23 @@ double3 clamp(double3, double3, double3);
655655
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp)
656656
double4 clamp(double4, double4, double4);
657657

658+
//===----------------------------------------------------------------------===//
659+
// clip builtins
660+
//===----------------------------------------------------------------------===//
661+
662+
/// \fn void clip(T Val)
663+
/// \brief Discards the current pixel if the specified value is less than zero.
664+
/// \param Val The input value.
665+
666+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip)
667+
void clip(float);
668+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip)
669+
void clip(float2);
670+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip)
671+
void clip(float3);
672+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip)
673+
void clip(float4);
674+
658675
//===----------------------------------------------------------------------===//
659676
// cos builtins
660677
//===----------------------------------------------------------------------===//

clang/lib/Sema/SemaHLSL.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -2133,6 +2133,14 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
21332133
return true;
21342134
break;
21352135
}
2136+
case Builtin::BI__builtin_hlsl_elementwise_clip: {
2137+
if (SemaRef.checkArgCount(TheCall, 1))
2138+
return true;
2139+
2140+
if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.FloatTy, 0))
2141+
return true;
2142+
break;
2143+
}
21362144
case Builtin::BI__builtin_elementwise_acos:
21372145
case Builtin::BI__builtin_elementwise_asin:
21382146
case Builtin::BI__builtin_elementwise_atan:
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s
2+
// RUN: %clang_cc1 -finclude-default-header -triple spirv-vulkan-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s --check-prefix=SPIRV
3+
4+
5+
void test_scalar(float Buf) {
6+
// CHECK: define void @{{.*}}test_scalar{{.*}}(float {{.*}} [[VALP:%.*]])
7+
// CHECK: [[LOAD:%.*]] = load float, ptr [[VALP]].addr, align 4
8+
// CHECK-NEXT: [[FCMP:%.*]] = fcmp olt float [[LOAD]], 0.000000e+00
9+
// CHECK-NO: call i1 @llvm.dx.any
10+
// CHECK-NEXT: call void @llvm.dx.discard(i1 [[FCMP]])
11+
//
12+
// SPIRV: define spir_func void @{{.*}}test_scalar{{.*}}(float {{.*}} [[VALP:%.*]])
13+
// SPIRV: [[LOAD:%.*]] = load float, ptr [[VALP]].addr, align 4
14+
// SPIRV-NEXT: [[FCMP:%.*]] = fcmp olt float [[LOAD]], 0.000000e+00
15+
// SPIRV-NO: call i1 @llvm.spv.any
16+
// SPIRV-NEXT: br i1 [[FCMP]], label %[[LTL:.*]], label %[[ENDL:.*]]
17+
// SPIRV: [[LTL]]: ; preds = %entry
18+
// SPIRV-NEXT: call void @llvm.spv.discard()
19+
// SPIRV: br label %[[ENDL]]
20+
clip(Buf);
21+
}
22+
23+
void test_vector4(float4 Buf) {
24+
// CHECK: define void @{{.*}}test_vector{{.*}}(<4 x float> {{.*}} [[VALP:%.*]])
25+
// CHECK: [[LOAD:%.*]] = load <4 x float>, ptr [[VALP]].addr, align 16
26+
// CHECK-NEXT: [[FCMP:%.*]] = fcmp olt <4 x float> [[LOAD]], zeroinitializer
27+
// CHECK-NEXT: [[ANYC:%.*]] = call i1 @llvm.dx.any.v4i1(<4 x i1> [[FCMP]])
28+
// CHECK-NEXT: call void @llvm.dx.discard(i1 [[ANYC]])
29+
//
30+
// SPIRV: define spir_func void @{{.*}}test_vector{{.*}}(<4 x float> {{.*}} [[VALP:%.*]])
31+
// SPIRV: [[LOAD:%.*]] = load <4 x float>, ptr [[VALP]].addr, align 16
32+
// SPIRV-NEXT: [[FCMP:%.*]] = fcmp olt <4 x float> [[LOAD]], zeroinitializer
33+
// SPIRV-NEXT: [[ANYC:%.*]] = call i1 @llvm.spv.any.v4i1(<4 x i1> [[FCMP]])
34+
// SPIRV-NEXT: br i1 [[ANYC]], label %[[LTL:.*]], label %[[ENDL:.*]]
35+
// SPIRV: [[LTL]]: ; preds = %entry
36+
// SPIRV-NEXT: call void @llvm.spv.discard()
37+
// SPIRV-NEXT: br label %[[ENDL]]
38+
clip(Buf);
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -verify
2+
3+
4+
void test_arg_missing() {
5+
__builtin_hlsl_elementwise_clip();
6+
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
7+
}
8+
9+
void test_too_many_args(float p1, float p2) {
10+
__builtin_hlsl_elementwise_clip(p1, p2);
11+
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
12+
}
13+
14+
void test_first_arg_type_mismatch(bool p) {
15+
__builtin_hlsl_elementwise_clip(p);
16+
// expected-error@-1 {{invalid operand of type 'bool' where 'float' or a vector of such type is required}}
17+
}
18+
19+
void test_first_arg_type_mismatch_3(half3 p) {
20+
__builtin_hlsl_elementwise_clip(p);
21+
// expected-error@-1 {{invalid operand of type 'half3' (aka 'vector<half, 3>') where 'float' or a vector of such type is required}}
22+
}
23+
24+
void test_first_arg_type_mismatch_3(double p) {
25+
__builtin_hlsl_elementwise_clip(p);
26+
// expected-error@-1 {{invalid operand of type 'double' where 'float' or a vector of such type is required}}
27+
}

llvm/docs/SPIRVUsage.rst

+2
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na
149149
- Adds atomic min and max instruction on floating-point numbers.
150150
* - ``SPV_EXT_arithmetic_fence``
151151
- Adds an instruction that prevents fast-math optimizations between its argument and the expression that contains it.
152+
* - ``SPV_EXT_demote_to_helper_invocation``
153+
- Adds an instruction that demotes a fragment shader invocation to a helper invocation.
152154
* - ``SPV_INTEL_arbitrary_precision_integers``
153155
- Allows generating arbitrary width integer types.
154156
* - ``SPV_INTEL_bfloat16_conversion``

llvm/include/llvm/IR/IntrinsicsDirectX.td

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ def int_dx_step : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, L
102102
def int_dx_splitdouble : DefaultAttrsIntrinsic<[llvm_anyint_ty, LLVMMatchType<0>],
103103
[LLVMScalarOrSameVectorWidth<0, llvm_double_ty>], [IntrNoMem]>;
104104
def int_dx_radians : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
105+
def int_dx_discard : DefaultAttrsIntrinsic<[], [llvm_i1_ty], []>;
105106
def int_dx_firstbituhigh : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_anyint_ty], [IntrNoMem]>;
106107
def int_dx_firstbitshigh : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_anyint_ty], [IntrNoMem]>;
107108
}

llvm/include/llvm/IR/IntrinsicsSPIRV.td

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ let TargetPrefix = "spv" in {
9191
def int_spv_sign : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_any_ty], [IntrNoMem]>;
9292
def int_spv_radians : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
9393
def int_spv_group_memory_barrier_with_group_sync : DefaultAttrsIntrinsic<[], [], []>;
94+
def int_spv_discard : DefaultAttrsIntrinsic<[], [], []>;
9495
def int_spv_uclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
9596
def int_spv_sclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
9697
def int_spv_nclamp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;

llvm/lib/Target/DirectX/DXIL.td

+8
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,14 @@ def CheckAccessFullyMapped : DXILOp<71, checkAccessFullyMapped> {
770770
let stages = [Stages<DXIL1_0, [all_stages]>];
771771
}
772772

773+
def Discard : DXILOp<82, discard> {
774+
let Doc = "discard the current pixel";
775+
let LLVMIntrinsic = int_dx_discard;
776+
let arguments = [Int1Ty];
777+
let result = VoidTy;
778+
let stages = [Stages<DXIL1_0, [pixel]>];
779+
}
780+
773781
def ThreadId : DXILOp<93, threadId> {
774782
let Doc = "Reads the thread ID";
775783
let LLVMIntrinsic = int_dx_thread_id;

llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
3030
SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_min_max},
3131
{"SPV_EXT_arithmetic_fence",
3232
SPIRV::Extension::Extension::SPV_EXT_arithmetic_fence},
33+
{"SPV_EXT_demote_to_helper_invocation",
34+
SPIRV::Extension::Extension::SPV_EXT_demote_to_helper_invocation},
3335
{"SPV_INTEL_arbitrary_precision_integers",
3436
SPIRV::Extension::Extension::SPV_INTEL_arbitrary_precision_integers},
3537
{"SPV_INTEL_cache_controls",

llvm/lib/Target/SPIRV/SPIRVInstrInfo.td

+1
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ let isReturn = 1, hasDelaySlot = 0, isBarrier = 0, isTerminator = 1, isNotDuplic
639639
}
640640
def OpLifetimeStart: Op<256, (outs), (ins ID:$ptr, i32imm:$sz), "OpLifetimeStart $ptr, $sz">;
641641
def OpLifetimeStop: Op<257, (outs), (ins ID:$ptr, i32imm:$sz), "OpLifetimeStop $ptr, $sz">;
642+
def OpDemoteToHelperInvocation: SimpleOp<"OpDemoteToHelperInvocation", 5380>;
642643

643644
// 3.42.18 Atomic Instructions
644645

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
165165
unsigned comparisonOpcode, MachineInstr &I) const;
166166
bool selectCross(Register ResVReg, const SPIRVType *ResType,
167167
MachineInstr &I) const;
168+
bool selectDiscard(Register ResVReg, const SPIRVType *ResType,
169+
MachineInstr &I) const;
170+
168171
bool selectICmp(Register ResVReg, const SPIRVType *ResType,
169172
MachineInstr &I) const;
170173
bool selectFCmp(Register ResVReg, const SPIRVType *ResType,
@@ -2183,6 +2186,28 @@ bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg,
21832186
return MIB.constrainAllUses(TII, TRI, RBI);
21842187
}
21852188

2189+
bool SPIRVInstructionSelector::selectDiscard(Register ResVReg,
2190+
const SPIRVType *ResType,
2191+
MachineInstr &I) const {
2192+
2193+
unsigned Opcode;
2194+
2195+
if (STI.canUseExtension(
2196+
SPIRV::Extension::SPV_EXT_demote_to_helper_invocation) ||
2197+
STI.isAtLeastSPIRVVer(llvm::VersionTuple(1, 6))) {
2198+
Opcode = SPIRV::OpDemoteToHelperInvocation;
2199+
} else {
2200+
Opcode = SPIRV::OpKill;
2201+
// OpKill must be the last operation of any basic block.
2202+
MachineInstr *NextI = I.getNextNode();
2203+
NextI->removeFromParent();
2204+
}
2205+
2206+
MachineBasicBlock &BB = *I.getParent();
2207+
return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
2208+
.constrainAllUses(TII, TRI, RBI);
2209+
}
2210+
21862211
bool SPIRVInstructionSelector::selectCmp(Register ResVReg,
21872212
const SPIRVType *ResType,
21882213
unsigned CmpOpc,
@@ -2857,6 +2882,9 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
28572882
selectReadImageIntrinsic(ResVReg, ResType, I);
28582883
return true;
28592884
}
2885+
case Intrinsic::spv_discard: {
2886+
return selectDiscard(ResVReg, ResType, I);
2887+
}
28602888
default: {
28612889
std::string DiagMsg;
28622890
raw_string_ostream OS(DiagMsg);

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,8 @@ void RequirementHandler::initAvailableCapabilities(const SPIRVSubtarget &ST) {
633633
if (ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
634634
addAvailableCaps({Capability::DotProduct, Capability::DotProductInputAll,
635635
Capability::DotProductInput4x8Bit,
636-
Capability::DotProductInput4x8BitPacked});
636+
Capability::DotProductInput4x8BitPacked,
637+
Capability::DemoteToHelperInvocation});
637638

638639
// Add capabilities enabled by extensions.
639640
for (auto Extension : ST.getAllAvailableExtensions()) {
@@ -1419,6 +1420,19 @@ void addInstrRequirements(const MachineInstr &MI,
14191420
Reqs.addCapability(SPIRV::Capability::SplitBarrierINTEL);
14201421
}
14211422
break;
1423+
case SPIRV::OpKill: {
1424+
Reqs.addCapability(SPIRV::Capability::Shader);
1425+
} break;
1426+
case SPIRV::OpDemoteToHelperInvocation:
1427+
Reqs.addCapability(SPIRV::Capability::DemoteToHelperInvocation);
1428+
1429+
if (ST.canUseExtension(
1430+
SPIRV::Extension::SPV_EXT_demote_to_helper_invocation)) {
1431+
if (!ST.isAtLeastSPIRVVer(llvm::VersionTuple(1, 6)))
1432+
Reqs.addExtension(
1433+
SPIRV::Extension::SPV_EXT_demote_to_helper_invocation);
1434+
}
1435+
break;
14221436
case SPIRV::OpSDot:
14231437
case SPIRV::OpUDot:
14241438
AddDotProductRequirements(MI, Reqs, ST);

llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td

+1
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ defm VulkanMemoryModelDeviceScopeKHR : CapabilityOperand<5346, 0, 0, [], []>;
456456
defm ImageFootprintNV : CapabilityOperand<5282, 0, 0, [], []>;
457457
defm FragmentBarycentricNV : CapabilityOperand<5284, 0, 0, [], []>;
458458
defm ComputeDerivativeGroupQuadsNV : CapabilityOperand<5288, 0, 0, [], []>;
459+
defm DemoteToHelperInvocation : CapabilityOperand<5379, 0x10600, 0, [SPV_EXT_demote_to_helper_invocation], []>;
459460
defm ComputeDerivativeGroupLinearNV : CapabilityOperand<5350, 0, 0, [], []>;
460461
defm FragmentDensityEXT : CapabilityOperand<5291, 0, 0, [], [Shader]>;
461462
defm PhysicalStorageBufferAddressesEXT : CapabilityOperand<5347, 0, 0, [], [Shader]>;

llvm/test/CodeGen/DirectX/discard.ll

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
; RUN: opt -passes='function(scalarizer),module(dxil-op-lower,dxil-intrinsic-expansion)' -S -mtriple=dxil-pc-shadermodel6.3-pixel %s | FileCheck %s
2+
3+
; CHECK-LABEL: define void @test_scalar
4+
; CHECK: call void @dx.op.discard(i32 82, i1 %0)
5+
;
6+
define void @test_scalar(float noundef %p) #0 {
7+
entry:
8+
%0 = fcmp olt float %p, 0.000000e+00
9+
call void @llvm.dx.discard(i1 %0)
10+
ret void
11+
}
12+
13+
; CHECK-LABEL: define void @test_vector
14+
; CHECK: [[EXTR0:%.*]] = extractelement <4 x i1> [[INP:%.*]], i64 0
15+
; CHECK-NEXT: [[EXTR1:%.*]] = extractelement <4 x i1> [[INP:%.*]], i64 1
16+
; CHECK-NEXT: [[OR1:%.*]] = or i1 [[EXTR0]], [[EXTR1]]
17+
; CHECK-NEXT: [[EXTR2:%.*]] = extractelement <4 x i1> [[INP:%.*]], i64 2
18+
; CHECK-NEXT: [[OR2:%.*]] = or i1 [[OR1]], [[EXTR2]]
19+
; CHECK-NEXT: [[EXTR3:%.*]] = extractelement <4 x i1> [[INP:%.*]], i64 3
20+
; CHECK-NEXT: [[OR3:%.*]] = or i1 [[OR2]], [[EXTR3]]
21+
; CHECK-NEXT: call void @dx.op.discard(i32 82, i1 [[OR3]])
22+
;
23+
define void @test_vector(<4 x float> noundef %p) #0 {
24+
entry:
25+
%0 = fcmp olt <4 x float> %p, zeroinitializer
26+
%1 = call i1 @llvm.dx.any.v4i1(<4 x i1> %0)
27+
call void @llvm.dx.discard(i1 %1)
28+
ret void
29+
}
30+
31+
declare void @llvm.dx.discard(i1)
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
2+
3+
; DXIL operation discard does not support no bool overload type
4+
5+
; CHECK: invalid intrinsic signature
6+
; CHECK: call void @llvm.dx.discard(double %p)
7+
;
8+
define void @discard_double(double noundef %p) {
9+
entry:
10+
call void @llvm.dx.discard(double %p)
11+
ret void
12+
}

0 commit comments

Comments
 (0)