From 20aaebbdebe3a6e61bee3bccac98843f300f4d0f Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sat, 2 Mar 2019 16:45:10 +0000 Subject: [PATCH] [InstCombine] move add after smin/smax Follow-up to rL355221. This isn't specifically called for within PR14613, but we'll get there eventually if it's not already requested in some other bug report. https://rise4fun.com/Alive/5b0 Name: smax Pre: WillNotOverflowSignedSub(C1,C0) %a = add nsw i8 %x, C0 %cond = icmp sgt i8 %a, C1 %r = select i1 %cond, i8 %a, i8 C1 => %c2 = icmp sgt i8 %x, C1-C0 %u2 = select i1 %c2, i8 %x, i8 C1-C0 %r = add nsw i8 %u2, C0 Name: smin Pre: WillNotOverflowSignedSub(C1,C0) %a = add nsw i32 %x, C0 %cond = icmp slt i32 %a, C1 %r = select i1 %cond, i32 %a, i32 C1 => %c2 = icmp slt i32 %x, C1-C0 %u2 = select i1 %c2, i32 %x, i32 C1-C0 %r = add nsw i32 %u2, C0 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355272 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineSelect.cpp | 19 +++++- test/Transforms/InstCombine/minmax-fold.ll | 64 ++++++++----------- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index b39a4648579..582353eba1c 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1566,7 +1566,7 @@ static Instruction *foldSelectCmpXchg(SelectInst &SI) { static Instruction *moveAddAfterMinMax(SelectPatternFlavor SPF, Value *X, Value *Y, InstCombiner::BuilderTy &Builder) { - assert (SelectPatternResult::isMinOrMax(SPF) && "Expected min/max pattern"); + assert(SelectPatternResult::isMinOrMax(SPF) && "Expected min/max pattern"); bool IsUnsigned = SPF == SelectPatternFlavor::SPF_UMIN || SPF == SelectPatternFlavor::SPF_UMAX; // TODO: If InstSimplify could fold all cases where C2 <= C1, we could change @@ -1582,8 +1582,21 @@ static Instruction *moveAddAfterMinMax(SelectPatternFlavor SPF, Value *X, return BinaryOperator::CreateNUW(BinaryOperator::Add, NewMinMax, ConstantInt::get(X->getType(), *C1)); } - // TODO: Handle SMIN/SMAX (similar to unsigned, but the signed subtraction of - // the constants must not overflow). + + if (!IsUnsigned && match(X, m_NSWAdd(m_Value(A), m_APInt(C1))) && + match(Y, m_APInt(C2)) && X->hasNUses(2)) { + bool Overflow; + APInt Diff = C2->ssub_ov(*C1, Overflow); + if (!Overflow) { + // smin (add nsw A, C1), C2 --> add nsw (smin A, C2 - C1), C1 + // smax (add nsw A, C1), C2 --> add nsw (smax A, C2 - C1), C1 + Value *NewMinMax = createMinMax(Builder, SPF, A, + ConstantInt::get(X->getType(), Diff)); + return BinaryOperator::CreateNSW(BinaryOperator::Add, NewMinMax, + ConstantInt::get(X->getType(), *C1)); + } + } + return nullptr; } diff --git a/test/Transforms/InstCombine/minmax-fold.ll b/test/Transforms/InstCombine/minmax-fold.ll index 0e232df9582..d312155c523 100644 --- a/test/Transforms/InstCombine/minmax-fold.ll +++ b/test/Transforms/InstCombine/minmax-fold.ll @@ -1164,9 +1164,9 @@ define i8 @PR14613_umax(i8 %x) { define i32 @add_smin(i32 %x) { ; CHECK-LABEL: @add_smin( -; CHECK-NEXT: [[A:%.*]] = add nsw i32 [[X:%.*]], 15 -; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[A]], 42 -; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A]], i32 42 +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 27 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 27 +; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[TMP2]], 15 ; CHECK-NEXT: ret i32 [[R]] ; %a = add nsw i32 %x, 15 @@ -1177,9 +1177,9 @@ define i32 @add_smin(i32 %x) { define i32 @add_smin_constant_limit(i32 %x) { ; CHECK-LABEL: @add_smin_constant_limit( -; CHECK-NEXT: [[A:%.*]] = add nsw i32 [[X:%.*]], -3 -; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[A]], 2147483643 -; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A]], i32 2147483643 +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 2147483646 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 2147483646 +; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[TMP2]], -3 ; CHECK-NEXT: ret i32 [[R]] ; %a = add nsw i32 %x, -3 @@ -1193,9 +1193,7 @@ define i32 @add_smin_constant_limit(i32 %x) { define i32 @add_smin_simplify(i32 %x) { ; CHECK-LABEL: @add_smin_simplify( -; CHECK-NEXT: [[A:%.*]] = add nsw i32 [[X:%.*]], -3 -; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[A]], 2147483644 -; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A]], i32 2147483644 +; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[X:%.*]], -3 ; CHECK-NEXT: ret i32 [[R]] ; %a = add nsw i32 %x, -3 @@ -1267,9 +1265,9 @@ define i32 @add_smin_extra_use(i32 %x, i32* %p) { define <2 x i16> @add_smin_vec(<2 x i16> %x) { ; CHECK-LABEL: @add_smin_vec( -; CHECK-NEXT: [[A:%.*]] = add nsw <2 x i16> [[X:%.*]], -; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i16> [[A]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[C]], <2 x i16> [[A]], <2 x i16> +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i16> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i16> [[X]], <2 x i16> +; CHECK-NEXT: [[R:%.*]] = add nsw <2 x i16> [[TMP2]], ; CHECK-NEXT: ret <2 x i16> [[R]] ; %a = add nsw <2 x i16> %x, @@ -1280,9 +1278,9 @@ define <2 x i16> @add_smin_vec(<2 x i16> %x) { define i37 @add_smax(i37 %x) { ; CHECK-LABEL: @add_smax( -; CHECK-NEXT: [[A:%.*]] = add nsw i37 [[X:%.*]], 5 -; CHECK-NEXT: [[C:%.*]] = icmp sgt i37 [[A]], 42 -; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i37 [[A]], i37 42 +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i37 [[X:%.*]], 37 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i37 [[X]], i37 37 +; CHECK-NEXT: [[R:%.*]] = add nuw nsw i37 [[TMP2]], 5 ; CHECK-NEXT: ret i37 [[R]] ; %a = add nsw i37 %x, 5 @@ -1293,9 +1291,9 @@ define i37 @add_smax(i37 %x) { define i8 @add_smax_constant_limit(i8 %x) { ; CHECK-LABEL: @add_smax_constant_limit( -; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 125 -; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[A]], -2 -; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i8 [[A]], i8 -2 +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[X:%.*]], -127 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 -127 +; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[TMP2]], 125 ; CHECK-NEXT: ret i8 [[R]] ; %a = add nsw i8 %x, 125 @@ -1309,9 +1307,7 @@ define i8 @add_smax_constant_limit(i8 %x) { define i8 @add_smax_simplify(i8 %x) { ; CHECK-LABEL: @add_smax_simplify( -; CHECK-NEXT: [[A:%.*]] = add nsw i8 [[X:%.*]], 126 -; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[A]], -2 -; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i8 [[A]], i8 -2 +; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[X:%.*]], 126 ; CHECK-NEXT: ret i8 [[R]] ; %a = add nsw i8 %x, 126 @@ -1383,9 +1379,9 @@ define i32 @add_smax_extra_use(i32 %x, i32* %p) { define <2 x i33> @add_smax_vec(<2 x i33> %x) { ; CHECK-LABEL: @add_smax_vec( -; CHECK-NEXT: [[A:%.*]] = add nsw <2 x i33> [[X:%.*]], -; CHECK-NEXT: [[C:%.*]] = icmp sgt <2 x i33> [[A]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[C]], <2 x i33> [[A]], <2 x i33> +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <2 x i33> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i33> [[X]], <2 x i33> +; CHECK-NEXT: [[R:%.*]] = add nuw nsw <2 x i33> [[TMP2]], ; CHECK-NEXT: ret <2 x i33> [[R]] ; %a = add nsw <2 x i33> %x, @@ -1396,12 +1392,10 @@ define <2 x i33> @add_smax_vec(<2 x i33> %x) { define i8 @PR14613_smin(i8 %x) { ; CHECK-LABEL: @PR14613_smin( -; CHECK-NEXT: [[U4:%.*]] = sext i8 [[X:%.*]] to i32 -; CHECK-NEXT: [[U5:%.*]] = add nuw nsw i32 [[U4]], 15 -; CHECK-NEXT: [[U6:%.*]] = icmp slt i32 [[U5]], 55 -; CHECK-NEXT: [[U7:%.*]] = select i1 [[U6]], i32 [[U5]], i32 55 -; CHECK-NEXT: [[R:%.*]] = trunc i32 [[U7]] to i8 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 40 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 40 +; CHECK-NEXT: [[U7:%.*]] = add i8 [[TMP2]], 15 +; CHECK-NEXT: ret i8 [[U7]] ; %u4 = sext i8 %x to i32 %u5 = add nuw nsw i32 %u4, 15 @@ -1413,12 +1407,10 @@ define i8 @PR14613_smin(i8 %x) { define i8 @PR14613_smax(i8 %x) { ; CHECK-LABEL: @PR14613_smax( -; CHECK-NEXT: [[U4:%.*]] = sext i8 [[X:%.*]] to i32 -; CHECK-NEXT: [[U5:%.*]] = add nuw nsw i32 [[U4]], 15 -; CHECK-NEXT: [[U6:%.*]] = icmp sgt i32 [[U5]], 55 -; CHECK-NEXT: [[U7:%.*]] = select i1 [[U6]], i32 [[U5]], i32 55 -; CHECK-NEXT: [[R:%.*]] = trunc i32 [[U7]] to i8 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[X:%.*]], 40 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 40 +; CHECK-NEXT: [[U7:%.*]] = add nuw i8 [[TMP2]], 15 +; CHECK-NEXT: ret i8 [[U7]] ; %u4 = sext i8 %x to i32 %u5 = add nuw nsw i32 %u4, 15 -- 2.50.1