[llvm] [GlobalISel] Add G_SUB for computeNumSignBits (PR #158384)
Yatao Wang via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 16 11:25:29 PDT 2025
https://github.com/ningxinr updated https://github.com/llvm/llvm-project/pull/158384
>From 21a88d95001c653eebb0e956687953c437935eab Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Fri, 12 Sep 2025 12:05:03 -0700
Subject: [PATCH 1/7] Add tests for ISel and GlobalISel Sub
---
.../AArch64/GlobalISel/knownbits-sub.mir | 234 ++++++++++++++++++
.../AArch64/AArch64SelectionDAGTest.cpp | 45 ++++
2 files changed, 279 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir
new file mode 100644
index 0000000000000..8051bd2d17812
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir
@@ -0,0 +1,234 @@
+# NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple aarch64 -passes="print<gisel-value-tracking>" %s -o - 2>&1 | FileCheck %s
+
+---
+name: Cst
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @Cst
+ ; CHECK-NEXT: %0:_ KnownBits:00000010 SignBits:6
+ ; CHECK-NEXT: %1:_ KnownBits:11100000 SignBits:3
+ ; CHECK-NEXT: %2:_ KnownBits:00100010 SignBits:2
+ %0:_(s8) = G_CONSTANT i8 2
+ %1:_(s8) = G_CONSTANT i8 224
+ %2:_(s8) = G_SUB %0, %1
+...
+---
+name: CstZero
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @CstZero
+ ; CHECK-NEXT: %0:_ KnownBits:00000000 SignBits:8
+ ; CHECK-NEXT: %1:_ KnownBits:00000000 SignBits:8
+ ; CHECK-NEXT: %2:_ KnownBits:00000000 SignBits:8
+ %0:_(s8) = G_CONSTANT i8 0
+ %1:_(s8) = G_CONSTANT i8 0
+ %2:_(s8) = G_SUB %0, %1
+...
+---
+name: CstNegOne
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @CstNegOne
+ ; CHECK-NEXT: %0:_ KnownBits:00000000 SignBits:8
+ ; CHECK-NEXT: %1:_ KnownBits:00000001 SignBits:7
+ ; CHECK-NEXT: %2:_ KnownBits:11111111 SignBits:8
+ %0:_(s8) = G_CONSTANT i8 0
+ %1:_(s8) = G_CONSTANT i8 1
+ %2:_(s8) = G_SUB %0, %1
+...
+---
+name: CstNeg
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @CstNeg
+ ; CHECK-NEXT: %0:_ KnownBits:11100000 SignBits:3
+ ; CHECK-NEXT: %1:_ KnownBits:00000010 SignBits:6
+ ; CHECK-NEXT: %2:_ KnownBits:11011110 SignBits:2
+ %0:_(s8) = G_CONSTANT i8 224
+ %1:_(s8) = G_CONSTANT i8 2
+ %2:_(s8) = G_SUB %0, %1
+...
+---
+name: ScalarVar
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @ScalarVar
+ ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %2:_ KnownBits:???????? SignBits:1
+ %0:_(s8) = COPY $b0
+ %1:_(s8) = COPY $b1
+ %2:_(s8) = G_SUB %0, %1
+...
+---
+name: ScalarRhsEarlyOut
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @ScalarRhsEarlyOut
+ ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:00000011 SignBits:6
+ ; CHECK-NEXT: %2:_ KnownBits:???????? SignBits:1
+ %0:_(s8) = COPY $b0
+ %1:_(s8) = G_CONSTANT i8 3
+ %2:_(s8) = G_SUB %0, %1
+...
+---
+name: ScalarNonNegative
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @ScalarNonNegative
+ ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:00001111 SignBits:4
+ ; CHECK-NEXT: %2:_ KnownBits:0000???? SignBits:4
+ ; CHECK-NEXT: %3:_ KnownBits:00000000 SignBits:8
+ ; CHECK-NEXT: %4:_ KnownBits:???????? SignBits:1
+ %0:_(s8) = COPY $b0
+ %1:_(s8) = G_CONSTANT i8 15
+ %2:_(s8) = G_AND %0, %1
+ %3:_(s8) = G_CONSTANT i8 0
+ %4:_(s8) = G_SUB %3, %2
+...
+---
+name: ScalarLhsEarlyOut
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @ScalarLhsEarlyOut
+ ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:00000011 SignBits:6
+ ; CHECK-NEXT: %2:_ KnownBits:???????? SignBits:1
+ %0:_(s8) = COPY $b0
+ %1:_(s8) = G_CONSTANT i8 3
+ %2:_(s8) = G_SUB %1, %0
+...
+---
+name: ScalarPartKnown
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @ScalarPartKnown
+ ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:00001111 SignBits:4
+ ; CHECK-NEXT: %2:_ KnownBits:0000???? SignBits:4
+ ; CHECK-NEXT: %3:_ KnownBits:00000101 SignBits:5
+ ; CHECK-NEXT: %4:_ KnownBits:???????? SignBits:1
+ %0:_(s8) = COPY $b0
+ %1:_(s8) = G_CONSTANT i8 15
+ %2:_(s8) = G_AND %0, %1
+ %3:_(s8) = G_CONSTANT i8 5
+ %4:_(s8) = G_SUB %2, %3
+...
+---
+name: VectorVar
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @VectorVar
+ ; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %2:_ KnownBits:???????????????? SignBits:1
+ %0:_(<4 x s16>) = COPY $d0
+ %1:_(<4 x s16>) = COPY $d1
+ %2:_(<4 x s16>) = G_SUB %0, %1
+...
+---
+name: VectorRhsEarlyOut
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @VectorRhsEarlyOut
+ ; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:0000000000000011 SignBits:14
+ ; CHECK-NEXT: %2:_ KnownBits:0000000000000011 SignBits:14
+ ; CHECK-NEXT: %3:_ KnownBits:???????????????? SignBits:1
+ %0:_(<4 x s16>) = COPY $d0
+ %1:_(s16) = G_CONSTANT i16 3
+ %2:_(<4 x s16>) = G_BUILD_VECTOR %1, %1, %1, %1
+ %3:_(<4 x s16>) = G_SUB %2, %0
+...
+---
+name: VectorNonNegative
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @VectorNonNegative
+ ; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:0000000011111111 SignBits:8
+ ; CHECK-NEXT: %2:_ KnownBits:0000000011111111 SignBits:8
+ ; CHECK-NEXT: %3:_ KnownBits:00000000???????? SignBits:8
+ ; CHECK-NEXT: %4:_ KnownBits:0000000000000000 SignBits:16
+ ; CHECK-NEXT: %5:_ KnownBits:0000000000000000 SignBits:16
+ ; CHECK-NEXT: %6:_ KnownBits:???????????????? SignBits:1
+ %0:_(<4 x s16>) = COPY $d0
+ %1:_(s16) = G_CONSTANT i16 255
+ %2:_(<4 x s16>) = G_BUILD_VECTOR %1, %1, %1, %1
+ %3:_(<4 x s16>) = G_AND %0, %2
+ %4:_(s16) = G_CONSTANT i16 0
+ %5:_(<4 x s16>) = G_BUILD_VECTOR %4, %4, %4, %4
+ %6:_(<4 x s16>) = G_SUB %5, %3
+...
+---
+name: VectorLhsEarlyOut
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @VectorLhsEarlyOut
+ ; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:0000000000000011 SignBits:14
+ ; CHECK-NEXT: %2:_ KnownBits:0000000000000011 SignBits:14
+ ; CHECK-NEXT: %3:_ KnownBits:???????????????? SignBits:1
+ %0:_(<4 x s16>) = COPY $d0
+ %1:_(s16) = G_CONSTANT i16 3
+ %2:_(<4 x s16>) = G_BUILD_VECTOR %1, %1, %1, %1
+ %3:_(<4 x s16>) = G_SUB %0, %2
+...
+---
+name: VectorPartKnown
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @VectorPartKnown
+ ; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:0000000011111111 SignBits:8
+ ; CHECK-NEXT: %2:_ KnownBits:0000000011111111 SignBits:8
+ ; CHECK-NEXT: %3:_ KnownBits:00000000???????? SignBits:8
+ ; CHECK-NEXT: %4:_ KnownBits:0000000000101010 SignBits:10
+ ; CHECK-NEXT: %5:_ KnownBits:0000000001001010 SignBits:9
+ ; CHECK-NEXT: %6:_ KnownBits:000000000??01010 SignBits:9
+ ; CHECK-NEXT: %7:_ KnownBits:???????????????? SignBits:1
+ %0:_(<4 x s16>) = COPY $d0
+ %1:_(s16) = G_CONSTANT i16 255
+ %2:_(<4 x s16>) = G_BUILD_VECTOR %1, %1, %1, %1
+ %3:_(<4 x s16>) = G_AND %0, %2
+ %4:_(s16) = G_CONSTANT i16 42
+ %5:_(s16) = G_CONSTANT i16 74
+ %6:_(<4 x s16>) = G_BUILD_VECTOR %4, %5, %5, %4
+ %7:_(<4 x s16>) = G_SUB %6, %3
+...
+---
+name: VectorCst36
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @VectorCst36
+ ; CHECK-NEXT: %0:_ KnownBits:0000000000000011 SignBits:14
+ ; CHECK-NEXT: %1:_ KnownBits:0000000000000110 SignBits:13
+ ; CHECK-NEXT: %2:_ KnownBits:0000000000000?1? SignBits:13
+ ; CHECK-NEXT: %3:_ KnownBits:0000000000000?1? SignBits:13
+ ; CHECK-NEXT: %4:_ KnownBits:???????????????? SignBits:1
+ %0:_(s16) = G_CONSTANT i16 3
+ %1:_(s16) = G_CONSTANT i16 6
+ %2:_(<4 x s16>) = G_BUILD_VECTOR %0, %1, %1, %0
+ %3:_(<4 x s16>) = G_BUILD_VECTOR %0, %1, %1, %0
+ %4:_(<4 x s16>) = G_SUB %2, %3
+...
+
+---
+name: VectorCst3unknown
+body: |
+ bb.1:
+ ; CHECK-LABEL: name: @VectorCst3unknown
+ ; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %2:_ KnownBits:0000000000000011 SignBits:14
+ ; CHECK-NEXT: %3:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %4:_ KnownBits:???????????????? SignBits:1
+ %0:_(<4 x s16>) = COPY $d0
+ %1:_(s16) = COPY $h0
+ %2:_(s16) = G_CONSTANT i16 3
+ %3:_(<4 x s16>) = G_BUILD_VECTOR %1, %2, %2, %1
+ %4:_(<4 x s16>) = G_SUB %0, %3
+...
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index c74d15782398a..b56e3ec53c18c 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -177,6 +177,51 @@ TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_VASHR) {
EXPECT_EQ(DAG->ComputeNumSignBits(Fr2), 5u);
}
+TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_SUB) {
+ SDLoc Loc;
+ auto IntVT = EVT::getIntegerVT(Context, 8);
+ auto N0 = DAG->getConstant(0x00, Loc, IntVT);
+ auto N1 = DAG->getConstant(0x01, Loc, IntVT);
+ auto N5 = DAG->getConstant(0x05, Loc, IntVT);
+ auto Nsign1 = DAG->getConstant(0x55, Loc, IntVT);
+ auto UnknownOp = DAG->getRegister(0, IntVT);
+ auto Mask = DAG->getConstant(0x1e, Loc, IntVT);
+ auto Nsign3 = DAG->getNode(ISD::AND, Loc, IntVT, Mask, UnknownOp);
+ // RHS early out
+ // Nsign1 = 01010101
+ // Nsign3 = 000????0
+ auto OpRhsEo = DAG->getNode(ISD::SUB, Loc, IntVT, Nsign3, Nsign1);
+ EXPECT_EQ(DAG->ComputeNumSignBits(OpRhsEo), 1u);
+
+ // Neg 0
+ // N0 = 00000000
+ auto OpNegZero = DAG->getNode(ISD::SUB, Loc, IntVT, N0, N0);
+ EXPECT_EQ(DAG->ComputeNumSignBits(OpNegZero), 8u);
+
+ // Neg 1
+ // N0 = 00000000
+ // N1 = 00000001
+ auto OpNegOne = DAG->getNode(ISD::SUB, Loc, IntVT, N0, N1);
+ EXPECT_EQ(DAG->ComputeNumSignBits(OpNegOne), 8u);
+
+ // Non negative
+ // N0 = 00000000
+ // Nsign3 = 000????0
+ auto OpNonNeg = DAG->getNode(ISD::SUB, Loc, IntVT, N0, Nsign3);
+ EXPECT_EQ(DAG->ComputeNumSignBits(OpNonNeg), 3u);
+
+ // LHS early out
+ // Nsign1 = 01010101
+ // Nsign3 = 000????0
+ auto OpLhsEo = DAG->getNode(ISD::SUB, Loc, IntVT, Nsign1, Nsign3);
+ EXPECT_EQ(DAG->ComputeNumSignBits(OpLhsEo), 1u);
+
+ // Nsign3 = 000????0
+ // N5 = 00000101
+ auto Op = DAG->getNode(ISD::SUB, Loc, IntVT, Nsign3, N5);
+ EXPECT_EQ(DAG->ComputeNumSignBits(Op), 2u);
+}
+
TEST_F(AArch64SelectionDAGTest, SimplifyDemandedVectorElts_EXTRACT_SUBVECTOR) {
TargetLowering TL(*TM);
>From 877acf41c0e0d985db65ec2b93fe6549d09fd219 Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Fri, 12 Sep 2025 13:42:57 -0700
Subject: [PATCH 2/7] Fix typo
---
llvm/test/CodeGen/AArch64/GlobalISel/knownbits-ashr.mir | 4 ++--
llvm/test/CodeGen/AArch64/GlobalISel/knownbits-shl.mir | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-ashr.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-ashr.mir
index 8552931c1f4c0..ee354479d603c 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-ashr.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-ashr.mir
@@ -102,8 +102,8 @@ body: |
; CHECK-NEXT: %3:_ KnownBits:???????????????? SignBits:1
; CHECK-NEXT: %4:_ KnownBits:???????????????? SignBits:1
%0:_(<4 x s16>) = COPY $d0
- %2:_(s16) = COPY $h0
- %1:_(s16) = G_CONSTANT i16 3
+ %1:_(s16) = COPY $h0
+ %2:_(s16) = G_CONSTANT i16 3
%3:_(<4 x s16>) = G_BUILD_VECTOR %1, %2, %2, %1
%4:_(<4 x s16>) = G_ASHR %0, %3
...
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-shl.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-shl.mir
index 61d1c4375bd6e..97bcb80503d8d 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-shl.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-shl.mir
@@ -135,8 +135,8 @@ body: |
; CHECK-NEXT: %3:_ KnownBits:???????????????? SignBits:1
; CHECK-NEXT: %4:_ KnownBits:???????????????? SignBits:1
%0:_(<4 x s16>) = COPY $d0
- %2:_(s16) = COPY $h0
- %1:_(s16) = G_CONSTANT i16 3
+ %1:_(s16) = COPY $h0
+ %2:_(s16) = G_CONSTANT i16 3
%3:_(<4 x s16>) = G_BUILD_VECTOR %1, %2, %2, %1
%4:_(<4 x s16>) = G_SHL %0, %3
...
>From 83df265c3023045de074b3f9b616f7d25d191495 Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Fri, 12 Sep 2025 16:19:38 -0700
Subject: [PATCH 3/7] Initial attemp for sub
---
llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp | 14 ++++++++++++++
.../CodeGen/AArch64/GlobalISel/knownbits-sub.mir | 10 +++++-----
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 0cf44e02254de..294a76b885f06 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1976,6 +1976,20 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
break;
}
+ case TargetOpcode::G_SUB: {
+ Register Src1 = MI.getOperand(1).getReg();
+ unsigned Src1NumSignBits =
+ computeNumSignBits(Src1, DemandedElts, Depth + 1);
+ if (Src1NumSignBits != 1) {
+ Register Src2 = MI.getOperand(2).getReg();
+ unsigned Src2NumSignBits =
+ computeNumSignBits(Src2, DemandedElts, Depth + 1);
+ if (Src2NumSignBits == 1)
+ return 1; // Early out.
+ FirstAnswer = std::min(Src1NumSignBits, Src2NumSignBits) - 1;
+ }
+ break;
+ }
case TargetOpcode::G_FCMP:
case TargetOpcode::G_ICMP: {
bool IsFP = Opcode == TargetOpcode::G_FCMP;
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir
index 8051bd2d17812..d91c39508d5de 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir
@@ -82,7 +82,7 @@ body: |
; CHECK-NEXT: %1:_ KnownBits:00001111 SignBits:4
; CHECK-NEXT: %2:_ KnownBits:0000???? SignBits:4
; CHECK-NEXT: %3:_ KnownBits:00000000 SignBits:8
- ; CHECK-NEXT: %4:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %4:_ KnownBits:???????? SignBits:3
%0:_(s8) = COPY $b0
%1:_(s8) = G_CONSTANT i8 15
%2:_(s8) = G_AND %0, %1
@@ -110,7 +110,7 @@ body: |
; CHECK-NEXT: %1:_ KnownBits:00001111 SignBits:4
; CHECK-NEXT: %2:_ KnownBits:0000???? SignBits:4
; CHECK-NEXT: %3:_ KnownBits:00000101 SignBits:5
- ; CHECK-NEXT: %4:_ KnownBits:???????? SignBits:1
+ ; CHECK-NEXT: %4:_ KnownBits:???????? SignBits:3
%0:_(s8) = COPY $b0
%1:_(s8) = G_CONSTANT i8 15
%2:_(s8) = G_AND %0, %1
@@ -154,7 +154,7 @@ body: |
; CHECK-NEXT: %3:_ KnownBits:00000000???????? SignBits:8
; CHECK-NEXT: %4:_ KnownBits:0000000000000000 SignBits:16
; CHECK-NEXT: %5:_ KnownBits:0000000000000000 SignBits:16
- ; CHECK-NEXT: %6:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %6:_ KnownBits:???????????????? SignBits:7
%0:_(<4 x s16>) = COPY $d0
%1:_(s16) = G_CONSTANT i16 255
%2:_(<4 x s16>) = G_BUILD_VECTOR %1, %1, %1, %1
@@ -189,7 +189,7 @@ body: |
; CHECK-NEXT: %4:_ KnownBits:0000000000101010 SignBits:10
; CHECK-NEXT: %5:_ KnownBits:0000000001001010 SignBits:9
; CHECK-NEXT: %6:_ KnownBits:000000000??01010 SignBits:9
- ; CHECK-NEXT: %7:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %7:_ KnownBits:???????????????? SignBits:7
%0:_(<4 x s16>) = COPY $d0
%1:_(s16) = G_CONSTANT i16 255
%2:_(<4 x s16>) = G_BUILD_VECTOR %1, %1, %1, %1
@@ -208,7 +208,7 @@ body: |
; CHECK-NEXT: %1:_ KnownBits:0000000000000110 SignBits:13
; CHECK-NEXT: %2:_ KnownBits:0000000000000?1? SignBits:13
; CHECK-NEXT: %3:_ KnownBits:0000000000000?1? SignBits:13
- ; CHECK-NEXT: %4:_ KnownBits:???????????????? SignBits:1
+ ; CHECK-NEXT: %4:_ KnownBits:???????????????? SignBits:12
%0:_(s16) = G_CONSTANT i16 3
%1:_(s16) = G_CONSTANT i16 6
%2:_(<4 x s16>) = G_BUILD_VECTOR %0, %1, %1, %0
>From bebcbc09f43008bee0793c7e9bf6d82b2b9ad908 Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Mon, 15 Sep 2025 11:07:33 -0700
Subject: [PATCH 4/7] Fix lit test
CodeGen/ARM/GlobalISel/arm-legalize-bitcounts.mir
---
.../test/CodeGen/ARM/GlobalISel/arm-legalize-bitcounts.mir | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-bitcounts.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-bitcounts.mir
index c8fee5d334429..7cbe5de22debc 100644
--- a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-bitcounts.mir
+++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-bitcounts.mir
@@ -119,9 +119,10 @@ body: |
; CHECK: [[R32:%[0-9]+]]:_(s32) = G_SUB [[COUNT]], [[BITDIFF]]
%2(s16) = G_CTLZ %1
- ; CHECK: [[SHIFTEDR:%[0-9]+]]:_(s32) = G_SHL [[R32]], [[BITDIFF]]
- ; CHECK: [[R:%[0-9]+]]:_(s32) = G_ASHR [[SHIFTEDR]], [[BITDIFF]]
- ; CHECK: $r0 = COPY [[R]]
+ ; LIBCALLS: [[SHIFTEDR:%[0-9]+]]:_(s32) = G_SHL [[R32]], [[BITDIFF]]
+ ; LIBCALLS: [[R:%[0-9]+]]:_(s32) = G_ASHR [[SHIFTEDR]], [[BITDIFF]]
+ ; LIBCALLS: $r0 = COPY [[R]]
+ ; CLZ: $r0 = COPY [[R32]]
%3(s32) = G_SEXT %2(s16)
$r0 = COPY %3(s32)
BX_RET 14, $noreg, implicit $r0
>From 59ddc872d8dc22fc44a942fb8bac40552339d36c Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Mon, 15 Sep 2025 11:10:05 -0700
Subject: [PATCH 5/7] Handle non neg case
---
.../CodeGen/GlobalISel/GISelValueTracking.cpp | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 294a76b885f06..f09b4e30e1ee6 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1980,14 +1980,15 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
Register Src1 = MI.getOperand(1).getReg();
unsigned Src1NumSignBits =
computeNumSignBits(Src1, DemandedElts, Depth + 1);
- if (Src1NumSignBits != 1) {
- Register Src2 = MI.getOperand(2).getReg();
- unsigned Src2NumSignBits =
- computeNumSignBits(Src2, DemandedElts, Depth + 1);
- if (Src2NumSignBits == 1)
- return 1; // Early out.
- FirstAnswer = std::min(Src1NumSignBits, Src2NumSignBits) - 1;
- }
+ if (Src1NumSignBits == 1)
+ return 1; // Early Out.
+ Register Src2 = MI.getOperand(2).getReg();
+ unsigned Src2NumSignBits =
+ computeNumSignBits(Src2, DemandedElts, Depth + 1);
+ if (Src2NumSignBits == 1)
+ return 1; // Early out.
+ FirstAnswer = std::min(Src1NumSignBits, Src2NumSignBits) - 1;
+
break;
}
case TargetOpcode::G_FCMP:
>From f7c2c793d762711f67335765ac1b197a999e44f8 Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Mon, 15 Sep 2025 15:17:26 -0700
Subject: [PATCH 6/7] Handle Non Neg
---
.../CodeGen/GlobalISel/GISelValueTracking.cpp | 23 ++++++++++++++++++-
.../AArch64/GlobalISel/knownbits-sub.mir | 4 ++--
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index f09b4e30e1ee6..0630d643f92a3 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1982,13 +1982,34 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
computeNumSignBits(Src1, DemandedElts, Depth + 1);
if (Src1NumSignBits == 1)
return 1; // Early Out.
+
Register Src2 = MI.getOperand(2).getReg();
unsigned Src2NumSignBits =
computeNumSignBits(Src2, DemandedElts, Depth + 1);
+
+ // Handle NEG.
+ KnownBits Known1 = getKnownBits(Src1, DemandedElts, Depth);
+ if (Known1.Zero.isAllOnes()) {
+ KnownBits Known2 = getKnownBits(Src2, DemandedElts, Depth);
+ // If the input is known to be 0 or 1, the output is 0/-1, which is all
+ // sign bits set.
+ if ((Known2.Zero | 1).isAllOnes())
+ return TyBits;
+
+ // If the input is known to be positive (the sign bit is known clear),
+ // the output of the NEG has the same number of sign bits as the input.
+ if (Known2.isNonNegative())
+ return Src2NumSignBits;
+
+ // Otherwise, we treat this like a SUB.
+ }
+
if (Src2NumSignBits == 1)
return 1; // Early out.
- FirstAnswer = std::min(Src1NumSignBits, Src2NumSignBits) - 1;
+ // Sub can have at most one carry bit. Thus we know that the output
+ // is, at worst, one more bit than the inputs.
+ FirstAnswer = std::min(Src1NumSignBits, Src2NumSignBits) - 1;
break;
}
case TargetOpcode::G_FCMP:
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir
index d91c39508d5de..7fdfb18dafeb2 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-sub.mir
@@ -82,7 +82,7 @@ body: |
; CHECK-NEXT: %1:_ KnownBits:00001111 SignBits:4
; CHECK-NEXT: %2:_ KnownBits:0000???? SignBits:4
; CHECK-NEXT: %3:_ KnownBits:00000000 SignBits:8
- ; CHECK-NEXT: %4:_ KnownBits:???????? SignBits:3
+ ; CHECK-NEXT: %4:_ KnownBits:???????? SignBits:4
%0:_(s8) = COPY $b0
%1:_(s8) = G_CONSTANT i8 15
%2:_(s8) = G_AND %0, %1
@@ -154,7 +154,7 @@ body: |
; CHECK-NEXT: %3:_ KnownBits:00000000???????? SignBits:8
; CHECK-NEXT: %4:_ KnownBits:0000000000000000 SignBits:16
; CHECK-NEXT: %5:_ KnownBits:0000000000000000 SignBits:16
- ; CHECK-NEXT: %6:_ KnownBits:???????????????? SignBits:7
+ ; CHECK-NEXT: %6:_ KnownBits:???????????????? SignBits:8
%0:_(<4 x s16>) = COPY $d0
%1:_(s16) = G_CONSTANT i16 255
%2:_(<4 x s16>) = G_BUILD_VECTOR %1, %1, %1, %1
>From 4c4500de79d197cd1432f5e75e394d68196e90db Mon Sep 17 00:00:00 2001
From: ningxinr <ningxinr at live.cn>
Date: Tue, 16 Sep 2025 10:54:48 -0700
Subject: [PATCH 7/7] Make early out out early
---
llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp | 5 ++---
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 9 ++++++---
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 0630d643f92a3..e89c4eed5850b 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1986,6 +1986,8 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
Register Src2 = MI.getOperand(2).getReg();
unsigned Src2NumSignBits =
computeNumSignBits(Src2, DemandedElts, Depth + 1);
+ if (Src2NumSignBits == 1)
+ return 1; // Early out.
// Handle NEG.
KnownBits Known1 = getKnownBits(Src1, DemandedElts, Depth);
@@ -2004,9 +2006,6 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
// Otherwise, we treat this like a SUB.
}
- if (Src2NumSignBits == 1)
- return 1; // Early out.
-
// Sub can have at most one carry bit. Thus we know that the output
// is, at worst, one more bit than the inputs.
FirstAnswer = std::min(Src1NumSignBits, Src2NumSignBits) - 1;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index bcf25958d0982..db46294bea0ce 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5066,8 +5066,13 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts,
if (Tmp2 == 1) return 1; // Early out.
return std::min(Tmp, Tmp2) - 1;
case ISD::SUB:
+ Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
+ if (Tmp == 1)
+ return 1; // Early out.
+
Tmp2 = ComputeNumSignBits(Op.getOperand(1), DemandedElts, Depth + 1);
- if (Tmp2 == 1) return 1; // Early out.
+ if (Tmp2 == 1)
+ return 1; // Early out.
// Handle NEG.
if (ConstantSDNode *CLHS =
@@ -5090,8 +5095,6 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts,
// Sub can have at most one carry bit. Thus we know that the output
// is, at worst, one more bit than the inputs.
- Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
- if (Tmp == 1) return 1; // Early out.
return std::min(Tmp, Tmp2) - 1;
case ISD::MUL: {
// The output of the Mul can be at most twice the valid bits in the inputs.
More information about the llvm-commits
mailing list