Skip to content

Commit dbcbac9

Browse files
authored
IsSpecialFloat 16 bit implementation for isinf, isnan, and isfinite (microsoft#7700)
Add 16 bit overloads for isinf, isnan, and isfinite For SM6.8 and below; emulate these operations using IR by bitcasting the half to an i16 and performing comparisons to constants For SM6.9 and later; the 16 bit isSpecialFloat DXIL Op Class is used. Add tests showing for SM6.8 the emulation in DXIL for isinf, isnan, and isfinite Add tests showing for SM6.9 the 16 bit version of isSpecialFloat is used Add tests for SPIRV showing the 16 bit OpIsInf and OpIsNan are used isinf: Closes microsoft#7650, Closes microsoft#7645, Closes microsoft#7653 isnan: Closes microsoft#7651, Closes microsoft#7646, Closes microsoft#7654 isfinite: Closes microsoft#7652, Closes microsoft#7647, Closes microsoft#7655 Closes microsoft#7496
1 parent 39f1dc1 commit dbcbac9

File tree

8 files changed

+397
-8
lines changed

8 files changed

+397
-8
lines changed

lib/HLSL/DxilPreparePasses.cpp

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -640,13 +640,99 @@ class DxilFinalizeModule : public ModulePass {
640640
}
641641
}
642642

643+
static void emulateIsInf(Module &M, CallInst *CI) {
644+
IRBuilder<> Builder(CI);
645+
Value *Val = CI->getOperand(1);
646+
DXASSERT(Val->getType()->isHalfTy(),
647+
"Only emulates Half overload of IsInf");
648+
Type *IType = Type::getInt16Ty(M.getContext());
649+
Constant *PosInf = ConstantInt::get(IType, 0x7c00);
650+
Constant *NegInf = ConstantInt::get(IType, 0xfc00);
651+
652+
Value *IVal = Builder.CreateBitCast(Val, IType);
653+
Value *B1 = Builder.CreateICmpEQ(IVal, PosInf);
654+
Value *B2 = Builder.CreateICmpEQ(IVal, NegInf);
655+
Value *B3 = Builder.CreateOr(B1, B2);
656+
CI->replaceAllUsesWith(B3);
657+
CI->eraseFromParent();
658+
}
659+
660+
static void emulateIsNaN(Module &M, CallInst *CI) {
661+
IRBuilder<> Builder(CI);
662+
Value *Val = CI->getOperand(1);
663+
DXASSERT(Val->getType()->isHalfTy(),
664+
"Only emulates Half overload of IsNaN");
665+
Type *IType = Type::getInt16Ty(M.getContext());
666+
667+
Constant *ExpBitMask = ConstantInt::get(IType, 0x7c00);
668+
Constant *SigBitMask = ConstantInt::get(IType, 0x3ff);
669+
670+
Value *IVal = Builder.CreateBitCast(Val, IType);
671+
Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
672+
Value *B1 = Builder.CreateICmpEQ(Exp, ExpBitMask);
673+
674+
Value *Sig = Builder.CreateAnd(IVal, SigBitMask);
675+
Value *B2 = Builder.CreateICmpNE(Sig, ConstantInt::get(IType, 0));
676+
Value *B3 = Builder.CreateAnd(B1, B2);
677+
CI->replaceAllUsesWith(B3);
678+
CI->eraseFromParent();
679+
}
680+
681+
static void emulateIsFinite(Module &M, CallInst *CI) {
682+
IRBuilder<> Builder(CI);
683+
Value *Val = CI->getOperand(1);
684+
DXASSERT(Val->getType()->isHalfTy(),
685+
"Only emulates Half overload of IsFinite");
686+
Type *IType = Type::getInt16Ty(M.getContext());
687+
688+
Constant *ExpBitMask = ConstantInt::get(IType, 0x7c00);
689+
690+
Value *IVal = Builder.CreateBitCast(Val, IType);
691+
Value *Exp = Builder.CreateAnd(IVal, ExpBitMask);
692+
Value *B1 = Builder.CreateICmpNE(Exp, ExpBitMask);
693+
CI->replaceAllUsesWith(B1);
694+
CI->eraseFromParent();
695+
}
696+
697+
// Emulate IsSpecialFloat for Half pre sm6.9
698+
static void emulateIsSpecialFloat(Module &M, hlsl::OP *hlslOP) {
699+
// Finds the OpCodeClass that IsInf belongs to, IsSpecialFloat
700+
// This IsNan, IsFinite, and IsNormal also belong to this OpCodeClass
701+
for (auto Fn : hlslOP->GetOpFuncList(DXIL::OpCode::IsInf)) {
702+
Function *F = Fn.second;
703+
if (!F)
704+
continue;
705+
if (!F->getFunctionType()->getParamType(1)->isHalfTy())
706+
continue;
707+
708+
for (auto UserIt = F->user_begin(); UserIt != F->user_end();) {
709+
CallInst *CI = cast<CallInst>(*(UserIt++));
710+
711+
uint64_t OpKind = cast<ConstantInt>(CI->getOperand(0))->getZExtValue();
712+
switch (OpKind) {
713+
case (uint64_t)DXIL::OpCode::IsInf:
714+
emulateIsInf(M, CI);
715+
continue;
716+
case (uint64_t)DXIL::OpCode::IsNaN:
717+
emulateIsNaN(M, CI);
718+
continue;
719+
case (uint64_t)DXIL::OpCode::IsFinite:
720+
emulateIsFinite(M, CI);
721+
continue;
722+
default:
723+
continue;
724+
}
725+
}
726+
}
727+
}
728+
643729
void convertQuadVote(Module &M, hlsl::OP *hlslOP) {
644730
for (auto FnIt : hlslOP->GetOpFuncList(DXIL::OpCode::QuadVote)) {
645731
Function *F = FnIt.second;
646732
if (!F)
647733
continue;
648-
for (auto UserIt = F->user_begin(); UserIt != F->user_end();) {
649-
CallInst *CI = cast<CallInst>(*(UserIt++));
734+
for (auto User = F->user_begin(); User != F->user_end();) {
735+
CallInst *CI = cast<CallInst>(*(User++));
650736

651737
IRBuilder<> B(CI);
652738
DXASSERT_NOMSG(CI->getOperand(1)->getType() ==
@@ -838,6 +924,13 @@ class DxilFinalizeModule : public ModulePass {
838924
convertQuadVote(M, DM.GetOP());
839925
}
840926

927+
// Convert IsSpecialFloat intrinsics for half in SM6.8 and below
928+
// Because 16 bit overload of IsSpecialFloat is not available
929+
// until SM6.9 and later
930+
if (DXIL::CompareVersions(DxilMajor, DxilMinor, 1, 9) < 0) {
931+
emulateIsSpecialFloat(M, DM.GetOP());
932+
}
933+
841934
// Remove store undef output.
842935
RemoveStoreUndefOutput(M, hlslOP);
843936

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %dxc -T lib_6_8 -enable-16bit-types %s | FileCheck %s
2+
3+
// 31744 = 0x7c00, which corresponds to positive infinity
4+
// it is also used as a mask to get the exp bits of a half
5+
// -1024 = 0xfc00, which corresponds to negative infinity
6+
// 1023 = 0x3ff, and is used to mask the significand of a half
7+
8+
// CHECK-LABEL: test_isinf
9+
// CHECK: [[V1:%.*]] = bitcast half {{.*}} to i16
10+
// CHECK: [[V2:%.*]] = icmp eq i16 [[V1]], 31744
11+
// CHECK: [[V3:%.*]] = icmp eq i16 [[V1]], -1024
12+
// CHECK: [[V4:%.*]] = or i1 [[V2]], [[V3]]
13+
// CHECK: ret i1 [[V4]]
14+
export bool test_isinf(half h) {
15+
return isinf(h);
16+
}
17+
18+
// CHECK-LABEL: test_isnan
19+
// CHECK: [[V1:%.*]] = bitcast half {{.*}} to i16
20+
// CHECK: [[V2:%.*]] = and i16 [[V1]], 31744
21+
// CHECK: [[V3:%.*]] = icmp eq i16 [[V2]], 31744
22+
// CHECK: [[V4:%.*]] = and i16 [[V1]], 1023
23+
// CHECK: [[V5:%.*]] = icmp ne i16 [[V4]], 0
24+
// CHECK: [[V6:%.*]] = and i1 [[V3]], [[V5]]
25+
// CHECK: ret i1 [[V6]]
26+
export bool test_isnan(half h) {
27+
return isnan(h);
28+
}
29+
30+
// CHECK-LABEL: test_isfinite
31+
// CHECK: [[V1:%.*]] = bitcast half {{.*}} to i16
32+
// CHECK: [[V2:%.*]] = and i16 [[V1]], 31744
33+
// CHECK: [[V3:%.*]] = icmp ne i16 [[V2]], 31744
34+
// CHECK: ret i1 [[V3]]
35+
export bool test_isfinite(half h) {
36+
return isfinite(h);
37+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %dxc -T lib_6_9 -enable-16bit-types -DFUNC=isnan %s | FileCheck %s
2+
// RUN: %dxc -T lib_6_9 -enable-16bit-types -DFUNC=isinf %s | FileCheck %s
3+
// RUN: %dxc -T lib_6_9 -enable-16bit-types -DFUNC=isfinite %s | FileCheck %s
4+
5+
// CHECK-LABEL: test_func
6+
// CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 [[OP:[0-9]*]], half
7+
export bool test_func(half h) {
8+
return FUNC(h);
9+
}
10+
11+
// CHECK-LABEL: test_func2
12+
// CHECK: call <2 x i1> @dx.op.isSpecialFloat.v2f16(i32 [[OP:[0-9]*]], <2 x half>
13+
export bool2 test_func2(half2 h) {
14+
return FUNC(h);
15+
}
16+
17+
// CHECK-LABEL: test_func3
18+
// CHECK: call <3 x i1> @dx.op.isSpecialFloat.v3f16(i32 [[OP:[0-9]*]], <3 x half>
19+
export bool3 test_func3(half3 h) {
20+
return FUNC(h);
21+
}
22+
23+
// CHECK-LABEL: test_func4
24+
// CHECK: call <4 x i1> @dx.op.isSpecialFloat.v4f16(i32 [[OP:[0-9]*]], <4 x half>
25+
export bool4 test_func4(half4 h) {
26+
return FUNC(h);
27+
}

tools/clang/test/CodeGenDXIL/hlsl/types/longvec-trivial-isspecial-intrinsics.hlsl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ void main() {
3434

3535
// CHECK-NOT: extractelement
3636
// CHECK-NOT: insertelement
37-
// NOTE: This behavior will change with #7588
38-
// CHECK: [[tmp:%.*]] = fpext <[[NUM]] x half> [[hvec]] to <[[NUM]] x float>
39-
// CHECK: call <[[NUM]] x i1> @dx.op.isSpecialFloat.[[FTY]](i32 [[OP]], <[[NUM]] x float> [[tmp]])
37+
// CHECK: call <[[NUM]] x i1> @dx.op.isSpecialFloat.[[HTY]](i32 [[OP]], <[[NUM]] x half> [[hvec]])
4038
vector<bool, NUM> hRes = FUNC(hVec);
4139

4240
// CHECK-NOT: extractelement
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// RUN: %dxc -T ps_6_2 -enable-16bit-types -E main -fcgl %s -spirv | FileCheck %s
2+
3+
RWStructuredBuffer<half> buffer;
4+
RWStructuredBuffer<half2x3> buffer_mat;
5+
RWByteAddressBuffer byte_buffer;
6+
7+
// Since OpIsFinite needs the Kernel capability, translation is done using OpIsNan and OpIsInf.
8+
// isFinite = !(isNan || isInf)
9+
10+
void main() {
11+
half a;
12+
half4 b;
13+
half2x3 c;
14+
15+
// CHECK: [[a:%[0-9]+]] = OpLoad %half %a
16+
// CHECK-NEXT: [[a_isNan:%[0-9]+]] = OpIsNan %bool [[a]]
17+
// CHECK-NEXT: [[a_isInf:%[0-9]+]] = OpIsInf %bool [[a]]
18+
// CHECK-NEXT: [[a_NanOrInf:%[0-9]+]] = OpLogicalOr %bool [[a_isNan]] [[a_isInf]]
19+
// CHECK-NEXT: {{%[0-9]+}} = OpLogicalNot %bool [[a_NanOrInf]]
20+
bool isf_a = isfinite(a);
21+
22+
// CHECK: [[b:%[0-9]+]] = OpLoad %v4half %b
23+
// CHECK-NEXT: [[b_isNan:%[0-9]+]] = OpIsNan %v4bool [[b]]
24+
// CHECK-NEXT: [[b_isInf:%[0-9]+]] = OpIsInf %v4bool [[b]]
25+
// CHECK-NEXT: [[b_NanOrInf:%[0-9]+]] = OpLogicalOr %v4bool [[b_isNan]] [[b_isInf]]
26+
// CHECK-NEXT: {{%[0-9]+}} = OpLogicalNot %v4bool [[b_NanOrInf]]
27+
bool4 isf_b = isfinite(b);
28+
29+
// TODO: We can not translate the following since boolean matrices are currently not supported.
30+
// bool2x3 isf_c = isfinite(c);
31+
32+
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_half %buffer %int_0 %uint_0
33+
// CHECK: [[tmp:%[0-9]+]] = OpLoad %half [[ptr]]
34+
// CHECK: [[nan:%[0-9]+]] = OpIsNan %bool [[tmp]]
35+
// CHECK: [[inf:%[0-9]+]] = OpIsInf %bool [[tmp]]
36+
// CHECK: [[or:%[0-9]+]] = OpLogicalOr %bool [[nan]] [[inf]]
37+
// CHECK: [[res:%[0-9]+]] = OpLogicalNot %bool [[or]]
38+
// CHECK: OpStore %res [[res]]
39+
// CHECK: [[res:%[0-9]+]] = OpLoad %bool %res
40+
// CHECK: [[tmp:%[0-9]+]] = OpSelect %half [[res]] %half_0x1p_0 %half_0x0p_0
41+
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_half %buffer %int_0 %uint_0
42+
// CHECK: OpStore [[ptr]] [[tmp]]
43+
bool res = isfinite(buffer[0]);
44+
buffer[0] = (half)res;
45+
46+
// CHECK: [[c:%[0-9]+]] = OpLoad %mat2v3half %c
47+
// CHECK: [[r0:%[0-9]+]] = OpCompositeExtract %v3half [[c]] 0
48+
// CHECK: [[isnan_r0:%[0-9]+]] = OpIsNan %v3bool [[r0]]
49+
// CHECK: [[isinf_r0:%[0-9]+]] = OpIsInf %v3bool [[r0]]
50+
// CHECK: [[or_r0:%[0-9]+]] = OpLogicalOr %v3bool [[isnan_r0]] [[isinf_r0]]
51+
// CHECK: [[not_r0:%[0-9]+]] = OpLogicalNot %v3bool [[or_r0]]
52+
// CHECK: [[r1:%[0-9]+]] = OpCompositeExtract %v3half [[c]] 1
53+
// CHECK: [[isnan_r1:%[0-9]+]] = OpIsNan %v3bool [[r1]]
54+
// CHECK: [[isinf_r1:%[0-9]+]] = OpIsInf %v3bool [[r1]]
55+
// CHECK: [[or_r1:%[0-9]+]] = OpLogicalOr %v3bool [[isnan_r1]] [[isinf_r1]]
56+
// CHECK: [[not_r1:%[0-9]+]] = OpLogicalNot %v3bool [[or_r1]]
57+
// CHECK: [[tmp:%[0-9]+]] = OpCompositeConstruct %_arr_v3bool_uint_2 [[not_r0]] [[not_r1]]
58+
// CHECK: OpStore %isfinite_c [[tmp]]
59+
bool2x3 isfinite_c = isfinite(c);
60+
61+
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_mat2v3half %buffer_mat %int_0 %uint_0
62+
// CHECK: [[tmp:%[0-9]+]] = OpLoad %mat2v3half [[ptr]]
63+
// CHECK: [[r0:%[0-9]+]] = OpCompositeExtract %v3half [[tmp]] 0
64+
// CHECK: [[isnan_r0:%[0-9]+]] = OpIsNan %v3bool [[r0]]
65+
// CHECK: [[isinf_r0:%[0-9]+]] = OpIsInf %v3bool [[r0]]
66+
// CHECK: [[or_r0:%[0-9]+]] = OpLogicalOr %v3bool [[isnan_r0]] [[isinf_r0]]
67+
// CHECK: [[isfinite_r0:%[0-9]+]] = OpLogicalNot %v3bool [[or_r0]]
68+
// CHECK: [[r1:%[0-9]+]] = OpCompositeExtract %v3half [[tmp]] 1
69+
// CHECK: [[isnan_r1:%[0-9]+]] = OpIsNan %v3bool [[r1]]
70+
// CHECK: [[isinf_r1:%[0-9]+]] = OpIsInf %v3bool [[r1]]
71+
// CHECK: [[or_r1:%[0-9]+]] = OpLogicalOr %v3bool [[isnan_r1]] [[isinf_r1]]
72+
// CHECK: [[isfinite_r1:%[0-9]+]] = OpLogicalNot %v3bool [[or_r1]]
73+
// CHECK: [[tmp:%[0-9]+]] = OpCompositeConstruct %_arr_v3bool_uint_2 [[isfinite_r0]] [[isfinite_r1]]
74+
// CHECK: OpStore %isfinite_d [[tmp]]
75+
bool2x3 isfinite_d = isfinite(buffer_mat[0]);
76+
77+
// CHECK: [[addr:%[0-9]+]] = OpShiftRightLogical %uint %uint_0 %uint_2
78+
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_uint %byte_buffer %uint_0 [[addr]]
79+
// CHECK: [[tmpL:%[0-9]+]] = OpLoad %uint [[ptr]]
80+
// CHECK: [[tmpS:%[0-9]+]] = OpShiftRightLogical %uint [[tmpL]] %101
81+
// CHECK: [[tmp:%[0-9]+]] = OpUConvert %ushort [[tmpS]]
82+
// CHECK: [[val:%[0-9]+]] = OpBitcast %half [[tmp]]
83+
// CHECK: [[nan:%[0-9]+]] = OpIsNan %bool [[val]]
84+
// CHECK: [[inf:%[0-9]+]] = OpIsInf %bool [[val]]
85+
// CHECK: [[or:%[0-9]+]] = OpLogicalOr %bool [[nan]] [[inf]]
86+
// CHECK: [[res:%[0-9]+]] = OpLogicalNot %bool [[or]]
87+
// CHECK: OpStore %isfinite_e [[res]]
88+
bool isfinite_e = isfinite(byte_buffer.Load<half>(0));
89+
90+
// CHECK: [[res:%[0-9]+]] = OpLoad %bool %isfinite_e
91+
// CHECK: [[addr:%[0-9]+]] = OpShiftRightLogical %uint %uint_0 %uint_2
92+
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_uint %byte_buffer %uint_0 [[addr]]
93+
// CHECK: [[tmp:%[0-9]+]] = OpSelect %uint [[res]] %uint_1 %uint_0
94+
// CHECK: OpStore [[ptr]] [[tmp]]
95+
byte_buffer.Store(0, isfinite_e);
96+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// RUN: %dxc -T ps_6_2 -enable-16bit-types -E main -fcgl %s -spirv | FileCheck %s
2+
3+
RWStructuredBuffer<half> buffer;
4+
RWStructuredBuffer<half2x3> buffer_mat;
5+
RWByteAddressBuffer byte_buffer;
6+
7+
void main() {
8+
half a;
9+
half4 b;
10+
half2x3 c;
11+
12+
// CHECK: [[a:%[0-9]+]] = OpLoad %half %a
13+
// CHECK-NEXT: {{%[0-9]+}} = OpIsInf %bool [[a]]
14+
bool isinf_a = isinf(a);
15+
16+
// CHECK: [[b:%[0-9]+]] = OpLoad %v4half %b
17+
// CHECK-NEXT: {{%[0-9]+}} = OpIsInf %v4bool [[b]]
18+
bool4 isinf_b = isinf(b);
19+
20+
// TODO: We can not translate the following since boolean matrices are currently not supported.
21+
// bool2x3 isinf_c = isinf(c);
22+
23+
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_half %buffer %int_0 %uint_0
24+
// CHECK: [[tmp:%[0-9]+]] = OpLoad %half [[ptr]]
25+
// CHECK: [[res:%[0-9]+]] = OpIsInf %bool [[tmp]]
26+
// CHECK: OpStore %res [[res]]
27+
// CHECK: [[res:%[0-9]+]] = OpLoad %bool %res
28+
// CHECK: [[tmp:%[0-9]+]] = OpSelect %half [[res]] %half_0x1p_0 %half_0x0p_0
29+
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_half %buffer %int_0 %uint_0
30+
// CHECK: OpStore [[ptr]] [[tmp]]
31+
bool res = isinf(buffer[0]);
32+
buffer[0] = (half)res;
33+
34+
// CHECK: [[c:%[0-9]+]] = OpLoad %mat2v3half %c
35+
// CHECK: [[r0:%[0-9]+]] = OpCompositeExtract %v3half [[c]] 0
36+
// CHECK: [[isinf_r0:%[0-9]+]] = OpIsInf %v3bool [[r0]]
37+
// CHECK: [[r1:%[0-9]+]] = OpCompositeExtract %v3half [[c]] 1
38+
// CHECK: [[isinf_r1:%[0-9]+]] = OpIsInf %v3bool [[r1]]
39+
// CHECK: [[tmp:%[0-9]+]] = OpCompositeConstruct %_arr_v3bool_uint_2 [[isinf_r0]] [[isinf_r1]]
40+
// CHECK: OpStore %isinf_c [[tmp]]
41+
bool2x3 isinf_c = isinf(c);
42+
43+
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_mat2v3half %buffer_mat %int_0 %uint_0
44+
// CHECK: [[tmp:%[0-9]+]] = OpLoad %mat2v3half [[ptr]]
45+
// CHECK: [[r0:%[0-9]+]] = OpCompositeExtract %v3half [[tmp]] 0
46+
// CHECK: [[isinf_r0:%[0-9]+]] = OpIsInf %v3bool [[r0]]
47+
// CHECK: [[r1:%[0-9]+]] = OpCompositeExtract %v3half [[tmp]] 1
48+
// CHECK: [[isinf_r1:%[0-9]+]] = OpIsInf %v3bool [[r1]]
49+
// CHECK: [[tmp:%[0-9]+]] = OpCompositeConstruct %_arr_v3bool_uint_2 [[isinf_r0]] [[isinf_r1]]
50+
// CHECK: OpStore %isinf_d [[tmp]]
51+
bool2x3 isinf_d = isinf(buffer_mat[0]);
52+
53+
// CHECK: [[addr:%[0-9]+]] = OpShiftRightLogical %uint %uint_0 %uint_2
54+
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_uint %byte_buffer %uint_0 [[addr]]
55+
// CHECK: [[tmpL:%[0-9]+]] = OpLoad %uint [[ptr]]
56+
// CHECK: [[tmpS:%[0-9]+]] = OpShiftRightLogical %uint [[tmpL]] %80
57+
// CHECK: [[tmp:%[0-9]+]] = OpUConvert %ushort [[tmpS]]
58+
// CHECK: [[val:%[0-9]+]] = OpBitcast %half [[tmp]]
59+
// CHECK: [[res:%[0-9]+]] = OpIsInf %bool [[val]]
60+
// CHECK: OpStore %isinf_e [[res]]
61+
bool isinf_e = isinf(byte_buffer.Load<half>(0));
62+
63+
// CHECK: [[res:%[0-9]+]] = OpLoad %bool %isinf_e
64+
// CHECK: [[addr:%[0-9]+]] = OpShiftRightLogical %uint %uint_0 %uint_2
65+
// CHECK: [[ptr:%[0-9]+]] = OpAccessChain %_ptr_Uniform_uint %byte_buffer %uint_0 [[addr]]
66+
// CHECK: [[tmp:%[0-9]+]] = OpSelect %uint [[res]] %uint_1 %uint_0
67+
// CHECK: OpStore [[ptr]] [[tmp]]
68+
byte_buffer.Store(0, isinf_e);
69+
}

0 commit comments

Comments
 (0)