Skip to content

Commit 9ba5c58

Browse files
asudarsajsji
authored andcommitted
Fix check for (neg) zero for fpclass emulation (#2154)
We should compare not only to zero integer, but also 'negated' zero. Original commit: KhronosGroup/SPIRV-LLVM-Translator@1c154ff
1 parent 83b4cf1 commit 9ba5c58

File tree

2 files changed

+45
-23
lines changed

2 files changed

+45
-23
lines changed

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4498,17 +4498,43 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
44984498
if (FPClass & fcZero) {
44994499
// Create zero integer constant and check for equality with bitcasted to
45004500
// int float value
4501+
auto SetUpCMPToZero = [&](SPIRVValue *BitCastToInt,
4502+
bool IsPositive) -> SPIRVValue * {
4503+
APInt ZeroInt = APInt::getZero(BitSize);
4504+
if (IsPositive) {
4505+
auto *ZeroConst =
4506+
transValue(Constant::getIntegerValue(IntOpLLVMTy, ZeroInt), BB);
4507+
return BM->addCmpInst(OpIEqual, ResTy, BitCastToInt, ZeroConst, BB);
4508+
}
4509+
// Created 'negated' zero
4510+
ZeroInt.setSignBit();
4511+
auto *NegZeroConst =
4512+
transValue(Constant::getIntegerValue(IntOpLLVMTy, ZeroInt), BB);
4513+
return BM->addCmpInst(OpIEqual, ResTy, BitCastToInt, NegZeroConst, BB);
4514+
};
45014515
auto *BitCastToInt =
45024516
BM->addUnaryInst(OpBitcast, OpSPIRVTy, InputFloat, BB);
4503-
auto *ZeroConst = transValue(
4504-
Constant::getIntegerValue(IntOpLLVMTy, APInt::getZero(BitSize)), BB);
4505-
auto *TestIsZero =
4506-
BM->addCmpInst(OpIEqual, ResTy, BitCastToInt, ZeroConst, BB);
4507-
if (FPClass & fcPosZero && FPClass & fcNegZero)
4517+
if (FPClass & fcPosZero && FPClass & fcNegZero) {
4518+
APInt ZeroInt = APInt::getZero(BitSize);
4519+
auto *ZeroConst =
4520+
transValue(Constant::getIntegerValue(IntOpLLVMTy, ZeroInt), BB);
4521+
APInt MaskToClearSignBit = APInt::getSignedMaxValue(BitSize);
4522+
auto *MaskToClearSignBitConst = transValue(
4523+
Constant::getIntegerValue(IntOpLLVMTy, MaskToClearSignBit), BB);
4524+
auto *BitwiseAndRes = BM->addBinaryInst(
4525+
OpBitwiseAnd, OpSPIRVTy, BitCastToInt, MaskToClearSignBitConst, BB);
4526+
auto *TestIsZero =
4527+
BM->addCmpInst(OpIEqual, ResTy, BitwiseAndRes, ZeroConst, BB);
45084528
ResultVec.emplace_back(GetInvertedTestIfNeeded(TestIsZero));
4509-
else
4510-
ResultVec.emplace_back(GetInvertedTestIfNeeded(
4511-
GetNegPosInstTest(TestIsZero, FPClass & fcNegZero)));
4529+
} else if (FPClass & fcPosZero) {
4530+
auto *TestIsPosZero =
4531+
SetUpCMPToZero(BitCastToInt, true /*'positive' zero*/);
4532+
ResultVec.emplace_back(GetInvertedTestIfNeeded(TestIsPosZero));
4533+
} else {
4534+
auto *TestIsNegZero =
4535+
SetUpCMPToZero(BitCastToInt, false /*'negated' zero*/);
4536+
ResultVec.emplace_back(GetInvertedTestIfNeeded(TestIsNegZero));
4537+
}
45124538
}
45134539
if (ResultVec.size() == 1)
45144540
return ResultVec.back();

llvm-spirv/test/llvm-intrinsics/fpclass.ll

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
; CHECK-SPIRV-DAG: Constant [[#Int32Ty]] [[#QNanBitConst:]] 2143289344
2222
; CHECK-SPIRV-DAG: Constant [[#Int32Ty]] [[#MantissaConst:]] 8388607
2323
; CHECK-SPIRV-DAG: Constant [[#Int32Ty]] [[#ZeroConst:]] 0
24+
; CHECK-SPIRV-DAG: Constant [[#Int32Ty]] [[#MaskToClearSignBit:]] 2147483647
25+
; CHECK-SPIRV-DAG: Constant [[#Int32Ty]] [[#NegatedZeroConst:]] 2147483648
2426
; CHECK-SPIRV-DAG: Constant [[#Int64Ty]] [[#QNanBitConst64:]] 0 2146959360
2527
; CHECK-SPIRV-DAG: Constant [[#Int64Ty]] [[#MantissaConst64:]] 4294967295 1048575
2628
; CHECK-SPIRV-DAG: Constant [[#Int64Ty]] [[#ZeroConst64:]] 0 0
@@ -307,8 +309,9 @@ define i1 @test_class_zero(float %arg) {
307309
; CHECK-SPIRV-EMPTY:
308310
; CHECK-SPIRV-NEXT: Label
309311
; CHECK-SPIRV-NEXT: Bitcast [[#Int32Ty]] [[#BitCast:]] [[#Val]]
310-
; CHECK-SPIRV-NEXT: IEqual [[#BoolTy]] [[#Equal:]] [[#BitCast]] [[#ZeroConst]]
311-
; CHECK-SPIRV-NEXT: ReturnValue [[#Equal]]
312+
; CHECK-SPIRV-NEXT: BitwiseAnd [[#Int32Ty]] [[#BitwiseAndRes:]] [[#BitCast]] [[#MaskToClearSignBit]]
313+
; CHECK-SPIRV-NEXT: IEqual [[#BoolTy]] [[#EqualPos:]] [[#BitwiseAndRes]] [[#ZeroConst]]
314+
; CHECK-SPIRV-NEXT: ReturnValue [[#EqualPos]]
312315
%val = call i1 @llvm.is.fpclass.f32(float %arg, i32 96)
313316
ret i1 %val
314317
}
@@ -320,11 +323,8 @@ define i1 @test_class_poszero(float %arg) {
320323
; CHECK-SPIRV-EMPTY:
321324
; CHECK-SPIRV-NEXT: Label
322325
; CHECK-SPIRV-NEXT: Bitcast [[#Int32Ty]] [[#BitCast:]] [[#Val]]
323-
; CHECK-SPIRV-NEXT: IEqual [[#BoolTy]] [[#Equal:]] [[#BitCast]] [[#ZeroConst]]
324-
; CHECK-SPIRV-NEXT: SignBitSet [[#BoolTy]] [[#Sign:]] [[#Val]]
325-
; CHECK-SPIRV-NEXT: LogicalNot [[#BoolTy]] [[#Not:]] [[#Sign]]
326-
; CHECK-SPIRV-NEXT: LogicalAnd [[#BoolTy]] [[#And:]] [[#Not]] [[#Equal]]
327-
; CHECK-SPIRV-NEXT: ReturnValue [[#And]]
326+
; CHECK-SPIRV-NEXT: IEqual [[#BoolTy]] [[#Equal:]] [[#BitCast]] [[#ZeroConst]]
327+
; CHECK-SPIRV-NEXT: ReturnValue [[#Equal]]
328328
%val = call i1 @llvm.is.fpclass.f32(float %arg, i32 64)
329329
ret i1 %val
330330
}
@@ -336,10 +336,8 @@ define i1 @test_class_negzero(float %arg) {
336336
; CHECK-SPIRV-EMPTY:
337337
; CHECK-SPIRV-NEXT: Label
338338
; CHECK-SPIRV-NEXT: Bitcast [[#Int32Ty]] [[#BitCast:]] [[#Val]]
339-
; CHECK-SPIRV-NEXT: IEqual [[#BoolTy]] [[#Equal:]] [[#BitCast]] [[#ZeroConst]]
340-
; CHECK-SPIRV-NEXT: SignBitSet [[#BoolTy]] [[#Sign:]] [[#Val]]
341-
; CHECK-SPIRV-NEXT: LogicalAnd [[#BoolTy]] [[#And:]] [[#Sign]] [[#Equal]]
342-
; CHECK-SPIRV-NEXT: ReturnValue [[#And]]
339+
; CHECK-SPIRV-NEXT: IEqual [[#BoolTy]] [[#Equal:]] [[#BitCast]] [[#NegatedZeroConst]]
340+
; CHECK-SPIRV-NEXT: ReturnValue [[#Equal]]
343341
%val = call i1 @llvm.is.fpclass.f32(float %arg, i32 32)
344342
ret i1 %val
345343
}
@@ -383,11 +381,10 @@ define i1 @test_class_neginf_posnormal_negsubnormal_poszero_snan_f64(double %arg
383381
; CHECK-SPIRV-NEXT: LogicalAnd [[#BoolTy]] [[#And4:]] [[#Sign]] [[#Less]]
384382
; CHECK-SPIRV-NEXT: Bitcast [[#Int64Ty]] [[#BitCast3:]] [[#Val]]
385383
; CHECK-SPIRV-NEXT: IEqual [[#BoolTy]] [[#Equal:]] [[#BitCast3]] [[#ZeroConst64]]
386-
; CHECK-SPIRV-NEXT: LogicalAnd [[#BoolTy]] [[#And5:]] [[#Not2]] [[#Equal]]
387384
; CHECK-SPIRV-NEXT: LogicalOr [[#BoolTy]] [[#Or1:]] [[#And1]] [[#And2]]
388385
; CHECK-SPIRV-NEXT: LogicalOr [[#BoolTy]] [[#Or2:]] [[#Or1]] [[#And3]]
389386
; CHECK-SPIRV-NEXT: LogicalOr [[#BoolTy]] [[#Or3:]] [[#Or2]] [[#And4]]
390-
; CHECK-SPIRV-NEXT: LogicalOr [[#BoolTy]] [[#Or4:]] [[#Or3]] [[#And5]]
387+
; CHECK-SPIRV-NEXT: LogicalOr [[#BoolTy]] [[#Or4:]] [[#Or3]] [[#Equal]]
391388
; CHECK-SPIRV-NEXT: ReturnValue [[#Or4]]
392389
%val = call i1 @llvm.is.fpclass.f64(double %arg, i32 341)
393390
ret i1 %val
@@ -416,11 +413,10 @@ define <2 x i1> @test_class_neginf_posnormal_negsubnormal_poszero_snan_v2f16(<2
416413
; CHECK-SPIRV-NEXT: LogicalAnd [[#VecBoolTy]] [[#And4:]] [[#Sign]] [[#Less]]
417414
; CHECK-SPIRV-NEXT: Bitcast [[#Int16VecTy]] [[#BitCast3:]] [[#Val]]
418415
; CHECK-SPIRV-NEXT: IEqual [[#VecBoolTy]] [[#Equal:]] [[#BitCast3]] [[#ZeroConst16]]
419-
; CHECK-SPIRV-NEXT: LogicalAnd [[#VecBoolTy]] [[#And5:]] [[#Not2]] [[#Equal]]
420416
; CHECK-SPIRV-NEXT: LogicalOr [[#VecBoolTy]] [[#Or1:]] [[#And1]] [[#And2]]
421417
; CHECK-SPIRV-NEXT: LogicalOr [[#VecBoolTy]] [[#Or2:]] [[#Or1]] [[#And3]]
422418
; CHECK-SPIRV-NEXT: LogicalOr [[#VecBoolTy]] [[#Or3:]] [[#Or2]] [[#And4]]
423-
; CHECK-SPIRV-NEXT: LogicalOr [[#VecBoolTy]] [[#Or4:]] [[#Or3]] [[#And5]]
419+
; CHECK-SPIRV-NEXT: LogicalOr [[#VecBoolTy]] [[#Or4:]] [[#Or3]] [[#Equal]]
424420
; CHECK-SPIRV-NEXT: ReturnValue [[#Or4]]
425421
%val = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> %arg, i32 341)
426422
ret <2 x i1> %val

0 commit comments

Comments
 (0)