diff options
author | Oliver Stannard <oliver.stannard@arm.com> | 2015-11-10 11:04:18 +0000 |
---|---|---|
committer | Oliver Stannard <oliver.stannard@arm.com> | 2015-11-10 11:04:18 +0000 |
commit | d414c99b9c20e2ff96524c015699f6bc6f71a888 (patch) | |
tree | 10479f0b59e665d073cba532859ef0602fe0b6c2 /llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp | |
parent | bf5210f8ed44bda0a4329c9c3b02ab773491781a (diff) | |
download | bcm5719-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.cpp | 12 |
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); |