[llvm] [CodeGen][AArch64] Use vector parts for internal non-power-of-two vectors (PR #213982)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 4 08:18:46 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Hari Limaye (hazzlim)
<details>
<summary>Changes</summary>
Decompose fixed-length, non-power-of-two vectors into the largest legal
vector type that exactly divides their element count. Apply this only to
internal register values.
Continue using the existing scalar breakdown for arguments and returns,
preserving the existing calling convention behaviour.
---
Patch is 34.38 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/213982.diff
10 Files Affected:
- (modified) llvm/include/llvm/CodeGen/TargetLowering.h (+31-16)
- (modified) llvm/lib/CodeGen/TargetLoweringBase.cpp (+54-7)
- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.h (+5)
- (modified) llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp (+5-4)
- (modified) llvm/lib/Target/NVPTX/NVPTXISelLowering.h (+2-1)
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+5-4)
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.h (+3-3)
- (modified) llvm/lib/Target/SPIRV/SPIRVISelLowering.h (+3-3)
- (modified) llvm/lib/Target/SystemZ/SystemZISelLowering.h (+5-4)
- (added) llvm/test/CodeGen/AArch64/non-pow2-fixed-vectors.ll (+537)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index c663bb8ea65b7..e8caf0c2471e8 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -1226,8 +1226,14 @@ class LLVM_ABI TargetLoweringBase {
/// before they are promoted/expanded.
unsigned getVectorTypeBreakdown(LLVMContext &Context, EVT VT,
EVT &IntermediateVT,
- unsigned &NumIntermediates,
- MVT &RegisterVT) const;
+ unsigned &NumIntermediates, MVT &RegisterVT,
+ bool ForCallingConv = false) const;
+
+ /// Return true if fixed-length, non-power-of-two vectors should be broken
+ /// down into legal vector parts instead of scalars for internal values.
+ virtual bool preferVectorizedNonPowerOfTwoTypeBreakdown() const {
+ return false;
+ }
/// Certain targets such as MIPS require that some types such as vectors are
/// always broken down into scalars in some contexts. This occurs even if the
@@ -1236,7 +1242,7 @@ class LLVM_ABI TargetLoweringBase {
LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT,
unsigned &NumIntermediates, MVT &RegisterVT) const {
return getVectorTypeBreakdown(Context, VT, IntermediateVT, NumIntermediates,
- RegisterVT);
+ RegisterVT, /*ForCallingConv=*/true);
}
struct IntrinsicInfo {
@@ -1851,19 +1857,23 @@ class LLVM_ABI TargetLoweringBase {
}
/// Return the type of registers that this ValueType will eventually require.
- MVT getRegisterType(LLVMContext &Context, EVT VT) const {
- if (VT.isSimple())
+ MVT getRegisterType(LLVMContext &Context, EVT VT,
+ bool ForCallingConv = false) const {
+ if (VT.isSimple() && (!ForCallingConv || !VT.isFixedLengthVector() ||
+ isPowerOf2_32(VT.getVectorNumElements()) ||
+ !preferVectorizedNonPowerOfTwoTypeBreakdown()))
return getRegisterType(VT.getSimpleVT());
if (VT.isVector()) {
EVT VT1;
MVT RegisterVT;
unsigned NumIntermediates;
- (void)getVectorTypeBreakdown(Context, VT, VT1,
- NumIntermediates, RegisterVT);
+ (void)getVectorTypeBreakdown(Context, VT, VT1, NumIntermediates,
+ RegisterVT, ForCallingConv);
return RegisterVT;
}
if (VT.isInteger()) {
- return getRegisterType(Context, getTypeToTransformTo(Context, VT));
+ return getRegisterType(Context, getTypeToTransformTo(Context, VT),
+ ForCallingConv);
}
llvm_unreachable("Unsupported extended type!");
}
@@ -1879,10 +1889,12 @@ class LLVM_ABI TargetLoweringBase {
///
/// RegisterVT may be passed as a way to override the default settings, for
/// instance with i128 inline assembly operands on SystemZ.
- virtual unsigned
- getNumRegisters(LLVMContext &Context, EVT VT,
- std::optional<MVT> RegisterVT = std::nullopt) const {
- if (VT.isSimple()) {
+ virtual unsigned getNumRegisters(LLVMContext &Context, EVT VT,
+ std::optional<MVT> RegisterVT = std::nullopt,
+ bool ForCallingConv = false) const {
+ if (VT.isSimple() && (!ForCallingConv || !VT.isFixedLengthVector() ||
+ isPowerOf2_32(VT.getVectorNumElements()) ||
+ !preferVectorizedNonPowerOfTwoTypeBreakdown())) {
assert((unsigned)VT.getSimpleVT().SimpleTy <
std::size(NumRegistersForVT));
return NumRegistersForVT[VT.getSimpleVT().SimpleTy];
@@ -1891,11 +1903,13 @@ class LLVM_ABI TargetLoweringBase {
EVT VT1;
MVT VT2;
unsigned NumIntermediates;
- return getVectorTypeBreakdown(Context, VT, VT1, NumIntermediates, VT2);
+ return getVectorTypeBreakdown(Context, VT, VT1, NumIntermediates, VT2,
+ ForCallingConv);
}
if (VT.isInteger()) {
unsigned BitWidth = VT.getSizeInBits();
- unsigned RegWidth = getRegisterType(Context, VT).getSizeInBits();
+ unsigned RegWidth =
+ getRegisterType(Context, VT, ForCallingConv).getSizeInBits();
return (BitWidth + RegWidth - 1) / RegWidth;
}
llvm_unreachable("Unsupported extended type!");
@@ -1906,7 +1920,7 @@ class LLVM_ABI TargetLoweringBase {
/// For MIPS all vector types must be passed through the integer register set.
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context,
CallingConv::ID CC, EVT VT) const {
- return getRegisterType(Context, VT);
+ return getRegisterType(Context, VT, /*ForCallingConv=*/true);
}
/// Certain targets require unusual breakdowns of certain types. For MIPS,
@@ -1915,7 +1929,8 @@ class LLVM_ABI TargetLoweringBase {
virtual unsigned getNumRegistersForCallingConv(LLVMContext &Context,
CallingConv::ID CC,
EVT VT) const {
- return getNumRegisters(Context, VT);
+ return getNumRegisters(Context, VT, /*RegisterVT=*/std::nullopt,
+ /*ForCallingConv=*/true);
}
/// Certain targets have context sensitive alignment requirements, where one
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index e5f2f3fc0e80e..9a9c87c1bced6 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -1545,11 +1545,33 @@ static unsigned getVectorTypeBreakdownMVT(MVT VT, MVT &IntermediateVT,
llvm_unreachable(
"Splitting or widening of non-power-of-2 MVTs is not implemented.");
- // FIXME: We don't support non-power-of-2-sized vectors for now.
+ // FIXME: We don't generically support non-power-of-2-sized vectors for now.
// Ideally we could break down into LHS/RHS like LegalizeDAG does.
if (!isPowerOf2_32(EC.getKnownMinValue())) {
- // Split EC to unit size (scalable property is preserved).
- NumVectorRegs = EC.getKnownMinValue();
+ assert(VT.isFixedLengthVector() && "Expected a fixed-length vector VT");
+ unsigned NumElts = EC.getKnownMinValue();
+
+ // Find the largest legal vector type that exactly divides a
+ // non-power-of-two vector.
+ if (TLI->preferVectorizedNonPowerOfTwoTypeBreakdown()) {
+ for (unsigned PartElts = llvm::bit_floor(NumElts); PartElts > 1;
+ PartElts >>= 1) {
+ if (NumElts % PartElts != 0)
+ continue;
+
+ MVT PartVT = MVT::getVectorVT(EltTy, ElementCount::getFixed(PartElts));
+ if (PartVT == MVT() || !TLI->isTypeLegal(PartVT))
+ continue;
+
+ IntermediateVT = PartVT;
+ NumIntermediates = NumElts / PartElts;
+ RegisterVT = PartVT;
+ return NumIntermediates;
+ }
+ }
+
+ // Fall back to scalars if there is no exact legal vector decomposition.
+ NumVectorRegs = NumElts;
EC = ElementCount::getFixed(1);
}
@@ -1984,7 +2006,8 @@ EVT TargetLoweringBase::getSetCCResultType(const DataLayout &DL, LLVMContext &,
unsigned TargetLoweringBase::getVectorTypeBreakdown(LLVMContext &Context,
EVT VT, EVT &IntermediateVT,
unsigned &NumIntermediates,
- MVT &RegisterVT) const {
+ MVT &RegisterVT,
+ bool ForCallingConv) const {
ElementCount EltCnt = VT.getVectorElementCount();
// If there is a wider vector type with the same element type as this one,
@@ -2033,10 +2056,34 @@ unsigned TargetLoweringBase::getVectorTypeBreakdown(LLVMContext &Context,
return NumIntermediates;
}
- // FIXME: We don't support non-power-of-2-sized vectors for now. Ideally
- // we could break down into LHS/RHS like LegalizeDAG does.
+ // FIXME: We don't generically support non-power-of-2-sized vectors for now.
+ // Ideally we could break down into LHS/RHS like LegalizeDAG does.
if (!isPowerOf2_32(EltCnt.getKnownMinValue())) {
- NumVectorRegs = EltCnt.getKnownMinValue();
+ assert(VT.isFixedLengthVector() && "Expected a fixed-length vector VT");
+ unsigned NumElts = EltCnt.getKnownMinValue();
+
+ // Find the largest legal vector type that exactly divides a
+ // non-power-of-two vector.
+ if (!ForCallingConv && preferVectorizedNonPowerOfTwoTypeBreakdown()) {
+ for (unsigned PartElts = llvm::bit_floor(NumElts); PartElts > 1;
+ PartElts >>= 1) {
+ if (NumElts % PartElts != 0)
+ continue;
+
+ EVT PartVT =
+ EVT::getVectorVT(Context, EltTy, ElementCount::getFixed(PartElts));
+ if (!isTypeLegal(PartVT))
+ continue;
+
+ IntermediateVT = PartVT;
+ NumIntermediates = NumElts / PartElts;
+ RegisterVT = PartVT.getSimpleVT();
+ return NumIntermediates;
+ }
+ }
+
+ // Fall back to scalars if there is no exact legal vector decomposition.
+ NumVectorRegs = NumElts;
EltCnt = ElementCount::getFixed(1);
}
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index 35f7ef0e2151e..c5a47414ddf18 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -20,6 +20,7 @@
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Instruction.h"
+#include "llvm/Support/MathExtras.h"
namespace llvm {
@@ -602,6 +603,10 @@ class AArch64TargetLowering : public TargetLowering {
unsigned &NumIntermediates,
MVT &RegisterVT) const override;
+ bool preferVectorizedNonPowerOfTwoTypeBreakdown() const override {
+ return true;
+ }
+
/// True if stack clash protection is enabled for this functions.
bool hasInlineStackProbe(const MachineFunction &MF) const override;
diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
index 29921ff86b352..dc777bacd47bf 100644
--- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
@@ -4028,12 +4028,13 @@ SDValue NVPTXTargetLowering::LowerCopyToReg_128(SDValue Op,
return DAG.getNode(ISD::CopyToReg, DL, ResultsType, NewOps);
}
-unsigned NVPTXTargetLowering::getNumRegisters(
- LLVMContext &Context, EVT VT,
- std::optional<MVT> RegisterVT = std::nullopt) const {
+unsigned NVPTXTargetLowering::getNumRegisters(LLVMContext &Context, EVT VT,
+ std::optional<MVT> RegisterVT,
+ bool ForCallingConv) const {
if (VT == MVT::i128 && RegisterVT == MVT::i128)
return 1;
- return TargetLoweringBase::getNumRegisters(Context, VT, RegisterVT);
+ return TargetLoweringBase::getNumRegisters(Context, VT, RegisterVT,
+ ForCallingConv);
}
bool NVPTXTargetLowering::splitValueIntoRegisterParts(
diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.h b/llvm/lib/Target/NVPTX/NVPTXISelLowering.h
index 42741ba98b438..c7238444ae61c 100644
--- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.h
+++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.h
@@ -224,7 +224,8 @@ class NVPTXTargetLowering : public TargetLowering {
SDValue LowerCopyToReg_128(SDValue Op, SelectionDAG &DAG) const;
unsigned getNumRegisters(LLVMContext &Context, EVT VT,
- std::optional<MVT> RegisterVT) const override;
+ std::optional<MVT> RegisterVT,
+ bool ForCallingConv = false) const override;
bool
splitValueIntoRegisterParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val,
SDValue *Parts, unsigned NumParts, MVT PartVT,
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index e23427482c1e4..b9d3871ef2374 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -2926,15 +2926,16 @@ MVT RISCVTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
}
-unsigned
-RISCVTargetLowering::getNumRegisters(LLVMContext &Context, EVT VT,
- std::optional<MVT> RegisterVT) const {
+unsigned RISCVTargetLowering::getNumRegisters(LLVMContext &Context, EVT VT,
+ std::optional<MVT> RegisterVT,
+ bool ForCallingConv) const {
// Pair inline assembly operand
if (VT == (Subtarget.is64Bit() ? MVT::i128 : MVT::i64) && RegisterVT &&
*RegisterVT == MVT::Untyped)
return 1;
- return TargetLowering::getNumRegisters(Context, VT, RegisterVT);
+ return TargetLowering::getNumRegisters(Context, VT, RegisterVT,
+ ForCallingConv);
}
unsigned RISCVTargetLowering::getNumRegistersForCallingConv(LLVMContext &Context,
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index 2ca7c392639f7..d2f0e1f62c845 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -82,9 +82,9 @@ class RISCVTargetLowering : public TargetLowering {
EVT VT) const override;
/// Return the number of registers for a given MVT, for inline assembly
- unsigned
- getNumRegisters(LLVMContext &Context, EVT VT,
- std::optional<MVT> RegisterVT = std::nullopt) const override;
+ unsigned getNumRegisters(LLVMContext &Context, EVT VT,
+ std::optional<MVT> RegisterVT = std::nullopt,
+ bool ForCallingConv = false) const override;
/// Return the number of registers for a given MVT, ensuring vectors are
/// treated as a series of gpr sized integers.
diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.h b/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
index ff843649fd6d3..a4e91b3f06d64 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
@@ -53,9 +53,9 @@ class SPIRVTargetLowering : public TargetLowering {
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
StringRef Constraint, MVT VT) const override;
- unsigned
- getNumRegisters(LLVMContext &Context, EVT VT,
- std::optional<MVT> RegisterVT = std::nullopt) const override {
+ unsigned getNumRegisters(LLVMContext &Context, EVT VT,
+ std::optional<MVT> RegisterVT = std::nullopt,
+ bool ForCallingConv = false) const override {
return 1;
}
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index e6da481353497..dc2da7aea77bf 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -75,13 +75,14 @@ class SystemZTargetLowering : public TargetLowering {
return TypeWidenVector;
return TargetLoweringBase::getPreferredVectorAction(VT);
}
- unsigned
- getNumRegisters(LLVMContext &Context, EVT VT,
- std::optional<MVT> RegisterVT) const override {
+ unsigned getNumRegisters(LLVMContext &Context, EVT VT,
+ std::optional<MVT> RegisterVT,
+ bool ForCallingConv = false) const override {
// i128 inline assembly operand.
if (VT == MVT::i128 && RegisterVT && *RegisterVT == MVT::Untyped)
return 1;
- return TargetLowering::getNumRegisters(Context, VT);
+ return TargetLowering::getNumRegisters(
+ Context, VT, /*RegisterVT=*/std::nullopt, ForCallingConv);
}
unsigned
getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC,
diff --git a/llvm/test/CodeGen/AArch64/non-pow2-fixed-vectors.ll b/llvm/test/CodeGen/AArch64/non-pow2-fixed-vectors.ll
new file mode 100644
index 0000000000000..ea945cdbcec43
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/non-pow2-fixed-vectors.ll
@@ -0,0 +1,537 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=aarch64-linux-gnu -O3 | FileCheck %s
+
+define void @v5i32_internal(ptr %c, ptr %in, ptr %out, i64 %n) {
+; CHECK-LABEL: v5i32_internal:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldp w12, w13, [x0]
+; CHECK-NEXT: mov w1, wzr
+; CHECK-NEXT: mov w11, wzr
+; CHECK-NEXT: mov w9, wzr
+; CHECK-NEXT: mov w8, wzr
+; CHECK-NEXT: mov w10, wzr
+; CHECK-NEXT: fmov s0, w12
+; CHECK-NEXT: mov v0.s[1], w13
+; CHECK-NEXT: ldp w13, w12, [x0, #8]
+; CHECK-NEXT: mov v0.s[2], w13
+; CHECK-NEXT: mov v0.s[3], w12
+; CHECK-NEXT: ldr w12, [x0, #16]
+; CHECK-NEXT: fmov s1, w12
+; CHECK-NEXT: .LBB0_1: // %loop
+; CHECK-NEXT: // =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: fmov s2, w1
+; CHECK-NEXT: fmov s3, w10
+; CHECK-NEXT: subs x3, x3, #1
+; CHECK-NEXT: mov v2.s[1], w11
+; CHECK-NEXT: add v3.4s, v3.4s, v1.4s
+; CHECK-NEXT: fmov w10, s3
+; CHECK-NEXT: mov v2.s[2], w9
+; CHECK-NEXT: mov v2.s[3], w8
+; CHECK-NEXT: add v2.4s, v2.4s, v0.4s
+; CHECK-NEXT: mov w8, v2.s[3]
+; CHECK-NEXT: mov w9, v2.s[2]
+; CHECK-NEXT: mov w11, v2.s[1]
+; CHECK-NEXT: fmov w1, s2
+; CHECK-NEXT: b.ne .LBB0_1
+; CHECK-NEXT: // %bb.2: // %exit
+; CHECK-NEXT: mov v2.s[1], w11
+; CHECK-NEXT: str w10, [x2, #16]
+; CHECK-NEXT: mov v2.s[2], w9
+; CHECK-NEXT: mov v2.s[3], w8
+; CHECK-NEXT: str q2, [x2]
+; CHECK-NEXT: ret
+entry:
+ %c.val = load <5 x i32>, ptr %c
+ br label %loop
+
+loop:
+ %acc = phi <5 x i32> [ zeroinitializer, %entry ], [ %acc.next, %loop ]
+ %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
+ %i.next = add nuw i64 %i, 1
+ %acc.next = add <5 x i32> %acc, %c.val
+ %cond = icmp eq i64 %i.next, %n
+ br i1 %cond, label %exit, label %loop
+
+exit:
+ store <5 x i32> %acc.next, ptr %out, align 8
+ ret void
+}
+
+define void @v6i32_internal(ptr %c, ptr %in, ptr %out, i64 %n) {
+; CHECK-LABEL: v6i32_internal:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: ldr q1, [x0]
+; CHECK-NEXT: movi v0.2d, #0000000000000000
+; CHECK-NEXT: movi v4.2d, #0000000000000000
+; CHECK-NEXT: movi v2.2d, #0000000000000000
+; CHECK-NEXT: ldr d5, [x0, #16]
+; CHECK-NEXT: mov d3, v1.d[1]
+; CHECK-NEXT: .LBB1_1: // %loop
+; CHECK-NEXT: // =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: add v0.2s, v0.2s, v1.2s
+; CHECK-NEXT: add v4.2s, v4.2s, v3.2s
+; CHECK-NEXT: subs x3, x3, #1
+; CHECK-NEXT: add v2.2s, v2.2s, v5.2s
+; CHECK-NEXT: b.ne .LBB1_1
+; CHECK-NEXT: // %bb.2: // %exit
+; CHECK-NEXT: mov v0.d[1], v4.d[0]
+; CHECK-NEXT: str d2, [x2, #16]
+; CHECK-NEXT: str q0, [x2]
+; CHECK-NEXT: ret
+entry:
+ %c.val = load <6 x i32>, ptr %c
+ br label %loop
+
+loop:
+ %acc = phi <6 x i32> [ zeroinitializer, %entry ], [ %acc.next, %loop ]
+ %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
+ %i.next = add nuw i64 %i, 1
+ %acc.next = add <6 x i32> %acc, %c.val
+ %cond = icmp eq i64 %i.next, %n
+ br i1 %cond, label %exit, label %loop
+
+exit:
+ store <6 x i32> %acc.next, ptr %out, align 8
+ ret void
+}
+
+define <6 x i32> @v6i32_cc(<6 x i32> %c.val, ptr %in, ptr %out, i64 %n) {
+; CHECK-LABEL: v6i32_cc:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: fmov s0, w4
+; CHECK-NEXT: fmov s1, w2
+; CHECK-NEXT: ldr x8, [sp]
+; CHECK-NEXT: fmov s3, w0
+; CHECK-NEXT: movi v2.2d, #0000000000000000
+; CHECK-NEXT: movi v4.2d, #0000000000000000
+; CHECK-NEXT: movi v5.2d, #0000000000000000
+; CHECK-NEXT: mov v0.s[1], w5
+; CHECK-NEXT: mov v1.s[1], w3
+; CHECK-NEXT: mov v3.s[1], w1
+; CHECK-NEXT: .LBB2_1: // %loop
...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/213982
More information about the llvm-commits
mailing list