[llvm] [GlobalISel] Add G_ABS computeKnownBits, add ComputeKnownBitsCache assertion to computeNumSignBits (PR #154413)

Pragyansh Chaturvedi via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 5 00:08:55 PDT 2025


https://github.com/r41k0u updated https://github.com/llvm/llvm-project/pull/154413

>From d98e7359b35eede1f21f5dad48b021568b286e15 Mon Sep 17 00:00:00 2001
From: Pragyansh Chaturvedi <pragyansh.chaturvedi at canonical.com>
Date: Wed, 20 Aug 2025 00:45:25 +0530
Subject: [PATCH 01/10] [GlobalISel] Add G_ABS computeKnownBits

---
 .../CodeGen/GlobalISel/GISelValueTracking.cpp |  8 +++++++
 .../AArch64/GlobalISel/knownbits-abs.mir      | 23 +++++++++++++++++++
 2 files changed, 31 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir

diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 974fc40de6222..df1b325fa5baf 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -697,6 +697,14 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
     }
     break;
   }
+  case TargetOpcode::G_ABS: {
+    Register SrcReg = MI.getOperand(1).getReg();
+    computeKnownBitsImpl(SrcReg, Known, DemandedElts, Depth + 1);
+    Known = Known.abs();
+    Known.Zero.setHighBits(computeNumSignBits(SrcReg, DemandedElts, Depth + 1) -
+                           1);
+    break;
+  }
   }
 
   LLVM_DEBUG(dumpResult(MI, Known, Depth));
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir
new file mode 100644
index 0000000000000..c3675dc17e342
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir
@@ -0,0 +1,23 @@
+# 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 -filetype=null 2>&1 | FileCheck %s
+
+---
+name: Cst
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @Cst
+  ; CHECK-NEXT: %0:_ KnownBits:00010011 SignBits:3
+  ; CHECK-NEXT: %1:_ KnownBits:00010011 SignBits:3
+    %0:_(s8) = G_CONSTANT i8 19
+    %1:_(s8) = G_ABS %0
+...
+---
+name: CstNeg
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @CstNeg
+  ; CHECK-NEXT: %0:_ KnownBits:11101110 SignBits:3
+  ; CHECK-NEXT: %1:_ KnownBits:00010010 SignBits:3
+    %0:_(s8) = G_CONSTANT i8 238
+    %1:_(s8) = G_ABS %0
+...

>From 12ec0e5c0b2b8af166f4510ac615b80195a61256 Mon Sep 17 00:00:00 2001
From: Pragyansh Chaturvedi <pragyansh.chaturvedi at canonical.com>
Date: Mon, 1 Sep 2025 02:55:42 +0530
Subject: [PATCH 02/10] [GlobalISel] Add more tests for G_ABS computeKnownBits

---
 .../AArch64/GlobalISel/knownbits-abs.mir      | 38 ++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir
index c3675dc17e342..1dd67bf301a32 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir
@@ -1,5 +1,5 @@
 # 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 -filetype=null 2>&1 | FileCheck %s
+# RUN: llc -mtriple=aarch64 -passes='print<gisel-value-tracking>' -filetype=null %s 2>&1 | FileCheck %s
 
 ---
 name: Cst
@@ -21,3 +21,39 @@ body: |
     %0:_(s8) = G_CONSTANT i8 238
     %1:_(s8) = G_ABS %0
 ...
+---
+name: SplatVecCst
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @SplatVecCst
+  ; CHECK-NEXT: %0:_ KnownBits:11111010 SignBits:5
+  ; CHECK-NEXT: %1:_ KnownBits:11111010 SignBits:5
+  ; CHECK-NEXT: %2:_ KnownBits:00000110 SignBits:5
+    %0:_(s8) = G_CONSTANT i8 250
+    %1:_(<vscale x 16 x s8>) = G_SPLAT_VECTOR %0(s8)
+    %2:_(<vscale x 16 x s8>) = G_ABS %1
+...
+---
+name: VecCst
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @VecCst
+  ; CHECK-NEXT: %0:_ KnownBits:00011001 SignBits:3
+  ; CHECK-NEXT: %1:_ KnownBits:11100001 SignBits:3
+  ; CHECK-NEXT: %2:_ KnownBits:?????001 SignBits:3
+  ; CHECK-NEXT: %3:_ KnownBits:0??????1 SignBits:1
+    %0:_(s8) = G_CONSTANT i8 25
+    %1:_(s8) = G_CONSTANT i8 225
+    %2:_(<2 x s8>) = G_BUILD_VECTOR %0:_(s8), %1:_(s8)
+    %3:_(<2 x s8>) = G_ABS %2
+...
+---
+name: ImplicitDef
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @ImplicitDef
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:???????? SignBits:1
+    %0:_(s8) = G_IMPLICIT_DEF
+    %1:_(s8) = G_ABS %0
+...

>From fbf33dd26139b6b7bd2af16e3fbc827f54022891 Mon Sep 17 00:00:00 2001
From: Pragyansh Chaturvedi <pragyansh.chaturvedi at canonical.com>
Date: Mon, 1 Sep 2025 15:44:54 +0530
Subject: [PATCH 03/10] [GlobalISel] Add cache assertion and clearing to
 GISelValueTracking::computeNumSignBits

---
 llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index df1b325fa5baf..b503abc793271 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -2045,7 +2045,8 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
 
   // Finally, if we can prove that the top bits of the result are 0's or 1's,
   // use this information.
-  KnownBits Known = getKnownBits(R, DemandedElts, Depth);
+  KnownBits Known;
+  computeKnownBitsImpl(R, Known, DemandedElts, Depth + 1);
   APInt Mask;
   if (Known.isNonNegative()) { // sign bit is 0
     Mask = Known.Zero;
@@ -2066,7 +2067,10 @@ unsigned GISelValueTracking::computeNumSignBits(Register R, unsigned Depth) {
   LLT Ty = MRI.getType(R);
   APInt DemandedElts =
       Ty.isFixedVector() ? APInt::getAllOnes(Ty.getNumElements()) : APInt(1, 1);
-  return computeNumSignBits(R, DemandedElts, Depth);
+  assert(ComputeKnownBitsCache.empty() && "Cache should be empty");
+  unsigned numSignBits = computeNumSignBits(R, DemandedElts, Depth);
+  ComputeKnownBitsCache.clear();
+  return numSignBits;
 }
 
 std::optional<ConstantRange> GISelValueTracking::getValidShiftAmountRange(
@@ -2172,7 +2176,7 @@ GISelValueTrackingPrinterPass::run(MachineFunction &MF,
         Register Reg = MO.getReg();
         if (!MRI.getType(Reg).isValid())
           continue;
-        KnownBits Known = VTA.getKnownBits(Reg);
+	KnownBits Known = VTA.getKnownBits(Reg);
         unsigned SignedBits = VTA.computeNumSignBits(Reg);
         OS << "  " << MO << " KnownBits:" << Known << " SignBits:" << SignedBits
            << '\n';

>From d8ca38464f857ff6db49b73baed71ca1ca83a4ba Mon Sep 17 00:00:00 2001
From: Pragyansh Chaturvedi <pragyansh.chaturvedi at canonical.com>
Date: Mon, 1 Sep 2025 15:49:12 +0530
Subject: [PATCH 04/10] [GlobalISel] Add sign extension tests for
 knownbits_abs, update tests

---
 .../AArch64/GlobalISel/knownbits-abs.mir      | 26 ++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir
index 1dd67bf301a32..b4ac62cd992cf 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-abs.mir
@@ -41,7 +41,7 @@ body: |
   ; CHECK-NEXT: %0:_ KnownBits:00011001 SignBits:3
   ; CHECK-NEXT: %1:_ KnownBits:11100001 SignBits:3
   ; CHECK-NEXT: %2:_ KnownBits:?????001 SignBits:3
-  ; CHECK-NEXT: %3:_ KnownBits:0??????1 SignBits:1
+  ; CHECK-NEXT: %3:_ KnownBits:00?????1 SignBits:2
     %0:_(s8) = G_CONSTANT i8 25
     %1:_(s8) = G_CONSTANT i8 225
     %2:_(<2 x s8>) = G_BUILD_VECTOR %0:_(s8), %1:_(s8)
@@ -57,3 +57,27 @@ body: |
     %0:_(s8) = G_IMPLICIT_DEF
     %1:_(s8) = G_ABS %0
 ...
+---
+name: CstSext
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @CstSext
+  ; CHECK-NEXT: %0:_ KnownBits:11000111 SignBits:2
+  ; CHECK-NEXT: %1:_ KnownBits:1111111111000111 SignBits:10
+  ; CHECK-NEXT: %2:_ KnownBits:0000000000111001 SignBits:10
+    %0:_(s8) = G_CONSTANT i8 199
+    %1:_(s16) = G_SEXT %0
+    %2:_(s16) = G_ABS %1
+...
+---
+name: ImplicitDefSext
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @ImplicitDefSext
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
+  ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:9
+  ; CHECK-NEXT: %2:_ KnownBits:00000000???????? SignBits:8
+    %0:_(s8) = G_IMPLICIT_DEF
+    %1:_(s16) = G_SEXT %0
+    %2:_(s16) = G_ABS %1
+...

>From 907deebb9dbe41bda985d670bd6bf6f2d07a92e6 Mon Sep 17 00:00:00 2001
From: Pragyansh Chaturvedi <pragyansh.chaturvedi at canonical.com>
Date: Mon, 1 Sep 2025 15:52:47 +0530
Subject: [PATCH 05/10] [GlobalISel] Fix formatting in
 GISelValueTrackingPrinterPass::run

---
 llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index b503abc793271..df34fda47eed8 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -2176,7 +2176,7 @@ GISelValueTrackingPrinterPass::run(MachineFunction &MF,
         Register Reg = MO.getReg();
         if (!MRI.getType(Reg).isValid())
           continue;
-	KnownBits Known = VTA.getKnownBits(Reg);
+        KnownBits Known = VTA.getKnownBits(Reg);
         unsigned SignedBits = VTA.computeNumSignBits(Reg);
         OS << "  " << MO << " KnownBits:" << Known << " SignBits:" << SignedBits
            << '\n';

>From 0e4af4b314fbcdd7cf5325cb6d9e36cb82eef53f Mon Sep 17 00:00:00 2001
From: Pragyansh Chaturvedi <pragyansh.chaturvedi at canonical.com>
Date: Wed, 3 Sep 2025 12:18:05 +0530
Subject: [PATCH 06/10] [GlobalIsel] Add computeNumSignBitsImpl to
 GISelValueTracking

---
 .../llvm/CodeGen/GlobalISel/GISelValueTracking.h |  4 ++++
 .../CodeGen/GlobalISel/GISelValueTracking.cpp    | 16 +++++++++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GISelValueTracking.h b/llvm/include/llvm/CodeGen/GlobalISel/GISelValueTracking.h
index 490d1a34cc846..01898cd853714 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GISelValueTracking.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GISelValueTracking.h
@@ -70,6 +70,10 @@ class LLVM_ABI GISelValueTracking : public GISelChangeObserver {
                                     const APInt &DemandedElts,
                                     unsigned Depth = 0);
 
+  virtual unsigned computeNumSignBitsImpl(Register R,
+                                          const APInt &DemandedElts,
+                                          unsigned Depth = 0);
+
   unsigned computeNumSignBits(Register R, const APInt &DemandedElts,
                               unsigned Depth = 0);
   unsigned computeNumSignBits(Register R, unsigned Depth = 0);
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index df34fda47eed8..19eb0e591e070 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1789,7 +1789,7 @@ static unsigned computeNumSignBitsFromRangeMetadata(const GAnyLoad *Ld,
                   CR.getSignedMax().getNumSignBits());
 }
 
-unsigned GISelValueTracking::computeNumSignBits(Register R,
+unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
                                                 const APInt &DemandedElts,
                                                 unsigned Depth) {
   MachineInstr &MI = *MRI.getVRegDef(R);
@@ -2063,14 +2063,20 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
   return std::max(FirstAnswer, Mask.countl_one());
 }
 
+unsigned GISelValueTracking::computeNumSignBits(Register R,
+                                                const APInt &DemandedElts,
+                                                unsigned Depth) {
+  assert(ComputeKnownBitsCache.empty() && "Cache should be empty");
+  unsigned NumSignBits = computeNumSignBitsImpl(R, DemandedElts, Depth);
+  ComputeKnownBitsCache.clear();
+  return NumSignBits;
+}
+
 unsigned GISelValueTracking::computeNumSignBits(Register R, unsigned Depth) {
   LLT Ty = MRI.getType(R);
   APInt DemandedElts =
       Ty.isFixedVector() ? APInt::getAllOnes(Ty.getNumElements()) : APInt(1, 1);
-  assert(ComputeKnownBitsCache.empty() && "Cache should be empty");
-  unsigned numSignBits = computeNumSignBits(R, DemandedElts, Depth);
-  ComputeKnownBitsCache.clear();
-  return numSignBits;
+  return computeNumSignBits(R, DemandedElts, Depth);
 }
 
 std::optional<ConstantRange> GISelValueTracking::getValidShiftAmountRange(

>From d930634501f41c745c97af0b84569afa6a80b585 Mon Sep 17 00:00:00 2001
From: Pragyansh Chaturvedi <pragyansh.chaturvedi at canonical.com>
Date: Wed, 3 Sep 2025 13:28:09 +0530
Subject: [PATCH 07/10] [GlobalISel] Update aarch64-smull.ll test

---
 llvm/test/CodeGen/AArch64/aarch64-smull.ll | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/aarch64-smull.ll b/llvm/test/CodeGen/AArch64/aarch64-smull.ll
index 6e5c666bdbc75..52cb13b1d9f30 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-smull.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-smull.ll
@@ -249,10 +249,20 @@ define <2 x i64> @smull_zext_v2i32_v2i64(ptr %A, ptr %B) nounwind {
 ; CHECK-GI-NEXT:    movi d0, #0x00ffff0000ffff
 ; CHECK-GI-NEXT:    mov v1.s[1], v2.s[0]
 ; CHECK-GI-NEXT:    and v0.8b, v1.8b, v0.8b
-; CHECK-GI-NEXT:    mov v1.s[0], v0.s[0]
-; CHECK-GI-NEXT:    mov v1.s[1], v0.s[1]
+; CHECK-GI-NEXT:    mov w8, v0.s[0]
+; CHECK-GI-NEXT:    mov w9, v0.s[1]
 ; CHECK-GI-NEXT:    ldr d0, [x1]
-; CHECK-GI-NEXT:    smull v0.2d, v1.2s, v0.2s
+; CHECK-GI-NEXT:    sshll v0.2d, v0.2s, #0
+; CHECK-GI-NEXT:    fmov d1, x8
+; CHECK-GI-NEXT:    fmov x11, d0
+; CHECK-GI-NEXT:    mov v1.d[1], x9
+; CHECK-GI-NEXT:    mov x9, v0.d[1]
+; CHECK-GI-NEXT:    fmov x10, d1
+; CHECK-GI-NEXT:    mov x8, v1.d[1]
+; CHECK-GI-NEXT:    mul x10, x10, x11
+; CHECK-GI-NEXT:    mul x8, x8, x9
+; CHECK-GI-NEXT:    fmov d0, x10
+; CHECK-GI-NEXT:    mov v0.d[1], x8
 ; CHECK-GI-NEXT:    ret
   %load.A = load <2 x i16>, ptr %A
   %load.B = load <2 x i32>, ptr %B

>From cdd97df17d8a162f4827880dfa8b853af56647ab Mon Sep 17 00:00:00 2001
From: Pragyansh Chaturvedi <pragyansh.chaturvedi at canonical.com>
Date: Thu, 4 Sep 2025 14:41:10 +0530
Subject: [PATCH 08/10] [GlobalISel] Replace relevant occurences of
 computeNumSignBits to computeNumSignBitsImpl

---
 .../CodeGen/GlobalISel/GISelValueTracking.cpp | 30 +++++++++----------
 llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp |  6 ++--
 2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 19eb0e591e070..a148211934bbf 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -701,7 +701,7 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
     Register SrcReg = MI.getOperand(1).getReg();
     computeKnownBitsImpl(SrcReg, Known, DemandedElts, Depth + 1);
     Known = Known.abs();
-    Known.Zero.setHighBits(computeNumSignBits(SrcReg, DemandedElts, Depth + 1) -
+    Known.Zero.setHighBits(computeNumSignBitsImpl(SrcReg, DemandedElts, Depth + 1) -
                            1);
     break;
   }
@@ -1756,10 +1756,10 @@ unsigned GISelValueTracking::computeNumSignBitsMin(Register Src0, Register Src1,
                                                    const APInt &DemandedElts,
                                                    unsigned Depth) {
   // Test src1 first, since we canonicalize simpler expressions to the RHS.
-  unsigned Src1SignBits = computeNumSignBits(Src1, DemandedElts, Depth);
+  unsigned Src1SignBits = computeNumSignBitsImpl(Src1, DemandedElts, Depth);
   if (Src1SignBits == 1)
     return 1;
-  return std::min(computeNumSignBits(Src0, DemandedElts, Depth), Src1SignBits);
+  return std::min(computeNumSignBitsImpl(Src0, DemandedElts, Depth), Src1SignBits);
 }
 
 /// Compute the known number of sign bits with attached range metadata in the
@@ -1821,7 +1821,7 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
     if (Src.getReg().isVirtual() && Src.getSubReg() == 0 &&
         MRI.getType(Src.getReg()).isValid()) {
       // Don't increment Depth for this one since we didn't do any work.
-      return computeNumSignBits(Src.getReg(), DemandedElts, Depth);
+      return computeNumSignBitsImpl(Src.getReg(), DemandedElts, Depth);
     }
 
     return 1;
@@ -1830,7 +1830,7 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
     Register Src = MI.getOperand(1).getReg();
     LLT SrcTy = MRI.getType(Src);
     unsigned Tmp = DstTy.getScalarSizeInBits() - SrcTy.getScalarSizeInBits();
-    return computeNumSignBits(Src, DemandedElts, Depth + 1) + Tmp;
+    return computeNumSignBitsImpl(Src, DemandedElts, Depth + 1) + Tmp;
   }
   case TargetOpcode::G_ASSERT_SEXT:
   case TargetOpcode::G_SEXT_INREG: {
@@ -1838,7 +1838,7 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
     Register Src = MI.getOperand(1).getReg();
     unsigned SrcBits = MI.getOperand(2).getImm();
     unsigned InRegBits = TyBits - SrcBits + 1;
-    return std::max(computeNumSignBits(Src, DemandedElts, Depth + 1),
+    return std::max(computeNumSignBitsImpl(Src, DemandedElts, Depth + 1),
                     InRegBits);
   }
   case TargetOpcode::G_LOAD: {
@@ -1883,11 +1883,11 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
   case TargetOpcode::G_XOR: {
     Register Src1 = MI.getOperand(1).getReg();
     unsigned Src1NumSignBits =
-        computeNumSignBits(Src1, DemandedElts, Depth + 1);
+        computeNumSignBitsImpl(Src1, DemandedElts, Depth + 1);
     if (Src1NumSignBits != 1) {
       Register Src2 = MI.getOperand(2).getReg();
       unsigned Src2NumSignBits =
-          computeNumSignBits(Src2, DemandedElts, Depth + 1);
+          computeNumSignBitsImpl(Src2, DemandedElts, Depth + 1);
       FirstAnswer = std::min(Src1NumSignBits, Src2NumSignBits);
     }
     break;
@@ -1895,7 +1895,7 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
   case TargetOpcode::G_ASHR: {
     Register Src1 = MI.getOperand(1).getReg();
     Register Src2 = MI.getOperand(2).getReg();
-    FirstAnswer = computeNumSignBits(Src1, DemandedElts, Depth + 1);
+    FirstAnswer = computeNumSignBitsImpl(Src1, DemandedElts, Depth + 1);
     if (auto C = getValidMinimumShiftAmount(Src2, DemandedElts, Depth + 1))
       FirstAnswer = std::min<uint64_t>(FirstAnswer + *C, TyBits);
     break;
@@ -1907,7 +1907,7 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
     // Check if the sign bits of source go down as far as the truncated value.
     unsigned DstTyBits = DstTy.getScalarSizeInBits();
     unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
-    unsigned NumSrcSignBits = computeNumSignBits(Src, DemandedElts, Depth + 1);
+    unsigned NumSrcSignBits = computeNumSignBitsImpl(Src, DemandedElts, Depth + 1);
     if (NumSrcSignBits > (NumSrcBits - DstTyBits))
       return NumSrcSignBits - (NumSrcBits - DstTyBits);
     break;
@@ -1967,7 +1967,7 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
         continue;
 
       unsigned Tmp2 =
-          computeNumSignBits(MO.getReg(), SingleDemandedElt, Depth + 1);
+          computeNumSignBitsImpl(MO.getReg(), SingleDemandedElt, Depth + 1);
       FirstAnswer = std::min(FirstAnswer, Tmp2);
 
       // If we don't know any bits, early out.
@@ -1989,7 +1989,7 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
           DemandedElts.extractBits(NumSubVectorElts, I * NumSubVectorElts);
       if (!DemandedSub)
         continue;
-      unsigned Tmp2 = computeNumSignBits(MO.getReg(), DemandedSub, Depth + 1);
+      unsigned Tmp2 = computeNumSignBitsImpl(MO.getReg(), DemandedSub, Depth + 1);
 
       FirstAnswer = std::min(FirstAnswer, Tmp2);
 
@@ -2010,13 +2010,13 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
       return 1;
 
     if (!!DemandedLHS)
-      FirstAnswer = computeNumSignBits(Src1, DemandedLHS, Depth + 1);
+      FirstAnswer = computeNumSignBitsImpl(Src1, DemandedLHS, Depth + 1);
     // If we don't know anything, early out and try computeKnownBits fall-back.
     if (FirstAnswer == 1)
       break;
     if (!!DemandedRHS) {
       unsigned Tmp2 =
-          computeNumSignBits(MI.getOperand(2).getReg(), DemandedRHS, Depth + 1);
+          computeNumSignBitsImpl(MI.getOperand(2).getReg(), DemandedRHS, Depth + 1);
       FirstAnswer = std::min(FirstAnswer, Tmp2);
     }
     break;
@@ -2024,7 +2024,7 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
   case TargetOpcode::G_SPLAT_VECTOR: {
     // Check if the sign bits of source go down as far as the truncated value.
     Register Src = MI.getOperand(1).getReg();
-    unsigned NumSrcSignBits = computeNumSignBits(Src, APInt(1, 1), Depth + 1);
+    unsigned NumSrcSignBits = computeNumSignBitsImpl(Src, APInt(1, 1), Depth + 1);
     unsigned NumSrcBits = MRI.getType(Src).getSizeInBits();
     if (NumSrcSignBits > (NumSrcBits - TyBits))
       return NumSrcSignBits - (NumSrcBits - TyBits);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index a28e272367c7a..365e47c97a177 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -6092,13 +6092,13 @@ unsigned AMDGPUTargetLowering::computeNumSignBitsForTargetInstr(
   case AMDGPU::G_AMDGPU_SMED3:
   case AMDGPU::G_AMDGPU_UMED3: {
     auto [Dst, Src0, Src1, Src2] = MI->getFirst4Regs();
-    unsigned Tmp2 = Analysis.computeNumSignBits(Src2, DemandedElts, Depth + 1);
+    unsigned Tmp2 = Analysis.computeNumSignBitsImpl(Src2, DemandedElts, Depth + 1);
     if (Tmp2 == 1)
       return 1;
-    unsigned Tmp1 = Analysis.computeNumSignBits(Src1, DemandedElts, Depth + 1);
+    unsigned Tmp1 = Analysis.computeNumSignBitsImpl(Src1, DemandedElts, Depth + 1);
     if (Tmp1 == 1)
       return 1;
-    unsigned Tmp0 = Analysis.computeNumSignBits(Src0, DemandedElts, Depth + 1);
+    unsigned Tmp0 = Analysis.computeNumSignBitsImpl(Src0, DemandedElts, Depth + 1);
     if (Tmp0 == 1)
       return 1;
     return std::min({Tmp0, Tmp1, Tmp2});

>From 3c82b86ad06def8918705e17a5813631b01b4201 Mon Sep 17 00:00:00 2001
From: Pragyansh Chaturvedi <pragyansh.chaturvedi at canonical.com>
Date: Fri, 5 Sep 2025 04:13:19 +0530
Subject: [PATCH 09/10] [GlobalISel] Fix depth for calling computeKnownBitsImpl
 in computeNumSignBitsImpl

---
 .../CodeGen/GlobalISel/GISelValueTracking.cpp    |  2 +-
 llvm/test/CodeGen/AArch64/aarch64-smull.ll       | 16 +++-------------
 2 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index a148211934bbf..525a361c267d7 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -2046,7 +2046,7 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
   // Finally, if we can prove that the top bits of the result are 0's or 1's,
   // use this information.
   KnownBits Known;
-  computeKnownBitsImpl(R, Known, DemandedElts, Depth + 1);
+  computeKnownBitsImpl(R, Known, DemandedElts, Depth);
   APInt Mask;
   if (Known.isNonNegative()) { // sign bit is 0
     Mask = Known.Zero;
diff --git a/llvm/test/CodeGen/AArch64/aarch64-smull.ll b/llvm/test/CodeGen/AArch64/aarch64-smull.ll
index 52cb13b1d9f30..6e5c666bdbc75 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-smull.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-smull.ll
@@ -249,20 +249,10 @@ define <2 x i64> @smull_zext_v2i32_v2i64(ptr %A, ptr %B) nounwind {
 ; CHECK-GI-NEXT:    movi d0, #0x00ffff0000ffff
 ; CHECK-GI-NEXT:    mov v1.s[1], v2.s[0]
 ; CHECK-GI-NEXT:    and v0.8b, v1.8b, v0.8b
-; CHECK-GI-NEXT:    mov w8, v0.s[0]
-; CHECK-GI-NEXT:    mov w9, v0.s[1]
+; CHECK-GI-NEXT:    mov v1.s[0], v0.s[0]
+; CHECK-GI-NEXT:    mov v1.s[1], v0.s[1]
 ; CHECK-GI-NEXT:    ldr d0, [x1]
-; CHECK-GI-NEXT:    sshll v0.2d, v0.2s, #0
-; CHECK-GI-NEXT:    fmov d1, x8
-; CHECK-GI-NEXT:    fmov x11, d0
-; CHECK-GI-NEXT:    mov v1.d[1], x9
-; CHECK-GI-NEXT:    mov x9, v0.d[1]
-; CHECK-GI-NEXT:    fmov x10, d1
-; CHECK-GI-NEXT:    mov x8, v1.d[1]
-; CHECK-GI-NEXT:    mul x10, x10, x11
-; CHECK-GI-NEXT:    mul x8, x8, x9
-; CHECK-GI-NEXT:    fmov d0, x10
-; CHECK-GI-NEXT:    mov v0.d[1], x8
+; CHECK-GI-NEXT:    smull v0.2d, v1.2s, v0.2s
 ; CHECK-GI-NEXT:    ret
   %load.A = load <2 x i16>, ptr %A
   %load.B = load <2 x i32>, ptr %B

>From dbda57f5d20109b6368efc1bb4729dd6bbc2c219 Mon Sep 17 00:00:00 2001
From: Pragyansh Chaturvedi <pragyansh.chaturvedi at canonical.com>
Date: Fri, 5 Sep 2025 12:38:07 +0530
Subject: [PATCH 10/10] [GlobalISel] clang-format

---
 .../CodeGen/GlobalISel/GISelValueTracking.h   |  3 +--
 .../CodeGen/GlobalISel/GISelValueTracking.cpp | 24 +++++++++++--------
 llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp |  9 ++++---
 3 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GISelValueTracking.h b/llvm/include/llvm/CodeGen/GlobalISel/GISelValueTracking.h
index 01898cd853714..17fcb91d783ac 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GISelValueTracking.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GISelValueTracking.h
@@ -70,8 +70,7 @@ class LLVM_ABI GISelValueTracking : public GISelChangeObserver {
                                     const APInt &DemandedElts,
                                     unsigned Depth = 0);
 
-  virtual unsigned computeNumSignBitsImpl(Register R,
-                                          const APInt &DemandedElts,
+  virtual unsigned computeNumSignBitsImpl(Register R, const APInt &DemandedElts,
                                           unsigned Depth = 0);
 
   unsigned computeNumSignBits(Register R, const APInt &DemandedElts,
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 525a361c267d7..7cfb86b5e61c9 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -701,8 +701,8 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
     Register SrcReg = MI.getOperand(1).getReg();
     computeKnownBitsImpl(SrcReg, Known, DemandedElts, Depth + 1);
     Known = Known.abs();
-    Known.Zero.setHighBits(computeNumSignBitsImpl(SrcReg, DemandedElts, Depth + 1) -
-                           1);
+    Known.Zero.setHighBits(
+        computeNumSignBitsImpl(SrcReg, DemandedElts, Depth + 1) - 1);
     break;
   }
   }
@@ -1759,7 +1759,8 @@ unsigned GISelValueTracking::computeNumSignBitsMin(Register Src0, Register Src1,
   unsigned Src1SignBits = computeNumSignBitsImpl(Src1, DemandedElts, Depth);
   if (Src1SignBits == 1)
     return 1;
-  return std::min(computeNumSignBitsImpl(Src0, DemandedElts, Depth), Src1SignBits);
+  return std::min(computeNumSignBitsImpl(Src0, DemandedElts, Depth),
+                  Src1SignBits);
 }
 
 /// Compute the known number of sign bits with attached range metadata in the
@@ -1790,8 +1791,8 @@ static unsigned computeNumSignBitsFromRangeMetadata(const GAnyLoad *Ld,
 }
 
 unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
-                                                const APInt &DemandedElts,
-                                                unsigned Depth) {
+                                                    const APInt &DemandedElts,
+                                                    unsigned Depth) {
   MachineInstr &MI = *MRI.getVRegDef(R);
   unsigned Opcode = MI.getOpcode();
 
@@ -1907,7 +1908,8 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
     // Check if the sign bits of source go down as far as the truncated value.
     unsigned DstTyBits = DstTy.getScalarSizeInBits();
     unsigned NumSrcBits = SrcTy.getScalarSizeInBits();
-    unsigned NumSrcSignBits = computeNumSignBitsImpl(Src, DemandedElts, Depth + 1);
+    unsigned NumSrcSignBits =
+        computeNumSignBitsImpl(Src, DemandedElts, Depth + 1);
     if (NumSrcSignBits > (NumSrcBits - DstTyBits))
       return NumSrcSignBits - (NumSrcBits - DstTyBits);
     break;
@@ -1989,7 +1991,8 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
           DemandedElts.extractBits(NumSubVectorElts, I * NumSubVectorElts);
       if (!DemandedSub)
         continue;
-      unsigned Tmp2 = computeNumSignBitsImpl(MO.getReg(), DemandedSub, Depth + 1);
+      unsigned Tmp2 =
+          computeNumSignBitsImpl(MO.getReg(), DemandedSub, Depth + 1);
 
       FirstAnswer = std::min(FirstAnswer, Tmp2);
 
@@ -2015,8 +2018,8 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
     if (FirstAnswer == 1)
       break;
     if (!!DemandedRHS) {
-      unsigned Tmp2 =
-          computeNumSignBitsImpl(MI.getOperand(2).getReg(), DemandedRHS, Depth + 1);
+      unsigned Tmp2 = computeNumSignBitsImpl(MI.getOperand(2).getReg(),
+                                             DemandedRHS, Depth + 1);
       FirstAnswer = std::min(FirstAnswer, Tmp2);
     }
     break;
@@ -2024,7 +2027,8 @@ unsigned GISelValueTracking::computeNumSignBitsImpl(Register R,
   case TargetOpcode::G_SPLAT_VECTOR: {
     // Check if the sign bits of source go down as far as the truncated value.
     Register Src = MI.getOperand(1).getReg();
-    unsigned NumSrcSignBits = computeNumSignBitsImpl(Src, APInt(1, 1), Depth + 1);
+    unsigned NumSrcSignBits =
+        computeNumSignBitsImpl(Src, APInt(1, 1), Depth + 1);
     unsigned NumSrcBits = MRI.getType(Src).getSizeInBits();
     if (NumSrcSignBits > (NumSrcBits - TyBits))
       return NumSrcSignBits - (NumSrcBits - TyBits);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index 365e47c97a177..91d96776ac347 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -6092,13 +6092,16 @@ unsigned AMDGPUTargetLowering::computeNumSignBitsForTargetInstr(
   case AMDGPU::G_AMDGPU_SMED3:
   case AMDGPU::G_AMDGPU_UMED3: {
     auto [Dst, Src0, Src1, Src2] = MI->getFirst4Regs();
-    unsigned Tmp2 = Analysis.computeNumSignBitsImpl(Src2, DemandedElts, Depth + 1);
+    unsigned Tmp2 =
+        Analysis.computeNumSignBitsImpl(Src2, DemandedElts, Depth + 1);
     if (Tmp2 == 1)
       return 1;
-    unsigned Tmp1 = Analysis.computeNumSignBitsImpl(Src1, DemandedElts, Depth + 1);
+    unsigned Tmp1 =
+        Analysis.computeNumSignBitsImpl(Src1, DemandedElts, Depth + 1);
     if (Tmp1 == 1)
       return 1;
-    unsigned Tmp0 = Analysis.computeNumSignBitsImpl(Src0, DemandedElts, Depth + 1);
+    unsigned Tmp0 =
+        Analysis.computeNumSignBitsImpl(Src0, DemandedElts, Depth + 1);
     if (Tmp0 == 1)
       return 1;
     return std::min({Tmp0, Tmp1, Tmp2});



More information about the llvm-commits mailing list