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 @@ -1953,6 +1953,30 @@ return new ICmpInst(NewPred, X, NewC); } + const APInt *OrC; + // icmp(X | OrC, C) --> icmp(X, 0) + if (C.isNonNegative() && match(Or, m_Or(m_Value(X), m_APInt(OrC)))) { + switch (Pred) { + // X | OrC s< C --> X s< 0 iff OrC s>= C s>= 0 + case ICmpInst::ICMP_SLT: + // X | OrC s>= C --> X s>= 0 iff OrC s>= C s>= 0 + case ICmpInst::ICMP_SGE: + if (OrC->sge(C)) + return new ICmpInst(Pred, X, ConstantInt::getNullValue(X->getType())); + break; + // X | OrC s<= C --> X s< 0 iff OrC s> C s>= 0 + case ICmpInst::ICMP_SLE: + // X | OrC s> C --> X s>= 0 iff OrC s> C s>= 0 + case ICmpInst::ICMP_SGT: + if (OrC->sgt(C)) + return new ICmpInst(ICmpInst::getFlippedStrictnessPredicate(Pred), X, + ConstantInt::getNullValue(X->getType())); + break; + default: + break; + } + } + if (!Cmp.isEquality() || !C.isZero() || !Or->hasOneUse()) return nullptr; 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 @@ -4634,8 +4634,7 @@ define i1 @or_positive_sgt_zero(i8 %a) { ; CHECK-LABEL: @or_positive_sgt_zero( -; CHECK-NEXT: [[B:%.*]] = or i8 [[A:%.*]], 24 -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[B]], 0 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], -1 ; CHECK-NEXT: ret i1 [[CMP]] ; %b = or i8 %a, 24 @@ -4645,8 +4644,7 @@ define <2 x i1> @or_postive_sgt_zero_vec(<2 x i8> %a) { ; CHECK-LABEL: @or_postive_sgt_zero_vec( -; CHECK-NEXT: [[B:%.*]] = or <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[B]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[A:%.*]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; @@ -4698,8 +4696,7 @@ define i1 @or_positive_sge_postive(i8 %a) { ; CHECK-LABEL: @or_positive_sge_postive( -; CHECK-NEXT: [[B:%.*]] = or i8 [[A:%.*]], 24 -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[B]], 23 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], -1 ; CHECK-NEXT: ret i1 [[CMP]] ; %b = or i8 %a, 24 @@ -4709,8 +4706,7 @@ define <2 x i1> @or_postive_sge_positive_vec(<2 x i8> %a) { ; CHECK-LABEL: @or_postive_sge_positive_vec( -; CHECK-NEXT: [[B:%.*]] = or <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[B]], +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[A:%.*]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; @@ -4731,8 +4727,7 @@ define i1 @or_positive_sle_zero(i8 %a) { ; CHECK-LABEL: @or_positive_sle_zero( -; CHECK-NEXT: [[B:%.*]] = or i8 [[A:%.*]], 24 -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[B]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[A:%.*]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %b = or i8 %a, 24 @@ -4742,8 +4737,7 @@ define <2 x i1> @or_postive_sle_zero_vec(<2 x i8> %a) { ; CHECK-LABEL: @or_postive_sle_zero_vec( -; CHECK-NEXT: [[B:%.*]] = or <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[B]], +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[A:%.*]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; @@ -4795,8 +4789,7 @@ define i1 @or_positive_slt_postive(i8 %a) { ; CHECK-LABEL: @or_positive_slt_postive( -; CHECK-NEXT: [[B:%.*]] = or i8 [[A:%.*]], 24 -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[B]], 24 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[A:%.*]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %b = or i8 %a, 24 @@ -4806,8 +4799,7 @@ define <2 x i1> @or_postive_slt_positive_vec(<2 x i8> %a) { ; CHECK-LABEL: @or_postive_slt_positive_vec( -; CHECK-NEXT: [[B:%.*]] = or <2 x i8> [[A:%.*]], -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[B]], +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[A:%.*]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; @@ -4968,7 +4960,7 @@ ; CHECK-LABEL: @or_positive_sgt_zero_multi_use( ; CHECK-NEXT: [[B:%.*]] = or i8 [[A:%.*]], 24 ; CHECK-NEXT: call void @use_i8(i8 [[B]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[B]], 0 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[A]], -1 ; CHECK-NEXT: ret i1 [[CMP]] ; %b = or i8 %a, 24 @@ -4981,7 +4973,7 @@ ; CHECK-LABEL: @or_postive_sgt_zero_vec_multi_use( ; CHECK-NEXT: [[B:%.*]] = or <2 x i8> [[A:%.*]], ; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[B]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[B]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[A]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; @@ -5022,7 +5014,7 @@ ; CHECK-LABEL: @or_positive_sge_postive_multi_use( ; CHECK-NEXT: [[B:%.*]] = or i8 [[A:%.*]], 24 ; CHECK-NEXT: call void @use_i8(i8 [[B]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[B]], 23 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[A]], -1 ; CHECK-NEXT: ret i1 [[CMP]] ; %b = or i8 %a, 24 @@ -5035,7 +5027,7 @@ ; CHECK-LABEL: @or_postive_sge_positive_vec_multi_use( ; CHECK-NEXT: [[B:%.*]] = or <2 x i8> [[A:%.*]], ; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[B]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[B]], +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[A]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; @@ -5049,7 +5041,7 @@ ; CHECK-LABEL: @or_positive_sle_zero_multi_use( ; CHECK-NEXT: [[B:%.*]] = or i8 [[A:%.*]], 24 ; CHECK-NEXT: call void @use_i8(i8 [[B]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[B]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[A]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %b = or i8 %a, 24 @@ -5062,7 +5054,7 @@ ; CHECK-LABEL: @or_postive_sle_zero_vec_multi_use( ; CHECK-NEXT: [[B:%.*]] = or <2 x i8> [[A:%.*]], ; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[B]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[B]], +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[A]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; @@ -5076,7 +5068,7 @@ ; CHECK-LABEL: @or_positive_slt_zero_multi_use( ; CHECK-NEXT: [[B:%.*]] = or i8 [[A:%.*]], 24 ; CHECK-NEXT: call void @use_i8(i8 [[B]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[B]], 0 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[A]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %b = or i8 %a, 24 @@ -5089,7 +5081,7 @@ ; CHECK-LABEL: @or_postive_slt_zero_vec_multi_use( ; CHECK-NEXT: [[B:%.*]] = or <2 x i8> [[A:%.*]], ; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[B]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[B]], zeroinitializer +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[A]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; @@ -5103,7 +5095,7 @@ ; CHECK-LABEL: @or_positive_slt_postive_multi_use( ; CHECK-NEXT: [[B:%.*]] = or i8 [[A:%.*]], 24 ; CHECK-NEXT: call void @use_i8(i8 [[B]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[B]], 24 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[A]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; %b = or i8 %a, 24 @@ -5116,7 +5108,7 @@ ; CHECK-LABEL: @or_postive_slt_positive_vec_multi_use( ; CHECK-NEXT: [[B:%.*]] = or <2 x i8> [[A:%.*]], ; CHECK-NEXT: call void @use_v2i8(<2 x i8> [[B]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[B]], +; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[A]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ;