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 1/5] [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} >From bf79e8624a1578c65ca3adc4c3c95512c0e18d53 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Mon, 18 Sep 2023 22:36:02 +0800 Subject: [PATCH 2/5] fixup! [InstCombine] Simplify the pattern `a ne/eq (zext (a ne/eq c))` --- .../lib/Transforms/InstCombine/InstCombineCompares.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index d0b62c17ec94358..d1f141bcf0e7df7 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6391,10 +6391,7 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { // 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)))); + I, ConstantInt::getBool(I.getType(), 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 @@ -6412,10 +6409,7 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { // 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)))); + I, ConstantInt::getBool(I.getType(), 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 >From ba475e31713758724305acbff496cbe605888da8 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Mon, 18 Sep 2023 23:00:17 +0800 Subject: [PATCH 3/5] fixup! [InstCombine] Simplify the pattern `a ne/eq (zext (a ne/eq c))` --- .../Transforms/InstCombine/InstCombineCompares.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index d1f141bcf0e7df7..c5e3ad8a55741fb 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6400,9 +6400,7 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { 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))); + ConstantInt::get(X->getType(), Pred1 == ICmpInst::ICMP_NE ? 1 : 2)); } } else if (C->isOne()) { if (Pred2 == ICmpInst::ICMP_NE) { @@ -6418,9 +6416,7 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { 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))); + ConstantInt::get(X->getType(), Pred1 == ICmpInst::ICMP_NE ? 1 : 2)); } } else { // C != 0 && C != 1 @@ -6430,10 +6426,7 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { // 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)))); + ConstantInt::get(X->getType(), Pred2 == ICmpInst::ICMP_NE ? 1 : 0)); } } >From 70a70fb44d0e628a1cf485e1767ada3eaaa26b0f Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Tue, 19 Sep 2023 03:30:11 +0800 Subject: [PATCH 4/5] fixup! [InstCombine] Simplify the pattern `a ne/eq (zext (a ne/eq c))` --- llvm/include/llvm/IR/PatternMatch.h | 22 ++++++++ .../InstCombine/InstCombineCompares.cpp | 50 +++++++++++++------ 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 13877538f79de6d..38d40d1ec9a839e 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -767,6 +767,28 @@ m_ImmConstant(Constant *&C) { return m_CombineAnd(m_Constant(C), m_Unless(m_ConstantExpr())); } +/// Match a pattern, capturing the value if we match. +template <typename SubPattern_t, typename Class> struct capture_ty { + SubPattern_t SubPattern; + Class *&VR; + + capture_ty(const SubPattern_t &SP, Class *&V) : SubPattern(SP), VR(V) {} + + template <typename ITy> bool match(ITy *V) { + if (auto *CV = dyn_cast<Class>(V)) { + VR = CV; + return SubPattern.match(V); + } + return false; + } +}; + +template <typename T> +inline capture_ty<T, Instruction> m_Instruction(Instruction *&I, + const T &SubPattern) { + return capture_ty<T, Instruction>(SubPattern, I); +} + /// Match a specified Value*. struct specificval_ty { const Value *Val; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index c5e3ad8a55741fb..aca8611026ef1ca 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6380,53 +6380,71 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE) return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y); + // icmp eq/ne X, (zext/sext (icmp eq/ne X, C)) ICmpInst::Predicate Pred1, Pred2; const APInt *C; - // icmp eq/ne X, (zext (icmp eq/ne X, C)) + Instruction *ExtI; 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)) { + m_Instruction(ExtI, + m_ZExtOrSExt(m_ICmp(Pred2, m_Deferred(X), + m_APInt(C))))))) { + bool IsSExt = ExtI->getOpcode() == Instruction::SExt; + bool HasOneUse = ExtI->hasOneUse() && ExtI->getOperand(0)->hasOneUse(); 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 + // icmp eq X, (zext/sext (icmp eq X, 0)) --> false + // icmp ne X, (zext/sext (icmp eq X, 0)) --> true return replaceInstUsesWith( I, ConstantInt::getBool(I.getType(), Pred1 == ICmpInst::ICMP_NE)); - } else { + } else if (!IsSExt || HasOneUse) { // icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2 // icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1 + // icmp eq X, (sext (icmp ne X, 0)) --> icmp ult (X + 1), 2 + // icmp ne X, (sext (icmp ne X, 0)) --> icmp ugt (X + 1), 1 return ICmpInst::Create( Instruction::ICmp, Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT : ICmpInst::ICMP_ULT, - X, + IsSExt ? Builder.CreateAdd(X, ConstantInt::get(X->getType(), 1)) + : X, ConstantInt::get(X->getType(), Pred1 == ICmpInst::ICMP_NE ? 1 : 2)); } - } else if (C->isOne()) { + } else if (IsSExt ? C->isAllOnes() : 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 + // icmp eq X, (sext (icmp ne X, -1)) --> false + // icmp ne X, (sext (icmp ne X, -1)) --> true return replaceInstUsesWith( I, ConstantInt::getBool(I.getType(), Pred1 == ICmpInst::ICMP_NE)); - } else { + } else if (!IsSExt || HasOneUse) { // icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2 // icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1 + // icmp eq X, (sext (icmp eq X, -1)) --> icmp ult (X + 1), 2 + // icmp ne X, (sext (icmp eq X, -1)) --> icmp ugt (X + 1), 1 return ICmpInst::Create( Instruction::ICmp, Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT : ICmpInst::ICMP_ULT, - X, + IsSExt ? Builder.CreateAdd(X, ConstantInt::get(X->getType(), 1)) + : X, ConstantInt::get(X->getType(), 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 + // when 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 + // when 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, - ConstantInt::get(X->getType(), Pred2 == ICmpInst::ICMP_NE ? 1 : 0)); + ConstantInt::get(X->getType(), + Pred2 == ICmpInst::ICMP_NE ? (IsSExt ? -1 : 1) : 0)); } } >From 418562d5dbd25167d3f9b2c61fb7265581ee99d4 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Tue, 19 Sep 2023 03:39:23 +0800 Subject: [PATCH 5/5] fixup! [InstCombine] Simplify the pattern `a ne/eq (zext (a ne/eq c))` --- llvm/include/llvm/IR/PatternMatch.h | 22 ----- .../InstCombine/InstCombineCompares.cpp | 6 +- .../Transforms/InstCombine/and-or-icmps.ll | 17 +--- .../test/Transforms/InstCombine/icmp-range.ll | 82 ++++++------------- 4 files changed, 31 insertions(+), 96 deletions(-) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 38d40d1ec9a839e..13877538f79de6d 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -767,28 +767,6 @@ m_ImmConstant(Constant *&C) { return m_CombineAnd(m_Constant(C), m_Unless(m_ConstantExpr())); } -/// Match a pattern, capturing the value if we match. -template <typename SubPattern_t, typename Class> struct capture_ty { - SubPattern_t SubPattern; - Class *&VR; - - capture_ty(const SubPattern_t &SP, Class *&V) : SubPattern(SP), VR(V) {} - - template <typename ITy> bool match(ITy *V) { - if (auto *CV = dyn_cast<Class>(V)) { - VR = CV; - return SubPattern.match(V); - } - return false; - } -}; - -template <typename T> -inline capture_ty<T, Instruction> m_Instruction(Instruction *&I, - const T &SubPattern) { - return capture_ty<T, Instruction>(SubPattern, I); -} - /// Match a specified Value*. struct specificval_ty { const Value *Val; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index aca8611026ef1ca..b72bde885de124b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6385,9 +6385,9 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { const APInt *C; Instruction *ExtI; if (match(&I, m_c_ICmp(Pred1, m_Value(X), - m_Instruction(ExtI, - m_ZExtOrSExt(m_ICmp(Pred2, m_Deferred(X), - m_APInt(C))))))) { + m_CombineAnd(m_Instruction(ExtI), + m_ZExtOrSExt(m_ICmp(Pred2, m_Deferred(X), + m_APInt(C))))))) { bool IsSExt = ExtI->getOpcode() == Instruction::SExt; bool HasOneUse = ExtI->hasOneUse() && ExtI->getOperand(0)->hasOneUse(); if (C->isZero()) { diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll index 065dbf261e131bf..2c887d574d397f6 100644 --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -366,19 +366,10 @@ define void @simplify_before_foldAndOfICmps(ptr %p) { ; CHECK-LABEL: @simplify_before_foldAndOfICmps( ; CHECK-NEXT: [[A8:%.*]] = alloca i16, align 2 ; CHECK-NEXT: [[L7:%.*]] = load i16, ptr [[A8]], align 2 -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[L7]], -1 -; CHECK-NEXT: [[B11:%.*]] = zext i1 [[TMP1]] to i16 -; CHECK-NEXT: [[C10:%.*]] = icmp ugt i16 [[L7]], [[B11]] -; CHECK-NEXT: [[C5:%.*]] = icmp slt i16 [[L7]], 1 -; CHECK-NEXT: [[C7:%.*]] = icmp slt i16 [[L7]], 0 -; CHECK-NEXT: [[B15:%.*]] = xor i1 [[C7]], [[C10]] -; CHECK-NEXT: [[C6:%.*]] = xor i1 [[B15]], true -; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[C5]], [[C6]] -; CHECK-NEXT: [[C3:%.*]] = and i1 [[TMP2]], [[C10]] -; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[C10]], true -; CHECK-NEXT: [[C18:%.*]] = or i1 [[C7]], [[TMP3]] -; CHECK-NEXT: [[TMP4:%.*]] = sext i1 [[C3]] to i64 -; CHECK-NEXT: [[G26:%.*]] = getelementptr i1, ptr null, i64 [[TMP4]] +; CHECK-NEXT: [[C18:%.*]] = icmp slt i16 [[L7]], 1 +; CHECK-NEXT: [[L7_LOBIT:%.*]] = ashr i16 [[L7]], 15 +; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[L7_LOBIT]] to i64 +; CHECK-NEXT: [[G26:%.*]] = getelementptr i1, ptr null, i64 [[TMP1]] ; CHECK-NEXT: store i16 [[L7]], ptr [[P:%.*]], align 2 ; CHECK-NEXT: store i1 [[C18]], ptr [[P]], align 1 ; CHECK-NEXT: store ptr [[G26]], ptr [[P]], align 8 diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll index f7efff9f675373a..3a40755384f2a21 100644 --- a/llvm/test/Transforms/InstCombine/icmp-range.ll +++ b/llvm/test/Transforms/InstCombine/icmp-range.ll @@ -1164,7 +1164,7 @@ define i1 @icmp_eq_zext_ne_non_boolean(i32 %a) { } define <2 x i1> @icmp_ne_zext_eq_zero_vec(<2 x i32> %a) { -; CHECK-LABEL: @icmp_ne_zext_eq_zero_vec +; 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> @@ -1218,10 +1218,7 @@ define <2 x i1> @icmp_ne_zext_eq_non_boolean_vec(<2 x i32> %a) { define i1 @icmp_ne_sext_eq_zero(i32 %a) { ; CHECK-LABEL: @icmp_ne_sext_eq_zero( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[CONV]], [[A]] -; CHECK-NEXT: ret i1 [[CMP1]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp eq i32 %a, 0 %conv = sext i1 %cmp to i32 @@ -1231,9 +1228,8 @@ define i1 @icmp_ne_sext_eq_zero(i32 %a) { define i1 @icmp_ne_sext_ne_zero(i32 %a) { ; CHECK-LABEL: @icmp_ne_sext_ne_zero( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], 0 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[CONV]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A:%.*]], -1 +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[TMP1]], -2 ; CHECK-NEXT: ret i1 [[CMP1]] ; %cmp = icmp ne i32 %a, 0 @@ -1244,10 +1240,7 @@ define i1 @icmp_ne_sext_ne_zero(i32 %a) { define i1 @icmp_eq_sext_eq_zero(i32 %a) { ; CHECK-LABEL: @icmp_eq_sext_eq_zero( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 0 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[CONV]], [[A]] -; CHECK-NEXT: ret i1 [[CMP1]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp eq i32 %a, 0 %conv = sext i1 %cmp to i32 @@ -1257,9 +1250,8 @@ define i1 @icmp_eq_sext_eq_zero(i32 %a) { define i1 @icmp_eq_sext_ne_zero(i32 %a) { ; CHECK-LABEL: @icmp_eq_sext_ne_zero( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], 0 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[CONV]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A:%.*]], 1 +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[TMP1]], 2 ; CHECK-NEXT: ret i1 [[CMP1]] ; %cmp = icmp ne i32 %a, 0 @@ -1270,9 +1262,8 @@ define i1 @icmp_eq_sext_ne_zero(i32 %a) { define i1 @icmp_ne_sext_eq_allones(i32 %a) { ; CHECK-LABEL: @icmp_ne_sext_eq_allones( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], -1 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[CONV]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A:%.*]], -1 +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[TMP1]], -2 ; CHECK-NEXT: ret i1 [[CMP1]] ; %cmp = icmp eq i32 %a, -1 @@ -1283,10 +1274,7 @@ define i1 @icmp_ne_sext_eq_allones(i32 %a) { define i1 @icmp_ne_sext_ne_allones(i32 %a) { ; CHECK-LABEL: @icmp_ne_sext_ne_allones( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], -1 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[CONV]], [[A]] -; CHECK-NEXT: ret i1 [[CMP1]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp ne i32 %a, -1 %conv = sext i1 %cmp to i32 @@ -1296,9 +1284,8 @@ define i1 @icmp_ne_sext_ne_allones(i32 %a) { define i1 @icmp_eq_sext_eq_allones(i32 %a) { ; CHECK-LABEL: @icmp_eq_sext_eq_allones( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], -1 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[CONV]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A:%.*]], 1 +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[TMP1]], 2 ; CHECK-NEXT: ret i1 [[CMP1]] ; %cmp = icmp eq i32 %a, -1 @@ -1309,10 +1296,7 @@ define i1 @icmp_eq_sext_eq_allones(i32 %a) { define i1 @icmp_eq_sext_ne_allones(i32 %a) { ; CHECK-LABEL: @icmp_eq_sext_ne_allones( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], -1 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[CONV]], [[A]] -; CHECK-NEXT: ret i1 [[CMP1]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp ne i32 %a, -1 %conv = sext i1 %cmp to i32 @@ -1322,9 +1306,7 @@ define i1 @icmp_eq_sext_ne_allones(i32 %a) { define i1 @icmp_ne_sext_eq_otherwise(i32 %a) { ; CHECK-LABEL: @icmp_ne_sext_eq_otherwise( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 2 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[CONV]], [[A]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 0 ; CHECK-NEXT: ret i1 [[CMP1]] ; %cmp = icmp eq i32 %a, 2 @@ -1335,9 +1317,7 @@ define i1 @icmp_ne_sext_eq_otherwise(i32 %a) { define i1 @icmp_ne_sext_ne_otherwise(i32 %a) { ; CHECK-LABEL: @icmp_ne_sext_ne_otherwise( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], 2 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[CONV]], [[A]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], -1 ; CHECK-NEXT: ret i1 [[CMP1]] ; %cmp = icmp ne i32 %a, 2 @@ -1348,9 +1328,7 @@ define i1 @icmp_ne_sext_ne_otherwise(i32 %a) { define i1 @icmp_eq_sext_eq_otherwise(i32 %a) { ; CHECK-LABEL: @icmp_eq_sext_eq_otherwise( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 2 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[CONV]], [[A]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 ; CHECK-NEXT: ret i1 [[CMP1]] ; %cmp = icmp eq i32 %a, 2 @@ -1361,9 +1339,7 @@ define i1 @icmp_eq_sext_eq_otherwise(i32 %a) { define i1 @icmp_eq_sext_ne_otherwise(i32 %a) { ; CHECK-LABEL: @icmp_eq_sext_ne_otherwise( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], 2 -; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[CONV]], [[A]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], -1 ; CHECK-NEXT: ret i1 [[CMP1]] ; %cmp = icmp ne i32 %a, 2 @@ -1374,10 +1350,7 @@ define i1 @icmp_eq_sext_ne_otherwise(i32 %a) { define <2 x i1> @icmp_ne_sext_eq_zero_vec(<2 x i32> %a) { ; CHECK-LABEL: @icmp_ne_sext_eq_zero_vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], zeroinitializer -; CHECK-NEXT: [[CONV:%.*]] = sext <2 x i1> [[CMP]] to <2 x i32> -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[CONV]], [[A]] -; CHECK-NEXT: ret <2 x i1> [[CMP1]] +; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true> ; %cmp = icmp eq <2 x i32> %a, <i32 0, i32 0> %conv = sext <2 x i1> %cmp to <2 x i32> @@ -1387,9 +1360,8 @@ define <2 x i1> @icmp_ne_sext_eq_zero_vec(<2 x i32> %a) { define <2 x i1> @icmp_ne_sext_ne_zero_vec(<2 x i32> %a) { ; CHECK-LABEL: @icmp_ne_sext_ne_zero_vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[A:%.*]], zeroinitializer -; CHECK-NEXT: [[CONV:%.*]] = sext <2 x i1> [[CMP]] to <2 x i32> -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[CONV]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[A:%.*]], <i32 -1, i32 -1> +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 -2, i32 -2> ; CHECK-NEXT: ret <2 x i1> [[CMP1]] ; %cmp = icmp ne <2 x i32> %a, <i32 0, i32 0> @@ -1400,9 +1372,8 @@ define <2 x i1> @icmp_ne_sext_ne_zero_vec(<2 x i32> %a) { define <2 x i1> @icmp_ne_sext_eq_allones_vec(<2 x i32> %a) { ; CHECK-LABEL: @icmp_ne_sext_eq_allones_vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 -1, i32 -1> -; CHECK-NEXT: [[CONV:%.*]] = sext <2 x i1> [[CMP]] to <2 x i32> -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[CONV]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[A:%.*]], <i32 -1, i32 -1> +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 -2, i32 -2> ; CHECK-NEXT: ret <2 x i1> [[CMP1]] ; %cmp = icmp eq <2 x i32> %a, <i32 -1, i32 -1> @@ -1413,10 +1384,7 @@ define <2 x i1> @icmp_ne_sext_eq_allones_vec(<2 x i32> %a) { define <2 x i1> @icmp_ne_sext_ne_allones_vec(<2 x i32> %a) { ; CHECK-LABEL: @icmp_ne_sext_ne_allones_vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[A:%.*]], <i32 -1, i32 -1> -; CHECK-NEXT: [[CONV:%.*]] = sext <2 x i1> [[CMP]] to <2 x i32> -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[CONV]], [[A]] -; CHECK-NEXT: ret <2 x i1> [[CMP1]] +; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true> ; %cmp = icmp ne <2 x i32> %a, <i32 -1, i32 -1> %conv = sext <2 x i1> %cmp to <2 x i32> @@ -1426,9 +1394,7 @@ define <2 x i1> @icmp_ne_sext_ne_allones_vec(<2 x i32> %a) { define <2 x i1> @icmp_ne_sext_eq_otherwise_vec(<2 x i32> %a) { ; CHECK-LABEL: @icmp_ne_sext_eq_otherwise_vec( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 2, i32 2> -; CHECK-NEXT: [[CONV:%.*]] = sext <2 x i1> [[CMP]] to <2 x i32> -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[CONV]], [[A]] +; 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> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits