From 86408a80486971d41d94a9959baf5080356cbae3 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Mon, 7 Nov 2016 15:52:45 +0000 Subject: [PATCH] [InstCombine] allow splat vector folds in adjustMinMax() (retry r285732) This was reverted at r285866 because there was a crash handling a scalar select of vectors. I added a check for that pattern and a test case based on the example provided in the post-commit thread for r285732. llvm-svn: 286113 --- .../Transforms/InstCombine/InstCombineSelect.cpp | 26 +++--- .../Transforms/InstCombine/adjust-for-minmax.ll | 93 +++++++++++----------- 2 files changed, 57 insertions(+), 62 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index cfae47f..6121b80 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -424,24 +424,22 @@ static bool adjustMinMax(SelectInst &Sel, ICmpInst &Cmp) { Value *FalseVal = Sel.getFalseValue(); // We may move or edit the compare, so make sure the select is the only user. - if (!Cmp.hasOneUse()) + const APInt *CmpC; + if (!Cmp.hasOneUse() || !match(CmpRHS, m_APInt(CmpC))) return false; - // FIXME: Use m_APInt to allow vector folds. - auto *CI = dyn_cast(CmpRHS); - if (!CI) - return false; - - // These transformations only work for selects over integers. - IntegerType *SelectTy = dyn_cast(Sel.getType()); - if (!SelectTy) + // These transforms only work for selects of integers or vector selects of + // integer vectors. + Type *SelTy = Sel.getType(); + auto *SelEltTy = dyn_cast(SelTy->getScalarType()); + if (!SelEltTy || SelTy->isVectorTy() != Cmp.getType()->isVectorTy()) return false; Constant *AdjustedRHS; if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_SGT) - AdjustedRHS = ConstantInt::get(CI->getContext(), CI->getValue() + 1); + AdjustedRHS = ConstantInt::get(CmpRHS->getType(), *CmpC + 1); else if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_SLT) - AdjustedRHS = ConstantInt::get(CI->getContext(), CI->getValue() - 1); + AdjustedRHS = ConstantInt::get(CmpRHS->getType(), *CmpC - 1); else return false; @@ -454,8 +452,8 @@ static bool adjustMinMax(SelectInst &Sel, ICmpInst &Cmp) { // Types do not match. Instead of calculating this with mixed types, promote // all to the larger type. This enables scalar evolution to analyze this // expression. - else if (CmpRHS->getType()->getScalarSizeInBits() < SelectTy->getBitWidth()) { - Constant *SextRHS = ConstantExpr::getSExt(AdjustedRHS, SelectTy); + else if (CmpRHS->getType()->getScalarSizeInBits() < SelEltTy->getBitWidth()) { + Constant *SextRHS = ConstantExpr::getSExt(AdjustedRHS, SelTy); // X = sext x; x >s c ? X : C+1 --> X = sext x; X X = sext x; X >s C-1 ? C-1 : X @@ -469,7 +467,7 @@ static bool adjustMinMax(SelectInst &Sel, ICmpInst &Cmp) { CmpLHS = FalseVal; AdjustedRHS = SextRHS; } else if (Cmp.isUnsigned()) { - Constant *ZextRHS = ConstantExpr::getZExt(AdjustedRHS, SelectTy); + Constant *ZextRHS = ConstantExpr::getZExt(AdjustedRHS, SelTy); // X = zext x; x >u c ? X : C+1 --> X = zext x; X X = zext x; X >u C-1 ? C-1 : X // zext + signed compare cannot be changed: diff --git a/llvm/test/Transforms/InstCombine/adjust-for-minmax.ll b/llvm/test/Transforms/InstCombine/adjust-for-minmax.ll index 813171b..53cea75 100644 --- a/llvm/test/Transforms/InstCombine/adjust-for-minmax.ll +++ b/llvm/test/Transforms/InstCombine/adjust-for-minmax.ll @@ -68,13 +68,12 @@ define i32 @smax3(i32 %n) { ret i32 %m } -; FIXME ; Swap vector signed pred and select ops. define <2 x i32> @smax3_vec(<2 x i32> %n) { ; CHECK-LABEL: @smax3_vec( -; CHECK-NEXT: [[T:%.*]] = icmp sgt <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> zeroinitializer +; CHECK-NEXT: [[T:%.*]] = icmp slt <2 x i32> %n, zeroinitializer +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> zeroinitializer, <2 x i32> %n ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp sgt <2 x i32> %n, @@ -95,13 +94,12 @@ define i32 @smin3(i32 %n) { ret i32 %m } -; FIXME ; Swap vector signed pred and select ops. define <2 x i32> @smin3_vec(<2 x i32> %n) { ; CHECK-LABEL: @smin3_vec( -; CHECK-NEXT: [[T:%.*]] = icmp slt <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> zeroinitializer +; CHECK-NEXT: [[T:%.*]] = icmp sgt <2 x i32> %n, zeroinitializer +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> zeroinitializer, <2 x i32> %n ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp slt <2 x i32> %n, @@ -122,13 +120,12 @@ define i32 @umax3(i32 %n) { ret i32 %m } -; FIXME ; Swap vector unsigned pred and select ops. define <2 x i32> @umax3_vec(<2 x i32> %n) { ; CHECK-LABEL: @umax3_vec( -; CHECK-NEXT: [[T:%.*]] = icmp ugt <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> +; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> %n, +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> , <2 x i32> %n ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp ugt <2 x i32> %n, @@ -149,13 +146,12 @@ define i32 @umin3(i32 %n) { ret i32 %m } -; FIXME ; Swap vector unsigned pred and select ops. define <2 x i32> @umin3_vec(<2 x i32> %n) { ; CHECK-LABEL: @umin3_vec( -; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> +; CHECK-NEXT: [[T:%.*]] = icmp ugt <2 x i32> %n, +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> , <2 x i32> %n ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp ult <2 x i32> %n, @@ -176,13 +172,12 @@ define i32 @smax4(i32 %n) { ret i32 %m } -; FIXME ; Canonicalize vector signed pred and swap pred and select ops. define <2 x i32> @smax4_vec(<2 x i32> %n) { ; CHECK-LABEL: @smax4_vec( -; CHECK-NEXT: [[T:%.*]] = icmp sgt <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> zeroinitializer +; CHECK-NEXT: [[T:%.*]] = icmp slt <2 x i32> %n, zeroinitializer +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> zeroinitializer, <2 x i32> %n ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp sge <2 x i32> %n, zeroinitializer @@ -203,13 +198,12 @@ define i32 @smin4(i32 %n) { ret i32 %m } -; FIXME ; Canonicalize vector signed pred and swap pred and select ops. define <2 x i32> @smin4_vec(<2 x i32> %n) { ; CHECK-LABEL: @smin4_vec( -; CHECK-NEXT: [[T:%.*]] = icmp slt <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> zeroinitializer +; CHECK-NEXT: [[T:%.*]] = icmp sgt <2 x i32> %n, zeroinitializer +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> zeroinitializer, <2 x i32> %n ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp sle <2 x i32> %n, zeroinitializer @@ -230,13 +224,12 @@ define i32 @umax4(i32 %n) { ret i32 %m } -; FIXME ; Canonicalize vector unsigned pred and swap pred and select ops. define <2 x i32> @umax4_vec(<2 x i32> %n) { ; CHECK-LABEL: @umax4_vec( -; CHECK-NEXT: [[T:%.*]] = icmp ugt <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> +; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> %n, +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> , <2 x i32> %n ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp uge <2 x i32> %n, @@ -257,13 +250,12 @@ define i32 @umin4(i32 %n) { ret i32 %m } -; FIXME ; Canonicalize vector unsigned pred and swap pred and select ops. define <2 x i32> @umin4_vec(<2 x i32> %n) { ; CHECK-LABEL: @umin4_vec( -; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> %n, -; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> %n, <2 x i32> +; CHECK-NEXT: [[T:%.*]] = icmp ugt <2 x i32> %n, +; CHECK-NEXT: [[M:%.*]] = select <2 x i1> [[T]], <2 x i32> , <2 x i32> %n ; CHECK-NEXT: ret <2 x i32> [[M]] ; %t = icmp ule <2 x i32> %n, @@ -284,12 +276,11 @@ define i64 @smax_sext(i32 %a) { ret i64 %max } -; FIXME define <2 x i64> @smax_sext_vec(<2 x i32> %a) { ; CHECK-LABEL: @smax_sext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = sext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> %a, -; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i64> [[A_EXT]], zeroinitializer +; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> zeroinitializer, <2 x i64> [[A_EXT]] ; CHECK-NEXT: ret <2 x i64> [[MAX]] ; %a_ext = sext <2 x i32> %a to <2 x i64> @@ -311,12 +302,11 @@ define i64 @smin_sext(i32 %a) { ret i64 %min } -; FIXME define <2 x i64>@smin_sext_vec(<2 x i32> %a) { ; CHECK-LABEL: @smin_sext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = sext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> %a, -; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i64> [[A_EXT]], zeroinitializer +; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> zeroinitializer, <2 x i64> [[A_EXT]] ; CHECK-NEXT: ret <2 x i64> [[MIN]] ; %a_ext = sext <2 x i32> %a to <2 x i64> @@ -338,12 +328,11 @@ define i64 @umax_sext(i32 %a) { ret i64 %max } -; FIXME define <2 x i64> @umax_sext_vec(<2 x i32> %a) { ; CHECK-LABEL: @umax_sext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = sext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i32> %a, -; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> +; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i64> [[A_EXT]], +; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> , <2 x i64> [[A_EXT]] ; CHECK-NEXT: ret <2 x i64> [[MAX]] ; %a_ext = sext <2 x i32> %a to <2 x i64> @@ -365,12 +354,11 @@ define i64 @umin_sext(i32 %a) { ret i64 %min } -; FIXME define <2 x i64> @umin_sext_vec(<2 x i32> %a) { ; CHECK-LABEL: @umin_sext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = sext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> %a, -; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i64> [[A_EXT]], +; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> , <2 x i64> [[A_EXT]] ; CHECK-NEXT: ret <2 x i64> [[MIN]] ; %a_ext = sext <2 x i32> %a to <2 x i64> @@ -392,12 +380,11 @@ define i64 @umax_sext2(i32 %a) { ret i64 %min } -; FIXME define <2 x i64> @umax_sext2_vec(<2 x i32> %a) { ; CHECK-LABEL: @umax_sext2_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = sext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> %a, -; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> , <2 x i64> [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i64> [[A_EXT]], +; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[MIN]] ; %a_ext = sext <2 x i32> %a to <2 x i64> @@ -419,12 +406,11 @@ define i64 @umin_sext2(i32 %a) { ret i64 %min } -; FIXME define <2 x i64> @umin_sext2_vec(<2 x i32> %a) { ; CHECK-LABEL: @umin_sext2_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = sext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i32> %a, -; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> , <2 x i64> [[A_EXT]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i64> [[A_EXT]], +; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[MIN]] ; %a_ext = sext <2 x i32> %a to <2 x i64> @@ -446,12 +432,11 @@ define i64 @umax_zext(i32 %a) { ret i64 %max } -; FIXME define <2 x i64> @umax_zext_vec(<2 x i32> %a) { ; CHECK-LABEL: @umax_zext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = zext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i32> %a, -; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> +; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i64> [[A_EXT]], +; CHECK-NEXT: [[MAX:%.*]] = select <2 x i1> [[CMP]], <2 x i64> , <2 x i64> [[A_EXT]] ; CHECK-NEXT: ret <2 x i64> [[MAX]] ; %a_ext = zext <2 x i32> %a to <2 x i64> @@ -473,12 +458,11 @@ define i64 @umin_zext(i32 %a) { ret i64 %min } -; FIXME define <2 x i64> @umin_zext_vec(<2 x i32> %a) { ; CHECK-LABEL: @umin_zext_vec( ; CHECK-NEXT: [[A_EXT:%.*]] = zext <2 x i32> %a to <2 x i64> -; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> %a, -; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[A_EXT]], <2 x i64> +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i64> [[A_EXT]], +; CHECK-NEXT: [[MIN:%.*]] = select <2 x i1> [[CMP]], <2 x i64> , <2 x i64> [[A_EXT]] ; CHECK-NEXT: ret <2 x i64> [[MIN]] ; %a_ext = zext <2 x i32> %a to <2 x i64> @@ -487,3 +471,16 @@ define <2 x i64> @umin_zext_vec(<2 x i32> %a) { ret <2 x i64> %min } +; Don't crash mishandling a pattern that can't be transformed. + +define <2 x i16> @scalar_select_of_vectors(<2 x i16> %a, <2 x i16> %b, i8 %x) { +; CHECK-LABEL: @scalar_select_of_vectors( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 %x, 0 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], <2 x i16> %a, <2 x i16> %b +; CHECK-NEXT: ret <2 x i16> [[SEL]] +; + %cmp = icmp slt i8 %x, 0 + %sel = select i1 %cmp, <2 x i16> %a, <2 x i16> %b + ret <2 x i16> %sel +} + -- 2.7.4