Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[InstCombine] Simplify the pattern a ne/eq (zext/sext (a ne/eq c)) #65852

Merged
merged 15 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6309,7 +6309,69 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) {
Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);

ICmpInst::Predicate Pred1, Pred2;
const APInt *C;
// icmp eq/ne X, (zext (icmp eq/ne X, C))
if (match(&I, m_c_ICmp(Pred1, m_Value(X),
m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C))))) &&
dtcxzyw marked this conversation as resolved.
Show resolved Hide resolved
ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
if (C->isZero()) {
if (Pred2 == ICmpInst::ICMP_EQ) {
// icmp eq X, (zext (icmp eq X, 0)) --> false
// icmp ne X, (zext (icmp eq X, 0)) --> true
return replaceInstUsesWith(
I,
Constant::getIntegerValue(
I.getType(),
APInt(1U, static_cast<uint64_t>(Pred1 == ICmpInst::ICMP_NE))));
dtcxzyw marked this conversation as resolved.
Show resolved Hide resolved
} else {
// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
return ICmpInst::Create(
Instruction::ICmp,
Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
: ICmpInst::ICMP_ULT,
X,
Constant::getIntegerValue(
X->getType(), APInt(X->getType()->getScalarSizeInBits(),
Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
}
} else if (C->isOne()) {
if (Pred2 == ICmpInst::ICMP_NE) {
// icmp eq X, (zext (icmp ne X, 1)) --> false
// icmp ne X, (zext (icmp ne X, 1)) --> true
return replaceInstUsesWith(
I,
Constant::getIntegerValue(
I.getType(),
APInt(1U, static_cast<uint64_t>(Pred1 == ICmpInst::ICMP_NE))));
} else {
// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
return ICmpInst::Create(
Instruction::ICmp,
Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
: ICmpInst::ICMP_ULT,
X,
Constant::getIntegerValue(
X->getType(), APInt(X->getType()->getScalarSizeInBits(),
Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
}
} else {
// C != 0 && C != 1
// icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
// icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
// icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
// icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
return ICmpInst::Create(
Instruction::ICmp, Pred1, X,
Constant::getIntegerValue(
X->getType(),
APInt(X->getType()->getScalarSizeInBits(),
static_cast<uint64_t>(Pred2 == ICmpInst::ICMP_NE))));
}
}

dtcxzyw marked this conversation as resolved.
Show resolved Hide resolved
if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y)))) &&
match(I.getOperand(1), m_APInt(C)) &&
X->getType()->isIntOrIntVectorTy(1) &&
Expand Down
181 changes: 181 additions & 0 deletions llvm/test/Transforms/InstCombine/icmp-range.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
ret i1 %cmp
}

define i1 @icmp_ne_zext_eq_zero(i32 %a) {
; CHECK-LABEL: @icmp_ne_zext_eq_zero(
; CHECK-NEXT: ret i1 true
;
%cmp = icmp eq i32 %a, 0
%conv = zext i1 %cmp to i32
%cmp1 = icmp ne i32 %conv, %a
ret i1 %cmp1
}

define i1 @icmp_ne_zext_ne_zero(i32 %a) {
; CHECK-LABEL: @icmp_ne_zext_ne_zero(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
; CHECK-NEXT: ret i1 [[CMP1]]
;
%cmp = icmp ne i32 %a, 0
%conv = zext i1 %cmp to i32
%cmp1 = icmp ne i32 %conv, %a
ret i1 %cmp1
}

define i1 @icmp_eq_zext_eq_zero(i32 %a) {
; CHECK-LABEL: @icmp_eq_zext_eq_zero(
; CHECK-NEXT: ret i1 false
;
%cmp = icmp eq i32 %a, 0
%conv = zext i1 %cmp to i32
%cmp1 = icmp eq i32 %conv, %a
ret i1 %cmp1
}

define i1 @icmp_eq_zext_ne_zero(i32 %a) {
; CHECK-LABEL: @icmp_eq_zext_ne_zero(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[A:%.*]], 2
; CHECK-NEXT: ret i1 [[CMP1]]
;
%cmp = icmp ne i32 %a, 0
%conv = zext i1 %cmp to i32
%cmp1 = icmp eq i32 %conv, %a
ret i1 %cmp1
}

define i1 @icmp_ne_zext_eq_one(i32 %a) {
; CHECK-LABEL: @icmp_ne_zext_eq_one(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
; CHECK-NEXT: ret i1 [[CMP1]]
;
%cmp = icmp eq i32 %a, 1
%conv = zext i1 %cmp to i32
%cmp1 = icmp ne i32 %conv, %a
ret i1 %cmp1
}

define i1 @icmp_ne_zext_ne_one(i32 %a) {
; CHECK-LABEL: @icmp_ne_zext_ne_one(
; CHECK-NEXT: ret i1 true
;
%cmp = icmp ne i32 %a, 1
%conv = zext i1 %cmp to i32
%cmp1 = icmp ne i32 %conv, %a
ret i1 %cmp1
}

define i1 @icmp_eq_zext_eq_one(i32 %a) {
; CHECK-LABEL: @icmp_eq_zext_eq_one(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[A:%.*]], 2
; CHECK-NEXT: ret i1 [[CMP1]]
;
%cmp = icmp eq i32 %a, 1
%conv = zext i1 %cmp to i32
%cmp1 = icmp eq i32 %conv, %a
ret i1 %cmp1
}

define i1 @icmp_eq_zext_ne_one(i32 %a) {
; CHECK-LABEL: @icmp_eq_zext_ne_one(
; CHECK-NEXT: ret i1 false
;
%cmp = icmp ne i32 %a, 1
%conv = zext i1 %cmp to i32
%cmp1 = icmp eq i32 %conv, %a
ret i1 %cmp1
}

define i1 @icmp_ne_zext_eq_non_boolean(i32 %a) {
; CHECK-LABEL: @icmp_ne_zext_eq_non_boolean(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 0
; CHECK-NEXT: ret i1 [[CMP1]]
;
%cmp = icmp eq i32 %a, 2
%conv = zext i1 %cmp to i32
%cmp1 = icmp ne i32 %conv, %a
ret i1 %cmp1
}

define i1 @icmp_ne_zext_ne_non_boolean(i32 %a) {
; CHECK-LABEL: @icmp_ne_zext_ne_non_boolean(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 1
; CHECK-NEXT: ret i1 [[CMP1]]
;
%cmp = icmp ne i32 %a, 2
%conv = zext i1 %cmp to i32
%cmp1 = icmp ne i32 %conv, %a
ret i1 %cmp1
}

define i1 @icmp_eq_zext_eq_non_boolean(i32 %a) {
; CHECK-LABEL: @icmp_eq_zext_eq_non_boolean(
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
; CHECK-NEXT: ret i1 [[CMP1]]
;
%cmp = icmp eq i32 %a, 2
%conv = zext i1 %cmp to i32
%cmp1 = icmp eq i32 %conv, %a
ret i1 %cmp1
}

define i1 @icmp_eq_zext_ne_non_boolean(i32 %a) {
; CHECK-LABEL: @icmp_eq_zext_ne_non_boolean(
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 1
; CHECK-NEXT: ret i1 [[CMP1]]
;
%cmp = icmp ne i32 %a, 2
%conv = zext i1 %cmp to i32
%cmp1 = icmp eq i32 %conv, %a
ret i1 %cmp1
}

define <2 x i1> @icmp_ne_zext_eq_zero_vec(<2 x i32> %a) {
; CHECK-LABEL: @icmp_ne_zext_eq_zero_vec(
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%cmp = icmp eq <2 x i32> %a, <i32 0, i32 0>
%conv = zext <2 x i1> %cmp to <2 x i32>
%cmp1 = icmp ne <2 x i32> %conv, %a
ret <2 x i1> %cmp1
}

define <2 x i1> @icmp_ne_zext_ne_zero_vec(<2 x i32> %a) {
; CHECK-LABEL: @icmp_ne_zext_ne_zero_vec(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <2 x i32> [[A:%.*]], <i32 1, i32 1>
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
;
%cmp = icmp ne <2 x i32> %a, <i32 0, i32 0>
%conv = zext <2 x i1> %cmp to <2 x i32>
%cmp1 = icmp ne <2 x i32> %conv, %a
ret <2 x i1> %cmp1
}

define <2 x i1> @icmp_ne_zext_eq_one_vec(<2 x i32> %a) {
; CHECK-LABEL: @icmp_ne_zext_eq_one_vec(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <2 x i32> [[A:%.*]], <i32 1, i32 1>
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
;
%cmp = icmp eq <2 x i32> %a, <i32 1, i32 1>
%conv = zext <2 x i1> %cmp to <2 x i32>
%cmp1 = icmp ne <2 x i32> %conv, %a
ret <2 x i1> %cmp1
}

define <2 x i1> @icmp_ne_zext_ne_one_vec(<2 x i32> %a) {
; CHECK-LABEL: @icmp_ne_zext_ne_one_vec(
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%cmp = icmp ne <2 x i32> %a, <i32 1, i32 1>
%conv = zext <2 x i1> %cmp to <2 x i32>
%cmp1 = icmp ne <2 x i32> %conv, %a
ret <2 x i1> %cmp1
}

define <2 x i1> @icmp_ne_zext_eq_non_boolean_vec(<2 x i32> %a) {
; CHECK-LABEL: @icmp_ne_zext_eq_non_boolean_vec(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[A:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
;
%cmp = icmp eq <2 x i32> %a, <i32 2, i32 2>
%conv = zext <2 x i1> %cmp to <2 x i32>
%cmp1 = icmp ne <2 x i32> %conv, %a
ret <2 x i1> %cmp1
}

dtcxzyw marked this conversation as resolved.
Show resolved Hide resolved
!0 = !{i32 1, i32 6}
!1 = !{i32 0, i32 6}
!2 = !{i8 0, i8 1}
Expand Down