diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 6707d1abf5ca0..668a0650de213 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -4423,6 +4423,109 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) { matchFMulByZeroIfResultEqZero(*this, Cmp0, Cmp1, MatchCmp1, MatchCmp0, SI, SIFPOp->hasNoSignedZeros())) return replaceInstUsesWith(SI, Cmp0); + + Type *EltTy = SelType->getScalarType(); + + // TODO: Generalize to any ordered / unordered compare. + if ((Pred == CmpInst::FCMP_ORD || Pred == CmpInst::FCMP_UNO) && + match(Cmp1, m_PosZeroFP()) && EltTy->isIEEELikeFPTy()) { + // Fold out only-canonicalize-non-nans pattern. This implements a + // wrapper around llvm.canonicalize which is not required to quiet + // signaling nans or preserve nan payload bits. + // + // %hard.canonical = call @llvm.canonicalize(%x) + // %soft.canonical = fdiv 1.0, %x + // %ord = fcmp ord %x, 0.0 + // %x.canon = select i1 %ord, %hard.canonical, %soft.canonical + // + // With known IEEE handling: + // => %x + // + // With other denormal behaviors: + // => llvm.canonicalize(%x) + // + // Note the fdiv could be any value preserving, potentially + // canonicalizing floating-point operation such as fmul by 1.0. However, + // since in the llvm model canonicalization is not mandatory, the fmul + // would have been dropped by the time we reached here. The trick here + // is to use a reciprocal fdiv. It's not a droppable no-op, as it could + // return an infinity if %x were sufficiently small, but in this pattern + // we're only using the output for nan values. + + if (Pred == CmpInst::FCMP_ORD) { + MatchCmp0 = TrueVal; + MatchCmp1 = FalseVal; + } else { + MatchCmp0 = FalseVal; + MatchCmp1 = TrueVal; + } + + bool RcpIfNan = match(MatchCmp1, m_FDiv(m_FPOne(), m_Specific(Cmp0))); + bool CanonicalizeIfNotNan = + match(MatchCmp0, m_FCanonicalize(m_Specific(Cmp0))); + + if (RcpIfNan || CanonicalizeIfNotNan) { + const fltSemantics &FPSem = EltTy->getFltSemantics(); + DenormalMode Mode = F.getDenormalMode(FPSem); + + if (RcpIfNan) { + if (Mode == DenormalMode::getIEEE()) { + // Special case for the other select operand. Otherwise, we may + // need to insert freeze on Cmp0 in the compare and select. + if (CanonicalizeIfNotNan) + return replaceInstUsesWith(SI, Cmp0); + + if (isGuaranteedNotToBeUndef(Cmp0, &AC, &SI, &DT)) { + // select (fcmp ord %cmp0, 0), y, (fdiv 1, x) + // => select (fcmp ord %cmp0, 0), y, x + // + // select (fcmp uno %cmp0, 0), (fdiv 1, x), y + // => select (fcmp uno %cmp0, 0), x, y + replaceOperand(SI, Pred == CmpInst::FCMP_ORD ? 2 : 1, Cmp0); + return &SI; + } + + auto *FrCmp0 = InsertNewInstBefore( + new FreezeInst(Cmp0, Cmp0->getName() + ".fr"), + FCmp->getIterator()); + + replaceOperand(*FCmp, 0, FrCmp0); + return replaceOperand(SI, Pred == CmpInst::FCMP_ORD ? 2 : 1, + FrCmp0); + } + } + + if (CanonicalizeIfNotNan) { + // IEEE handling does not have non-canonical values, so the + // canonicalize can be dropped for direct replacement without + // looking for the intermediate maybe-canonicalizing operation. + if (Mode == DenormalMode::getIEEE()) { + // select (fcmp ord %cmp0, 0), canonicalize(x), y + // => select (fcmp ord %cmp0, 0), x, y + + replaceOperand(SI, Pred == CmpInst::FCMP_ORD ? 1 : 2, Cmp0); + return &SI; + } + + // If denormals may be flushed, we need to retain the canonicalize + // call. This introduces a canonicalization on the nan path, which + // we are not free to do as that could change the sign bit or + // payload bits. We can only do this if there were a no-op like + // floating-point instruction which may have changed the nan bits + // anyway. + if (RcpIfNan) { + if (Mode == DenormalMode::getIEEE()) + return replaceInstUsesWith(SI, Cmp0); + + if (Mode.inputsAreZero() || Mode.outputsAreZero()) + return replaceInstUsesWith(SI, MatchCmp0); + } + + // Leave the dynamic mode case alone. This would introduce new + // constraints if the mode may be refined later. + } + } + } } } diff --git a/llvm/test/Transforms/InstCombine/nanless-canonicalize-combine.ll b/llvm/test/Transforms/InstCombine/nanless-canonicalize-combine.ll index 56e0808c650ff..ad6020f0eda91 100644 --- a/llvm/test/Transforms/InstCombine/nanless-canonicalize-combine.ll +++ b/llvm/test/Transforms/InstCombine/nanless-canonicalize-combine.ll @@ -9,11 +9,7 @@ define float @canonicalize_ieee_0(float %x) #0 { ; CHECK-LABEL: define float @canonicalize_ieee_0( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0:[0-9]+]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %soft.canonical = fdiv float 1.0, %x @@ -26,11 +22,7 @@ define float @canonicalize_ieee_0(float %x) #0 { define float @canonicalize_ieee_1(float %x) #0 { ; CHECK-LABEL: define float @canonicalize_ieee_1( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]] -; CHECK-NEXT: [[UNO:%.*]] = fcmp uno float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], float [[SOFT_CANONICAL]], float [[HARD_CANONICAL]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %soft.canonical = fdiv float 1.0, %x @@ -44,10 +36,7 @@ define float @canonicalize_ieee_1(float %x) #0 { define float @canonicalize_ieee_0_fmul(float %x) #0 { ; CHECK-LABEL: define float @canonicalize_ieee_0_fmul( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[X]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %soft.canonical = fmul float %x, 1.0 @@ -61,10 +50,7 @@ define float @canonicalize_ieee_0_fmul(float %x) #0 { define float @canonicalize_ieee_0_fdiv_commute(float %x) #0 { ; CHECK-LABEL: define float @canonicalize_ieee_0_fdiv_commute( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[X]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %soft.canonical = fdiv float %x, 1.0 @@ -78,11 +64,7 @@ define float @canonicalize_ieee_0_fdiv_commute(float %x) #0 { define float @canonicalize_daz_0(float %x) #1 { ; CHECK-LABEL: define float @canonicalize_daz_0( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR1:[0-9]+]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %soft.canonical = fdiv float 1.0, %x @@ -96,11 +78,7 @@ define float @canonicalize_daz_0(float %x) #1 { define float @canonicalize_daz_1(float %x) #1 { ; CHECK-LABEL: define float @canonicalize_daz_1( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]] -; CHECK-NEXT: [[UNO:%.*]] = fcmp uno float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], float [[SOFT_CANONICAL]], float [[HARD_CANONICAL]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %soft.canonical = fdiv float 1.0, %x @@ -113,11 +91,7 @@ define float @canonicalize_daz_1(float %x) #1 { define float @canonicalize_dynamic_0(float %x) #2 { ; CHECK-LABEL: define float @canonicalize_dynamic_0( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR2:[0-9]+]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %soft.canonical = fdiv float 1.0, %x @@ -130,11 +104,7 @@ define float @canonicalize_dynamic_0(float %x) #2 { define float @canonicalize_dynamic_1(float %x) #2 { ; CHECK-LABEL: define float @canonicalize_dynamic_1( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR2]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]] -; CHECK-NEXT: [[UNO:%.*]] = fcmp uno float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], float [[SOFT_CANONICAL]], float [[HARD_CANONICAL]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %soft.canonical = fdiv float 1.0, %x @@ -146,11 +116,7 @@ define float @canonicalize_dynamic_1(float %x) #2 { define <2 x float> @canonicalize_ieee_0_vec(<2 x float> %x) #0 { ; CHECK-LABEL: define <2 x float> @canonicalize_ieee_0_vec( ; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv <2 x float> splat (float 1.000000e+00), [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord <2 x float> [[X]], zeroinitializer -; CHECK-NEXT: [[X_CANON:%.*]] = select <2 x i1> [[ORD]], <2 x float> [[HARD_CANONICAL]], <2 x float> [[SOFT_CANONICAL]] -; CHECK-NEXT: ret <2 x float> [[X_CANON]] +; CHECK-NEXT: ret <2 x float> [[X]] ; %hard.canonical = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x) %soft.canonical = fdiv <2 x float> splat (float 1.0), %x @@ -162,11 +128,7 @@ define <2 x float> @canonicalize_ieee_0_vec(<2 x float> %x) #0 { define <2 x float> @canonicalize_ieee_1_vec(<2 x float> %x) #0 { ; CHECK-LABEL: define <2 x float> @canonicalize_ieee_1_vec( ; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv <2 x float> splat (float 1.000000e+00), [[X]] -; CHECK-NEXT: [[UNO:%.*]] = fcmp uno <2 x float> [[X]], zeroinitializer -; CHECK-NEXT: [[X_CANON:%.*]] = select <2 x i1> [[UNO]], <2 x float> [[SOFT_CANONICAL]], <2 x float> [[HARD_CANONICAL]] -; CHECK-NEXT: ret <2 x float> [[X_CANON]] +; CHECK-NEXT: ret <2 x float> [[X]] ; %hard.canonical = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x) %soft.canonical = fdiv <2 x float> splat (float 1.0), %x @@ -178,10 +140,9 @@ define <2 x float> @canonicalize_ieee_1_vec(<2 x float> %x) #0 { define <2 x float> @canonicalize_ieee_0_vec_poison_elt(<2 x float> %x) #0 { ; CHECK-LABEL: define <2 x float> @canonicalize_ieee_0_vec_poison_elt( ; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> [[X]]) ; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv <2 x float> , [[X]] ; CHECK-NEXT: [[ORD:%.*]] = fcmp ord <2 x float> [[X]], zeroinitializer -; CHECK-NEXT: [[X_CANON:%.*]] = select <2 x i1> [[ORD]], <2 x float> [[HARD_CANONICAL]], <2 x float> [[SOFT_CANONICAL]] +; CHECK-NEXT: [[X_CANON:%.*]] = select <2 x i1> [[ORD]], <2 x float> [[X]], <2 x float> [[SOFT_CANONICAL]] ; CHECK-NEXT: ret <2 x float> [[X_CANON]] ; %hard.canonical = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x) @@ -194,11 +155,7 @@ define <2 x float> @canonicalize_ieee_0_vec_poison_elt(<2 x float> %x) #0 { define <2 x float> @canonicalize_daz_0_vec(<2 x float> %x) #1 { ; CHECK-LABEL: define <2 x float> @canonicalize_daz_0_vec( ; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv <2 x float> splat (float 1.000000e+00), [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord <2 x float> [[X]], zeroinitializer -; CHECK-NEXT: [[X_CANON:%.*]] = select <2 x i1> [[ORD]], <2 x float> [[HARD_CANONICAL]], <2 x float> [[SOFT_CANONICAL]] -; CHECK-NEXT: ret <2 x float> [[X_CANON]] +; CHECK-NEXT: ret <2 x float> [[X]] ; %hard.canonical = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x) %soft.canonical = fdiv <2 x float> splat (float 1.0), %x @@ -210,11 +167,7 @@ define <2 x float> @canonicalize_daz_0_vec(<2 x float> %x) #1 { define <2 x float> @canonicalize_daz_1_vec(<2 x float> %x) #1 { ; CHECK-LABEL: define <2 x float> @canonicalize_daz_1_vec( ; CHECK-SAME: <2 x float> [[X:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv <2 x float> splat (float 1.000000e+00), [[X]] -; CHECK-NEXT: [[UNO:%.*]] = fcmp uno <2 x float> [[X]], zeroinitializer -; CHECK-NEXT: [[X_CANON:%.*]] = select <2 x i1> [[UNO]], <2 x float> [[SOFT_CANONICAL]], <2 x float> [[HARD_CANONICAL]] -; CHECK-NEXT: ret <2 x float> [[X_CANON]] +; CHECK-NEXT: ret <2 x float> [[X]] ; %hard.canonical = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x) %soft.canonical = fdiv <2 x float> splat (float 1.0), %x @@ -226,11 +179,7 @@ define <2 x float> @canonicalize_daz_1_vec(<2 x float> %x) #1 { define bfloat @canonicalize_ieee_bf16(bfloat %x) #0 { ; CHECK-LABEL: define bfloat @canonicalize_ieee_bf16( ; CHECK-SAME: bfloat [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call bfloat @llvm.canonicalize.bf16(bfloat [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv bfloat 0xR3F80, [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord bfloat [[X]], 0xR0000 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], bfloat [[HARD_CANONICAL]], bfloat [[SOFT_CANONICAL]] -; CHECK-NEXT: ret bfloat [[X_CANON]] +; CHECK-NEXT: ret bfloat [[X]] ; %hard.canonical = call bfloat @llvm.canonicalize.bf16(bfloat %x) %soft.canonical = fdiv bfloat 1.0, %x @@ -242,11 +191,7 @@ define bfloat @canonicalize_ieee_bf16(bfloat %x) #0 { define half @canonicalize_ieee_f16(half %x) #0 { ; CHECK-LABEL: define half @canonicalize_ieee_f16( ; CHECK-SAME: half [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call half @llvm.canonicalize.f16(half [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv half 0xH3C00, [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], half [[HARD_CANONICAL]], half [[SOFT_CANONICAL]] -; CHECK-NEXT: ret half [[X_CANON]] +; CHECK-NEXT: ret half [[X]] ; %hard.canonical = call half @llvm.canonicalize.f16(half %x) %soft.canonical = fdiv half 1.0, %x @@ -258,11 +203,7 @@ define half @canonicalize_ieee_f16(half %x) #0 { define double @canonicalize_ieee_f64(double %x) #0 { ; CHECK-LABEL: define double @canonicalize_ieee_f64( ; CHECK-SAME: double [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call double @llvm.canonicalize.f64(double [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv double 1.000000e+00, [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord double [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], double [[HARD_CANONICAL]], double [[SOFT_CANONICAL]] -; CHECK-NEXT: ret double [[X_CANON]] +; CHECK-NEXT: ret double [[X]] ; %hard.canonical = call double @llvm.canonicalize.f64(double %x) %soft.canonical = fdiv double 1.0, %x @@ -274,10 +215,7 @@ define double @canonicalize_ieee_f64(double %x) #0 { define fp128 @canonicalize_ieee_f128(fp128 %x) #0 { ; CHECK-LABEL: define fp128 @canonicalize_ieee_f128( ; CHECK-SAME: fp128 [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call fp128 @llvm.canonicalize.f128(fp128 [[X]]) -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord fp128 [[X]], 0xL00000000000000000000000000000000 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], fp128 [[HARD_CANONICAL]], fp128 [[X]] -; CHECK-NEXT: ret fp128 [[X_CANON]] +; CHECK-NEXT: ret fp128 [[X]] ; %hard.canonical = call fp128 @llvm.canonicalize.f128(fp128 %x) %ord = fcmp ord fp128 %x, 0xL00000000000000000000000000000000 @@ -289,10 +227,9 @@ define fp128 @canonicalize_ieee_f128(fp128 %x) #0 { define float @div_not_one(float %x) #0 { ; CHECK-LABEL: define float @div_not_one( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) ; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 2.000000e+00, [[X]] ; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[X]], float [[SOFT_CANONICAL]] ; CHECK-NEXT: ret float [[X_CANON]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) @@ -306,10 +243,9 @@ define float @div_not_one(float %x) #0 { define float @not_fdiv(float %x) #0 { ; CHECK-LABEL: define float @not_fdiv( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) ; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fadd float [[X]], 1.000000e+00 ; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[X]], float [[SOFT_CANONICAL]] ; CHECK-NEXT: ret float [[X_CANON]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) @@ -342,10 +278,10 @@ declare float @func(float) define float @not_canonicalize(float %x) #0 { ; CHECK-LABEL: define float @not_canonicalize( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[NOT_CANONICAL:%.*]] = call noundef float @func(float [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[NOT_CANONICAL]], float [[SOFT_CANONICAL]] +; CHECK-NEXT: [[X_FR:%.*]] = freeze float [[X]] +; CHECK-NEXT: [[NOT_CANONICAL:%.*]] = call noundef float @func(float [[X_FR]]) +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X_FR]], 0.000000e+00 +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[NOT_CANONICAL]], float [[X_FR]] ; CHECK-NEXT: ret float [[X_CANON]] ; %not.canonical = call noundef float @func(float %x) @@ -376,10 +312,9 @@ define float @compared_value_different(float %x, float %y) #0 { define float @fdiv_value_different_ieee(float %x, float %y) #0 { ; CHECK-LABEL: define float @fdiv_value_different_ieee( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) ; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[Y]] ; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[X]], float [[SOFT_CANONICAL]] ; CHECK-NEXT: ret float [[X_CANON]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) @@ -393,10 +328,9 @@ define float @fdiv_value_different_ieee(float %x, float %y) #0 { define float @fdiv_value_different_ieee_commute(float %x, float %y) #0 { ; CHECK-LABEL: define float @fdiv_value_different_ieee_commute( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) ; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[Y]] ; CHECK-NEXT: [[ORD:%.*]] = fcmp uno float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[SOFT_CANONICAL]], float [[HARD_CANONICAL]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[SOFT_CANONICAL]], float [[X]] ; CHECK-NEXT: ret float [[X_CANON]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) @@ -410,10 +344,9 @@ define float @fdiv_value_different_ieee_commute(float %x, float %y) #0 { define float @fdiv_value_different_daz(float %x, float %y) #1 { ; CHECK-LABEL: define float @fdiv_value_different_daz( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) ; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[Y]] ; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[X]], float [[SOFT_CANONICAL]] ; CHECK-NEXT: ret float [[X_CANON]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) @@ -427,10 +360,9 @@ define float @fdiv_value_different_daz(float %x, float %y) #1 { define float @fdiv_value_different_daz_commute(float %x, float %y) #1 { ; CHECK-LABEL: define float @fdiv_value_different_daz_commute( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) ; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[Y]] ; CHECK-NEXT: [[ORD:%.*]] = fcmp uno float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[SOFT_CANONICAL]], float [[HARD_CANONICAL]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[SOFT_CANONICAL]], float [[X]] ; CHECK-NEXT: ret float [[X_CANON]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) @@ -503,10 +435,7 @@ define ppc_fp128 @ignore_ppc_fp128(ppc_fp128 %x) #0 { define float @canonicalize_ieee_0_missing_noop(float %x) #0 { ; CHECK-LABEL: define float @canonicalize_ieee_0_missing_noop( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[X]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %ord = fcmp ord float %x, 0.0 @@ -519,10 +448,7 @@ define float @canonicalize_ieee_0_missing_noop(float %x) #0 { define float @canonicalize_ieee_1_missing_noop(float %x) #0 { ; CHECK-LABEL: define float @canonicalize_ieee_1_missing_noop( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[UNO:%.*]] = fcmp uno float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], float [[X]], float [[HARD_CANONICAL]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %uno = fcmp uno float %x, 0.0 @@ -535,10 +461,7 @@ define float @canonicalize_ieee_1_missing_noop(float %x) #0 { define float @canonicalize_da_0_missing_noop(float %x) #1 { ; CHECK-LABEL: define float @canonicalize_da_0_missing_noop( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[X]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %ord = fcmp ord float %x, 0.0 @@ -551,10 +474,7 @@ define float @canonicalize_da_0_missing_noop(float %x) #1 { define float @canonicalize_daz_1_missing_noop(float %x) #1 { ; CHECK-LABEL: define float @canonicalize_daz_1_missing_noop( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[UNO:%.*]] = fcmp uno float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], float [[X]], float [[HARD_CANONICAL]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %uno = fcmp uno float %x, 0.0 @@ -566,11 +486,7 @@ define float @canonicalize_daz_1_missing_noop(float %x) #1 { define float @canonicalize_only_ftz(float %x) "denormal-fp-math"="preserve-sign,ieee" { ; CHECK-LABEL: define float @canonicalize_only_ftz( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR3:[0-9]+]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %soft.canonical = fdiv float 1.0, %x @@ -583,11 +499,7 @@ define float @canonicalize_only_ftz(float %x) "denormal-fp-math"="preserve-sign, define float @canonicalize_only_daz(float %x) "denormal-fp-math"="ieee,preserve-sign" { ; CHECK-LABEL: define float @canonicalize_only_daz( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR4:[0-9]+]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[SOFT_CANONICAL:%.*]] = fdiv float 1.000000e+00, [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[SOFT_CANONICAL]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %soft.canonical = fdiv float 1.0, %x @@ -600,10 +512,7 @@ define float @canonicalize_only_daz(float %x) "denormal-fp-math"="ieee,preserve- define float @canonicalize_missing_noop_only_ftz(float %x) "denormal-fp-math"="preserve-sign,ieee" { ; CHECK-LABEL: define float @canonicalize_missing_noop_only_ftz( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR3]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[X]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %ord = fcmp ord float %x, 0.0 @@ -615,10 +524,7 @@ define float @canonicalize_missing_noop_only_ftz(float %x) "denormal-fp-math"="p define float @canonicalize_missing_noop_only_daz(float %x) "denormal-fp-math"="ieee,preserve-sign" { ; CHECK-LABEL: define float @canonicalize_missing_noop_only_daz( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR4]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float [[X]]) -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X]], 0.000000e+00 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], float [[HARD_CANONICAL]], float [[X]] -; CHECK-NEXT: ret float [[X_CANON]] +; CHECK-NEXT: ret float [[X]] ; %hard.canonical = call float @llvm.canonicalize.f32(float %x) %ord = fcmp ord float %x, 0.0 @@ -629,9 +535,8 @@ define float @canonicalize_missing_noop_only_daz(float %x) "denormal-fp-math"="i define half @independent_hands_canonicalize_ieee_0(half noundef %x, half %y) #0 { ; CHECK-LABEL: define half @independent_hands_canonicalize_ieee_0( ; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call half @llvm.canonicalize.f16(half [[X]]) ; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], half [[HARD_CANONICAL]], half [[Y]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], half [[X]], half [[Y]] ; CHECK-NEXT: ret half [[X_CANON]] ; %hard.canonical = call half @llvm.canonicalize.f16(half %x) @@ -643,9 +548,8 @@ define half @independent_hands_canonicalize_ieee_0(half noundef %x, half %y) #0 define half @independent_hands_canonicalize_ieee_1(half noundef %x, half %y) #0 { ; CHECK-LABEL: define half @independent_hands_canonicalize_ieee_1( ; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call half @llvm.canonicalize.f16(half [[X]]) ; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0xH0000 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], half [[Y]], half [[HARD_CANONICAL]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], half [[Y]], half [[X]] ; CHECK-NEXT: ret half [[X_CANON]] ; %hard.canonical = call half @llvm.canonicalize.f16(half %x) @@ -657,9 +561,8 @@ define half @independent_hands_canonicalize_ieee_1(half noundef %x, half %y) #0 define half @independent_hands_fdiv_ieee_0(half noundef %x, half %y) #0 { ; CHECK-LABEL: define half @independent_hands_fdiv_ieee_0( ; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[RCP:%.*]] = fdiv half 0xH3C00, [[X]] ; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ORD]], half [[Y]], half [[RCP]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ORD]], half [[Y]], half [[X]] ; CHECK-NEXT: ret half [[SEL]] ; %rcp = fdiv half 1.0, %x @@ -671,9 +574,8 @@ define half @independent_hands_fdiv_ieee_0(half noundef %x, half %y) #0 { define half @independent_hands_fdiv_ieee_1(half noundef %x, half %y) #0 { ; CHECK-LABEL: define half @independent_hands_fdiv_ieee_1( ; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[RCP:%.*]] = fdiv half 0xH3C00, [[X]] ; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0xH0000 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[UNO]], half [[RCP]], half [[Y]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[UNO]], half [[X]], half [[Y]] ; CHECK-NEXT: ret half [[SEL]] ; %rcp = fdiv half 1.0, %x @@ -685,9 +587,8 @@ define half @independent_hands_fdiv_ieee_1(half noundef %x, half %y) #0 { define half @independent_hands_canonicalize_daz_0(half noundef %x, half %y) #1 { ; CHECK-LABEL: define half @independent_hands_canonicalize_daz_0( ; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call half @llvm.canonicalize.f16(half [[X]]) ; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], half [[HARD_CANONICAL]], half [[Y]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], half [[X]], half [[Y]] ; CHECK-NEXT: ret half [[X_CANON]] ; %hard.canonical = call half @llvm.canonicalize.f16(half %x) @@ -699,9 +600,8 @@ define half @independent_hands_canonicalize_daz_0(half noundef %x, half %y) #1 { define half @independent_hands_canonicalize_daz_1(half noundef %x, half %y) #1 { ; CHECK-LABEL: define half @independent_hands_canonicalize_daz_1( ; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call half @llvm.canonicalize.f16(half [[X]]) ; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0xH0000 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], half [[Y]], half [[HARD_CANONICAL]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], half [[Y]], half [[X]] ; CHECK-NEXT: ret half [[X_CANON]] ; %hard.canonical = call half @llvm.canonicalize.f16(half %x) @@ -713,9 +613,8 @@ define half @independent_hands_canonicalize_daz_1(half noundef %x, half %y) #1 { define half @independent_hands_fdiv_daz_0(half noundef %x, half %y) #1 { ; CHECK-LABEL: define half @independent_hands_fdiv_daz_0( ; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[RCP:%.*]] = fdiv half 0xH3C00, [[X]] ; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ORD]], half [[Y]], half [[RCP]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ORD]], half [[Y]], half [[X]] ; CHECK-NEXT: ret half [[SEL]] ; %rcp = fdiv half 1.0, %x @@ -727,9 +626,8 @@ define half @independent_hands_fdiv_daz_0(half noundef %x, half %y) #1 { define half @independent_hands_fdiv_daz_1(half noundef %x, half %y) #1 { ; CHECK-LABEL: define half @independent_hands_fdiv_daz_1( ; CHECK-SAME: half noundef [[X:%.*]], half [[Y:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[RCP:%.*]] = fdiv half 0xH3C00, [[X]] ; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0xH0000 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[UNO]], half [[RCP]], half [[Y]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[UNO]], half [[X]], half [[Y]] ; CHECK-NEXT: ret half [[SEL]] ; %rcp = fdiv half 1.0, %x @@ -771,9 +669,8 @@ define x86_fp80 @independent_hands_fdiv_ieee_0_x86_fp80(x86_fp80 noundef %x, x86 define half @independent_hands_canonicalize_ieee_0_maybe_undef(half %x, half %y) #0 { ; CHECK-LABEL: define half @independent_hands_canonicalize_ieee_0_maybe_undef( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call half @llvm.canonicalize.f16(half [[X]]) ; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], half [[HARD_CANONICAL]], half [[Y]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[ORD]], half [[X]], half [[Y]] ; CHECK-NEXT: ret half [[X_CANON]] ; %hard.canonical = call half @llvm.canonicalize.f16(half %x) @@ -786,9 +683,8 @@ define half @independent_hands_canonicalize_ieee_0_maybe_undef(half %x, half %y) define half @independent_hands_canonicalize_ieee_1_maybe_undef(half %x, half %y) #0 { ; CHECK-LABEL: define half @independent_hands_canonicalize_ieee_1_maybe_undef( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[HARD_CANONICAL:%.*]] = call half @llvm.canonicalize.f16(half [[X]]) ; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0xH0000 -; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], half [[Y]], half [[HARD_CANONICAL]] +; CHECK-NEXT: [[X_CANON:%.*]] = select i1 [[UNO]], half [[Y]], half [[X]] ; CHECK-NEXT: ret half [[X_CANON]] ; %hard.canonical = call half @llvm.canonicalize.f16(half %x) @@ -801,9 +697,9 @@ define half @independent_hands_canonicalize_ieee_1_maybe_undef(half %x, half %y) define half @independent_hands_fdiv_ieee_0_maybe_undef(half %x, half %y) #0 { ; CHECK-LABEL: define half @independent_hands_fdiv_ieee_0_maybe_undef( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[RCP:%.*]] = fdiv half 0xH3C00, [[X]] -; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ORD]], half [[Y]], half [[RCP]] +; CHECK-NEXT: [[X_FR:%.*]] = freeze half [[X]] +; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X_FR]], 0xH0000 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[ORD]], half [[Y]], half [[X_FR]] ; CHECK-NEXT: ret half [[SEL]] ; %rcp = fdiv half 1.0, %x @@ -816,9 +712,9 @@ define half @independent_hands_fdiv_ieee_0_maybe_undef(half %x, half %y) #0 { define half @independent_hands_fdiv_ieee_1_maybe_undef(half %x, half %y) #0 { ; CHECK-LABEL: define half @independent_hands_fdiv_ieee_1_maybe_undef( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) #[[ATTR0]] { -; CHECK-NEXT: [[RCP:%.*]] = fdiv half 0xH3C00, [[X]] -; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X]], 0xH0000 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[UNO]], half [[RCP]], half [[Y]] +; CHECK-NEXT: [[X_FR:%.*]] = freeze half [[X]] +; CHECK-NEXT: [[UNO:%.*]] = fcmp uno half [[X_FR]], 0xH0000 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[UNO]], half [[X_FR]], half [[Y]] ; CHECK-NEXT: ret half [[SEL]] ; %rcp = fdiv half 1.0, %x