[llvm] b46a51d - [GISel] Add operands check for G_INSERT_SUBVECTOR and G_EXTRACT_SUBVECTOR in buildInstr (#186021)

via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 28 02:24:53 PDT 2026


Author: Jianjian Guan
Date: 2026-04-28T17:24:48+08:00
New Revision: b46a51d9c29519666f70807b52301d94be804f07

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

LOG: [GISel] Add operands check for G_INSERT_SUBVECTOR and G_EXTRACT_SUBVECTOR in buildInstr (#186021)

Added: 
    

Modified: 
    llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
    llvm/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 63c9ada9b059d..f6f437638cb92 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -1434,6 +1434,65 @@ MachineIRBuilder::buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps,
            "Type mismatch");
     break;
   }
+  case TargetOpcode::G_INSERT_SUBVECTOR: {
+    assert(DstOps.size() == 1 && "Invalid Dst");
+    assert(SrcOps.size() == 3 && "Invalid Srcs");
+    LLT DstTy = DstOps[0].getLLTTy(*getMRI());
+    LLT BigVecTy = SrcOps[0].getLLTTy(*getMRI());
+    LLT SubVecTy = SrcOps[1].getLLTTy(*getMRI());
+    assert(DstTy == BigVecTy &&
+           "Dest and insert subvector source types must match!");
+    assert(DstTy.isVector() && SubVecTy.isVector() &&
+           "Insert subvector VTs must be vectors!");
+    assert(DstTy.getElementType() == SubVecTy.getElementType() &&
+           "Insert subvector VTs must have the same element type!");
+    assert((DstTy.isScalable() || !SubVecTy.isScalable()) &&
+           "Cannot insert a scalable vector into a fixed length vector!");
+    assert((DstTy.isScalable() != SubVecTy.isScalable() ||
+            DstTy.getElementCount().getKnownMinValue() >=
+                SubVecTy.getElementCount().getKnownMinValue()) &&
+           "Insert subvector must be from smaller vector to larger vector!");
+    assert(SrcOps[2].getSrcOpKind() == SrcOp::SrcType::Ty_Imm &&
+           "Insert subvector index must be constant");
+    assert((DstTy.isScalable() != SubVecTy.isScalable() ||
+            (SubVecTy.getElementCount().getKnownMinValue() +
+             (uint64_t)SrcOps[2].getImm()) <=
+                DstTy.getElementCount().getKnownMinValue()) &&
+           "Insert subvector overflow!");
+    assert((uint64_t)SrcOps[2].getImm() %
+                   SubVecTy.getElementCount().getKnownMinValue() ==
+               0 &&
+           "Insert index is not a multiple of the subvector length");
+    break;
+  }
+  case TargetOpcode::G_EXTRACT_SUBVECTOR: {
+    assert(DstOps.size() == 1 && "Invalid Dst");
+    assert(SrcOps.size() == 2 && "Invalid Srcs");
+    LLT DstTy = DstOps[0].getLLTTy(*getMRI());
+    LLT SrcVecTy = SrcOps[0].getLLTTy(*getMRI());
+    assert(DstTy.isVector() && SrcVecTy.isVector() &&
+           "Extract subvector VTs must be vectors!");
+    assert(DstTy.getElementType() == SrcVecTy.getElementType() &&
+           "Extract subvector VTs must have the same element type!");
+    assert((!DstTy.isScalable() || SrcVecTy.isScalable()) &&
+           "Cannot extract a scalable vector from a fixed length vector!");
+    assert((DstTy.isScalable() != SrcVecTy.isScalable() ||
+            DstTy.getElementCount().getKnownMinValue() <=
+                SrcVecTy.getElementCount().getKnownMinValue()) &&
+           "Extract subvector must be from larger vector to smaller vector!");
+    assert(SrcOps[1].getSrcOpKind() == SrcOp::SrcType::Ty_Imm &&
+           "Extract subvector index must be a constant");
+    assert((DstTy.isScalable() != SrcVecTy.isScalable() ||
+            (DstTy.getElementCount().getKnownMinValue() +
+             (uint64_t)SrcOps[1].getImm()) <=
+                SrcVecTy.getElementCount().getKnownMinValue()) &&
+           "Extract subvector overflow!");
+    assert((uint64_t)SrcOps[1].getImm() %
+                   DstTy.getElementCount().getKnownMinValue() ==
+               0 &&
+           "Extract index is not a multiple of the output vector length");
+    break;
+  }
   case TargetOpcode::G_BUILD_VECTOR: {
     assert((!SrcOps.empty() || SrcOps.size() < 2) &&
            "Must have at least 2 operands");

diff  --git a/llvm/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp b/llvm/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp
index c85e6d486e0ac..caff8ed761ab2 100644
--- a/llvm/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp
@@ -486,22 +486,112 @@ TEST_F(AArch64GISelMITest, BuildExtractSubvector) {
   if (!TM)
     GTEST_SKIP();
 
-  LLT VecTy = LLT::fixed_vector(4, 32);
-  LLT SubVecTy = LLT::fixed_vector(2, 32);
-  auto Vec = B.buildUndef(VecTy);
-  B.buildExtractSubvector(SubVecTy, Vec, 0);
+  LLT Vec4x32 = LLT::fixed_vector(4, 32);
+  LLT Vec2x32 = LLT::fixed_vector(2, 32);
+  LLT Vec2x64 = LLT::fixed_vector(2, 64);
+  LLT SVec4x32 = LLT::scalable_vector(4, 32);
+  LLT SVec2x32 = LLT::scalable_vector(2, 32);
 
-  VecTy = LLT::scalable_vector(4, 32);
-  SubVecTy = LLT::scalable_vector(2, 32);
-  Vec = B.buildUndef(VecTy);
-  B.buildExtractSubvector(SubVecTy, Vec, 0);
+  // Fixed-length: extract <2 x s32> from <4 x s32> at index 0.
+  auto BigVec = B.buildUndef(Vec4x32);
+  B.buildExtractSubvector(Vec2x32, BigVec, 0);
+
+  // Scalable: extract <vscale x 2 x s32> from <vscale x 4 x s32> at index 0.
+  auto SBigVec = B.buildUndef(SVec4x32);
+  B.buildExtractSubvector(SVec2x32, SBigVec, 0);
 
   auto CheckStr = R"(
   ; CHECK: [[DEF:%[0-9]+]]:_(<4 x s32>) = G_IMPLICIT_DEF
-  ; CHECK: [[EXTRACT_SUBVECTOR:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT_SUBVECTOR [[DEF]]:_(<4 x s32>), 0
-  ; CHECK: [[DEF1:%[0-9]+]]:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF
-  ; CHECK: [[EXTRACT_SUBVECTOR1:%[0-9]+]]:_(<vscale x 2 x s32>) = G_EXTRACT_SUBVECTOR [[DEF1]]:_(<vscale x 4 x s32>), 0
+  ; CHECK: [[EXTRACT:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT_SUBVECTOR [[DEF]]:_(<4 x s32>), 0
+  ; CHECK: [[SDEF:%[0-9]+]]:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF
+  ; CHECK: [[SEXTRACT:%[0-9]+]]:_(<vscale x 2 x s32>) = G_EXTRACT_SUBVECTOR [[SDEF]]:_(<vscale x 4 x s32>), 0
   )";
 
   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
+
+  // Different element types between result and source.
+  EXPECT_DEBUG_DEATH(B.buildExtractSubvector(Vec2x64, BigVec, 0),
+                     "Extract subvector VTs must have the same element type!");
+
+  // Cannot extract a scalable subvector from a fixed-length vector.
+  EXPECT_DEBUG_DEATH(
+      B.buildExtractSubvector(SVec2x32, BigVec, 0),
+      "Cannot extract a scalable vector from a fixed length vector!");
+
+  // Result must not be larger than the source.
+  EXPECT_DEBUG_DEATH(
+      B.buildExtractSubvector(Vec4x32, B.buildUndef(Vec2x32), 0),
+      "Extract subvector must be from larger vector to smaller vector!");
+
+  // Extraction index causes overflow (2 + 4 > 4).
+  EXPECT_DEBUG_DEATH(B.buildExtractSubvector(Vec2x32, BigVec, 4),
+                     "Extract subvector overflow!");
+
+  // Index must be a multiple of the result vector length (1 % 2 != 0).
+  EXPECT_DEBUG_DEATH(
+      B.buildExtractSubvector(Vec2x32, BigVec, 1),
+      "Extract index is not a multiple of the output vector length");
+}
+
+TEST_F(AArch64GISelMITest, BuildInsertSubvector) {
+  setUp();
+  if (!TM)
+    GTEST_SKIP();
+
+  LLT Vec4x32 = LLT::fixed_vector(4, 32);
+  LLT Vec2x32 = LLT::fixed_vector(2, 32);
+  LLT Vec2x64 = LLT::fixed_vector(2, 64);
+  LLT SVec4x32 = LLT::scalable_vector(4, 32);
+  LLT SVec2x32 = LLT::scalable_vector(2, 32);
+
+  // Fixed-length: insert <2 x s32> into <4 x s32> at index 0 and 2.
+  auto BigVec = B.buildUndef(Vec4x32);
+  auto SubVec = B.buildUndef(Vec2x32);
+  B.buildInsertSubvector(Vec4x32, BigVec, SubVec, 0);
+  B.buildInsertSubvector(Vec4x32, BigVec, SubVec, 2);
+
+  // Scalable: insert <vscale x 2 x s32> into <vscale x 4 x s32> at index 0.
+  auto SBigVec = B.buildUndef(SVec4x32);
+  auto SSubVec = B.buildUndef(SVec2x32);
+  B.buildInsertSubvector(SVec4x32, SBigVec, SSubVec, 0);
+
+  auto CheckStr = R"(
+  ; CHECK: [[DEF0:%[0-9]+]]:_(<4 x s32>) = G_IMPLICIT_DEF
+  ; CHECK: [[DEF1:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF
+  ; CHECK: {{%[0-9]+}}:_(<4 x s32>) = G_INSERT_SUBVECTOR [[DEF0]]:_, [[DEF1]]:_(<2 x s32>), 0
+  ; CHECK: {{%[0-9]+}}:_(<4 x s32>) = G_INSERT_SUBVECTOR [[DEF0]]:_, [[DEF1]]:_(<2 x s32>), 2
+  ; CHECK: [[SDEF0:%[0-9]+]]:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF
+  ; CHECK: [[SDEF1:%[0-9]+]]:_(<vscale x 2 x s32>) = G_IMPLICIT_DEF
+  ; CHECK: {{%[0-9]+}}:_(<vscale x 4 x s32>) = G_INSERT_SUBVECTOR [[SDEF0]]:_, [[SDEF1]]:_(<vscale x 2 x s32>), 0
+  )";
+
+  EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
+
+  // Dst type must match the BigVec (Src0) type.
+  EXPECT_DEBUG_DEATH(B.buildInsertSubvector(Vec2x32, BigVec, SubVec, 0),
+                     "Dest and insert subvector source types must match!");
+
+  // Different element types between dst and subvec.
+  EXPECT_DEBUG_DEATH(
+      B.buildInsertSubvector(Vec4x32, BigVec, B.buildUndef(Vec2x64), 0),
+      "Insert subvector VTs must have the same element type!");
+
+  // Cannot insert a scalable subvector into a fixed-length vector.
+  EXPECT_DEBUG_DEATH(
+      B.buildInsertSubvector(Vec4x32, BigVec, B.buildUndef(SVec2x32), 0),
+      "Cannot insert a scalable vector into a fixed length vector!");
+
+  // Subvector must not be larger than the destination.
+  EXPECT_DEBUG_DEATH(
+      B.buildInsertSubvector(Vec2x32, B.buildUndef(Vec2x32),
+                             B.buildUndef(Vec4x32), 0),
+      "Insert subvector must be from smaller vector to larger vector!");
+
+  // Insertion index causes overflow (2 + 4 > 4).
+  EXPECT_DEBUG_DEATH(B.buildInsertSubvector(Vec4x32, BigVec, SubVec, 4),
+                     "Insert subvector overflow!");
+
+  // Index must be a multiple of the subvector length (1 % 2 != 0).
+  EXPECT_DEBUG_DEATH(B.buildInsertSubvector(Vec4x32, BigVec, SubVec, 1),
+                     "Insert index is not a multiple of the subvector length");
 }


        


More information about the llvm-commits mailing list