From 89d3405bf7458679ffd6a9550f1e439a4b19f84f Mon Sep 17 00:00:00 2001 From: rbajpai Date: Wed, 21 Aug 2024 14:48:08 +0530 Subject: [PATCH 1/7] [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 c5f39a4c381ed..99bc3708355ca 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3640,6 +3640,51 @@ static bool hasAffectedValue(Value *V, SmallPtrSetImpl &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(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(); @@ -4036,6 +4081,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 0000000000000..fced2d961b241 --- /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 4210a4c5dc1cc0b774fec7a6a44c6274a91f54ec Mon Sep 17 00:00:00 2001 From: rbajpai Date: Mon, 2 Sep 2024 10:55:36 +0530 Subject: [PATCH 2/7] 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 99bc3708355ca..f8b5012090314 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3640,42 +3640,56 @@ static bool hasAffectedValue(Value *V, SmallPtrSetImpl &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(&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(NewSelect)->setFastMathFlags(FMF); + Value *NewSelect = Builder.CreateSelect(SI.getCondition(), X, Z, + SI.getName() + ".new", &SI); + cast(NewSelect)->setFastMathFlags(SI.getFastMathFlags()); Value *NewFAdd = Builder.CreateFAddFMF(NewSelect, C, FAdd, FAdd->getName() + ".new"); @@ -4081,9 +4095,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 fced2d961b241..b9717f78c79ab 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]], +; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] +; + %cmp1 = fcmp ogt <2 x float> %in, + %add = fadd <2 x float> %in, + %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> + 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]], +; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] +; + %cmp1 = fcmp olt <2 x float> %in, + %add = fadd <2 x float> %in, + %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> + 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]], +; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] +; + %cmp1 = fcmp oge <2 x float> %in, + %add = fadd <2 x float> %in, + %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> + 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]], +; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] +; + %cmp1 = fcmp ole <2 x float> %in, + %add = fadd <2 x float> %in, + %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> + 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]], +; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] +; + %cmp1 = fcmp ugt <2 x float> %in, + %add = fadd <2 x float> %in, + %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> + 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]], +; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] +; + %cmp1 = fcmp uge <2 x float> %in, + %add = fadd <2 x float> %in, + %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> + 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]], +; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] +; + %cmp1 = fcmp ult <2 x float> %in, + %add = fadd <2 x float> %in, + %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> + 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]], +; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] +; + %cmp1 = fcmp ule <2 x float> %in, + %add = fadd <2 x float> %in, + %sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> + 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 } From ca985dff8b8abae55b4ce580c3e69909d39f6cf1 Mon Sep 17 00:00:00 2001 From: rbajpai Date: Mon, 30 Sep 2024 15:53:48 +0530 Subject: [PATCH 3/7] Addressed review comments. --- .../InstCombine/InstCombineSelect.cpp | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index f8b5012090314..6558ba23bd4ae 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3661,7 +3661,7 @@ static Value *foldSelectIntoAddConstant(SelectInst &SI, // 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. + // 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))), @@ -3669,31 +3669,19 @@ static Value *foldSelectIntoAddConstant(SelectInst &SI, if (!match(Z, m_AnyZeroFP())) return nullptr; - // Only these Predicates can be transformed into fmaxnum/fminnum intrinsic. - switch (Pred) { - default: + // Only these relational predicates can be transformed into maxnum/minnum + // intrinsic. + if (!CmpInst::isRelational(Pred)) 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; - Value *NewSelect = Builder.CreateSelect(SI.getCondition(), X, Z, - SI.getName() + ".new", &SI); + Value *NewSelect = + Builder.CreateSelect(SI.getCondition(), X, Z, SI.getName(), &SI); cast(NewSelect)->setFastMathFlags(SI.getFastMathFlags()); - Value *NewFAdd = - Builder.CreateFAddFMF(NewSelect, C, FAdd, FAdd->getName() + ".new"); - return NewFAdd; + return Builder.CreateFAddFMF(NewSelect, C, FAdd, FAdd->getName()); } return nullptr; From e3145629f84d8b27c22d84815a2c9013843a66da Mon Sep 17 00:00:00 2001 From: rbajpai Date: Fri, 4 Oct 2024 13:19:15 +0530 Subject: [PATCH 4/7] Added `takeName` calls to take name from existing instructions --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 6558ba23bd4ae..9fe8c0febe6db 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3677,11 +3677,13 @@ static Value *foldSelectIntoAddConstant(SelectInst &SI, if (!match(FAdd, m_FAdd(m_Specific(X), m_Specific(C)))) return nullptr; - Value *NewSelect = - Builder.CreateSelect(SI.getCondition(), X, Z, SI.getName(), &SI); + Value *NewSelect = Builder.CreateSelect(SI.getCondition(), X, Z, "", &SI); cast(NewSelect)->setFastMathFlags(SI.getFastMathFlags()); + NewSelect->takeName(&SI); - return Builder.CreateFAddFMF(NewSelect, C, FAdd, FAdd->getName()); + Value *NewFAdd = Builder.CreateFAddFMF(NewSelect, C, FAdd); + NewFAdd->takeName(FAdd); + return NewFAdd; } return nullptr; From 1a434e92b1959c8c70a9c1ff35f59b9d9eb0e9ec Mon Sep 17 00:00:00 2001 From: rbajpai Date: Fri, 4 Oct 2024 13:25:01 +0530 Subject: [PATCH 5/7] Combine two if conditions into one. --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 9fe8c0febe6db..82a2534c1cdbe 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3666,12 +3666,9 @@ static Value *foldSelectIntoAddConstant(SelectInst &SI, 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; - // Only these relational predicates can be transformed into maxnum/minnum // intrinsic. - if (!CmpInst::isRelational(Pred)) + if (!CmpInst::isRelational(Pred) || !match(Z, m_AnyZeroFP())) return nullptr; if (!match(FAdd, m_FAdd(m_Specific(X), m_Specific(C)))) From f3892479f0ec8e4f51c56c1d920558054f4a23e8 Mon Sep 17 00:00:00 2001 From: rbajpai Date: Tue, 8 Oct 2024 15:51:55 +0530 Subject: [PATCH 6/7] Added intersection of rewrite-based flags. --- .../InstCombine/InstCombineSelect.cpp | 29 +++++++++++++++++-- .../InstCombine/fcmp-fadd-select.ll | 27 +++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 82a2534c1cdbe..0348ea50aa764 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3675,11 +3675,36 @@ static Value *foldSelectIntoAddConstant(SelectInst &SI, return nullptr; Value *NewSelect = Builder.CreateSelect(SI.getCondition(), X, Z, "", &SI); - cast(NewSelect)->setFastMathFlags(SI.getFastMathFlags()); NewSelect->takeName(&SI); - Value *NewFAdd = Builder.CreateFAddFMF(NewSelect, C, FAdd); + Value *NewFAdd = Builder.CreateFAdd(NewSelect, C); NewFAdd->takeName(FAdd); + + // Propagate rewrite-based flags + auto SelectFMF = SI.getFastMathFlags(); + auto FAddFMF = FAdd->getFastMathFlags(); + FastMathFlags CommonFMF, NewFAddFMF, NewSelectFMF; + + CommonFMF.setAllowReassoc(SelectFMF.allowReassoc() && + FAddFMF.allowReassoc()); + CommonFMF.setAllowReciprocal(SelectFMF.allowReciprocal() && + FAddFMF.allowReciprocal()); + CommonFMF.setAllowContract(SelectFMF.allowContract() && + FAddFMF.allowContract()); + CommonFMF.setApproxFunc(SelectFMF.approxFunc() && FAddFMF.approxFunc()); + NewSelectFMF = NewFAddFMF = CommonFMF; + + // Propagate FastMath flags + NewFAddFMF.setNoNaNs(FAddFMF.noNaNs()); + NewFAddFMF.setNoInfs(FAddFMF.noInfs()); + NewFAddFMF.setNoSignedZeros(FAddFMF.noSignedZeros()); + cast(NewFAdd)->setFastMathFlags(NewFAddFMF); + + NewSelectFMF.setNoNaNs(SelectFMF.noNaNs()); + NewSelectFMF.setNoInfs(SelectFMF.noInfs()); + NewSelectFMF.setNoSignedZeros(SelectFMF.noSignedZeros()); + cast(NewSelect)->setFastMathFlags(NewSelectFMF); + return NewFAdd; } diff --git a/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll b/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll index b9717f78c79ab..dd6ee8197cdab 100644 --- a/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll +++ b/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll @@ -632,3 +632,30 @@ define float @test_fcmp_multiple_uses(float %in) { %res = fadd float %sel.1, %sel.2 ret float %res } + +; Rewrite-based flags propagation +define float @test_fcmp_ogt_fadd_select_rewrite_flags(float %in) { +; CHECK-LABEL: define float @test_fcmp_ogt_fadd_select_rewrite_flags( +; 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 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_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 float %in, 1.000000e+00 + %sel = select fast i1 %cmp1, float %add, float 1.000000e+00 + ret float %sel +} From 77fc700425bd77789059623fc83d92ca58cb9bb2 Mon Sep 17 00:00:00 2001 From: rbajpai Date: Mon, 21 Oct 2024 12:03:11 +0530 Subject: [PATCH 7/7] Added `intersectRewrite` and `unionValue` apis in FastMath class. --- llvm/include/llvm/IR/FMF.h | 14 +++ .../InstCombine/InstCombineSelect.cpp | 29 ++--- .../InstCombine/fcmp-fadd-select.ll | 101 ++++++++++-------- 3 files changed, 77 insertions(+), 67 deletions(-) diff --git a/llvm/include/llvm/IR/FMF.h b/llvm/include/llvm/IR/FMF.h index f063060567db2..d204d0a0e9d9a 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 0348ea50aa764..df08050aa4abd 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3680,30 +3680,13 @@ static Value *foldSelectIntoAddConstant(SelectInst &SI, Value *NewFAdd = Builder.CreateFAdd(NewSelect, C); NewFAdd->takeName(FAdd); - // Propagate rewrite-based flags - auto SelectFMF = SI.getFastMathFlags(); - auto FAddFMF = FAdd->getFastMathFlags(); - FastMathFlags CommonFMF, NewFAddFMF, NewSelectFMF; - - CommonFMF.setAllowReassoc(SelectFMF.allowReassoc() && - FAddFMF.allowReassoc()); - CommonFMF.setAllowReciprocal(SelectFMF.allowReciprocal() && - FAddFMF.allowReciprocal()); - CommonFMF.setAllowContract(SelectFMF.allowContract() && - FAddFMF.allowContract()); - CommonFMF.setApproxFunc(SelectFMF.approxFunc() && FAddFMF.approxFunc()); - NewSelectFMF = NewFAddFMF = CommonFMF; - // Propagate FastMath flags - NewFAddFMF.setNoNaNs(FAddFMF.noNaNs()); - NewFAddFMF.setNoInfs(FAddFMF.noInfs()); - NewFAddFMF.setNoSignedZeros(FAddFMF.noSignedZeros()); - cast(NewFAdd)->setFastMathFlags(NewFAddFMF); - - NewSelectFMF.setNoNaNs(SelectFMF.noNaNs()); - NewSelectFMF.setNoInfs(SelectFMF.noInfs()); - NewSelectFMF.setNoSignedZeros(SelectFMF.noSignedZeros()); - cast(NewSelect)->setFastMathFlags(NewSelectFMF); + FastMathFlags SelectFMF = SI.getFastMathFlags(); + FastMathFlags FAddFMF = FAdd->getFastMathFlags(); + FastMathFlags NewFMF = FastMathFlags::intersectRewrite(SelectFMF, FAddFMF) | + FastMathFlags::unionValue(SelectFMF, FAddFMF); + cast(NewFAdd)->setFastMathFlags(NewFMF); + cast(NewSelect)->setFastMathFlags(NewFMF); return NewFAdd; } diff --git a/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll b/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll index dd6ee8197cdab..9f9cf7a633c87 100644 --- a/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll +++ b/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll @@ -7,7 +7,7 @@ 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 float [[SEL_NEW]], 1.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 @@ -20,7 +20,7 @@ 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 float [[SEL_NEW]], 1.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 @@ -33,7 +33,7 @@ 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 float [[SEL_NEW]], 1.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 @@ -46,7 +46,7 @@ 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 float [[SEL_NEW]], 1.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 @@ -59,7 +59,7 @@ 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]], +; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], ; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] ; %cmp1 = fcmp ogt <2 x float> %in, @@ -75,7 +75,7 @@ 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 float [[SEL_NEW]], 1.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 @@ -88,7 +88,7 @@ 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 float [[SEL_NEW]], 1.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 @@ -101,7 +101,7 @@ 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 float [[SEL_NEW]], 1.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 @@ -114,7 +114,7 @@ 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: [[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 @@ -127,7 +127,7 @@ 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]], +; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], ; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] ; %cmp1 = fcmp olt <2 x float> %in, @@ -143,7 +143,7 @@ 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: [[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 @@ -156,7 +156,7 @@ 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 float [[SEL_NEW]], 1.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 @@ -169,7 +169,7 @@ 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 float [[SEL_NEW]], 1.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 @@ -182,7 +182,7 @@ 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 float [[SEL_NEW]], 1.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 @@ -195,7 +195,7 @@ 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]], +; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], ; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] ; %cmp1 = fcmp oge <2 x float> %in, @@ -211,7 +211,7 @@ 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: [[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 @@ -224,7 +224,7 @@ 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 float [[SEL_NEW]], 1.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 @@ -237,7 +237,7 @@ 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: [[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 @@ -250,7 +250,7 @@ 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: [[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 @@ -263,7 +263,7 @@ 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]], +; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], ; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] ; %cmp1 = fcmp ole <2 x float> %in, @@ -280,7 +280,7 @@ define float @test_fcmp_ugt_fadd_select_constant(float %in) { ; 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: [[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 @@ -294,7 +294,7 @@ define float @test_fcmp_ugt_fadd_select_constant_swapped(float %in) { ; 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: [[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 @@ -308,7 +308,7 @@ define float @test_fcmp_ugt_fadd_select_neg_constant(float %in) { ; 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: [[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 @@ -322,7 +322,7 @@ define float @test_fcmp_ugt_fadd_select_fastmath_preserve(float %in) { ; 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: [[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 @@ -336,7 +336,7 @@ define <2 x float> @test_fcmp_ugt_fadd_select_constant_vectors(<2 x float> %in) ; 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]], +; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], ; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] ; %cmp1 = fcmp ugt <2 x float> %in, @@ -353,7 +353,7 @@ define float @test_fcmp_uge_fadd_select_constant(float %in) { ; 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: [[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 @@ -367,7 +367,7 @@ define float @test_fcmp_uge_fadd_select_constant_swapped(float %in) { ; 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: [[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 @@ -381,7 +381,7 @@ define float @test_fcmp_uge_fadd_select_neg_constant(float %in) { ; 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: [[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 @@ -395,7 +395,7 @@ define float @test_fcmp_uge_fadd_select_fastmath_preserve(float %in) { ; 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: [[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 @@ -409,7 +409,7 @@ define <2 x float> @test_fcmp_uge_fadd_select_constant_vectors(<2 x float> %in) ; 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]], +; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], ; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] ; %cmp1 = fcmp uge <2 x float> %in, @@ -426,7 +426,7 @@ define float @test_fcmp_ult_fadd_select_constant(float %in) { ; 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: [[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 @@ -440,7 +440,7 @@ define float @test_fcmp_ult_fadd_select_constant_swapped(float %in) { ; 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: [[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 @@ -454,7 +454,7 @@ define float @test_fcmp_ult_fadd_select_neg_constant(float %in) { ; 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: [[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 @@ -468,7 +468,7 @@ define float @test_fcmp_ult_fadd_select_fastmath_preserve(float %in) { ; 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: [[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 @@ -482,7 +482,7 @@ define <2 x float> @test_fcmp_ult_fadd_select_constant_vectors(<2 x float> %in) ; 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]], +; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], ; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] ; %cmp1 = fcmp ult <2 x float> %in, @@ -499,7 +499,7 @@ define float @test_fcmp_ule_fadd_select_constant(float %in) { ; 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: [[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 @@ -513,7 +513,7 @@ define float @test_fcmp_ule_fadd_select_constant_swapped(float %in) { ; 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: [[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 @@ -527,7 +527,7 @@ define float @test_fcmp_ule_fadd_select_neg_constant(float %in) { ; 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: [[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 @@ -541,7 +541,7 @@ define float @test_fcmp_ule_fadd_select_fastmath_preserve(float %in) { ; 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: [[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 @@ -555,7 +555,7 @@ define <2 x float> @test_fcmp_ule_fadd_select_constant_vectors(<2 x float> %in) ; 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]], +; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], ; CHECK-NEXT: ret <2 x float> [[ADD_NEW]] ; %cmp1 = fcmp ule <2 x float> %in, @@ -634,11 +634,11 @@ define float @test_fcmp_multiple_uses(float %in) { } ; Rewrite-based flags propagation -define float @test_fcmp_ogt_fadd_select_rewrite_flags(float %in) { -; CHECK-LABEL: define float @test_fcmp_ogt_fadd_select_rewrite_flags( +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 arcp contract afn float [[SEL_NEW]], 1.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 @@ -647,6 +647,19 @@ define float @test_fcmp_ogt_fadd_select_rewrite_flags(float %in) { 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:%.*]]) { @@ -655,7 +668,7 @@ define float @test_fcmp_ogt_fadd_select_rewrite_and_fastmath(float %in) { ; CHECK-NEXT: ret float [[ADD_NEW]] ; %cmp1 = fcmp ogt float %in, 0.000000e+00 - %add = fadd fast float %in, 1.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 }