[llvm] [InstCombine] Fold selection between less than zero and one (PR #69961)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 31 05:02:52 PST 2024


https://github.com/elhewaty updated https://github.com/llvm/llvm-project/pull/69961

>From dd694fde3767c4900732b848b818f4cce6bddfab Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Mon, 23 Oct 2023 21:37:47 +0300
Subject: [PATCH 1/2] [InstCombine] Add test coverage for (A Pred C) ? (A >> BW
 - 1) : 1 (NFC)

---
 .../Transforms/InstCombine/icmp-select.ll     | 67 +++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/icmp-select.ll b/llvm/test/Transforms/InstCombine/icmp-select.ll
index 0d723c9df32e2..d7bdf336c122a 100644
--- a/llvm/test/Transforms/InstCombine/icmp-select.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-select.ll
@@ -5,6 +5,73 @@ declare void @use(i8)
 declare void @use.i1(i1)
 declare i8 @llvm.umin.i8(i8, i8)
 
+define i32 @test_icmp_select_lte(i32 %x) {
+; CHECK-LABEL: @test_icmp_select_lte(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1234
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[X]], 31
+; CHECK-NEXT:    [[RE:%.*]] = select i1 [[CMP]], i32 [[LSHR]], i32 1
+; CHECK-NEXT:    ret i32 [[RE]]
+;
+  %cmp = icmp slt i32 %x, 1234
+  %lshr = lshr i32 %x, 31
+  %re = select i1 %cmp, i32 %lshr, i32 1
+  ret i32 %re
+}
+
+define i16 @test_icmp_select_sgt(i16 %x) {
+; CHECK-LABEL: @test_icmp_select_sgt(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i16 [[X:%.*]], 123
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i16 [[X]], 15
+; CHECK-NEXT:    [[RE:%.*]] = select i1 [[CMP]], i16 [[LSHR]], i16 1
+; CHECK-NEXT:    ret i16 [[RE]]
+;
+  %cmp = icmp sgt i16 %x, 123
+  %lshr = lshr i16 %x, 15
+  %re = select i1 %cmp, i16 %lshr, i16 1
+  ret i16 %re
+}
+
+define i8 @test_icmp_select_ugt(i8 %x) {
+; CHECK-LABEL: @test_icmp_select_ugt(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 10
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X]], 7
+; CHECK-NEXT:    [[RE:%.*]] = select i1 [[CMP]], i8 [[LSHR]], i8 1
+; CHECK-NEXT:    ret i8 [[RE]]
+;
+  %cmp = icmp ugt i8 %x, 10
+  %lshr = lshr i8 %x, 7
+  %re = select i1 %cmp, i8 %lshr, i8 1
+  ret i8 %re
+}
+
+define <2 x i32> @test_icmp_select_sge_vector(<2 x i32> %x) {
+; CHECK-LABEL: @test_icmp_select_sge_vector(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i32> [[X:%.*]], <i32 511, i32 511>
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr <2 x i32> [[X]], <i32 31, i32 31>
+; CHECK-NEXT:    [[RE:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[LSHR]], <2 x i32> <i32 1, i32 1>
+; CHECK-NEXT:    ret <2 x i32> [[RE]]
+;
+  %cmp = icmp sge <2 x i32> %x, <i32 512, i32 512>
+  %lshr = lshr <2 x i32> %x, <i32 31, i32 31>
+  %re = select <2 x i1> %cmp, <2 x i32> %lshr, <2 x i32> <i32 1, i32 1>
+  ret <2 x i32> %re;
+}
+
+define i8 @test_with_more_than_one_use(i8 %x) {
+; CHECK-LABEL: @test_with_more_than_one_use(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], 9
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X]], 7
+; CHECK-NEXT:    [[RE:%.*]] = select i1 [[CMP]], i8 [[LSHR]], i8 1
+; CHECK-NEXT:    call void @use(i8 [[LSHR]])
+; CHECK-NEXT:    ret i8 [[RE]]
+;
+  %cmp = icmp sge i8 %x, 10
+  %lshr = lshr i8 %x, 7
+  %re = select i1 %cmp, i8 %lshr, i8 1
+  call void @use(i8 %lshr)
+  ret i8 %re
+}
+
 define i1 @icmp_select_const(i8 %x, i8 %y) {
 ; CHECK-LABEL: @icmp_select_const(
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0

>From 146d548e068e694197d468d5f4b3ce3603db9d76 Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Tue, 30 Jan 2024 22:40:45 +0200
Subject: [PATCH 2/2] [InstCombine] Fold A pred C ? (A >> BW - 1) : 1 -->
 ZExt(A pred C ? A < 0 : 1)

---
 .../InstCombine/InstCombineSelect.cpp         | 19 ++++++++++++++++++
 .../Transforms/InstCombine/icmp-select.ll     | 20 ++++++++-----------
 2 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 453e4d788705f..9314d8ba4123b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3409,6 +3409,25 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
       return replaceOperand(SI, 2, S);
   }
 
+  {
+    // A pred C ? (A >> BW - 1) : 1 --> ZExt(A pred C ? A < 0 : 1)
+    CmpInst::Predicate Pred;
+    Value *A;
+    const APInt *C;
+    if (match(CondVal, m_ICmp(Pred, m_Value(A), m_APInt(C))) &&
+        match(TrueVal,
+              m_LShr(m_Specific(A),
+                     m_SpecificInt(A->getType()->getScalarSizeInBits() - 1))) &&
+        match(FalseVal, m_One()) && TrueVal->hasOneUse()) {
+      auto *NewTrue =
+          Builder.CreateICmpSLT(A, ConstantInt::getNullValue(A->getType()));
+      auto *NewFalse = ConstantInt::get(NewTrue->getType(), 1);
+      auto *NewSelect = Builder.CreateSelect(CondVal, NewTrue, NewFalse);
+      auto *ZExt = Builder.CreateZExt(NewSelect, A->getType());
+      return replaceInstUsesWith(SI, ZExt);
+    }
+  }
+
   if (Instruction *R = foldSelectOfBools(SI))
     return R;
 
diff --git a/llvm/test/Transforms/InstCombine/icmp-select.ll b/llvm/test/Transforms/InstCombine/icmp-select.ll
index d7bdf336c122a..551f696dcf8b6 100644
--- a/llvm/test/Transforms/InstCombine/icmp-select.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-select.ll
@@ -7,9 +7,8 @@ declare i8 @llvm.umin.i8(i8, i8)
 
 define i32 @test_icmp_select_lte(i32 %x) {
 ; CHECK-LABEL: @test_icmp_select_lte(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 1234
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[X]], 31
-; CHECK-NEXT:    [[RE:%.*]] = select i1 [[CMP]], i32 [[LSHR]], i32 1
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[X:%.*]], 1233
+; CHECK-NEXT:    [[RE:%.*]] = zext i1 [[TMP1]] to i32
 ; CHECK-NEXT:    ret i32 [[RE]]
 ;
   %cmp = icmp slt i32 %x, 1234
@@ -20,9 +19,8 @@ define i32 @test_icmp_select_lte(i32 %x) {
 
 define i16 @test_icmp_select_sgt(i16 %x) {
 ; CHECK-LABEL: @test_icmp_select_sgt(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i16 [[X:%.*]], 123
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i16 [[X]], 15
-; CHECK-NEXT:    [[RE:%.*]] = select i1 [[CMP]], i16 [[LSHR]], i16 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i16 [[X:%.*]], 124
+; CHECK-NEXT:    [[RE:%.*]] = zext i1 [[CMP]] to i16
 ; CHECK-NEXT:    ret i16 [[RE]]
 ;
   %cmp = icmp sgt i16 %x, 123
@@ -33,9 +31,8 @@ define i16 @test_icmp_select_sgt(i16 %x) {
 
 define i8 @test_icmp_select_ugt(i8 %x) {
 ; CHECK-LABEL: @test_icmp_select_ugt(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 10
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i8 [[X]], 7
-; CHECK-NEXT:    [[RE:%.*]] = select i1 [[CMP]], i8 [[LSHR]], i8 1
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 11
+; CHECK-NEXT:    [[RE:%.*]] = zext i1 [[TMP1]] to i8
 ; CHECK-NEXT:    ret i8 [[RE]]
 ;
   %cmp = icmp ugt i8 %x, 10
@@ -46,9 +43,8 @@ define i8 @test_icmp_select_ugt(i8 %x) {
 
 define <2 x i32> @test_icmp_select_sge_vector(<2 x i32> %x) {
 ; CHECK-LABEL: @test_icmp_select_sge_vector(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i32> [[X:%.*]], <i32 511, i32 511>
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr <2 x i32> [[X]], <i32 31, i32 31>
-; CHECK-NEXT:    [[RE:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[LSHR]], <2 x i32> <i32 1, i32 1>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i32> [[X:%.*]], <i32 512, i32 512>
+; CHECK-NEXT:    [[RE:%.*]] = zext <2 x i1> [[CMP]] to <2 x i32>
 ; CHECK-NEXT:    ret <2 x i32> [[RE]]
 ;
   %cmp = icmp sge <2 x i32> %x, <i32 512, i32 512>



More information about the llvm-commits mailing list