[llvm] ef2d6da - [InstCombine] Transform (fcmp + fadd + sel) into (fcmp + sel + fadd) (#106492)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 11 12:11:47 PST 2024
Author: Rajat Bajpai
Date: 2024-11-11T12:11:43-08:00
New Revision: ef2d6dafc40c5a58532eb773fc74ddd8e1f53a33
URL: https://github.com/llvm/llvm-project/commit/ef2d6dafc40c5a58532eb773fc74ddd8e1f53a33
DIFF: https://github.com/llvm/llvm-project/commit/ef2d6dafc40c5a58532eb773fc74ddd8e1f53a33.diff
LOG: [InstCombine] Transform (fcmp + fadd + sel) into (fcmp + sel + fadd) (#106492)
Transform `fcmp + fadd + sel` into `fcmp + sel + fadd` which enables the
possibility of transforming `fcmp + sel` into `maxnum/minnum`
intrinsics.
Alive2 results:
https://alive2.llvm.org/ce/z/2cmimW
https://alive2.llvm.org/ce/z/Qh9ZJt
https://alive2.llvm.org/ce/z/vtLj3R
Added:
llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll
Modified:
llvm/include/llvm/IR/FMF.h
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/FMF.h b/llvm/include/llvm/IR/FMF.h
index f063060567db21..d204d0a0e9d9a9 100644
--- a/llvm/include/llvm/IR/FMF.h
+++ b/llvm/include/llvm/IR/FMF.h
@@ -108,6 +108,20 @@ class FastMathFlags {
/// Print fast-math flags to \p O.
void print(raw_ostream &O) const;
+
+ /// Intersect rewrite-based flags
+ static inline FastMathFlags intersectRewrite(FastMathFlags LHS,
+ FastMathFlags RHS) {
+ const unsigned RewriteMask =
+ AllowReassoc | AllowReciprocal | AllowContract | ApproxFunc;
+ return FastMathFlags(RewriteMask & LHS.Flags & RHS.Flags);
+ }
+
+ /// Union value flags
+ static inline FastMathFlags unionValue(FastMathFlags LHS, FastMathFlags RHS) {
+ const unsigned ValueMask = NoNaNs | NoInfs | NoSignedZeros;
+ return FastMathFlags(ValueMask & (LHS.Flags | RHS.Flags));
+ }
};
inline FastMathFlags operator|(FastMathFlags LHS, FastMathFlags RHS) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 999ad1adff20b8..010b77548c152a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3645,6 +3645,60 @@ static bool hasAffectedValue(Value *V, SmallPtrSetImpl<Value *> &Affected,
return false;
}
+// This transformation enables the possibility of transforming fcmp + sel into
+// a fmaxnum/fminnum intrinsic.
+static Value *foldSelectIntoAddConstant(SelectInst &SI,
+ InstCombiner::BuilderTy &Builder) {
+ // Do this transformation only when select instruction gives NaN and NSZ
+ // guarantee.
+ auto *SIFOp = dyn_cast<FPMathOperator>(&SI);
+ if (!SIFOp || !SIFOp->hasNoSignedZeros() || !SIFOp->hasNoNaNs())
+ return nullptr;
+
+ // select((fcmp Pred, X, 0), (fadd X, C), C)
+ // => fadd((select (fcmp Pred, X, 0), X, 0), C)
+ //
+ // Pred := OGT, OGE, OLT, OLE, UGT, UGE, ULT, and ULE
+ Instruction *FAdd;
+ Constant *C;
+ Value *X, *Z;
+ CmpInst::Predicate Pred;
+
+ // Note: OneUse check for `Cmp` is necessary because it makes sure that other
+ // InstCombine folds don't undo this transformation and cause an infinite
+ // loop. Furthermore, it could also increase the operation count.
+ if (match(&SI, m_Select(m_OneUse(m_FCmp(Pred, m_Value(X), m_Value(Z))),
+ m_OneUse(m_Instruction(FAdd)), m_Constant(C))) ||
+ match(&SI, m_Select(m_OneUse(m_FCmp(Pred, m_Value(X), m_Value(Z))),
+ m_Constant(C), m_OneUse(m_Instruction(FAdd))))) {
+ // Only these relational predicates can be transformed into maxnum/minnum
+ // intrinsic.
+ if (!CmpInst::isRelational(Pred) || !match(Z, m_AnyZeroFP()))
+ return nullptr;
+
+ if (!match(FAdd, m_FAdd(m_Specific(X), m_Specific(C))))
+ return nullptr;
+
+ Value *NewSelect = Builder.CreateSelect(SI.getCondition(), X, Z, "", &SI);
+ NewSelect->takeName(&SI);
+
+ Value *NewFAdd = Builder.CreateFAdd(NewSelect, C);
+ NewFAdd->takeName(FAdd);
+
+ // Propagate FastMath flags
+ FastMathFlags SelectFMF = SI.getFastMathFlags();
+ FastMathFlags FAddFMF = FAdd->getFastMathFlags();
+ FastMathFlags NewFMF = FastMathFlags::intersectRewrite(SelectFMF, FAddFMF) |
+ FastMathFlags::unionValue(SelectFMF, FAddFMF);
+ cast<Instruction>(NewFAdd)->setFastMathFlags(NewFMF);
+ cast<Instruction>(NewSelect)->setFastMathFlags(NewFMF);
+
+ return NewFAdd;
+ }
+
+ return nullptr;
+}
+
Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
Value *CondVal = SI.getCondition();
Value *TrueVal = SI.getTrueValue();
@@ -4041,6 +4095,9 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
if (Value *V = foldRoundUpIntegerWithPow2Alignment(SI, Builder))
return replaceInstUsesWith(SI, V);
+ if (Value *V = foldSelectIntoAddConstant(SI, Builder))
+ return replaceInstUsesWith(SI, V);
+
// select(mask, mload(,,mask,0), 0) -> mload(,,mask,0)
// Load inst is intentionally not checked for hasOneUse()
if (match(FalseVal, m_Zero()) &&
diff --git a/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll b/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll
new file mode 100644
index 00000000000000..9f9cf7a633c875
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll
@@ -0,0 +1,674 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+; fcmp OGT + fadd + sel => fcmp OGT + sel => fmaxnum
+
+define float @test_fcmp_ogt_fadd_select_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ogt_fadd_select_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ogt_fadd_select_constant_swapped(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ogt_fadd_select_constant_swapped(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fcmp_ogt_fadd_select_neg_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ogt_fadd_select_neg_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ogt float %in, -0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ogt_fadd_select_fastmath_preserve(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ogt_fadd_select_fastmath_preserve(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %add = fadd nnan float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define <2 x float> @test_fcmp_ogt_fadd_select_constant_vectors(<2 x float> %in) {
+; CHECK-LABEL: define <2 x float> @test_fcmp_ogt_fadd_select_constant_vectors(
+; CHECK-SAME: <2 x float> [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz <2 x float> @llvm.maxnum.v2f32(<2 x float> [[IN]], <2 x float> zeroinitializer)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], <float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
+;
+ %cmp1 = fcmp ogt <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
+ %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
+ ret <2 x float> %sel
+}
+
+
+; fcmp OLT + fadd + sel => fcmp OLT + sel => fminnum
+
+define float @test_fcmp_olt_fadd_select_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_olt_fadd_select_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp olt float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_olt_fadd_select_constant_swapped(float %in) {
+; CHECK-LABEL: define float @test_fcmp_olt_fadd_select_constant_swapped(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp olt float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fcmp_olt_fadd_select_neg_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_olt_fadd_select_neg_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp olt float %in, -0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_olt_fadd_select_fastmath_preserve(float %in) {
+; CHECK-LABEL: define float @test_fcmp_olt_fadd_select_fastmath_preserve(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp olt float %in, 0.000000e+00
+ %add = fadd nnan float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define <2 x float> @test_fcmp_olt_fadd_select_constant_vectors(<2 x float> %in) {
+; CHECK-LABEL: define <2 x float> @test_fcmp_olt_fadd_select_constant_vectors(
+; CHECK-SAME: <2 x float> [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz <2 x float> @llvm.minnum.v2f32(<2 x float> [[IN]], <2 x float> zeroinitializer)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], <float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
+;
+ %cmp1 = fcmp olt <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
+ %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
+ ret <2 x float> %sel
+}
+
+
+; fcmp OGE + fadd + sel => fcmp OGE + sel => fmaxnum
+
+define float @test_fcmp_oge_fadd_select_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_oge_fadd_select_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp oge float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_oge_fadd_select_constant_swapped(float %in) {
+; CHECK-LABEL: define float @test_fcmp_oge_fadd_select_constant_swapped(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp oge float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fcmp_oge_fadd_select_neg_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_oge_fadd_select_neg_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp oge float %in, -0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_oge_fadd_select_fastmath_preserve(float %in) {
+; CHECK-LABEL: define float @test_fcmp_oge_fadd_select_fastmath_preserve(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp oge float %in, 0.000000e+00
+ %add = fadd nnan float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define <2 x float> @test_fcmp_oge_fadd_select_constant_vectors(<2 x float> %in) {
+; CHECK-LABEL: define <2 x float> @test_fcmp_oge_fadd_select_constant_vectors(
+; CHECK-SAME: <2 x float> [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz <2 x float> @llvm.maxnum.v2f32(<2 x float> [[IN]], <2 x float> zeroinitializer)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], <float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
+;
+ %cmp1 = fcmp oge <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
+ %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
+ ret <2 x float> %sel
+}
+
+
+; fcmp OLE + fadd + sel => fcmp OLE + sel => fminnum
+
+define float @test_fcmp_ole_fadd_select_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ole_fadd_select_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ole float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ole_fadd_select_constant_swapped(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ole_fadd_select_constant_swapped(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ole float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fcmp_ole_fadd_select_neg_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ole_fadd_select_neg_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ole float %in, -0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ole_fadd_select_fastmath_preserve(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ole_fadd_select_fastmath_preserve(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ole float %in, 0.000000e+00
+ %add = fadd nnan float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define <2 x float> @test_fcmp_ole_fadd_select_constant_vectors(<2 x float> %in) {
+; CHECK-LABEL: define <2 x float> @test_fcmp_ole_fadd_select_constant_vectors(
+; CHECK-SAME: <2 x float> [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz <2 x float> @llvm.minnum.v2f32(<2 x float> [[IN]], <2 x float> zeroinitializer)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], <float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
+;
+ %cmp1 = fcmp ole <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
+ %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
+ ret <2 x float> %sel
+}
+
+
+; fcmp UGT + fadd + sel => fcmp UGT + sel => fcmp OLE + sel
+
+define float @test_fcmp_ugt_fadd_select_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ugt_fadd_select_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp ole float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ugt float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ugt_fadd_select_constant_swapped(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ugt_fadd_select_constant_swapped(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp ole float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ugt float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fcmp_ugt_fadd_select_neg_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ugt_fadd_select_neg_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp ole float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ugt float %in, -0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ugt_fadd_select_fastmath_preserve(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ugt_fadd_select_fastmath_preserve(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp ole float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ugt float %in, 0.000000e+00
+ %add = fadd nnan float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define <2 x float> @test_fcmp_ugt_fadd_select_constant_vectors(<2 x float> %in) {
+; CHECK-LABEL: define <2 x float> @test_fcmp_ugt_fadd_select_constant_vectors(
+; CHECK-SAME: <2 x float> [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp ole <2 x float> [[IN]], zeroinitializer
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select <2 x i1> [[CMP1_INV]], <2 x float> zeroinitializer, <2 x float> [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], <float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
+;
+ %cmp1 = fcmp ugt <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
+ %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
+ ret <2 x float> %sel
+}
+
+
+; fcmp UGE + fadd + sel => fcmp UGE + sel => fcmp olt + sel
+
+define float @test_fcmp_uge_fadd_select_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_uge_fadd_select_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp olt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp uge float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_uge_fadd_select_constant_swapped(float %in) {
+; CHECK-LABEL: define float @test_fcmp_uge_fadd_select_constant_swapped(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp olt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp uge float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fcmp_uge_fadd_select_neg_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_uge_fadd_select_neg_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp olt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp uge float %in, -0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_uge_fadd_select_fastmath_preserve(float %in) {
+; CHECK-LABEL: define float @test_fcmp_uge_fadd_select_fastmath_preserve(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp olt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp uge float %in, 0.000000e+00
+ %add = fadd nnan float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define <2 x float> @test_fcmp_uge_fadd_select_constant_vectors(<2 x float> %in) {
+; CHECK-LABEL: define <2 x float> @test_fcmp_uge_fadd_select_constant_vectors(
+; CHECK-SAME: <2 x float> [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp olt <2 x float> [[IN]], zeroinitializer
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select <2 x i1> [[CMP1_INV]], <2 x float> zeroinitializer, <2 x float> [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], <float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
+;
+ %cmp1 = fcmp uge <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
+ %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
+ ret <2 x float> %sel
+}
+
+
+; fcmp ULT + fadd + sel => fcmp ULT + sel => fcmp OGE + sel
+
+define float @test_fcmp_ult_fadd_select_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ult_fadd_select_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp oge float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ult float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ult_fadd_select_constant_swapped(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ult_fadd_select_constant_swapped(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp oge float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ult float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fcmp_ult_fadd_select_neg_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ult_fadd_select_neg_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp oge float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ult float %in, -0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ult_fadd_select_fastmath_preserve(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ult_fadd_select_fastmath_preserve(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp oge float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ult float %in, 0.000000e+00
+ %add = fadd nnan float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define <2 x float> @test_fcmp_ult_fadd_select_constant_vectors(<2 x float> %in) {
+; CHECK-LABEL: define <2 x float> @test_fcmp_ult_fadd_select_constant_vectors(
+; CHECK-SAME: <2 x float> [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp oge <2 x float> [[IN]], zeroinitializer
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select <2 x i1> [[CMP1_INV]], <2 x float> zeroinitializer, <2 x float> [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], <float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
+;
+ %cmp1 = fcmp ult <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
+ %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
+ ret <2 x float> %sel
+}
+
+
+; fcmp ULE + fadd + sel => fcmp ULE + sel => fcmp OGT + sel
+
+define float @test_fcmp_ule_fadd_select_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ule_fadd_select_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ule float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ule_fadd_select_constant_swapped(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ule_fadd_select_constant_swapped(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ule float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fcmp_ule_fadd_select_neg_constant(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ule_fadd_select_neg_constant(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ule float %in, -0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ule_fadd_select_fastmath_preserve(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ule_fadd_select_fastmath_preserve(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1_INV]], float 0.000000e+00, float [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ule float %in, 0.000000e+00
+ %add = fadd nnan float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define <2 x float> @test_fcmp_ule_fadd_select_constant_vectors(<2 x float> %in) {
+; CHECK-LABEL: define <2 x float> @test_fcmp_ule_fadd_select_constant_vectors(
+; CHECK-SAME: <2 x float> [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp ogt <2 x float> [[IN]], zeroinitializer
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select <2 x i1> [[CMP1_INV]], <2 x float> zeroinitializer, <2 x float> [[IN]]
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], <float 1.000000e+00, float 1.000000e+00>
+; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
+;
+ %cmp1 = fcmp ule <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
+ %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
+ ret <2 x float> %sel
+}
+
+
+; Negative scenarios
+
+; select instruction doesn't give nnan and nsz guarantees.
+define float @test_select_without_nnan_nsz(float %in) {
+; CHECK-LABEL: define float @test_select_without_nnan_nsz(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[ADD:%.*]] = fadd float [[IN]], 1.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], float [[ADD]], float 1.000000e+00
+; CHECK-NEXT: ret float [[SEL]]
+;
+ %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+; fcmp arg doesn't match with fadd's. This won't be converted to maxnum/minnum.
+define float @test_fcmp_fadd_arg_mismatch(float %in, float %in2) {
+; CHECK-LABEL: define float @test_fcmp_fadd_arg_mismatch(
+; CHECK-SAME: float [[IN:%.*]], float [[IN2:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[IN2]], 0.000000e+00
+; CHECK-NEXT: [[ADD:%.*]] = fadd float [[IN]], 1.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select nnan nsz i1 [[CMP1]], float [[ADD]], float 1.000000e+00
+; CHECK-NEXT: ret float [[SEL]]
+;
+ %cmp1 = fcmp ogt float %in2, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+; It won't be converted to maxnum/minnum because constant arg in fcmp isn't zero.
+define float @test_fcmp_arg_non_zero(float %in) {
+; CHECK-LABEL: define float @test_fcmp_arg_non_zero(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[IN]], 1.000000e+00
+; CHECK-NEXT: [[ADD:%.*]] = fadd float [[IN]], 1.000000e+00
+; CHECK-NEXT: [[SEL:%.*]] = select nnan nsz i1 [[CMP1]], float [[ADD]], float 1.000000e+00
+; CHECK-NEXT: ret float [[SEL]]
+;
+ %cmp1 = fcmp ogt float %in, 1.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+; fcmp has more than one use.
+define float @test_fcmp_multiple_uses(float %in) {
+; CHECK-LABEL: define float @test_fcmp_multiple_uses(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[ADD:%.*]] = fadd float [[IN]], 1.000000e+00
+; CHECK-NEXT: [[ADD_2:%.*]] = fadd float [[IN]], 1.000000e+00
+; CHECK-NEXT: [[SEL_1:%.*]] = select nnan nsz i1 [[CMP1]], float [[ADD]], float 1.000000e+00
+; CHECK-NEXT: [[SEL_2:%.*]] = select nnan nsz i1 [[CMP1]], float 2.000000e+00, float [[ADD_2]]
+; CHECK-NEXT: [[RES:%.*]] = fadd float [[SEL_1]], [[SEL_2]]
+; CHECK-NEXT: ret float [[RES]]
+;
+ %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %add.2 = fadd float %in, 1.000000e+00
+ %sel.1 = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ %sel.2 = select nnan nsz i1 %cmp1, float 2.000000e+00, float %add.2
+ %res = fadd float %sel.1, %sel.2
+ ret float %res
+}
+
+; Rewrite-based flags propagation
+define float @test_fcmp_ogt_fadd_select_rewrite_flags1(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ogt_fadd_select_rewrite_flags1(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call reassoc nnan nsz arcp contract afn float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %add = fadd reassoc afn arcp contract float %in, 1.000000e+00
+ %sel = select nnan nsz reassoc afn arcp contract i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ogt_fadd_select_rewrite_flags2(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ogt_fadd_select_rewrite_flags2(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %add = fadd reassoc float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fcmp_ogt_fadd_select_rewrite_and_fastmath(float %in) {
+; CHECK-LABEL: define float @test_fcmp_ogt_fadd_select_rewrite_and_fastmath(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call fast float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd fast float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %add = fadd fast reassoc float %in, 1.000000e+00
+ %sel = select fast i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
More information about the llvm-commits
mailing list