diff options
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 16 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/maxnum.ll | 19 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/minnum.ll | 18 |
3 files changed, 32 insertions, 21 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index c0c6a0db1c9..d36380ee6f3 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1952,8 +1952,24 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { II->setArgOperand(1, Arg0); return II; } + + // FIXME: Simplifications should be in instsimplify. if (Value *V = simplifyMinnumMaxnum(*II)) return replaceInstUsesWith(*II, V); + + Value *X, *Y; + if (match(Arg0, m_FNeg(m_Value(X))) && match(Arg1, m_FNeg(m_Value(Y))) && + (Arg0->hasOneUse() || Arg1->hasOneUse())) { + // If both operands are negated, invert the call and negate the result: + // minnum(-X, -Y) --> -(maxnum(X, Y)) + // maxnum(-X, -Y) --> -(minnum(X, Y)) + Intrinsic::ID NewIID = II->getIntrinsicID() == Intrinsic::maxnum ? + Intrinsic::minnum : Intrinsic::maxnum; + Value *NewCall = Builder.CreateIntrinsic(NewIID, { X, Y }, II); + Instruction *FNeg = BinaryOperator::CreateFNeg(NewCall); + FNeg->copyIRFlags(II); + return FNeg; + } break; } case Intrinsic::fmuladd: { diff --git a/llvm/test/Transforms/InstCombine/maxnum.ll b/llvm/test/Transforms/InstCombine/maxnum.ll index 8a7c88b47fb..11bff42391a 100644 --- a/llvm/test/Transforms/InstCombine/maxnum.ll +++ b/llvm/test/Transforms/InstCombine/maxnum.ll @@ -253,9 +253,8 @@ define float @fold_maxnum_f32_neginf_val(float %x) { define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) { ; CHECK-LABEL: @neg_neg( -; CHECK-NEXT: [[NEGX:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[X:%.*]] -; CHECK-NEXT: [[NEGY:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = call <2 x float> @llvm.maxnum.v2f32(<2 x float> [[NEGX]], <2 x float> [[NEGY]]) +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.minnum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]] ; CHECK-NEXT: ret <2 x float> [[R]] ; %negx = fsub <2 x float> <float -0.0, float -0.0>, %x @@ -265,13 +264,11 @@ define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) { } ; FMF is not required, but it should be propagated from the intrinsic (not the fnegs). -; Also, make sure this works with vectors. define float @neg_neg_vec_fmf(float %x, float %y) { ; CHECK-LABEL: @neg_neg_vec_fmf( -; CHECK-NEXT: [[NEGX:%.*]] = fsub arcp float -0.000000e+00, [[X:%.*]] -; CHECK-NEXT: [[NEGY:%.*]] = fsub afn float -0.000000e+00, [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = call fast float @llvm.maxnum.f32(float [[NEGX]], float [[NEGY]]) +; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub fast float -0.000000e+00, [[TMP1]] ; CHECK-NEXT: ret float [[R]] ; %negx = fsub arcp float -0.0, %x @@ -287,8 +284,8 @@ declare void @use(float) define float @neg_neg_extra_use_x(float %x, float %y) { ; CHECK-LABEL: @neg_neg_extra_use_x( ; CHECK-NEXT: [[NEGX:%.*]] = fsub float -0.000000e+00, [[X:%.*]] -; CHECK-NEXT: [[NEGY:%.*]] = fsub float -0.000000e+00, [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[NEGX]], float [[NEGY]]) +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]] ; CHECK-NEXT: call void @use(float [[NEGX]]) ; CHECK-NEXT: ret float [[R]] ; @@ -301,9 +298,9 @@ define float @neg_neg_extra_use_x(float %x, float %y) { define float @neg_neg_extra_use_y(float %x, float %y) { ; CHECK-LABEL: @neg_neg_extra_use_y( -; CHECK-NEXT: [[NEGX:%.*]] = fsub float -0.000000e+00, [[X:%.*]] ; CHECK-NEXT: [[NEGY:%.*]] = fsub float -0.000000e+00, [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(float [[NEGX]], float [[NEGY]]) +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y]]) +; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]] ; CHECK-NEXT: call void @use(float [[NEGY]]) ; CHECK-NEXT: ret float [[R]] ; diff --git a/llvm/test/Transforms/InstCombine/minnum.ll b/llvm/test/Transforms/InstCombine/minnum.ll index dfc040681ad..a05ce8c545c 100644 --- a/llvm/test/Transforms/InstCombine/minnum.ll +++ b/llvm/test/Transforms/InstCombine/minnum.ll @@ -277,9 +277,8 @@ define float @fold_minnum_f32_minf_val(float %x) { define double @neg_neg(double %x, double %y) { ; CHECK-LABEL: @neg_neg( -; CHECK-NEXT: [[NEGX:%.*]] = fsub double -0.000000e+00, [[X:%.*]] -; CHECK-NEXT: [[NEGY:%.*]] = fsub double -0.000000e+00, [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = call double @llvm.minnum.f64(double [[NEGX]], double [[NEGY]]) +; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] ; CHECK-NEXT: ret double [[R]] ; %negx = fsub double -0.0, %x @@ -293,9 +292,8 @@ define double @neg_neg(double %x, double %y) { define <2 x double> @neg_neg_vec_fmf(<2 x double> %x, <2 x double> %y) { ; CHECK-LABEL: @neg_neg_vec_fmf( -; CHECK-NEXT: [[NEGX:%.*]] = fsub reassoc <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[X:%.*]] -; CHECK-NEXT: [[NEGY:%.*]] = fsub fast <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = call nnan ninf <2 x double> @llvm.minnum.v2f64(<2 x double> [[NEGX]], <2 x double> [[NEGY]]) +; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf <2 x double> @llvm.maxnum.v2f64(<2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub nnan ninf <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[TMP1]] ; CHECK-NEXT: ret <2 x double> [[R]] ; %negx = fsub reassoc <2 x double> <double -0.0, double -0.0>, %x @@ -311,8 +309,8 @@ declare void @use(double) define double @neg_neg_extra_use_x(double %x, double %y) { ; CHECK-LABEL: @neg_neg_extra_use_x( ; CHECK-NEXT: [[NEGX:%.*]] = fsub double -0.000000e+00, [[X:%.*]] -; CHECK-NEXT: [[NEGY:%.*]] = fsub double -0.000000e+00, [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = call double @llvm.minnum.f64(double [[NEGX]], double [[NEGY]]) +; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maxnum.f64(double [[X]], double [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] ; CHECK-NEXT: call void @use(double [[NEGX]]) ; CHECK-NEXT: ret double [[R]] ; @@ -325,9 +323,9 @@ define double @neg_neg_extra_use_x(double %x, double %y) { define double @neg_neg_extra_use_y(double %x, double %y) { ; CHECK-LABEL: @neg_neg_extra_use_y( -; CHECK-NEXT: [[NEGX:%.*]] = fsub double -0.000000e+00, [[X:%.*]] ; CHECK-NEXT: [[NEGY:%.*]] = fsub double -0.000000e+00, [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = call double @llvm.minnum.f64(double [[NEGX]], double [[NEGY]]) +; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maxnum.f64(double [[X:%.*]], double [[Y]]) +; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] ; CHECK-NEXT: call void @use(double [[NEGY]]) ; CHECK-NEXT: ret double [[R]] ; |