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 01/10] [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 02/10] 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 03/10] 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 04/10] 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 05/10] 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> >From b7565ccc7090e15f6330da274225420691a4160d Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Tue, 19 Sep 2023 10:24:50 +0800 Subject: [PATCH 06/10] [InstCombine] Fix comments `zext` -> `sext`. NFC. --- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index b72bde885de124b..c7b9366bfd45e41 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6437,10 +6437,10 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { // 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 + // icmp eq X, (sext (icmp eq X, C)) --> icmp eq X, 0 + // icmp eq X, (sext (icmp ne X, C)) --> icmp eq X, -1 + // icmp ne X, (sext (icmp eq X, C)) --> icmp ne X, 0 + // icmp ne X, (sext (icmp ne X, C)) --> icmp ne X, -1 return ICmpInst::Create( Instruction::ICmp, Pred1, X, ConstantInt::get(X->getType(), >From 5b5052403968d4b394b30779c8912a1e732e9998 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Sun, 24 Sep 2023 17:59:26 +0800 Subject: [PATCH 07/10] fixup! [InstCombine] Simplify the pattern `a ne/eq (zext (a ne/eq c))` --- .../InstCombine/InstCombineCompares.cpp | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index c7b9366bfd45e41..7c7ab62c64dac89 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6390,6 +6390,13 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { m_APInt(C))))))) { bool IsSExt = ExtI->getOpcode() == Instruction::SExt; bool HasOneUse = ExtI->hasOneUse() && ExtI->getOperand(0)->hasOneUse(); + auto CreateRangeCheck = [&] { + Value *V1 = Constant::getNullValue(X->getType()); + Value *V2 = ConstantInt::get(X->getType(), IsSExt ? -1 : 1); + return BinaryOperator::Create( + Pred1 == ICmpInst::ICMP_EQ ? Instruction::Or : Instruction::And, + Builder.CreateICmp(Pred1, X, V1), Builder.CreateICmp(Pred1, X, V2)); + }; if (C->isZero()) { if (Pred2 == ICmpInst::ICMP_EQ) { // icmp eq X, (zext/sext (icmp eq X, 0)) --> false @@ -6397,17 +6404,11 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { return replaceInstUsesWith( I, ConstantInt::getBool(I.getType(), Pred1 == ICmpInst::ICMP_NE)); } 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, - IsSExt ? Builder.CreateAdd(X, ConstantInt::get(X->getType(), 1)) - : X, - ConstantInt::get(X->getType(), Pred1 == ICmpInst::ICMP_NE ? 1 : 2)); + // icmp eq X, (zext (icmp ne X, 0)) --> X == 0 || X == 1 + // icmp ne X, (zext (icmp ne X, 0)) --> X != 0 && X != 1 + // icmp eq X, (sext (icmp ne X, 0)) --> X == 0 || X == -1 + // icmp ne X, (sext (icmp ne X, 0)) --> X != 0 && X == -1 + return CreateRangeCheck(); } } else if (IsSExt ? C->isAllOnes() : C->isOne()) { if (Pred2 == ICmpInst::ICMP_NE) { @@ -6418,17 +6419,11 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { return replaceInstUsesWith( I, ConstantInt::getBool(I.getType(), Pred1 == ICmpInst::ICMP_NE)); } 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, - IsSExt ? Builder.CreateAdd(X, ConstantInt::get(X->getType(), 1)) - : X, - ConstantInt::get(X->getType(), Pred1 == ICmpInst::ICMP_NE ? 1 : 2)); + // icmp eq X, (zext (icmp eq X, 1)) --> X == 0 || X == 1 + // icmp ne X, (zext (icmp eq X, 1)) --> X != 0 && X != 1 + // icmp eq X, (sext (icmp eq X, -1)) --> X == 0 || X == -1 + // icmp ne X, (sext (icmp eq X, -1)) --> X != 0 && X == -1 + return CreateRangeCheck(); } } else { // when C != 0 && C != 1: >From 55d52b1f05004abe6c4187dc07437580c7f5aa73 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Sun, 24 Sep 2023 21:49:47 +0800 Subject: [PATCH 08/10] fixup! [InstCombine] Simplify the pattern `a ne/eq (zext (a ne/eq c))` --- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 7c7ab62c64dac89..9f2d0c8110f79e0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6391,11 +6391,13 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { bool IsSExt = ExtI->getOpcode() == Instruction::SExt; bool HasOneUse = ExtI->hasOneUse() && ExtI->getOperand(0)->hasOneUse(); auto CreateRangeCheck = [&] { - Value *V1 = Constant::getNullValue(X->getType()); - Value *V2 = ConstantInt::get(X->getType(), IsSExt ? -1 : 1); + Value *CmpV1 = + Builder.CreateICmp(Pred1, X, Constant::getNullValue(X->getType())); + Value *CmpV2 = Builder.CreateICmp( + Pred1, X, ConstantInt::get(X->getType(), IsSExt ? -1 : 1)); return BinaryOperator::Create( Pred1 == ICmpInst::ICMP_EQ ? Instruction::Or : Instruction::And, - Builder.CreateICmp(Pred1, X, V1), Builder.CreateICmp(Pred1, X, V2)); + CmpV1, CmpV2); }; if (C->isZero()) { if (Pred2 == ICmpInst::ICMP_EQ) { >From c0d8f8193fa1620db1f84379f2316fcf4b401e4c Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Sun, 1 Oct 2023 20:10:57 +0800 Subject: [PATCH 09/10] fixup! [InstCombine] Simplify the pattern `a ne/eq (zext (a ne/eq c))` --- .../InstCombine/InstCombineCompares.cpp | 10 ++++---- .../Transforms/InstCombine/and-or-icmps.ll | 17 ++++++++++---- .../test/Transforms/InstCombine/icmp-range.ll | 23 +++++++++++++++++++ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 9f2d0c8110f79e0..4fca8859dea7acc 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6387,14 +6387,15 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { if (match(&I, m_c_ICmp(Pred1, m_Value(X), m_CombineAnd(m_Instruction(ExtI), m_ZExtOrSExt(m_ICmp(Pred2, m_Deferred(X), - m_APInt(C))))))) { + m_APInt(C)))))) && + ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) { bool IsSExt = ExtI->getOpcode() == Instruction::SExt; bool HasOneUse = ExtI->hasOneUse() && ExtI->getOperand(0)->hasOneUse(); auto CreateRangeCheck = [&] { Value *CmpV1 = Builder.CreateICmp(Pred1, X, Constant::getNullValue(X->getType())); Value *CmpV2 = Builder.CreateICmp( - Pred1, X, ConstantInt::get(X->getType(), IsSExt ? -1 : 1)); + Pred1, X, ConstantInt::getSigned(X->getType(), IsSExt ? -1 : 1)); return BinaryOperator::Create( Pred1 == ICmpInst::ICMP_EQ ? Instruction::Or : Instruction::And, CmpV1, CmpV2); @@ -6440,8 +6441,9 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) { // icmp ne X, (sext (icmp ne X, C)) --> icmp ne X, -1 return ICmpInst::Create( Instruction::ICmp, Pred1, X, - ConstantInt::get(X->getType(), - Pred2 == ICmpInst::ICMP_NE ? (IsSExt ? -1 : 1) : 0)); + ConstantInt::getSigned(X->getType(), Pred2 == ICmpInst::ICMP_NE + ? (IsSExt ? -1 : 1) + : 0)); } } diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll index 2c887d574d397f6..065dbf261e131bf 100644 --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -366,10 +366,19 @@ 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: [[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: [[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: 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 3a40755384f2a21..79790b7458d4219 100644 --- a/llvm/test/Transforms/InstCombine/icmp-range.ll +++ b/llvm/test/Transforms/InstCombine/icmp-range.ll @@ -1403,6 +1403,29 @@ define <2 x i1> @icmp_ne_sext_eq_otherwise_vec(<2 x i32> %a) { ret <2 x i1> %cmp1 } +define i1 @icmp_ne_sext_ne_zero_i128(i128 %a) { +; CHECK-LABEL: @icmp_ne_sext_ne_zero_i128( +; CHECK-NEXT: [[TMP1:%.*]] = add i128 [[A:%.*]], -1 +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i128 [[TMP1]], -2 +; CHECK-NEXT: ret i1 [[CMP1]] +; + %cmp = icmp ne i128 %a, 0 + %conv = sext i1 %cmp to i128 + %cmp1 = icmp ne i128 %conv, %a + ret i1 %cmp1 +} + +define i1 @icmp_ne_sext_ne_otherwise_i128(i128 %a) { +; CHECK-LABEL: @icmp_ne_sext_ne_otherwise_i128( +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i128 [[A:%.*]], -1 +; CHECK-NEXT: ret i1 [[CMP1]] +; + %cmp = icmp ne i128 %a, 2 + %conv = sext i1 %cmp to i128 + %cmp1 = icmp ne i128 %conv, %a + ret i1 %cmp1 +} + !0 = !{i32 1, i32 6} !1 = !{i32 0, i32 6} !2 = !{i8 0, i8 1} >From 2285a2c6b8e66cf35aed6151c61e841f1349817f Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Fri, 6 Oct 2023 17:17:53 +0800 Subject: [PATCH 10/10] fixup! [InstCombine] Simplify the pattern `a ne/eq (zext (a ne/eq c))` Add negative tests --- .../test/Transforms/InstCombine/icmp-range.ll | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll index 17903be937057ab..7af06e03fd4b2a9 100644 --- a/llvm/test/Transforms/InstCombine/icmp-range.ll +++ b/llvm/test/Transforms/InstCombine/icmp-range.ll @@ -1426,6 +1426,85 @@ define i1 @icmp_ne_sext_ne_otherwise_i128(i128 %a) { ret i1 %cmp1 } +; Negative tests with non-equality predicates +define i1 @icmp_ne_sext_sgt_zero_nofold(i32 %a) { +; CHECK-LABEL: @icmp_ne_sext_sgt_zero_nofold( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 0 +; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[CONV]], [[A]] +; CHECK-NEXT: ret i1 [[CMP1]] +; + %cmp = icmp sgt i32 %a, 0 + %conv = sext i1 %cmp to i32 + %cmp1 = icmp ne i32 %conv, %a + ret i1 %cmp1 +} + +define i1 @icmp_slt_sext_ne_zero_nofold(i32 %a) { +; CHECK-LABEL: @icmp_slt_sext_ne_zero_nofold( +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], 0 +; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[CONV]], [[A]] +; CHECK-NEXT: ret i1 [[CMP1]] +; + %cmp = icmp ne i32 %a, 0 + %conv = sext i1 %cmp to i32 + %cmp1 = icmp slt i32 %conv, %a + ret i1 %cmp1 +} + +define i1 @icmp_ne_sext_slt_allones_nofold(i32 %a) { +; CHECK-LABEL: @icmp_ne_sext_slt_allones_nofold( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], -1 +; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[CONV]], [[A]] +; CHECK-NEXT: ret i1 [[CMP1]] +; + %cmp = icmp slt i32 %a, -1 + %conv = sext i1 %cmp to i32 + %cmp1 = icmp ne i32 %conv, %a + ret i1 %cmp1 +} + +define i1 @icmp_slt_sext_ne_allones_nofold(i32 %a) { +; CHECK-LABEL: @icmp_slt_sext_ne_allones_nofold( +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], -1 +; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[CONV]], [[A]] +; CHECK-NEXT: ret i1 [[CMP1]] +; + %cmp = icmp ne i32 %a, -1 + %conv = sext i1 %cmp to i32 + %cmp1 = icmp slt i32 %conv, %a + ret i1 %cmp1 +} + +define i1 @icmp_ne_sext_slt_otherwise_nofold(i32 %a) { +; CHECK-LABEL: @icmp_ne_sext_slt_otherwise_nofold( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], 2 +; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[CONV]], [[A]] +; CHECK-NEXT: ret i1 [[CMP1]] +; + %cmp = icmp slt i32 %a, 2 + %conv = sext i1 %cmp to i32 + %cmp1 = icmp ne i32 %conv, %a + ret i1 %cmp1 +} + +define i1 @icmp_slt_sext_ne_otherwise_nofold(i32 %a) { +; CHECK-LABEL: @icmp_slt_sext_ne_otherwise_nofold( +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], 2 +; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[CMP]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[CONV]], [[A]] +; CHECK-NEXT: ret i1 [[CMP1]] +; + %cmp = icmp ne i32 %a, 2 + %conv = sext i1 %cmp to i32 + %cmp1 = icmp slt i32 %conv, %a + ret i1 %cmp1 +} + ; tests from PR59555 define i1 @isFloat(i64 %0) { ; CHECK-LABEL: @isFloat( _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits