diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1358,6 +1358,18 @@ if (!match(Cmp.getOperand(1), m_Zero())) return nullptr; + // (icmp eq and(~A, B) 0) -> (icmp eq or(freeze(A), B) A) + // (icmp ne and(~A, B) 0) -> (icmp ne or(freeze(A), B) A) + if (Pred == ICmpInst::ICMP_EQ || Pred == ICmpInst::ICMP_NE) { + Value *A, *B; + if (match(Cmp.getOperand(0), + m_OneUse(m_c_And(m_Not(m_Value(A)), m_Value(B))))) { + Value *NewA = Builder.CreateFreeze(A); + Value *NewOr = Builder.CreateOr(NewA, B); + return new ICmpInst(Pred, NewOr, NewA); + } + } + // (icmp sgt smin(PosA, B) 0) -> (icmp sgt B 0) if (Pred == ICmpInst::ICMP_SGT) { Value *A, *B; diff --git a/llvm/test/Transforms/InstCombine/2010-11-23-Distributed.ll b/llvm/test/Transforms/InstCombine/2010-11-23-Distributed.ll --- a/llvm/test/Transforms/InstCombine/2010-11-23-Distributed.ll +++ b/llvm/test/Transforms/InstCombine/2010-11-23-Distributed.ll @@ -15,9 +15,9 @@ define i1 @bar(i64 %x, i64 %y) { ; CHECK-LABEL: @bar( -; CHECK-NEXT: [[TMP1:%.*]] = xor i64 [[X:%.*]], -1 -; CHECK-NEXT: [[B:%.*]] = and i64 [[TMP1]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[B]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = freeze i64 [[X:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i64 [[TMP1]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[TMP2]], [[TMP1]] ; CHECK-NEXT: ret i1 [[R]] ; %a = and i64 %y, %x diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -1803,8 +1803,9 @@ define i1 @icmp_and_shl_neg_ne_0(i32 %A, i32 %B) { ; CHECK-LABEL: @icmp_and_shl_neg_ne_0( ; CHECK-NEXT: [[SHL:%.*]] = shl i32 1, [[B:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[SHL]], [[A:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[A:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[SHL]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] ; CHECK-NEXT: ret i1 [[CMP]] ; %neg = xor i32 %A, -1 @@ -1817,8 +1818,9 @@ define i1 @icmp_and_shl_neg_eq_0(i32 %A, i32 %B) { ; CHECK-LABEL: @icmp_and_shl_neg_eq_0( ; CHECK-NEXT: [[SHL:%.*]] = shl i32 1, [[B:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[SHL]], [[A:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP1]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[A:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[SHL]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP2]], [[TMP1]] ; CHECK-NEXT: ret i1 [[CMP]] ; %neg = xor i32 %A, -1 diff --git a/llvm/test/Transforms/InstCombine/rem.ll b/llvm/test/Transforms/InstCombine/rem.ll --- a/llvm/test/Transforms/InstCombine/rem.ll +++ b/llvm/test/Transforms/InstCombine/rem.ll @@ -703,9 +703,9 @@ define i1 @test26(i32 %A, i32 %B) { ; CHECK-LABEL: @test26( ; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i32 -1, [[B:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[NOTMASK]], -1 -; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[A:%.*]] -; CHECK-NEXT: [[E:%.*]] = icmp ne i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[NOTMASK]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: [[E:%.*]] = icmp ne i32 [[TMP2]], [[TMP1]] ; CHECK-NEXT: ret i1 [[E]] ; %C = shl i32 1, %B ; not a constant