Skip to content

Commit

Permalink
[ValueTracking] Fix incorrect inferrence about the signbit of sqrt (l…
Browse files Browse the repository at this point in the history
…lvm#92510)

According to IEEE Std 754-2019, `sqrt` returns nan when the input is
negative (except for -0). In this case, we cannot make assumptions about
sign bit of the result.

Fixes llvm#92217
  • Loading branch information
dtcxzyw authored May 20, 2024
1 parent 36899d6 commit 04ae6e6
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 5 deletions.
5 changes: 1 addition & 4 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4940,11 +4940,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
// subnormal input could produce a negative zero output.
const Function *F = II->getFunction();
if (Q.IIQ.hasNoSignedZeros(II) ||
(F && KnownSrc.isKnownNeverLogicalNegZero(*F, II->getType()))) {
(F && KnownSrc.isKnownNeverLogicalNegZero(*F, II->getType())))
Known.knownNot(fcNegZero);
if (KnownSrc.isKnownNeverNaN())
Known.signBitMustBeZero();
}

break;
}
Expand Down
38 changes: 38 additions & 0 deletions llvm/test/Transforms/InstCombine/known-bits.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1698,6 +1698,44 @@ define i32 @test_none(float nofpclass(all) %x) {
ret i32 %and
}

; We cannot make assumptions about the sign of result of sqrt
; when the input is a negative value (except for -0).
define i1 @pr92217() {
; CHECK-LABEL: @pr92217(
; CHECK-NEXT: [[X:%.*]] = call float @llvm.sqrt.f32(float 0xC6DEBE9E60000000)
; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X]] to i32
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[Y]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%x = call float @llvm.sqrt.f32(float 0xC6DEBE9E60000000)
%y = bitcast float %x to i32
%cmp = icmp slt i32 %y, 0
ret i1 %cmp
}

define i1 @sqrt_negative_input(float nofpclass(nan zero pnorm psub pinf) %a) {
; CHECK-LABEL: @sqrt_negative_input(
; CHECK-NEXT: [[X:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X]] to i32
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[Y]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%x = call float @llvm.sqrt.f32(float %a)
%y = bitcast float %x to i32
%cmp = icmp slt i32 %y, 0
ret i1 %cmp
}

define i1 @sqrt_negative_input_nnan(float nofpclass(nan zero pnorm psub pinf) %a) {
; CHECK-LABEL: @sqrt_negative_input_nnan(
; CHECK-NEXT: ret i1 false
;
%x = call nnan float @llvm.sqrt.f32(float %a)
%y = bitcast float %x to i32
%cmp = icmp slt i32 %y, 0
ret i1 %cmp
}

define i8 @test_icmp_add(i8 %n, i8 %n2, i8 %other) {
; CHECK-LABEL: @test_icmp_add(
; CHECK-NEXT: entry:
Expand Down
2 changes: 1 addition & 1 deletion llvm/unittests/Analysis/ValueTrackingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2005,7 +2005,7 @@ TEST_F(ComputeKnownFPClassTest, SqrtNszSignBit) {
computeKnownFPClass(A4, M->getDataLayout(), fcAllFlags, 0, nullptr,
nullptr, nullptr, nullptr, /*UseInstrInfo=*/true);
EXPECT_EQ(fcPositive | fcQNan, UseInstrInfoNSZNoNan.KnownFPClasses);
EXPECT_EQ(false, UseInstrInfoNSZNoNan.SignBit);
EXPECT_EQ(std::nullopt, UseInstrInfoNSZNoNan.SignBit);

KnownFPClass NoUseInstrInfoNSZNoNan =
computeKnownFPClass(A4, M->getDataLayout(), fcAllFlags, 0, nullptr,
Expand Down

0 comments on commit 04ae6e6

Please sign in to comment.