[llvm] [RISCV][GISEL] Add IRTranslation for insertelement with scalable vector type (PR #80377)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 1 18:11:46 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Michael Maitland (michaelmaitland)
<details>
<summary>Changes</summary>
This patch is stacked on #<!-- -->80372, #<!-- -->80307, and #<!-- -->80306.
---
Patch is 119.58 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/80377.diff
9 Files Affected:
- (modified) llvm/include/llvm/CodeGen/GlobalISel/Utils.h (+10-4)
- (modified) llvm/lib/CodeGen/GlobalISel/CallLowering.cpp (+7-6)
- (modified) llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp (+2-1)
- (modified) llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (+2-2)
- (modified) llvm/lib/CodeGen/GlobalISel/Utils.cpp (+100-61)
- (modified) llvm/lib/CodeGen/MachineVerifier.cpp (+4-3)
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+3-3)
- (added) llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/insertelement.ll (+1941)
- (modified) llvm/unittests/CodeGen/GlobalISel/GISelUtilsTest.cpp (+143)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
index bf02911e19351..f8900f3434cca 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
@@ -343,10 +343,13 @@ Register getFunctionLiveInPhysReg(MachineFunction &MF,
const TargetRegisterClass &RC,
const DebugLoc &DL, LLT RegTy = LLT());
-/// Return the least common multiple type of \p OrigTy and \p TargetTy, by changing the
-/// number of vector elements or scalar bitwidth. The intent is a
+/// Return the least common multiple type of \p OrigTy and \p TargetTy, by
+/// changing the number of vector elements or scalar bitwidth. The intent is a
/// G_MERGE_VALUES, G_BUILD_VECTOR, or G_CONCAT_VECTORS can be constructed from
-/// \p OrigTy elements, and unmerged into \p TargetTy
+/// \p OrigTy elements, and unmerged into \p TargetTy. It is an error to call
+/// this function where one argument is a fixed vector and the other is a
+/// scalable vector, since it is illegal to build a G_{MERGE|UNMERGE}_VALUES
+/// between fixed and scalable vectors.
LLVM_READNONE
LLT getLCMType(LLT OrigTy, LLT TargetTy);
@@ -365,7 +368,10 @@ LLT getCoverTy(LLT OrigTy, LLT TargetTy);
/// If these are vectors with different element types, this will try to produce
/// a vector with a compatible total size, but the element type of \p OrigTy. If
/// this can't be satisfied, this will produce a scalar smaller than the
-/// original vector elements.
+/// original vector elements. It is an error to call this function where
+/// one argument is a fixed vector and the other is a scalable vector, since it
+/// is illegal to build a G_{MERGE|UNMERGE}_VALUES between fixed and scalable
+/// vectors.
///
/// In the worst case, this returns LLT::scalar(1)
LLVM_READNONE
diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
index ccd9b13d730b6..3bd1542eeb746 100644
--- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
@@ -412,7 +412,7 @@ static void buildCopyFromRegs(MachineIRBuilder &B, ArrayRef<Register> OrigRegs,
// size, e.g. PartLLT == v2s64 and LLTy is v3s32, then first coerce it to
// have the same elt type, i.e. v4s32.
// TODO: Extend this coersion to element multiples other than just 2.
- if (PartLLT.getSizeInBits() > LLTy.getSizeInBits() &&
+ if (TypeSize::isKnownGT(PartLLT.getSizeInBits(), LLTy.getSizeInBits()) &&
PartLLT.getScalarSizeInBits() == LLTy.getScalarSizeInBits() * 2 &&
Regs.size() == 1) {
LLT NewTy = PartLLT.changeElementType(LLTy.getElementType())
@@ -529,7 +529,7 @@ static void buildCopyToRegs(MachineIRBuilder &B, ArrayRef<Register> DstRegs,
// We could just insert a regular copy, but this is unreachable at the moment.
assert(SrcTy != PartTy && "identical part types shouldn't reach here");
- const unsigned PartSize = PartTy.getSizeInBits();
+ const TypeSize PartSize = PartTy.getSizeInBits();
if (PartTy.isVector() == SrcTy.isVector() &&
PartTy.getScalarSizeInBits() > SrcTy.getScalarSizeInBits()) {
@@ -539,7 +539,7 @@ static void buildCopyToRegs(MachineIRBuilder &B, ArrayRef<Register> DstRegs,
}
if (SrcTy.isVector() && !PartTy.isVector() &&
- PartSize > SrcTy.getElementType().getSizeInBits()) {
+ TypeSize::isKnownGT(PartSize, SrcTy.getElementType().getSizeInBits())) {
// Vector was scalarized, and the elements extended.
auto UnmergeToEltTy = B.buildUnmerge(SrcTy.getElementType(), SrcReg);
for (int i = 0, e = DstRegs.size(); i != e; ++i)
@@ -548,9 +548,10 @@ static void buildCopyToRegs(MachineIRBuilder &B, ArrayRef<Register> DstRegs,
}
if (SrcTy.isVector() && PartTy.isVector() &&
- PartTy.getScalarSizeInBits() == SrcTy.getScalarSizeInBits() &&
- SrcTy.getNumElements() < PartTy.getNumElements()) {
- // A coercion like: v2f32 -> v4f32.
+ PartTy.getSizeInBits() == SrcTy.getSizeInBits() &&
+ ElementCount::isKnownLT(SrcTy.getElementCount(),
+ PartTy.getElementCount())) {
+ // A coercion like: v2f32 -> v4f32 or nxv2f32 -> nxv4f32
Register DstReg = DstRegs.front();
B.buildPadVectorWithUndefElements(DstReg, SrcReg);
return;
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index dd38317c26bff..d8d6acd2b5a5c 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -2956,7 +2956,8 @@ bool IRTranslator::translateInsertElement(const User &U,
MachineIRBuilder &MIRBuilder) {
// If it is a <1 x Ty> vector, use the scalar as it is
// not a legal vector type in LLT.
- if (cast<FixedVectorType>(U.getType())->getNumElements() == 1)
+ if (auto *FVT = dyn_cast<FixedVectorType>(U.getType());
+ FVT && FVT->getNumElements() == 1)
return translateCopy(U, *U.getOperand(1), MIRBuilder);
Register Res = getOrCreateVReg(U);
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index a5827c26c04f4..2596fa5f53cee 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -1282,8 +1282,8 @@ MachineIRBuilder::buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps,
SrcOps[1].getLLTTy(*getMRI()) &&
"Type mismatch");
assert(SrcOps[2].getLLTTy(*getMRI()).isScalar() && "Invalid index");
- assert(DstOps[0].getLLTTy(*getMRI()).getNumElements() ==
- SrcOps[0].getLLTTy(*getMRI()).getNumElements() &&
+ assert(DstOps[0].getLLTTy(*getMRI()).getElementCount() ==
+ SrcOps[0].getLLTTy(*getMRI()).getElementCount() &&
"Type mismatch");
break;
}
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index aed826a9cbc54..73da8e61972eb 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -1071,49 +1071,73 @@ void llvm::getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU) {
}
LLT llvm::getLCMType(LLT OrigTy, LLT TargetTy) {
- const unsigned OrigSize = OrigTy.getSizeInBits();
- const unsigned TargetSize = TargetTy.getSizeInBits();
-
- if (OrigSize == TargetSize)
+ if (OrigTy.getSizeInBits() == TargetTy.getSizeInBits())
return OrigTy;
- if (OrigTy.isVector()) {
- const LLT OrigElt = OrigTy.getElementType();
-
- if (TargetTy.isVector()) {
- const LLT TargetElt = TargetTy.getElementType();
+ if (OrigTy.isVector() && TargetTy.isVector()) {
+ LLT OrigElt = OrigTy.getElementType();
+ LLT TargetElt = TargetTy.getElementType();
- if (OrigElt.getSizeInBits() == TargetElt.getSizeInBits()) {
- int GCDElts =
- std::gcd(OrigTy.getNumElements(), TargetTy.getNumElements());
- // Prefer the original element type.
- ElementCount Mul = OrigTy.getElementCount() * TargetTy.getNumElements();
- return LLT::vector(Mul.divideCoefficientBy(GCDElts),
- OrigTy.getElementType());
- }
- } else {
- if (OrigElt.getSizeInBits() == TargetSize)
- return OrigTy;
+ // TODO: The docstring for this function says the intention is to use this
+ // function to build MERGE/UNMERGE instructions. It won't be the case that
+ // we generate a MERGE/UNMERGE between fixed and scalable vector types. We
+ // could implement getLCMType between the two in the future if there was a
+ // need, but it is not worth it now as this function should not be used in
+ // that way.
+ if ((OrigTy.isScalableVector() && TargetTy.isFixedVector()) ||
+ (OrigTy.isFixedVector() && TargetTy.isScalableVector()))
+ llvm_unreachable(
+ "getLCMType not implemented between fixed and scalable vectors.");
+
+ if (OrigElt.getSizeInBits() == TargetElt.getSizeInBits()) {
+ int GCDMinElts = std::gcd(OrigTy.getElementCount().getKnownMinValue(),
+ TargetTy.getElementCount().getKnownMinValue());
+ // Prefer the original element type.
+ ElementCount Mul = OrigTy.getElementCount().multiplyCoefficientBy(
+ TargetTy.getElementCount().getKnownMinValue());
+ return LLT::vector(Mul.divideCoefficientBy(GCDMinElts),
+ OrigTy.getElementType());
}
-
- unsigned LCMSize = std::lcm(OrigSize, TargetSize);
- return LLT::fixed_vector(LCMSize / OrigElt.getSizeInBits(), OrigElt);
+ unsigned LCM = std::lcm(OrigTy.getElementCount().getKnownMinValue() *
+ OrigElt.getSizeInBits().getFixedValue(),
+ TargetTy.getElementCount().getKnownMinValue() *
+ TargetElt.getSizeInBits().getFixedValue());
+ return LLT::vector(
+ ElementCount::get(LCM / OrigElt.getSizeInBits(), OrigTy.isScalable()),
+ OrigElt);
}
- if (TargetTy.isVector()) {
- unsigned LCMSize = std::lcm(OrigSize, TargetSize);
- return LLT::fixed_vector(LCMSize / OrigSize, OrigTy);
+ // One type is scalar, one type is vector
+ if (OrigTy.isVector() || TargetTy.isVector()) {
+ LLT VecTy = OrigTy.isVector() ? OrigTy : TargetTy;
+ LLT ScalarTy = OrigTy.isVector() ? TargetTy : OrigTy;
+ LLT EltTy = VecTy.getElementType();
+ LLT OrigEltTy = OrigTy.isVector() ? OrigTy.getElementType() : OrigTy;
+
+ // Prefer scalar type from OrigTy.
+ if (EltTy.getSizeInBits() == ScalarTy.getSizeInBits())
+ return LLT::vector(VecTy.getElementCount(), OrigEltTy);
+
+ // Different size scalars. Create vector with the same total size.
+ // LCM will take fixed/scalable from VecTy.
+ unsigned LCM = std::lcm(EltTy.getSizeInBits().getFixedValue() *
+ VecTy.getElementCount().getKnownMinValue(),
+ ScalarTy.getSizeInBits().getFixedValue());
+ // Prefer type from OrigTy
+ return LLT::vector(ElementCount::get(LCM / OrigEltTy.getSizeInBits(),
+ VecTy.getElementCount().isScalable()),
+ OrigEltTy);
}
- unsigned LCMSize = std::lcm(OrigSize, TargetSize);
-
+ // At this point, both types are scalars of different size
+ unsigned LCM = std::lcm(OrigTy.getSizeInBits().getFixedValue(),
+ TargetTy.getSizeInBits().getFixedValue());
// Preserve pointer types.
- if (LCMSize == OrigSize)
+ if (LCM == OrigTy.getSizeInBits())
return OrigTy;
- if (LCMSize == TargetSize)
+ if (LCM == TargetTy.getSizeInBits())
return TargetTy;
-
- return LLT::scalar(LCMSize);
+ return LLT::scalar(LCM);
}
LLT llvm::getCoverTy(LLT OrigTy, LLT TargetTy) {
@@ -1132,45 +1156,60 @@ LLT llvm::getCoverTy(LLT OrigTy, LLT TargetTy) {
}
LLT llvm::getGCDType(LLT OrigTy, LLT TargetTy) {
- const unsigned OrigSize = OrigTy.getSizeInBits();
- const unsigned TargetSize = TargetTy.getSizeInBits();
-
- if (OrigSize == TargetSize)
+ if (OrigTy.getSizeInBits() == TargetTy.getSizeInBits())
return OrigTy;
- if (OrigTy.isVector()) {
+ if (OrigTy.isVector() && TargetTy.isVector()) {
LLT OrigElt = OrigTy.getElementType();
- if (TargetTy.isVector()) {
- LLT TargetElt = TargetTy.getElementType();
- if (OrigElt.getSizeInBits() == TargetElt.getSizeInBits()) {
- int GCD = std::gcd(OrigTy.getNumElements(), TargetTy.getNumElements());
- return LLT::scalarOrVector(ElementCount::getFixed(GCD), OrigElt);
- }
- } else {
- // If the source is a vector of pointers, return a pointer element.
- if (OrigElt.getSizeInBits() == TargetSize)
- return OrigElt;
- }
+ LLT TargetElt = TargetTy.getElementType();
- unsigned GCD = std::gcd(OrigSize, TargetSize);
+ // TODO: The docstring for this function says the intention is to use this
+ // function to build MERGE/UNMERGE instructions. It won't be the case that
+ // we generate a MERGE/UNMERGE between fixed and scalable vector types. We
+ // could implement getGCDType between the two in the future if there was a
+ // need, but it is not worth it now as this function should not be used in
+ // that way.
+ if ((OrigTy.isScalableVector() && TargetTy.isFixedVector()) ||
+ (OrigTy.isFixedVector() && TargetTy.isScalableVector()))
+ llvm_unreachable(
+ "getGCDType not implemented between fixed and scalable vectors.");
+
+ unsigned GCD = std::gcd(OrigTy.getElementCount().getKnownMinValue() *
+ OrigElt.getSizeInBits().getFixedValue(),
+ TargetTy.getElementCount().getKnownMinValue() *
+ TargetElt.getSizeInBits().getFixedValue());
if (GCD == OrigElt.getSizeInBits())
- return OrigElt;
+ return LLT::scalarOrVector(ElementCount::get(1, OrigTy.isScalable()),
+ OrigElt);
- // If we can't produce the original element type, we have to use a smaller
- // scalar.
+ // Cannot produce original element type, but both have vscale in common.
if (GCD < OrigElt.getSizeInBits())
- return LLT::scalar(GCD);
- return LLT::fixed_vector(GCD / OrigElt.getSizeInBits(), OrigElt);
- }
+ return LLT::scalarOrVector(ElementCount::get(1, OrigTy.isScalable()),
+ GCD);
- if (TargetTy.isVector()) {
- // Try to preserve the original element type.
- LLT TargetElt = TargetTy.getElementType();
- if (TargetElt.getSizeInBits() == OrigSize)
- return OrigTy;
+ return LLT::vector(
+ ElementCount::get(GCD / OrigElt.getSizeInBits().getFixedValue(),
+ OrigTy.isScalable()),
+ OrigElt);
}
- unsigned GCD = std::gcd(OrigSize, TargetSize);
+ // If one type is vector and the element size matches the scalar size, then
+ // the gcd is the scalar type.
+ if (OrigTy.isVector() &&
+ OrigTy.getElementType().getSizeInBits() == TargetTy.getSizeInBits())
+ return OrigTy.getElementType();
+ if (TargetTy.isVector() &&
+ TargetTy.getElementType().getSizeInBits() == OrigTy.getSizeInBits())
+ return OrigTy;
+
+ // At this point, both types are either scalars of different type or one is a
+ // vector and one is a scalar. If both types are scalars, the GCD type is the
+ // GCD between the two scalar sizes. If one is vector and one is scalar, then
+ // the GCD type is the GCD between the scalar and the vector element size.
+ LLT OrigScalar = OrigTy.isVector() ? OrigTy.getElementType() : OrigTy;
+ LLT TargetScalar = TargetTy.isVector() ? TargetTy.getElementType() : TargetTy;
+ unsigned GCD = std::gcd(OrigScalar.getSizeInBits().getFixedValue(),
+ TargetScalar.getSizeInBits().getFixedValue());
return LLT::scalar(GCD);
}
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index b182000a3d705..fe865ed6f8a0e 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -1400,7 +1400,8 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
if (DstTy.isVector()) {
// This case is the converse of G_CONCAT_VECTORS.
if (!SrcTy.isVector() || SrcTy.getScalarType() != DstTy.getScalarType() ||
- SrcTy.getNumElements() != NumDsts * DstTy.getNumElements())
+ SrcTy.isScalableVector() != DstTy.isScalableVector() ||
+ SrcTy.getSizeInBits() != NumDsts * DstTy.getSizeInBits())
report("G_UNMERGE_VALUES source operand does not match vector "
"destination operands",
MI);
@@ -1477,8 +1478,8 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
for (const MachineOperand &MO : llvm::drop_begin(MI->operands(), 2))
if (MRI->getType(MI->getOperand(1).getReg()) != MRI->getType(MO.getReg()))
report("G_CONCAT_VECTOR source operand types are not homogeneous", MI);
- if (DstTy.getNumElements() !=
- SrcTy.getNumElements() * (MI->getNumOperands() - 1))
+ if (DstTy.getElementCount() !=
+ SrcTy.getElementCount() * (MI->getNumOperands() - 1))
report("G_CONCAT_VECTOR num dest and source elements should match", MI);
break;
}
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index b5db41197a35a..2f3fe9cfd88e9 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20485,11 +20485,11 @@ unsigned RISCVTargetLowering::getCustomCtpopCost(EVT VT,
bool RISCVTargetLowering::fallBackToDAGISel(const Instruction &Inst) const {
- // GISel support is in progress or complete for G_ADD, G_SUB, G_AND, G_OR, and
- // G_XOR.
+ // GISel support is in progress or complete for these opcodes.
unsigned Op = Inst.getOpcode();
if (Op == Instruction::Add || Op == Instruction::Sub ||
- Op == Instruction::And || Op == Instruction::Or || Op == Instruction::Xor)
+ Op == Instruction::And || Op == Instruction::Or ||
+ Op == Instruction::Xor || Op == Instruction::InsertElement)
return false;
if (Inst.getType()->isScalableTy())
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/insertelement.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/insertelement.ll
new file mode 100644
index 0000000000000..9255967a4da82
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/insertelement.ll
@@ -0,0 +1,1941 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
+; RUN: llc -mtriple=riscv32 -mattr=+v -global-isel -stop-after=irtranslator \
+; RUN: -verify-machineinstrs < %s | FileCheck -check-prefixes=RV32 %s
+; RUN: llc -mtriple=riscv64 -mattr=+v -global-isel -stop-after=irtranslator \
+; RUN: -verify-machineinstrs < %s | FileCheck -check-prefixes=RV64 %s
+
+define <vscale x 1 x i1> @insertelement_nxv1i1_0() {
+ ; RV32-LABEL: name: insertelement_nxv1i1_0
+ ; RV32: bb.1 (%ir-block.0):
+ ; RV32-NEXT: [[DEF:%[0-9]+]]:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF
+ ; RV32-NEXT: [[C:%[0-9]+]]:_(s1) = G_CONSTANT i1 false
+ ; RV32-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; RV32-NEXT: [[IVEC:%[0-9]+]]:_(<vscale x 1 x s1>) = G_INSERT_VECTOR_ELT [[DEF]], [[C]](s1), [[C1]](s32)
+ ; RV32-NEXT: $v0 = COPY [[IVEC]](<vscale x 1 x s1>)
+ ; RV32-NEXT: PseudoRET implicit $v0
+ ;
+ ; RV64-LABEL: name: insertelement_nxv1i1_0
+ ; RV64: bb.1 (%ir-block.0):
+ ; RV64-NEXT: [[DEF:%[0-9]+]]:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF
+ ; RV64-NEXT: [[C:%[0-9]+]]:_(s1) = G_CONSTANT i1 false
+ ; RV64-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; RV64-NEXT: [[IVEC:%[0-9]+]]:_(<vscale x 1 x s1>) = G_INSERT_VECTOR_ELT [[DEF]], [[C]](s1), [[C1]](s32)
+ ; RV64-NEXT: $v0 = COPY [[IVEC]](<vscale x 1 x s1>)
+ ; RV64-NEXT: PseudoRET implicit $v0
+ %a = insertelement <vscale x 1 x i1> poison, i1 0, i32 0
+ ret <vscale x 1 x i1> %a
+}
+
+define <vscale x 1 x i1> @insertelement_nxv1i1_1() {
+ ; RV32-LABEL: name: insertelement_nxv1i1_1
+ ; RV32: bb.1 (%ir-block.0):
+ ; RV32-NEXT: [[DEF:%[0-9]+]]:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF
+ ; RV32-NEXT: [[C:%[0-9]+]]:_(s1) = G_CONSTANT i1 true
+ ; RV32-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; RV32-NEXT: [[IVEC:%[0-9]+]]:_(<vscale x 1 x s1>) = G_INSERT_VECTOR_ELT [[DEF]], [[C]](s1), [[C1]](s32)
+ ; RV32-NEXT: $v0 = COPY [[IVEC]](<vscale x 1 x s1>)
+ ; RV32-NEXT: PseudoRET implicit $v0
+ ;
+ ; RV64-LABEL: name: insertelement_nxv1i1_1
+ ; RV64: bb.1 (%ir-block.0):
+ ; RV64-NEXT: [[DEF:%[0-9]+]]:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF
+ ; RV64-NEXT: [[C:%[0-9]+]]:_(s1) = G_CONSTANT i1 true
+ ; RV64-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; RV64-NEXT: [[IVEC:%[0-9]+]]:_(<vscale x 1 x s1>) = G_INSERT_VECTOR_ELT [[DEF]], [[C]](s1), [[C1]](s32)
+ ; RV64-NEXT: $v0 = COPY [[IVEC]](<vscale x 1 x s1>)
+ ; RV64-NEXT: PseudoRET implicit $v0
+ %a = insertelement <vscale x 1 x i1> poison, i1 -1, i32 0
+ ret <vscale x 1 x i1> %a
+}
+
+define <vscale x 1 x i1> @insertelement_nxv1i1_2(i1 %x) {
+ ; RV32-LABEL: name: insertelement_nxv1i1_2
+ ; RV32: bb.1 (%ir-block.0):
+ ; RV32...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/80377
More information about the llvm-commits
mailing list