forked from OSchip/llvm-project
[ValueTracking] Implement SignBitMustBeZero correctly for sqrt.
Summary: Previously we assumed that the result of sqrt(x) always had 0 as its sign bit. But sqrt(-0) == -0. Reviewers: hfinkel, efriedma, sanjoy Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D28928 llvm-svn: 293115
This commit is contained in:
parent
a31f9dd69a
commit
7e3184c412
|
@ -2645,7 +2645,8 @@ static bool cannotBeOrderedLessThanZeroImpl(const Value *V,
|
||||||
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
|
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
|
||||||
Depth + 1);
|
Depth + 1);
|
||||||
case Instruction::Call:
|
case Instruction::Call:
|
||||||
Intrinsic::ID IID = getIntrinsicForCallSite(cast<CallInst>(I), TLI);
|
const auto *CI = cast<CallInst>(I);
|
||||||
|
Intrinsic::ID IID = getIntrinsicForCallSite(CI, TLI);
|
||||||
switch (IID) {
|
switch (IID) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -2662,12 +2663,19 @@ static bool cannotBeOrderedLessThanZeroImpl(const Value *V,
|
||||||
case Intrinsic::exp:
|
case Intrinsic::exp:
|
||||||
case Intrinsic::exp2:
|
case Intrinsic::exp2:
|
||||||
case Intrinsic::fabs:
|
case Intrinsic::fabs:
|
||||||
case Intrinsic::sqrt:
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case Intrinsic::sqrt:
|
||||||
|
// sqrt(x) is always >= -0 or NaN. Moreover, sqrt(x) == -0 iff x == -0.
|
||||||
|
if (!SignBitOnly)
|
||||||
|
return true;
|
||||||
|
return CI->hasNoNaNs() && (CI->hasNoSignedZeros() ||
|
||||||
|
CannotBeNegativeZero(CI->getOperand(0), TLI));
|
||||||
|
|
||||||
case Intrinsic::powi:
|
case Intrinsic::powi:
|
||||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
if (ConstantInt *Exponent = dyn_cast<ConstantInt>(I->getOperand(1))) {
|
||||||
// powi(x,n) is non-negative if n is even.
|
// powi(x,n) is non-negative if n is even.
|
||||||
if (CI->getBitWidth() <= 64 && CI->getSExtValue() % 2u == 0)
|
if (Exponent->getBitWidth() <= 64 && Exponent->getSExtValue() % 2u == 0)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
|
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
|
||||||
|
|
|
@ -104,6 +104,7 @@ define float @PR22688(float %x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
declare float @llvm.fabs.f32(float)
|
declare float @llvm.fabs.f32(float)
|
||||||
|
declare float @llvm.sqrt.f32(float)
|
||||||
|
|
||||||
; CHECK-LABEL: @fabs_select_positive_constants(
|
; CHECK-LABEL: @fabs_select_positive_constants(
|
||||||
; CHECK: %select = select i1 %cmp, float 1.000000e+00, float 2.000000e+00
|
; CHECK: %select = select i1 %cmp, float 1.000000e+00, float 2.000000e+00
|
||||||
|
@ -195,3 +196,56 @@ define float @fabs_select_negnan_zero(float addrspace(1)* %out, i32 %c) {
|
||||||
%fabs = call float @llvm.fabs.f32(float %select)
|
%fabs = call float @llvm.fabs.f32(float %select)
|
||||||
ret float %fabs
|
ret float %fabs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @fabs_sqrt
|
||||||
|
; CHECK: call float @llvm.sqrt.f32
|
||||||
|
; CHECK: call float @llvm.fabs.f32
|
||||||
|
define float @fabs_sqrt(float %a) {
|
||||||
|
; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with
|
||||||
|
; an arbitrary sign bit.
|
||||||
|
%sqrt = call float @llvm.sqrt.f32(float %a)
|
||||||
|
%fabs = call float @llvm.fabs.f32(float %sqrt)
|
||||||
|
ret float %fabs
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @fabs_sqrt_nnan
|
||||||
|
; CHECK: call nnan float @llvm.sqrt.f32
|
||||||
|
; CHECK: call float @llvm.fabs.f32
|
||||||
|
define float @fabs_sqrt_nnan(float %a) {
|
||||||
|
; The fabs can't be eliminated because the nnan sqrt may still return -0.
|
||||||
|
%sqrt = call nnan float @llvm.sqrt.f32(float %a)
|
||||||
|
%fabs = call float @llvm.fabs.f32(float %sqrt)
|
||||||
|
ret float %fabs
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @fabs_sqrt_nsz
|
||||||
|
; CHECK: call nsz float @llvm.sqrt.f32
|
||||||
|
; CHECK: call float @llvm.fabs.f32
|
||||||
|
define float @fabs_sqrt_nsz(float %a) {
|
||||||
|
; The fabs can't be eliminated because the nsz sqrt may still return NaN.
|
||||||
|
%sqrt = call nsz float @llvm.sqrt.f32(float %a)
|
||||||
|
%fabs = call float @llvm.fabs.f32(float %sqrt)
|
||||||
|
ret float %fabs
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @fabs_sqrt_nnan_nsz
|
||||||
|
; CHECK: call nnan nsz float @llvm.sqrt.f32
|
||||||
|
; CHECK-NOT: call float @llvm.fabs.f32
|
||||||
|
define float @fabs_sqrt_nnan_nsz(float %a) {
|
||||||
|
; The fabs can be eliminated because we're nsz and nnan.
|
||||||
|
%sqrt = call nnan nsz float @llvm.sqrt.f32(float %a)
|
||||||
|
%fabs = call float @llvm.fabs.f32(float %sqrt)
|
||||||
|
ret float %fabs
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @fabs_sqrt_nnan_fabs
|
||||||
|
; CHECK: call float @llvm.fabs.f32
|
||||||
|
; CHECK: call nnan float @llvm.sqrt.f32
|
||||||
|
; CHECK-NOT: call float @llvm.fabs.f32
|
||||||
|
define float @fabs_sqrt_nnan_fabs(float %a) {
|
||||||
|
; The second fabs can be eliminated because the operand to sqrt cannot be -0.
|
||||||
|
%b = call float @llvm.fabs.f32(float %a)
|
||||||
|
%sqrt = call nnan float @llvm.sqrt.f32(float %b)
|
||||||
|
%fabs = call float @llvm.fabs.f32(float %sqrt)
|
||||||
|
ret float %fabs
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue