-
Notifications
You must be signed in to change notification settings - Fork 15.7k
InstCombine: Handle log/log2/log10 in SimplifyDemandedFPClass #173881
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/arsenm/instcombine/add-baseline-test-simplifydemandedfpclass-log
Are you sure you want to change the base?
Conversation
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
@llvm/pr-subscribers-llvm-adt @llvm/pr-subscribers-llvm-support Author: Matt Arsenault (arsenm) ChangesFull diff: https://github.com/llvm/llvm-project/pull/173881.diff 6 Files Affected:
diff --git a/llvm/include/llvm/ADT/FloatingPointMode.h b/llvm/include/llvm/ADT/FloatingPointMode.h
index a9702c65e631f..0605e0b4f4cf9 100644
--- a/llvm/include/llvm/ADT/FloatingPointMode.h
+++ b/llvm/include/llvm/ADT/FloatingPointMode.h
@@ -153,6 +153,11 @@ struct DenormalMode {
Input == DenormalModeKind::PositiveZero;
}
+ /// Return true if input denormals may be implicitly treated as 0.
+ constexpr bool inputsMayBeZero() const {
+ return inputsAreZero() || Input == DenormalMode::Dynamic;
+ }
+
/// Return true if output denormals should be flushed to 0.
constexpr bool outputsAreZero() const {
return Output == DenormalModeKind::PreserveSign ||
diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h
index 62df87ad8a67e..07d74f2867089 100644
--- a/llvm/include/llvm/Support/KnownFPClass.h
+++ b/llvm/include/llvm/Support/KnownFPClass.h
@@ -263,6 +263,10 @@ struct KnownFPClass {
LLVM_ABI void propagateCanonicalizingSrc(const KnownFPClass &Src,
DenormalMode Mode);
+ /// Propagate known class for log/log2/log10
+ static LLVM_ABI KnownFPClass
+ log(const KnownFPClass &Src, DenormalMode Mode = DenormalMode::getDynamic());
+
void resetAll() { *this = KnownFPClass(); }
};
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index cddd6f9c25074..bac863cb3c67c 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5391,22 +5391,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs,
KnownSrc, Q, Depth + 1);
- if (KnownSrc.isKnownNeverPosInfinity())
- Known.knownNot(fcPosInf);
-
- if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
- Known.knownNot(fcNan);
-
const Function *F = II->getFunction();
- if (!F)
- break;
-
- const fltSemantics &FltSem = EltTy->getFltSemantics();
- DenormalMode Mode = F->getDenormalMode(FltSem);
-
- if (KnownSrc.isKnownNeverLogicalZero(Mode))
- Known.knownNot(fcNegInf);
-
+ DenormalMode Mode = F ? F->getDenormalMode(EltTy->getFltSemantics())
+ : DenormalMode::getDynamic();
+ Known = KnownFPClass::log(KnownSrc, Mode);
break;
}
case Intrinsic::powi: {
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 125bee00c38ff..ff98908fdb2c4 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -226,3 +226,20 @@ void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src,
propagateDenormal(Src, Mode);
propagateNaN(Src, /*PreserveSign=*/true);
}
+
+KnownFPClass KnownFPClass::log(const KnownFPClass &KnownSrc,
+ DenormalMode Mode) {
+ KnownFPClass Known;
+ Known.knownNot(fcNegZero);
+
+ if (KnownSrc.isKnownNeverPosInfinity())
+ Known.knownNot(fcPosInf);
+
+ if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
+ Known.knownNot(fcNan);
+
+ if (KnownSrc.isKnownNeverLogicalZero(Mode))
+ Known.knownNot(fcNegInf);
+
+ return Known;
+}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 33ece6c2b69d8..3cb4c629b9108 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2202,6 +2202,43 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
Known = KnownFPClass::exp(KnownSrc);
break;
}
+ case Intrinsic::log:
+ case Intrinsic::log2:
+ case Intrinsic::log10: {
+ FPClassTest DemandedSrcMask = DemandedMask & (fcNan | fcPosInf);
+
+ Type *EltTy = VTy->getScalarType();
+ DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+
+ // log(x < 0) = nan
+ if (DemandedMask & fcNan)
+ DemandedSrcMask |= (fcNegative & ~fcNegZero);
+
+ // log(0) = -inf
+ if (DemandedMask & fcNegInf) {
+ DemandedSrcMask |= fcZero;
+
+ // No value produces subnormal result.
+ if (Mode.inputsMayBeZero())
+ DemandedSrcMask |= fcSubnormal;
+ }
+
+ if (DemandedMask & fcNormal)
+ DemandedSrcMask |= fcNormal | fcSubnormal;
+
+ // log(1) = 0
+ if (DemandedMask & fcZero)
+ DemandedSrcMask |= fcPosNormal;
+
+ KnownFPClass KnownSrc;
+ if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
+ return I;
+
+ Known = KnownFPClass::log(KnownSrc, Mode);
+
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ }
case Intrinsic::canonicalize: {
Type *EltTy = VTy->getScalarType();
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-log.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-log.ll
index d6f2cab6687ab..87973fa36b478 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-log.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-log.ll
@@ -5,8 +5,7 @@
define nofpclass(inf norm sub zero) float @ret_nofpclass_only_nan__log(float %unknown) {
; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_nofpclass_only_nan__log(
; CHECK-SAME: float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
-; CHECK-NEXT: ret float [[RESULT]]
+; CHECK-NEXT: ret float 0x7FF8000000000000
;
%result = call float @llvm.log.f32(float %unknown)
ret float %result
@@ -16,8 +15,7 @@ define nofpclass(inf norm sub zero) float @ret_nofpclass_only_nan__log(float %un
define nofpclass(nan inf norm sub) float @ret_nofpclass_only_zero__log(float %unknown) {
; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_nofpclass_only_zero__log(
; CHECK-SAME: float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
-; CHECK-NEXT: ret float [[RESULT]]
+; CHECK-NEXT: ret float 0.000000e+00
;
%result = call float @llvm.log.f32(float %unknown)
ret float %result
@@ -57,7 +55,7 @@ define nofpclass(nan pinf norm sub zero) float @ret_nofpclass_only_ninf__log(flo
define nofpclass(nan inf norm sub pzero) float @ret_nofpclass_only_nzero__log(float %unknown) {
; CHECK-LABEL: define nofpclass(nan inf pzero sub norm) float @ret_nofpclass_only_nzero__log(
; CHECK-SAME: float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: ret float -0.000000e+00
+; CHECK-NEXT: ret float poison
;
%result = call float @llvm.log.f32(float %unknown)
ret float %result
@@ -87,8 +85,7 @@ define nofpclass(norm sub zero) float @ret_nofpclass_only_inf_nan__log(float %un
define nofpclass(ninf) float @ret_nofpclass_ninf_log(i1 %cond, float %x) {
; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf_log(
; CHECK-SAME: i1 [[COND:%.*]], float [[X:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0.000000e+00, float [[X]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[X]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float 0.0, float %x
@@ -100,8 +97,7 @@ define nofpclass(ninf) float @ret_nofpclass_ninf_log(i1 %cond, float %x) {
define nofpclass(pinf) float @ret_nofpclass_pinf_log_select_inf_or_unknown(i1 %cond, float %unknown) {
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf_log_select_inf_or_unknown(
; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[UNKNOWN]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float 0x7ff0000000000000, float %unknown
@@ -113,8 +109,7 @@ define nofpclass(pinf) float @ret_nofpclass_pinf_log_select_inf_or_unknown(i1 %c
define nofpclass(pinf) float @ret_nofpclass_pinf_log2_select_inf_or_unknown(i1 %cond, float %unknown) {
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf_log2_select_inf_or_unknown(
; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[UNKNOWN]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log2.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log2.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float 0x7ff0000000000000, float %unknown
@@ -126,8 +121,7 @@ define nofpclass(pinf) float @ret_nofpclass_pinf_log2_select_inf_or_unknown(i1 %
define nofpclass(pinf) float @ret_nofpclass_pinf_log10_select_inf_or_unknown(i1 %cond, float %unknown) {
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf_log10_select_inf_or_unknown(
; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[UNKNOWN]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log10.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log10.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float 0x7ff0000000000000, float %unknown
@@ -139,8 +133,7 @@ define nofpclass(pinf) float @ret_nofpclass_pinf_log10_select_inf_or_unknown(i1
define nofpclass(ninf norm zero) float @ret_nofpclass_nan_or_sub__log_select__finite_positive__unknown(i1 %cond, float nofpclass(inf nnorm nsub nan) %must.be.finite.positive, float %unknown) {
; CHECK-LABEL: define nofpclass(ninf zero norm) float @ret_nofpclass_nan_or_sub__log_select__finite_positive__unknown(
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf nsub nnorm) [[MUST_BE_FINITE_POSITIVE:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MUST_BE_FINITE_POSITIVE]], float [[UNKNOWN]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float %must.be.finite.positive, float %unknown
@@ -165,8 +158,7 @@ define nofpclass(ninf norm zero) float @ret_nofpclass_nan_or_sub__log_select__fi
define nofpclass(pinf nan norm zero) float @ret_ninf_or_sub__log_select__pinf_or_sub_orzero__else_not0__ieee(i1 %cond, float nofpclass(ninf norm nan) %must.be.pinf.or.sub.or.zero, float nofpclass(zero) %not.zero) {
; CHECK-LABEL: define nofpclass(nan pinf zero norm) float @ret_ninf_or_sub__log_select__pinf_or_sub_orzero__else_not0__ieee(
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan ninf norm) [[MUST_BE_PINF_OR_SUB_OR_ZERO:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MUST_BE_PINF_OR_SUB_OR_ZERO]], float [[NOT_ZERO]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[MUST_BE_PINF_OR_SUB_OR_ZERO]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float %must.be.pinf.or.sub.or.zero, float %not.zero
@@ -204,8 +196,7 @@ define nofpclass(pinf nan norm zero) float @ret_ninf_or_sub__log_select__pinf_or
define nofpclass(inf nan pnorm sub zero) float @ret_only_nnorm__log__select_unknown_or_infnan(i1 %cond, float %unknown, float nofpclass(norm sub zero) %b) {
; CHECK-LABEL: define nofpclass(nan inf zero sub pnorm) float @ret_only_nnorm__log__select_unknown_or_infnan(
; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(zero sub norm) [[B:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[B]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float %unknown, float %b
@@ -217,8 +208,7 @@ define nofpclass(inf nan pnorm sub zero) float @ret_only_nnorm__log__select_unkn
define nofpclass(inf nan nnorm sub zero) float @ret_only_pnorm__log__select_unknown_or_infnan(i1 %cond, float %unknown, float nofpclass(norm sub zero) %b) {
; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @ret_only_pnorm__log__select_unknown_or_infnan(
; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(zero sub norm) [[B:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[B]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float %unknown, float %b
@@ -243,8 +233,7 @@ define nofpclass(nan inf norm) float @ret_only_zero_sub__log__select_pnormnan_or
define nofpclass(nan inf norm) float @ret_only_zero_sub__log__select_nnormnan_or_unknown(i1 %cond, float nofpclass(inf sub zero pnorm) %nnorm.or.nan, float %b) {
; CHECK-LABEL: define nofpclass(nan inf norm) float @ret_only_zero_sub__log__select_nnormnan_or_unknown(
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub pnorm) [[NNORM_OR_NAN:%.*]], float [[B:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[NNORM_OR_NAN]], float [[B]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[B]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float %nnorm.or.nan, float %b
|
|
@llvm/pr-subscribers-llvm-transforms Author: Matt Arsenault (arsenm) ChangesFull diff: https://github.com/llvm/llvm-project/pull/173881.diff 6 Files Affected:
diff --git a/llvm/include/llvm/ADT/FloatingPointMode.h b/llvm/include/llvm/ADT/FloatingPointMode.h
index a9702c65e631f..0605e0b4f4cf9 100644
--- a/llvm/include/llvm/ADT/FloatingPointMode.h
+++ b/llvm/include/llvm/ADT/FloatingPointMode.h
@@ -153,6 +153,11 @@ struct DenormalMode {
Input == DenormalModeKind::PositiveZero;
}
+ /// Return true if input denormals may be implicitly treated as 0.
+ constexpr bool inputsMayBeZero() const {
+ return inputsAreZero() || Input == DenormalMode::Dynamic;
+ }
+
/// Return true if output denormals should be flushed to 0.
constexpr bool outputsAreZero() const {
return Output == DenormalModeKind::PreserveSign ||
diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h
index 62df87ad8a67e..07d74f2867089 100644
--- a/llvm/include/llvm/Support/KnownFPClass.h
+++ b/llvm/include/llvm/Support/KnownFPClass.h
@@ -263,6 +263,10 @@ struct KnownFPClass {
LLVM_ABI void propagateCanonicalizingSrc(const KnownFPClass &Src,
DenormalMode Mode);
+ /// Propagate known class for log/log2/log10
+ static LLVM_ABI KnownFPClass
+ log(const KnownFPClass &Src, DenormalMode Mode = DenormalMode::getDynamic());
+
void resetAll() { *this = KnownFPClass(); }
};
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index cddd6f9c25074..bac863cb3c67c 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5391,22 +5391,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs,
KnownSrc, Q, Depth + 1);
- if (KnownSrc.isKnownNeverPosInfinity())
- Known.knownNot(fcPosInf);
-
- if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
- Known.knownNot(fcNan);
-
const Function *F = II->getFunction();
- if (!F)
- break;
-
- const fltSemantics &FltSem = EltTy->getFltSemantics();
- DenormalMode Mode = F->getDenormalMode(FltSem);
-
- if (KnownSrc.isKnownNeverLogicalZero(Mode))
- Known.knownNot(fcNegInf);
-
+ DenormalMode Mode = F ? F->getDenormalMode(EltTy->getFltSemantics())
+ : DenormalMode::getDynamic();
+ Known = KnownFPClass::log(KnownSrc, Mode);
break;
}
case Intrinsic::powi: {
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 125bee00c38ff..ff98908fdb2c4 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -226,3 +226,20 @@ void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src,
propagateDenormal(Src, Mode);
propagateNaN(Src, /*PreserveSign=*/true);
}
+
+KnownFPClass KnownFPClass::log(const KnownFPClass &KnownSrc,
+ DenormalMode Mode) {
+ KnownFPClass Known;
+ Known.knownNot(fcNegZero);
+
+ if (KnownSrc.isKnownNeverPosInfinity())
+ Known.knownNot(fcPosInf);
+
+ if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
+ Known.knownNot(fcNan);
+
+ if (KnownSrc.isKnownNeverLogicalZero(Mode))
+ Known.knownNot(fcNegInf);
+
+ return Known;
+}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 33ece6c2b69d8..3cb4c629b9108 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2202,6 +2202,43 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
Known = KnownFPClass::exp(KnownSrc);
break;
}
+ case Intrinsic::log:
+ case Intrinsic::log2:
+ case Intrinsic::log10: {
+ FPClassTest DemandedSrcMask = DemandedMask & (fcNan | fcPosInf);
+
+ Type *EltTy = VTy->getScalarType();
+ DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+
+ // log(x < 0) = nan
+ if (DemandedMask & fcNan)
+ DemandedSrcMask |= (fcNegative & ~fcNegZero);
+
+ // log(0) = -inf
+ if (DemandedMask & fcNegInf) {
+ DemandedSrcMask |= fcZero;
+
+ // No value produces subnormal result.
+ if (Mode.inputsMayBeZero())
+ DemandedSrcMask |= fcSubnormal;
+ }
+
+ if (DemandedMask & fcNormal)
+ DemandedSrcMask |= fcNormal | fcSubnormal;
+
+ // log(1) = 0
+ if (DemandedMask & fcZero)
+ DemandedSrcMask |= fcPosNormal;
+
+ KnownFPClass KnownSrc;
+ if (SimplifyDemandedFPClass(I, 0, DemandedSrcMask, KnownSrc, Depth + 1))
+ return I;
+
+ Known = KnownFPClass::log(KnownSrc, Mode);
+
+ FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+ return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+ }
case Intrinsic::canonicalize: {
Type *EltTy = VTy->getScalarType();
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-log.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-log.ll
index d6f2cab6687ab..87973fa36b478 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-log.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-log.ll
@@ -5,8 +5,7 @@
define nofpclass(inf norm sub zero) float @ret_nofpclass_only_nan__log(float %unknown) {
; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_nofpclass_only_nan__log(
; CHECK-SAME: float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
-; CHECK-NEXT: ret float [[RESULT]]
+; CHECK-NEXT: ret float 0x7FF8000000000000
;
%result = call float @llvm.log.f32(float %unknown)
ret float %result
@@ -16,8 +15,7 @@ define nofpclass(inf norm sub zero) float @ret_nofpclass_only_nan__log(float %un
define nofpclass(nan inf norm sub) float @ret_nofpclass_only_zero__log(float %unknown) {
; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_nofpclass_only_zero__log(
; CHECK-SAME: float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
-; CHECK-NEXT: ret float [[RESULT]]
+; CHECK-NEXT: ret float 0.000000e+00
;
%result = call float @llvm.log.f32(float %unknown)
ret float %result
@@ -57,7 +55,7 @@ define nofpclass(nan pinf norm sub zero) float @ret_nofpclass_only_ninf__log(flo
define nofpclass(nan inf norm sub pzero) float @ret_nofpclass_only_nzero__log(float %unknown) {
; CHECK-LABEL: define nofpclass(nan inf pzero sub norm) float @ret_nofpclass_only_nzero__log(
; CHECK-SAME: float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: ret float -0.000000e+00
+; CHECK-NEXT: ret float poison
;
%result = call float @llvm.log.f32(float %unknown)
ret float %result
@@ -87,8 +85,7 @@ define nofpclass(norm sub zero) float @ret_nofpclass_only_inf_nan__log(float %un
define nofpclass(ninf) float @ret_nofpclass_ninf_log(i1 %cond, float %x) {
; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf_log(
; CHECK-SAME: i1 [[COND:%.*]], float [[X:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0.000000e+00, float [[X]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[X]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float 0.0, float %x
@@ -100,8 +97,7 @@ define nofpclass(ninf) float @ret_nofpclass_ninf_log(i1 %cond, float %x) {
define nofpclass(pinf) float @ret_nofpclass_pinf_log_select_inf_or_unknown(i1 %cond, float %unknown) {
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf_log_select_inf_or_unknown(
; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[UNKNOWN]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float 0x7ff0000000000000, float %unknown
@@ -113,8 +109,7 @@ define nofpclass(pinf) float @ret_nofpclass_pinf_log_select_inf_or_unknown(i1 %c
define nofpclass(pinf) float @ret_nofpclass_pinf_log2_select_inf_or_unknown(i1 %cond, float %unknown) {
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf_log2_select_inf_or_unknown(
; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[UNKNOWN]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log2.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log2.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float 0x7ff0000000000000, float %unknown
@@ -126,8 +121,7 @@ define nofpclass(pinf) float @ret_nofpclass_pinf_log2_select_inf_or_unknown(i1 %
define nofpclass(pinf) float @ret_nofpclass_pinf_log10_select_inf_or_unknown(i1 %cond, float %unknown) {
; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf_log10_select_inf_or_unknown(
; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[UNKNOWN]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log10.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log10.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float 0x7ff0000000000000, float %unknown
@@ -139,8 +133,7 @@ define nofpclass(pinf) float @ret_nofpclass_pinf_log10_select_inf_or_unknown(i1
define nofpclass(ninf norm zero) float @ret_nofpclass_nan_or_sub__log_select__finite_positive__unknown(i1 %cond, float nofpclass(inf nnorm nsub nan) %must.be.finite.positive, float %unknown) {
; CHECK-LABEL: define nofpclass(ninf zero norm) float @ret_nofpclass_nan_or_sub__log_select__finite_positive__unknown(
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan inf nsub nnorm) [[MUST_BE_FINITE_POSITIVE:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MUST_BE_FINITE_POSITIVE]], float [[UNKNOWN]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float %must.be.finite.positive, float %unknown
@@ -165,8 +158,7 @@ define nofpclass(ninf norm zero) float @ret_nofpclass_nan_or_sub__log_select__fi
define nofpclass(pinf nan norm zero) float @ret_ninf_or_sub__log_select__pinf_or_sub_orzero__else_not0__ieee(i1 %cond, float nofpclass(ninf norm nan) %must.be.pinf.or.sub.or.zero, float nofpclass(zero) %not.zero) {
; CHECK-LABEL: define nofpclass(nan pinf zero norm) float @ret_ninf_or_sub__log_select__pinf_or_sub_orzero__else_not0__ieee(
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan ninf norm) [[MUST_BE_PINF_OR_SUB_OR_ZERO:%.*]], float nofpclass(zero) [[NOT_ZERO:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[MUST_BE_PINF_OR_SUB_OR_ZERO]], float [[NOT_ZERO]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[MUST_BE_PINF_OR_SUB_OR_ZERO]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float %must.be.pinf.or.sub.or.zero, float %not.zero
@@ -204,8 +196,7 @@ define nofpclass(pinf nan norm zero) float @ret_ninf_or_sub__log_select__pinf_or
define nofpclass(inf nan pnorm sub zero) float @ret_only_nnorm__log__select_unknown_or_infnan(i1 %cond, float %unknown, float nofpclass(norm sub zero) %b) {
; CHECK-LABEL: define nofpclass(nan inf zero sub pnorm) float @ret_only_nnorm__log__select_unknown_or_infnan(
; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(zero sub norm) [[B:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[B]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float %unknown, float %b
@@ -217,8 +208,7 @@ define nofpclass(inf nan pnorm sub zero) float @ret_only_nnorm__log__select_unkn
define nofpclass(inf nan nnorm sub zero) float @ret_only_pnorm__log__select_unknown_or_infnan(i1 %cond, float %unknown, float nofpclass(norm sub zero) %b) {
; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @ret_only_pnorm__log__select_unknown_or_infnan(
; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]], float nofpclass(zero sub norm) [[B:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[UNKNOWN]], float [[B]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[UNKNOWN]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float %unknown, float %b
@@ -243,8 +233,7 @@ define nofpclass(nan inf norm) float @ret_only_zero_sub__log__select_pnormnan_or
define nofpclass(nan inf norm) float @ret_only_zero_sub__log__select_nnormnan_or_unknown(i1 %cond, float nofpclass(inf sub zero pnorm) %nnorm.or.nan, float %b) {
; CHECK-LABEL: define nofpclass(nan inf norm) float @ret_only_zero_sub__log__select_nnormnan_or_unknown(
; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub pnorm) [[NNORM_OR_NAN:%.*]], float [[B:%.*]]) {
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[NNORM_OR_NAN]], float [[B]]
-; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[SELECT]])
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.log.f32(float [[B]])
; CHECK-NEXT: ret float [[RESULT]]
;
%select = select i1 %cond, float %nnorm.or.nan, float %b
|
🪟 Windows x64 Test Results
✅ The build succeeded and all tests passed. |
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
51c1ea4 to
bc98197
Compare
61a27d9 to
b340145
Compare
bc98197 to
ce1a943
Compare
b340145 to
65337de
Compare
ce1a943 to
b7cff00
Compare
44e3fe0 to
442fbbb
Compare
b7cff00 to
293a863
Compare
442fbbb to
c3b27f9
Compare
eb1e33a to
d86b4c3
Compare
c3b27f9 to
2ed972f
Compare
dtcxzyw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
2ed972f to
b60b014
Compare
d86b4c3 to
cb094e2
Compare

No description provided.