[llvm] 4afd874 - [GlobalISel] Add G_EXTRACT_SUBVECTOR to computeKnownBits (#214533)

via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 17 06:00:07 PDT 2026


Author: Deepak Shirke
Date: 2026-08-17T15:00:01+02:00
New Revision: 4afd874c4a51827a101bfcc0747f067f845d118b

URL: https://github.com/llvm/llvm-project/commit/4afd874c4a51827a101bfcc0747f067f845d118b
DIFF: https://github.com/llvm/llvm-project/commit/4afd874c4a51827a101bfcc0747f067f845d118b.diff

LOG: [GlobalISel] Add G_EXTRACT_SUBVECTOR to computeKnownBits (#214533)

Port the SDAG EXTRACT_SUBVECTOR computeKnownBits handling to GlobalISel.
Offsets the demanded elements by the subvector index to propagate known
bits from the source vector to the extracted subvector.

Part of #150515.

Added: 
    llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-subvector.mir

Modified: 
    llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
    llvm/test/CodeGen/AArch64/extract-subvec-combine.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index e5da97191c29e..8c41409812e3a 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1067,6 +1067,20 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
     }
     break;
   }
+  case TargetOpcode::G_EXTRACT_SUBVECTOR: {
+    Register SrcReg = MI.getOperand(1).getReg();
+    LLT SrcTy = MRI.getType(SrcReg);
+    APInt DemandedSrcElts;
+    if (SrcTy.isScalableVector()) {
+      DemandedSrcElts = APInt(1, 1);
+    } else {
+      uint64_t Idx = MI.getOperand(2).getImm();
+      unsigned NumSrcElts = SrcTy.getNumElements();
+      DemandedSrcElts = DemandedElts.zext(NumSrcElts).shl(Idx);
+    }
+    computeKnownBitsImpl(SrcReg, Known, DemandedSrcElts, Depth + 1);
+    break;
+  }
   case TargetOpcode::G_SHUFFLE_VECTOR: {
     APInt DemandedLHS, DemandedRHS;
     // Collect the known bits that are shared by every vector element referenced

diff  --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-subvector.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-subvector.mir
new file mode 100644
index 0000000000000..ddcb709232652
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-subvector.mir
@@ -0,0 +1,90 @@
+# NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple aarch64 -passes="print<gisel-value-tracking>" %s -filetype=null 2>&1 | FileCheck %s
+---
+# Extract subvector from constant vector - known bits propagate
+name: ExtractSubvector_Constant
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @ExtractSubvector_Constant
+  ; CHECK-NEXT: %0:_ KnownBits:0000000000001111 SignBits:12 IsKnownNeverZero:1
+  ; CHECK-NEXT: %1:_ KnownBits:0000000000000111 SignBits:13 IsKnownNeverZero:1
+  ; CHECK-NEXT: %2:_ KnownBits:0000000000000011 SignBits:14 IsKnownNeverZero:1
+  ; CHECK-NEXT: %3:_ KnownBits:0000000000000001 SignBits:15 IsKnownNeverZero:1
+  ; CHECK-NEXT: %4:_ KnownBits:0000000011111111 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %5:_ KnownBits:0000000000111111 SignBits:10 IsKnownNeverZero:1
+  ; CHECK-NEXT: %6:_ KnownBits:0000000000011111 SignBits:11 IsKnownNeverZero:1
+  ; CHECK-NEXT: %7:_ KnownBits:0000000001111111 SignBits:9 IsKnownNeverZero:1
+  ; CHECK-NEXT: %8:_ KnownBits:00000000???????1 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %9:_ KnownBits:000000000000???1 SignBits:12 IsKnownNeverZero:1
+    %0:_(i16) = G_CONSTANT i16 15
+    %1:_(i16) = G_CONSTANT i16 7
+    %2:_(i16) = G_CONSTANT i16 3
+    %3:_(i16) = G_CONSTANT i16 1
+    %4:_(i16) = G_CONSTANT i16 255
+    %5:_(i16) = G_CONSTANT i16 63
+    %6:_(i16) = G_CONSTANT i16 31
+    %7:_(i16) = G_CONSTANT i16 127
+    %8:_(<8 x i16>) = G_BUILD_VECTOR %0, %1, %2, %3, %4, %5, %6, %7
+    %9:_(<4 x i16>) = G_EXTRACT_SUBVECTOR %8, 0
+...
+---
+# Extract subvector with known zero high bits
+name: ExtractSubvector_KnownZero
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @ExtractSubvector_KnownZero
+  ; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %1:_ KnownBits:0000000011111111 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %2:_ KnownBits:0000000011111111 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %3:_ KnownBits:00000000???????? SignBits:8 IsKnownNeverZero:0
+  ; CHECK-NEXT: %4:_ KnownBits:00000000???????? SignBits:8 IsKnownNeverZero:0
+    %0:_(<8 x i16>) = COPY $q0
+    %1:_(i16) = G_CONSTANT i16 255
+    %2:_(<8 x i16>) = G_BUILD_VECTOR %1, %1, %1, %1, %1, %1, %1, %1
+    %3:_(<8 x i16>) = G_AND %0, %2
+    %4:_(<4 x i16>) = G_EXTRACT_SUBVECTOR %3, 0
+...
+---
+# Extract from non-zero index
+name: ExtractSubvector_HighIndex
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @ExtractSubvector_HighIndex
+  ; CHECK-NEXT: %0:_ KnownBits:0000000000001111 SignBits:12 IsKnownNeverZero:1
+  ; CHECK-NEXT: %1:_ KnownBits:0000000000000111 SignBits:13 IsKnownNeverZero:1
+  ; CHECK-NEXT: %2:_ KnownBits:0000000000000011 SignBits:14 IsKnownNeverZero:1
+  ; CHECK-NEXT: %3:_ KnownBits:0000000000000001 SignBits:15 IsKnownNeverZero:1
+  ; CHECK-NEXT: %4:_ KnownBits:0000000011111111 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %5:_ KnownBits:0000000000111111 SignBits:10 IsKnownNeverZero:1
+  ; CHECK-NEXT: %6:_ KnownBits:0000000000011111 SignBits:11 IsKnownNeverZero:1
+  ; CHECK-NEXT: %7:_ KnownBits:0000000001111111 SignBits:9 IsKnownNeverZero:1
+  ; CHECK-NEXT: %8:_ KnownBits:00000000???????1 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %9:_ KnownBits:00000000???11111 SignBits:8 IsKnownNeverZero:1
+    %0:_(i16) = G_CONSTANT i16 15
+    %1:_(i16) = G_CONSTANT i16 7
+    %2:_(i16) = G_CONSTANT i16 3
+    %3:_(i16) = G_CONSTANT i16 1
+    %4:_(i16) = G_CONSTANT i16 255
+    %5:_(i16) = G_CONSTANT i16 63
+    %6:_(i16) = G_CONSTANT i16 31
+    %7:_(i16) = G_CONSTANT i16 127
+    %8:_(<8 x i16>) = G_BUILD_VECTOR %0, %1, %2, %3, %4, %5, %6, %7
+    %9:_(<4 x i16>) = G_EXTRACT_SUBVECTOR %8, 4
+...
+---
+# Scalable vector - conservative known bits
+name: ExtractSubvector_Scalable
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @ExtractSubvector_Scalable
+  ; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %1:_ KnownBits:0000000011111111 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %2:_ KnownBits:0000000011111111 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %3:_ KnownBits:00000000???????? SignBits:8 IsKnownNeverZero:0
+  ; CHECK-NEXT: %4:_ KnownBits:00000000???????? SignBits:8 IsKnownNeverZero:0
+    %0:_(<vscale x 4 x i16>) = COPY $z0
+    %1:_(i16) = G_CONSTANT i16 255
+    %2:_(<vscale x 4 x i16>) = G_SPLAT_VECTOR %1
+    %3:_(<vscale x 4 x i16>) = G_AND %0, %2
+    %4:_(<vscale x 2 x i16>) = G_EXTRACT_SUBVECTOR %3, 0
+...

diff  --git a/llvm/test/CodeGen/AArch64/extract-subvec-combine.ll b/llvm/test/CodeGen/AArch64/extract-subvec-combine.ll
index 2779f535adc4b..ce6e3c0a32b38 100644
--- a/llvm/test/CodeGen/AArch64/extract-subvec-combine.ll
+++ b/llvm/test/CodeGen/AArch64/extract-subvec-combine.ll
@@ -3,18 +3,11 @@
 ; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
 
 define <2 x i32> @and_extract_zext_idx0(<4 x i16> %vec) nounwind {
-; CHECK-SD-LABEL: and_extract_zext_idx0:
-; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    ushll v0.4s, v0.4h, #0
-; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
-; CHECK-SD-NEXT:    ret
-;
-; CHECK-GI-LABEL: and_extract_zext_idx0:
-; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    movi d1, #0x00ffff0000ffff
-; CHECK-GI-NEXT:    ushll v0.4s, v0.4h, #0
-; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
-; CHECK-GI-NEXT:    ret
+; CHECK-LABEL: and_extract_zext_idx0:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ushll v0.4s, v0.4h, #0
+; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT:    ret
   %zext = zext <4 x i16> %vec to <4 x i32>
   %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 0)
   %and = and <2 x i32> %extract, <i32 65535, i32 65535>
@@ -41,19 +34,11 @@ define <4 x i16> @and_extract_sext_idx0(<8 x i8> %vec) nounwind {
 }
 
 define <2 x i32> @and_extract_zext_idx2(<4 x i16> %vec) nounwind {
-; CHECK-SD-LABEL: and_extract_zext_idx2:
-; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    ushll v0.4s, v0.4h, #0
-; CHECK-SD-NEXT:    mov d0, v0.d[1]
-; CHECK-SD-NEXT:    ret
-;
-; CHECK-GI-LABEL: and_extract_zext_idx2:
-; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    ushll v0.4s, v0.4h, #0
-; CHECK-GI-NEXT:    movi d1, #0x00ffff0000ffff
-; CHECK-GI-NEXT:    mov d0, v0.d[1]
-; CHECK-GI-NEXT:    and v0.8b, v0.8b, v1.8b
-; CHECK-GI-NEXT:    ret
+; CHECK-LABEL: and_extract_zext_idx2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ushll v0.4s, v0.4h, #0
+; CHECK-NEXT:    mov d0, v0.d[1]
+; CHECK-NEXT:    ret
   %zext = zext <4 x i16> %vec to <4 x i32>
   %extract = call <2 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %zext, i64 2)
   %and = and <2 x i32> %extract, <i32 65535, i32 65535>


        


More information about the llvm-commits mailing list