[llvm] [InstCombine] Transform (fcmp + fadd + sel) into (fcmp + sel + fadd) (PR #106492)
Rajat Bajpai via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 5 04:28:41 PDT 2024
https://github.com/rajatbajpai updated https://github.com/llvm/llvm-project/pull/106492
>From 7c20ea35a39cae0c07155f441a58ec8072a2ad39 Mon Sep 17 00:00:00 2001
From: rbajpai <rbajpai at nvidia.com>
Date: Wed, 21 Aug 2024 14:48:08 +0530
Subject: [PATCH 1/2] [InstCombine] Transform (fcmp + fadd + sel) into (fcmp +
sel + fadd)
Transform `fcmp + fadd + sel` into `fcmp + sel + fadd` which enables
the possibility of lowering `fcmp + sel` into `fmax/fmin`.
---
.../InstCombine/InstCombineSelect.cpp | 49 ++++
.../InstCombine/fcmp-fadd-select.ll | 245 ++++++++++++++++++
2 files changed, 294 insertions(+)
create mode 100644 llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 66f7c4592457c2..83cf10df30b459 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3633,6 +3633,51 @@ static bool hasAffectedValue(Value *V, SmallPtrSetImpl<Value *> &Affected,
return false;
}
+static Value *foldSelectAddConstant(SelectInst &SI,
+ InstCombiner::BuilderTy &Builder) {
+ Value *Cmp;
+ Instruction *FAdd;
+ ConstantFP *C;
+
+ // select((fcmp OGT/OLT, X, 0), (fadd X, C), C) => fadd((select (fcmp OGT/OLT,
+ // X, 0), X, 0), C)
+
+ // This transformation enables the possibility of transforming fcmp + sel into
+ // a fmax/fmin.
+
+ // OneUse check for `Cmp` is necessary because it makes sure that other
+ // InstCombine folds don't undo this transformation and cause an infinite
+ // loop.
+ if (match(&SI, m_Select(m_OneUse(m_Value(Cmp)), m_OneUse(m_Instruction(FAdd)),
+ m_ConstantFP(C))) ||
+ match(&SI, m_Select(m_OneUse(m_Value(Cmp)), m_ConstantFP(C),
+ m_OneUse(m_Instruction(FAdd))))) {
+ Value *X;
+ CmpInst::Predicate Pred;
+ if (!match(Cmp, m_FCmp(Pred, m_Value(X), m_AnyZeroFP())))
+ return nullptr;
+
+ if (Pred != CmpInst::FCMP_OGT && Pred != CmpInst::FCMP_OLT)
+ return nullptr;
+
+ if (!match(FAdd, m_FAdd(m_Specific(X), m_Specific(C))))
+ return nullptr;
+
+ FastMathFlags FMF = FAdd->getFastMathFlags();
+ FMF |= SI.getFastMathFlags();
+
+ Value *NewSelect = Builder.CreateSelect(
+ Cmp, X, ConstantFP::getZero(C->getType()), SI.getName() + ".new", &SI);
+ cast<Instruction>(NewSelect)->setFastMathFlags(FMF);
+
+ Value *NewFAdd =
+ Builder.CreateFAddFMF(NewSelect, C, FAdd, FAdd->getName() + ".new");
+ return NewFAdd;
+ }
+
+ return nullptr;
+}
+
Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
Value *CondVal = SI.getCondition();
Value *TrueVal = SI.getTrueValue();
@@ -4029,6 +4074,10 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
if (Value *V = foldRoundUpIntegerWithPow2Alignment(SI, Builder))
return replaceInstUsesWith(SI, V);
+ if (Value *V = foldSelectAddConstant(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..fced2d961b2415
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll
@@ -0,0 +1,245 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+; Check for fcmp + sel pattern which later lowered into fmax
+define float @test_fmax_pos1(float %in) {
+; CHECK-LABEL: define float @test_fmax_pos1(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd 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 i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fmax_pos2(float %in) {
+; CHECK-LABEL: define float @test_fmax_pos2(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd 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 i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fmax_pos3(float %in) {
+; CHECK-LABEL: define float @test_fmax_pos3(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %add = fadd float 1.000000e+00, %in
+ %sel = select i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fmax_pos4(float %in) {
+; CHECK-LABEL: define float @test_fmax_pos4(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %add = fadd float 1.000000e+00, %in
+ %sel = select i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fmax_pos5(float %in) {
+; CHECK-LABEL: define float @test_fmax_pos5(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 2.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %add = fadd float 2.000000e+00, %in
+ %sel = select i1 %cmp1, float 2.000000e+00, float %add
+ ret float %sel
+}
+
+
+; Check for fcmp + sel pattern which later lowered into fmin
+define float @test_fmin_pos1(float %in) {
+; CHECK-LABEL: define float @test_fmin_pos1(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd 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 i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fmin_pos2(float %in) {
+; CHECK-LABEL: define float @test_fmin_pos2(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd 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 i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fmin_pos3(float %in) {
+; CHECK-LABEL: define float @test_fmin_pos3(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp olt float %in, 0.000000e+00
+ %add = fadd float 1.000000e+00, %in
+ %sel = select i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fmin_pos4(float %in) {
+; CHECK-LABEL: define float @test_fmin_pos4(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp olt float %in, 0.000000e+00
+ %add = fadd float 1.000000e+00, %in
+ %sel = select i1 %cmp1, float 1.000000e+00, float %add
+ ret float %sel
+}
+
+define float @test_fmin_pos5(float %in) {
+; CHECK-LABEL: define float @test_fmin_pos5(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[IN]], 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 2.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
+;
+ %cmp1 = fcmp olt float %in, 0.000000e+00
+ %add = fadd float 2.000000e+00, %in
+ %sel = select i1 %cmp1, float 2.000000e+00, float %add
+ ret float %sel
+}
+
+
+; Check for fmax scenarios that shouldn't be transformed.
+define float @test_fmax_neg1(float %in, float %in2) {
+; CHECK-LABEL: define float @test_fmax_neg1(
+; 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 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 i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fmax_neg2(float %in) {
+; CHECK-LABEL: define float @test_fmax_neg2(
+; 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 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 i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fmax_neg3(float %in) {
+; CHECK-LABEL: define float @test_fmax_neg3(
+; 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 i1 [[CMP1]], float [[ADD]], float 1.000000e+00
+; CHECK-NEXT: [[SEL_2:%.*]] = select 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 i1 %cmp1, float %add, float 1.000000e+00
+ %sel.2 = select i1 %cmp1, float 2.000000e+00, float %add.2
+ %res = fadd float %sel.1, %sel.2
+ ret float %res
+}
+
+
+; Check for fmin scenarios that shouldn't be transformed.
+define float @test_fmin_neg1(float %in, float %in2) {
+; CHECK-LABEL: define float @test_fmin_neg1(
+; CHECK-SAME: float [[IN:%.*]], float [[IN2:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[IN2]], 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 olt float %in2, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fmin_neg2(float %in) {
+; CHECK-LABEL: define float @test_fmin_neg2(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[IN]], 1.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 olt float %in, 1.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %sel = select i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
+}
+
+define float @test_fmin_neg3(float %in) {
+; CHECK-LABEL: define float @test_fmin_neg3(
+; CHECK-SAME: float [[IN:%.*]]) {
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt 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 i1 [[CMP1]], float [[ADD]], float 1.000000e+00
+; CHECK-NEXT: [[SEL_2:%.*]] = select 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 olt float %in, 0.000000e+00
+ %add = fadd float %in, 1.000000e+00
+ %add.2 = fadd float %in, 1.000000e+00
+ %sel.1 = select i1 %cmp1, float %add, float 1.000000e+00
+ %sel.2 = select i1 %cmp1, float 2.000000e+00, float %add.2
+ %res = fadd float %sel.1, %sel.2
+ ret float %res
+}
>From 603b7363f0f68fa48b4e3003a467626f8d73066a Mon Sep 17 00:00:00 2001
From: rbajpai <rbajpai at nvidia.com>
Date: Mon, 2 Sep 2024 10:55:36 +0530
Subject: [PATCH 2/2] Addressed review comments.
---
.../InstCombine/InstCombineSelect.cpp | 67 +-
.../InstCombine/fcmp-fadd-select.ll | 627 ++++++++++++++----
2 files changed, 548 insertions(+), 146 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 83cf10df30b459..ae91a5c7de9f26 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3633,42 +3633,56 @@ static bool hasAffectedValue(Value *V, SmallPtrSetImpl<Value *> &Affected,
return false;
}
-static Value *foldSelectAddConstant(SelectInst &SI,
- InstCombiner::BuilderTy &Builder) {
- Value *Cmp;
- Instruction *FAdd;
- ConstantFP *C;
-
- // select((fcmp OGT/OLT, X, 0), (fadd X, C), C) => fadd((select (fcmp OGT/OLT,
- // X, 0), X, 0), C)
+// 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;
- // This transformation enables the possibility of transforming fcmp + sel into
- // a fmax/fmin.
+ // 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;
- // OneUse check for `Cmp` is necessary because it makes sure that other
+ // 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.
- if (match(&SI, m_Select(m_OneUse(m_Value(Cmp)), m_OneUse(m_Instruction(FAdd)),
- m_ConstantFP(C))) ||
- match(&SI, m_Select(m_OneUse(m_Value(Cmp)), m_ConstantFP(C),
- m_OneUse(m_Instruction(FAdd))))) {
- Value *X;
- CmpInst::Predicate Pred;
- if (!match(Cmp, m_FCmp(Pred, m_Value(X), m_AnyZeroFP())))
+ 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))))) {
+ if (!match(Z, m_AnyZeroFP()))
return nullptr;
- if (Pred != CmpInst::FCMP_OGT && Pred != CmpInst::FCMP_OLT)
+ // Only these Predicates can be transformed into fmaxnum/fminnum intrinsic.
+ switch (Pred) {
+ default:
return nullptr;
+ case FCmpInst::FCMP_OGT:
+ case FCmpInst::FCMP_OGE:
+ case FCmpInst::FCMP_OLT:
+ case FCmpInst::FCMP_OLE:
+ case FCmpInst::FCMP_UGT:
+ case FCmpInst::FCMP_UGE:
+ case FCmpInst::FCMP_ULT:
+ case FCmpInst::FCMP_ULE:
+ break;
+ }
if (!match(FAdd, m_FAdd(m_Specific(X), m_Specific(C))))
return nullptr;
- FastMathFlags FMF = FAdd->getFastMathFlags();
- FMF |= SI.getFastMathFlags();
-
- Value *NewSelect = Builder.CreateSelect(
- Cmp, X, ConstantFP::getZero(C->getType()), SI.getName() + ".new", &SI);
- cast<Instruction>(NewSelect)->setFastMathFlags(FMF);
+ Value *NewSelect = Builder.CreateSelect(SI.getCondition(), X, Z,
+ SI.getName() + ".new", &SI);
+ cast<Instruction>(NewSelect)->setFastMathFlags(SI.getFastMathFlags());
Value *NewFAdd =
Builder.CreateFAddFMF(NewSelect, C, FAdd, FAdd->getName() + ".new");
@@ -4074,9 +4088,8 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
if (Value *V = foldRoundUpIntegerWithPow2Alignment(SI, Builder))
return replaceInstUsesWith(SI, V);
- if (Value *V = foldSelectAddConstant(SI, Builder)) {
+ 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()
diff --git a/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll b/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll
index fced2d961b2415..b9717f78c79ab7 100644
--- a/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll
@@ -1,245 +1,634 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
-; Check for fcmp + sel pattern which later lowered into fmax
-define float @test_fmax_pos1(float %in) {
-; CHECK-LABEL: define float @test_fmax_pos1(
+; 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: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
-; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd 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 i1 %cmp1, float %add, float 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
}
-define float @test_fmax_pos2(float %in) {
-; CHECK-LABEL: define float @test_fmax_pos2(
+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: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
-; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd 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 i1 %cmp1, float 1.000000e+00, float %add
+ %sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
ret float %sel
}
-define float @test_fmax_pos3(float %in) {
-; CHECK-LABEL: define float @test_fmax_pos3(
+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: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
-; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ogt float %in, 0.000000e+00
- %add = fadd float 1.000000e+00, %in
- %sel = select i1 %cmp1, float %add, float 1.000000e+00
+ %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_fmax_pos4(float %in) {
-; CHECK-LABEL: define float @test_fmax_pos4(
+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: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
-; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
-; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
%cmp1 = fcmp ogt float %in, 0.000000e+00
- %add = fadd float 1.000000e+00, %in
- %sel = select i1 %cmp1, float 1.000000e+00, float %add
+ %add = fadd nnan float %in, 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
}
-define float @test_fmax_pos5(float %in) {
-; CHECK-LABEL: define float @test_fmax_pos5(
+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 <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: [[CMP1:%.*]] = fcmp ogt float [[IN]], 0.000000e+00
-; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
-; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 2.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ogt float %in, 0.000000e+00
- %add = fadd float 2.000000e+00, %in
- %sel = select i1 %cmp1, float 2.000000e+00, float %add
+ %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
}
-
-; Check for fcmp + sel pattern which later lowered into fmin
-define float @test_fmin_pos1(float %in) {
-; CHECK-LABEL: define float @test_fmin_pos1(
+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: [[CMP1:%.*]] = fcmp olt float [[IN]], 0.000000e+00
-; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd 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 i1 %cmp1, float %add, float 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
ret float %sel
}
-define float @test_fmin_pos2(float %in) {
-; CHECK-LABEL: define float @test_fmin_pos2(
+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: [[CMP1:%.*]] = fcmp olt float [[IN]], 0.000000e+00
-; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd 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 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 <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 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 i1 %cmp1, float 1.000000e+00, float %add
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
}
-define float @test_fmin_pos3(float %in) {
-; CHECK-LABEL: define float @test_fmin_pos3(
+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: [[CMP1:%.*]] = fcmp olt float [[IN]], 0.000000e+00
-; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp olt float %in, 0.000000e+00
- %add = fadd float 1.000000e+00, %in
- %sel = select i1 %cmp1, float %add, float 1.000000e+00
+ %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_fmin_pos4(float %in) {
-; CHECK-LABEL: define float @test_fmin_pos4(
+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: [[CMP1:%.*]] = fcmp olt float [[IN]], 0.000000e+00
-; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp olt float %in, 0.000000e+00
- %add = fadd float 1.000000e+00, %in
- %sel = select i1 %cmp1, float 1.000000e+00, float %add
+ %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_fmin_pos5(float %in) {
-; CHECK-LABEL: define float @test_fmin_pos5(
+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: [[CMP1:%.*]] = fcmp olt float [[IN]], 0.000000e+00
-; CHECK-NEXT: [[SEL_NEW:%.*]] = select i1 [[CMP1]], float [[IN]], float 0.000000e+00
-; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 2.000000e+00
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp olt float %in, 0.000000e+00
- %add = fadd float 2.000000e+00, %in
- %sel = select i1 %cmp1, float 2.000000e+00, float %add
+ %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 <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
+}
-; Check for fmax scenarios that shouldn't be transformed.
-define float @test_fmax_neg1(float %in, float %in2) {
-; CHECK-LABEL: define float @test_fmax_neg1(
-; 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 i1 [[CMP1]], float [[ADD]], float 1.000000e+00
-; CHECK-NEXT: ret 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 float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ogt float %in2, 0.000000e+00
+ %cmp1 = fcmp ole float %in, 0.000000e+00
%add = fadd float %in, 1.000000e+00
- %sel = select i1 %cmp1, float %add, float 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
}
-define float @test_fmax_neg2(float %in) {
-; CHECK-LABEL: define float @test_fmax_neg2(
+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: [[CMP1:%.*]] = fcmp ogt float [[IN]], 1.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]]
+; CHECK-NEXT: [[SEL_NEW:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[IN]], float 0.000000e+00)
+; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd float [[SEL_NEW]], 1.000000e+00
+; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ogt float %in, 1.000000e+00
+ %cmp1 = fcmp ole float %in, 0.000000e+00
%add = fadd float %in, 1.000000e+00
- %sel = select i1 %cmp1, float %add, float 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 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 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 <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 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 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 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 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 <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 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 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 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_fmax_neg3(float %in) {
-; CHECK-LABEL: define float @test_fmax_neg3(
+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 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 <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 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 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 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 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 <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 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 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 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 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 <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: [[ADD_2:%.*]] = fadd float [[IN]], 1.000000e+00
-; CHECK-NEXT: [[SEL_1:%.*]] = select i1 [[CMP1]], float [[ADD]], float 1.000000e+00
-; CHECK-NEXT: [[SEL_2:%.*]] = select i1 [[CMP1]], float 2.000000e+00, float [[ADD_2]]
-; CHECK-NEXT: [[RES:%.*]] = fadd float [[SEL_1]], [[SEL_2]]
-; CHECK-NEXT: ret float [[RES]]
+; 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
- %add.2 = fadd float %in, 1.000000e+00
- %sel.1 = select i1 %cmp1, float %add, float 1.000000e+00
- %sel.2 = select i1 %cmp1, float 2.000000e+00, float %add.2
- %res = fadd float %sel.1, %sel.2
- ret float %res
+ %sel = select i1 %cmp1, float %add, float 1.000000e+00
+ ret float %sel
}
-
-; Check for fmin scenarios that shouldn't be transformed.
-define float @test_fmin_neg1(float %in, float %in2) {
-; CHECK-LABEL: define float @test_fmin_neg1(
+; 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 olt float [[IN2]], 0.000000e+00
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[IN2]], 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: [[SEL:%.*]] = select nnan nsz i1 [[CMP1]], float [[ADD]], float 1.000000e+00
; CHECK-NEXT: ret float [[SEL]]
;
- %cmp1 = fcmp olt float %in2, 0.000000e+00
+ %cmp1 = fcmp ogt float %in2, 0.000000e+00
%add = fadd float %in, 1.000000e+00
- %sel = select i1 %cmp1, float %add, float 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
}
-define float @test_fmin_neg2(float %in) {
-; CHECK-LABEL: define float @test_fmin_neg2(
+; 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 olt float [[IN]], 1.000000e+00
+; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[IN]], 1.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: [[SEL:%.*]] = select nnan nsz i1 [[CMP1]], float [[ADD]], float 1.000000e+00
; CHECK-NEXT: ret float [[SEL]]
;
- %cmp1 = fcmp olt float %in, 1.000000e+00
+ %cmp1 = fcmp ogt float %in, 1.000000e+00
%add = fadd float %in, 1.000000e+00
- %sel = select i1 %cmp1, float %add, float 1.000000e+00
+ %sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
}
-define float @test_fmin_neg3(float %in) {
-; CHECK-LABEL: define float @test_fmin_neg3(
+; 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 olt float [[IN]], 0.000000e+00
+; 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 i1 [[CMP1]], float [[ADD]], float 1.000000e+00
-; CHECK-NEXT: [[SEL_2:%.*]] = select i1 [[CMP1]], float 2.000000e+00, float [[ADD_2]]
+; 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 olt float %in, 0.000000e+00
+ %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 i1 %cmp1, float %add, float 1.000000e+00
- %sel.2 = select i1 %cmp1, float 2.000000e+00, float %add.2
+ %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
}
More information about the llvm-commits
mailing list