[llvm] [SelectionDAG] Fold (icmp eq/ne (shift X, C), 0) -> (icmp eq/ne X, 0) (PR #88801)

Björn Pettersson via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 24 23:33:48 PDT 2024


https://github.com/bjope updated https://github.com/llvm/llvm-project/pull/88801

>From f603024d54df8b87428e9eb3ddb6b44856c28b5a Mon Sep 17 00:00:00 2001
From: Bjorn Pettersson <bjorn.a.pettersson at ericsson.com>
Date: Mon, 15 Apr 2024 23:51:35 +0200
Subject: [PATCH] [SelectionDAG] Fold (icmp eq/ne (shift X, C), 0) -> (icmp
 eq/ne X, 0)

Optimize
  (icmp eq/ne (shift X, C), 0) -> (icmp eq/ne X, 0)
We do this if all shifted out bits, as well as shifted in bits,
are known to be zero. And we also do it if all shifted out bits are
known to be equal to at least one bit that isn't shifted out.

Defensively limit this to one-use shifts (haven't really
considered if this can be profitable also when there are multiple
uses of the shift, but that is likely to depend on the target).
---
 .../CodeGen/SelectionDAG/TargetLowering.cpp   | 29 ++++++++++++++
 llvm/test/CodeGen/ARM/and-cmpz.ll             | 10 ++---
 .../CodeGen/ARM/simplifysetcc_narrow_load.ll  | 18 ++++-----
 llvm/test/CodeGen/Hexagon/isel-memory-vNi1.ll | 37 +++++++++---------
 .../CodeGen/PowerPC/opt-cmp-inst-cr0-live.ll  |  4 +-
 .../RISCV/lack-of-signed-truncation-check.ll  |  1 +
 llvm/test/CodeGen/RISCV/sextw-removal.ll      | 38 +++++++++++--------
 .../CodeGen/RISCV/signed-truncation-check.ll  |  1 +
 8 files changed, 86 insertions(+), 52 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index c938b3996be393c..15331276a6e63d4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -4516,6 +4516,35 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
         }
       }
     }
+
+    // Optimize
+    //    (setcc (shift N00, N01C), 0, eq/ne) -> (setcc N00, 0, eq/ne)
+    // If all shifted out bits are known to be zero, then the zero'd ness
+    // doesn't change and we can omit the shift.
+    // If all shifted out bits are equal to at least one bit that isn't
+    // shifted out, then the zero'd ness doesn't change and we can omit the
+    // shift.
+    if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && C1.isZero() &&
+        N0.hasOneUse() &&
+        (N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL ||
+         N0.getOpcode() == ISD::SRA)) {
+      bool IsRightShift = N0.getOpcode() != ISD::SHL;
+      SDValue N00 = N0.getOperand(0);
+      // Quick checks based on exact/nuw/nsw flags.
+      if (IsRightShift ? N0->getFlags().hasExact()
+                       : (N0->getFlags().hasNoUnsignedWrap() ||
+                          N0->getFlags().hasNoSignedWrap()))
+        return DAG.getSetCC(dl, VT, N00, N1, Cond);
+      // More expensive checks based on known bits.
+      if (const APInt *ShAmt = DAG.getValidMaximumShiftAmountConstant(N0)) {
+        KnownBits Known = DAG.computeKnownBits(N00);
+        if (IsRightShift)
+          Known = Known.reverseBits();
+        if (ShAmt->ule(Known.countMinLeadingZeros()) ||
+            ShAmt->ult(Known.countMinSignBits()))
+          return DAG.getSetCC(dl, VT, N00, N1, Cond);
+      }
+    }
   }
 
   // FIXME: Support vectors.
diff --git a/llvm/test/CodeGen/ARM/and-cmpz.ll b/llvm/test/CodeGen/ARM/and-cmpz.ll
index 1f72307f12a6825..ca01680792eff14 100644
--- a/llvm/test/CodeGen/ARM/and-cmpz.ll
+++ b/llvm/test/CodeGen/ARM/and-cmpz.ll
@@ -89,12 +89,12 @@ false:
 }
 
 ; CHECK-LABEL: i16_cmpz:
-; T1:      uxth    r0, r0
-; T1-NEXT: lsrs    r0, r0, #9
+; T1:      lsls    r0, r0, #16
+; T1-NEXT: lsrs    r0, r0, #25
 ; T1-NEXT: bne
-; T2:      uxth    r0, r0
-; T2-NEXT: movs    r2, #0
-; T2-NEXT: cmp.w   r2, r0, lsr #9
+; T2:      tst.w   r0, #65024
+; T2-NEXT: it
+; T2-NEXT: bxne
 define void @i16_cmpz(i16 %x, ptr %foo) {
 entry:
   %cmp = icmp ult i16 %x, 512
diff --git a/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll b/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll
index 838da59f9e412cc..bad99b5c7d976d8 100644
--- a/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll
+++ b/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll
@@ -311,7 +311,7 @@ define i1 @test_48_16_8(ptr %y) {
 ; CHECK-LE-LABEL: test_48_16_8:
 ; CHECK-LE:       @ %bb.0:
 ; CHECK-LE-NEXT:    ldrh r0, [r0, #1]
-; CHECK-LE-NEXT:    lsls r0, r0, #8
+; CHECK-LE-NEXT:    cmp r0, #0
 ; CHECK-LE-NEXT:    movne r0, #1
 ; CHECK-LE-NEXT:    mov pc, lr
 ;
@@ -559,28 +559,28 @@ define i1 @test_24_8_8(ptr %y) {
 ; CHECK-LE-LABEL: test_24_8_8:
 ; CHECK-LE:       @ %bb.0:
 ; CHECK-LE-NEXT:    ldrb r0, [r0, #1]
-; CHECK-LE-NEXT:    lsls r0, r0, #8
+; CHECK-LE-NEXT:    cmp r0, #0
 ; CHECK-LE-NEXT:    movne r0, #1
 ; CHECK-LE-NEXT:    mov pc, lr
 ;
 ; CHECK-V7-LE-LABEL: test_24_8_8:
 ; CHECK-V7-LE:       @ %bb.0:
 ; CHECK-V7-LE-NEXT:    ldrb r0, [r0, #1]
-; CHECK-V7-LE-NEXT:    lsls r0, r0, #8
+; CHECK-V7-LE-NEXT:    cmp r0, #0
 ; CHECK-V7-LE-NEXT:    movwne r0, #1
 ; CHECK-V7-LE-NEXT:    bx lr
 ;
 ; CHECK-BE-LABEL: test_24_8_8:
 ; CHECK-BE:       @ %bb.0:
 ; CHECK-BE-NEXT:    ldrb r0, [r0, #1]
-; CHECK-BE-NEXT:    lsls r0, r0, #8
+; CHECK-BE-NEXT:    cmp r0, #0
 ; CHECK-BE-NEXT:    movne r0, #1
 ; CHECK-BE-NEXT:    mov pc, lr
 ;
 ; CHECK-V7-BE-LABEL: test_24_8_8:
 ; CHECK-V7-BE:       @ %bb.0:
 ; CHECK-V7-BE-NEXT:    ldrb r0, [r0, #1]
-; CHECK-V7-BE-NEXT:    lsls r0, r0, #8
+; CHECK-V7-BE-NEXT:    cmp r0, #0
 ; CHECK-V7-BE-NEXT:    movwne r0, #1
 ; CHECK-V7-BE-NEXT:    bx lr
   %a = load i24, ptr %y
@@ -633,28 +633,28 @@ define i1 @test_24_8_16(ptr %y) {
 ; CHECK-LE-LABEL: test_24_8_16:
 ; CHECK-LE:       @ %bb.0:
 ; CHECK-LE-NEXT:    ldrb r0, [r0, #2]
-; CHECK-LE-NEXT:    lsls r0, r0, #16
+; CHECK-LE-NEXT:    cmp r0, #0
 ; CHECK-LE-NEXT:    movne r0, #1
 ; CHECK-LE-NEXT:    mov pc, lr
 ;
 ; CHECK-V7-LE-LABEL: test_24_8_16:
 ; CHECK-V7-LE:       @ %bb.0:
 ; CHECK-V7-LE-NEXT:    ldrb r0, [r0, #2]
-; CHECK-V7-LE-NEXT:    lsls r0, r0, #16
+; CHECK-V7-LE-NEXT:    cmp r0, #0
 ; CHECK-V7-LE-NEXT:    movwne r0, #1
 ; CHECK-V7-LE-NEXT:    bx lr
 ;
 ; CHECK-BE-LABEL: test_24_8_16:
 ; CHECK-BE:       @ %bb.0:
 ; CHECK-BE-NEXT:    ldrb r0, [r0]
-; CHECK-BE-NEXT:    lsls r0, r0, #16
+; CHECK-BE-NEXT:    cmp r0, #0
 ; CHECK-BE-NEXT:    movne r0, #1
 ; CHECK-BE-NEXT:    mov pc, lr
 ;
 ; CHECK-V7-BE-LABEL: test_24_8_16:
 ; CHECK-V7-BE:       @ %bb.0:
 ; CHECK-V7-BE-NEXT:    ldrb r0, [r0]
-; CHECK-V7-BE-NEXT:    lsls r0, r0, #16
+; CHECK-V7-BE-NEXT:    cmp r0, #0
 ; CHECK-V7-BE-NEXT:    movwne r0, #1
 ; CHECK-V7-BE-NEXT:    bx lr
   %a = load i24, ptr %y
diff --git a/llvm/test/CodeGen/Hexagon/isel-memory-vNi1.ll b/llvm/test/CodeGen/Hexagon/isel-memory-vNi1.ll
index 2eecfa9f47f176c..9df3289a3f589a6 100644
--- a/llvm/test/CodeGen/Hexagon/isel-memory-vNi1.ll
+++ b/llvm/test/CodeGen/Hexagon/isel-memory-vNi1.ll
@@ -173,64 +173,61 @@ define void @f6(ptr %a0, i16 %a1) #0 {
 ; CHECK-LABEL: f6:
 ; CHECK:       // %bb.0: // %b0
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     r2 = extractu(r1,#8,#8)
-; CHECK-NEXT:    }
-; CHECK-NEXT:    {
-; CHECK-NEXT:     r3 = #255
+; CHECK-NEXT:     r2 = #255
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     p1 = !bitsclr(r1,r3)
+; CHECK-NEXT:     r3 = ##65280
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     p0 = cmp.eq(r2,#0)
+; CHECK-NEXT:     p1 = !bitsclr(r1,r2)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     if (p0) r2 = #0
+; CHECK-NEXT:     p0 = !bitsclr(r1,r3)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
 ; CHECK-NEXT:     r1 = mux(p1,#8,#0)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     r3 = mux(p1,#2,#0)
+; CHECK-NEXT:     r2 = mux(p1,#2,#0)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     r5 = setbit(r1,#2)
+; CHECK-NEXT:     r3 = mux(p0,##128,#0)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     r6 = setbit(r3,#0)
+; CHECK-NEXT:     r4 = mux(p0,#32,#0)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     if (!p0) r2 = #128
+; CHECK-NEXT:     r5 = setbit(r1,#2)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     r4 = mux(p0,#0,#32)
+; CHECK-NEXT:     r6 = setbit(r2,#0)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
 ; CHECK-NEXT:     if (!p1) r5 = add(r1,#0)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     if (!p1) r6 = add(r3,#0)
+; CHECK-NEXT:     r1 = setbit(r3,#6)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     r1 = setbit(r2,#6)
+; CHECK-NEXT:     if (!p1) r6 = add(r2,#0)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     r3 = setbit(r4,#4)
+; CHECK-NEXT:     r2 = setbit(r4,#4)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     r5 = or(r6,r5)
+; CHECK-NEXT:     if (!p0) r2 = add(r4,#0)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     if (!p0) r2 = add(r1,#0)
+; CHECK-NEXT:     if (!p0) r1 = add(r3,#0)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     if (!p0) r4 = add(r3,#0)
+; CHECK-NEXT:     r4 = or(r6,r5)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     r5 |= or(r4,r2)
+; CHECK-NEXT:     r4 |= or(r2,r1)
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
-; CHECK-NEXT:     memb(r0+#0) = r5
+; CHECK-NEXT:     memb(r0+#0) = r4
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    {
 ; CHECK-NEXT:     jumpr r31
diff --git a/llvm/test/CodeGen/PowerPC/opt-cmp-inst-cr0-live.ll b/llvm/test/CodeGen/PowerPC/opt-cmp-inst-cr0-live.ll
index 8a443c164b75529..4cf21db1f934d78 100644
--- a/llvm/test/CodeGen/PowerPC/opt-cmp-inst-cr0-live.ll
+++ b/llvm/test/CodeGen/PowerPC/opt-cmp-inst-cr0-live.ll
@@ -7,11 +7,11 @@ define signext i32 @fn1(i32 %baz) {
   %2 = zext i32 %1 to i64
   %3 = shl i64 %2, 48
   %4 = ashr exact i64 %3, 48
-; CHECK: RLWINM8 killed {{[^,]+}}, 0, 16, 27
+; CHECK: RLDICR {{[^,]+}}, 48, 15
 ; CHECK: CMPLDI
 ; CHECK: BCC
 
-; CHECK: ANDI8_rec {{[^,]+}}, 65520, implicit-def $cr0
+; CHECK: RLDICR_rec {{[^,]+}}, 48, 15, implicit-def $cr0
 ; CHECK: COPY killed $cr0
 ; CHECK: BCC
   %5 = icmp eq i64 %4, 0
diff --git a/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll b/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll
index 6e3a50542939f15..abfa1d3d3f06cb4 100644
--- a/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll
+++ b/llvm/test/CodeGen/RISCV/lack-of-signed-truncation-check.ll
@@ -534,6 +534,7 @@ define i1 @add_ugecmp_i32_i16(i32 %x) nounwind {
 ; RV64I-NEXT:    lui a1, 8
 ; RV64I-NEXT:    add a0, a0, a1
 ; RV64I-NEXT:    srliw a0, a0, 16
+; RV64I-NEXT:    slli a0, a0, 16
 ; RV64I-NEXT:    snez a0, a0
 ; RV64I-NEXT:    ret
 ;
diff --git a/llvm/test/CodeGen/RISCV/sextw-removal.ll b/llvm/test/CodeGen/RISCV/sextw-removal.ll
index f707cb31e3ecedc..dc5ff5c8081bfa5 100644
--- a/llvm/test/CodeGen/RISCV/sextw-removal.ll
+++ b/llvm/test/CodeGen/RISCV/sextw-removal.ll
@@ -1034,31 +1034,34 @@ define signext i32 @bug(i32 signext %x) {
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    beqz a0, .LBB18_4
 ; CHECK-NEXT:  # %bb.1: # %if.end
-; CHECK-NEXT:    srliw a2, a0, 16
-; CHECK-NEXT:    seqz a1, a2
+; CHECK-NEXT:    srliw a3, a0, 16
+; CHECK-NEXT:    seqz a1, a3
 ; CHECK-NEXT:    slli a1, a1, 4
 ; CHECK-NEXT:    sllw a1, a0, a1
+; CHECK-NEXT:    srliw a2, a1, 24
+; CHECK-NEXT:    slli a2, a2, 24
 ; CHECK-NEXT:    li a0, 16
-; CHECK-NEXT:    beqz a2, .LBB18_3
+; CHECK-NEXT:    beqz a3, .LBB18_3
 ; CHECK-NEXT:  # %bb.2: # %if.end
 ; CHECK-NEXT:    li a0, 32
 ; CHECK-NEXT:  .LBB18_3: # %if.end
-; CHECK-NEXT:    srliw a2, a1, 24
 ; CHECK-NEXT:    seqz a2, a2
 ; CHECK-NEXT:    slli a3, a2, 3
 ; CHECK-NEXT:    sllw a1, a1, a3
+; CHECK-NEXT:    srliw a3, a1, 28
+; CHECK-NEXT:    slli a3, a3, 28
 ; CHECK-NEXT:    neg a2, a2
 ; CHECK-NEXT:    andi a2, a2, -8
 ; CHECK-NEXT:    add a0, a0, a2
-; CHECK-NEXT:    srliw a2, a1, 28
-; CHECK-NEXT:    seqz a2, a2
+; CHECK-NEXT:    seqz a2, a3
 ; CHECK-NEXT:    slli a3, a2, 2
 ; CHECK-NEXT:    sllw a1, a1, a3
+; CHECK-NEXT:    srliw a3, a1, 30
+; CHECK-NEXT:    slli a3, a3, 30
 ; CHECK-NEXT:    neg a2, a2
 ; CHECK-NEXT:    andi a2, a2, -4
 ; CHECK-NEXT:    add a0, a0, a2
-; CHECK-NEXT:    srliw a2, a1, 30
-; CHECK-NEXT:    seqz a2, a2
+; CHECK-NEXT:    seqz a2, a3
 ; CHECK-NEXT:    slli a3, a2, 1
 ; CHECK-NEXT:    sllw a1, a1, a3
 ; CHECK-NEXT:    neg a2, a2
@@ -1074,31 +1077,34 @@ define signext i32 @bug(i32 signext %x) {
 ; NOREMOVAL:       # %bb.0: # %entry
 ; NOREMOVAL-NEXT:    beqz a0, .LBB18_4
 ; NOREMOVAL-NEXT:  # %bb.1: # %if.end
-; NOREMOVAL-NEXT:    srliw a2, a0, 16
-; NOREMOVAL-NEXT:    seqz a1, a2
+; NOREMOVAL-NEXT:    srliw a3, a0, 16
+; NOREMOVAL-NEXT:    seqz a1, a3
 ; NOREMOVAL-NEXT:    slli a1, a1, 4
 ; NOREMOVAL-NEXT:    sllw a1, a0, a1
+; NOREMOVAL-NEXT:    srliw a2, a1, 24
+; NOREMOVAL-NEXT:    slli a2, a2, 24
 ; NOREMOVAL-NEXT:    li a0, 16
-; NOREMOVAL-NEXT:    beqz a2, .LBB18_3
+; NOREMOVAL-NEXT:    beqz a3, .LBB18_3
 ; NOREMOVAL-NEXT:  # %bb.2: # %if.end
 ; NOREMOVAL-NEXT:    li a0, 32
 ; NOREMOVAL-NEXT:  .LBB18_3: # %if.end
-; NOREMOVAL-NEXT:    srliw a2, a1, 24
 ; NOREMOVAL-NEXT:    seqz a2, a2
 ; NOREMOVAL-NEXT:    slli a3, a2, 3
 ; NOREMOVAL-NEXT:    sllw a1, a1, a3
+; NOREMOVAL-NEXT:    srliw a3, a1, 28
+; NOREMOVAL-NEXT:    slli a3, a3, 28
 ; NOREMOVAL-NEXT:    neg a2, a2
 ; NOREMOVAL-NEXT:    andi a2, a2, -8
 ; NOREMOVAL-NEXT:    add a0, a0, a2
-; NOREMOVAL-NEXT:    srliw a2, a1, 28
-; NOREMOVAL-NEXT:    seqz a2, a2
+; NOREMOVAL-NEXT:    seqz a2, a3
 ; NOREMOVAL-NEXT:    slli a3, a2, 2
 ; NOREMOVAL-NEXT:    sllw a1, a1, a3
+; NOREMOVAL-NEXT:    srliw a3, a1, 30
+; NOREMOVAL-NEXT:    slli a3, a3, 30
 ; NOREMOVAL-NEXT:    neg a2, a2
 ; NOREMOVAL-NEXT:    andi a2, a2, -4
 ; NOREMOVAL-NEXT:    add a0, a0, a2
-; NOREMOVAL-NEXT:    srliw a2, a1, 30
-; NOREMOVAL-NEXT:    seqz a2, a2
+; NOREMOVAL-NEXT:    seqz a2, a3
 ; NOREMOVAL-NEXT:    slli a3, a2, 1
 ; NOREMOVAL-NEXT:    sllw a1, a1, a3
 ; NOREMOVAL-NEXT:    neg a2, a2
diff --git a/llvm/test/CodeGen/RISCV/signed-truncation-check.ll b/llvm/test/CodeGen/RISCV/signed-truncation-check.ll
index de36bcdb9106099..c5e2c23169df0c0 100644
--- a/llvm/test/CodeGen/RISCV/signed-truncation-check.ll
+++ b/llvm/test/CodeGen/RISCV/signed-truncation-check.ll
@@ -586,6 +586,7 @@ define i1 @add_ultcmp_i32_i16(i32 %x) nounwind {
 ; RV64I-NEXT:    lui a1, 8
 ; RV64I-NEXT:    add a0, a0, a1
 ; RV64I-NEXT:    srliw a0, a0, 16
+; RV64I-NEXT:    slli a0, a0, 16
 ; RV64I-NEXT:    seqz a0, a0
 ; RV64I-NEXT:    ret
 ;



More information about the llvm-commits mailing list