[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
Tue May 7 02:53:38 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 1/3] [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 c938b3996be3..15331276a6e6 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 1f72307f12a6..ca01680792ef 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 838da59f9e41..bad99b5c7d97 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 2eecfa9f47f1..9df3289a3f58 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 8a443c164b75..4cf21db1f934 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 6e3a50542939..abfa1d3d3f06 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 f707cb31e3ec..dc5ff5c8081b 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 de36bcdb9106..c5e2c23169df 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
;
>From add73576eceef36678dbdcb8062188a8ad8c861d Mon Sep 17 00:00:00 2001
From: Bjorn Pettersson <bjorn.a.pettersson at ericsson.com>
Date: Tue, 7 May 2024 10:39:45 +0200
Subject: [PATCH 2/3] To be sqashed: Add SelectionDAG::computeShiftFlags
helper.
---
llvm/include/llvm/CodeGen/SelectionDAG.h | 3 ++
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 32 +++++++++++++++++++
.../CodeGen/SelectionDAG/TargetLowering.cpp | 21 ++++--------
3 files changed, 42 insertions(+), 14 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index f353aef1f446..1610effa48ab 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -1991,6 +1991,9 @@ class SelectionDAG {
return computeOverflowForMul(IsSigned, N0, N1) == OFK_Never;
}
+ /// Determine if a SHL/SRL/SRA operation is known to be exact/nuw/nsw.
+ SDNodeFlags computeShiftFlags(SDValue Op) const;
+
/// Test if the given value is known to have exactly one bit set. This differs
/// from computeKnownBits in that it doesn't necessarily determine which bit
/// is set.
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 5b7d6376d7d7..4737721b7a38 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4282,6 +4282,38 @@ SelectionDAG::computeOverflowForSignedMul(SDValue N0, SDValue N1) const {
return OFK_Sometime;
}
+SDNodeFlags SelectionDAG::computeShiftFlags(SDValue Op) const {
+ assert((Op.getOpcode() == ISD::SRL || Op.getOpcode() == ISD::SRA ||
+ Op.getOpcode() == ISD::SHL) &&
+ "Expecting an SHL/SRL/SRA operation.");
+ SDValue Op0 = Op.getOperand(0);
+ SDNodeFlags Flags = Op->getFlags();
+
+ // Left shift: Try to derive 'nsw' and 'nuw' via value tracking.
+ if (Op.getOpcode() == ISD::SHL) {
+ if (const APInt *ShAmt = getValidMaximumShiftAmountConstant(Op)) {
+ if (!Flags.hasNoSignedWrap() && ShAmt->ult(ComputeNumSignBits(Op0)))
+ Flags.setNoSignedWrap(true);
+ if (!Flags.hasNoUnsignedWrap() &&
+ ShAmt->ule(computeKnownBits(Op0).countMinLeadingZeros()))
+ Flags.setNoUnsignedWrap(true);
+ }
+ return Flags;
+ }
+
+ // Right shift: Try to derive 'exact' via value tracking.
+ if ((Op.getOpcode() == ISD::SRL || Op.getOpcode() == ISD::SRA)) {
+ if (!Flags.hasExact())
+ if (const APInt *ShAmt = getValidMaximumShiftAmountConstant(Op)) {
+ if (ShAmt->ule(computeKnownBits(Op0).countMinTrailingZeros()))
+ Flags.setExact(true);
+ }
+ }
+
+ return Flags;
+}
+
+
bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val, unsigned Depth) const {
if (Depth >= MaxRecursionDepth)
return false; // Limit search depth.
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 15331276a6e6..aec4ef763b40 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -4518,7 +4518,7 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
}
// Optimize
- // (setcc (shift N00, N01C), 0, eq/ne) -> (setcc N00, 0, eq/ne)
+ // (setcc (shift N00, N01), 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
@@ -4530,20 +4530,13 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
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()))
+ // We cam't rely on flags already being present on all shift operations,
+ // so let's compute the flags using value tracking.
+ SDNodeFlags Flags = DAG.computeShiftFlags(N0);
+ if (IsRightShift ? Flags.hasExact()
+ : (Flags.hasNoUnsignedWrap() ||
+ Flags.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);
- }
}
}
>From 8d7384a26746f879578a290ba7dca5c2b0097868 Mon Sep 17 00:00:00 2001
From: Bjorn Pettersson <bjorn.a.pettersson at ericsson.com>
Date: Tue, 7 May 2024 11:52:23 +0200
Subject: [PATCH 3/3] To be squashed: cleanup
---
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 3 +--
llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 5 ++---
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 4737721b7a38..50b1055d32e4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4283,7 +4283,7 @@ SelectionDAG::computeOverflowForSignedMul(SDValue N0, SDValue N1) const {
}
SDNodeFlags SelectionDAG::computeShiftFlags(SDValue Op) const {
- assert((Op.getOpcode() == ISD::SRL || Op.getOpcode() == ISD::SRA ||
+ assert((Op.getOpcode() == ISD::SRL || Op.getOpcode() == ISD::SRA ||
Op.getOpcode() == ISD::SHL) &&
"Expecting an SHL/SRL/SRA operation.");
SDValue Op0 = Op.getOperand(0);
@@ -4313,7 +4313,6 @@ SDNodeFlags SelectionDAG::computeShiftFlags(SDValue Op) const {
return Flags;
}
-
bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val, unsigned Depth) const {
if (Depth >= MaxRecursionDepth)
return false; // Limit search depth.
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index aec4ef763b40..f125d86df35a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -4530,12 +4530,11 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
N0.getOpcode() == ISD::SRA)) {
bool IsRightShift = N0.getOpcode() != ISD::SHL;
SDValue N00 = N0.getOperand(0);
- // We cam't rely on flags already being present on all shift operations,
+ // We can't rely on flags already being present on all shift operations,
// so let's compute the flags using value tracking.
SDNodeFlags Flags = DAG.computeShiftFlags(N0);
if (IsRightShift ? Flags.hasExact()
- : (Flags.hasNoUnsignedWrap() ||
- Flags.hasNoSignedWrap()))
+ : (Flags.hasNoUnsignedWrap() || Flags.hasNoSignedWrap()))
return DAG.getSetCC(dl, VT, N00, N1, Cond);
}
}
More information about the llvm-commits
mailing list