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

Deepak Shirke via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 23 13:17:20 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/2] [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/2] [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:



More information about the llvm-commits mailing list