[llvm] [InstCombine] Missed optimization for select a%2==0, (a/2*2)*(a/2*2), 0 (PR #92658)
Jorge Botto via llvm-commits
llvm-commits at lists.llvm.org
Sun May 19 03:10:47 PDT 2024
https://github.com/jf-botto updated https://github.com/llvm/llvm-project/pull/92658
>From 056ad41d49e6e2f8c85aca5b1576acf35801e176 Mon Sep 17 00:00:00 2001
From: Jorge Botto <jorge.botto.16 at ucl.ac.uk>
Date: Fri, 17 May 2024 18:53:07 +0100
Subject: [PATCH 1/2] Initial tests precommit
---
llvm/test/Transforms/InstCombine/select.ll | 58 ++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 2ade6faa99be3..df3352fe247f8 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -1456,6 +1456,64 @@ define <2 x i32> @select_icmp_slt0_xor_vec(<2 x i32> %x) {
ret <2 x i32> %x.xor
}
+define i8 @select_icmp_eq_mul_and(i8 noundef %a, i8 %b) {
+; CHECK-LABEL: @select_icmp_eq_mul_and(
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[A:%.*]], 1
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1]], 0
+; CHECK-NEXT: [[DIV7:%.*]] = and i8 [[A]], -2
+; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[DIV7]], [[DIV7]]
+; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], i8 [[MUL]], i8 [[B:%.*]]
+; CHECK-NEXT: ret i8 [[RETVAL_0]]
+;
+ %1 = and i8 %a, 1
+ %cmp = icmp eq i8 %1, 0
+ %div7 = and i8 %a, -2
+ %mul = mul i8 %div7, %div7
+ %retval.0 = select i1 %cmp, i8 %mul, i8 %b
+ ret i8 %retval.0
+}
+
+define i8 @select_icmp_eq_and(i8 noundef %a, i8 %b) {
+; CHECK-LABEL: @select_icmp_eq_and(
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[A:%.*]], 1
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1]], 0
+; CHECK-NEXT: [[DIV7:%.*]] = and i8 [[A]], -2
+; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], i8 [[DIV7]], i8 [[B:%.*]]
+; CHECK-NEXT: ret i8 [[RETVAL_0]]
+;
+ %1 = and i8 %a, 1
+ %cmp = icmp eq i8 %1, 0
+ %div7 = and i8 %a, -2
+ %retval.0 = select i1 %cmp, i8 %div7, i8 %b
+ ret i8 %retval.0
+}
+
+;negative test
+define i8 @select_and(i8 noundef %a, i8 %b, i1 %cmp) {
+; CHECK-LABEL: @select_and(
+; CHECK-NEXT: [[DIV7:%.*]] = and i8 [[A:%.*]], -2
+; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP:%.*]], i8 [[DIV7]], i8 [[B:%.*]]
+; CHECK-NEXT: ret i8 [[RETVAL_0]]
+;
+ %div7 = and i8 %a, -2
+ %retval.0 = select i1 %cmp, i8 %div7, i8 %b
+ ret i8 %retval.0
+}
+
+;negative test
+define i8 @select_mul_and(i8 noundef %a, i8 %b, i1 %cmp) {
+; CHECK-LABEL: @select_mul_and(
+; CHECK-NEXT: [[DIV7:%.*]] = and i8 [[A:%.*]], -2
+; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[DIV7]], [[DIV7]]
+; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP:%.*]], i8 [[MUL]], i8 [[B:%.*]]
+; CHECK-NEXT: ret i8 [[RETVAL_0]]
+;
+ %div7 = and i8 %a, -2
+ %mul = mul i8 %div7, %div7
+ %retval.0 = select i1 %cmp, i8 %mul, i8 %b
+ ret i8 %retval.0
+}
+
define <4 x i32> @canonicalize_to_shuffle(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: @canonicalize_to_shuffle(
; CHECK-NEXT: [[SEL:%.*]] = shufflevector <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 3>
>From 70553da774536c15f120cacf92e8a67e14082971 Mon Sep 17 00:00:00 2001
From: Jorge Botto <jorge.botto.16 at ucl.ac.uk>
Date: Sun, 19 May 2024 11:10:12 +0100
Subject: [PATCH 2/2] Adding missed optimisation
---
.../InstCombine/InstCombineSelect.cpp | 38 +++++++++++++++++++
llvm/test/Transforms/InstCombine/select.ll | 8 ++--
2 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index a3ddb402bf662..51dc8c7bdc800 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1073,6 +1073,40 @@ static Value *foldAbsDiff(ICmpInst *Cmp, Value *TVal, Value *FVal,
return nullptr;
}
+// (A % 2 == 0) ? (A/2*2) : B --> (A % 2 == 0) ? A : B
+// (A % 2 == 0) ? (A/2*2) * (A/2*2) : B --> (A % 2 == 0) ? BinOp A, A : B
+static Value *foldSelectWithIcmpEqAndPattern(ICmpInst *Cmp, Value *TVal,
+ Value *FVal,
+ InstCombiner::BuilderTy &Builder) {
+ Value *A;
+ ConstantInt *MaskedConstant;
+ ICmpInst::Predicate Pred = Cmp->getPredicate();
+
+ // Checks if the comparison is (A % 2 == 0) and A is not undef.
+ if (!(Pred == ICmpInst::ICMP_EQ &&
+ match(Cmp->getOperand(0), m_And(m_Value(A), m_SpecificInt(1))) &&
+ match(Cmp->getOperand(1), m_SpecificInt(0)) &&
+ isGuaranteedNotToBeUndef(A)))
+ return nullptr;
+
+ // Checks if true branch matches (A % 2).
+ if (match(TVal,
+ m_OneUse(m_And(m_Specific(A), m_ConstantInt(MaskedConstant)))) &&
+ MaskedConstant->getValue().getSExtValue() == -2)
+ return Builder.CreateSelect(Cmp, A, FVal);
+
+ // Checks if true branch is (A/2*2) * (A/2*2).
+ Value *MulVal;
+ if (match(TVal, m_OneUse(m_Mul(m_Value(MulVal), m_Deferred(MulVal)))))
+ if (match(MulVal, m_And(m_Specific(A), m_ConstantInt(MaskedConstant))) &&
+ MaskedConstant->getValue().getSExtValue() == -2) {
+ Value *NewBinop = Builder.CreateMul(A, A);
+ return Builder.CreateSelect(Cmp, NewBinop, FVal);
+ }
+
+ return nullptr;
+}
+
/// Fold the following code sequence:
/// \code
/// int a = ctlz(x & -x);
@@ -1933,6 +1967,10 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
if (Value *V = foldAbsDiff(ICI, TrueVal, FalseVal, Builder))
return replaceInstUsesWith(SI, V);
+ if (Value *V =
+ foldSelectWithIcmpEqAndPattern(ICI, TrueVal, FalseVal, Builder))
+ return replaceInstUsesWith(SI, V);
+
return Changed ? &SI : nullptr;
}
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index df3352fe247f8..759b0b14ae4d5 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -1460,9 +1460,8 @@ define i8 @select_icmp_eq_mul_and(i8 noundef %a, i8 %b) {
; CHECK-LABEL: @select_icmp_eq_mul_and(
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[A:%.*]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1]], 0
-; CHECK-NEXT: [[DIV7:%.*]] = and i8 [[A]], -2
-; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[DIV7]], [[DIV7]]
-; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], i8 [[MUL]], i8 [[B:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = mul i8 [[A]], [[A]]
+; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], i8 [[TMP2]], i8 [[B:%.*]]
; CHECK-NEXT: ret i8 [[RETVAL_0]]
;
%1 = and i8 %a, 1
@@ -1477,8 +1476,7 @@ define i8 @select_icmp_eq_and(i8 noundef %a, i8 %b) {
; CHECK-LABEL: @select_icmp_eq_and(
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[A:%.*]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1]], 0
-; CHECK-NEXT: [[DIV7:%.*]] = and i8 [[A]], -2
-; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], i8 [[DIV7]], i8 [[B:%.*]]
+; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[CMP]], i8 [[A]], i8 [[B:%.*]]
; CHECK-NEXT: ret i8 [[RETVAL_0]]
;
%1 = and i8 %a, 1
More information about the llvm-commits
mailing list