diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 8968f6b934d77..59a213b47825a 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3261,20 +3261,20 @@ static Value *simplifyICmpWithBinOpOnLHS(CmpPredicate Pred, BinaryOperator *LBO, // If only one of the icmp's operands has NSW flags, try to prove that: // -// icmp slt (x + C1), (x +nsw C2) +// icmp slt/sgt/sle/sge (x + C1), (x +nsw C2) // // is equivalent to: // -// icmp slt C1, C2 +// icmp slt/sgt/sle/sge C1, C2 // // which is true if x + C2 has the NSW flags set and: -// *) C1 < C2 && C1 >= 0, or -// *) C2 < C1 && C1 <= 0. +// *) C1 <= C2 && C1 >= 0, or +// *) C2 <= C1 && C1 <= 0. // static bool trySimplifyICmpWithAdds(CmpPredicate Pred, Value *LHS, Value *RHS, const InstrInfoQuery &IIQ) { - // TODO: only support icmp slt for now. - if (Pred != CmpInst::ICMP_SLT || !IIQ.UseInstrInfo) + // TODO: support other predicates. + if (!ICmpInst::isSigned(Pred) || !IIQ.UseInstrInfo) return false; // Canonicalize nsw add as RHS. @@ -3289,8 +3289,8 @@ static bool trySimplifyICmpWithAdds(CmpPredicate Pred, Value *LHS, Value *RHS, !match(RHS, m_Add(m_Specific(X), m_APInt(C2)))) return false; - return (C1->slt(*C2) && C1->isNonNegative()) || - (C2->slt(*C1) && C1->isNonPositive()); + return (C1->sle(*C2) && C1->isNonNegative()) || + (C2->sle(*C1) && C1->isNonPositive()); } /// TODO: A large part of this logic is duplicated in InstCombine's diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll index 97ac8f2ea47ea..ba10ea532a34a 100644 --- a/llvm/test/Transforms/InstSimplify/compare.ll +++ b/llvm/test/Transforms/InstSimplify/compare.ll @@ -2687,10 +2687,7 @@ define i1 @icmp_nsw_false_2(i32 %V) { define i1 @icmp_nsw_false_3(i32 %V) { ; CHECK-LABEL: @icmp_nsw_false_3( -; CHECK-NEXT: [[ADD5:%.*]] = add nsw i32 [[V:%.*]], 5 -; CHECK-NEXT: [[ADD6:%.*]] = add i32 [[V]], 5 -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD5]], [[ADD6]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %add5 = add nsw i32 %V, 5 %add6 = add i32 %V, 5 @@ -2724,6 +2721,45 @@ define i1 @icmp_nsw_false_5(i8 %V) { ret i1 %cmp } +define i1 @icmp_nsw_false_6(i8 %V) { +; CHECK-LABEL: @icmp_nsw_false_6( +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], 6 +; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[ADD]], [[ADDNSW]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add = add i8 %V, 6 + %addnsw = add nsw i8 %V, -1 + %cmp = icmp sgt i8 %add, %addnsw + ret i1 %cmp +} + +define i1 @icmp_nsw_false_7(i8 %V) { +; CHECK-LABEL: @icmp_nsw_false_7( +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], -1 +; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], 3 +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[ADD]], [[ADDNSW]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add = add i8 %V, -1 + %addnsw = add nsw i8 %V, 3 + %cmp = icmp sle i8 %add, %addnsw + ret i1 %cmp +} + +define i1 @icmp_nsw_false_8(i8 %V) { +; CHECK-LABEL: @icmp_nsw_false_8( +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], -15 +; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], 42 +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[ADD]], [[ADDNSW]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add = add i8 %V, -15 + %addnsw = add nsw i8 %V, 42 + %cmp = icmp sge i8 %add, %addnsw + ret i1 %cmp +} + define i1 @icmp_nsw_i8(i8 %V) { ; CHECK-LABEL: @icmp_nsw_i8( ; CHECK-NEXT: ret i1 true @@ -2766,10 +2802,7 @@ define <4 x i1> @icmp_nsw_vec(<4 x i32> %V) { define i1 @icmp_nsw_3(i32 %V) { ; CHECK-LABEL: @icmp_nsw_3( -; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 5 -; CHECK-NEXT: [[ADD5_2:%.*]] = add nsw i32 [[V]], 5 -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD5]], [[ADD5_2]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %add5 = add i32 %V, 5 %add5_2 = add nsw i32 %V, 5 @@ -2844,10 +2877,7 @@ define i1 @icmp_nsw_9(i32 %V1, i32 %V2) { define i1 @icmp_nsw_10(i32 %V) { ; CHECK-LABEL: @icmp_nsw_10( -; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 5 -; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], 6 -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD6]], [[ADD5]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %add5 = add i32 %V, 5 %add6 = add nsw i32 %V, 6 @@ -2868,6 +2898,36 @@ define i1 @icmp_nsw_11(i32 %V) { ret i1 %cmp } +define i1 @icmp_nsw_12(i32 %V) { +; CHECK-LABEL: @icmp_nsw_12( +; CHECK-NEXT: ret i1 true +; + %add5 = add i32 %V, 2 + %add6 = add nsw i32 %V, 3 + %cmp = icmp slt i32 %add5, %add6 + ret i1 %cmp +} + +define i1 @icmp_nsw_13(i32 %V) { +; CHECK-LABEL: @icmp_nsw_13( +; CHECK-NEXT: ret i1 true +; + %add5 = add i32 %V, 7 + %add6 = add nsw i32 %V, 10 + %cmp = icmp sle i32 %add5, %add6 + ret i1 %cmp +} + +define i1 @icmp_nsw_14(i32 %V) { +; CHECK-LABEL: @icmp_nsw_14( +; CHECK-NEXT: ret i1 false +; + %add5 = add i32 %V, 7 + %add6 = add nsw i32 %V, 10 + %cmp = icmp sge i32 %add5, %add6 + ret i1 %cmp +} + define i1 @icmp_nsw_nonpos(i32 %V) { ; CHECK-LABEL: @icmp_nsw_nonpos( ; CHECK-NEXT: ret i1 false @@ -2890,6 +2950,36 @@ define i1 @icmp_nsw_nonpos2(i32 %V) { ret i1 %cmp } +define i1 @icmp_nsw_nonpos3(i32 %V) { +; CHECK-LABEL: @icmp_nsw_nonpos3( +; CHECK-NEXT: ret i1 false +; + %add5 = add i32 %V, -2 + %add6 = add nsw i32 %V, -5 + %cmp = icmp sle i32 %add5, %add6 + ret i1 %cmp +} + +define i1 @icmp_nsw_nonpos4(i32 %V) { +; CHECK-LABEL: @icmp_nsw_nonpos4( +; CHECK-NEXT: ret i1 true +; + %add5 = add i32 %V, -10 + %add6 = add nsw i32 %V, -30 + %cmp = icmp sgt i32 %add5, %add6 + ret i1 %cmp +} + +define i1 @icmp_nsw_nonpos5(i32 %V) { +; CHECK-LABEL: @icmp_nsw_nonpos5( +; CHECK-NEXT: ret i1 true +; + %add5 = add i32 %V, -15 + %add6 = add nsw i32 %V, -100 + %cmp = icmp sge i32 %add5, %add6 + ret i1 %cmp +} + declare i11 @llvm.ctpop.i11(i11) declare i73 @llvm.ctpop.i73(i73) declare <2 x i13> @llvm.ctpop.v2i13(<2 x i13>)