[llvm] a9f4d3f - [GlobalISel] Add G_VECTOR_COMPRESS support of computeKnownBits & computeNumSignBits (#223967)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 21 06:05:06 PDT 2026
Author: Vikash Gupta
Date: 2026-09-21T18:34:59+05:30
New Revision: a9f4d3ff18c554d29bbabc546f9a9df0376701e0
URL: https://github.com/llvm/llvm-project/commit/a9f4d3ff18c554d29bbabc546f9a9df0376701e0
DIFF: https://github.com/llvm/llvm-project/commit/a9f4d3ff18c554d29bbabc546f9a9df0376701e0.diff
LOG: [GlobalISel] Add G_VECTOR_COMPRESS support of computeKnownBits & computeNumSignBits (#223967)
Port the value tracking for ISD::VECTOR_COMPRESS to the GlobalISel
G_VECTOR_COMPRESS. Each result lane is either a lane of the source or
the passthrough operand, so:
- KnownBits is the intersection of the source and passthrough and,
- the number of sign bits is the minimum of the two.
Added:
llvm/test/CodeGen/AArch64/GlobalISel/knownbits-vector-compress.mir
Modified:
llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 4f3de265bf543..95984afe36d3b 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1188,6 +1188,22 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
}
break;
}
+ case TargetOpcode::G_VECTOR_COMPRESS: {
+ // Each result lane is either a lane of the source vector or the passthru,
+ // so the known bits are those shared by both.
+ Register Vec = MI.getOperand(1).getReg();
+ Register PassThru = MI.getOperand(3).getReg();
+ computeKnownBitsImpl(PassThru, Known, DemandedElts, Depth + 1);
+ // If we don't know any bits, early out.
+ if (Known.isUnknown())
+ break;
+ // Compression can move any source lane to any result position, so all
+ // source lanes are demanded.
+ APInt DemandedSrcElts = APInt::getAllOnes(DemandedElts.getBitWidth());
+ computeKnownBitsImpl(Vec, Known2, DemandedSrcElts, Depth + 1);
+ Known = Known.intersectWith(Known2);
+ break;
+ }
case TargetOpcode::G_ABS: {
Register SrcReg = MI.getOperand(1).getReg();
computeKnownBitsImpl(SrcReg, Known, DemandedElts, Depth + 1);
@@ -2796,6 +2812,22 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
}
break;
}
+ case TargetOpcode::G_VECTOR_COMPRESS: {
+ // Each result lane is either a lane of the source vector or the passthru,
+ // so the number of sign bits is the minimum of the two.
+ Register Vec = MI.getOperand(1).getReg();
+ Register PassThru = MI.getOperand(3).getReg();
+ unsigned Tmp = computeNumSignBits(PassThru, DemandedElts, Depth + 1);
+ // If passthru contributes nothing, fall back to the KnownBits refinement.
+ if (Tmp == 1)
+ break;
+ // Compression can move any source lane to any result position, so all
+ // source lanes are demanded.
+ APInt DemandedSrcElts = APInt::getAllOnes(DemandedElts.getBitWidth());
+ unsigned Tmp2 = computeNumSignBits(Vec, DemandedSrcElts, Depth + 1);
+ FirstAnswer = std::min(Tmp, Tmp2);
+ break;
+ }
case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
GExtractVectorElement &Extract = cast<GExtractVectorElement>(MI);
Register InVec = Extract.getVectorReg();
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-vector-compress.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-vector-compress.mir
new file mode 100644
index 0000000000000..88bbee44f0355
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-vector-compress.mir
@@ -0,0 +1,83 @@
+# 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>" -filetype=null %s 2>&1 | FileCheck %s
+
+---
+# KnownBits: 0x00F0 and 0x0FF0 agree on the low/high zeros and bits 4..7, but
+# disagree on bits 8..11 -> those become unknown in the result.
+name: CompressKnownIntersect
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @CompressKnownIntersect
+ ; CHECK-NEXT: %0:_ KnownBits:00000000000000000000000011110000 SignBits:24 IsKnownNeverZero:1
+ ; CHECK-NEXT: %1:_ KnownBits:00000000000000000000000011110000 SignBits:24 IsKnownNeverZero:1
+ ; CHECK-NEXT: %2:_ KnownBits:00000000000000000000111111110000 SignBits:20 IsKnownNeverZero:1
+ ; CHECK-NEXT: %3:_ KnownBits:00000000000000000000111111110000 SignBits:20 IsKnownNeverZero:1
+ ; CHECK-NEXT: %4:_ KnownBits:? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %5:_ KnownBits:00000000000000000000????11110000 SignBits:20 IsKnownNeverZero:1
+ %0:_(s32) = G_CONSTANT i32 240
+ %1:_(<4 x s32>) = G_BUILD_VECTOR %0, %0, %0, %0
+ %2:_(s32) = G_CONSTANT i32 4080
+ %3:_(<4 x s32>) = G_BUILD_VECTOR %2, %2, %2, %2
+ %4:_(<4 x s1>) = G_IMPLICIT_DEF
+ %5:_(<4 x s32>) = G_VECTOR_COMPRESS %1, %4, %3
+...
+---
+# KnownBits: an unknown passthru forces the whole result to unknown, since any
+# result lane may come from the passthru.
+name: CompressPassthruUnknown
+body: |
+ bb.0:
+ liveins: $q0
+ ; CHECK-LABEL: name: @CompressPassthruUnknown
+ ; CHECK-NEXT: %0:_ KnownBits:00000000000000000000111111110000 SignBits:20 IsKnownNeverZero:1
+ ; CHECK-NEXT: %1:_ KnownBits:00000000000000000000111111110000 SignBits:20 IsKnownNeverZero:1
+ ; CHECK-NEXT: %2:_ KnownBits:???????????????????????????????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %3:_ KnownBits:? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %4:_ KnownBits:???????????????????????????????? SignBits:1 IsKnownNeverZero:0
+ %0:_(s32) = G_CONSTANT i32 4080
+ %1:_(<4 x s32>) = G_BUILD_VECTOR %0, %0, %0, %0
+ %2:_(<4 x s32>) = COPY $q0
+ %3:_(<4 x s1>) = G_IMPLICIT_DEF
+ %4:_(<4 x s32>) = G_VECTOR_COMPRESS %1, %3, %2
+...
+---
+# NumSignBits: both sources are sign-extended from 8 bits (25 sign bits each), so
+# the result has min(25,25)=25 sign bits -- information the intersected KnownBits
+# alone cannot recover (the two unknown signs
diff er).
+name: CompressSignBits
+body: |
+ bb.0:
+ liveins: $q0, $q1
+ ; CHECK-LABEL: name: @CompressSignBits
+ ; CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:25 IsKnownNeverZero:0
+ ; CHECK-NEXT: %2:_ KnownBits:???????????????????????????????? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %3:_ KnownBits:???????????????????????????????? SignBits:25 IsKnownNeverZero:0
+ ; CHECK-NEXT: %4:_ KnownBits:? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %5:_ KnownBits:???????????????????????????????? SignBits:25 IsKnownNeverZero:0
+ %0:_(<4 x s32>) = COPY $q0
+ %1:_(<4 x s32>) = G_SEXT_INREG %0, 8
+ %2:_(<4 x s32>) = COPY $q1
+ %3:_(<4 x s32>) = G_SEXT_INREG %2, 8
+ %4:_(<4 x s1>) = G_IMPLICIT_DEF
+ %5:_(<4 x s32>) = G_VECTOR_COMPRESS %1, %4, %3
+...
+---
+# Scalable-vector path: same intersection, per lane.
+name: CompressScalable
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: @CompressScalable
+ ; CHECK-NEXT: %0:_ KnownBits:00000000000000000000000011110000 SignBits:24 IsKnownNeverZero:1
+ ; CHECK-NEXT: %1:_ KnownBits:00000000000000000000000011110000 SignBits:24 IsKnownNeverZero:1
+ ; CHECK-NEXT: %2:_ KnownBits:00000000000000000000111111110000 SignBits:20 IsKnownNeverZero:1
+ ; CHECK-NEXT: %3:_ KnownBits:00000000000000000000111111110000 SignBits:20 IsKnownNeverZero:1
+ ; CHECK-NEXT: %4:_ KnownBits:? SignBits:1 IsKnownNeverZero:0
+ ; CHECK-NEXT: %5:_ KnownBits:00000000000000000000????11110000 SignBits:20 IsKnownNeverZero:1
+ %0:_(s32) = G_CONSTANT i32 240
+ %1:_(<vscale x 4 x s32>) = G_SPLAT_VECTOR %0
+ %2:_(s32) = G_CONSTANT i32 4080
+ %3:_(<vscale x 4 x s32>) = G_SPLAT_VECTOR %2
+ %4:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF
+ %5:_(<vscale x 4 x s32>) = G_VECTOR_COMPRESS %1, %4, %3
+...
More information about the llvm-commits
mailing list