summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
diff options
context:
space:
mode:
authorOliver Stannard <oliver.stannard@arm.com>2015-11-10 11:04:18 +0000
committerOliver Stannard <oliver.stannard@arm.com>2015-11-10 11:04:18 +0000
commitd414c99b9c20e2ff96524c015699f6bc6f71a888 (patch)
tree10479f0b59e665d073cba532859ef0602fe0b6c2 /llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
parentbf5210f8ed44bda0a4329c9c3b02ab773491781a (diff)
downloadbcm5719-llvm-d414c99b9c20e2ff96524c015699f6bc6f71a888.tar.gz
bcm5719-llvm-d414c99b9c20e2ff96524c015699f6bc6f71a888.zip
[AArch64] Fix halfword load merging for big-endian targets
For big-endian targets, when we merge two halfword loads into a word load, the order of the halfwords in the loaded value is reversed compared to little-endian, so the load-store optimiser needs to swap the destination registers. This does not affect merging of two word loads, as we use ldp, which treats the memory as two separate 32-bit words. llvm-svn: 252597
Diffstat (limited to 'llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp')
-rw-r--r--llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp12
1 files changed, 9 insertions, 3 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
index 6ef4c269d8f..ffe6ab2cb53 100644
--- a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
@@ -84,6 +84,7 @@ struct AArch64LoadStoreOpt : public MachineFunctionPass {
const AArch64InstrInfo *TII;
const TargetRegisterInfo *TRI;
+ const AArch64Subtarget *Subtarget;
// Scan the instructions looking for a load/store that can be combined
// with the current instruction into a load/store pair.
@@ -537,6 +538,10 @@ AArch64LoadStoreOpt::mergePairedInsns(MachineBasicBlock::iterator I,
if (!IsUnscaled)
OffsetImm /= 2;
MachineInstr *RtNewDest = MergeForward ? I : Paired;
+ // When merging small (< 32 bit) loads for big-endian targets, the order of
+ // the component parts gets swapped.
+ if (!Subtarget->isLittleEndian())
+ std::swap(RtMI, Rt2MI);
// Construct the new load instruction.
// FIXME: currently we support only halfword unsigned load. We need to
// handle byte type, signed, and store instructions as well.
@@ -560,7 +565,7 @@ AArch64LoadStoreOpt::mergePairedInsns(MachineBasicBlock::iterator I,
DEBUG((NewMemMI)->print(dbgs()));
MachineInstr *ExtDestMI = MergeForward ? Paired : I;
- if (ExtDestMI == Rt2MI) {
+ if ((ExtDestMI == Rt2MI) == Subtarget->isLittleEndian()) {
// Create the bitfield extract for high half.
BitExtMI1 = BuildMI(*I->getParent(), InsertionPoint, I->getDebugLoc(),
TII->get(AArch64::UBFMWri))
@@ -1388,8 +1393,9 @@ bool AArch64LoadStoreOpt::enableNarrowLdMerge(MachineFunction &Fn) {
}
bool AArch64LoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
- TII = static_cast<const AArch64InstrInfo *>(Fn.getSubtarget().getInstrInfo());
- TRI = Fn.getSubtarget().getRegisterInfo();
+ Subtarget = &static_cast<const AArch64Subtarget &>(Fn.getSubtarget());
+ TII = static_cast<const AArch64InstrInfo *>(Subtarget->getInstrInfo());
+ TRI = Subtarget->getRegisterInfo();
bool Modified = false;
bool enableNarrowLdOpt = enableNarrowLdMerge(Fn);
OpenPOWER on IntegriCloud