diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index fba1ccf2c8c9b..212a47af2cd20 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -7855,6 +7855,26 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) { } } + // Transform (x | y) > x + y into x > x + y + Value *OrLHS, *OrRHS, *AddLHS, *AddRHS; + if (match(Op0, m_Or(m_Value(OrLHS), m_Value(OrRHS))) && + match(Op1, m_Add(m_Value(AddLHS), m_Value(AddRHS))) && + ((OrLHS == AddLHS && OrRHS == AddRHS) || + (OrLHS == AddRHS && OrRHS == AddLHS))) { + // Replace (x | y) with x in the comparison + replaceOperand(I, 0, AddLHS); + return &I; + } + + if (match(Op0, m_Add(m_Value(AddLHS), m_Value(AddRHS))) && + match(Op1, m_Or(m_Value(OrLHS), m_Value(OrRHS))) && + ((AddLHS == OrLHS && AddRHS == OrRHS) || + (AddLHS == OrRHS && AddRHS == OrLHS))) { + // Replace (x | y) with x in the comparison + replaceOperand(I, 1, AddLHS); + return &I; + } + Instruction *AddI = nullptr; if (match(&I, m_UAddWithOverflow(m_Value(X), m_Value(Y), m_Instruction(AddI))) && diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index 696208b903798..721c89fac1e44 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -6240,3 +6240,32 @@ entry: %cmp = icmp ult i8 %p0, %p1 ret i1 %cmp } + +; Transform (x | y) > x + y into x > x + y +; This is valid because (x | y) >= x always, so (x | y) > x + y is equivalent to x > x + y +define i1 @uaddo_or(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @uaddo_or( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[Y]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X]], [[TMP1]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %or = or i32 %y, %x + %add = add i32 %y, %x + %cmp = icmp ugt i32 %or, %add + ret i1 %cmp +} + +; Transform x + y < (x | y) into x + y < x (equivalent to x > x + y) +define i1 @uaddo_or_reverse(i32 %x, i32 %y) { +; CHECK-LABEL: define i1 @uaddo_or_reverse( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[Y]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X]], [[TMP1]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add = add i32 %y, %x + %or = or i32 %y, %x + %cmp = icmp ult i32 %add, %or + ret i1 %cmp +}