Skip to content

Commit 1c154ff

Browse files
authored
Fix check for (neg) zero for fpclass emulation (#2154)
We should compare not only to zero integer, but also 'negated' zero.
1 parent b6c49e3 commit 1c154ff

File tree

2 files changed

+45
-23
lines changed

2 files changed

+45
-23
lines changed

lib/SPIRV/SPIRVWriter.cpp

+34-8
Original file line numberDiff line numberDiff line change
@@ -4434,17 +4434,43 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
44344434
if (FPClass & fcZero) {
44354435
// Create zero integer constant and check for equality with bitcasted to
44364436
// int float value
4437+
auto SetUpCMPToZero = [&](SPIRVValue *BitCastToInt,
4438+
bool IsPositive) -> SPIRVValue * {
4439+
APInt ZeroInt = APInt::getZero(BitSize);
4440+
if (IsPositive) {
4441+
auto *ZeroConst =
4442+
transValue(Constant::getIntegerValue(IntOpLLVMTy, ZeroInt), BB);
4443+
return BM->addCmpInst(OpIEqual, ResTy, BitCastToInt, ZeroConst, BB);
4444+
}
4445+
// Created 'negated' zero
4446+
ZeroInt.setSignBit();
4447+
auto *NegZeroConst =
4448+
transValue(Constant::getIntegerValue(IntOpLLVMTy, ZeroInt), BB);
4449+
return BM->addCmpInst(OpIEqual, ResTy, BitCastToInt, NegZeroConst, BB);
4450+
};
44374451
auto *BitCastToInt =
44384452
BM->addUnaryInst(OpBitcast, OpSPIRVTy, InputFloat, BB);
4439-
auto *ZeroConst = transValue(
4440-
Constant::getIntegerValue(IntOpLLVMTy, APInt::getZero(BitSize)), BB);
4441-
auto *TestIsZero =
4442-
BM->addCmpInst(OpIEqual, ResTy, BitCastToInt, ZeroConst, BB);
4443-
if (FPClass & fcPosZero && FPClass & fcNegZero)
4453+
if (FPClass & fcPosZero && FPClass & fcNegZero) {
4454+
APInt ZeroInt = APInt::getZero(BitSize);
4455+
auto *ZeroConst =
4456+
transValue(Constant::getIntegerValue(IntOpLLVMTy, ZeroInt), BB);
4457+
APInt MaskToClearSignBit = APInt::getSignedMaxValue(BitSize);
4458+
auto *MaskToClearSignBitConst = transValue(
4459+
Constant::getIntegerValue(IntOpLLVMTy, MaskToClearSignBit), BB);
4460+
auto *BitwiseAndRes = BM->addBinaryInst(
4461+
OpBitwiseAnd, OpSPIRVTy, BitCastToInt, MaskToClearSignBitConst, BB);
4462+
auto *TestIsZero =
4463+
BM->addCmpInst(OpIEqual, ResTy, BitwiseAndRes, ZeroConst, BB);
44444464
ResultVec.emplace_back(GetInvertedTestIfNeeded(TestIsZero));
4445-
else
4446-
ResultVec.emplace_back(GetInvertedTestIfNeeded(
4447-
GetNegPosInstTest(TestIsZero, FPClass & fcNegZero)));
4465+
} else if (FPClass & fcPosZero) {
4466+
auto *TestIsPosZero =
4467+
SetUpCMPToZero(BitCastToInt, true /*'positive' zero*/);
4468+
ResultVec.emplace_back(GetInvertedTestIfNeeded(TestIsPosZero));
4469+
} else {
4470+
auto *TestIsNegZero =
4471+
SetUpCMPToZero(BitCastToInt, false /*'negated' zero*/);
4472+
ResultVec.emplace_back(GetInvertedTestIfNeeded(TestIsNegZero));
4473+
}
44484474
}
44494475
if (ResultVec.size() == 1)
44504476
return ResultVec.back();

test/llvm-intrinsics/fpclass.ll

+11-15
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)