return nullptr;
const CmpInst::Predicate Pred = I.getPredicate();
+ Value *X;
+
+ // Convert add-with-unsigned-overflow comparisons into a 'not' with compare.
+ // (Op1 + X) <u Op1 --> ~Op1 <u X
+ // Op0 >u (Op0 + X) --> X >u ~Op0
+ if (match(Op0, m_OneUse(m_c_Add(m_Specific(Op1), m_Value(X)))) &&
+ Pred == ICmpInst::ICMP_ULT)
+ return new ICmpInst(Pred, Builder.CreateNot(Op1), X);
+ if (match(Op1, m_OneUse(m_c_Add(m_Specific(Op0), m_Value(X)))) &&
+ Pred == ICmpInst::ICMP_UGT)
+ return new ICmpInst(Pred, X, Builder.CreateNot(Op0));
+
bool NoOp0WrapProblem = false, NoOp1WrapProblem = false;
if (BO0 && isa<OverflowingBinaryOperator>(BO0))
NoOp0WrapProblem =
; CHECK-LABEL: @op_ugt_sum_commute1(
; CHECK-NEXT: [[X:%.*]] = sdiv i8 42, [[P1:%.*]]
; CHECK-NEXT: [[Y:%.*]] = sdiv i8 42, [[P2:%.*]]
-; CHECK-NEXT: [[A:%.*]] = add i8 [[X]], [[Y]]
-; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[X]], [[A]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X]], -1
+; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[Y]], [[TMP1]]
; CHECK-NEXT: ret i1 [[C]]
;
%x = sdiv i8 42, %p1
; CHECK-LABEL: @op_ugt_sum_vec_commute2(
; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> <i8 42, i8 -42>, [[P1:%.*]]
; CHECK-NEXT: [[Y:%.*]] = sdiv <2 x i8> <i8 42, i8 -42>, [[P2:%.*]]
-; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[Y]], [[X]]
-; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i8> [[X]], [[A]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[X]], <i8 -1, i8 -1>
+; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i8> [[Y]], [[TMP1]]
; CHECK-NEXT: ret <2 x i1> [[C]]
;
%x = sdiv <2 x i8> <i8 42, i8 -42>, %p1
; CHECK-LABEL: @sum_ult_op_vec_commute1(
; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> <i8 42, i8 -42>, [[P1:%.*]]
; CHECK-NEXT: [[Y:%.*]] = sdiv <2 x i8> <i8 -42, i8 42>, [[P2:%.*]]
-; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X]], [[Y]]
-; CHECK-NEXT: [[C:%.*]] = icmp ult <2 x i8> [[A]], [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[X]], <i8 -1, i8 -1>
+; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i8> [[Y]], [[TMP1]]
; CHECK-NEXT: ret <2 x i1> [[C]]
;
%x = sdiv <2 x i8> <i8 42, i8 -42>, %p1
; CHECK-LABEL: @sum_ult_op_commute2(
; CHECK-NEXT: [[X:%.*]] = sdiv i8 42, [[P1:%.*]]
; CHECK-NEXT: [[Y:%.*]] = sdiv i8 42, [[P2:%.*]]
-; CHECK-NEXT: [[A:%.*]] = add i8 [[Y]], [[X]]
-; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[A]], [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X]], -1
+; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[Y]], [[TMP1]]
; CHECK-NEXT: ret i1 [[C]]
;
%x = sdiv i8 42, %p1