[llvm] 5298e75 - [GlobalISel] Add G_EXTRACT_SUBVECTOR to computeNumSignBits (#216798)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 20 05:58:42 PDT 2026
Author: Deepak Shirke
Date: 2026-08-20T13:58:36+01:00
New Revision: 5298e757c1c95504e77dbe3f1585791d397c418f
URL: https://github.com/llvm/llvm-project/commit/5298e757c1c95504e77dbe3f1585791d397c418f
DIFF: https://github.com/llvm/llvm-project/commit/5298e757c1c95504e77dbe3f1585791d397c418f.diff
LOG: [GlobalISel] Add G_EXTRACT_SUBVECTOR to computeNumSignBits (#216798)
Port the SDAG EXTRACT_SUBVECTOR computeNumSignBits handling to
GlobalISel. Offsets the demanded elements by the subvector index to
propagate sign bits from the source vector to the extracted subvector.
For scalable vectors, conservatively demands all elements.
Part of #150515.
Added:
Modified:
llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-subvector.mir
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 f5b8cb3a0fbd7..0672cfffc6eac 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -2669,6 +2669,20 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
}
break;
}
+ case TargetOpcode::G_EXTRACT_SUBVECTOR: {
+ // Offset the demanded elts by the subvector index.
+ 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);
+ }
+ return computeNumSignBits(SrcReg, DemandedSrcElts, Depth + 1);
+ }
case TargetOpcode::G_SHUFFLE_VECTOR: {
// Collect the minimum number of sign bits that are shared by every vector
// element referenced by the shuffle.
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-subvector.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-subvector.mir
index ddcb709232652..6deea48cfa732 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-subvector.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-extract-subvector.mir
@@ -88,3 +88,54 @@ body: |
%3:_(<vscale x 4 x i16>) = G_AND %0, %2
%4:_(<vscale x 2 x i16>) = G_EXTRACT_SUBVECTOR %3, 0
...
+---
+---
+# computeNumSignBits: sign bits propagate through extract subvector
+# Tests both lower and upper half extraction
+name: ExtractSubvector_Sext
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @ExtractSubvector_Sext
+ ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:1 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
+ ; CHECK-NEXT: %5:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+ %0:_(i8) = COPY $b0
+ %1:_(i16) = COPY $h1
+ %2:_(i16) = G_SEXT %0
+ %3:_(<8 x i16>) = G_BUILD_VECTOR %2, %2, %2, %2, %2, %1, %2, %2
+ %4:_(<4 x i16>) = G_EXTRACT_SUBVECTOR %3, 0
+ %5:_(<4 x i16>) = G_EXTRACT_SUBVECTOR %3, 4
+...
+---
+# computeNumSignBits: unknown in lower half, extract upper half
+name: ExtractSubvector_Sext_HighIndex
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @ExtractSubvector_Sext_HighIndex
+ ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %1:_ KnownBits:???????????????? SignBits:1 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) = COPY $h1
+ %2:_(i16) = G_SEXT %0
+ %3:_(<8 x i16>) = G_BUILD_VECTOR %1, %1, %1, %1, %2, %2, %2, %2
+ %4:_(<4 x i16>) = G_EXTRACT_SUBVECTOR %3, 4
+...
+---
+# computeNumSignBits: scalable vector conservative
+name: ExtractSubvector_Sext_Scalable
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @ExtractSubvector_Sext_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
+ %0:_(<vscale x 4 x i8>) = COPY $z0
+ %1:_(<vscale x 4 x i16>) = G_SEXT %0
+ %2:_(<vscale x 2 x i16>) = G_EXTRACT_SUBVECTOR %1, 0
+...
diff --git a/llvm/test/CodeGen/AArch64/extract-subvec-combine.ll b/llvm/test/CodeGen/AArch64/extract-subvec-combine.ll
index ce6e3c0a32b38..f9bc0f61ac722 100644
--- a/llvm/test/CodeGen/AArch64/extract-subvec-combine.ll
+++ b/llvm/test/CodeGen/AArch64/extract-subvec-combine.ll
@@ -108,18 +108,11 @@ define <2 x i32> @sext_extract_zext_idx0_negtest(<4 x i16> %vec) nounwind {
}
define <4 x i16> @sext_extract_sext_idx0(<8 x i8> %vec) nounwind {
-; CHECK-SD-LABEL: sext_extract_sext_idx0:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: sshll v0.8h, v0.8b, #0
-; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: sext_extract_sext_idx0:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: sshll v0.8h, v0.8b, #0
-; CHECK-GI-NEXT: shl v0.4h, v0.4h, #8
-; CHECK-GI-NEXT: sshr v0.4h, v0.4h, #8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: sext_extract_sext_idx0:
+; CHECK: // %bb.0:
+; CHECK-NEXT: sshll v0.8h, v0.8b, #0
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
%sext = sext <8 x i8> %vec to <8 x i16>
%extract = call <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16> %sext, i64 0)
%sext_inreg_step0 = shl <4 x i16> %extract, <i16 8, i16 8, i16 8, i16 8>
@@ -149,19 +142,11 @@ define <2 x i32> @sext_extract_zext_idx2(<4 x i16> %vec) nounwind {
}
define <4 x i16> @sext_extract_sext_idx4(<8 x i8> %vec) nounwind {
-; CHECK-SD-LABEL: sext_extract_sext_idx4:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: sshll v0.8h, v0.8b, #0
-; CHECK-SD-NEXT: mov d0, v0.d[1]
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: sext_extract_sext_idx4:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: sshll v0.8h, v0.8b, #0
-; CHECK-GI-NEXT: mov d0, v0.d[1]
-; CHECK-GI-NEXT: shl v0.4h, v0.4h, #8
-; CHECK-GI-NEXT: sshr v0.4h, v0.4h, #8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: sext_extract_sext_idx4:
+; CHECK: // %bb.0:
+; CHECK-NEXT: sshll v0.8h, v0.8b, #0
+; CHECK-NEXT: mov d0, v0.d[1]
+; CHECK-NEXT: ret
%sext = sext <8 x i8> %vec to <8 x i16>
%extract = call <4 x i16> @llvm.vector.extract.v4i16.v8i16(<8 x i16> %sext, i64 4)
%sext_inreg_step0 = shl <4 x i16> %extract, <i16 8, i16 8, i16 8, i16 8>
More information about the llvm-commits
mailing list