diff options
author | Luke Cheeseman <luke.cheeseman@arm.com> | 2018-09-24 10:42:22 +0000 |
---|---|---|
committer | Luke Cheeseman <luke.cheeseman@arm.com> | 2018-09-24 10:42:22 +0000 |
commit | bda54bca391de6b83a2131bf6344d3a2ae8eca34 (patch) | |
tree | 9428d980c44f9214a6fa526bf2910b72f1180a5b /llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp | |
parent | c451c9ef50b7b3df260e709a9dcd6324356d57a2 (diff) | |
download | llvm-bda54bca391de6b83a2131bf6344d3a2ae8eca34.zip llvm-bda54bca391de6b83a2131bf6344d3a2ae8eca34.tar.gz llvm-bda54bca391de6b83a2131bf6344d3a2ae8eca34.tar.bz2 |
[ARM][ARMLoadStoreOptimizer]
- The load store optimizer is currently merging multiple loads/stores into VLDM/VSTM with more than 16 doubleword registers
- This is an UNPREDICTABLE instruction and shouldn't be done
- It looks like the Limit for how many registers included in a merge got dropped at some point so I am reintroducing it in this patch
- This fixes https://bugs.llvm.org/show_bug.cgi?id=38389
Differential Revision: https://reviews.llvm.org/D52085
llvm-svn: 342872
Diffstat (limited to 'llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index bb79783..e6b8f2f 100644 --- a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -1027,6 +1027,18 @@ void ARMLoadStoreOpt::FormCandidates(const MemOpQueue &MemOps) { if (AssumeMisalignedLoadStores && !mayCombineMisaligned(*STI, *MI)) CanMergeToLSMulti = CanMergeToLSDouble = false; + // vldm / vstm limit are 32 for S variants, 16 for D variants. + unsigned Limit; + switch (Opcode) { + default: + Limit = UINT_MAX; + break; + case ARM::VLDRD: + case ARM::VSTRD: + Limit = 16; + break; + } + // Merge following instructions where possible. for (unsigned I = SIndex+1; I < EIndex; ++I, ++Count) { int NewOffset = MemOps[I].Offset; @@ -1036,6 +1048,8 @@ void ARMLoadStoreOpt::FormCandidates(const MemOpQueue &MemOps) { unsigned Reg = MO.getReg(); if (Reg == ARM::SP || Reg == ARM::PC) break; + if (Count == Limit) + break; // See if the current load/store may be part of a multi load/store. unsigned RegNum = MO.isUndef() ? std::numeric_limits<unsigned>::max() |