ARMLoadStoreOptimizer.cpp revision 14805e2afd5aa754e13fd5bb99365ffe972e9696
1a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//===-- ARMLoadStoreOptimizer.cpp - ARM load / store opt. pass ----*- C++ -*-=//
2a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//
3a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//                     The LLVM Compiler Infrastructure
4a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//
8a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//===----------------------------------------------------------------------===//
9a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//
10a8e2989ece6dc46df59b0768184028257f913843Evan Cheng// This file contains a pass that performs load / store related peephole
11a8e2989ece6dc46df59b0768184028257f913843Evan Cheng// optimizations. This pass should be run after register allocation.
12a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//
13a8e2989ece6dc46df59b0768184028257f913843Evan Cheng//===----------------------------------------------------------------------===//
14a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
15a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#define DEBUG_TYPE "arm-ldst-opt"
16a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include "ARM.h"
17a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include "ARMAddressingModes.h"
188fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng#include "ARMBaseInstrInfo.h"
19603b83ebcdfb9c27e44c1da16f2799755e3e3022Evan Cheng#include "ARMMachineFunctionInfo.h"
20a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include "ARMRegisterInfo.h"
21358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng#include "llvm/DerivedTypes.h"
221d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson#include "llvm/Function.h"
23a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include "llvm/CodeGen/MachineBasicBlock.h"
24a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include "llvm/CodeGen/MachineFunctionPass.h"
25a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include "llvm/CodeGen/MachineInstr.h"
26a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include "llvm/CodeGen/MachineInstrBuilder.h"
27e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng#include "llvm/CodeGen/MachineRegisterInfo.h"
28cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng#include "llvm/CodeGen/RegisterScavenging.h"
29358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng#include "llvm/Target/TargetData.h"
30a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include "llvm/Target/TargetInstrInfo.h"
31a8e2989ece6dc46df59b0768184028257f913843Evan Cheng#include "llvm/Target/TargetMachine.h"
32358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng#include "llvm/Target/TargetRegisterInfo.h"
33ab7c09b6b6f4516a631fd6788918c237c83939afTorok Edwin#include "llvm/Support/ErrorHandling.h"
34e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng#include "llvm/ADT/DenseMap.h"
35e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng#include "llvm/ADT/STLExtras.h"
36e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng#include "llvm/ADT/SmallPtrSet.h"
37ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng#include "llvm/ADT/SmallSet.h"
38e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng#include "llvm/ADT/SmallVector.h"
39e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng#include "llvm/ADT/Statistic.h"
40a8e2989ece6dc46df59b0768184028257f913843Evan Chengusing namespace llvm;
41a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
42a8e2989ece6dc46df59b0768184028257f913843Evan ChengSTATISTIC(NumLDMGened , "Number of ldm instructions generated");
43a8e2989ece6dc46df59b0768184028257f913843Evan ChengSTATISTIC(NumSTMGened , "Number of stm instructions generated");
44e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim GrosbachSTATISTIC(NumVLDMGened, "Number of vldm instructions generated");
45e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim GrosbachSTATISTIC(NumVSTMGened, "Number of vstm instructions generated");
46e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan ChengSTATISTIC(NumLdStMoved, "Number of load / store instructions moved");
47f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan ChengSTATISTIC(NumLDRDFormed,"Number of ldrd created before allocation");
48f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan ChengSTATISTIC(NumSTRDFormed,"Number of strd created before allocation");
49f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan ChengSTATISTIC(NumLDRD2LDM,  "Number of ldrd instructions turned back into ldm");
50f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan ChengSTATISTIC(NumSTRD2STM,  "Number of strd instructions turned back into stm");
51f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan ChengSTATISTIC(NumLDRD2LDR,  "Number of ldrd instructions turned back into ldr's");
52f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan ChengSTATISTIC(NumSTRD2STR,  "Number of strd instructions turned back into str's");
53e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
54e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng/// ARMAllocLoadStoreOpt - Post- register allocation pass the combine
55e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng/// load / store instructions to form ldm / stm instructions.
56a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
57a8e2989ece6dc46df59b0768184028257f913843Evan Chengnamespace {
586726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky  struct ARMLoadStoreOpt : public MachineFunctionPass {
591997473cf72957d0e70322e2fe6fe2ab141c58a6Devang Patel    static char ID;
6090c579de5a383cee278acc3f7e7b9d0a656e6a35Owen Anderson    ARMLoadStoreOpt() : MachineFunctionPass(ID) {}
61794fd75c67a2cdc128d67342c6d88a504d186896Devang Patel
62a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    const TargetInstrInfo *TII;
636f0d024a534af18d9e60b3ea757376cd8a3a980eDan Gohman    const TargetRegisterInfo *TRI;
64603b83ebcdfb9c27e44c1da16f2799755e3e3022Evan Cheng    ARMFunctionInfo *AFI;
65cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng    RegScavenger *RS;
6645032f28013aa69d07bf859da9d976947910f059Evan Cheng    bool isThumb2;
67a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
68a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    virtual bool runOnMachineFunction(MachineFunction &Fn);
69a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
70a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    virtual const char *getPassName() const {
71a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      return "ARM load / store optimization pass";
72a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
73a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
74a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  private:
75a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    struct MemOpQueueEntry {
76a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      int Offset;
77d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      unsigned Reg;
78d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      bool isKill;
79a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      unsigned Position;
80a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      MachineBasicBlock::iterator MBBI;
81a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      bool Merged;
82d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      MemOpQueueEntry(int o, unsigned r, bool k, unsigned p,
83d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                      MachineBasicBlock::iterator i)
84d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng        : Offset(o), Reg(r), isKill(k), Position(p), MBBI(i), Merged(false) {}
85a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    };
86a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    typedef SmallVector<MemOpQueueEntry,8> MemOpQueue;
87a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    typedef MemOpQueue::iterator MemOpQueueIter;
88a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
89925492279ae7d93180ebdd689c87cd58522e68f5Evan Cheng    bool MergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
9087d59e49e9008767896c4c8c80efdc172f1cbd18Evan Cheng                  int Offset, unsigned Base, bool BaseKill, int Opcode,
9187d59e49e9008767896c4c8c80efdc172f1cbd18Evan Cheng                  ARMCC::CondCodes Pred, unsigned PredReg, unsigned Scratch,
9287d59e49e9008767896c4c8c80efdc172f1cbd18Evan Cheng                  DebugLoc dl, SmallVector<std::pair<unsigned, bool>, 8> &Regs);
93f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen    void MergeOpsUpdate(MachineBasicBlock &MBB,
946528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen                        MemOpQueue &MemOps,
956528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen                        unsigned memOpsBegin,
966528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen                        unsigned memOpsEnd,
976528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen                        unsigned insertAfter,
98f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen                        int Offset,
99f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen                        unsigned Base,
100f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen                        bool BaseKill,
101f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen                        int Opcode,
102f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen                        ARMCC::CondCodes Pred,
103f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen                        unsigned PredReg,
104f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen                        unsigned Scratch,
105f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen                        DebugLoc dl,
106f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen                        SmallVector<MachineBasicBlock::iterator, 4> &Merges);
1075ba71887f918a9da82140210494608df020dcbd5Evan Cheng    void MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base,
1085ba71887f918a9da82140210494608df020dcbd5Evan Cheng                      int Opcode, unsigned Size,
1095ba71887f918a9da82140210494608df020dcbd5Evan Cheng                      ARMCC::CondCodes Pred, unsigned PredReg,
1105ba71887f918a9da82140210494608df020dcbd5Evan Cheng                      unsigned Scratch, MemOpQueue &MemOps,
1115ba71887f918a9da82140210494608df020dcbd5Evan Cheng                      SmallVector<MachineBasicBlock::iterator, 4> &Merges);
112a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
11311788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng    void AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps);
114358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    bool FixInvalidRegPairOp(MachineBasicBlock &MBB,
115358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng                             MachineBasicBlock::iterator &MBBI);
11645032f28013aa69d07bf859da9d976947910f059Evan Cheng    bool MergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
11745032f28013aa69d07bf859da9d976947910f059Evan Cheng                                  MachineBasicBlock::iterator MBBI,
11845032f28013aa69d07bf859da9d976947910f059Evan Cheng                                  const TargetInstrInfo *TII,
11945032f28013aa69d07bf859da9d976947910f059Evan Cheng                                  bool &Advance,
12045032f28013aa69d07bf859da9d976947910f059Evan Cheng                                  MachineBasicBlock::iterator &I);
12145032f28013aa69d07bf859da9d976947910f059Evan Cheng    bool MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
12245032f28013aa69d07bf859da9d976947910f059Evan Cheng                                   MachineBasicBlock::iterator MBBI,
12345032f28013aa69d07bf859da9d976947910f059Evan Cheng                                   bool &Advance,
12445032f28013aa69d07bf859da9d976947910f059Evan Cheng                                   MachineBasicBlock::iterator &I);
125a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    bool LoadStoreMultipleOpti(MachineBasicBlock &MBB);
126a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    bool MergeReturnIntoLDM(MachineBasicBlock &MBB);
127a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  };
1281997473cf72957d0e70322e2fe6fe2ab141c58a6Devang Patel  char ARMLoadStoreOpt::ID = 0;
129a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
130a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
131a8e2989ece6dc46df59b0768184028257f913843Evan Chengstatic int getLoadStoreMultipleOpcode(int Opcode) {
132a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  switch (Opcode) {
133a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  case ARM::LDR:
134fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman    ++NumLDMGened;
135a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    return ARM::LDM;
136a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  case ARM::STR:
137fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman    ++NumSTMGened;
138a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    return ARM::STM;
13945032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2LDRi8:
14045032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2LDRi12:
141fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman    ++NumLDMGened;
14245032f28013aa69d07bf859da9d976947910f059Evan Cheng    return ARM::t2LDM;
14345032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2STRi8:
14445032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2STRi12:
145fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman    ++NumSTMGened;
14645032f28013aa69d07bf859da9d976947910f059Evan Cheng    return ARM::t2STM;
147e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VLDRS:
148fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman    ++NumVLDMGened;
149e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach    return ARM::VLDMS;
150e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VSTRS:
151fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman    ++NumVSTMGened;
152e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach    return ARM::VSTMS;
153e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VLDRD:
154fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman    ++NumVLDMGened;
155e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach    return ARM::VLDMD;
156e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VSTRD:
157fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman    ++NumVSTMGened;
158e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach    return ARM::VSTMD;
159c23197a26f34f559ea9797de51e187087c039c42Torok Edwin  default: llvm_unreachable("Unhandled opcode!");
160a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
161a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  return 0;
162a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
163a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
16427934da97bcb7a6a4949dfc0c449d99f43077e98Evan Chengstatic bool isT2i32Load(unsigned Opc) {
16527934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  return Opc == ARM::t2LDRi12 || Opc == ARM::t2LDRi8;
16627934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng}
16727934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng
16845032f28013aa69d07bf859da9d976947910f059Evan Chengstatic bool isi32Load(unsigned Opc) {
16927934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  return Opc == ARM::LDR || isT2i32Load(Opc);
17027934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng}
17127934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng
17227934da97bcb7a6a4949dfc0c449d99f43077e98Evan Chengstatic bool isT2i32Store(unsigned Opc) {
17327934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  return Opc == ARM::t2STRi12 || Opc == ARM::t2STRi8;
17445032f28013aa69d07bf859da9d976947910f059Evan Cheng}
17545032f28013aa69d07bf859da9d976947910f059Evan Cheng
17645032f28013aa69d07bf859da9d976947910f059Evan Chengstatic bool isi32Store(unsigned Opc) {
17727934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  return Opc == ARM::STR || isT2i32Store(Opc);
17845032f28013aa69d07bf859da9d976947910f059Evan Cheng}
17945032f28013aa69d07bf859da9d976947910f059Evan Cheng
180925492279ae7d93180ebdd689c87cd58522e68f5Evan Cheng/// MergeOps - Create and insert a LDM or STM with Base as base register and
181a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// registers in Regs as the register operands that would be loaded / stored.
182764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach/// It returns true if the transformation is done.
18387d59e49e9008767896c4c8c80efdc172f1cbd18Evan Chengbool
184925492279ae7d93180ebdd689c87cd58522e68f5Evan ChengARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
18587d59e49e9008767896c4c8c80efdc172f1cbd18Evan Cheng                          MachineBasicBlock::iterator MBBI,
18687d59e49e9008767896c4c8c80efdc172f1cbd18Evan Cheng                          int Offset, unsigned Base, bool BaseKill,
18787d59e49e9008767896c4c8c80efdc172f1cbd18Evan Cheng                          int Opcode, ARMCC::CondCodes Pred,
18887d59e49e9008767896c4c8c80efdc172f1cbd18Evan Cheng                          unsigned PredReg, unsigned Scratch, DebugLoc dl,
18987d59e49e9008767896c4c8c80efdc172f1cbd18Evan Cheng                          SmallVector<std::pair<unsigned, bool>, 8> &Regs) {
190a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  // Only a single register to load / store. Don't bother.
191a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  unsigned NumRegs = Regs.size();
192a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  if (NumRegs <= 1)
193a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    return false;
194a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
195a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  ARM_AM::AMSubMode Mode = ARM_AM::ia;
19614805e2afd5aa754e13fd5bb99365ffe972e9696Bob Wilson  // VFP and Thumb2 do not support IB or DA modes.
197d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson  bool isNotVFP = isi32Load(Opcode) || isi32Store(Opcode);
19814805e2afd5aa754e13fd5bb99365ffe972e9696Bob Wilson  bool haveIBAndDA = isNotVFP && !isThumb2;
19914805e2afd5aa754e13fd5bb99365ffe972e9696Bob Wilson  if (Offset == 4 && haveIBAndDA)
200a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    Mode = ARM_AM::ib;
20114805e2afd5aa754e13fd5bb99365ffe972e9696Bob Wilson  else if (Offset == -4 * (int)NumRegs + 4 && haveIBAndDA)
202a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    Mode = ARM_AM::da;
20314805e2afd5aa754e13fd5bb99365ffe972e9696Bob Wilson  else if (Offset == -4 * (int)NumRegs && isNotVFP)
20414805e2afd5aa754e13fd5bb99365ffe972e9696Bob Wilson    // VLDM/VSTM do not support DB mode without also updating the base reg.
205a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    Mode = ARM_AM::db;
20614805e2afd5aa754e13fd5bb99365ffe972e9696Bob Wilson  else if (Offset != 0) {
207a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    // If starting offset isn't zero, insert a MI to materialize a new base.
208a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    // But only do so if it is cost effective, i.e. merging more than two
209a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    // loads / stores.
210a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    if (NumRegs <= 2)
211a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      return false;
212a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
213a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    unsigned NewBase;
21445032f28013aa69d07bf859da9d976947910f059Evan Cheng    if (isi32Load(Opcode))
215a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // If it is a load, then just use one of the destination register to
216a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // use as the new base.
217a90f3408b3aca71cd438efa2c539af041430e059Evan Cheng      NewBase = Regs[NumRegs-1].first;
218a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    else {
2190ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng      // Use the scratch register to use as a new base.
2200ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng      NewBase = Scratch;
221a90f3408b3aca71cd438efa2c539af041430e059Evan Cheng      if (NewBase == 0)
222a90f3408b3aca71cd438efa2c539af041430e059Evan Cheng        return false;
223a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
224861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng    int BaseOpc = !isThumb2
225861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng      ? ARM::ADDri
226861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng      : ((Base == ARM::SP) ? ARM::t2ADDrSPi : ARM::t2ADDri);
227a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    if (Offset < 0) {
228861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng      BaseOpc = !isThumb2
229861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng        ? ARM::SUBri
230861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng        : ((Base == ARM::SP) ? ARM::t2SUBrSPi : ARM::t2SUBri);
231a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      Offset = - Offset;
232a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
23345032f28013aa69d07bf859da9d976947910f059Evan Cheng    int ImmedOffset = isThumb2
23445032f28013aa69d07bf859da9d976947910f059Evan Cheng      ? ARM_AM::getT2SOImmVal(Offset) : ARM_AM::getSOImmVal(Offset);
23545032f28013aa69d07bf859da9d976947910f059Evan Cheng    if (ImmedOffset == -1)
23645032f28013aa69d07bf859da9d976947910f059Evan Cheng      // FIXME: Try t2ADDri12 or t2SUBri12?
237a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      return false;  // Probably not worth it then.
238a90f3408b3aca71cd438efa2c539af041430e059Evan Cheng
239b67284057ee130114055309eabe0bcd1af13777dDale Johannesen    BuildMI(MBB, MBBI, dl, TII->get(BaseOpc), NewBase)
240e7cbe4118b7ddf05032ff8772a98c51e1637bb5cEvan Cheng      .addReg(Base, getKillRegState(BaseKill)).addImm(Offset)
24113ab020ea08826f1b87db6ec3da63889a12e3d9dEvan Cheng      .addImm(Pred).addReg(PredReg).addReg(0);
242a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    Base = NewBase;
243a90f3408b3aca71cd438efa2c539af041430e059Evan Cheng    BaseKill = true;  // New base is always killed right its use.
244a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
245a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
2468d95e0be13079339c2b84f245fb1665953e2bc77Bob Wilson  bool isDef = (isi32Load(Opcode) || Opcode == ARM::VLDRS ||
2478d95e0be13079339c2b84f245fb1665953e2bc77Bob Wilson                Opcode == ARM::VLDRD);
248a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  Opcode = getLoadStoreMultipleOpcode(Opcode);
249d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson  MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(Opcode))
250d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    .addReg(Base, getKillRegState(BaseKill))
251d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    .addImm(ARM_AM::getAM4ModeImm(Mode)).addImm(Pred).addReg(PredReg);
252a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  for (unsigned i = 0; i != NumRegs; ++i)
253587daedce2d6c2b2d380b6a5843a6f8b6cfc79e4Bill Wendling    MIB = MIB.addReg(Regs[i].first, getDefRegState(isDef)
254587daedce2d6c2b2d380b6a5843a6f8b6cfc79e4Bill Wendling                     | getKillRegState(Regs[i].second));
255a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
256a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  return true;
257a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
258a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
259f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen// MergeOpsUpdate - call MergeOps and update MemOps and merges accordingly on
260f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen// success.
261d95ea2da28901ca6e81645e444e528d66350d781Evan Chengvoid ARMLoadStoreOpt::MergeOpsUpdate(MachineBasicBlock &MBB,
262d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                                     MemOpQueue &memOps,
263d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                                     unsigned memOpsBegin, unsigned memOpsEnd,
264d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                                     unsigned insertAfter, int Offset,
265d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                                     unsigned Base, bool BaseKill,
266d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                                     int Opcode,
267d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                                     ARMCC::CondCodes Pred, unsigned PredReg,
268d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                                     unsigned Scratch,
269d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                                     DebugLoc dl,
270d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                          SmallVector<MachineBasicBlock::iterator, 4> &Merges) {
2713063aed8d29cf2418fc1c3022a3dd9c8de0e4922Jakob Stoklund Olesen  // First calculate which of the registers should be killed by the merged
2723063aed8d29cf2418fc1c3022a3dd9c8de0e4922Jakob Stoklund Olesen  // instruction.
2731dbc38f52e2d6436ba79048013e42d96187993d8Jakob Stoklund Olesen  const unsigned insertPos = memOps[insertAfter].Position;
274d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng
275d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng  SmallSet<unsigned, 4> UnavailRegs;
276d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng  SmallSet<unsigned, 4> KilledRegs;
277d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng  DenseMap<unsigned, unsigned> Killer;
278d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng  for (unsigned i = 0; i < memOpsBegin; ++i) {
279d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    if (memOps[i].Position < insertPos && memOps[i].isKill) {
280d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      unsigned Reg = memOps[i].Reg;
281d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      if (memOps[i].Merged)
282d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng        UnavailRegs.insert(Reg);
283d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      else {
284d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng        KilledRegs.insert(Reg);
285d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng        Killer[Reg] = i;
286d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      }
287d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    }
288d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng  }
289d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng  for (unsigned i = memOpsEnd, e = memOps.size(); i != e; ++i) {
290d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    if (memOps[i].Position < insertPos && memOps[i].isKill) {
291d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      unsigned Reg = memOps[i].Reg;
292d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      KilledRegs.insert(Reg);
293d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      Killer[Reg] = i;
294d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    }
295d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng  }
296d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng
297d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng  SmallVector<std::pair<unsigned, bool>, 8> Regs;
2986528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen  for (unsigned i = memOpsBegin; i < memOpsEnd; ++i) {
299d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    unsigned Reg = memOps[i].Reg;
300d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    if (UnavailRegs.count(Reg))
301d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      // Register is killed before and it's not easy / possible to update the
302d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      // kill marker on already merged instructions. Abort.
303d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      return;
3041dbc38f52e2d6436ba79048013e42d96187993d8Jakob Stoklund Olesen
3051dbc38f52e2d6436ba79048013e42d96187993d8Jakob Stoklund Olesen    // If we are inserting the merged operation after an unmerged operation that
3061dbc38f52e2d6436ba79048013e42d96187993d8Jakob Stoklund Olesen    // uses the same register, make sure to transfer any kill flag.
307d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    bool isKill = memOps[i].isKill || KilledRegs.count(Reg);
3081dbc38f52e2d6436ba79048013e42d96187993d8Jakob Stoklund Olesen    Regs.push_back(std::make_pair(Reg, isKill));
3093063aed8d29cf2418fc1c3022a3dd9c8de0e4922Jakob Stoklund Olesen  }
3103063aed8d29cf2418fc1c3022a3dd9c8de0e4922Jakob Stoklund Olesen
3116528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen  // Try to do the merge.
3126528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen  MachineBasicBlock::iterator Loc = memOps[insertAfter].MBBI;
313fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman  ++Loc;
3146528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen  if (!MergeOps(MBB, Loc, Offset, Base, BaseKill, Opcode,
315f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen                Pred, PredReg, Scratch, dl, Regs))
316f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen    return;
3173063aed8d29cf2418fc1c3022a3dd9c8de0e4922Jakob Stoklund Olesen
3183063aed8d29cf2418fc1c3022a3dd9c8de0e4922Jakob Stoklund Olesen  // Merge succeeded, update records.
3196528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen  Merges.push_back(prior(Loc));
3206528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen  for (unsigned i = memOpsBegin; i < memOpsEnd; ++i) {
3211dbc38f52e2d6436ba79048013e42d96187993d8Jakob Stoklund Olesen    // Remove kill flags from any unmerged memops that come before insertPos.
322d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    if (Regs[i-memOpsBegin].second) {
323d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      unsigned Reg = Regs[i-memOpsBegin].first;
324d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      if (KilledRegs.count(Reg)) {
325d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng        unsigned j = Killer[Reg];
326d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng        memOps[j].MBBI->getOperand(0).setIsKill(false);
327d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      }
328d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    }
3296528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen    MBB.erase(memOps[i].MBBI);
3306528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen    memOps[i].Merged = true;
331f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen  }
332f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen}
333f8e33e513f2620ea30fda7f17bc227729b7621b8Jakob Stoklund Olesen
334a90f3408b3aca71cd438efa2c539af041430e059Evan Cheng/// MergeLDR_STR - Merge a number of load / store instructions into one or more
335a90f3408b3aca71cd438efa2c539af041430e059Evan Cheng/// load / store multiple instructions.
3365ba71887f918a9da82140210494608df020dcbd5Evan Chengvoid
3370ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan ChengARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
3385ba71887f918a9da82140210494608df020dcbd5Evan Cheng                          unsigned Base, int Opcode, unsigned Size,
3395ba71887f918a9da82140210494608df020dcbd5Evan Cheng                          ARMCC::CondCodes Pred, unsigned PredReg,
3405ba71887f918a9da82140210494608df020dcbd5Evan Cheng                          unsigned Scratch, MemOpQueue &MemOps,
3415ba71887f918a9da82140210494608df020dcbd5Evan Cheng                          SmallVector<MachineBasicBlock::iterator, 4> &Merges) {
342d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson  bool isNotVFP = isi32Load(Opcode) || isi32Store(Opcode);
343a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  int Offset = MemOps[SIndex].Offset;
344a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  int SOffset = Offset;
3456528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen  unsigned insertAfter = SIndex;
346a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  MachineBasicBlock::iterator Loc = MemOps[SIndex].MBBI;
34787d59e49e9008767896c4c8c80efdc172f1cbd18Evan Cheng  DebugLoc dl = Loc->getDebugLoc();
348158a2263bd221a6920c6c7f7f96d6272344efb8fJakob Stoklund Olesen  const MachineOperand &PMO = Loc->getOperand(0);
349158a2263bd221a6920c6c7f7f96d6272344efb8fJakob Stoklund Olesen  unsigned PReg = PMO.getReg();
350158a2263bd221a6920c6c7f7f96d6272344efb8fJakob Stoklund Olesen  unsigned PRegNum = PMO.isUndef() ? UINT_MAX
351158a2263bd221a6920c6c7f7f96d6272344efb8fJakob Stoklund Olesen    : ARMRegisterInfo::getRegisterNumbering(PReg);
3529a52d0c352c852dc9517430442afc54f53e1d4ddJim Grosbach  unsigned Count = 1;
35344bec52b1b7e9a3ac1efbae90db240b8c1ca2ad4Evan Cheng
354a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  for (unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) {
355a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    int NewOffset = MemOps[i].Offset;
356158a2263bd221a6920c6c7f7f96d6272344efb8fJakob Stoklund Olesen    const MachineOperand &MO = MemOps[i].MBBI->getOperand(0);
357158a2263bd221a6920c6c7f7f96d6272344efb8fJakob Stoklund Olesen    unsigned Reg = MO.getReg();
358158a2263bd221a6920c6c7f7f96d6272344efb8fJakob Stoklund Olesen    unsigned RegNum = MO.isUndef() ? UINT_MAX
359158a2263bd221a6920c6c7f7f96d6272344efb8fJakob Stoklund Olesen      : ARMRegisterInfo::getRegisterNumbering(Reg);
360d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    // Register numbers must be in ascending order.  For VFP, the registers
361d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    // must also be consecutive and there is a limit of 16 double-word
362d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    // registers per instruction.
3633f7aa79c2a46d525cf0468ad74ef2395246a309fEvan Cheng    if (Reg != ARM::SP &&
3643f7aa79c2a46d525cf0468ad74ef2395246a309fEvan Cheng        NewOffset == Offset + (int)Size &&
365d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson        ((isNotVFP && RegNum > PRegNum)
3669a52d0c352c852dc9517430442afc54f53e1d4ddJim Grosbach         || ((Size < 8 || Count < 16) && RegNum == PRegNum+1))) {
367a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      Offset += Size;
368a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      PRegNum = RegNum;
3699a52d0c352c852dc9517430442afc54f53e1d4ddJim Grosbach      ++Count;
370a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    } else {
371a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // Can't merge this in. Try merge the earlier ones first.
3726528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen      MergeOpsUpdate(MBB, MemOps, SIndex, i, insertAfter, SOffset,
3736528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen                     Base, false, Opcode, Pred, PredReg, Scratch, dl, Merges);
3745ba71887f918a9da82140210494608df020dcbd5Evan Cheng      MergeLDR_STR(MBB, i, Base, Opcode, Size, Pred, PredReg, Scratch,
3755ba71887f918a9da82140210494608df020dcbd5Evan Cheng                   MemOps, Merges);
3765ba71887f918a9da82140210494608df020dcbd5Evan Cheng      return;
377a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
378a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
3796528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen    if (MemOps[i].Position > MemOps[insertAfter].Position)
3806528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen      insertAfter = i;
381a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
382a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
383faa510726f4b40aa4495e60e4d341c6467e3fb01Evan Cheng  bool BaseKill = Loc->findRegisterUseOperandIdx(Base, true) != -1;
3846528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen  MergeOpsUpdate(MBB, MemOps, SIndex, MemOps.size(), insertAfter, SOffset,
3856528966eaeaf38244ce165ef7c80326aa34a55caJakob Stoklund Olesen                 Base, BaseKill, Opcode, Pred, PredReg, Scratch, dl, Merges);
3865ba71887f918a9da82140210494608df020dcbd5Evan Cheng  return;
387a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
388a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
389a8e2989ece6dc46df59b0768184028257f913843Evan Chengstatic inline bool isMatchingDecrement(MachineInstr *MI, unsigned Base,
39027934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng                                       unsigned Bytes, unsigned Limit,
39127934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng                                       ARMCC::CondCodes Pred, unsigned PredReg){
3920e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng  unsigned MyPredReg = 0;
39345032f28013aa69d07bf859da9d976947910f059Evan Cheng  if (!MI)
39445032f28013aa69d07bf859da9d976947910f059Evan Cheng    return false;
39527934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  if (MI->getOpcode() != ARM::t2SUBri &&
396861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng      MI->getOpcode() != ARM::t2SUBrSPi &&
397861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng      MI->getOpcode() != ARM::t2SUBrSPi12 &&
398861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng      MI->getOpcode() != ARM::tSUBspi &&
39927934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      MI->getOpcode() != ARM::SUBri)
40027934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng    return false;
40127934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng
40227934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  // Make sure the offset fits in 8 bits.
4033d38e8364a542abab6ca3d3aed658cf60d3112b4Bob Wilson  if (Bytes == 0 || (Limit && Bytes >= Limit))
40427934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng    return false;
40545032f28013aa69d07bf859da9d976947910f059Evan Cheng
406861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng  unsigned Scale = (MI->getOpcode() == ARM::tSUBspi) ? 4 : 1; // FIXME
40745032f28013aa69d07bf859da9d976947910f059Evan Cheng  return (MI->getOperand(0).getReg() == Base &&
408a8e2989ece6dc46df59b0768184028257f913843Evan Cheng          MI->getOperand(1).getReg() == Base &&
409861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng          (MI->getOperand(2).getImm()*Scale) == Bytes &&
4108fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng          llvm::getInstrPredicate(MI, MyPredReg) == Pred &&
4110e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng          MyPredReg == PredReg);
412a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
413a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
414a8e2989ece6dc46df59b0768184028257f913843Evan Chengstatic inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base,
41527934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng                                       unsigned Bytes, unsigned Limit,
41627934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng                                       ARMCC::CondCodes Pred, unsigned PredReg){
4170e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng  unsigned MyPredReg = 0;
41845032f28013aa69d07bf859da9d976947910f059Evan Cheng  if (!MI)
41945032f28013aa69d07bf859da9d976947910f059Evan Cheng    return false;
42027934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  if (MI->getOpcode() != ARM::t2ADDri &&
421861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng      MI->getOpcode() != ARM::t2ADDrSPi &&
422861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng      MI->getOpcode() != ARM::t2ADDrSPi12 &&
423861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng      MI->getOpcode() != ARM::tADDspi &&
42427934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      MI->getOpcode() != ARM::ADDri)
42527934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng    return false;
42627934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng
4273d38e8364a542abab6ca3d3aed658cf60d3112b4Bob Wilson  if (Bytes == 0 || (Limit && Bytes >= Limit))
42845032f28013aa69d07bf859da9d976947910f059Evan Cheng    // Make sure the offset fits in 8 bits.
42927934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng    return false;
43045032f28013aa69d07bf859da9d976947910f059Evan Cheng
431861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng  unsigned Scale = (MI->getOpcode() == ARM::tADDspi) ? 4 : 1; // FIXME
43245032f28013aa69d07bf859da9d976947910f059Evan Cheng  return (MI->getOperand(0).getReg() == Base &&
433a8e2989ece6dc46df59b0768184028257f913843Evan Cheng          MI->getOperand(1).getReg() == Base &&
434861986401e05e437cb33bfd8320d510b956fe41eEvan Cheng          (MI->getOperand(2).getImm()*Scale) == Bytes &&
4358fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng          llvm::getInstrPredicate(MI, MyPredReg) == Pred &&
4360e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng          MyPredReg == PredReg);
437a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
438a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
439a8e2989ece6dc46df59b0768184028257f913843Evan Chengstatic inline unsigned getLSMultipleTransferSize(MachineInstr *MI) {
440a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  switch (MI->getOpcode()) {
441a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  default: return 0;
442a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  case ARM::LDR:
443a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  case ARM::STR:
44445032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2LDRi8:
44545032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2LDRi12:
44645032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2STRi8:
44745032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2STRi12:
448e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VLDRS:
449e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VSTRS:
450a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    return 4;
451e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VLDRD:
452e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VSTRD:
453a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    return 8;
454a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  case ARM::LDM:
455a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  case ARM::STM:
45627934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  case ARM::t2LDM:
45727934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  case ARM::t2STM:
458e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VLDMS:
459e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VSTMS:
460e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VLDMD:
461e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VSTMD:
462d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    return (MI->getNumOperands() - 4) * 4;
463a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
464a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
465a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
466815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilsonstatic unsigned getUpdatingLSMultipleOpcode(unsigned Opc) {
467815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  switch (Opc) {
468815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::LDM: return ARM::LDM_UPD;
469815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::STM: return ARM::STM_UPD;
470815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::t2LDM: return ARM::t2LDM_UPD;
471815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::t2STM: return ARM::t2STM_UPD;
472815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VLDMS: return ARM::VLDMS_UPD;
473815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VLDMD: return ARM::VLDMD_UPD;
474815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VSTMS: return ARM::VSTMS_UPD;
475815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VSTMD: return ARM::VSTMD_UPD;
476815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  default: llvm_unreachable("Unhandled opcode!");
477815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  }
478815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  return 0;
479815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson}
480815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson
48145032f28013aa69d07bf859da9d976947910f059Evan Cheng/// MergeBaseUpdateLSMultiple - Fold proceeding/trailing inc/dec of base
482e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach/// register into the LDM/STM/VLDM{D|S}/VSTM{D|S} op when possible:
483a8e2989ece6dc46df59b0768184028257f913843Evan Cheng///
484a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// stmia rn, <ra, rb, rc>
485a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// rn := rn + 4 * 3;
486a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// =>
487a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// stmia rn!, <ra, rb, rc>
488a8e2989ece6dc46df59b0768184028257f913843Evan Cheng///
489a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// rn := rn - 4 * 3;
490a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// ldmia rn, <ra, rb, rc>
491a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// =>
492a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// ldmdb rn!, <ra, rb, rc>
49345032f28013aa69d07bf859da9d976947910f059Evan Chengbool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
49445032f28013aa69d07bf859da9d976947910f059Evan Cheng                                               MachineBasicBlock::iterator MBBI,
49545032f28013aa69d07bf859da9d976947910f059Evan Cheng                                               bool &Advance,
49645032f28013aa69d07bf859da9d976947910f059Evan Cheng                                               MachineBasicBlock::iterator &I) {
497a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  MachineInstr *MI = MBBI;
498a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  unsigned Base = MI->getOperand(0).getReg();
499815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  bool BaseKill = MI->getOperand(0).isKill();
500a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  unsigned Bytes = getLSMultipleTransferSize(MI);
5010e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng  unsigned PredReg = 0;
5028fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng  ARMCC::CondCodes Pred = llvm::getInstrPredicate(MI, PredReg);
503a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  int Opcode = MI->getOpcode();
504815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  DebugLoc dl = MI->getDebugLoc();
505a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
506815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  bool DoMerge = false;
507815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  ARM_AM::AMSubMode Mode = ARM_AM::ia;
508a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
509d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson  // Can't use an updating ld/st if the base register is also a dest
510d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson  // register. e.g. ldmdb r0!, {r0, r1, r2}. The behavior is undefined.
511d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson  for (unsigned i = 3, e = MI->getNumOperands(); i != e; ++i) {
512d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    if (MI->getOperand(i).getReg() == Base)
513d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson      return false;
514815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  }
515d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson  Mode = ARM_AM::getAM4SubMode(MI->getOperand(1).getImm());
516a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
517815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  // Try merging with the previous instruction.
5183de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach  MachineBasicBlock::iterator BeginMBBI = MBB.begin();
5193de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach  if (MBBI != BeginMBBI) {
520815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson    MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
5213de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach    while (PrevMBBI != BeginMBBI && PrevMBBI->isDebugValue())
5223de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach      --PrevMBBI;
523d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    if (Mode == ARM_AM::ia &&
524d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson        isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) {
525d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson      Mode = ARM_AM::db;
526d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson      DoMerge = true;
527d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    } else if (Mode == ARM_AM::ib &&
528d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson               isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) {
529d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson      Mode = ARM_AM::da;
530d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson      DoMerge = true;
531a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
532815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson    if (DoMerge)
533815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson      MBB.erase(PrevMBBI);
534815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  }
535a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
536815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  // Try merging with the next instruction.
5373de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach  MachineBasicBlock::iterator EndMBBI = MBB.end();
5383de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach  if (!DoMerge && MBBI != EndMBBI) {
539815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson    MachineBasicBlock::iterator NextMBBI = llvm::next(MBBI);
5403de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach    while (NextMBBI != EndMBBI && NextMBBI->isDebugValue())
5413de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach      ++NextMBBI;
542d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) &&
543d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson        isMatchingIncrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) {
544d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson      DoMerge = true;
545d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    } else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) &&
546d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson               isMatchingDecrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) {
547d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson      DoMerge = true;
548a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
549815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson    if (DoMerge) {
550815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson      if (NextMBBI == I) {
551815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson        Advance = true;
552815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson        ++I;
553a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      }
554815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson      MBB.erase(NextMBBI);
555a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
556a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
557a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
558815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  if (!DoMerge)
559815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson    return false;
560815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson
561815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  unsigned NewOpc = getUpdatingLSMultipleOpcode(Opcode);
562815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(NewOpc))
563815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson    .addReg(Base, getDefRegState(true)) // WB base register
564d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    .addReg(Base, getKillRegState(BaseKill))
565d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    .addImm(ARM_AM::getAM4ModeImm(Mode))
566d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    .addImm(Pred).addReg(PredReg);
567815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  // Transfer the rest of operands.
568815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  for (unsigned OpNum = 4, e = MI->getNumOperands(); OpNum != e; ++OpNum)
569815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson    MIB.addOperand(MI->getOperand(OpNum));
570815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  // Transfer memoperands.
571815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  (*MIB).setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
572815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson
573815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  MBB.erase(MBBI);
574815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  return true;
575a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
576a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
577a8e2989ece6dc46df59b0768184028257f913843Evan Chengstatic unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) {
578a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  switch (Opc) {
579a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  case ARM::LDR: return ARM::LDR_PRE;
580a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  case ARM::STR: return ARM::STR_PRE;
581815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VLDRS: return ARM::VLDMS_UPD;
582815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VLDRD: return ARM::VLDMD_UPD;
583815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VSTRS: return ARM::VSTMS_UPD;
584815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VSTRD: return ARM::VSTMD_UPD;
58545032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2LDRi8:
58645032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2LDRi12:
58745032f28013aa69d07bf859da9d976947910f059Evan Cheng    return ARM::t2LDR_PRE;
58845032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2STRi8:
58945032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2STRi12:
59045032f28013aa69d07bf859da9d976947910f059Evan Cheng    return ARM::t2STR_PRE;
591c23197a26f34f559ea9797de51e187087c039c42Torok Edwin  default: llvm_unreachable("Unhandled opcode!");
592a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
593a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  return 0;
594a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
595a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
596a8e2989ece6dc46df59b0768184028257f913843Evan Chengstatic unsigned getPostIndexedLoadStoreOpcode(unsigned Opc) {
597a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  switch (Opc) {
598a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  case ARM::LDR: return ARM::LDR_POST;
599a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  case ARM::STR: return ARM::STR_POST;
600815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VLDRS: return ARM::VLDMS_UPD;
601815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VLDRD: return ARM::VLDMD_UPD;
602815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VSTRS: return ARM::VSTMS_UPD;
603815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson  case ARM::VSTRD: return ARM::VSTMD_UPD;
60445032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2LDRi8:
60545032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2LDRi12:
60645032f28013aa69d07bf859da9d976947910f059Evan Cheng    return ARM::t2LDR_POST;
60745032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2STRi8:
60845032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2STRi12:
60945032f28013aa69d07bf859da9d976947910f059Evan Cheng    return ARM::t2STR_POST;
610c23197a26f34f559ea9797de51e187087c039c42Torok Edwin  default: llvm_unreachable("Unhandled opcode!");
611a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
612a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  return 0;
613a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
614a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
61545032f28013aa69d07bf859da9d976947910f059Evan Cheng/// MergeBaseUpdateLoadStore - Fold proceeding/trailing inc/dec of base
616a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// register into the LDR/STR/FLD{D|S}/FST{D|S} op when possible:
61745032f28013aa69d07bf859da9d976947910f059Evan Chengbool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
61845032f28013aa69d07bf859da9d976947910f059Evan Cheng                                               MachineBasicBlock::iterator MBBI,
61945032f28013aa69d07bf859da9d976947910f059Evan Cheng                                               const TargetInstrInfo *TII,
62045032f28013aa69d07bf859da9d976947910f059Evan Cheng                                               bool &Advance,
62145032f28013aa69d07bf859da9d976947910f059Evan Cheng                                               MachineBasicBlock::iterator &I) {
622a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  MachineInstr *MI = MBBI;
623a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  unsigned Base = MI->getOperand(1).getReg();
624a90f3408b3aca71cd438efa2c539af041430e059Evan Cheng  bool BaseKill = MI->getOperand(1).isKill();
625a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  unsigned Bytes = getLSMultipleTransferSize(MI);
626a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  int Opcode = MI->getOpcode();
627b67284057ee130114055309eabe0bcd1af13777dDale Johannesen  DebugLoc dl = MI->getDebugLoc();
628e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson  bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
629e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson                Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);
630e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson  bool isAM2 = (Opcode == ARM::LDR || Opcode == ARM::STR);
63145032f28013aa69d07bf859da9d976947910f059Evan Cheng  if (isAM2 && ARM_AM::getAM2Offset(MI->getOperand(3).getImm()) != 0)
63245032f28013aa69d07bf859da9d976947910f059Evan Cheng    return false;
633e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson  if (isAM5 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0)
634a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    return false;
635e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson  if (isT2i32Load(Opcode) || isT2i32Store(Opcode))
63627934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng    if (MI->getOperand(2).getImm() != 0)
63727934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      return false;
638a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
639e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  bool isLd = isi32Load(Opcode) || Opcode == ARM::VLDRS || Opcode == ARM::VLDRD;
640a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  // Can't do the merge if the destination register is the same as the would-be
641a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  // writeback register.
642a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  if (isLd && MI->getOperand(0).getReg() == Base)
643a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    return false;
644a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
6450e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng  unsigned PredReg = 0;
6468fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng  ARMCC::CondCodes Pred = llvm::getInstrPredicate(MI, PredReg);
647a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  bool DoMerge = false;
648a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  ARM_AM::AddrOpc AddSub = ARM_AM::add;
649a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  unsigned NewOpc = 0;
65027934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  // AM2 - 12 bits, thumb2 - 8 bits.
65127934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  unsigned Limit = isAM5 ? 0 : (isAM2 ? 0x1000 : 0x100);
652e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson
653e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson  // Try merging with the previous instruction.
6543de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach  MachineBasicBlock::iterator BeginMBBI = MBB.begin();
6553de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach  if (MBBI != BeginMBBI) {
656a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
6573de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach    while (PrevMBBI != BeginMBBI && PrevMBBI->isDebugValue())
6583de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach      --PrevMBBI;
65927934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng    if (isMatchingDecrement(PrevMBBI, Base, Bytes, Limit, Pred, PredReg)) {
660a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      DoMerge = true;
661a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      AddSub = ARM_AM::sub;
66227934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng    } else if (!isAM5 &&
66327934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng               isMatchingIncrement(PrevMBBI, Base, Bytes, Limit,Pred,PredReg)) {
664a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      DoMerge = true;
665a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
666e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson    if (DoMerge) {
667e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson      NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
668a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      MBB.erase(PrevMBBI);
669e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson    }
670a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
671a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
672e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson  // Try merging with the next instruction.
6736335ac67b60c69c7314b1fb16721ae4a51043fc0Jim Grosbach  MachineBasicBlock::iterator EndMBBI = MBB.end();
6743de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach  if (!DoMerge && MBBI != EndMBBI) {
6757896c9f436a4eda5ec15e882a7505ba482a2fcd0Chris Lattner    MachineBasicBlock::iterator NextMBBI = llvm::next(MBBI);
6763de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach    while (NextMBBI != EndMBBI && NextMBBI->isDebugValue())
6773de755bb407f91c494ae675fa6408a29b1954a52Jim Grosbach      ++NextMBBI;
67827934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng    if (!isAM5 &&
67927934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng        isMatchingDecrement(NextMBBI, Base, Bytes, Limit, Pred, PredReg)) {
680a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      DoMerge = true;
681a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      AddSub = ARM_AM::sub;
68227934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng    } else if (isMatchingIncrement(NextMBBI, Base, Bytes, Limit,Pred,PredReg)) {
683a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      DoMerge = true;
684a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
685e71bff7405392ad5904f986724a65f965c0686e8Evan Cheng    if (DoMerge) {
686e4193b20fd30e59c389814835ed2f6b3bc3b225cBob Wilson      NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
687e71bff7405392ad5904f986724a65f965c0686e8Evan Cheng      if (NextMBBI == I) {
688e71bff7405392ad5904f986724a65f965c0686e8Evan Cheng        Advance = true;
689e71bff7405392ad5904f986724a65f965c0686e8Evan Cheng        ++I;
690e71bff7405392ad5904f986724a65f965c0686e8Evan Cheng      }
691a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      MBB.erase(NextMBBI);
692e71bff7405392ad5904f986724a65f965c0686e8Evan Cheng    }
693a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
694a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
695a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  if (!DoMerge)
696a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    return false;
697a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
6989e7a312391cb955bfc148d15a69adcaf7cc3ae50Evan Cheng  unsigned Offset = 0;
6999e7a312391cb955bfc148d15a69adcaf7cc3ae50Evan Cheng  if (isAM5)
700d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    Offset = ARM_AM::getAM4ModeImm(AddSub == ARM_AM::sub ?
701d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson                                   ARM_AM::db : ARM_AM::ia);
7029e7a312391cb955bfc148d15a69adcaf7cc3ae50Evan Cheng  else if (isAM2)
7039e7a312391cb955bfc148d15a69adcaf7cc3ae50Evan Cheng    Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift);
7049e7a312391cb955bfc148d15a69adcaf7cc3ae50Evan Cheng  else
7059e7a312391cb955bfc148d15a69adcaf7cc3ae50Evan Cheng    Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes;
7063943ac38c946aaac21dbe686978d098770d7679eBob Wilson
7073943ac38c946aaac21dbe686978d098770d7679eBob Wilson  if (isAM5) {
708815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson    // VLDM[SD}_UPD, VSTM[SD]_UPD
709d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    // (There are no base-updating versions of VLDR/VSTR instructions, but the
710d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    // updating load/store-multiple instructions can be used with only one
711d4bfd54ec2947e73ab152c3c548e4dd4beb700baBob Wilson    // register.)
7123943ac38c946aaac21dbe686978d098770d7679eBob Wilson    MachineOperand &MO = MI->getOperand(0);
7133943ac38c946aaac21dbe686978d098770d7679eBob Wilson    BuildMI(MBB, MBBI, dl, TII->get(NewOpc))
714815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson      .addReg(Base, getDefRegState(true)) // WB base register
7153943ac38c946aaac21dbe686978d098770d7679eBob Wilson      .addReg(Base, getKillRegState(isLd ? BaseKill : false))
7163943ac38c946aaac21dbe686978d098770d7679eBob Wilson      .addImm(Offset)
7173943ac38c946aaac21dbe686978d098770d7679eBob Wilson      .addImm(Pred).addReg(PredReg)
7183943ac38c946aaac21dbe686978d098770d7679eBob Wilson      .addReg(MO.getReg(), (isLd ? getDefRegState(true) :
7193943ac38c946aaac21dbe686978d098770d7679eBob Wilson                            getKillRegState(MO.isKill())));
7203943ac38c946aaac21dbe686978d098770d7679eBob Wilson  } else if (isLd) {
7213943ac38c946aaac21dbe686978d098770d7679eBob Wilson    if (isAM2)
72227934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      // LDR_PRE, LDR_POST,
72327934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg())
72427934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng        .addReg(Base, RegState::Define)
7250e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng        .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
726a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    else
72727934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      // t2LDR_PRE, t2LDR_POST
72827934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg())
72927934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng        .addReg(Base, RegState::Define)
73027934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng        .addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg);
73127934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng  } else {
73227934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng    MachineOperand &MO = MI->getOperand(0);
7333943ac38c946aaac21dbe686978d098770d7679eBob Wilson    if (isAM2)
73427934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      // STR_PRE, STR_POST
73527934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base)
73627934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng        .addReg(MO.getReg(), getKillRegState(MO.isKill()))
73727934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng        .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
73827934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng    else
73927934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      // t2STR_PRE, t2STR_POST
74027934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base)
74127934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng        .addReg(MO.getReg(), getKillRegState(MO.isKill()))
74227934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng        .addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg);
743a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
744a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  MBB.erase(MBBI);
745a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
746a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  return true;
747a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
748a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
749cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng/// isMemoryOp - Returns true if instruction is a memory operations (that this
750cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng/// pass is capable of operating on).
75145032f28013aa69d07bf859da9d976947910f059Evan Chengstatic bool isMemoryOp(const MachineInstr *MI) {
752628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen  // When no memory operands are present, conservatively assume unaligned,
753628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen  // volatile, unfoldable.
754628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen  if (!MI->hasOneMemOperand())
755628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen    return false;
756069e100f9a79a63db177a521fd790f4d77d1209cJakob Stoklund Olesen
757628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen  const MachineMemOperand *MMO = *MI->memoperands_begin();
758069e100f9a79a63db177a521fd790f4d77d1209cJakob Stoklund Olesen
759628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen  // Don't touch volatile memory accesses - we may be changing their order.
760628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen  if (MMO->isVolatile())
761628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen    return false;
762628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen
763628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen  // Unaligned ldr/str is emulated by some kernels, but unaligned ldm/stm is
764628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen  // not.
765628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen  if (MMO->getAlignment() < 4)
766628a79771ba6d293ba7b6f2615f022e1ae9c7c49Jakob Stoklund Olesen    return false;
767069e100f9a79a63db177a521fd790f4d77d1209cJakob Stoklund Olesen
7689e6396d05ee43858f04b0f52eb7da6240845f530Jakob Stoklund Olesen  // str <undef> could probably be eliminated entirely, but for now we just want
7699e6396d05ee43858f04b0f52eb7da6240845f530Jakob Stoklund Olesen  // to avoid making a mess of it.
7709e6396d05ee43858f04b0f52eb7da6240845f530Jakob Stoklund Olesen  // FIXME: Use str <undef> as a wildcard to enable better stm folding.
7719e6396d05ee43858f04b0f52eb7da6240845f530Jakob Stoklund Olesen  if (MI->getNumOperands() > 0 && MI->getOperand(0).isReg() &&
7729e6396d05ee43858f04b0f52eb7da6240845f530Jakob Stoklund Olesen      MI->getOperand(0).isUndef())
7739e6396d05ee43858f04b0f52eb7da6240845f530Jakob Stoklund Olesen    return false;
7749e6396d05ee43858f04b0f52eb7da6240845f530Jakob Stoklund Olesen
775bbf39b0fd9c83f1d46ca5f858e66de66fb64ec98Bob Wilson  // Likewise don't mess with references to undefined addresses.
776bbf39b0fd9c83f1d46ca5f858e66de66fb64ec98Bob Wilson  if (MI->getNumOperands() > 1 && MI->getOperand(1).isReg() &&
777bbf39b0fd9c83f1d46ca5f858e66de66fb64ec98Bob Wilson      MI->getOperand(1).isUndef())
778bbf39b0fd9c83f1d46ca5f858e66de66fb64ec98Bob Wilson    return false;
779bbf39b0fd9c83f1d46ca5f858e66de66fb64ec98Bob Wilson
780cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng  int Opcode = MI->getOpcode();
781cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng  switch (Opcode) {
782cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng  default: break;
783cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng  case ARM::LDR:
784cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng  case ARM::STR:
785d735b8019b0f297d7c14b55adcd887af24d8e602Dan Gohman    return MI->getOperand(1).isReg() && MI->getOperand(2).getReg() == 0;
786e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VLDRS:
787e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VSTRS:
788d735b8019b0f297d7c14b55adcd887af24d8e602Dan Gohman    return MI->getOperand(1).isReg();
789e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VLDRD:
790e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  case ARM::VSTRD:
791d735b8019b0f297d7c14b55adcd887af24d8e602Dan Gohman    return MI->getOperand(1).isReg();
79245032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2LDRi8:
79345032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2LDRi12:
79445032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2STRi8:
79545032f28013aa69d07bf859da9d976947910f059Evan Cheng  case ARM::t2STRi12:
796e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    return MI->getOperand(1).isReg();
797cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng  }
798cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng  return false;
799cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng}
800cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng
80111788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng/// AdvanceRS - Advance register scavenger to just before the earliest memory
80211788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng/// op that is being merged.
80311788fde93fb74636aa333b2910d606d2c19ba9eEvan Chengvoid ARMLoadStoreOpt::AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps) {
80411788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng  MachineBasicBlock::iterator Loc = MemOps[0].MBBI;
80511788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng  unsigned Position = MemOps[0].Position;
80611788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng  for (unsigned i = 1, e = MemOps.size(); i != e; ++i) {
80711788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng    if (MemOps[i].Position < Position) {
80811788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng      Position = MemOps[i].Position;
80911788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng      Loc = MemOps[i].MBBI;
81011788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng    }
81111788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng  }
81211788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng
81311788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng  if (Loc != MBB.begin())
81411788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng    RS->forward(prior(Loc));
81511788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng}
81611788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng
817e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Chengstatic int getMemoryOpOffset(const MachineInstr *MI) {
818e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  int Opcode = MI->getOpcode();
819e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
820358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng  bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
821e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  unsigned NumOperands = MI->getDesc().getNumOperands();
822e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  unsigned OffField = MI->getOperand(NumOperands-3).getImm();
82345032f28013aa69d07bf859da9d976947910f059Evan Cheng
82445032f28013aa69d07bf859da9d976947910f059Evan Cheng  if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||
82545032f28013aa69d07bf859da9d976947910f059Evan Cheng      Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||
82645032f28013aa69d07bf859da9d976947910f059Evan Cheng      Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8)
82745032f28013aa69d07bf859da9d976947910f059Evan Cheng    return OffField;
82845032f28013aa69d07bf859da9d976947910f059Evan Cheng
829e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  int Offset = isAM2
830358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    ? ARM_AM::getAM2Offset(OffField)
831358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    : (isAM3 ? ARM_AM::getAM3Offset(OffField)
832358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng             : ARM_AM::getAM5Offset(OffField) * 4);
833e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  if (isAM2) {
834e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    if (ARM_AM::getAM2Op(OffField) == ARM_AM::sub)
835e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      Offset = -Offset;
836358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng  } else if (isAM3) {
837358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    if (ARM_AM::getAM3Op(OffField) == ARM_AM::sub)
838358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng      Offset = -Offset;
839e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  } else {
840e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    if (ARM_AM::getAM5Op(OffField) == ARM_AM::sub)
841e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      Offset = -Offset;
842e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  }
843e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  return Offset;
844e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng}
845e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
846358dec51804ee52e47ea3a47c9248086e458ad7cEvan Chengstatic void InsertLDR_STR(MachineBasicBlock &MBB,
847358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng                          MachineBasicBlock::iterator &MBBI,
848358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng                          int OffImm, bool isDef,
849358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng                          DebugLoc dl, unsigned NewOpc,
850e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                          unsigned Reg, bool RegDeadKill, bool RegUndef,
851e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                          unsigned BaseReg, bool BaseKill, bool BaseUndef,
852e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                          unsigned OffReg, bool OffKill, bool OffUndef,
853358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng                          ARMCC::CondCodes Pred, unsigned PredReg,
854e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                          const TargetInstrInfo *TII, bool isT2) {
855e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng  int Offset = OffImm;
856e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng  if (!isT2) {
857e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    if (OffImm < 0)
858e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      Offset = ARM_AM::getAM2Opc(ARM_AM::sub, -OffImm, ARM_AM::no_shift);
859e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    else
860e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      Offset = ARM_AM::getAM2Opc(ARM_AM::add, OffImm, ARM_AM::no_shift);
861e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng  }
862e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng  if (isDef) {
863e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
864e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                                      TII->get(NewOpc))
865974fe5d69187bdf33b0e111ff72e965431df4191Evan Cheng      .addReg(Reg, getDefRegState(true) | getDeadRegState(RegDeadKill))
866e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      .addReg(BaseReg, getKillRegState(BaseKill)|getUndefRegState(BaseUndef));
867e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    if (!isT2)
868e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      MIB.addReg(OffReg,  getKillRegState(OffKill)|getUndefRegState(OffUndef));
869e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    MIB.addImm(Offset).addImm(Pred).addReg(PredReg);
870e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng  } else {
871e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MBBI->getDebugLoc(),
872e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                                      TII->get(NewOpc))
873e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      .addReg(Reg, getKillRegState(RegDeadKill) | getUndefRegState(RegUndef))
874e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      .addReg(BaseReg, getKillRegState(BaseKill)|getUndefRegState(BaseUndef));
875e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    if (!isT2)
876e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      MIB.addReg(OffReg,  getKillRegState(OffKill)|getUndefRegState(OffUndef));
877e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    MIB.addImm(Offset).addImm(Pred).addReg(PredReg);
878e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng  }
879358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng}
880358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng
881358dec51804ee52e47ea3a47c9248086e458ad7cEvan Chengbool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB,
882358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng                                          MachineBasicBlock::iterator &MBBI) {
883358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng  MachineInstr *MI = &*MBBI;
884358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng  unsigned Opcode = MI->getOpcode();
885e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng  if (Opcode == ARM::LDRD || Opcode == ARM::STRD ||
886e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) {
887358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    unsigned EvenReg = MI->getOperand(0).getReg();
888358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    unsigned OddReg  = MI->getOperand(1).getReg();
889358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    unsigned EvenRegNum = TRI->getDwarfRegNum(EvenReg, false);
890358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    unsigned OddRegNum  = TRI->getDwarfRegNum(OddReg, false);
891358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    if ((EvenRegNum & 1) == 0 && (EvenRegNum + 1) == OddRegNum)
892358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng      return false;
893358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng
894d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    MachineBasicBlock::iterator NewBBI = MBBI;
895e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    bool isT2 = Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8;
896e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    bool isLd = Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8;
897974fe5d69187bdf33b0e111ff72e965431df4191Evan Cheng    bool EvenDeadKill = isLd ?
898974fe5d69187bdf33b0e111ff72e965431df4191Evan Cheng      MI->getOperand(0).isDead() : MI->getOperand(0).isKill();
899e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    bool EvenUndef = MI->getOperand(0).isUndef();
900974fe5d69187bdf33b0e111ff72e965431df4191Evan Cheng    bool OddDeadKill  = isLd ?
901974fe5d69187bdf33b0e111ff72e965431df4191Evan Cheng      MI->getOperand(1).isDead() : MI->getOperand(1).isKill();
902e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    bool OddUndef = MI->getOperand(1).isUndef();
903358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    const MachineOperand &BaseOp = MI->getOperand(2);
904358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    unsigned BaseReg = BaseOp.getReg();
905358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    bool BaseKill = BaseOp.isKill();
906e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    bool BaseUndef = BaseOp.isUndef();
907e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    unsigned OffReg = isT2 ? 0 : MI->getOperand(3).getReg();
908e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    bool OffKill = isT2 ? false : MI->getOperand(3).isKill();
909e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    bool OffUndef = isT2 ? false : MI->getOperand(3).isUndef();
910358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    int OffImm = getMemoryOpOffset(MI);
911358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    unsigned PredReg = 0;
9128fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng    ARMCC::CondCodes Pred = llvm::getInstrPredicate(MI, PredReg);
913358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng
914358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    if (OddRegNum > EvenRegNum && OffReg == 0 && OffImm == 0) {
915358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng      // Ascending register numbers and no offset. It's safe to change it to a
916358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng      // ldm or stm.
917e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      unsigned NewOpc = (isLd)
918e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng        ? (isT2 ? ARM::t2LDM : ARM::LDM)
919e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng        : (isT2 ? ARM::t2STM : ARM::STM);
920f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng      if (isLd) {
921f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng        BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc))
922f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng          .addReg(BaseReg, getKillRegState(BaseKill))
923f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng          .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))
924f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng          .addImm(Pred).addReg(PredReg)
925974fe5d69187bdf33b0e111ff72e965431df4191Evan Cheng          .addReg(EvenReg, getDefRegState(isLd) | getDeadRegState(EvenDeadKill))
926d20d6586759fe7a53ec8b1dde80622cda49e31b8Evan Cheng          .addReg(OddReg,  getDefRegState(isLd) | getDeadRegState(OddDeadKill));
927f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng        ++NumLDRD2LDM;
928f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng      } else {
929f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng        BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc))
930f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng          .addReg(BaseReg, getKillRegState(BaseKill))
931f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng          .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))
932f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng          .addImm(Pred).addReg(PredReg)
933e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng          .addReg(EvenReg,
934e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                  getKillRegState(EvenDeadKill) | getUndefRegState(EvenUndef))
935e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng          .addReg(OddReg,
936d20d6586759fe7a53ec8b1dde80622cda49e31b8Evan Cheng                  getKillRegState(OddDeadKill)  | getUndefRegState(OddUndef));
937f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng        ++NumSTRD2STM;
938f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng      }
939d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      NewBBI = llvm::prior(MBBI);
940358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    } else {
941358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng      // Split into two instructions.
942e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      assert((!isT2 || !OffReg) &&
943e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng             "Thumb2 ldrd / strd does not encode offset register!");
944e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      unsigned NewOpc = (isLd)
945e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng        ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDR)
946e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng        : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STR);
947358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng      DebugLoc dl = MBBI->getDebugLoc();
948358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng      // If this is a load and base register is killed, it may have been
949358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng      // re-defed by the load, make sure the first load does not clobber it.
950f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng      if (isLd &&
951358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng          (BaseKill || OffKill) &&
952358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng          (TRI->regsOverlap(EvenReg, BaseReg) ||
953358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng           (OffReg && TRI->regsOverlap(EvenReg, OffReg)))) {
954358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng        assert(!TRI->regsOverlap(OddReg, BaseReg) &&
955358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng               (!OffReg || !TRI->regsOverlap(OddReg, OffReg)));
956e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng        InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc,
957e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      OddReg, OddDeadKill, false,
958e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      BaseReg, false, BaseUndef, OffReg, false, OffUndef,
959e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      Pred, PredReg, TII, isT2);
960d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng        NewBBI = llvm::prior(MBBI);
961e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng        InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc,
962e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      EvenReg, EvenDeadKill, false,
963e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      BaseReg, BaseKill, BaseUndef, OffReg, OffKill, OffUndef,
964e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      Pred, PredReg, TII, isT2);
965358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng      } else {
9660cd22dd7383111192571884eb941ac2ccb668025Evan Cheng        if (OddReg == EvenReg && EvenDeadKill) {
96718f30e6f5e80787808fe1455742452a5210afe07Jim Grosbach          // If the two source operands are the same, the kill marker is
96818f30e6f5e80787808fe1455742452a5210afe07Jim Grosbach          // probably on the first one. e.g.
9690cd22dd7383111192571884eb941ac2ccb668025Evan Cheng          // t2STRDi8 %R5<kill>, %R5, %R9<kill>, 0, 14, %reg0
9700cd22dd7383111192571884eb941ac2ccb668025Evan Cheng          EvenDeadKill = false;
9710cd22dd7383111192571884eb941ac2ccb668025Evan Cheng          OddDeadKill = true;
9720cd22dd7383111192571884eb941ac2ccb668025Evan Cheng        }
973974fe5d69187bdf33b0e111ff72e965431df4191Evan Cheng        InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc,
974e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      EvenReg, EvenDeadKill, EvenUndef,
975e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      BaseReg, false, BaseUndef, OffReg, false, OffUndef,
976e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      Pred, PredReg, TII, isT2);
977d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng        NewBBI = llvm::prior(MBBI);
978974fe5d69187bdf33b0e111ff72e965431df4191Evan Cheng        InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc,
979e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      OddReg, OddDeadKill, OddUndef,
980e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      BaseReg, BaseKill, BaseUndef, OffReg, OffKill, OffUndef,
981e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                      Pred, PredReg, TII, isT2);
982358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng      }
983f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng      if (isLd)
984f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng        ++NumLDRD2LDR;
985f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng      else
986f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng        ++NumSTRD2STR;
987358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    }
988358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng
989358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    MBB.erase(MI);
990d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    MBBI = NewBBI;
991d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng    return true;
992358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng  }
993358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng  return false;
994358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng}
995358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng
996a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// LoadStoreMultipleOpti - An optimization pass to turn multiple LDR / STR
997a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// ops of the same base and incrementing offset into LDM / STM ops.
998a8e2989ece6dc46df59b0768184028257f913843Evan Chengbool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
999a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  unsigned NumMerges = 0;
1000a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  unsigned NumMemOps = 0;
1001a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  MemOpQueue MemOps;
1002a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  unsigned CurrBase = 0;
1003a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  int CurrOpc = -1;
1004a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  unsigned CurrSize = 0;
100544bec52b1b7e9a3ac1efbae90db240b8c1ca2ad4Evan Cheng  ARMCC::CondCodes CurrPred = ARMCC::AL;
10060e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng  unsigned CurrPredReg = 0;
1007a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  unsigned Position = 0;
10085ba71887f918a9da82140210494608df020dcbd5Evan Cheng  SmallVector<MachineBasicBlock::iterator,4> Merges;
1009cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng
10100ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng  RS->enterBasicBlock(&MBB);
1011a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
1012a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  while (MBBI != E) {
1013358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    if (FixInvalidRegPairOp(MBB, MBBI))
1014358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng      continue;
1015358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng
1016a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    bool Advance  = false;
1017a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    bool TryMerge = false;
1018a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    bool Clobber  = false;
1019a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
1020cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng    bool isMemOp = isMemoryOp(MBBI);
1021a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    if (isMemOp) {
1022cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng      int Opcode = MBBI->getOpcode();
1023cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng      unsigned Size = getLSMultipleTransferSize(MBBI);
1024d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      const MachineOperand &MO = MBBI->getOperand(0);
1025d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      unsigned Reg = MO.getReg();
1026d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng      bool isKill = MO.isDef() ? false : MO.isKill();
1027a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      unsigned Base = MBBI->getOperand(1).getReg();
10280e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng      unsigned PredReg = 0;
10298fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng      ARMCC::CondCodes Pred = llvm::getInstrPredicate(MBBI, PredReg);
1030e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      int Offset = getMemoryOpOffset(MBBI);
1031a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // Watch out for:
1032a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // r4 := ldr [r5]
1033a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // r5 := ldr [r5, #4]
1034a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // r6 := ldr [r5, #8]
1035a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      //
1036a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // The second ldr has effectively broken the chain even though it
1037a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // looks like the later ldr(s) use the same base register. Try to
1038a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // merge the ldr's so far, including this one. But don't try to
1039a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // combine the following ldr(s).
104045032f28013aa69d07bf859da9d976947910f059Evan Cheng      Clobber = (isi32Load(Opcode) && Base == MBBI->getOperand(0).getReg());
1041a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      if (CurrBase == 0 && !Clobber) {
1042a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        // Start of a new chain.
1043a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        CurrBase = Base;
1044a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        CurrOpc  = Opcode;
1045a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        CurrSize = Size;
104644bec52b1b7e9a3ac1efbae90db240b8c1ca2ad4Evan Cheng        CurrPred = Pred;
10470e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng        CurrPredReg = PredReg;
1048d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng        MemOps.push_back(MemOpQueueEntry(Offset, Reg, isKill, Position, MBBI));
1049fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman        ++NumMemOps;
1050a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        Advance = true;
1051a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      } else {
1052a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        if (Clobber) {
1053a8e2989ece6dc46df59b0768184028257f913843Evan Cheng          TryMerge = true;
1054a8e2989ece6dc46df59b0768184028257f913843Evan Cheng          Advance = true;
1055a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        }
1056a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
105744bec52b1b7e9a3ac1efbae90db240b8c1ca2ad4Evan Cheng        if (CurrOpc == Opcode && CurrBase == Base && CurrPred == Pred) {
10580e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng          // No need to match PredReg.
1059a8e2989ece6dc46df59b0768184028257f913843Evan Cheng          // Continue adding to the queue.
1060a8e2989ece6dc46df59b0768184028257f913843Evan Cheng          if (Offset > MemOps.back().Offset) {
1061d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng            MemOps.push_back(MemOpQueueEntry(Offset, Reg, isKill,
1062d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                                             Position, MBBI));
1063fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman            ++NumMemOps;
1064a8e2989ece6dc46df59b0768184028257f913843Evan Cheng            Advance = true;
1065a8e2989ece6dc46df59b0768184028257f913843Evan Cheng          } else {
1066a8e2989ece6dc46df59b0768184028257f913843Evan Cheng            for (MemOpQueueIter I = MemOps.begin(), E = MemOps.end();
1067a8e2989ece6dc46df59b0768184028257f913843Evan Cheng                 I != E; ++I) {
1068a8e2989ece6dc46df59b0768184028257f913843Evan Cheng              if (Offset < I->Offset) {
1069d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                MemOps.insert(I, MemOpQueueEntry(Offset, Reg, isKill,
1070d95ea2da28901ca6e81645e444e528d66350d781Evan Cheng                                                 Position, MBBI));
1071fe60104ac97f3a8736dcfbfdf9547c7b7cc7b951Dan Gohman                ++NumMemOps;
1072a8e2989ece6dc46df59b0768184028257f913843Evan Cheng                Advance = true;
1073a8e2989ece6dc46df59b0768184028257f913843Evan Cheng                break;
1074a8e2989ece6dc46df59b0768184028257f913843Evan Cheng              } else if (Offset == I->Offset) {
1075a8e2989ece6dc46df59b0768184028257f913843Evan Cheng                // Collision! This can't be merged!
1076a8e2989ece6dc46df59b0768184028257f913843Evan Cheng                break;
1077a8e2989ece6dc46df59b0768184028257f913843Evan Cheng              }
1078a8e2989ece6dc46df59b0768184028257f913843Evan Cheng            }
1079a8e2989ece6dc46df59b0768184028257f913843Evan Cheng          }
1080a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        }
1081a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      }
1082a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
1083a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
1084db03adb34615331c6ef55ebbd80d8bc750deefe0Jim Grosbach    if (MBBI->isDebugValue()) {
1085db03adb34615331c6ef55ebbd80d8bc750deefe0Jim Grosbach      ++MBBI;
1086db03adb34615331c6ef55ebbd80d8bc750deefe0Jim Grosbach      if (MBBI == E)
1087db03adb34615331c6ef55ebbd80d8bc750deefe0Jim Grosbach        // Reach the end of the block, try merging the memory instructions.
1088db03adb34615331c6ef55ebbd80d8bc750deefe0Jim Grosbach        TryMerge = true;
1089db03adb34615331c6ef55ebbd80d8bc750deefe0Jim Grosbach    } else if (Advance) {
1090a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      ++Position;
1091a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      ++MBBI;
1092faf93aa23390389375b8e52f0dd1c3727ed07ee8Evan Cheng      if (MBBI == E)
1093faf93aa23390389375b8e52f0dd1c3727ed07ee8Evan Cheng        // Reach the end of the block, try merging the memory instructions.
1094faf93aa23390389375b8e52f0dd1c3727ed07ee8Evan Cheng        TryMerge = true;
1095a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    } else
1096a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      TryMerge = true;
1097a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
1098a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    if (TryMerge) {
1099a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      if (NumMemOps > 1) {
11000ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng        // Try to find a free register to use as a new base in case it's needed.
11010ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng        // First advance to the instruction just before the start of the chain.
110211788fde93fb74636aa333b2910d606d2c19ba9eEvan Cheng        AdvanceRS(MBB, MemOps);
1103c0823fe7c679ca8f7d1667a310c2fca97b9402d5Jakob Stoklund Olesen        // Find a scratch register.
1104e11a8f565c6a019ddc54667227be9c4d8f117473Jim Grosbach        unsigned Scratch = RS->FindUnusedReg(ARM::GPRRegisterClass);
11050ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng        // Process the load / store instructions.
11060ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng        RS->forward(prior(MBBI));
11070ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng
11080ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng        // Merge ops.
11095ba71887f918a9da82140210494608df020dcbd5Evan Cheng        Merges.clear();
11105ba71887f918a9da82140210494608df020dcbd5Evan Cheng        MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize,
11115ba71887f918a9da82140210494608df020dcbd5Evan Cheng                     CurrPred, CurrPredReg, Scratch, MemOps, Merges);
11120ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng
1113a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        // Try folding preceeding/trailing base inc/dec into the generated
1114a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        // LDM/STM ops.
11155ba71887f918a9da82140210494608df020dcbd5Evan Cheng        for (unsigned i = 0, e = Merges.size(); i < e; ++i)
111645032f28013aa69d07bf859da9d976947910f059Evan Cheng          if (MergeBaseUpdateLSMultiple(MBB, Merges[i], Advance, MBBI))
11179d5fb981b0ebc00e068b9bcb4df7388a8ea94b71Evan Cheng            ++NumMerges;
11185ba71887f918a9da82140210494608df020dcbd5Evan Cheng        NumMerges += Merges.size();
1119a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
11200ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng        // Try folding preceeding/trailing base inc/dec into those load/store
11210ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng        // that were not merged to form LDM/STM ops.
11220ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng        for (unsigned i = 0; i != NumMemOps; ++i)
11230ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng          if (!MemOps[i].Merged)
112445032f28013aa69d07bf859da9d976947910f059Evan Cheng            if (MergeBaseUpdateLoadStore(MBB, MemOps[i].MBBI, TII,Advance,MBBI))
11259d5fb981b0ebc00e068b9bcb4df7388a8ea94b71Evan Cheng              ++NumMerges;
11260ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng
1127764ab52dd80310a205c9888bf166d09dab858f90Jim Grosbach        // RS may be pointing to an instruction that's deleted.
11280ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng        RS->skipTo(prior(MBBI));
11291488326156741063fa7a23e1638c13e81d167e22Evan Cheng      } else if (NumMemOps == 1) {
11301488326156741063fa7a23e1638c13e81d167e22Evan Cheng        // Try folding preceeding/trailing base inc/dec into the single
11311488326156741063fa7a23e1638c13e81d167e22Evan Cheng        // load/store.
113245032f28013aa69d07bf859da9d976947910f059Evan Cheng        if (MergeBaseUpdateLoadStore(MBB, MemOps[0].MBBI, TII, Advance, MBBI)) {
11331488326156741063fa7a23e1638c13e81d167e22Evan Cheng          ++NumMerges;
11341488326156741063fa7a23e1638c13e81d167e22Evan Cheng          RS->forward(prior(MBBI));
11351488326156741063fa7a23e1638c13e81d167e22Evan Cheng        }
11360ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng      }
1137a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
1138a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      CurrBase = 0;
1139a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      CurrOpc = -1;
114044bec52b1b7e9a3ac1efbae90db240b8c1ca2ad4Evan Cheng      CurrSize = 0;
114144bec52b1b7e9a3ac1efbae90db240b8c1ca2ad4Evan Cheng      CurrPred = ARMCC::AL;
11420e1d37904abbf7e8c4c478408253dd995f3040f4Evan Cheng      CurrPredReg = 0;
1143a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      if (NumMemOps) {
1144a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        MemOps.clear();
1145a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        NumMemOps = 0;
1146a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      }
1147a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
1148a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // If iterator hasn't been advanced and this is not a memory op, skip it.
1149a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      // It can't start a new chain anyway.
1150a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      if (!Advance && !isMemOp && MBBI != E) {
1151a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        ++Position;
1152a8e2989ece6dc46df59b0768184028257f913843Evan Cheng        ++MBBI;
1153a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      }
1154a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
1155a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
1156a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  return NumMerges > 0;
1157a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
1158a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
1159e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Chengnamespace {
1160e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  struct OffsetCompare {
1161e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    bool operator()(const MachineInstr *LHS, const MachineInstr *RHS) const {
1162e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      int LOffset = getMemoryOpOffset(LHS);
1163e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      int ROffset = getMemoryOpOffset(RHS);
1164e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      assert(LHS == RHS || LOffset != ROffset);
1165e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      return LOffset > ROffset;
1166e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    }
1167e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  };
1168e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng}
1169e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1170c88d0722931b8442cd347bd530e2182d164c82c6Bob Wilson/// MergeReturnIntoLDM - If this is a exit BB, try merging the return ops
1171c88d0722931b8442cd347bd530e2182d164c82c6Bob Wilson/// ("bx lr" and "mov pc, lr") into the preceeding stack restore so it
1172c88d0722931b8442cd347bd530e2182d164c82c6Bob Wilson/// directly restore the value of LR into pc.
1173c88d0722931b8442cd347bd530e2182d164c82c6Bob Wilson///   ldmfd sp!, {..., lr}
1174a8e2989ece6dc46df59b0768184028257f913843Evan Cheng///   bx lr
1175c88d0722931b8442cd347bd530e2182d164c82c6Bob Wilson/// or
1176c88d0722931b8442cd347bd530e2182d164c82c6Bob Wilson///   ldmfd sp!, {..., lr}
1177c88d0722931b8442cd347bd530e2182d164c82c6Bob Wilson///   mov pc, lr
1178a8e2989ece6dc46df59b0768184028257f913843Evan Cheng/// =>
1179c88d0722931b8442cd347bd530e2182d164c82c6Bob Wilson///   ldmfd sp!, {..., pc}
1180a8e2989ece6dc46df59b0768184028257f913843Evan Chengbool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) {
1181a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  if (MBB.empty()) return false;
1182a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
1183a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  MachineBasicBlock::iterator MBBI = prior(MBB.end());
118445032f28013aa69d07bf859da9d976947910f059Evan Cheng  if (MBBI != MBB.begin() &&
1185c88d0722931b8442cd347bd530e2182d164c82c6Bob Wilson      (MBBI->getOpcode() == ARM::BX_RET ||
1186c88d0722931b8442cd347bd530e2182d164c82c6Bob Wilson       MBBI->getOpcode() == ARM::tBX_RET ||
1187c88d0722931b8442cd347bd530e2182d164c82c6Bob Wilson       MBBI->getOpcode() == ARM::MOVPCLR)) {
1188a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    MachineInstr *PrevMI = prior(MBBI);
1189815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson    if (PrevMI->getOpcode() == ARM::LDM_UPD ||
1190815baebe1c8dc02accf128ae10dff9a1742d3244Bob Wilson        PrevMI->getOpcode() == ARM::t2LDM_UPD) {
1191a8e2989ece6dc46df59b0768184028257f913843Evan Cheng      MachineOperand &MO = PrevMI->getOperand(PrevMI->getNumOperands()-1);
119227934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      if (MO.getReg() != ARM::LR)
119327934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng        return false;
119427934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      unsigned NewOpc = isThumb2 ? ARM::t2LDM_RET : ARM::LDM_RET;
119527934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      PrevMI->setDesc(TII->get(NewOpc));
119627934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      MO.setReg(ARM::PC);
119727934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      MBB.erase(MBBI);
119827934da97bcb7a6a4949dfc0c449d99f43077e98Evan Cheng      return true;
1199a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    }
1200a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
1201a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  return false;
1202a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
1203a8e2989ece6dc46df59b0768184028257f913843Evan Cheng
1204a8e2989ece6dc46df59b0768184028257f913843Evan Chengbool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
1205cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng  const TargetMachine &TM = Fn.getTarget();
1206603b83ebcdfb9c27e44c1da16f2799755e3e3022Evan Cheng  AFI = Fn.getInfo<ARMFunctionInfo>();
1207cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng  TII = TM.getInstrInfo();
12086f0d024a534af18d9e60b3ea757376cd8a3a980eDan Gohman  TRI = TM.getRegisterInfo();
12090ea12ec8484c45ca1394f3b2dcd39c9a34cf2ab9Evan Cheng  RS = new RegScavenger();
121045032f28013aa69d07bf859da9d976947910f059Evan Cheng  isThumb2 = AFI->isThumb2Function();
1211cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng
1212a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  bool Modified = false;
1213a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
1214a8e2989ece6dc46df59b0768184028257f913843Evan Cheng       ++MFI) {
1215a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    MachineBasicBlock &MBB = *MFI;
1216a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    Modified |= LoadStoreMultipleOpti(MBB);
1217a8e2989ece6dc46df59b0768184028257f913843Evan Cheng    Modified |= MergeReturnIntoLDM(MBB);
1218a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  }
1219cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng
1220cc1c427266817e0f41cbb9d0dc97a52890182040Evan Cheng  delete RS;
1221a8e2989ece6dc46df59b0768184028257f913843Evan Cheng  return Modified;
1222a8e2989ece6dc46df59b0768184028257f913843Evan Cheng}
1223e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1224e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1225e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng/// ARMPreAllocLoadStoreOpt - Pre- register allocation pass that move
1226e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng/// load / stores from consecutive locations close to make it more
1227e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng/// likely they will be combined later.
1228e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1229e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Chengnamespace {
12306726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky  struct ARMPreAllocLoadStoreOpt : public MachineFunctionPass{
1231e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    static char ID;
123290c579de5a383cee278acc3f7e7b9d0a656e6a35Owen Anderson    ARMPreAllocLoadStoreOpt() : MachineFunctionPass(ID) {}
1233e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1234358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    const TargetData *TD;
1235e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    const TargetInstrInfo *TII;
1236e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    const TargetRegisterInfo *TRI;
1237358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    const ARMSubtarget *STI;
1238e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    MachineRegisterInfo *MRI;
1239eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    MachineFunction *MF;
1240e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1241e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    virtual bool runOnMachineFunction(MachineFunction &Fn);
1242e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1243e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    virtual const char *getPassName() const {
1244e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      return "ARM pre- register allocation load / store optimization pass";
1245e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    }
1246e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1247e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  private:
1248d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng    bool CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, DebugLoc &dl,
1249d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng                          unsigned &NewOpc, unsigned &EvenReg,
1250d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng                          unsigned &OddReg, unsigned &BaseReg,
1251e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                          unsigned &OffReg, int &Offset,
1252eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng                          unsigned &PredReg, ARMCC::CondCodes &Pred,
1253eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng                          bool &isT2);
1254e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    bool RescheduleOps(MachineBasicBlock *MBB,
1255e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng                       SmallVector<MachineInstr*, 4> &Ops,
1256e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng                       unsigned Base, bool isLd,
1257e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng                       DenseMap<MachineInstr*, unsigned> &MI2LocMap);
1258e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    bool RescheduleLoadStoreInstrs(MachineBasicBlock *MBB);
1259e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  };
1260e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  char ARMPreAllocLoadStoreOpt::ID = 0;
1261e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng}
1262e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1263e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Chengbool ARMPreAllocLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
1264358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng  TD  = Fn.getTarget().getTargetData();
1265e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  TII = Fn.getTarget().getInstrInfo();
1266e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  TRI = Fn.getTarget().getRegisterInfo();
1267358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng  STI = &Fn.getTarget().getSubtarget<ARMSubtarget>();
1268e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  MRI = &Fn.getRegInfo();
1269eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng  MF  = &Fn;
1270e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1271e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  bool Modified = false;
1272e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
1273e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng       ++MFI)
1274e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    Modified |= RescheduleLoadStoreInstrs(MFI);
1275e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1276e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  return Modified;
1277e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng}
1278e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1279ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Chengstatic bool IsSafeAndProfitableToMove(bool isLd, unsigned Base,
1280ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng                                      MachineBasicBlock::iterator I,
1281ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng                                      MachineBasicBlock::iterator E,
1282ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng                                      SmallPtrSet<MachineInstr*, 4> &MemOps,
1283ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng                                      SmallSet<unsigned, 4> &MemRegs,
1284ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng                                      const TargetRegisterInfo *TRI) {
1285e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  // Are there stores / loads / calls between them?
1286e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  // FIXME: This is overly conservative. We should make use of alias information
1287e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  // some day.
1288ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng  SmallSet<unsigned, 4> AddedRegPressure;
1289e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  while (++I != E) {
1290958e4e1967838766d327f1112e5b4900be939275Jim Grosbach    if (I->isDebugValue() || MemOps.count(&*I))
1291ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng      continue;
1292e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    const TargetInstrDesc &TID = I->getDesc();
1293e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    if (TID.isCall() || TID.isTerminator() || TID.hasUnmodeledSideEffects())
1294e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      return false;
1295e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    if (isLd && TID.mayStore())
1296e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      return false;
1297e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    if (!isLd) {
1298e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (TID.mayLoad())
1299e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        return false;
1300e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      // It's not safe to move the first 'str' down.
1301e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      // str r1, [r0]
1302e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      // strh r5, [r0]
1303e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      // str r4, [r0, #+4]
1304ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng      if (TID.mayStore())
1305e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        return false;
1306e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    }
1307e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    for (unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) {
1308e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      MachineOperand &MO = I->getOperand(j);
1309ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng      if (!MO.isReg())
1310ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng        continue;
1311ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng      unsigned Reg = MO.getReg();
1312ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng      if (MO.isDef() && TRI->regsOverlap(Reg, Base))
1313e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        return false;
1314ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng      if (Reg != Base && !MemRegs.count(Reg))
1315ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng        AddedRegPressure.insert(Reg);
1316e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    }
1317e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  }
1318ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng
1319ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng  // Estimate register pressure increase due to the transformation.
1320ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng  if (MemRegs.size() <= 4)
1321ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng    // Ok if we are moving small number of instructions.
1322ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng    return true;
1323ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng  return AddedRegPressure.size() <= MemRegs.size() * 2;
1324e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng}
1325e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1326d780f357941fc587d36d141bab3d78d6ff972dd4Evan Chengbool
1327d780f357941fc587d36d141bab3d78d6ff972dd4Evan ChengARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1,
1328d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng                                          DebugLoc &dl,
1329d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng                                          unsigned &NewOpc, unsigned &EvenReg,
1330d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng                                          unsigned &OddReg, unsigned &BaseReg,
1331e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng                                          unsigned &OffReg, int &Offset,
1332d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng                                          unsigned &PredReg,
1333eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng                                          ARMCC::CondCodes &Pred,
1334eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng                                          bool &isT2) {
1335fa1be5d99153a4709740ce5aabba3793e9f77982Evan Cheng  // Make sure we're allowed to generate LDRD/STRD.
1336fa1be5d99153a4709740ce5aabba3793e9f77982Evan Cheng  if (!STI->hasV5TEOps())
1337fa1be5d99153a4709740ce5aabba3793e9f77982Evan Cheng    return false;
1338fa1be5d99153a4709740ce5aabba3793e9f77982Evan Cheng
1339e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach  // FIXME: VLDRS / VSTRS -> VLDRD / VSTRD
1340eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng  unsigned Scale = 1;
1341d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  unsigned Opcode = Op0->getOpcode();
1342d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  if (Opcode == ARM::LDR)
1343d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng    NewOpc = ARM::LDRD;
1344d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  else if (Opcode == ARM::STR)
1345d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng    NewOpc = ARM::STRD;
1346eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng  else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) {
1347eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    NewOpc = ARM::t2LDRDi8;
1348eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    Scale = 4;
1349eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    isT2 = true;
1350eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng  } else if (Opcode == ARM::t2STRi8 || Opcode == ARM::t2STRi12) {
1351eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    NewOpc = ARM::t2STRDi8;
1352eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    Scale = 4;
1353eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    isT2 = true;
1354eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng  } else
1355eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    return false;
1356eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng
13578f05c1004a642ba79c609b40cb3b6524d810b5f3Evan Cheng  // Make sure the offset registers match.
1358eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng  if (!isT2 &&
1359eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng      (Op0->getOperand(2).getReg() != Op1->getOperand(2).getReg()))
1360eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng      return false;
1361d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng
1362d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  // Must sure the base address satisfies i64 ld / st alignment requirement.
1363d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  if (!Op0->hasOneMemOperand() ||
1364c76909abfec876c6b751d693ebd3df07df686aa0Dan Gohman      !(*Op0->memoperands_begin())->getValue() ||
1365c76909abfec876c6b751d693ebd3df07df686aa0Dan Gohman      (*Op0->memoperands_begin())->isVolatile())
1366358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng    return false;
1367358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng
1368c76909abfec876c6b751d693ebd3df07df686aa0Dan Gohman  unsigned Align = (*Op0->memoperands_begin())->getAlignment();
1369ae541aad5c36cb3e4256514447d1f81e253079c7Dan Gohman  const Function *Func = MF->getFunction();
1370358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng  unsigned ReqAlign = STI->hasV6Ops()
1371eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    ? TD->getPrefTypeAlignment(Type::getInt64Ty(Func->getContext()))
1372eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    : 8;  // Pre-v6 need 8-byte align
1373d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  if (Align < ReqAlign)
1374d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng    return false;
1375d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng
1376d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  // Then make sure the immediate offset fits.
1377d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  int OffImm = getMemoryOpOffset(Op0);
1378e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng  if (isT2) {
1379e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    if (OffImm < 0) {
1380e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      if (OffImm < -255)
1381e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng        // Can't fall back to t2LDRi8 / t2STRi8.
1382e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng        return false;
1383e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    } else {
1384e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      int Limit = (1 << 8) * Scale;
1385e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      if (OffImm >= Limit || (OffImm & (Scale-1)))
1386e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng        return false;
1387e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    }
1388eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    Offset = OffImm;
1389e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng  } else {
1390e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    ARM_AM::AddrOpc AddSub = ARM_AM::add;
1391e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    if (OffImm < 0) {
1392e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      AddSub = ARM_AM::sub;
1393e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      OffImm = - OffImm;
1394e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    }
1395e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    int Limit = (1 << 8) * Scale;
1396e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng    if (OffImm >= Limit || (OffImm & (Scale-1)))
1397e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng      return false;
1398eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    Offset = ARM_AM::getAM3Opc(AddSub, OffImm);
1399e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng  }
1400d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  EvenReg = Op0->getOperand(0).getReg();
1401675860758ec8926f9803840615366931aca7f8d8Evan Cheng  OddReg  = Op1->getOperand(0).getReg();
1402d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  if (EvenReg == OddReg)
1403d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng    return false;
1404d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  BaseReg = Op0->getOperand(1).getReg();
1405eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng  if (!isT2)
1406eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng    OffReg = Op0->getOperand(2).getReg();
14078fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng  Pred = llvm::getInstrPredicate(Op0, PredReg);
1408d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  dl = Op0->getDebugLoc();
1409d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng  return true;
1410358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng}
1411358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng
1412e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Chengbool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
1413e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng                                 SmallVector<MachineInstr*, 4> &Ops,
1414e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng                                 unsigned Base, bool isLd,
1415e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng                                 DenseMap<MachineInstr*, unsigned> &MI2LocMap) {
1416e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  bool RetVal = false;
1417e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1418e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  // Sort by offset (in reverse order).
1419e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  std::sort(Ops.begin(), Ops.end(), OffsetCompare());
1420e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1421e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  // The loads / stores of the same base are in order. Scan them from first to
1422d089a7ac70397ea41fe6128639dc54b8e273ed60Jim Grosbach  // last and check for the following:
1423e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  // 1. Any def of base.
1424e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  // 2. Any gaps.
1425e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  while (Ops.size() > 1) {
1426e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    unsigned FirstLoc = ~0U;
1427e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    unsigned LastLoc = 0;
1428e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    MachineInstr *FirstOp = 0;
1429e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    MachineInstr *LastOp = 0;
1430e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    int LastOffset = 0;
1431f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng    unsigned LastOpcode = 0;
1432e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    unsigned LastBytes = 0;
1433e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    unsigned NumMove = 0;
1434e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    for (int i = Ops.size() - 1; i >= 0; --i) {
1435e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      MachineInstr *Op = Ops[i];
1436e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      unsigned Loc = MI2LocMap[Op];
1437e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (Loc <= FirstLoc) {
1438e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        FirstLoc = Loc;
1439e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        FirstOp = Op;
1440e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      }
1441e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (Loc >= LastLoc) {
1442e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        LastLoc = Loc;
1443e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        LastOp = Op;
1444e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      }
1445e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1446f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng      unsigned Opcode = Op->getOpcode();
1447f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng      if (LastOpcode && Opcode != LastOpcode)
1448f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng        break;
1449f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng
1450e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      int Offset = getMemoryOpOffset(Op);
1451e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      unsigned Bytes = getLSMultipleTransferSize(Op);
1452e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (LastBytes) {
1453e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        if (Bytes != LastBytes || Offset != (LastOffset + (int)Bytes))
1454e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          break;
1455e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      }
1456e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      LastOffset = Offset;
1457e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      LastBytes = Bytes;
1458f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng      LastOpcode = Opcode;
1459eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng      if (++NumMove == 8) // FIXME: Tune this limit.
1460e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        break;
1461e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    }
1462e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1463e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    if (NumMove <= 1)
1464e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      Ops.pop_back();
1465e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    else {
1466ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng      SmallPtrSet<MachineInstr*, 4> MemOps;
1467ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng      SmallSet<unsigned, 4> MemRegs;
1468ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng      for (int i = NumMove-1; i >= 0; --i) {
1469ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng        MemOps.insert(Ops[i]);
1470ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng        MemRegs.insert(Ops[i]->getOperand(0).getReg());
1471ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng      }
1472e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1473e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      // Be conservative, if the instructions are too far apart, don't
1474e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      // move them. We want to limit the increase of register pressure.
1475ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng      bool DoMove = (LastLoc - FirstLoc) <= NumMove*4; // FIXME: Tune this.
1476e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (DoMove)
1477ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng        DoMove = IsSafeAndProfitableToMove(isLd, Base, FirstOp, LastOp,
1478ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng                                           MemOps, MemRegs, TRI);
1479e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (!DoMove) {
1480e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        for (unsigned i = 0; i != NumMove; ++i)
1481e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          Ops.pop_back();
1482e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      } else {
1483e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        // This is the new location for the loads / stores.
1484e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        MachineBasicBlock::iterator InsertPos = isLd ? FirstOp : LastOp;
1485400c95fe3802821815c69077e48c8fd276ec6494Jim Grosbach        while (InsertPos != MBB->end()
1486400c95fe3802821815c69077e48c8fd276ec6494Jim Grosbach               && (MemOps.count(InsertPos) || InsertPos->isDebugValue()))
1487e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          ++InsertPos;
1488358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng
1489358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng        // If we are moving a pair of loads / stores, see if it makes sense
1490358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng        // to try to allocate a pair of registers that can form register pairs.
1491d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng        MachineInstr *Op0 = Ops.back();
1492d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng        MachineInstr *Op1 = Ops[Ops.size()-2];
1493d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng        unsigned EvenReg = 0, OddReg = 0;
1494d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng        unsigned BaseReg = 0, OffReg = 0, PredReg = 0;
1495d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng        ARMCC::CondCodes Pred = ARMCC::AL;
1496eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng        bool isT2 = false;
1497d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng        unsigned NewOpc = 0;
1498e298ab26b11cf6e278b4876bbc5b890e234d4029Evan Cheng        int Offset = 0;
1499d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng        DebugLoc dl;
1500d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng        if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,
1501d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng                                             EvenReg, OddReg, BaseReg, OffReg,
1502eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng                                             Offset, PredReg, Pred, isT2)) {
1503d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng          Ops.pop_back();
1504d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng          Ops.pop_back();
1505358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng
1506d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng          // Form the pair instruction.
1507f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng          if (isLd) {
1508eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng            MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos,
1509eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng                                              dl, TII->get(NewOpc))
1510358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng              .addReg(EvenReg, RegState::Define)
1511358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng              .addReg(OddReg, RegState::Define)
1512eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng              .addReg(BaseReg);
1513eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng            if (!isT2)
1514eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng              MIB.addReg(OffReg);
1515eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng            MIB.addImm(Offset).addImm(Pred).addReg(PredReg);
1516f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng            ++NumLDRDFormed;
1517f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng          } else {
1518eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng            MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos,
1519eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng                                              dl, TII->get(NewOpc))
1520358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng              .addReg(EvenReg)
1521358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng              .addReg(OddReg)
1522eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng              .addReg(BaseReg);
1523eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng            if (!isT2)
1524eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng              MIB.addReg(OffReg);
1525eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng            MIB.addImm(Offset).addImm(Pred).addReg(PredReg);
1526f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng            ++NumSTRDFormed;
1527f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng          }
1528f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng          MBB->erase(Op0);
1529f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4Evan Cheng          MBB->erase(Op1);
1530358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng
1531358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng          // Add register allocation hints to form register pairs.
1532358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng          MRI->setRegAllocationHint(EvenReg, ARMRI::RegPairEven, OddReg);
1533358dec51804ee52e47ea3a47c9248086e458ad7cEvan Cheng          MRI->setRegAllocationHint(OddReg,  ARMRI::RegPairOdd, EvenReg);
1534d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng        } else {
1535d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng          for (unsigned i = 0; i != NumMove; ++i) {
1536d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng            MachineInstr *Op = Ops.back();
1537d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng            Ops.pop_back();
1538d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng            MBB->splice(InsertPos, MBB, Op);
1539d780f357941fc587d36d141bab3d78d6ff972dd4Evan Cheng          }
1540e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        }
1541e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1542e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        NumLdStMoved += NumMove;
1543e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        RetVal = true;
1544e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      }
1545e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    }
1546e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  }
1547e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1548e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  return RetVal;
1549e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng}
1550e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1551e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Chengbool
1552e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan ChengARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) {
1553e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  bool RetVal = false;
1554e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1555e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  DenseMap<MachineInstr*, unsigned> MI2LocMap;
1556e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  DenseMap<unsigned, SmallVector<MachineInstr*, 4> > Base2LdsMap;
1557e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  DenseMap<unsigned, SmallVector<MachineInstr*, 4> > Base2StsMap;
1558e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  SmallVector<unsigned, 4> LdBases;
1559e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  SmallVector<unsigned, 4> StBases;
1560e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1561e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  unsigned Loc = 0;
1562e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  MachineBasicBlock::iterator MBBI = MBB->begin();
1563e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  MachineBasicBlock::iterator E = MBB->end();
1564e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  while (MBBI != E) {
1565e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    for (; MBBI != E; ++MBBI) {
1566e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      MachineInstr *MI = MBBI;
1567e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      const TargetInstrDesc &TID = MI->getDesc();
1568e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (TID.isCall() || TID.isTerminator()) {
1569e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        // Stop at barriers.
1570e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        ++MBBI;
1571e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        break;
1572e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      }
1573e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1574958e4e1967838766d327f1112e5b4900be939275Jim Grosbach      if (!MI->isDebugValue())
1575958e4e1967838766d327f1112e5b4900be939275Jim Grosbach        MI2LocMap[MI] = ++Loc;
1576958e4e1967838766d327f1112e5b4900be939275Jim Grosbach
1577e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (!isMemoryOp(MI))
1578e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        continue;
1579e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      unsigned PredReg = 0;
15808fb903604e83dfd63659c919042bf2bfed3c940fEvan Cheng      if (llvm::getInstrPredicate(MI, PredReg) != ARMCC::AL)
1581e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        continue;
1582e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1583eef490f45919c8f279e40b8b5ef09f612ec6ce2cEvan Cheng      int Opc = MI->getOpcode();
1584e5165490b7ba24bb2f3043399e0d60e7f3bcf8a5Jim Grosbach      bool isLd = isi32Load(Opc) || Opc == ARM::VLDRS || Opc == ARM::VLDRD;
1585e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      unsigned Base = MI->getOperand(1).getReg();
1586e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      int Offset = getMemoryOpOffset(MI);
1587e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1588e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      bool StopHere = false;
1589e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (isLd) {
1590e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        DenseMap<unsigned, SmallVector<MachineInstr*, 4> >::iterator BI =
1591e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          Base2LdsMap.find(Base);
1592e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        if (BI != Base2LdsMap.end()) {
1593e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          for (unsigned i = 0, e = BI->second.size(); i != e; ++i) {
1594e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng            if (Offset == getMemoryOpOffset(BI->second[i])) {
1595e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng              StopHere = true;
1596e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng              break;
1597e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng            }
1598e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          }
1599e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          if (!StopHere)
1600e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng            BI->second.push_back(MI);
1601e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        } else {
1602e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          SmallVector<MachineInstr*, 4> MIs;
1603e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          MIs.push_back(MI);
1604e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          Base2LdsMap[Base] = MIs;
1605e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          LdBases.push_back(Base);
1606e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        }
1607e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      } else {
1608e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        DenseMap<unsigned, SmallVector<MachineInstr*, 4> >::iterator BI =
1609e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          Base2StsMap.find(Base);
1610e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        if (BI != Base2StsMap.end()) {
1611e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          for (unsigned i = 0, e = BI->second.size(); i != e; ++i) {
1612e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng            if (Offset == getMemoryOpOffset(BI->second[i])) {
1613e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng              StopHere = true;
1614e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng              break;
1615e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng            }
1616e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          }
1617e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          if (!StopHere)
1618e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng            BI->second.push_back(MI);
1619e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        } else {
1620e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          SmallVector<MachineInstr*, 4> MIs;
1621e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          MIs.push_back(MI);
1622e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          Base2StsMap[Base] = MIs;
1623e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng          StBases.push_back(Base);
1624e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        }
1625e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      }
1626e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1627e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (StopHere) {
1628ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng        // Found a duplicate (a base+offset combination that's seen earlier).
1629ae69a2a12bd0af3fa81957f7896d1a54ad69dbb2Evan Cheng        // Backtrack.
1630e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        --Loc;
1631e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        break;
1632e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      }
1633e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    }
1634e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1635e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    // Re-schedule loads.
1636e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    for (unsigned i = 0, e = LdBases.size(); i != e; ++i) {
1637e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      unsigned Base = LdBases[i];
1638e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      SmallVector<MachineInstr*, 4> &Lds = Base2LdsMap[Base];
1639e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (Lds.size() > 1)
1640e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        RetVal |= RescheduleOps(MBB, Lds, Base, true, MI2LocMap);
1641e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    }
1642e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1643e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    // Re-schedule stores.
1644e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    for (unsigned i = 0, e = StBases.size(); i != e; ++i) {
1645e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      unsigned Base = StBases[i];
1646e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      SmallVector<MachineInstr*, 4> &Sts = Base2StsMap[Base];
1647e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      if (Sts.size() > 1)
1648e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng        RetVal |= RescheduleOps(MBB, Sts, Base, false, MI2LocMap);
1649e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    }
1650e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1651e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    if (MBBI != E) {
1652e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      Base2LdsMap.clear();
1653e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      Base2StsMap.clear();
1654e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      LdBases.clear();
1655e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng      StBases.clear();
1656e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    }
1657e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  }
1658e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1659e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  return RetVal;
1660e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng}
1661e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1662e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng
1663e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng/// createARMLoadStoreOptimizationPass - returns an instance of the load / store
1664e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng/// optimization pass.
1665e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan ChengFunctionPass *llvm::createARMLoadStoreOptimizationPass(bool PreAlloc) {
1666e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  if (PreAlloc)
1667e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng    return new ARMPreAllocLoadStoreOpt();
1668e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng  return new ARMLoadStoreOpt();
1669e7d6df73530a98a5cc5f69ddfd17073b464caa57Evan Cheng}
1670