From 83c2fb9f66be0eab489818ca87027dd2dbfeaa8e Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Fri, 5 Nov 2021 17:32:24 -0400 Subject: [PATCH] [InstCombine] match usub.sat from umax intrinsic umax(X, Op1) - Op1 --> usub.sat(X, Op1) https://alive2.llvm.org/ce/z/HpcGiJ This happens in 2 or more steps with an icmp-select idiom instead of an intrinsic. This is another step towards canonicalization of the min/max intrinsics. See: D98152 --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 7 +++++++ llvm/test/Transforms/InstCombine/minmax-intrinsics.ll | 5 ++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 6c93969..2c43158 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -2168,6 +2168,13 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) { return replaceInstUsesWith( I, Builder.CreateIntrinsic(Intrinsic::umin, {I.getType()}, {Op0, Y})); + // umax(X, Op1) - Op1 --> usub.sat(X, Op1) + // TODO: The one-use restriction is not strictly necessary, but it may + // require improving other pattern matching and/or codegen. + if (match(Op0, m_OneUse(m_UMax(m_Value(X), m_Specific(Op1))))) + return replaceInstUsesWith( + I, Builder.CreateIntrinsic(Intrinsic::usub_sat, {Ty}, {X, Op1})); + // C - ctpop(X) => ctpop(~X) if C is bitwidth if (match(Op0, m_SpecificInt(Ty->getScalarSizeInBits())) && match(Op1, m_OneUse(m_Intrinsic(m_Value(X))))) diff --git a/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll b/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll index 573ed8e..6c55c23 100644 --- a/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll +++ b/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll @@ -2132,9 +2132,8 @@ define <3 x i8> @umax_vector_splat_undef(<3 x i8> %x) { define <3 x i8> @umax_sub_vec(<3 x i8> %x, <3 x i8> %y) { ; CHECK-LABEL: @umax_sub_vec( -; CHECK-NEXT: [[U:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = sub <3 x i8> [[U]], [[Y]] -; CHECK-NEXT: ret <3 x i8> [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i8> @llvm.usub.sat.v3i8(<3 x i8> [[X:%.*]], <3 x i8> [[Y:%.*]]) +; CHECK-NEXT: ret <3 x i8> [[TMP1]] ; %u = call <3 x i8> @llvm.umax.v3i8(<3 x i8> %x, <3 x i8> %y) %r = sub <3 x i8> %u, %y -- 2.7.4