https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/65852
>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Sat, 9 Sep 2023 23:07:29 +0800 Subject: [PATCH] [InstCombine] Simplify the pattern `a ne/eq (zext (a ne/eq c))` --- .../InstCombine/InstCombineCompares.cpp | 62 ++++++ .../test/Transforms/InstCombine/icmp-range.ll | 181 ++++++++++++++++++ 2 files changed, 243 insertions(+) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 9fdc46fec631679..837b8e6d2619989 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -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))))) && + 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)))); + } 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)))); + } + } + 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) && diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll index 4281e09cb0309c8..15424fce33fdeea 100644 --- a/llvm/test/Transforms/InstCombine/icmp-range.ll +++ b/llvm/test/Transforms/InstCombine/icmp-range.ll @@ -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 +} + !0 = !{i32 1, i32 6} !1 = !{i32 0, i32 6} !2 = !{i8 0, i8 1} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits