aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2010-01-14 00:54:10 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2010-01-14 00:54:10 +0000
commit069e100f9a79a63db177a521fd790f4d77d1209c (patch)
treee18a2e5782f83df4d10f5570cb72ff18e7be6bec /lib/Target/ARM/ARMLoadStoreOptimizer.cpp
parentb7eaa130d05347b6e84fd25f1f59f85681be1ede (diff)
Don't fold insufficiently aligned ldr/str into ldm/stm instructions.
An unaligned ldr causes a trap, and is then emulated by the kernel with awesome performance. The darwin kernel does not emulate unaligned ldm/stm Thumb2 instructions, so don't generate them. This fixes the miscompilation of Multisource/Applications/JM/lencod for Thumb2. Generating unaligned ldr/str pairs from a 16-bit aligned memcpy is probably also a bad idea, but that is beyond the scope of this patch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@93393 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/ARMLoadStoreOptimizer.cpp')
-rw-r--r--lib/Target/ARM/ARMLoadStoreOptimizer.cpp12
1 files changed, 12 insertions, 0 deletions
diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
index b13f98acb7..b78b95b22e 100644
--- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
+++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
@@ -740,6 +740,18 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
/// isMemoryOp - Returns true if instruction is a memory operations (that this
/// pass is capable of operating on).
static bool isMemoryOp(const MachineInstr *MI) {
+ if (MI->hasOneMemOperand()) {
+ const MachineMemOperand *MMO = *MI->memoperands_begin();
+
+ // Don't touch volatile memory accesses - we may be changing their order.
+ if (MMO->isVolatile())
+ return false;
+
+ // Unaligned ldr/str is emulated by some kernels, but unaligned ldm/stm is not.
+ if (MMO->getAlignment() < 4)
+ return false;
+ }
+
int Opcode = MI->getOpcode();
switch (Opcode) {
default: break;