[llvm] [GlobalISel] Add G_EXTRACT_VECTOR_ELT to computeNumSignBits (PR #218283)

Deepak Shirke via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 24 01:12:42 PDT 2026


https://github.com/deepakshirkem updated https://github.com/llvm/llvm-project/pull/218283

>From b1c35444100c352a008b1414d96b8a4a23b73d21 Mon Sep 17 00:00:00 2001
From: deepakshirkem <deepakshirke509 at gmail.com>
Date: Mon, 24 Aug 2026 01:20:42 +0530
Subject: [PATCH 1/3] [GlobalISel] Add G_EXTRACT_VECTOR_ELT to
 computeNumSignBits

Port the SDAG EXTRACT_VECTOR_ELT computeNumSignBits handling to GlobalISel.
If the element index is known, demand only that element from the source
vector. If unknown, conservatively demand all elements.
---
 .../CodeGen/GlobalISel/GISelValueTracking.cpp |  15 +++
 .../GlobalISel/knownbits-extract-vector.mir   | 105 ++++++++++++------
 2 files changed, 83 insertions(+), 37 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 0672cfffc6eac..1674c98f40ffa 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -2669,6 +2669,21 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
     }
     break;
   }
+  case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
+    GExtractVectorElement &Extract = cast<GExtractVectorElement>(MI);
+    Register InVec = Extract.getVectorReg();
+    Register EltNo = Extract.getIndexReg();
+    LLT VecVT = MRI.getType(InVec);
+    if (VecVT.isScalableVector())
+      break;
+    unsigned NumSrcElts = VecVT.getNumElements();
+    auto ConstEltNo = getIConstantVRegVal(EltNo, MRI);
+    APInt DemandedSrcElts = APInt::getAllOnes(NumSrcElts);
+    if (ConstEltNo && ConstEltNo->ult(NumSrcElts))
+      DemandedSrcElts =
+          APInt::getOneBitSet(NumSrcElts, ConstEltNo->getZExtValue());
+    return computeNumSignBits(InVec, DemandedSrcElts, Depth + 1);
+  }
   case TargetOpcode::G_EXTRACT_SUBVECTOR: {
     // Offset the demanded elts by the subvector index.
     Register SrcReg = MI.getOperand(1).getReg();
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-vector.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-vector.mir
index 7ff593f18adc9..23084e288ac53 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-vector.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-vector.mir
@@ -6,11 +6,11 @@ name: all_knownbits_const_idx
 body: |
   bb.0:
   ; CHECK-LABEL: name: @all_knownbits_const_idx
-  ; CHECK-NEXT: %0:_ KnownBits:00000011 SignBits:6
-  ; CHECK-NEXT: %1:_ KnownBits:00001010 SignBits:4
-  ; CHECK-NEXT: %2:_ KnownBits:0000?01? SignBits:4
-  ; CHECK-NEXT: %idx:_ KnownBits:0000000000000000000000000000000000000000000000000000000000000001 SignBits:63
-  ; CHECK-NEXT: %4:_ KnownBits:00001010 SignBits:4
+  ; CHECK-NEXT: %0:_ KnownBits:00000011 SignBits:6 IsKnownNeverZero:1
+  ; CHECK-NEXT: %1:_ KnownBits:00001010 SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %2:_ KnownBits:0000?01? SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %idx:_ KnownBits:0000000000000000000000000000000000000000000000000000000000000001 SignBits:63 IsKnownNeverZero:1
+  ; CHECK-NEXT: %4:_ KnownBits:00001010 SignBits:4 IsKnownNeverZero:1
     %0:_(i8) = G_CONSTANT i8 3
     %1:_(i8) = G_CONSTANT i8 10
     %2:_(<2 x i8>) = G_BUILD_VECTOR %0, %1
@@ -22,11 +22,11 @@ name: all_knownbits
 body: |
   bb.0:
   ; CHECK-LABEL: name: @all_knownbits
-  ; CHECK-NEXT: %0:_ KnownBits:00000011 SignBits:6
-  ; CHECK-NEXT: %1:_ KnownBits:00001010 SignBits:4
-  ; CHECK-NEXT: %2:_ KnownBits:0000?01? SignBits:4
-  ; CHECK-NEXT: %idx:_ KnownBits:???????????????????????????????????????????????????????????????? SignBits:1
-  ; CHECK-NEXT: %4:_ KnownBits:0000?01? SignBits:4
+  ; CHECK-NEXT: %0:_ KnownBits:00000011 SignBits:6 IsKnownNeverZero:1
+  ; CHECK-NEXT: %1:_ KnownBits:00001010 SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %2:_ KnownBits:0000?01? SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %idx:_ KnownBits:???????????????????????????????????????????????????????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %4:_ KnownBits:0000?01? SignBits:4 IsKnownNeverZero:1
     %0:_(i8) = G_CONSTANT i8 3
     %1:_(i8) = G_CONSTANT i8 10
     %2:_(<2 x i8>) = G_BUILD_VECTOR %0, %1
@@ -38,9 +38,9 @@ name: no_knownbits_const_idx
 body: |
   bb.0:
   ; CHECK-LABEL: name: @no_knownbits_const_idx
-  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
-  ; CHECK-NEXT: %idx:_ KnownBits:0000000000000000000000000000000000000000000000000000000000000001 SignBits:63
-  ; CHECK-NEXT: %2:_ KnownBits:???????? SignBits:1
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %idx:_ KnownBits:0000000000000000000000000000000000000000000000000000000000000001 SignBits:63 IsKnownNeverZero:1
+  ; CHECK-NEXT: %2:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
     %0:_(<2 x i8>) = COPY $h0
     %idx:_(i64) = G_CONSTANT i64 1
     %1:_(i8) = G_EXTRACT_VECTOR_ELT %0, %idx
@@ -50,9 +50,9 @@ name: no_knownbits
 body: |
   bb.0:
   ; CHECK-LABEL: name: @no_knownbits
-  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
-  ; CHECK-NEXT: %idx:_ KnownBits:???????????????????????????????????????????????????????????????? SignBits:1
-  ; CHECK-NEXT: %2:_ KnownBits:???????? SignBits:1
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %idx:_ KnownBits:???????????????????????????????????????????????????????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %2:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
     %0:_(<2 x i8>) = COPY $h0
     %idx:_(i64) = COPY $d1
     %1:_(i8) = G_EXTRACT_VECTOR_ELT %0, %idx
@@ -62,10 +62,10 @@ name: zext_const_idx
 body: |
   bb.0:
   ; CHECK-LABEL: name: @zext_const_idx
-  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
-  ; CHECK-NEXT: %zext0:_ KnownBits:00000000???????? SignBits:8
-  ; CHECK-NEXT: %idx:_ KnownBits:0000000000000000000000000000000000000000000000000000000000000001 SignBits:63
-  ; CHECK-NEXT: %3:_ KnownBits:00000000???????? SignBits:8
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %zext0:_ KnownBits:00000000???????? SignBits:8 IsKnownNeverZero:0
+  ; CHECK-NEXT: %idx:_ KnownBits:0000000000000000000000000000000000000000000000000000000000000001 SignBits:63 IsKnownNeverZero:1
+  ; CHECK-NEXT: %3:_ KnownBits:00000000???????? SignBits:8 IsKnownNeverZero:0
     %0:_(<2 x i8>) = COPY $h0
     %zext0:_(<2 x i16>) = G_ZEXT %0
     %idx:_(i64) = G_CONSTANT i64 1
@@ -77,10 +77,10 @@ body: |
   bb.0:
 
   ; CHECK-LABEL: name: @zext
-  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
-  ; CHECK-NEXT: %zext0:_ KnownBits:00000000???????? SignBits:8
-  ; CHECK-NEXT: %idx:_ KnownBits:???????????????????????????????????????????????????????????????? SignBits:1
-  ; CHECK-NEXT: %3:_ KnownBits:00000000???????? SignBits:8
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %zext0:_ KnownBits:00000000???????? SignBits:8 IsKnownNeverZero:0
+  ; CHECK-NEXT: %idx:_ KnownBits:???????????????????????????????????????????????????????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %3:_ KnownBits:00000000???????? SignBits:8 IsKnownNeverZero:0
     %0:_(<2 x i8>) = COPY $h0
     %zext0:_(<2 x i16>) = G_ZEXT %0
     %idx:_(i64) = COPY $d1
@@ -91,10 +91,10 @@ name: sext_const_idx
 body: |
   bb.0:
   ; CHECK-LABEL: name: @sext_const_idx
-  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
-  ; CHECK-NEXT: %sext0:_ KnownBits:???????????????? SignBits:9
-  ; CHECK-NEXT: %idx:_ KnownBits:0000000000000000000000000000000000000000000000000000000000000001 SignBits:63
-  ; CHECK-NEXT: %3:_ KnownBits:???????????????? SignBits:1
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %sext0:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
+  ; CHECK-NEXT: %idx:_ KnownBits:0000000000000000000000000000000000000000000000000000000000000001 SignBits:63 IsKnownNeverZero:1
+  ; CHECK-NEXT: %3:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
     %0:_(<2 x i8>) = COPY $h0
     %sext0:_(<2 x i16>) = G_SEXT %0
     %idx:_(i64) = G_CONSTANT i64 1
@@ -105,10 +105,10 @@ name: sext
 body: |
   bb.0:
   ; CHECK-LABEL: name: @sext
-  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1
-  ; CHECK-NEXT: %sext0:_ KnownBits:???????????????? SignBits:9
-  ; CHECK-NEXT: %idx:_ KnownBits:???????????????????????????????????????????????????????????????? SignBits:1
-  ; CHECK-NEXT: %3:_ KnownBits:???????????????? SignBits:1
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %sext0:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
+  ; CHECK-NEXT: %idx:_ KnownBits:???????????????????????????????????????????????????????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %3:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
     %0:_(<2 x i8>) = COPY $h0
     %sext0:_(<2 x i16>) = G_SEXT %0
     %idx:_(i64) = COPY $d1
@@ -121,13 +121,44 @@ name: bail_on_different_return_type
 body: |
   bb.0:
   ; CHECK-LABEL: name: @bail_on_different_return_type
-  ; CHECK-NEXT: %0:_ KnownBits:00000011 SignBits:6
-  ; CHECK-NEXT: %1:_ KnownBits:00001010 SignBits:4
-  ; CHECK-NEXT: %2:_ KnownBits:0000?01? SignBits:4
-  ; CHECK-NEXT: %idx:_ KnownBits:0000000000000000000000000000000000000000000000000000000000000001 SignBits:63
-  ; CHECK-NEXT: %4:_ KnownBits:???????????????? SignBits:1
+  ; CHECK-NEXT: %0:_ KnownBits:00000011 SignBits:6 IsKnownNeverZero:1
+  ; CHECK-NEXT: %1:_ KnownBits:00001010 SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %2:_ KnownBits:0000?01? SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %idx:_ KnownBits:0000000000000000000000000000000000000000000000000000000000000001 SignBits:63 IsKnownNeverZero:1
+  ; CHECK-NEXT: %4:_ KnownBits:???????????????? SignBits:4 IsKnownNeverZero:1
     %0:_(i8) = G_CONSTANT i8 3
     %1:_(i8) = G_CONSTANT i8 10
     %2:_(<2 x i8>) = G_BUILD_VECTOR %0, %1
     %idx:_(i64) = G_CONSTANT i64 1
     %3:_(i16) = G_EXTRACT_VECTOR_ELT %2, %idx
+---
+# computeNumSignBits: sign bits propagate through G_EXTRACT_VECTOR_ELT
+name: signbits_known_idx
+body: |
+  bb.0:
+    %0:_(i8) = COPY $b0
+    %1:_(i16) = G_SEXT %0
+    %2:_(i16) = COPY $h1
+    %3:_(<4 x i16>) = G_BUILD_VECTOR %1, %1, %2, %1
+    %4:_(i64) = G_CONSTANT i64 0
+    %5:_(i16) = G_EXTRACT_VECTOR_ELT %3, %4
+    %6:_(i64) = G_CONSTANT i64 2
+    %7:_(i16) = G_EXTRACT_VECTOR_ELT %3, %6
+...
+---
+# computeNumSignBits: unknown index demands all elements
+name: signbits_unknown_idx
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @signbits_unknown_idx
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
+  ; CHECK-NEXT: %2:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
+  ; CHECK-NEXT: %3:_ KnownBits:???????????????????????????????????????????????????????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %4:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
+    %0:_(i8) = COPY $b0
+    %1:_(i16) = G_SEXT %0
+    %2:_(<4 x i16>) = G_BUILD_VECTOR %1, %1, %1, %1
+    %3:_(i64) = COPY $x0
+    %4:_(i16) = G_EXTRACT_VECTOR_ELT %2, %3
+...

>From 1d59085d41d72af4d27602d984afdd23fa8ea7bb Mon Sep 17 00:00:00 2001
From: deepakshirkem <deepakshirke509 at gmail.com>
Date: Mon, 24 Aug 2026 01:46:56 +0530
Subject: [PATCH 2/3] [AArch64] Update neon-extadd-extract tests for improved
 GlobalISel sign-bits

GlobalISel now correctly propagates sign bits through G_EXTRACT_VECTOR_ELT,
allowing it to use smull instead of mul for sign-extended vector extracts.
---
 llvm/test/CodeGen/AArch64/neon-extadd-extract.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/AArch64/neon-extadd-extract.ll b/llvm/test/CodeGen/AArch64/neon-extadd-extract.ll
index b35511dd4ab69..ae21d8f339dd3 100644
--- a/llvm/test/CodeGen/AArch64/neon-extadd-extract.ll
+++ b/llvm/test/CodeGen/AArch64/neon-extadd-extract.ll
@@ -683,7 +683,7 @@ define <1 x i64> @mulls_v2i32_0(<2 x i32> %s0, <2 x i32> %s1) {
 ; CHECK-GI-NEXT:    sshll v1.2d, v1.2s, #0
 ; CHECK-GI-NEXT:    fmov x8, d0
 ; CHECK-GI-NEXT:    fmov x9, d1
-; CHECK-GI-NEXT:    mul x8, x8, x9
+; CHECK-GI-NEXT:    smull x8, w8, w9
 ; CHECK-GI-NEXT:    fmov d0, x8
 ; CHECK-GI-NEXT:    ret
 entry:

>From 6a4afde6fdc4f841aeabd7de5afbbd111925a798 Mon Sep 17 00:00:00 2001
From: deepakshirkem <deepakshirke509 at gmail.com>
Date: Mon, 24 Aug 2026 13:42:24 +0530
Subject: [PATCH 3/3] Address review comments: handle scalable vectors and
 out-of-bounds index

- For scalable vectors, don't give up; demand the whole vector source
  instead of breaking early.
- Simplify DemandedSrcElts computation using a ternary expression.
- Add test coverage for out-of-bounds constant index and scalable
  vectors.
---
 .../CodeGen/GlobalISel/GISelValueTracking.cpp | 10 +++---
 .../GlobalISel/knownbits-extract-vector.mir   | 34 +++++++++++++++++++
 2 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 1674c98f40ffa..92903183349e2 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -2675,13 +2675,13 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
     Register EltNo = Extract.getIndexReg();
     LLT VecVT = MRI.getType(InVec);
     if (VecVT.isScalableVector())
-      break;
+      return computeNumSignBits(InVec, APInt(1, 1), Depth + 1);
     unsigned NumSrcElts = VecVT.getNumElements();
     auto ConstEltNo = getIConstantVRegVal(EltNo, MRI);
-    APInt DemandedSrcElts = APInt::getAllOnes(NumSrcElts);
-    if (ConstEltNo && ConstEltNo->ult(NumSrcElts))
-      DemandedSrcElts =
-          APInt::getOneBitSet(NumSrcElts, ConstEltNo->getZExtValue());
+    APInt DemandedSrcElts =
+        ConstEltNo && ConstEltNo->ult(NumSrcElts)
+            ? APInt::getOneBitSet(NumSrcElts, ConstEltNo->getZExtValue())
+            : APInt::getAllOnes(NumSrcElts);
     return computeNumSignBits(InVec, DemandedSrcElts, Depth + 1);
   }
   case TargetOpcode::G_EXTRACT_SUBVECTOR: {
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-vector.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-vector.mir
index 23084e288ac53..37a80d11b9c50 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-vector.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-vector.mir
@@ -162,3 +162,37 @@ body: |
     %3:_(i64) = COPY $x0
     %4:_(i16) = G_EXTRACT_VECTOR_ELT %2, %3
 ...
+---
+# computeNumSignBits: out of bounds constant index falls back to demanding all
+name: signbits_out_of_bounds_idx
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @signbits_out_of_bounds_idx
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
+  ; CHECK-NEXT: %2:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
+  ; CHECK-NEXT: %3:_ KnownBits:0000000000000000000000000000000000000000000000000000000000001010 SignBits:60 IsKnownNeverZero:1
+  ; CHECK-NEXT: %4:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
+    %0:_(i8) = COPY $b0
+    %1:_(i16) = G_SEXT %0
+    %2:_(<4 x i16>) = G_BUILD_VECTOR %1, %1, %1, %1
+    %3:_(i64) = G_CONSTANT i64 10
+    %4:_(i16) = G_EXTRACT_VECTOR_ELT %2, %3
+...
+---
+# computeNumSignBits: scalable vector demands whole source
+name: signbits_scalable
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @signbits_scalable
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
+  ; CHECK-NEXT: %2:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
+  ; CHECK-NEXT: %3:_ KnownBits:0000000000000000000000000000000000000000000000000000000000000000 SignBits:64 IsKnownNeverZero:0
+  ; CHECK-NEXT: %4:_ KnownBits:???????????????? SignBits:9 IsKnownNeverZero:0
+    %0:_(i8) = COPY $b0
+    %1:_(i16) = G_SEXT %0
+    %2:_(<vscale x 4 x i16>) = G_SPLAT_VECTOR %1
+    %3:_(i64) = G_CONSTANT i64 0
+    %4:_(i16) = G_EXTRACT_VECTOR_ELT %2, %3
+...



More information about the llvm-commits mailing list