Index: llvm/trunk/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp +++ llvm/trunk/lib/Analysis/ValueTracking.cpp @@ -4626,35 +4626,50 @@ case FCmpInst::FCMP_OLE: return {SPF_FMINNUM, NaNBehavior, Ordered}; } } - - // Sign-extending LHS does not change its sign, so TrueVal/FalseVal can - // match against either LHS or sext(LHS). - auto MaybeSExtLHS = m_CombineOr(m_Specific(CmpLHS), - m_SExt(m_Specific(CmpLHS))); - if ((match(TrueVal, MaybeSExtLHS) && - match(FalseVal, m_Neg(m_Specific(TrueVal)))) || - (match(FalseVal, MaybeSExtLHS) && - match(TrueVal, m_Neg(m_Specific(FalseVal))))) { - // Set LHS and RHS so that RHS is the negated operand of the select - if (match(TrueVal, MaybeSExtLHS)) { + + if (isKnownNegation(TrueVal, FalseVal)) { + // Sign-extending LHS does not change its sign, so TrueVal/FalseVal can + // match against either LHS or sext(LHS). + auto MaybeSExtCmpLHS = + m_CombineOr(m_Specific(CmpLHS), m_SExt(m_Specific(CmpLHS))); + auto ZeroOrAllOnes = m_CombineOr(m_ZeroInt(), m_AllOnes()); + auto ZeroOrOne = m_CombineOr(m_ZeroInt(), m_One()); + if (match(TrueVal, MaybeSExtCmpLHS)) { + // Set the return values. If the compare uses the negated value (-X >s 0), + // swap the return values because the negated value is always 'RHS'. LHS = TrueVal; RHS = FalseVal; - } else { + if (match(CmpLHS, m_Neg(m_Specific(FalseVal)))) + std::swap(LHS, RHS); + + // (X >s 0) ? X : -X or (X >s -1) ? X : -X --> ABS(X) + // (-X >s 0) ? -X : X or (-X >s -1) ? -X : X --> ABS(X) + if (Pred == ICmpInst::ICMP_SGT && match(CmpRHS, ZeroOrAllOnes)) + return {SPF_ABS, SPNB_NA, false}; + + // (X NABS(X) + // (-X NABS(X) + if (Pred == ICmpInst::ICMP_SLT && match(CmpRHS, ZeroOrOne)) + return {SPF_NABS, SPNB_NA, false}; + } + else if (match(FalseVal, MaybeSExtCmpLHS)) { + // Set the return values. If the compare uses the negated value (-X >s 0), + // swap the return values because the negated value is always 'RHS'. LHS = FalseVal; RHS = TrueVal; - } + if (match(CmpLHS, m_Neg(m_Specific(TrueVal)))) + std::swap(LHS, RHS); - // (X >s 0) ? X : -X or (X >s -1) ? X : -X --> ABS(X) - // (X >s 0) ? -X : X or (X >s -1) ? -X : X --> NABS(X) - if (Pred == ICmpInst::ICMP_SGT && - match(CmpRHS, m_CombineOr(m_ZeroInt(), m_AllOnes()))) - return {(LHS == TrueVal) ? SPF_ABS : SPF_NABS, SPNB_NA, false}; - - // (X ABS(X) - // (X NABS(X) - if (Pred == ICmpInst::ICMP_SLT && - match(CmpRHS, m_CombineOr(m_ZeroInt(), m_One()))) - return {(LHS == FalseVal) ? SPF_ABS : SPF_NABS, SPNB_NA, false}; + // (X >s 0) ? -X : X or (X >s -1) ? -X : X --> NABS(X) + // (-X >s 0) ? X : -X or (-X >s -1) ? X : -X --> NABS(X) + if (Pred == ICmpInst::ICMP_SGT && match(CmpRHS, ZeroOrAllOnes)) + return {SPF_NABS, SPNB_NA, false}; + + // (X ABS(X) + // (-X ABS(X) + if (Pred == ICmpInst::ICMP_SLT && match(CmpRHS, ZeroOrOne)) + return {SPF_ABS, SPNB_NA, false}; + } } if (CmpInst::isIntPredicate(Pred)) Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -810,6 +810,11 @@ 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()) && Index: llvm/trunk/test/Transforms/InstCombine/abs_abs.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/abs_abs.ll +++ llvm/trunk/test/Transforms/InstCombine/abs_abs.ll @@ -293,7 +293,7 @@ define i32 @abs_abs_x17(i32 %x) { ; CHECK-LABEL: @abs_abs_x17( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 0 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[SUB]], -1 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[X]] ; CHECK-NEXT: ret i32 [[COND]] ; @@ -313,10 +313,7 @@ ; 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: [[CMP1:%.*]] = icmp slt i32 [[COND]], 0 -; CHECK-NEXT: [[SUB16:%.*]] = sub nsw i32 0, [[COND]] -; CHECK-NEXT: [[COND18:%.*]] = select i1 [[CMP1]], i32 [[SUB16]], i32 [[COND]] -; CHECK-NEXT: ret i32 [[COND18]] +; CHECK-NEXT: ret i32 [[COND]] ; %a = sub nsw i32 %x, %y %b = sub nsw i32 %y, %x @@ -332,7 +329,7 @@ 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 slt <2 x i32> [[X]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[SUB]], ; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[SUB]], <2 x i32> [[X]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; @@ -352,10 +349,7 @@ ; 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: [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], zeroinitializer -; CHECK-NEXT: [[SUB16:%.*]] = sub nsw <2 x i32> zeroinitializer, [[COND]] -; CHECK-NEXT: [[COND18:%.*]] = select <2 x i1> [[CMP1]], <2 x i32> [[SUB16]], <2 x i32> [[COND]] -; CHECK-NEXT: ret <2 x i32> [[COND18]] +; CHECK-NEXT: ret <2 x i32> [[COND]] ; %a = sub nsw <2 x i32> %x, %y %b = sub nsw <2 x i32> %y, %x @@ -627,7 +621,7 @@ define i32 @nabs_nabs_x17(i32 %x) { ; CHECK-LABEL: @nabs_nabs_x17( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 0 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[SUB]], -1 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] ; CHECK-NEXT: ret i32 [[COND]] ; @@ -647,10 +641,7 @@ ; 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: [[CMP1:%.*]] = icmp slt i32 [[COND]], 0 -; CHECK-NEXT: [[SUB16:%.*]] = sub nsw i32 0, [[COND]] -; CHECK-NEXT: [[COND18:%.*]] = select i1 [[CMP1]], i32 [[COND]], i32 [[SUB16]] -; CHECK-NEXT: ret i32 [[COND18]] +; CHECK-NEXT: ret i32 [[COND]] ; %a = sub nsw i32 %x, %y %b = sub nsw i32 %y, %x @@ -666,7 +657,7 @@ 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 slt <2 x i32> [[X]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[SUB]], ; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[X]], <2 x i32> [[SUB]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; @@ -686,10 +677,7 @@ ; 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: [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], zeroinitializer -; CHECK-NEXT: [[SUB16:%.*]] = sub nsw <2 x i32> zeroinitializer, [[COND]] -; CHECK-NEXT: [[COND18:%.*]] = select <2 x i1> [[CMP1]], <2 x i32> [[COND]], <2 x i32> [[SUB16]] -; CHECK-NEXT: ret <2 x i32> [[COND18]] +; CHECK-NEXT: ret <2 x i32> [[COND]] ; %a = sub nsw <2 x i32> %x, %y %b = sub nsw <2 x i32> %y, %x @@ -961,9 +949,9 @@ define i32 @abs_nabs_x17(i32 %x) { ; CHECK-LABEL: @abs_nabs_x17( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 0 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[SUB]], -1 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[X]] -; CHECK-NEXT: ret i32 [[COND1]] +; CHECK-NEXT: ret i32 [[COND]] ; %sub = sub nsw i32 0, %x %cmp = icmp sgt i32 %sub, -1 @@ -980,11 +968,8 @@ ; 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: [[CMP1:%.*]] = icmp slt i32 [[COND]], 0 -; CHECK-NEXT: [[SUB16:%.*]] = sub nsw i32 0, [[COND]] -; CHECK-NEXT: [[COND18:%.*]] = select i1 [[CMP1]], i32 [[SUB16]], i32 [[COND]] -; CHECK-NEXT: ret i32 [[COND18]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[B]] +; CHECK-NEXT: ret i32 [[COND]] ; %a = sub nsw i32 %x, %y %b = sub nsw i32 %y, %x @@ -1000,7 +985,7 @@ 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 slt <2 x i32> [[X]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[SUB]], ; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[SUB]], <2 x i32> [[X]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; @@ -1019,11 +1004,8 @@ ; 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: [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], zeroinitializer -; CHECK-NEXT: [[SUB16:%.*]] = sub nsw <2 x i32> zeroinitializer, [[COND]] -; CHECK-NEXT: [[COND18:%.*]] = select <2 x i1> [[CMP1]], <2 x i32> [[SUB16]], <2 x i32> [[COND]] -; CHECK-NEXT: ret <2 x i32> [[COND18]] +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[A]], <2 x i32> [[B]] +; CHECK-NEXT: ret <2 x i32> [[COND]] ; %a = sub nsw <2 x i32> %x, %y %b = sub nsw <2 x i32> %y, %x @@ -1295,9 +1277,9 @@ define i32 @nabs_abs_x17(i32 %x) { ; CHECK-LABEL: @nabs_abs_x17( ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 0 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[SUB]], -1 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] -; CHECK-NEXT: ret i32 [[COND1]] +; CHECK-NEXT: ret i32 [[COND]] ; %sub = sub nsw i32 0, %x %cmp = icmp sgt i32 %sub, -1 @@ -1314,11 +1296,8 @@ ; 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: [[CMP1:%.*]] = icmp slt i32 [[COND]], 0 -; CHECK-NEXT: [[SUB16:%.*]] = sub nsw i32 0, [[COND]] -; CHECK-NEXT: [[COND18:%.*]] = select i1 [[CMP1]], i32 [[COND]], i32 [[SUB16]] -; CHECK-NEXT: ret i32 [[COND18]] +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[B]], i32 [[A]] +; CHECK-NEXT: ret i32 [[COND]] ; %a = sub nsw i32 %x, %y %b = sub nsw i32 %y, %x @@ -1334,7 +1313,7 @@ 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 slt <2 x i32> [[X]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[SUB]], ; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[X]], <2 x i32> [[SUB]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ; @@ -1353,11 +1332,8 @@ ; 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: [[CMP1:%.*]] = icmp slt <2 x i32> [[COND]], zeroinitializer -; CHECK-NEXT: [[SUB16:%.*]] = sub nsw <2 x i32> zeroinitializer, [[COND]] -; CHECK-NEXT: [[COND18:%.*]] = select <2 x i1> [[CMP1]], <2 x i32> [[COND]], <2 x i32> [[SUB16]] -; CHECK-NEXT: ret <2 x i32> [[COND18]] +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[B]], <2 x i32> [[A]] +; CHECK-NEXT: ret <2 x i32> [[COND]] ; %a = sub nsw <2 x i32> %x, %y %b = sub nsw <2 x i32> %y, %x Index: llvm/trunk/test/Transforms/InstCombine/icmp.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/icmp.ll +++ llvm/trunk/test/Transforms/InstCombine/icmp.ll @@ -3345,7 +3345,7 @@ 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 slt <2 x i32> [[X]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i32> [[SUB]], ; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[SUB]], <2 x i32> [[X]] ; CHECK-NEXT: ret <2 x i32> [[COND]] ;