[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