From 567485a72ff71e34c9e25aaab8eecfda3aa6cd62 Mon Sep 17 00:00:00 2001 From: Chen Zheng Date: Fri, 27 Jul 2018 01:49:51 +0000 Subject: [PATCH] [InstCombine] canonicalize abs pattern Differential Revision: https://reviews.llvm.org/D48754 llvm-svn: 338092 --- .../InstCombine/InstCombineSelect.cpp | 76 ++++++++++----- llvm/test/Transforms/InstCombine/abs-1.ll | 96 +++++++++++++++---- llvm/test/Transforms/InstCombine/abs_abs.ll | 80 ++++++++-------- llvm/test/Transforms/InstCombine/icmp.ll | 2 +- 4 files changed, 174 insertions(+), 80 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 108d29ab0d60..4867808478a3 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -794,8 +794,11 @@ canonicalizeMinMaxWithConstant(SelectInst &Sel, ICmpInst &Cmp, return &Sel; } -/// There are 4 select variants for each of ABS/NABS (different compare -/// constants, compare predicates, select operands). Canonicalize to 1 pattern. +/// There are many select variants for each of ABS/NABS. +/// In matchSelectPattern(), there are different compare constants, compare +/// predicates/operands and select operands. +/// In isKnownNegation(), there are different formats of negated operands. +/// Canonicalize all these variants to 1 pattern. /// This makes CSE more likely. static Instruction *canonicalizeAbsNabs(SelectInst &Sel, ICmpInst &Cmp, InstCombiner::BuilderTy &Builder) { @@ -810,34 +813,61 @@ static Instruction *canonicalizeAbsNabs(SelectInst &Sel, ICmpInst &Cmp, if (SPF != SelectPatternFlavor::SPF_ABS && SPF != SelectPatternFlavor::SPF_NABS) return nullptr; - - // TODO: later canonicalization change will move this condition check. - // Without this check, following assert will be hit. - if (match(Cmp.getOperand(0), m_Sub(m_Value(), m_Value()))) - return nullptr; - // Is this already canonical? - if (match(Cmp.getOperand(1), m_ZeroInt()) && - Cmp.getPredicate() == ICmpInst::ICMP_SLT) - return nullptr; - - // Create the canonical compare. - Cmp.setPredicate(ICmpInst::ICMP_SLT); - Cmp.setOperand(1, ConstantInt::getNullValue(Cmp.getOperand(0)->getType())); - - // If the select operands do not change, we're done. Value *TVal = Sel.getTrueValue(); Value *FVal = Sel.getFalseValue(); + assert(isKnownNegation(TVal, FVal) && + "Unexpected result from matchSelectPattern"); + + // The compare may use the negated abs()/nabs() operand, or it may use + // negation in non-canonical form such as: sub A, B. + bool CmpUsesNegatedOp = match(Cmp.getOperand(0), m_Neg(m_Specific(TVal))) || + match(Cmp.getOperand(0), m_Neg(m_Specific(FVal))); + + bool CmpCanonicalized = !CmpUsesNegatedOp && + match(Cmp.getOperand(1), m_ZeroInt()) && + Cmp.getPredicate() == ICmpInst::ICMP_SLT; + bool RHSCanonicalized = match(RHS, m_Neg(m_Specific(LHS))); + + // Is this already canonical? + if (CmpCanonicalized && RHSCanonicalized) + return nullptr; + + // If RHS is used by other instructions except compare and select, don't + // canonicalize it to not increase the instruction count. + if (!(RHS->hasOneUse() || (RHS->hasNUses(2) && CmpUsesNegatedOp))) + return nullptr; + + // Create the canonical compare: icmp slt LHS 0. + if (!CmpCanonicalized) { + Cmp.setPredicate(ICmpInst::ICMP_SLT); + Cmp.setOperand(1, ConstantInt::getNullValue(Cmp.getOperand(0)->getType())); + if (CmpUsesNegatedOp) + Cmp.setOperand(0, LHS); + } + + // Create the canonical RHS: RHS = sub (0, LHS). + if (!RHSCanonicalized) { + assert(RHS->hasOneUse() && "RHS use number is not right"); + RHS = Builder.CreateNeg(LHS); + if (TVal == LHS) { + Sel.setFalseValue(RHS); + FVal = RHS; + } else { + Sel.setTrueValue(RHS); + TVal = RHS; + } + } + + // If the select operands do not change, we're done. if (SPF == SelectPatternFlavor::SPF_NABS) { - if (TVal == LHS && match(FVal, m_Neg(m_Specific(TVal)))) + if (TVal == LHS) return &Sel; - assert(FVal == LHS && match(TVal, m_Neg(m_Specific(FVal))) && - "Unexpected results from matchSelectPattern"); + assert(FVal == LHS && "Unexpected results from matchSelectPattern"); } else { - if (FVal == LHS && match(TVal, m_Neg(m_Specific(FVal)))) + if (FVal == LHS) return &Sel; - assert(TVal == LHS && match(FVal, m_Neg(m_Specific(TVal))) && - "Unexpected results from matchSelectPattern"); + assert(TVal == LHS && "Unexpected results from matchSelectPattern"); } // We are swapping the select operands, so swap the metadata too. diff --git a/llvm/test/Transforms/InstCombine/abs-1.ll b/llvm/test/Transforms/InstCombine/abs-1.ll index c5e39af34b2a..8bbc833d5d44 100644 --- a/llvm/test/Transforms/InstCombine/abs-1.ll +++ b/llvm/test/Transforms/InstCombine/abs-1.ll @@ -134,9 +134,9 @@ define i32 @abs_canonical_5(i8 %x) { define i32 @abs_canonical_6(i32 %a, i32 %b) { ; CHECK-LABEL: @abs_canonical_6( ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1 -; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[B]], [[A]] -; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[TMP2]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]] +; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP2]], i32 [[TMP1]] ; CHECK-NEXT: ret i32 [[ABS]] ; %tmp1 = sub i32 %a, %b @@ -149,9 +149,9 @@ define i32 @abs_canonical_6(i32 %a, i32 %b) { define <2 x i8> @abs_canonical_7(<2 x i8> %a, <2 x i8 > %b) { ; CHECK-LABEL: @abs_canonical_7( ; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[TMP1]], -; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> [[B]], [[A]] -; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP1]], <2 x i8> [[TMP2]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]] +; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP2]], <2 x i8> [[TMP1]] ; CHECK-NEXT: ret <2 x i8> [[ABS]] ; @@ -165,8 +165,8 @@ define <2 x i8> @abs_canonical_7(<2 x i8> %a, <2 x i8 > %b) { define i32 @abs_canonical_8(i32 %a) { ; CHECK-LABEL: @abs_canonical_8( ; CHECK-NEXT: [[TMP:%.*]] = sub i32 0, [[A:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP]], 0 -; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[TMP]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 +; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP]], i32 [[A]] ; CHECK-NEXT: ret i32 [[ABS]] ; %tmp = sub i32 0, %a @@ -175,6 +175,38 @@ define i32 @abs_canonical_8(i32 %a) { ret i32 %abs } +define i32 @abs_canonical_9(i32 %a, i32 %b) { +; CHECK-LABEL: @abs_canonical_9( +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[B]], [[A]] +; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[TMP2]] +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[ABS]], [[TMP2]] +; CHECK-NEXT: ret i32 [[ADD]] +; + %tmp1 = sub i32 %a, %b + %cmp = icmp sgt i32 %tmp1, -1 + %tmp2 = sub i32 %b, %a + %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2 + %add = add i32 %abs, %tmp2 ; increase use count for %tmp2. + ret i32 %add +} + +define i32 @abs_canonical_10(i32 %a, i32 %b) { +; CHECK-LABEL: @abs_canonical_10( +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0 +; CHECK-NEXT: [[NEGTMP:%.*]] = sub i32 0, [[TMP1]] +; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGTMP]], i32 [[TMP1]] +; CHECK-NEXT: ret i32 [[ABS]] +; + %tmp2 = sub i32 %b, %a + %tmp1 = sub i32 %a, %b + %cmp = icmp sgt i32 %tmp1, -1 + %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2 + ret i32 %abs +} + ; We have a canonical form of nabs to make CSE easier. define i8 @nabs_canonical_1(i8 %x) { @@ -266,9 +298,9 @@ define i32 @nabs_canonical_5(i8 %x) { define i32 @nabs_canonical_6(i32 %a, i32 %b) { ; CHECK-LABEL: @nabs_canonical_6( ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1 -; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[B]], [[A]] -; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP2]], i32 [[TMP1]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]] +; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[TMP2]] ; CHECK-NEXT: ret i32 [[ABS]] ; %tmp1 = sub i32 %a, %b @@ -281,9 +313,9 @@ define i32 @nabs_canonical_6(i32 %a, i32 %b) { define <2 x i8> @nabs_canonical_7(<2 x i8> %a, <2 x i8 > %b) { ; CHECK-LABEL: @nabs_canonical_7( ; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[TMP1]], -; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> [[B]], [[A]] -; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP2]], <2 x i8> [[TMP1]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]] +; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP1]], <2 x i8> [[TMP2]] ; CHECK-NEXT: ret <2 x i8> [[ABS]] ; %tmp1 = sub <2 x i8> %a, %b @@ -296,8 +328,8 @@ define <2 x i8> @nabs_canonical_7(<2 x i8> %a, <2 x i8 > %b) { define i32 @nabs_canonical_8(i32 %a) { ; CHECK-LABEL: @nabs_canonical_8( ; CHECK-NEXT: [[TMP:%.*]] = sub i32 0, [[A:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP]], 0 -; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP]], i32 [[A]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 +; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[TMP]] ; CHECK-NEXT: ret i32 [[ABS]] ; %tmp = sub i32 0, %a @@ -306,6 +338,38 @@ define i32 @nabs_canonical_8(i32 %a) { ret i32 %abs } +define i32 @nabs_canonical_9(i32 %a, i32 %b) { +; CHECK-LABEL: @nabs_canonical_9( +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[B]], [[A]] +; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP2]], i32 [[TMP1]] +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP2]], [[ABS]] +; CHECK-NEXT: ret i32 [[ADD]] +; + %tmp1 = sub i32 %a, %b + %cmp = icmp sgt i32 %tmp1, -1 + %tmp2 = sub i32 %b, %a + %abs = select i1 %cmp, i32 %tmp2, i32 %tmp1 + %add = add i32 %tmp2, %abs ; increase use count for %tmp2 + ret i32 %add +} + +define i32 @nabs_canonical_10(i32 %a, i32 %b) { +; CHECK-LABEL: @nabs_canonical_10( +; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0 +; CHECK-NEXT: [[NEGTMP:%.*]] = sub i32 0, [[TMP1]] +; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[NEGTMP]] +; CHECK-NEXT: ret i32 [[ABS]] +; + %tmp2 = sub i32 %b, %a + %tmp1 = sub i32 %a, %b + %cmp = icmp slt i32 %tmp1, 1 + %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2 + ret i32 %abs +} + ; The following 5 tests use a shift+add+xor to implement abs(): ; B = ashr i8 A, 7 -- smear the sign bit. ; xor (add A, B), B -- add -1 and flip bits if negative diff --git a/llvm/test/Transforms/InstCombine/abs_abs.ll b/llvm/test/Transforms/InstCombine/abs_abs.ll index daa965c5b977..207ceb5215a7 100644 --- a/llvm/test/Transforms/InstCombine/abs_abs.ll +++ b/llvm/test/Transforms/InstCombine/abs_abs.ll @@ -289,11 +289,11 @@ define i32 @abs_abs_x16(i32 %x) { ret i32 %cond18 } -; abs(abs(-x)) -> abs(-x) +; abs(abs(-x)) -> abs(-x) -> abs(x) define i32 @abs_abs_x17(i32 %x) { ; CHECK-LABEL: @abs_abs_x17( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[SUB]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 0 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[X]] ; CHECK-NEXT: ret i32 [[COND]] ; @@ -310,9 +310,9 @@ define i32 @abs_abs_x17(i32 %x) { define i32 @abs_abs_x18(i32 %x, i32 %y) { ; CHECK-LABEL: @abs_abs_x18( ; CHECK-NEXT: [[A:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[B:%.*]] = sub nsw i32 [[Y]], [[X]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], -1 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[B]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 +; CHECK-NEXT: [[NEGA:%.*]] = sub i32 0, [[A]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[NEGA]], i32 [[A]] ; CHECK-NEXT: ret i32 [[COND]] ; %a = sub nsw i32 %x, %y @@ -325,11 +325,11 @@ define i32 @abs_abs_x18(i32 %x, i32 %y) { ret i32 %cond18 } -; abs(abs(-x)) -> abs(-x) +; abs(abs(-x)) -> abs(-x) -> abs(x) define <2 x i32> @abs_abs_x02_vec(<2 x i32> %x) { ; CHECK-LABEL: @abs_abs_x02_vec( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw <2 x i32> zeroinitializer, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[SUB]], +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[X]], zeroinitializer ; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[SUB]], <2 x i32> [[X]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; @@ -346,9 +346,9 @@ define <2 x i32> @abs_abs_x02_vec(<2 x i32> %x) { define <2 x i32> @abs_abs_x03_vec(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @abs_abs_x03_vec( ; CHECK-NEXT: [[A:%.*]] = sub nsw <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[B:%.*]] = sub nsw <2 x i32> [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[A]], -; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[A]], <2 x i32> [[B]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[A]], zeroinitializer +; CHECK-NEXT: [[NEGA:%.*]] = sub <2 x i32> zeroinitializer, [[A]] +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[NEGA]], <2 x i32> [[A]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; %a = sub nsw <2 x i32> %x, %y @@ -617,11 +617,11 @@ define i32 @nabs_nabs_x16(i32 %x) { ret i32 %cond18 } -; nabs(nabs(-x)) -> nabs(-x) +; nabs(nabs(-x)) -> nabs(-x) -> nabs(x) define i32 @nabs_nabs_x17(i32 %x) { ; CHECK-LABEL: @nabs_nabs_x17( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[SUB]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 0 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] ; CHECK-NEXT: ret i32 [[COND]] ; @@ -638,9 +638,9 @@ define i32 @nabs_nabs_x17(i32 %x) { define i32 @nabs_nabs_x18(i32 %x, i32 %y) { ; CHECK-LABEL: @nabs_nabs_x18( ; CHECK-NEXT: [[A:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[B:%.*]] = sub nsw i32 [[Y]], [[X]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], -1 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[B]], i32 [[A]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 +; CHECK-NEXT: [[NEGA:%.*]] = sub i32 0, [[A]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[NEGA]] ; CHECK-NEXT: ret i32 [[COND]] ; %a = sub nsw i32 %x, %y @@ -653,11 +653,11 @@ define i32 @nabs_nabs_x18(i32 %x, i32 %y) { ret i32 %cond18 } -; nabs(nabs(-x)) -> nabs(-x) +; nabs(nabs(-x)) -> nabs(-x) -> nabs(x) define <2 x i32> @nabs_nabs_x01_vec(<2 x i32> %x) { ; CHECK-LABEL: @nabs_nabs_x01_vec( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw <2 x i32> zeroinitializer, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[SUB]], +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[X]], zeroinitializer ; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[X]], <2 x i32> [[SUB]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; @@ -674,9 +674,9 @@ define <2 x i32> @nabs_nabs_x01_vec(<2 x i32> %x) { define <2 x i32> @nabs_nabs_x02_vec(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @nabs_nabs_x02_vec( ; CHECK-NEXT: [[A:%.*]] = sub nsw <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[B:%.*]] = sub nsw <2 x i32> [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[A]], -; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[B]], <2 x i32> [[A]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[A]], zeroinitializer +; CHECK-NEXT: [[NEGA:%.*]] = sub <2 x i32> zeroinitializer, [[A]] +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[A]], <2 x i32> [[NEGA]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; %a = sub nsw <2 x i32> %x, %y @@ -945,11 +945,11 @@ define i32 @abs_nabs_x16(i32 %x) { ret i32 %cond18 } -; abs(nabs(-x)) -> abs(-x) +; abs(nabs(-x)) -> abs(-x) -> abs(x) define i32 @abs_nabs_x17(i32 %x) { ; CHECK-LABEL: @abs_nabs_x17( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[SUB]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 0 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[X]] ; CHECK-NEXT: ret i32 [[COND]] ; @@ -966,9 +966,9 @@ define i32 @abs_nabs_x17(i32 %x) { define i32 @abs_nabs_x18(i32 %x, i32 %y) { ; CHECK-LABEL: @abs_nabs_x18( ; CHECK-NEXT: [[A:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[B:%.*]] = sub nsw i32 [[Y]], [[X]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], -1 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[B]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 +; CHECK-NEXT: [[NEGA:%.*]] = sub i32 0, [[A]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[NEGA]], i32 [[A]] ; CHECK-NEXT: ret i32 [[COND]] ; %a = sub nsw i32 %x, %y @@ -981,11 +981,11 @@ define i32 @abs_nabs_x18(i32 %x, i32 %y) { ret i32 %cond18 } -; abs(nabs(-x)) -> abs(-x) +; abs(nabs(-x)) -> abs(-x) -> abs(x) define <2 x i32> @abs_nabs_x01_vec(<2 x i32> %x) { ; CHECK-LABEL: @abs_nabs_x01_vec( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw <2 x i32> zeroinitializer, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[SUB]], +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[X]], zeroinitializer ; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[SUB]], <2 x i32> [[X]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; @@ -1002,9 +1002,9 @@ define <2 x i32> @abs_nabs_x01_vec(<2 x i32> %x) { define <2 x i32> @abs_nabs_x02_vec(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @abs_nabs_x02_vec( ; CHECK-NEXT: [[A:%.*]] = sub nsw <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[B:%.*]] = sub nsw <2 x i32> [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[A]], -; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[A]], <2 x i32> [[B]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[A]], zeroinitializer +; CHECK-NEXT: [[NEGA:%.*]] = sub <2 x i32> zeroinitializer, [[A]] +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[NEGA]], <2 x i32> [[A]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; %a = sub nsw <2 x i32> %x, %y @@ -1273,11 +1273,11 @@ define i32 @nabs_abs_x16(i32 %x) { ret i32 %cond18 } -; nabs(abs(-x)) -> nabs(-x) +; nabs(abs(-x)) -> nabs(-x) -> nabs(x) define i32 @nabs_abs_x17(i32 %x) { ; CHECK-LABEL: @nabs_abs_x17( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[SUB]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 0 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] ; CHECK-NEXT: ret i32 [[COND]] ; @@ -1294,9 +1294,9 @@ define i32 @nabs_abs_x17(i32 %x) { define i32 @nabs_abs_x18(i32 %x, i32 %y) { ; CHECK-LABEL: @nabs_abs_x18( ; CHECK-NEXT: [[A:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[B:%.*]] = sub nsw i32 [[Y]], [[X]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], -1 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[B]], i32 [[A]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 +; CHECK-NEXT: [[NEGA:%.*]] = sub i32 0, [[A]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[NEGA]] ; CHECK-NEXT: ret i32 [[COND]] ; %a = sub nsw i32 %x, %y @@ -1309,11 +1309,11 @@ define i32 @nabs_abs_x18(i32 %x, i32 %y) { ret i32 %cond18 } -; nabs(abs(-x)) -> nabs(-x) +; nabs(abs(-x)) -> nabs(-x) -> nabs(x) define <2 x i32> @nabs_abs_x01_vec(<2 x i32> %x) { ; CHECK-LABEL: @nabs_abs_x01_vec( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw <2 x i32> zeroinitializer, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[SUB]], +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[X]], zeroinitializer ; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[X]], <2 x i32> [[SUB]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; @@ -1330,9 +1330,9 @@ define <2 x i32> @nabs_abs_x01_vec(<2 x i32> %x) { define <2 x i32> @nabs_abs_x02_vec(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @nabs_abs_x02_vec( ; CHECK-NEXT: [[A:%.*]] = sub nsw <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[B:%.*]] = sub nsw <2 x i32> [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[A]], -; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[B]], <2 x i32> [[A]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[A]], zeroinitializer +; CHECK-NEXT: [[NEGA:%.*]] = sub <2 x i32> zeroinitializer, [[A]] +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[A]], <2 x i32> [[NEGA]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; %a = sub nsw <2 x i32> %x, %y diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index 722b0a7fa791..7e52e3c7ffbb 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -3345,7 +3345,7 @@ define <2 x i1> @PR36583(<2 x i8*>) { define <2 x i32> @Op1Negated_Vec(<2 x i32> %x) { ; CHECK-LABEL: @Op1Negated_Vec( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw <2 x i32> zeroinitializer, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[SUB]], +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i32> [[X]], zeroinitializer ; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[SUB]], <2 x i32> [[X]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ;