[llvm] ac8aca0 - [GlobalISel] Add KnownBits support for G_INSERT_SUBVECTOR (#215048)

via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 13 13:30:20 PDT 2026


Author: Yousef
Date: 2026-09-13T20:30:14Z
New Revision: ac8aca03372551f8a8c999e86e5cb6cbfae3e307

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

LOG: [GlobalISel] Add KnownBits support for G_INSERT_SUBVECTOR (#215048)

## Summary

Add KnownBits support for `G_INSERT_SUBVECTOR` in GlobalISel value
tracking.

The implementation splits the demanded elements between the original
vector and inserted subvector, ignores overwritten source elements, and
intersects the KnownBits information from the contributing operands.

Part of #150515.

## Testing

- `llvm-lit
llvm/test/CodeGen/AArch64/GlobalISel/knownbits-insert-subvector.mir`
- `llvm-lit llvm/test/CodeGen/AArch64/GlobalISel/knownbits-*.mir`
  - 40/40 passed

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

Modified: 
    llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
    llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 4cdbeeebc39bb..e608b1ff6bb67 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1061,6 +1061,43 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
     }
     break;
   }
+  case TargetOpcode::G_INSERT_SUBVECTOR: {
+    GInsertSubvector &Insert = cast<GInsertSubvector>(MI);
+    Register Src = Insert.getBigVec();
+    Register Sub = Insert.getSubVec();
+    uint64_t Idx = Insert.getIndexImm();
+    LLT SrcTy = MRI.getType(Src);
+    LLT SubTy = MRI.getType(Sub);
+    APInt DemandedSubElts;
+    APInt DemandedSrcElts;
+
+    if (SrcTy.isScalableVector()) {
+      DemandedSubElts = SubTy.isScalableVector()
+                            ? APInt(1, 1)
+                            : APInt::getAllOnes(SubTy.getNumElements());
+      DemandedSrcElts = APInt(1, 1);
+    } else {
+      unsigned NumSubElts = SubTy.getNumElements();
+      DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx);
+      DemandedSrcElts = DemandedElts;
+      DemandedSrcElts.clearBits(Idx, Idx + NumSubElts);
+    }
+
+    Known.setAllConflict();
+    if (!!DemandedSubElts) {
+      computeKnownBitsImpl(Sub, Known2, DemandedSubElts, Depth + 1);
+      Known = Known.intersectWith(Known2);
+      if (Known.isUnknown())
+        break;
+    }
+
+    if (!!DemandedSrcElts) {
+      computeKnownBitsImpl(Src, Known2, DemandedSrcElts, Depth + 1);
+      Known = Known.intersectWith(Known2);
+    }
+
+    break;
+  }
   case TargetOpcode::G_EXTRACT_SUBVECTOR: {
     Register SrcReg = MI.getOperand(1).getReg();
     LLT SrcTy = MRI.getType(SrcReg);

diff  --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-insert-subvector.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-insert-subvector.mir
new file mode 100644
index 0000000000000..7275f008368c5
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-insert-subvector.mir
@@ -0,0 +1,105 @@
+# 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>" -filetype=null %s 2>&1 | FileCheck %s
+
+---
+name: no_knownbits
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @no_knownbits
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %1:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %2:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+    %0:_(<4 x i8>) = COPY $s0
+    %1:_(<2 x i8>) = COPY $h1
+    %2:_(<4 x i8>) = G_INSERT_SUBVECTOR %0, %1, 2
+...
+---
+name: zext_insert_subvector
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @zext_insert_subvector
+  ; CHECK-NEXT: %0:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %1:_ KnownBits:???????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %src:_ KnownBits:00000000???????? SignBits:8 IsKnownNeverZero:0
+  ; CHECK-NEXT: %sub:_ KnownBits:00000000???????? SignBits:8 IsKnownNeverZero:0
+  ; CHECK-NEXT: %res:_ KnownBits:00000000???????? SignBits:8 IsKnownNeverZero:0
+    %0:_(<4 x i8>) = COPY $s0
+    %1:_(<2 x i8>) = COPY $h1
+    %src:_(<4 x i16>) = G_ZEXT %0
+    %sub:_(<2 x i16>) = G_ZEXT %1
+    %res:_(<4 x i16>) = G_INSERT_SUBVECTOR %src, %sub, 2
+...
+---
+name: overwritten_src_ignored
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @overwritten_src_ignored
+  ; CHECK-NEXT: %zero:_ KnownBits:0000000000000000 SignBits:16 IsKnownNeverZero:0
+  ; CHECK-NEXT: %bad0:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %bad1:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %src:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %sub:_ KnownBits:0000000000000000 SignBits:16 IsKnownNeverZero:0
+  ; CHECK-NEXT: %res:_ KnownBits:0000000000000000 SignBits:16 IsKnownNeverZero:0
+    %zero:_(s16) = G_CONSTANT i16 0
+    %bad0:_(s16) = COPY $h0
+    %bad1:_(s16) = COPY $h1
+
+    %src:_(<4 x i16>) = G_BUILD_VECTOR %zero, %zero, %bad0, %bad1
+    %sub:_(<2 x i16>) = G_BUILD_VECTOR %zero, %zero
+
+    %res:_(<4 x i16>) = G_INSERT_SUBVECTOR %src, %sub, 2
+...
+---
+name: intersect_src_and_sub
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @intersect_src_and_sub
+  ; CHECK-NEXT: %srcval:_ KnownBits:0000000011111111 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %subval:_ KnownBits:0000111111111111 SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %bad0:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %bad1:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %src:_ KnownBits:???????????????? SignBits:1 IsKnownNeverZero:0
+  ; CHECK-NEXT: %sub:_ KnownBits:0000111111111111 SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %res:_ KnownBits:0000????11111111 SignBits:4 IsKnownNeverZero:1
+    %srcval:_(s16) = G_CONSTANT i16 255
+    %subval:_(s16) = G_CONSTANT i16 4095
+    %bad0:_(s16) = COPY $h0
+    %bad1:_(s16) = COPY $h1
+
+    %src:_(<4 x i16>) = G_BUILD_VECTOR %srcval, %srcval, %bad0, %bad1
+    %sub:_(<2 x i16>) = G_BUILD_VECTOR %subval, %subval
+
+    %res:_(<4 x i16>) = G_INSERT_SUBVECTOR %src, %sub, 2
+...
+---
+name: scalable_src_scalable_sub
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @scalable_src_scalable_sub
+  ; CHECK-NEXT: %srcval:_ KnownBits:0000000011111111 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %subval:_ KnownBits:0000111111111111 SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %src:_ KnownBits:0000000011111111 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %sub:_ KnownBits:0000111111111111 SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %res:_ KnownBits:0000????11111111 SignBits:4 IsKnownNeverZero:1
+    %srcval:_(s16) = G_CONSTANT i16 255
+    %subval:_(s16) = G_CONSTANT i16 4095
+    %src:_(<vscale x 4 x i16>) = G_SPLAT_VECTOR %srcval
+    %sub:_(<vscale x 2 x i16>) = G_SPLAT_VECTOR %subval
+    %res:_(<vscale x 4 x i16>) = G_INSERT_SUBVECTOR %src, %sub, 2
+...
+---
+name: scalable_src_fixed_sub
+body: |
+  bb.0:
+  ; CHECK-LABEL: name: @scalable_src_fixed_sub
+  ; CHECK-NEXT: %srcval:_ KnownBits:0000000011111111 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %subval:_ KnownBits:0000111111111111 SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %src:_ KnownBits:0000000011111111 SignBits:8 IsKnownNeverZero:1
+  ; CHECK-NEXT: %sub:_ KnownBits:0000111111111111 SignBits:4 IsKnownNeverZero:1
+  ; CHECK-NEXT: %res:_ KnownBits:0000????11111111 SignBits:4 IsKnownNeverZero:1
+    %srcval:_(s16) = G_CONSTANT i16 255
+    %subval:_(s16) = G_CONSTANT i16 4095
+    %src:_(<vscale x 4 x i16>) = G_SPLAT_VECTOR %srcval
+    %sub:_(<2 x i16>) = G_BUILD_VECTOR %subval, %subval
+    %res:_(<vscale x 4 x i16>) = G_INSERT_SUBVECTOR %src, %sub, 2
+...

diff  --git a/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp
index 44c0406426587..7ac776a1f7a7e 100644
--- a/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp
@@ -180,3 +180,39 @@ TEST_F(AArch64GISelMITest, TestVectorMetadata) {
   Mask.flipAllBits();
   EXPECT_EQ(Mask.getZExtValue(), Res.Zero.getZExtValue());
 }
+
+TEST_F(AArch64GISelMITest, TestInsertSubvectorDemandedElts) {
+  setUp();
+  if (!TM)
+    GTEST_SKIP();
+
+  const LLT S16 = LLT::scalar(16);
+  const LLT V2S16 = LLT::fixed_vector(2, 16);
+  const LLT V4S16 = LLT::fixed_vector(4, 16);
+
+  Register C255 = B.buildConstant(S16, 255).getReg(0);
+  Register C4095 = B.buildConstant(S16, 4095).getReg(0);
+  Register Undef = B.buildUndef(S16).getReg(0);
+
+  auto Src = B.buildBuildVector(V4S16, {C255, C255, Undef, Undef});
+  auto Sub = B.buildBuildVector(V2S16, {C4095, Undef});
+  auto Insert = B.buildInsertSubvector(V4S16, Src, Sub, 2);
+
+  GISelValueTracking Info(*MF);
+
+  KnownBits SrcOnly = Info.getKnownBits(Insert.getReg(0), APInt(4, 0b0001));
+  EXPECT_EQ(APInt(16, 0xff00), SrcOnly.Zero);
+  EXPECT_EQ(APInt(16, 0x00ff), SrcOnly.One);
+
+  KnownBits SubOnly = Info.getKnownBits(Insert.getReg(0), APInt(4, 0b0100));
+  EXPECT_EQ(APInt(16, 0xf000), SubOnly.Zero);
+  EXPECT_EQ(APInt(16, 0x0fff), SubOnly.One);
+
+  KnownBits SrcAndSub = Info.getKnownBits(Insert.getReg(0), APInt(4, 0b0101));
+  EXPECT_EQ(APInt(16, 0xf000), SrcAndSub.Zero);
+  EXPECT_EQ(APInt(16, 0x00ff), SrcAndSub.One);
+
+  KnownBits UnknownSub = Info.getKnownBits(Insert.getReg(0), APInt(4, 0b1000));
+  EXPECT_TRUE(UnknownSub.Zero.isZero());
+  EXPECT_TRUE(UnknownSub.One.isZero());
+}


        


More information about the llvm-commits mailing list