ARMLoadStoreOptimizer.cpp revision 675860758ec8926f9803840615366931aca7f8d8
18e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner//===-- ARMLoadStoreOptimizer.cpp - ARM load / store opt. pass ----*- C++ -*-=// 28e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner// 38e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner// The LLVM Compiler Infrastructure 48e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner// 54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source 64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details. 78e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner// 88e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner//===----------------------------------------------------------------------===// 98e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner// 108e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner// This file contains a pass that performs load / store related peephole 118e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner// optimizations. This pass should be run after register allocation. 128e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner// 138e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner//===----------------------------------------------------------------------===// 148e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 157336f7febb5170b374a4cbffee273ad82ff8a1a3Jordan Rose#define DEBUG_TYPE "arm-ldst-opt" 16d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "ARM.h" 17d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "ARMAddressingModes.h" 180b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "ARMMachineFunctionInfo.h" 190b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "ARMRegisterInfo.h" 200b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/DerivedTypes.h" 21c25e7581b9b8088910da31702d4ca21c4734c6d7Torok Edwin#include "llvm/CodeGen/MachineBasicBlock.h" 22d185f64f828ce1f8b476807a4a1345c0c53d8213Chris Lattner#include "llvm/CodeGen/MachineFunctionPass.h" 23d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/CodeGen/MachineInstr.h" 2492bcb426c3e4503c99324afd4ed0a73521711a56Chris Lattner#include "llvm/CodeGen/MachineInstrBuilder.h" 25df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner#include "llvm/CodeGen/MachineRegisterInfo.h" 26476b242fe7a61e5f9ac6214b0bc5c680d24f152eNick Lewycky#include "llvm/CodeGen/RegisterScavenging.h" 27bcef7df6ec9aba7c5009a4d33944f80227563665Duncan Sands#include "llvm/Target/TargetData.h" 28a896176973d59d8e22514b363d31e8d1becf185eChris Lattner#include "llvm/Target/TargetInstrInfo.h" 295679d18c54ef46170e46f51bf471bb334f2b6525Misha Brukman#include "llvm/Target/TargetMachine.h" 308e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner#include "llvm/Target/TargetRegisterInfo.h" 318e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner#include "llvm/Support/Compiler.h" 32d1e1703c39742f3c9fc3d27a442ff59bbdbfb5aaBenjamin Kramer#include "llvm/ADT/DenseMap.h" 333f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner#include "llvm/ADT/STLExtras.h" 34df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner#include "llvm/ADT/SmallPtrSet.h" 35df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner#include "llvm/ADT/SmallVector.h" 36df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner#include "llvm/ADT/Statistic.h" 378e3a8e0452695643d04c21e15c94b802aef81baeChris Lattnerusing namespace llvm; 388e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 398e3a8e0452695643d04c21e15c94b802aef81baeChris LattnerSTATISTIC(NumLDMGened , "Number of ldm instructions generated"); 408e3a8e0452695643d04c21e15c94b802aef81baeChris LattnerSTATISTIC(NumSTMGened , "Number of stm instructions generated"); 418e3a8e0452695643d04c21e15c94b802aef81baeChris LattnerSTATISTIC(NumFLDMGened, "Number of fldm instructions generated"); 428e3a8e0452695643d04c21e15c94b802aef81baeChris LattnerSTATISTIC(NumFSTMGened, "Number of fstm instructions generated"); 438e3a8e0452695643d04c21e15c94b802aef81baeChris LattnerSTATISTIC(NumLdStMoved, "Number of load / store instructions moved"); 448e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 45df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner/// ARMAllocLoadStoreOpt - Post- register allocation pass the combine 468e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner/// load / store instructions to form ldm / stm instructions. 478e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 488e3a8e0452695643d04c21e15c94b802aef81baeChris Lattnernamespace { 498e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner struct VISIBILITY_HIDDEN ARMLoadStoreOpt : public MachineFunctionPass { 508e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner static char ID; 518e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ARMLoadStoreOpt() : MachineFunctionPass(&ID) {} 52df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 538e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner const TargetInstrInfo *TII; 548e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner const TargetRegisterInfo *TRI; 558e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ARMFunctionInfo *AFI; 568e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner RegScavenger *RS; 578e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 588e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner virtual bool runOnMachineFunction(MachineFunction &Fn); 59df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 608e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner virtual const char *getPassName() const { 618e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return "ARM load / store optimization pass"; 628e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 638e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 647336f7febb5170b374a4cbffee273ad82ff8a1a3Jordan Rose private: 652c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling struct MemOpQueueEntry { 668e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int Offset; 67df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned Position; 688e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MachineBasicBlock::iterator MBBI; 698e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool Merged; 708e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MemOpQueueEntry(int o, int p, MachineBasicBlock::iterator i) 718e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner : Offset(o), Position(p), MBBI(i), Merged(false) {}; 728e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner }; 738e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner typedef SmallVector<MemOpQueueEntry,8> MemOpQueue; 74df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner typedef MemOpQueue::iterator MemOpQueueIter; 75df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 768e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool MergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 778e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int Offset, unsigned Base, bool BaseKill, int Opcode, 788e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ARMCC::CondCodes Pred, unsigned PredReg, unsigned Scratch, 798e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner DebugLoc dl, SmallVector<std::pair<unsigned, bool>, 8> &Regs); 807336f7febb5170b374a4cbffee273ad82ff8a1a3Jordan Rose void MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base, 818e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int Opcode, unsigned Size, 828e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ARMCC::CondCodes Pred, unsigned PredReg, 838e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned Scratch, MemOpQueue &MemOps, 848e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner SmallVector<MachineBasicBlock::iterator, 4> &Merges); 857336f7febb5170b374a4cbffee273ad82ff8a1a3Jordan Rose 868e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner void AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps); 87d343c6b70ec03b357d42e47ce7c00b3c3cb78efdChris Lattner bool FixInvalidRegPairOp(MachineBasicBlock &MBB, 88df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MachineBasicBlock::iterator &MBBI); 898e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool LoadStoreMultipleOpti(MachineBasicBlock &MBB); 908e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool MergeReturnIntoLDM(MachineBasicBlock &MBB); 911b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen }; 921b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen char ARMLoadStoreOpt::ID = 0; 931b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen} 941b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen 951b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesenstatic int getLoadStoreMultipleOpcode(int Opcode) { 961b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen switch (Opcode) { 971b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen case ARM::LDR: 981b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen NumLDMGened++; 997336f7febb5170b374a4cbffee273ad82ff8a1a3Jordan Rose return ARM::LDM; 1001b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen case ARM::STR: 1011b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen NumSTMGened++; 1021b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen return ARM::STM; 1031b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen case ARM::FLDS: 1047336f7febb5170b374a4cbffee273ad82ff8a1a3Jordan Rose NumFLDMGened++; 1051b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen return ARM::FLDMS; 1061b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen case ARM::FSTS: 1071b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen NumFSTMGened++; 1081b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen return ARM::FSTMS; 1091b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen case ARM::FLDD: 1108e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner NumFLDMGened++; 1118e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return ARM::FLDMD; 1128e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner case ARM::FSTD: 1138e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner NumFSTMGened++; 1142c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling return ARM::FSTMD; 1158e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner default: abort(); 1168e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 1178e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return 0; 1188e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner} 1198e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 1208e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner/// MergeOps - Create and insert a LDM or STM with Base as base register and 1218e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner/// registers in Regs as the register operands that would be loaded / stored. 12287d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei/// It returns true if the transformation is done. 12387d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyeibool 12487d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy BenyeiARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB, 1257336f7febb5170b374a4cbffee273ad82ff8a1a3Jordan Rose MachineBasicBlock::iterator MBBI, 1268e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int Offset, unsigned Base, bool BaseKill, 1278e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int Opcode, ARMCC::CondCodes Pred, 1288e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned PredReg, unsigned Scratch, DebugLoc dl, 1298e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner SmallVector<std::pair<unsigned, bool>, 8> &Regs) { 1308e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // Only a single register to load / store. Don't bother. 1318e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned NumRegs = Regs.size(); 1328e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (NumRegs <= 1) 1338e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return false; 1348e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 1358e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ARM_AM::AMSubMode Mode = ARM_AM::ia; 1368e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR; 1378e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (isAM4 && Offset == 4) 1388e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner Mode = ARM_AM::ib; 1398e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner else if (isAM4 && Offset == -4 * (int)NumRegs + 4) 14087d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei Mode = ARM_AM::da; 14187d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei else if (isAM4 && Offset == -4 * (int)NumRegs) 1428e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner Mode = ARM_AM::db; 1438e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner else if (Offset != 0) { 1448e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // If starting offset isn't zero, insert a MI to materialize a new base. 1458e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // But only do so if it is cost effective, i.e. merging more than two 1468e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // loads / stores. 1478e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (NumRegs <= 2) 1488e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return false; 1498e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 1508e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned NewBase; 1518e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (Opcode == ARM::LDR) 1528e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // If it is a load, then just use one of the destination register to 1538e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // use as the new base. 1548e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner NewBase = Regs[NumRegs-1].first; 1558e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner else { 1568e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // Use the scratch register to use as a new base. 1578e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner NewBase = Scratch; 1588e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (NewBase == 0) 1598e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return false; 160ff6c91efcf62d1cb99343fdcb2de6271520a1981Owen Anderson } 161ff6c91efcf62d1cb99343fdcb2de6271520a1981Owen Anderson int BaseOpc = ARM::ADDri; 162ff6c91efcf62d1cb99343fdcb2de6271520a1981Owen Anderson if (Offset < 0) { 1638e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner BaseOpc = ARM::SUBri; 1648e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner Offset = - Offset; 1658e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 1668e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int ImmedOffset = ARM_AM::getSOImmVal(Offset); 1678e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (ImmedOffset == -1) 1688e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return false; // Probably not worth it then. 1698e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 1708e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner BuildMI(MBB, MBBI, dl, TII->get(BaseOpc), NewBase) 1718e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner .addReg(Base, getKillRegState(BaseKill)).addImm(ImmedOffset) 1728e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner .addImm(Pred).addReg(PredReg).addReg(0); 1738e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner Base = NewBase; 1748e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner BaseKill = true; // New base is always killed right its use. 1758e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 1768e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 1778e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool isDPR = Opcode == ARM::FLDD || Opcode == ARM::FSTD; 1788e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool isDef = Opcode == ARM::LDR || Opcode == ARM::FLDS || Opcode == ARM::FLDD; 1792c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling Opcode = getLoadStoreMultipleOpcode(Opcode); 1808e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MachineInstrBuilder MIB = (isAM4) 1812c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling ? BuildMI(MBB, MBBI, dl, TII->get(Opcode)) 1828e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner .addReg(Base, getKillRegState(BaseKill)) 1832c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling .addImm(ARM_AM::getAM4ModeImm(Mode)).addImm(Pred).addReg(PredReg) 1848e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner : BuildMI(MBB, MBBI, dl, TII->get(Opcode)) 1858e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner .addReg(Base, getKillRegState(BaseKill)) 1868e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner .addImm(ARM_AM::getAM5Opc(Mode, false, isDPR ? NumRegs<<1 : NumRegs)) 187df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addImm(Pred).addReg(PredReg); 1888e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner for (unsigned i = 0; i != NumRegs; ++i) 1892c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling MIB = MIB.addReg(Regs[i].first, getDefRegState(isDef) 1908e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner | getKillRegState(Regs[i].second)); 1918e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 1928e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return true; 1938e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner} 19487d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei 1958e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner/// MergeLDR_STR - Merge a number of load / store instructions into one or more 1962c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling/// load / store multiple instructions. 197df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattnervoid 198df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris LattnerARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, 1998e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned Base, int Opcode, unsigned Size, 2008e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ARMCC::CondCodes Pred, unsigned PredReg, 2018e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned Scratch, MemOpQueue &MemOps, 2028e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner SmallVector<MachineBasicBlock::iterator, 4> &Merges) { 2038e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR; 2048e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int Offset = MemOps[SIndex].Offset; 2058e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int SOffset = Offset; 2068e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned Pos = MemOps[SIndex].Position; 2078e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MachineBasicBlock::iterator Loc = MemOps[SIndex].MBBI; 2088e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner DebugLoc dl = Loc->getDebugLoc(); 2098e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned PReg = Loc->getOperand(0).getReg(); 2108e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned PRegNum = ARMRegisterInfo::getRegisterNumbering(PReg); 2118e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool isKill = Loc->getOperand(0).isKill(); 2128e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 213df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner SmallVector<std::pair<unsigned,bool>, 8> Regs; 214df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner Regs.push_back(std::make_pair(PReg, isKill)); 2158e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner for (unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) { 2168e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int NewOffset = MemOps[i].Offset; 2178e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned Reg = MemOps[i].MBBI->getOperand(0).getReg(); 218df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg); 2198e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner isKill = MemOps[i].MBBI->getOperand(0).isKill(); 220df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner // AM4 - register numbers in ascending order. 2218e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // AM5 - consecutive register numbers in ascending order. 2228e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (NewOffset == Offset + (int)Size && 2238e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ((isAM4 && RegNum > PRegNum) || RegNum == PRegNum+1)) { 224df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner Offset += Size; 225df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner Regs.push_back(std::make_pair(Reg, isKill)); 2268e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner PRegNum = RegNum; 227df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } else { 2288e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // Can't merge this in. Try merge the earlier ones first. 2298e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (MergeOps(MBB, ++Loc, SOffset, Base, false, Opcode, Pred, PredReg, 2308e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner Scratch, dl, Regs)) { 231e434d277ca5183eeb6f881000732dcf4c8edd52eChris Lattner Merges.push_back(prior(Loc)); 23295ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling for (unsigned j = SIndex; j < i; ++j) { 2338e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MBB.erase(MemOps[j].MBBI); 2348e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MemOps[j].Merged = true; 2352c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling } 2368e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 237df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MergeLDR_STR(MBB, i, Base, Opcode, Size, Pred, PredReg, Scratch, 238df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MemOps, Merges); 239df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner return; 240df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } 241df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 242df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (MemOps[i].Position > Pos) { 243df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner Pos = MemOps[i].Position; 244df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner Loc = MemOps[i].MBBI; 245df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } 246df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } 247df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 248df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner bool BaseKill = Loc->findRegisterUseOperandIdx(Base, true) != -1; 2498e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (MergeOps(MBB, ++Loc, SOffset, Base, BaseKill, Opcode, Pred, PredReg, 2508e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner Scratch, dl, Regs)) { 2518e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner Merges.push_back(prior(Loc)); 2528e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner for (unsigned i = SIndex, e = MemOps.size(); i != e; ++i) { 2538e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MBB.erase(MemOps[i].MBBI); 2548e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MemOps[i].Merged = true; 2558e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 2568e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 2578e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 2588e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return; 2598e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner} 260df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 261df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner/// getInstrPredicate - If instruction is predicated, returns its predicate 262df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner/// condition, otherwise returns AL. It also returns the condition code 263df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner/// register by reference. 2648e3a8e0452695643d04c21e15c94b802aef81baeChris Lattnerstatic ARMCC::CondCodes getInstrPredicate(MachineInstr *MI, unsigned &PredReg) { 2658e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int PIdx = MI->findFirstPredOperandIdx(); 2668e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (PIdx == -1) { 2672c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling PredReg = 0; 2688e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return ARMCC::AL; 2698e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 2702c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling 2712c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling PredReg = MI->getOperand(PIdx+1).getReg(); 272df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner return (ARMCC::CondCodes)MI->getOperand(PIdx).getImm(); 273df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner} 2748e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 2758e3a8e0452695643d04c21e15c94b802aef81baeChris Lattnerstatic inline bool isMatchingDecrement(MachineInstr *MI, unsigned Base, 276df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned Bytes, ARMCC::CondCodes Pred, 277df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned PredReg) { 278df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned MyPredReg = 0; 2798e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return (MI && MI->getOpcode() == ARM::SUBri && 2808e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MI->getOperand(0).getReg() == Base && 2818e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MI->getOperand(1).getReg() == Base && 2822c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes && 2838e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner getInstrPredicate(MI, MyPredReg) == Pred && 2849fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky MyPredReg == PredReg); 285df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner} 2862c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling 2878e3a8e0452695643d04c21e15c94b802aef81baeChris Lattnerstatic inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base, 28887d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei unsigned Bytes, ARMCC::CondCodes Pred, 28987d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei unsigned PredReg) { 2902c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling unsigned MyPredReg = 0; 2912c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling return (MI && MI->getOpcode() == ARM::ADDri && 2928e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MI->getOperand(0).getReg() == Base && 2938e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MI->getOperand(1).getReg() == Base && 294df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes && 295df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner getInstrPredicate(MI, MyPredReg) == Pred && 296df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MyPredReg == PredReg); 2978e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner} 2982c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling 299df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattnerstatic inline unsigned getLSMultipleTransferSize(MachineInstr *MI) { 3008e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner switch (MI->getOpcode()) { 3018e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner default: return 0; 3029fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::LDR: 3039fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::STR: 3049fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::FLDS: 3059fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::FSTS: 3069fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky return 4; 3079fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::FLDD: 3089fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::FSTD: 3099fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky return 8; 3109fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::LDM: 3119fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::STM: 3129fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky return (MI->getNumOperands() - 4) * 4; 3139fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::FLDMS: 3149fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::FSTMS: 3159fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::FLDMD: 3169fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky case ARM::FSTMD: 3179fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky return ARM_AM::getAM5Offset(MI->getOperand(1).getImm()) * 4; 3189fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky } 3199fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky} 3209fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky 3219fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky/// mergeBaseUpdateLSMultiple - Fold proceeding/trailing inc/dec of base 3229fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky/// register into the LDM/STM/FLDM{D|S}/FSTM{D|S} op when possible: 32387d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei/// 32487d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei/// stmia rn, <ra, rb, rc> 3259fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky/// rn := rn + 4 * 3; 3269fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky/// => 32787d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei/// stmia rn!, <ra, rb, rc> 32887d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei/// 3299fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky/// rn := rn - 4 * 3; 3309fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky/// ldmia rn, <ra, rb, rc> 3319fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky/// => 3329fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky/// ldmdb rn!, <ra, rb, rc> 3339fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewyckystatic bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB, 3349fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky MachineBasicBlock::iterator MBBI, 3359fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky bool &Advance, 3369fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky MachineBasicBlock::iterator &I) { 3378e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MachineInstr *MI = MBBI; 3388e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned Base = MI->getOperand(0).getReg(); 339df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned Bytes = getLSMultipleTransferSize(MI); 340df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned PredReg = 0; 341df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); 342df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner int Opcode = MI->getOpcode(); 343df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner bool isAM4 = Opcode == ARM::LDM || Opcode == ARM::STM; 3448e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 3458e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (isAM4) { 3469fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky if (ARM_AM::getAM4WBFlag(MI->getOperand(1).getImm())) 3478e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return false; 3482c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling 3498e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // Can't use the updating AM4 sub-mode if the base register is also a dest 3509fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky // register. e.g. ldmdb r0!, {r0, r1, r2}. The behavior is undefined. 351df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner for (unsigned i = 3, e = MI->getNumOperands(); i != e; ++i) { 3522c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling if (MI->getOperand(i).getReg() == Base) 3538e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return false; 35487d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei } 35587d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei 3562c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(1).getImm()); 3572c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling if (MBBI != MBB.begin()) { 3588e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MachineBasicBlock::iterator PrevMBBI = prior(MBBI); 3598e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (Mode == ARM_AM::ia && 360df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) { 361df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::db, true)); 362df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MBB.erase(PrevMBBI); 3638e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return true; 3642c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling } else if (Mode == ARM_AM::ib && 365df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) { 3668e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::da, true)); 3678e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MBB.erase(PrevMBBI); 3688e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return true; 3698e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 3708e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 371df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 3729fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky if (MBBI != MBB.end()) { 3739fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky MachineBasicBlock::iterator NextMBBI = next(MBBI); 3749fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) && 3752c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg)) { 3769fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true)); 3778e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (NextMBBI == I) { 3789fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky Advance = true; 3798e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ++I; 3809fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky } 3819fa89334f1045b56e8ae409004e119d47ef17ec7Nick Lewycky MBB.erase(NextMBBI); 3828e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return true; 3838e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) && 384e434d277ca5183eeb6f881000732dcf4c8edd52eChris Lattner isMatchingDecrement(NextMBBI, Base, Bytes, Pred, PredReg)) { 385eff2ab61b5d411fe64ba601d402b7c549644b590Devang Patel MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true)); 3861d92831759620a2e5ce4f5a3088c0a1a77a48c8fChris Lattner if (NextMBBI == I) { 387e434d277ca5183eeb6f881000732dcf4c8edd52eChris Lattner Advance = true; 3881d92831759620a2e5ce4f5a3088c0a1a77a48c8fChris Lattner ++I; 38987d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei } 39087d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei MBB.erase(NextMBBI); 3919100a78bce4e1d34d8ffd5efa2cc79ed864dd1c0Nick Lewycky return true; 392eff2ab61b5d411fe64ba601d402b7c549644b590Devang Patel } 39387d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei } 39487d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei } else { 3959100a78bce4e1d34d8ffd5efa2cc79ed864dd1c0Nick Lewycky // FLDM{D|S}, FSTM{D|S} addressing mode 5 ops. 396eff2ab61b5d411fe64ba601d402b7c549644b590Devang Patel if (ARM_AM::getAM5WBFlag(MI->getOperand(1).getImm())) 3978e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return false; 398eff2ab61b5d411fe64ba601d402b7c549644b590Devang Patel 3999100a78bce4e1d34d8ffd5efa2cc79ed864dd1c0Nick Lewycky ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MI->getOperand(1).getImm()); 4001d92831759620a2e5ce4f5a3088c0a1a77a48c8fChris Lattner unsigned Offset = ARM_AM::getAM5Offset(MI->getOperand(1).getImm()); 401eff2ab61b5d411fe64ba601d402b7c549644b590Devang Patel if (MBBI != MBB.begin()) { 402e434d277ca5183eeb6f881000732dcf4c8edd52eChris Lattner MachineBasicBlock::iterator PrevMBBI = prior(MBBI); 403eff2ab61b5d411fe64ba601d402b7c549644b590Devang Patel if (Mode == ARM_AM::ia && 40415c13d3e63d7745bccad74d547af4e3482193eaaMichael Ilseman isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) { 40595ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::db, true, Offset)); 40695ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling MBB.erase(PrevMBBI); 40795ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling return true; 40895ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling } 40987d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei } 41087d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei 41195ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling if (MBBI != MBB.end()) { 41295ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling MachineBasicBlock::iterator NextMBBI = next(MBBI); 41395ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling if (Mode == ARM_AM::ia && 41495ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg)) { 41595ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::ia, true, Offset)); 41695ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling if (NextMBBI == I) { 41795ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling Advance = true; 41895ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling ++I; 41995ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling } 42095ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling MBB.erase(NextMBBI); 42195ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling } 42295ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling return true; 4238e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 4248e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 4258e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 4268e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return false; 4278e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner} 428df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 4298e3a8e0452695643d04c21e15c94b802aef81baeChris Lattnerstatic unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) { 4308e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner switch (Opc) { 4318e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner case ARM::LDR: return ARM::LDR_PRE; 4322c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling case ARM::STR: return ARM::STR_PRE; 4338e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner case ARM::FLDS: return ARM::FLDMS; 4348e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner case ARM::FLDD: return ARM::FLDMD; 43587d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei case ARM::FSTS: return ARM::FSTMS; 43687d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei case ARM::FSTD: return ARM::FSTMD; 43787d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei default: abort(); 43887d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei } 43987d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei return 0; 4408e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner} 4412c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling 4428e3a8e0452695643d04c21e15c94b802aef81baeChris Lattnerstatic unsigned getPostIndexedLoadStoreOpcode(unsigned Opc) { 4438e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner switch (Opc) { 444df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner case ARM::LDR: return ARM::LDR_POST; 445df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner case ARM::STR: return ARM::STR_POST; 4468e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner case ARM::FLDS: return ARM::FLDMS; 4472c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling case ARM::FLDD: return ARM::FLDMD; 4488e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner case ARM::FSTS: return ARM::FSTMS; 4498e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner case ARM::FSTD: return ARM::FSTMD; 4508e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner default: abort(); 4518e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 4528e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return 0; 4538e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner} 4542c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling 4558e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner/// mergeBaseUpdateLoadStore - Fold proceeding/trailing inc/dec of base 456df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner/// register into the LDR/STR/FLD{D|S}/FST{D|S} op when possible: 457df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattnerstatic bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB, 4588e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MachineBasicBlock::iterator MBBI, 4591d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson const TargetInstrInfo *TII, 460df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner bool &Advance, 4618e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MachineBasicBlock::iterator &I) { 4622c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling MachineInstr *MI = MBBI; 4638e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned Base = MI->getOperand(1).getReg(); 4648e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool BaseKill = MI->getOperand(1).isKill(); 4658e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned Bytes = getLSMultipleTransferSize(MI); 4668e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int Opcode = MI->getOpcode(); 4678e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner DebugLoc dl = MI->getDebugLoc(); 468ae510f3936f2510cebff86ea38536b30fdf2a30cBill Wendling bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR; 469ae510f3936f2510cebff86ea38536b30fdf2a30cBill Wendling if ((isAM2 && ARM_AM::getAM2Offset(MI->getOperand(3).getImm()) != 0) || 470ae510f3936f2510cebff86ea38536b30fdf2a30cBill Wendling (!isAM2 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0)) 471ae510f3936f2510cebff86ea38536b30fdf2a30cBill Wendling return false; 472ae510f3936f2510cebff86ea38536b30fdf2a30cBill Wendling 473df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner bool isLd = Opcode == ARM::LDR || Opcode == ARM::FLDS || Opcode == ARM::FLDD; 474df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner // Can't do the merge if the destination register is the same as the would-be 475df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner // writeback register. 476df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (isLd && MI->getOperand(0).getReg() == Base) 477df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner return false; 478bb46f52027416598a662dc1c58f48d9d56b1a65bRafael Espindola 4793d10a5a75794356a0a568ce283713adc3a963200Bill Wendling unsigned PredReg = 0; 4805e721d768254a920b78b9129d79a84c0163cb3f4Bill Wendling ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); 48132811bef956e0fae4329e6515420d85f7e510660Bill Wendling bool DoMerge = false; 482df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner ARM_AM::AddrOpc AddSub = ARM_AM::add; 483266c7bbbbcc4b326dea82e577de1a415d6acc23eChris Lattner unsigned NewOpc = 0; 484df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (MBBI != MBB.begin()) { 485667d4b8de6dea70195ff12ef39a4deebffa2f5c7Duncan Sands MachineBasicBlock::iterator PrevMBBI = prior(MBBI); 48632811bef956e0fae4329e6515420d85f7e510660Bill Wendling if (isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) { 487df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner DoMerge = true; 488667d4b8de6dea70195ff12ef39a4deebffa2f5c7Duncan Sands AddSub = ARM_AM::sub; 489df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner NewOpc = getPreIndexedLoadStoreOpcode(Opcode); 490df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } else if (isAM2 && isMatchingIncrement(PrevMBBI, Base, Bytes, 491df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner Pred, PredReg)) { 492df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner DoMerge = true; 493df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner NewOpc = getPreIndexedLoadStoreOpcode(Opcode); 494df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } 495df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (DoMerge) 496bea4626f93c830e31f82cc947df28fdae583cd09Rafael Espindola MBB.erase(PrevMBBI); 497a2de37c897556fbd1f94a3ed84ad27accd8f8debMichael Gottesman } 498df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 499df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (!DoMerge && MBBI != MBB.end()) { 500df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MachineBasicBlock::iterator NextMBBI = next(MBBI); 501ce718ff9f42c7da092eaa01dd0242e8d5ba84713Hans Wennborg if (isAM2 && isMatchingDecrement(NextMBBI, Base, Bytes, Pred, PredReg)) { 502ce718ff9f42c7da092eaa01dd0242e8d5ba84713Hans Wennborg DoMerge = true; 503ce718ff9f42c7da092eaa01dd0242e8d5ba84713Hans Wennborg AddSub = ARM_AM::sub; 504df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner NewOpc = getPostIndexedLoadStoreOpcode(Opcode); 505df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } else if (isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg)) { 506df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner DoMerge = true; 507df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner NewOpc = getPostIndexedLoadStoreOpcode(Opcode); 508df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } 509df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (DoMerge) { 510df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (NextMBBI == I) { 5110f96817d010c4d2abbb0e1c1cfc56ff537010081Bill Wendling Advance = true; 5123defc0bfa600cc253f0cba0fe781aa49435d968aBill Wendling ++I; 513df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } 514df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MBB.erase(NextMBBI); 51547f3513dd574535aeb40c9eb11134f0899e92269Eli Friedman } 51647f3513dd574535aeb40c9eb11134f0899e92269Eli Friedman } 51747f3513dd574535aeb40c9eb11134f0899e92269Eli Friedman 51847f3513dd574535aeb40c9eb11134f0899e92269Eli Friedman if (!DoMerge) 51947f3513dd574535aeb40c9eb11134f0899e92269Eli Friedman return false; 52047f3513dd574535aeb40c9eb11134f0899e92269Eli Friedman 52147f3513dd574535aeb40c9eb11134f0899e92269Eli Friedman bool isDPR = NewOpc == ARM::FLDMD || NewOpc == ARM::FSTMD; 52247f3513dd574535aeb40c9eb11134f0899e92269Eli Friedman unsigned Offset = isAM2 ? ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift) 52347f3513dd574535aeb40c9eb11134f0899e92269Eli Friedman : ARM_AM::getAM5Opc((AddSub == ARM_AM::sub) ? ARM_AM::db : ARM_AM::ia, 524ae510f3936f2510cebff86ea38536b30fdf2a30cBill Wendling true, isDPR ? 2 : 1); 525ae510f3936f2510cebff86ea38536b30fdf2a30cBill Wendling if (isLd) { 526ae510f3936f2510cebff86ea38536b30fdf2a30cBill Wendling if (isAM2) 527ae510f3936f2510cebff86ea38536b30fdf2a30cBill Wendling // LDR_PRE, LDR_POST; 528ae510f3936f2510cebff86ea38536b30fdf2a30cBill Wendling BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg()) 52908d012eba490c4906ec773c39db9f2a18a78c997Dan Gohman .addReg(Base, RegState::Define) 53008d012eba490c4906ec773c39db9f2a18a78c997Dan Gohman .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg); 5311224c386981f7948f298ed9ad444c40609570f2eDan Gohman else 532dd8004dc73d091ccb3927dbbc3b41639a3738ae3Dan Gohman // FLDMS, FLDMD 533df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner BuildMI(MBB, MBBI, dl, TII->get(NewOpc)) 534df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addReg(Base, getKillRegState(BaseKill)) 535df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addImm(Offset).addImm(Pred).addReg(PredReg) 536df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addReg(MI->getOperand(0).getReg(), RegState::Define); 537df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } else { 538df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MachineOperand &MO = MI->getOperand(0); 539df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (isAM2) 5408ba2d5befc05ca73d3bac8708819bbbe759e2cf9Dale Johannesen // STR_PRE, STR_POST; 541581600bfc3060ee13afb278cd87e25da5b5f7db2Chad Rosier BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base) 542df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addReg(MO.getReg(), getKillRegState(MO.isKill())) 543df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg); 544df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner else 545df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner // FSTMS, FSTMD 546df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner BuildMI(MBB, MBBI, dl, TII->get(NewOpc)).addReg(Base).addImm(Offset) 547df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addImm(Pred).addReg(PredReg) 548df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addReg(MO.getReg(), getKillRegState(MO.isKill())); 549ded05e34b65dc42998e9db6ca1abd513e7a9d120Anton Korobeynikov } 550385f5a99ecc7fee48a7539bc63d3e1d3b5089c0dAnton Korobeynikov MBB.erase(MBBI); 551385f5a99ecc7fee48a7539bc63d3e1d3b5089c0dAnton Korobeynikov 552385f5a99ecc7fee48a7539bc63d3e1d3b5089c0dAnton Korobeynikov return true; 553211a14e476abc9b864ab6a5d5e0bbb86d288b650Anton Korobeynikov} 554f9930da2ef72350c6c805af09e754e4e6e13d47bChe-Liang Chiou 555f9930da2ef72350c6c805af09e754e4e6e13d47bChe-Liang Chiou/// isMemoryOp - Returns true if instruction is a memory operations (that this 556e53d6051b7e173722351a5647bfd71eebee3d837Micah Villmow/// pass is capable of operating on). 557e53d6051b7e173722351a5647bfd71eebee3d837Micah Villmowstatic bool isMemoryOp(MachineInstr *MI) { 5583575222175b4982f380ff291bb17be67aadc0966Elena Demikhovsky int Opcode = MI->getOpcode(); 559385f5a99ecc7fee48a7539bc63d3e1d3b5089c0dAnton Korobeynikov switch (Opcode) { 560df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner default: break; 561df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner case ARM::LDR: 562df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner case ARM::STR: 56395ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling return MI->getOperand(1).isReg() && MI->getOperand(2).getReg() == 0; 56495ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling case ARM::FLDS: 56595ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling case ARM::FSTS: 5662253a2f52f3c46ae75cd05f5885acb987bd1d6b6Michael Gottesman return MI->getOperand(1).isReg(); 56795ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling case ARM::FLDD: 56877226a03dca98e6237c1068f2652fe41bea7b687Diego Novillo case ARM::FSTD: 56995ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling return MI->getOperand(1).isReg(); 570df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } 57195ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling return false; 57295ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling} 57395ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling 574df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner/// AdvanceRS - Advance register scavenger to just before the earliest memory 575143d46476cdcf5b88b9ee18ebd799e5820a2db0eBill Wendling/// op that is being merged. 576df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattnervoid ARMLoadStoreOpt::AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps) { 57795ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling MachineBasicBlock::iterator Loc = MemOps[0].MBBI; 57895ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling unsigned Position = MemOps[0].Position; 57995ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling for (unsigned i = 1, e = MemOps.size(); i != e; ++i) { 58095ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling if (MemOps[i].Position < Position) { 58195ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling Position = MemOps[i].Position; 58295ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling Loc = MemOps[i].MBBI; 58395ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling } 58495ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling } 585df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 586df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (Loc != MBB.begin()) 587456ca048af35163b9f52187e92a23ee0a9f059e8Stephen Lin RS->forward(prior(Loc)); 58825456ef74ca7ac9bf46451f28d995f785e2596deRafael Espindola} 58995ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling 59095ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendlingstatic int getMemoryOpOffset(const MachineInstr *MI) { 591df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner int Opcode = MI->getOpcode(); 592df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR; 593114baee1fa017daefad2339c77b45b9ca3d79a41Bill Wendling bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD; 5948eec41fc778e99d42172a7f6de76faa43a6d8847Kostya Serebryany unsigned NumOperands = MI->getDesc().getNumOperands(); 5958eec41fc778e99d42172a7f6de76faa43a6d8847Kostya Serebryany unsigned OffField = MI->getOperand(NumOperands-3).getImm(); 5968eec41fc778e99d42172a7f6de76faa43a6d8847Kostya Serebryany int Offset = isAM2 59795ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling ? ARM_AM::getAM2Offset(OffField) 59895ce4c2ffb0ff31a79b060fb112659322a5be3bfBill Wendling : (isAM3 ? ARM_AM::getAM3Offset(OffField) 599df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner : ARM_AM::getAM5Offset(OffField) * 4); 600df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (isAM2) { 601df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (ARM_AM::getAM2Op(OffField) == ARM_AM::sub) 602df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner Offset = -Offset; 603df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } else if (isAM3) { 604df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (ARM_AM::getAM3Op(OffField) == ARM_AM::sub) 605df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner Offset = -Offset; 606df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } else { 6079ea4034e007a83c778cd306ea66481be1317a51bMisha Brukman if (ARM_AM::getAM5Op(OffField) == ARM_AM::sub) 608ff03048c1350fcc4fda1ef6d6c57252f3a950854Eli Friedman Offset = -Offset; 609ff03048c1350fcc4fda1ef6d6c57252f3a950854Eli Friedman } 610ff03048c1350fcc4fda1ef6d6c57252f3a950854Eli Friedman return Offset; 611df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner} 61209d9ef4122414a1a2ec95f52d660d6500f2819d0Chris Lattner 613e6e8826870bee3facb04f950f0bd725f8a88623dBill Wendlingstatic void InsertLDR_STR(MachineBasicBlock &MBB, 614e6e8826870bee3facb04f950f0bd725f8a88623dBill Wendling MachineBasicBlock::iterator &MBBI, 615e6e8826870bee3facb04f950f0bd725f8a88623dBill Wendling int OffImm, bool isDef, 616e6e8826870bee3facb04f950f0bd725f8a88623dBill Wendling DebugLoc dl, unsigned NewOpc, 617e6e8826870bee3facb04f950f0bd725f8a88623dBill Wendling unsigned Reg, bool RegKill, 6188e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned BaseReg, bool BaseKill, 6198e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned OffReg, bool OffKill, 6208e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ARMCC::CondCodes Pred, unsigned PredReg, 621df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner const TargetInstrInfo *TII) { 6228e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned Offset; 623df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (OffImm < 0) 6241d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson Offset = ARM_AM::getAM2Opc(ARM_AM::sub, -OffImm, ARM_AM::no_shift); 625ce16339930a2b03e53b4e6399ef59c092a7f2cfaDan Gohman else 6261d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson Offset = ARM_AM::getAM2Opc(ARM_AM::add, OffImm, ARM_AM::no_shift); 6271d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson if (isDef) 6281d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc), Reg) 6291d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson .addReg(BaseReg, getKillRegState(BaseKill)) 6301d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson .addReg(OffReg, getKillRegState(OffKill)) 6311d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson .addImm(Offset) 6321d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson .addImm(Pred).addReg(PredReg); 633bb811a244567aa8a1522203f15588f4d001b7353Dale Johannesen else 6348e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc)) 6358e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner .addReg(Reg, getKillRegState(RegKill)) 6368e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner .addReg(BaseReg, getKillRegState(BaseKill)) 637df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addReg(OffReg, getKillRegState(OffKill)) 638df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addImm(Offset) 639df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addImm(Pred).addReg(PredReg); 640df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner} 641ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman 642ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohmanbool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB, 643ae3a0be92e33bc716722aa600983fc1535acb122Dan Gohman MachineBasicBlock::iterator &MBBI) { 644df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MachineInstr *MI = &*MBBI; 645df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned Opcode = MI->getOpcode(); 646df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (Opcode == ARM::LDRD || Opcode == ARM::STRD) { 647df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned EvenReg = MI->getOperand(0).getReg(); 648df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned OddReg = MI->getOperand(1).getReg(); 649df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned EvenRegNum = TRI->getDwarfRegNum(EvenReg, false); 650df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned OddRegNum = TRI->getDwarfRegNum(OddReg, false); 651df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if ((EvenRegNum & 1) == 0 && (EvenRegNum + 1) == OddRegNum) 652df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner return false; 653df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 654df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner bool isDef = Opcode == ARM::LDRD; 655df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner bool EvenKill = isDef ? false : MI->getOperand(0).isKill(); 656df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner bool OddKill = isDef ? false : MI->getOperand(1).isKill(); 657df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner const MachineOperand &BaseOp = MI->getOperand(2); 658df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned BaseReg = BaseOp.getReg(); 659df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner bool BaseKill = BaseOp.isKill(); 660df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner const MachineOperand &OffOp = MI->getOperand(3); 661df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned OffReg = OffOp.getReg(); 662df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner bool OffKill = OffOp.isKill(); 663df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner int OffImm = getMemoryOpOffset(MI); 664df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned PredReg = 0; 665df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg); 666df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner 667df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (OddRegNum > EvenRegNum && OffReg == 0 && OffImm == 0) { 668df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner // Ascending register numbers and no offset. It's safe to change it to a 669ab21db79ef1d2530880ad11f21f0b87ffca02dd4Chris Lattner // ldm or stm. 670df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned NewOpc = (Opcode == ARM::LDRD) ? ARM::LDM : ARM::STM; 671dccc03b2423fe65efb5963ae816b99c24fc53374Bill Wendling BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc)) 672df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addReg(BaseReg, getKillRegState(BaseKill)) 673df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) 674df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addImm(Pred).addReg(PredReg) 675df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addReg(EvenReg, getDefRegState(isDef)) 676df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner .addReg(OddReg, getDefRegState(isDef)); 677ff03048c1350fcc4fda1ef6d6c57252f3a950854Eli Friedman } else { 678ff03048c1350fcc4fda1ef6d6c57252f3a950854Eli Friedman // Split into two instructions. 67947f3513dd574535aeb40c9eb11134f0899e92269Eli Friedman unsigned NewOpc = (Opcode == ARM::LDRD) ? ARM::LDR : ARM::STR; 680df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner DebugLoc dl = MBBI->getDebugLoc(); 681df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner // If this is a load and base register is killed, it may have been 682df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner // re-defed by the load, make sure the first load does not clobber it. 683df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (isDef && 684df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner (BaseKill || OffKill) && 685df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner (TRI->regsOverlap(EvenReg, BaseReg) || 686df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner (OffReg && TRI->regsOverlap(EvenReg, OffReg)))) { 687e6e8826870bee3facb04f950f0bd725f8a88623dBill Wendling assert(!TRI->regsOverlap(OddReg, BaseReg) && 6882c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling (!OffReg || !TRI->regsOverlap(OddReg, OffReg))); 6892c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling InsertLDR_STR(MBB, MBBI, OffImm+4, isDef, dl, NewOpc, OddReg, OddKill, 6908e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner BaseReg, false, OffReg, false, Pred, PredReg, TII); 6918e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner InsertLDR_STR(MBB, MBBI, OffImm, isDef, dl, NewOpc, EvenReg, EvenKill, 6928e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner BaseReg, BaseKill, OffReg, OffKill, Pred, PredReg, TII); 69387d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei } else { 69487d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei InsertLDR_STR(MBB, MBBI, OffImm, isDef, dl, NewOpc, EvenReg, EvenKill, 6958e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner BaseReg, false, OffReg, false, Pred, PredReg, TII); 6968e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner InsertLDR_STR(MBB, MBBI, OffImm+4, isDef, dl, NewOpc, OddReg, OddKill, 697689ad6ef3fd2e89394f1e8860dfebfe56b73c3daDaniel Dunbar BaseReg, BaseKill, OffReg, OffKill, Pred, PredReg, TII); 6988e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 6998e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 70040f8f6264d5af2c38e797e0dc59827cd231e8ff7Jay Foad 701df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MBBI = prior(MBBI); 702df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MBB.erase(MI); 7038e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 7042c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling return false; 7054ce0df610879e82d9853c6a38a75b1883feaee06Chris Lattner} 7068e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 7078e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner/// LoadStoreMultipleOpti - An optimization pass to turn multiple LDR / STR 708df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner/// ops of the same base and incrementing offset into LDM / STM ops. 7098e3a8e0452695643d04c21e15c94b802aef81baeChris Lattnerbool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { 7102c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling unsigned NumMerges = 0; 711df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned NumMemOps = 0; 7128e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MemOpQueue MemOps; 713df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned CurrBase = 0; 7148e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int CurrOpc = -1; 7158e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned CurrSize = 0; 71610c6d12a9fd4dab411091f64db4db69670b88850Bill Wendling ARMCC::CondCodes CurrPred = ARMCC::AL; 7178e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned CurrPredReg = 0; 7188e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned Position = 0; 7198e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner SmallVector<MachineBasicBlock::iterator,4> Merges; 7208e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 7218e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner RS->enterBasicBlock(&MBB); 7228e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 723057beb8d4fe8d5dad98ad80a49a649730c3a3eb0Tobias Grosser while (MBBI != E) { 724df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (FixInvalidRegPairOp(MBB, MBBI)) 7258e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner continue; 7262c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling 7278e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool Advance = false; 7288d2a004822f9cc5bf38d5ef14494e2f0faa82b8cDavid Blaikie bool TryMerge = false; 7298e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool Clobber = false; 7308e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 7318e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner bool isMemOp = isMemoryOp(MBBI); 7328e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (isMemOp) { 7338e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int Opcode = MBBI->getOpcode(); 73487d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei unsigned Size = getLSMultipleTransferSize(MBBI); 735df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner unsigned Base = MBBI->getOperand(1).getReg(); 7368e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner unsigned PredReg = 0; 737df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner ARMCC::CondCodes Pred = getInstrPredicate(MBBI, PredReg); 7388e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int Offset = getMemoryOpOffset(MBBI); 7392c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling // Watch out for: 74087d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei // r4 := ldr [r5] 7418e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // r5 := ldr [r5, #4] 7422c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling // r6 := ldr [r5, #8] 7438e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // 7448e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // The second ldr has effectively broken the chain even though it 7458e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // looks like the later ldr(s) use the same base register. Try to 746ce16339930a2b03e53b4e6399ef59c092a7f2cfaDan Gohman // merge the ldr's so far, including this one. But don't try to 747df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner // combine the following ldr(s). 748df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner Clobber = (Opcode == ARM::LDR && Base == MBBI->getOperand(0).getReg()); 7498e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (CurrBase == 0 && !Clobber) { 7502c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling // Start of a new chain. 7518e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner CurrBase = Base; 7528e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner CurrOpc = Opcode; 753c23197a26f34f559ea9797de51e187087c039c42Torok Edwin CurrSize = Size; 7548e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner CurrPred = Pred; 7558e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner CurrPredReg = PredReg; 7561b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI)); 7570a29cb045444c13160e90fe7942a9d7c720185edTim Northover NumMemOps++; 758df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner Advance = true; 7598e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } else { 7608e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (Clobber) { 7611b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen TryMerge = true; 7620a29cb045444c13160e90fe7942a9d7c720185edTim Northover Advance = true; 763df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } 7648e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 7658e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (CurrOpc == Opcode && CurrBase == Base && CurrPred == Pred) { 7661b25cb2416c46a6cebf2a6c52235e9fe46a10d11Dale Johannesen // No need to match PredReg. 7670a29cb045444c13160e90fe7942a9d7c720185edTim Northover // Continue adding to the queue. 768df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (Offset > MemOps.back().Offset) { 769057beb8d4fe8d5dad98ad80a49a649730c3a3eb0Tobias Grosser MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI)); 7700a29cb045444c13160e90fe7942a9d7c720185edTim Northover NumMemOps++; 7710a29cb045444c13160e90fe7942a9d7c720185edTim Northover Advance = true; 772057beb8d4fe8d5dad98ad80a49a649730c3a3eb0Tobias Grosser } else { 7738e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner for (MemOpQueueIter I = MemOps.begin(), E = MemOps.end(); 7748e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner I != E; ++I) { 7758e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (Offset < I->Offset) { 7768e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MemOps.insert(I, MemOpQueueEntry(Offset, Position, MBBI)); 7778e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner NumMemOps++; 7788e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner Advance = true; 7798e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner break; 7808e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } else if (Offset == I->Offset) { 7818e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // Collision! This can't be merged! 7828e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner break; 7838e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 7848e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 785df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } 78606be8b8a698b3d71aa93f30456b197ca6d54b1d0Craig Topper } 78787d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei } 78887d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei } 7898e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 7908e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (Advance) { 791df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner ++Position; 7928e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ++MBBI; 793df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } else 7948e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner TryMerge = true; 7952c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling 796df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (TryMerge) { 7978e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (NumMemOps > 1) { 7982c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling // Try to find a free register to use as a new base in case it's needed. 7998e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // First advance to the instruction just before the start of the chain. 8002c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling AdvanceRS(MBB, MemOps); 8018e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // Find a scratch register. Make sure it's a call clobbered register or 80287d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei // a spilled callee-saved register. 8032c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling unsigned Scratch = RS->FindUnusedReg(&ARM::GPRRegClass, true); 8042c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling if (!Scratch) 8058e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner Scratch = RS->FindUnusedReg(&ARM::GPRRegClass, 8068e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner AFI->getSpilledCSRegisters()); 8078e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // Process the load / store instructions. 808df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner RS->forward(prior(MBBI)); 8098e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 810df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner // Merge ops. 8118e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner Merges.clear(); 8128e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize, 8132c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling CurrPred, CurrPredReg, Scratch, MemOps, Merges); 8148e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 8158e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // Try folding preceeding/trailing base inc/dec into the generated 8168e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // LDM/STM ops. 8178e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner for (unsigned i = 0, e = Merges.size(); i < e; ++i) 8188e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (mergeBaseUpdateLSMultiple(MBB, Merges[i], Advance, MBBI)) 8198e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ++NumMerges; 8208e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner NumMerges += Merges.size(); 821689ad6ef3fd2e89394f1e8860dfebfe56b73c3daDaniel Dunbar 8228e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // Try folding preceeding/trailing base inc/dec into those load/store 8238e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // that were not merged to form LDM/STM ops. 8248e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner for (unsigned i = 0; i != NumMemOps; ++i) 82540f8f6264d5af2c38e797e0dc59827cd231e8ff7Jay Foad if (!MemOps[i].Merged) 826df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner if (mergeBaseUpdateLoadStore(MBB, MemOps[i].MBBI, TII,Advance,MBBI)) 8278e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ++NumMerges; 8288e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 8298e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // RS may be pointing to an instruction that's deleted. 83040f8f6264d5af2c38e797e0dc59827cd231e8ff7Jay Foad RS->skipTo(prior(MBBI)); 831df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } else if (NumMemOps == 1) { 8328e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner // Try folding preceeding/trailing base inc/dec into the single 833df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner // load/store. 8348e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (mergeBaseUpdateLoadStore(MBB, MemOps[0].MBBI, TII, Advance, MBBI)) { 8358e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ++NumMerges; 8368e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner RS->forward(prior(MBBI)); 8372c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling } 8388e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 83987d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei 8402c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling CurrBase = 0; 8418e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner CurrOpc = -1; 84287d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei CurrSize = 0; 84387d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei CurrPred = ARMCC::AL; 84487d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei CurrPredReg = 0; 8458e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (NumMemOps) { 84687d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei MemOps.clear(); 8478e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner NumMemOps = 0; 8488e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 8492c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling 8502402123413080aee8e9418e4f08b8613ef5cc360Nick Lewycky // If iterator hasn't been advanced and this is not a memory op, skip it. 851df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner // It can't start a new chain anyway. 8528e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (!Advance && !isMemOp && MBBI != E) { 8538e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ++Position; 8548e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner ++MBBI; 855df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } 8568e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 8578e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner } 85887d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei return NumMerges > 0; 859df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner} 8602c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling 8618e3a8e0452695643d04c21e15c94b802aef81baeChris Lattnernamespace { 86287d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei struct OffsetCompare { 8632c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling bool operator()(const MachineInstr *LHS, const MachineInstr *RHS) const { 8648e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int LOffset = getMemoryOpOffset(LHS); 8658e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner int ROffset = getMemoryOpOffset(RHS); 8668e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner assert(LHS == RHS || LOffset != ROffset); 8678e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner return LOffset > ROffset; 868df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner } 8698e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner }; 8702c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling} 8718e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner 8722c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling/// MergeReturnIntoLDM - If this is a exit BB, try merging the return op 8738e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner/// (bx lr) into the preceeding stack restore so it directly restore the value 87487d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei/// of LR into pc. 8752c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling/// ldmfd sp!, {r7, lr} 8768e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner/// bx lr 87787d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei/// => 87887d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei/// ldmfd sp!, {r7, pc} 87987d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyeibool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) { 8808e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (MBB.empty()) return false; 88187d0b9ed1462705dd9bf1cb7f67d0bf03af776c8Guy Benyei 8828e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner MachineBasicBlock::iterator MBBI = prior(MBB.end()); 8838e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (MBBI->getOpcode() == ARM::BX_RET && MBBI != MBB.begin()) { 8842c6fd8c7ceea0392635ce21038d2b7fc215d9116Bill Wendling MachineInstr *PrevMI = prior(MBBI); 8852402123413080aee8e9418e4f08b8613ef5cc360Nick Lewycky if (PrevMI->getOpcode() == ARM::LDM) { 886df98617b23315e427cc4fad8ccfdd50d68bec2f9Chris Lattner MachineOperand &MO = PrevMI->getOperand(PrevMI->getNumOperands()-1); 8878e3a8e0452695643d04c21e15c94b802aef81baeChris Lattner if (MO.getReg() == ARM::LR) { 888 PrevMI->setDesc(TII->get(ARM::LDM_RET)); 889 MO.setReg(ARM::PC); 890 MBB.erase(MBBI); 891 return true; 892 } 893 } 894 } 895 return false; 896} 897 898bool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) { 899 const TargetMachine &TM = Fn.getTarget(); 900 AFI = Fn.getInfo<ARMFunctionInfo>(); 901 TII = TM.getInstrInfo(); 902 TRI = TM.getRegisterInfo(); 903 RS = new RegScavenger(); 904 905 bool Modified = false; 906 for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; 907 ++MFI) { 908 MachineBasicBlock &MBB = *MFI; 909 Modified |= LoadStoreMultipleOpti(MBB); 910 Modified |= MergeReturnIntoLDM(MBB); 911 } 912 913 delete RS; 914 return Modified; 915} 916 917 918/// ARMPreAllocLoadStoreOpt - Pre- register allocation pass that move 919/// load / stores from consecutive locations close to make it more 920/// likely they will be combined later. 921 922namespace { 923 struct VISIBILITY_HIDDEN ARMPreAllocLoadStoreOpt : public MachineFunctionPass{ 924 static char ID; 925 ARMPreAllocLoadStoreOpt() : MachineFunctionPass(&ID) {} 926 927 const TargetData *TD; 928 const TargetInstrInfo *TII; 929 const TargetRegisterInfo *TRI; 930 const ARMSubtarget *STI; 931 MachineRegisterInfo *MRI; 932 933 virtual bool runOnMachineFunction(MachineFunction &Fn); 934 935 virtual const char *getPassName() const { 936 return "ARM pre- register allocation load / store optimization pass"; 937 } 938 939 private: 940 bool CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, DebugLoc &dl, 941 unsigned &NewOpc, unsigned &EvenReg, 942 unsigned &OddReg, unsigned &BaseReg, 943 unsigned &OffReg, unsigned &Offset, 944 unsigned &PredReg, ARMCC::CondCodes &Pred); 945 bool RescheduleOps(MachineBasicBlock *MBB, 946 SmallVector<MachineInstr*, 4> &Ops, 947 unsigned Base, bool isLd, 948 DenseMap<MachineInstr*, unsigned> &MI2LocMap); 949 bool RescheduleLoadStoreInstrs(MachineBasicBlock *MBB); 950 }; 951 char ARMPreAllocLoadStoreOpt::ID = 0; 952} 953 954bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) { 955 TD = Fn.getTarget().getTargetData(); 956 TII = Fn.getTarget().getInstrInfo(); 957 TRI = Fn.getTarget().getRegisterInfo(); 958 STI = &Fn.getTarget().getSubtarget<ARMSubtarget>(); 959 MRI = &Fn.getRegInfo(); 960 961 bool Modified = false; 962 for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; 963 ++MFI) 964 Modified |= RescheduleLoadStoreInstrs(MFI); 965 966 return Modified; 967} 968 969static bool IsSafeToMove(bool isLd, unsigned Base, 970 MachineBasicBlock::iterator I, 971 MachineBasicBlock::iterator E, 972 SmallPtrSet<MachineInstr*, 4> MoveOps, 973 const TargetRegisterInfo *TRI) { 974 // Are there stores / loads / calls between them? 975 // FIXME: This is overly conservative. We should make use of alias information 976 // some day. 977 while (++I != E) { 978 const TargetInstrDesc &TID = I->getDesc(); 979 if (TID.isCall() || TID.isTerminator() || TID.hasUnmodeledSideEffects()) 980 return false; 981 if (isLd && TID.mayStore()) 982 return false; 983 if (!isLd) { 984 if (TID.mayLoad()) 985 return false; 986 // It's not safe to move the first 'str' down. 987 // str r1, [r0] 988 // strh r5, [r0] 989 // str r4, [r0, #+4] 990 if (TID.mayStore() && !MoveOps.count(&*I)) 991 return false; 992 } 993 for (unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) { 994 MachineOperand &MO = I->getOperand(j); 995 if (MO.isReg() && MO.isDef() && TRI->regsOverlap(MO.getReg(), Base)) 996 return false; 997 } 998 } 999 return true; 1000} 1001 1002bool 1003ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, 1004 DebugLoc &dl, 1005 unsigned &NewOpc, unsigned &EvenReg, 1006 unsigned &OddReg, unsigned &BaseReg, 1007 unsigned &OffReg, unsigned &Offset, 1008 unsigned &PredReg, 1009 ARMCC::CondCodes &Pred) { 1010 // FIXME: FLDS / FSTS -> FLDD / FSTD 1011 unsigned Opcode = Op0->getOpcode(); 1012 if (Opcode == ARM::LDR) 1013 NewOpc = ARM::LDRD; 1014 else if (Opcode == ARM::STR) 1015 NewOpc = ARM::STRD; 1016 else 1017 return 0; 1018 1019 // Must sure the base address satisfies i64 ld / st alignment requirement. 1020 if (!Op0->hasOneMemOperand() || 1021 !Op0->memoperands_begin()->getValue() || 1022 Op0->memoperands_begin()->isVolatile()) 1023 return false; 1024 1025 unsigned Align = Op0->memoperands_begin()->getAlignment(); 1026 unsigned ReqAlign = STI->hasV6Ops() 1027 ? TD->getPrefTypeAlignment(Type::Int64Ty) : 8; // Pre-v6 need 8-byte align 1028 if (Align < ReqAlign) 1029 return false; 1030 1031 // Then make sure the immediate offset fits. 1032 int OffImm = getMemoryOpOffset(Op0); 1033 ARM_AM::AddrOpc AddSub = ARM_AM::add; 1034 if (OffImm < 0) { 1035 AddSub = ARM_AM::sub; 1036 OffImm = - OffImm; 1037 } 1038 if (OffImm >= 256) // 8 bits 1039 return false; 1040 Offset = ARM_AM::getAM3Opc(AddSub, OffImm); 1041 1042 EvenReg = Op0->getOperand(0).getReg(); 1043 OddReg = Op1->getOperand(0).getReg(); 1044 if (EvenReg == OddReg) 1045 return false; 1046 BaseReg = Op0->getOperand(1).getReg(); 1047 OffReg = Op0->getOperand(2).getReg(); 1048 Pred = getInstrPredicate(Op0, PredReg); 1049 dl = Op0->getDebugLoc(); 1050 return true; 1051} 1052 1053bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, 1054 SmallVector<MachineInstr*, 4> &Ops, 1055 unsigned Base, bool isLd, 1056 DenseMap<MachineInstr*, unsigned> &MI2LocMap) { 1057 bool RetVal = false; 1058 1059 // Sort by offset (in reverse order). 1060 std::sort(Ops.begin(), Ops.end(), OffsetCompare()); 1061 1062 // The loads / stores of the same base are in order. Scan them from first to 1063 // last and check for the followins: 1064 // 1. Any def of base. 1065 // 2. Any gaps. 1066 while (Ops.size() > 1) { 1067 unsigned FirstLoc = ~0U; 1068 unsigned LastLoc = 0; 1069 MachineInstr *FirstOp = 0; 1070 MachineInstr *LastOp = 0; 1071 int LastOffset = 0; 1072 unsigned LastBytes = 0; 1073 unsigned NumMove = 0; 1074 for (int i = Ops.size() - 1; i >= 0; --i) { 1075 MachineInstr *Op = Ops[i]; 1076 unsigned Loc = MI2LocMap[Op]; 1077 if (Loc <= FirstLoc) { 1078 FirstLoc = Loc; 1079 FirstOp = Op; 1080 } 1081 if (Loc >= LastLoc) { 1082 LastLoc = Loc; 1083 LastOp = Op; 1084 } 1085 1086 int Offset = getMemoryOpOffset(Op); 1087 unsigned Bytes = getLSMultipleTransferSize(Op); 1088 if (LastBytes) { 1089 if (Bytes != LastBytes || Offset != (LastOffset + (int)Bytes)) 1090 break; 1091 } 1092 LastOffset = Offset; 1093 LastBytes = Bytes; 1094 if (++NumMove == 4) 1095 break; 1096 } 1097 1098 if (NumMove <= 1) 1099 Ops.pop_back(); 1100 else { 1101 SmallPtrSet<MachineInstr*, 4> MoveOps; 1102 for (int i = NumMove-1; i >= 0; --i) 1103 MoveOps.insert(Ops[i]); 1104 1105 // Be conservative, if the instructions are too far apart, don't 1106 // move them. We want to limit the increase of register pressure. 1107 bool DoMove = (LastLoc - FirstLoc) < NumMove*4; 1108 if (DoMove) 1109 DoMove = IsSafeToMove(isLd, Base, FirstOp, LastOp, MoveOps, TRI); 1110 if (!DoMove) { 1111 for (unsigned i = 0; i != NumMove; ++i) 1112 Ops.pop_back(); 1113 } else { 1114 // This is the new location for the loads / stores. 1115 MachineBasicBlock::iterator InsertPos = isLd ? FirstOp : LastOp; 1116 while (InsertPos != MBB->end() && MoveOps.count(InsertPos)) 1117 ++InsertPos; 1118 1119 // If we are moving a pair of loads / stores, see if it makes sense 1120 // to try to allocate a pair of registers that can form register pairs. 1121 MachineInstr *Op0 = Ops.back(); 1122 MachineInstr *Op1 = Ops[Ops.size()-2]; 1123 unsigned EvenReg = 0, OddReg = 0; 1124 unsigned BaseReg = 0, OffReg = 0, PredReg = 0; 1125 ARMCC::CondCodes Pred = ARMCC::AL; 1126 unsigned NewOpc = 0; 1127 unsigned Offset = 0; 1128 DebugLoc dl; 1129 if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc, 1130 EvenReg, OddReg, BaseReg, OffReg, 1131 Offset, PredReg, Pred)) { 1132 Ops.pop_back(); 1133 Ops.pop_back(); 1134 MBB->erase(Op0); 1135 MBB->erase(Op1); 1136 1137 // Form the pair instruction. 1138 if (isLd) 1139 BuildMI(*MBB, InsertPos, dl, TII->get(NewOpc)) 1140 .addReg(EvenReg, RegState::Define) 1141 .addReg(OddReg, RegState::Define) 1142 .addReg(BaseReg).addReg(0).addImm(Offset) 1143 .addImm(Pred).addReg(PredReg); 1144 else 1145 BuildMI(*MBB, InsertPos, dl, TII->get(NewOpc)) 1146 .addReg(EvenReg) 1147 .addReg(OddReg) 1148 .addReg(BaseReg).addReg(0).addImm(Offset) 1149 .addImm(Pred).addReg(PredReg); 1150 1151 // Add register allocation hints to form register pairs. 1152 MRI->setRegAllocationHint(EvenReg, ARMRI::RegPairEven, OddReg); 1153 MRI->setRegAllocationHint(OddReg, ARMRI::RegPairOdd, EvenReg); 1154 } else { 1155 for (unsigned i = 0; i != NumMove; ++i) { 1156 MachineInstr *Op = Ops.back(); 1157 Ops.pop_back(); 1158 MBB->splice(InsertPos, MBB, Op); 1159 } 1160 } 1161 1162 NumLdStMoved += NumMove; 1163 RetVal = true; 1164 } 1165 } 1166 } 1167 1168 return RetVal; 1169} 1170 1171bool 1172ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) { 1173 bool RetVal = false; 1174 1175 DenseMap<MachineInstr*, unsigned> MI2LocMap; 1176 DenseMap<unsigned, SmallVector<MachineInstr*, 4> > Base2LdsMap; 1177 DenseMap<unsigned, SmallVector<MachineInstr*, 4> > Base2StsMap; 1178 SmallVector<unsigned, 4> LdBases; 1179 SmallVector<unsigned, 4> StBases; 1180 1181 unsigned Loc = 0; 1182 MachineBasicBlock::iterator MBBI = MBB->begin(); 1183 MachineBasicBlock::iterator E = MBB->end(); 1184 while (MBBI != E) { 1185 for (; MBBI != E; ++MBBI) { 1186 MachineInstr *MI = MBBI; 1187 const TargetInstrDesc &TID = MI->getDesc(); 1188 if (TID.isCall() || TID.isTerminator()) { 1189 // Stop at barriers. 1190 ++MBBI; 1191 break; 1192 } 1193 1194 MI2LocMap[MI] = Loc++; 1195 if (!isMemoryOp(MI)) 1196 continue; 1197 unsigned PredReg = 0; 1198 if (getInstrPredicate(MI, PredReg) != ARMCC::AL) 1199 continue; 1200 1201 int Opcode = MI->getOpcode(); 1202 bool isLd = Opcode == ARM::LDR || 1203 Opcode == ARM::FLDS || Opcode == ARM::FLDD; 1204 unsigned Base = MI->getOperand(1).getReg(); 1205 int Offset = getMemoryOpOffset(MI); 1206 1207 bool StopHere = false; 1208 if (isLd) { 1209 DenseMap<unsigned, SmallVector<MachineInstr*, 4> >::iterator BI = 1210 Base2LdsMap.find(Base); 1211 if (BI != Base2LdsMap.end()) { 1212 for (unsigned i = 0, e = BI->second.size(); i != e; ++i) { 1213 if (Offset == getMemoryOpOffset(BI->second[i])) { 1214 StopHere = true; 1215 break; 1216 } 1217 } 1218 if (!StopHere) 1219 BI->second.push_back(MI); 1220 } else { 1221 SmallVector<MachineInstr*, 4> MIs; 1222 MIs.push_back(MI); 1223 Base2LdsMap[Base] = MIs; 1224 LdBases.push_back(Base); 1225 } 1226 } else { 1227 DenseMap<unsigned, SmallVector<MachineInstr*, 4> >::iterator BI = 1228 Base2StsMap.find(Base); 1229 if (BI != Base2StsMap.end()) { 1230 for (unsigned i = 0, e = BI->second.size(); i != e; ++i) { 1231 if (Offset == getMemoryOpOffset(BI->second[i])) { 1232 StopHere = true; 1233 break; 1234 } 1235 } 1236 if (!StopHere) 1237 BI->second.push_back(MI); 1238 } else { 1239 SmallVector<MachineInstr*, 4> MIs; 1240 MIs.push_back(MI); 1241 Base2StsMap[Base] = MIs; 1242 StBases.push_back(Base); 1243 } 1244 } 1245 1246 if (StopHere) { 1247 // Found a duplicate (a base+offset combination that's seen earlier). Backtrack. 1248 --Loc; 1249 break; 1250 } 1251 } 1252 1253 // Re-schedule loads. 1254 for (unsigned i = 0, e = LdBases.size(); i != e; ++i) { 1255 unsigned Base = LdBases[i]; 1256 SmallVector<MachineInstr*, 4> &Lds = Base2LdsMap[Base]; 1257 if (Lds.size() > 1) 1258 RetVal |= RescheduleOps(MBB, Lds, Base, true, MI2LocMap); 1259 } 1260 1261 // Re-schedule stores. 1262 for (unsigned i = 0, e = StBases.size(); i != e; ++i) { 1263 unsigned Base = StBases[i]; 1264 SmallVector<MachineInstr*, 4> &Sts = Base2StsMap[Base]; 1265 if (Sts.size() > 1) 1266 RetVal |= RescheduleOps(MBB, Sts, Base, false, MI2LocMap); 1267 } 1268 1269 if (MBBI != E) { 1270 Base2LdsMap.clear(); 1271 Base2StsMap.clear(); 1272 LdBases.clear(); 1273 StBases.clear(); 1274 } 1275 } 1276 1277 return RetVal; 1278} 1279 1280 1281/// createARMLoadStoreOptimizationPass - returns an instance of the load / store 1282/// optimization pass. 1283FunctionPass *llvm::createARMLoadStoreOptimizationPass(bool PreAlloc) { 1284 if (PreAlloc) 1285 return new ARMPreAllocLoadStoreOpt(); 1286 return new ARMLoadStoreOpt(); 1287} 1288