-
Notifications
You must be signed in to change notification settings - Fork 15.6k
InstCombine: Handle canonicalize in SimplifyDemandedFPClass #173189
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-simplify-demanded-fpclass-canonicalize
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-support @llvm/pr-subscribers-llvm-transforms Author: Matt Arsenault (arsenm) ChangesDoesn't try to handle PositiveZero flushing mode, but I Patch is 25.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/173189.diff 5 Files Affected:
diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h
index b3c18bcf6b34b..e50b97ac7f00d 100644
--- a/llvm/include/llvm/Support/KnownFPClass.h
+++ b/llvm/include/llvm/Support/KnownFPClass.h
@@ -155,6 +155,11 @@ struct KnownFPClass {
signBitMustBeZero();
}
+ /// Apply the canonicalize intrinsic to this value. This is essentially a
+ /// stronger form of propagateCanonicalizingSrc.
+ LLVM_ABI void
+ canonicalize(DenormalMode DenormMode = DenormalMode::getDynamic());
+
/// Return true if the sign bit must be 0, ignoring the sign of nans.
bool signBitIsZeroOrNaN() const { return isKnownNever(fcNegative); }
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 0321c08f55776..f7fdf9f1c0985 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5269,58 +5269,15 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
break;
}
case Intrinsic::canonicalize: {
- KnownFPClass KnownSrc;
computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedClasses,
- KnownSrc, Q, Depth + 1);
-
- // This is essentially a stronger form of
- // propagateCanonicalizingSrc. Other "canonicalizing" operations don't
- // actually have an IR canonicalization guarantee.
-
- // Canonicalize may flush denormals to zero, so we have to consider the
- // denormal mode to preserve known-not-0 knowledge.
- Known.KnownFPClasses = KnownSrc.KnownFPClasses | fcZero | fcQNan;
-
- // Stronger version of propagateNaN
- // Canonicalize is guaranteed to quiet signaling nans.
- if (KnownSrc.isKnownNeverNaN())
- Known.knownNot(fcNan);
- else
- Known.knownNot(fcSNan);
+ Known, Q, Depth + 1);
const Function *F = II->getFunction();
- if (!F)
- break;
-
- // If the parent function flushes denormals, the canonical output cannot
- // be a denormal.
- const fltSemantics &FPType =
- II->getType()->getScalarType()->getFltSemantics();
- DenormalMode DenormMode = F->getDenormalMode(FPType);
- if (DenormMode == DenormalMode::getIEEE()) {
- if (KnownSrc.isKnownNever(fcPosZero))
- Known.knownNot(fcPosZero);
- if (KnownSrc.isKnownNever(fcNegZero))
- Known.knownNot(fcNegZero);
- break;
- }
-
- if (DenormMode.inputsAreZero() || DenormMode.outputsAreZero())
- Known.knownNot(fcSubnormal);
-
- if (DenormMode == DenormalMode::getPreserveSign()) {
- if (KnownSrc.isKnownNever(fcPosZero | fcPosSubnormal))
- Known.knownNot(fcPosZero);
- if (KnownSrc.isKnownNever(fcNegZero | fcNegSubnormal))
- Known.knownNot(fcNegZero);
- break;
- }
-
- if (DenormMode.Input == DenormalMode::PositiveZero ||
- (DenormMode.Output == DenormalMode::PositiveZero &&
- DenormMode.Input == DenormalMode::IEEE))
- Known.knownNot(fcNegZero);
-
+ DenormalMode DenormMode =
+ F ? F->getDenormalMode(
+ II->getType()->getScalarType()->getFltSemantics())
+ : DenormalMode::getDynamic();
+ Known.canonicalize(DenormMode);
break;
}
case Intrinsic::vector_reduce_fmax:
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 43fb2e7108d2b..cb9563e0e52c3 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -87,6 +87,54 @@ void KnownFPClass::propagateDenormal(const KnownFPClass &Src,
}
}
+void KnownFPClass::canonicalize(DenormalMode DenormMode) {
+ KnownFPClass KnownSrc = *this;
+ *this = KnownFPClass();
+
+ // This is essentially a stronger form of
+ // propagateCanonicalizingSrc. Other "canonicalizing" operations don't
+ // actually have an IR canonicalization guarantee.
+
+ // Canonicalize may flush denormals to zero, so we have to consider the
+ // denormal mode to preserve known-not-0 knowledge.
+ KnownFPClasses = KnownSrc.KnownFPClasses | fcZero | fcQNan;
+
+ // Stronger version of propagateNaN
+ // Canonicalize is guaranteed to quiet signaling nans.
+ if (KnownSrc.isKnownNeverNaN())
+ knownNot(fcNan);
+ else
+ knownNot(fcSNan);
+
+ // FIXME: Missing check of IEEE like types.
+
+ // If the parent function flushes denormals, the canonical output cannot be a
+ // denormal.
+ if (DenormMode == DenormalMode::getIEEE()) {
+ if (KnownSrc.isKnownNever(fcPosZero))
+ knownNot(fcPosZero);
+ if (KnownSrc.isKnownNever(fcNegZero))
+ knownNot(fcNegZero);
+ return;
+ }
+
+ if (DenormMode.inputsAreZero() || DenormMode.outputsAreZero())
+ knownNot(fcSubnormal);
+
+ if (DenormMode == DenormalMode::getPreserveSign()) {
+ if (KnownSrc.isKnownNever(fcPosZero | fcPosSubnormal))
+ knownNot(fcPosZero);
+ if (KnownSrc.isKnownNever(fcNegZero | fcNegSubnormal))
+ knownNot(fcNegZero);
+ return;
+ }
+
+ if (DenormMode.Input == DenormalMode::PositiveZero ||
+ (DenormMode.Output == DenormalMode::PositiveZero &&
+ DenormMode.Input == DenormalMode::IEEE))
+ knownNot(fcNegZero);
+}
+
void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src,
DenormalMode Mode) {
propagateDenormal(Src, Mode);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 550dfc57a348b..3df89c930967e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2106,6 +2106,79 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
Known.copysign(KnownSign);
break;
}
+ case Intrinsic::canonicalize: {
+ Type *EltTy = VTy->getScalarType();
+
+ // TODO: This could have more refined support for PositiveZero denormal
+ // mode.
+ if (EltTy->isIEEELikeFPTy()) {
+ DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+
+ FPClassTest SrcDemandedMask = DemandedMask;
+
+ // A demanded quiet nan result may have come from a signaling nan, so we
+ // need to expand the demanded mask.
+ if ((DemandedMask & fcQNan) != fcNone)
+ SrcDemandedMask |= fcSNan;
+
+ // This cannot have produced a signaling nan, so we can trim any snan
+ // inputs.
+ if ((DemandedMask & fcSNan) != fcNone)
+ SrcDemandedMask &= ~fcSNan;
+
+ if (Mode != DenormalMode::getIEEE()) {
+ // Any zero results may have come from flushed denormals.
+ if (DemandedMask & fcPosZero)
+ SrcDemandedMask |= fcPosSubnormal;
+ if (DemandedMask & fcNegZero)
+ SrcDemandedMask |= fcNegSubnormal;
+ }
+
+ if (Mode == DenormalMode::getPreserveSign()) {
+ // If a denormal input will be flushed, and we don't need zeros, we
+ // don't need denormals either.
+ if ((DemandedMask & fcPosZero) == fcNone)
+ SrcDemandedMask &= ~fcPosSubnormal;
+
+ if ((DemandedMask & fcNegZero) == fcNone)
+ SrcDemandedMask &= ~fcNegSubnormal;
+ }
+
+ KnownFPClass KnownSrc;
+
+ // Simplify upstream operations before trying to simplify this call.
+ if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownSrc, Depth + 1))
+ return I;
+
+ Known = KnownSrc;
+
+ // Perform the canonicalization to see if this folded to a constant.
+ Known.canonicalize(Mode);
+
+ if (Constant *SingleVal =
+ getFPClassConstant(VTy, DemandedMask & Known.KnownFPClasses))
+ return SingleVal;
+
+ if (Mode == DenormalMode::getIEEE()) {
+ // For IEEE handling, there is only a bit change for nan inputs, so we
+ // can drop it if we do not demand nan results or we know the input
+ // isn't a nan.
+ if (KnownSrc.isKnownNeverNaN() || (DemandedMask & fcNan) == fcNone)
+ return CI->getArgOperand(0);
+ } else {
+ // Nan handling is the same as the IEEE case, but we also need to
+ // avoid denormal inputs to drop the canonicalize.
+ if ((KnownSrc.isKnownNeverNaN() ||
+ (DemandedMask & fcNan) == fcNone) &&
+ KnownSrc.isKnownNeverSubnormal())
+ return CI->getArgOperand(0);
+ }
+
+ return nullptr;
+ }
+
+ [[fallthrough]];
+ }
default:
Known = computeKnownFPClass(I, ~DemandedMask, CxtI, Depth + 1);
break;
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-canonicalize.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-canonicalize.ll
index 20de837d14367..0c305762d5c36 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-canonicalize.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-canonicalize.ll
@@ -71,8 +71,7 @@ define nofpclass(nan pzero) float @ret_nofpclass_nan_pzero__canonicalize_select_
; CHECK-LABEL: define nofpclass(nan pzero) float @ret_nofpclass_nan_pzero__canonicalize_select_psub_daz(
; CHECK-SAME: float [[X:%.*]], i1 [[COND:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub()
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[PSUB]]
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[SELECT]])
+; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
; CHECK-NEXT: ret float [[CANON]]
;
%psub = call float @returns_psub()
@@ -85,8 +84,7 @@ define nofpclass(nan nzero) float @ret_nofpclass_nan_nzero__canonicalize_select_
; CHECK-LABEL: define nofpclass(nan nzero) float @ret_nofpclass_nan_nzero__canonicalize_select_nsub_daz(
; CHECK-SAME: float [[X:%.*]], i1 [[COND:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub()
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[NSUB]]
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[SELECT]])
+; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
; CHECK-NEXT: ret float [[CANON]]
;
%nsub = call float @returns_nsub()
@@ -99,8 +97,7 @@ define nofpclass(nan zero) float @ret_nofpclass_nan_zero__canonicalize_select_su
; CHECK-LABEL: define nofpclass(nan zero) float @ret_nofpclass_nan_zero__canonicalize_select_sub_daz(
; CHECK-SAME: float [[X:%.*]], i1 [[COND:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SUB:%.*]] = call float @returns_sub()
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[SUB]]
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[SELECT]])
+; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
; CHECK-NEXT: ret float [[CANON]]
;
%sub = call float @returns_sub()
@@ -112,8 +109,7 @@ define nofpclass(nan zero) float @ret_nofpclass_nan_zero__canonicalize_select_su
define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_psub_ieee() {
; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_psub_ieee() {
; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub()
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[PSUB]])
-; CHECK-NEXT: ret float [[CANON]]
+; CHECK-NEXT: ret float [[PSUB]]
;
%psub = call float @returns_psub()
%canon = call float @llvm.canonicalize.f32(float %psub)
@@ -123,8 +119,7 @@ define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_psub_ieee() {
define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_nsub_ieee() {
; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_nsub_ieee() {
; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub()
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[NSUB]])
-; CHECK-NEXT: ret float [[CANON]]
+; CHECK-NEXT: ret float [[NSUB]]
;
%nsub = call float @returns_nsub()
%canon = call float @llvm.canonicalize.f32(float %nsub)
@@ -134,8 +129,7 @@ define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_nsub_ieee() {
define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_sub_ieee() {
; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_sub_ieee() {
; CHECK-NEXT: [[SUB:%.*]] = call float @returns_sub()
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[SUB]])
-; CHECK-NEXT: ret float [[CANON]]
+; CHECK-NEXT: ret float [[SUB]]
;
%sub = call float @returns_sub()
%canon = call float @llvm.canonicalize.f32(float %sub)
@@ -146,8 +140,7 @@ define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_psub_daz() #0
; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_psub_daz(
; CHECK-SAME: ) #[[ATTR0]] {
; CHECK-NEXT: [[PSUB:%.*]] = call float @returns_psub()
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[PSUB]])
-; CHECK-NEXT: ret float [[CANON]]
+; CHECK-NEXT: ret float 0.000000e+00
;
%psub = call float @returns_psub()
%canon = call float @llvm.canonicalize.f32(float %psub)
@@ -158,8 +151,7 @@ define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_nsub_daz() #0
; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_only_nsub_daz(
; CHECK-SAME: ) #[[ATTR0]] {
; CHECK-NEXT: [[NSUB:%.*]] = call float @returns_nsub()
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[NSUB]])
-; CHECK-NEXT: ret float [[CANON]]
+; CHECK-NEXT: ret float -0.000000e+00
;
%nsub = call float @returns_nsub()
%canon = call float @llvm.canonicalize.f32(float %nsub)
@@ -182,8 +174,7 @@ define nofpclass(zero) <2 x float> @ret_nofpclass_zero__canonicalize_daz_vec(<2
; CHECK-LABEL: define nofpclass(zero) <2 x float> @ret_nofpclass_zero__canonicalize_daz_vec(
; CHECK-SAME: <2 x float> [[X:%.*]], <2 x i1> [[COND:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SUB:%.*]] = call <2 x float> @returns_sub_vec()
-; CHECK-NEXT: [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x float> [[X]], <2 x float> [[SUB]]
-; CHECK-NEXT: [[CANON:%.*]] = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> [[SELECT]])
+; CHECK-NEXT: [[CANON:%.*]] = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> [[X]])
; CHECK-NEXT: ret <2 x float> [[CANON]]
;
%sub = call <2 x float> @returns_sub_vec()
@@ -196,8 +187,7 @@ define nofpclass(zero sub) float @ret_nofpclass_sub_zero__canonicalize_daz(float
; CHECK-LABEL: define nofpclass(zero sub) float @ret_nofpclass_sub_zero__canonicalize_daz(
; CHECK-SAME: float [[X:%.*]], i1 [[COND:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SUB_OR_ZERO:%.*]] = call float @returns_sub_zero()
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[SUB_OR_ZERO]]
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[SELECT]])
+; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
; CHECK-NEXT: ret float [[CANON]]
;
%sub_or_zero = call float @returns_sub_zero()
@@ -209,8 +199,7 @@ define nofpclass(zero sub) float @ret_nofpclass_sub_zero__canonicalize_daz(float
define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_ieee(float %unknown) {
; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_ieee(
; CHECK-SAME: float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[UNKNOWN]])
-; CHECK-NEXT: ret float [[CANON]]
+; CHECK-NEXT: ret float [[UNKNOWN]]
;
%canon = call float @llvm.canonicalize.f32(float %unknown)
ret float %canon
@@ -310,8 +299,7 @@ define nofpclass(qnan) float @ret_nofpclass_qnan__canonicalize_select_unknown_or
; CHECK-LABEL: define nofpclass(qnan) float @ret_nofpclass_qnan__canonicalize_select_unknown_or_snan(
; CHECK-SAME: float [[X:%.*]], i1 [[COND:%.*]]) {
; CHECK-NEXT: [[SNAN:%.*]] = call float @returns_snan()
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[SNAN]]
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[SELECT]])
+; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
; CHECK-NEXT: ret float [[CANON]]
;
%snan = call float @returns_snan()
@@ -325,9 +313,7 @@ define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_select_unknown_or_s
; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_select_unknown_or_snan(
; CHECK-SAME: float [[X:%.*]], i1 [[COND:%.*]]) {
; CHECK-NEXT: [[SNAN:%.*]] = call float @returns_snan()
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[SNAN]]
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[SELECT]])
-; CHECK-NEXT: ret float [[CANON]]
+; CHECK-NEXT: ret float [[X]]
;
%snan = call float @returns_snan()
%select = select i1 %cond, float %x, float %snan
@@ -339,8 +325,7 @@ define nofpclass(zero) float @ret_nofpclass_zero_nnan_flag__canonicalize_select_
; CHECK-LABEL: define nofpclass(zero) float @ret_nofpclass_zero_nnan_flag__canonicalize_select_unknown_or_snan(
; CHECK-SAME: float [[X:%.*]], i1 [[COND:%.*]]) {
; CHECK-NEXT: [[SNAN:%.*]] = call float @returns_snan()
-; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[SNAN]]
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[SELECT]])
+; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
; CHECK-NEXT: ret float [[CANON]]
;
%snan = call float @returns_snan()
@@ -356,8 +341,7 @@ define nofpclass(zero) float @ret_nofpclass_zero_nnan_flag__canonicalize_select_
define nofpclass(zero) float @ret_nofpclass_zero__canonicalize_nnan_src_ieee(float nofpclass(nan) %x, i1 %cond) {
; CHECK-LABEL: define nofpclass(zero) float @ret_nofpclass_zero__canonicalize_nnan_src_ieee(
; CHECK-SAME: float nofpclass(nan) [[X:%.*]], i1 [[COND:%.*]]) {
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
-; CHECK-NEXT: ret float [[CANON]]
+; CHECK-NEXT: ret float [[X]]
;
%canon = call float @llvm.canonicalize.f32(float %x)
ret float %canon
@@ -387,8 +371,7 @@ define nofpclass(zero) float @ret_nofpclass_zero__canonicalize_no_sub_src_daz(fl
define nofpclass(zero) float @ret_nofpclass_zero__canonicalize_no_sub_no_nan_src_daz(float nofpclass(nan sub) %x, i1 %cond) #0 {
; CHECK-LABEL: define nofpclass(zero) float @ret_nofpclass_zero__canonicalize_no_sub_no_nan_src_daz(
; CHECK-SAME: float nofpclass(nan sub) [[X:%.*]], i1 [[COND:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
-; CHECK-NEXT: ret float [[CANON]]
+; CHECK-NEXT: ret float [[X]]
;
%canon = call float @llvm.canonicalize.f32(float %x)
ret float %canon
@@ -397,8 +380,7 @@ define nofpclass(zero) float @ret_nofpclass_zero__canonicalize_no_sub_no_nan_src
define nofpclass(zero) float @ret_nofpclass_zero__canonicalize_no_sub_no_nan_src_dynamic(float nofpclass(nan sub) %x, i1 %cond) #1 {
; CHECK-LABEL: define nofpclass(zero) float @ret_nofpclass_zero__canonicalize_no_sub_no_nan_src_dynamic(
; CHECK-SAME: float nofpclass(nan sub) [[X:%.*]], i1 [[COND:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
-; CHECK-NEXT: ret float [[CANON]]
+; CHECK-NEXT: ret float [[X]]
;
%canon = call float @llvm.canonicalize.f32(float %x)
ret float %canon
@@ -408,8 +390,7 @@ define nofpclass(zero) float @ret_nofpclass_zero__canonicalize_no_sub_no_nan_src
define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_no_sub_src_daz(float nofpclass(sub) %x, i1 %cond) #0 {
; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__canonicalize_no_sub_src_daz(
; CHECK-SAME: float nofpclass(sub) [[X:%.*]], i1 [[COND:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[CANON:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
-; CHECK-NEXT: ret float [[CANON]]
+; CHECK-NEXT: ret float [[X]]
;
%canon = call float @llvm.canonicalize.f32(float %x)
ret float %canon
@@ -440,8 +421,7 @@ define nofpclass(snan) float @ret_nofpclass_snan__canonicalize_no_sub_src_daz(fl
define nofpclass(nan) flo...
[truncated]
|
Doesn't try to handle PositiveZero flushing mode, but I don't believe it is incorrect with it.
06ef509 to
fa6f411
Compare
01cb854 to
9ed4b6d
Compare

Doesn't try to handle PositiveZero flushing mode, but I
don't believe it is incorrect with it.