[llvm] [InstCombine] disable select folding resulting in extra instructions (PR #97184)

Alex MacLean via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 29 18:06:02 PDT 2024


https://github.com/AlexMaclean created https://github.com/llvm/llvm-project/pull/97184

Disable conversion of a `(select (icmp))` when it would result in more instructions `(xor (lshr (and)))`. This transformation produces more instructions and can interfere with other more profitable folds for `select`.  For example before this change the following folding would occur:
```llvm
  %1 = icmp slt i32 %X, 0
  %2 = select i1 %1, i64 0, i64 8
```
to 
```llvm
  %1 = lshr i32 %X, 28
  %2 = and i32 %1, 8
  %3 = xor i32 %2, 8
  %4 = zext nneg i32 %3 to i64
```

>From 181b19186d9f4707f7ab6db94c55411e9c2062b4 Mon Sep 17 00:00:00 2001
From: Alex MacLean <amaclean at nvidia.com>
Date: Wed, 26 Jun 2024 18:27:16 +0000
Subject: [PATCH] [InstCombine] disable select folding resulting in extra
 instructions

---
 llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 10 ++++++++--
 llvm/test/Transforms/InstCombine/select-icmp-and.ll   | 11 +++++++++++
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index aff691b000413..db52684e174a4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -202,6 +202,14 @@ static Value *foldSelectICmpAnd(SelectInst &Sel, ICmpInst *Cmp,
   const APInt &ValC = !TC.isZero() ? TC : FC;
   unsigned ValZeros = ValC.logBase2();
   unsigned AndZeros = AndMask.logBase2();
+  bool ShouldNotVal = !TC.isZero();
+  ShouldNotVal ^= Pred == ICmpInst::ICMP_NE;
+
+  // If we would need to create an 'and' + 'shift' + 'xor' to replace a 'select'
+  // + 'icmp', then this transformation would result in more instructions and
+  // potentially interfere with other folding.
+  if (CreateAnd && ShouldNotVal && ValZeros != AndZeros)
+    return nullptr;
 
   // Insert the 'and' instruction on the input to the truncate.
   if (CreateAnd)
@@ -221,8 +229,6 @@ static Value *foldSelectICmpAnd(SelectInst &Sel, ICmpInst *Cmp,
 
   // Okay, now we know that everything is set up, we just don't know whether we
   // have a icmp_ne or icmp_eq and whether the true or false val is the zero.
-  bool ShouldNotVal = !TC.isZero();
-  ShouldNotVal ^= Pred == ICmpInst::ICMP_NE;
   if (ShouldNotVal)
     V = Builder.CreateXor(V, ValC);
 
diff --git a/llvm/test/Transforms/InstCombine/select-icmp-and.ll b/llvm/test/Transforms/InstCombine/select-icmp-and.ll
index e1799d1091dac..8bedf699dc922 100644
--- a/llvm/test/Transforms/InstCombine/select-icmp-and.ll
+++ b/llvm/test/Transforms/InstCombine/select-icmp-and.ll
@@ -299,6 +299,17 @@ define <2 x i32> @test74vec(<2 x i32> %x) {
   ret <2 x i32> %2
 }
 
+define i64 @test75(i32 %X) {
+; CHECK-LABEL: @test75(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i64 0, i64 8
+; CHECK-NEXT:    ret i64 [[TMP2]]
+;
+  %1 = icmp slt i32 %X, 0
+  %2 = select i1 %1, i64 0, i64 8
+  ret i64 %2
+}
+
 ;; Code sequence for (X & 16) ? 16 : 0
 define i32 @test15a(i32 %X) {
 ; CHECK-LABEL: @test15a(



More information about the llvm-commits mailing list