]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Target/ARM/ARMLoadStoreOptimizer.cpp
Import LLVM, at r72995.
[FreeBSD/FreeBSD.git] / lib / Target / ARM / ARMLoadStoreOptimizer.cpp
1 //===-- ARMLoadStoreOptimizer.cpp - ARM load / store opt. pass ----*- C++ -*-=//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains a pass that performs load / store related peephole
11 // optimizations. This pass should be run after register allocation.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "arm-ldst-opt"
16 #include "ARM.h"
17 #include "ARMAddressingModes.h"
18 #include "ARMMachineFunctionInfo.h"
19 #include "ARMRegisterInfo.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/Statistic.h"
23 #include "llvm/CodeGen/MachineBasicBlock.h"
24 #include "llvm/CodeGen/MachineFunctionPass.h"
25 #include "llvm/CodeGen/MachineInstr.h"
26 #include "llvm/CodeGen/MachineInstrBuilder.h"
27 #include "llvm/CodeGen/RegisterScavenging.h"
28 #include "llvm/Support/Compiler.h"
29 #include "llvm/Target/TargetRegisterInfo.h"
30 #include "llvm/Target/TargetInstrInfo.h"
31 #include "llvm/Target/TargetMachine.h"
32 using namespace llvm;
33
34 STATISTIC(NumLDMGened , "Number of ldm instructions generated");
35 STATISTIC(NumSTMGened , "Number of stm instructions generated");
36 STATISTIC(NumFLDMGened, "Number of fldm instructions generated");
37 STATISTIC(NumFSTMGened, "Number of fstm instructions generated");
38
39 namespace {
40   struct VISIBILITY_HIDDEN ARMLoadStoreOpt : public MachineFunctionPass {
41     static char ID;
42     ARMLoadStoreOpt() : MachineFunctionPass(&ID) {}
43
44     const TargetInstrInfo *TII;
45     const TargetRegisterInfo *TRI;
46     ARMFunctionInfo *AFI;
47     RegScavenger *RS;
48
49     virtual bool runOnMachineFunction(MachineFunction &Fn);
50
51     virtual const char *getPassName() const {
52       return "ARM load / store optimization pass";
53     }
54
55   private:
56     struct MemOpQueueEntry {
57       int Offset;
58       unsigned Position;
59       MachineBasicBlock::iterator MBBI;
60       bool Merged;
61       MemOpQueueEntry(int o, int p, MachineBasicBlock::iterator i)
62         : Offset(o), Position(p), MBBI(i), Merged(false) {};
63     };
64     typedef SmallVector<MemOpQueueEntry,8> MemOpQueue;
65     typedef MemOpQueue::iterator MemOpQueueIter;
66
67     bool MergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
68                   int Offset, unsigned Base, bool BaseKill, int Opcode,
69                   ARMCC::CondCodes Pred, unsigned PredReg, unsigned Scratch,
70                   DebugLoc dl, SmallVector<std::pair<unsigned, bool>, 8> &Regs);
71     void MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base,
72                       int Opcode, unsigned Size,
73                       ARMCC::CondCodes Pred, unsigned PredReg,
74                       unsigned Scratch, MemOpQueue &MemOps,
75                       SmallVector<MachineBasicBlock::iterator, 4> &Merges);
76
77     void AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps);
78     bool LoadStoreMultipleOpti(MachineBasicBlock &MBB);
79     bool MergeReturnIntoLDM(MachineBasicBlock &MBB);
80   };
81   char ARMLoadStoreOpt::ID = 0;
82 }
83
84 /// createARMLoadStoreOptimizationPass - returns an instance of the load / store
85 /// optimization pass.
86 FunctionPass *llvm::createARMLoadStoreOptimizationPass() {
87   return new ARMLoadStoreOpt();
88 }
89
90 static int getLoadStoreMultipleOpcode(int Opcode) {
91   switch (Opcode) {
92   case ARM::LDR:
93     NumLDMGened++;
94     return ARM::LDM;
95   case ARM::STR:
96     NumSTMGened++;
97     return ARM::STM;
98   case ARM::FLDS:
99     NumFLDMGened++;
100     return ARM::FLDMS;
101   case ARM::FSTS:
102     NumFSTMGened++;
103     return ARM::FSTMS;
104   case ARM::FLDD:
105     NumFLDMGened++;
106     return ARM::FLDMD;
107   case ARM::FSTD:
108     NumFSTMGened++;
109     return ARM::FSTMD;
110   default: abort();
111   }
112   return 0;
113 }
114
115 /// MergeOps - Create and insert a LDM or STM with Base as base register and
116 /// registers in Regs as the register operands that would be loaded / stored.
117 /// It returns true if the transformation is done. 
118 bool
119 ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
120                           MachineBasicBlock::iterator MBBI,
121                           int Offset, unsigned Base, bool BaseKill,
122                           int Opcode, ARMCC::CondCodes Pred,
123                           unsigned PredReg, unsigned Scratch, DebugLoc dl,
124                           SmallVector<std::pair<unsigned, bool>, 8> &Regs) {
125   // Only a single register to load / store. Don't bother.
126   unsigned NumRegs = Regs.size();
127   if (NumRegs <= 1)
128     return false;
129
130   ARM_AM::AMSubMode Mode = ARM_AM::ia;
131   bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
132   if (isAM4 && Offset == 4)
133     Mode = ARM_AM::ib;
134   else if (isAM4 && Offset == -4 * (int)NumRegs + 4)
135     Mode = ARM_AM::da;
136   else if (isAM4 && Offset == -4 * (int)NumRegs)
137     Mode = ARM_AM::db;
138   else if (Offset != 0) {
139     // If starting offset isn't zero, insert a MI to materialize a new base.
140     // But only do so if it is cost effective, i.e. merging more than two
141     // loads / stores.
142     if (NumRegs <= 2)
143       return false;
144
145     unsigned NewBase;
146     if (Opcode == ARM::LDR)
147       // If it is a load, then just use one of the destination register to
148       // use as the new base.
149       NewBase = Regs[NumRegs-1].first;
150     else {
151       // Use the scratch register to use as a new base.
152       NewBase = Scratch;
153       if (NewBase == 0)
154         return false;
155     }
156     int BaseOpc = ARM::ADDri;
157     if (Offset < 0) {
158       BaseOpc = ARM::SUBri;
159       Offset = - Offset;
160     }
161     int ImmedOffset = ARM_AM::getSOImmVal(Offset);
162     if (ImmedOffset == -1)
163       return false;  // Probably not worth it then.
164
165     BuildMI(MBB, MBBI, dl, TII->get(BaseOpc), NewBase)
166       .addReg(Base, getKillRegState(BaseKill)).addImm(ImmedOffset)
167       .addImm(Pred).addReg(PredReg).addReg(0);
168     Base = NewBase;
169     BaseKill = true;  // New base is always killed right its use.
170   }
171
172   bool isDPR = Opcode == ARM::FLDD || Opcode == ARM::FSTD;
173   bool isDef = Opcode == ARM::LDR || Opcode == ARM::FLDS || Opcode == ARM::FLDD;
174   Opcode = getLoadStoreMultipleOpcode(Opcode);
175   MachineInstrBuilder MIB = (isAM4)
176     ? BuildMI(MBB, MBBI, dl, TII->get(Opcode))
177         .addReg(Base, getKillRegState(BaseKill))
178         .addImm(ARM_AM::getAM4ModeImm(Mode)).addImm(Pred).addReg(PredReg)
179     : BuildMI(MBB, MBBI, dl, TII->get(Opcode))
180         .addReg(Base, getKillRegState(BaseKill))
181         .addImm(ARM_AM::getAM5Opc(Mode, false, isDPR ? NumRegs<<1 : NumRegs))
182         .addImm(Pred).addReg(PredReg);
183   for (unsigned i = 0; i != NumRegs; ++i)
184     MIB = MIB.addReg(Regs[i].first, getDefRegState(isDef)
185                      | getKillRegState(Regs[i].second));
186
187   return true;
188 }
189
190 /// MergeLDR_STR - Merge a number of load / store instructions into one or more
191 /// load / store multiple instructions.
192 void
193 ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
194                           unsigned Base, int Opcode, unsigned Size,
195                           ARMCC::CondCodes Pred, unsigned PredReg,
196                           unsigned Scratch, MemOpQueue &MemOps,
197                           SmallVector<MachineBasicBlock::iterator, 4> &Merges) {
198   bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
199   int Offset = MemOps[SIndex].Offset;
200   int SOffset = Offset;
201   unsigned Pos = MemOps[SIndex].Position;
202   MachineBasicBlock::iterator Loc = MemOps[SIndex].MBBI;
203   DebugLoc dl = Loc->getDebugLoc();
204   unsigned PReg = Loc->getOperand(0).getReg();
205   unsigned PRegNum = ARMRegisterInfo::getRegisterNumbering(PReg);
206   bool isKill = Loc->getOperand(0).isKill();
207
208   SmallVector<std::pair<unsigned,bool>, 8> Regs;
209   Regs.push_back(std::make_pair(PReg, isKill));
210   for (unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) {
211     int NewOffset = MemOps[i].Offset;
212     unsigned Reg = MemOps[i].MBBI->getOperand(0).getReg();
213     unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
214     isKill = MemOps[i].MBBI->getOperand(0).isKill();
215     // AM4 - register numbers in ascending order.
216     // AM5 - consecutive register numbers in ascending order.
217     if (NewOffset == Offset + (int)Size &&
218         ((isAM4 && RegNum > PRegNum) || RegNum == PRegNum+1)) {
219       Offset += Size;
220       Regs.push_back(std::make_pair(Reg, isKill));
221       PRegNum = RegNum;
222     } else {
223       // Can't merge this in. Try merge the earlier ones first.
224       if (MergeOps(MBB, ++Loc, SOffset, Base, false, Opcode, Pred, PredReg,
225                    Scratch, dl, Regs)) {
226         Merges.push_back(prior(Loc));
227         for (unsigned j = SIndex; j < i; ++j) {
228           MBB.erase(MemOps[j].MBBI);
229           MemOps[j].Merged = true;
230         }
231       }
232       MergeLDR_STR(MBB, i, Base, Opcode, Size, Pred, PredReg, Scratch,
233                    MemOps, Merges);
234       return;
235     }
236
237     if (MemOps[i].Position > Pos) {
238       Pos = MemOps[i].Position;
239       Loc = MemOps[i].MBBI;
240     }
241   }
242
243   bool BaseKill = Loc->findRegisterUseOperandIdx(Base, true) != -1;
244   if (MergeOps(MBB, ++Loc, SOffset, Base, BaseKill, Opcode, Pred, PredReg,
245                Scratch, dl, Regs)) {
246     Merges.push_back(prior(Loc));
247     for (unsigned i = SIndex, e = MemOps.size(); i != e; ++i) {
248       MBB.erase(MemOps[i].MBBI);
249       MemOps[i].Merged = true;
250     }
251   }
252
253   return;
254 }
255
256 /// getInstrPredicate - If instruction is predicated, returns its predicate
257 /// condition, otherwise returns AL. It also returns the condition code
258 /// register by reference.
259 static ARMCC::CondCodes getInstrPredicate(MachineInstr *MI, unsigned &PredReg) {
260   int PIdx = MI->findFirstPredOperandIdx();
261   if (PIdx == -1) {
262     PredReg = 0;
263     return ARMCC::AL;
264   }
265
266   PredReg = MI->getOperand(PIdx+1).getReg();
267   return (ARMCC::CondCodes)MI->getOperand(PIdx).getImm();
268 }
269
270 static inline bool isMatchingDecrement(MachineInstr *MI, unsigned Base,
271                                        unsigned Bytes, ARMCC::CondCodes Pred,
272                                        unsigned PredReg) {
273   unsigned MyPredReg = 0;
274   return (MI && MI->getOpcode() == ARM::SUBri &&
275           MI->getOperand(0).getReg() == Base &&
276           MI->getOperand(1).getReg() == Base &&
277           ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes &&
278           getInstrPredicate(MI, MyPredReg) == Pred &&
279           MyPredReg == PredReg);
280 }
281
282 static inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base,
283                                        unsigned Bytes, ARMCC::CondCodes Pred,
284                                        unsigned PredReg) {
285   unsigned MyPredReg = 0;
286   return (MI && MI->getOpcode() == ARM::ADDri &&
287           MI->getOperand(0).getReg() == Base &&
288           MI->getOperand(1).getReg() == Base &&
289           ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes &&
290           getInstrPredicate(MI, MyPredReg) == Pred &&
291           MyPredReg == PredReg);
292 }
293
294 static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) {
295   switch (MI->getOpcode()) {
296   default: return 0;
297   case ARM::LDR:
298   case ARM::STR:
299   case ARM::FLDS:
300   case ARM::FSTS:
301     return 4;
302   case ARM::FLDD:
303   case ARM::FSTD:
304     return 8;
305   case ARM::LDM:
306   case ARM::STM:
307     return (MI->getNumOperands() - 4) * 4;
308   case ARM::FLDMS:
309   case ARM::FSTMS:
310   case ARM::FLDMD:
311   case ARM::FSTMD:
312     return ARM_AM::getAM5Offset(MI->getOperand(1).getImm()) * 4;
313   }
314 }
315
316 /// mergeBaseUpdateLSMultiple - Fold proceeding/trailing inc/dec of base
317 /// register into the LDM/STM/FLDM{D|S}/FSTM{D|S} op when possible:
318 ///
319 /// stmia rn, <ra, rb, rc>
320 /// rn := rn + 4 * 3;
321 /// =>
322 /// stmia rn!, <ra, rb, rc>
323 ///
324 /// rn := rn - 4 * 3;
325 /// ldmia rn, <ra, rb, rc>
326 /// =>
327 /// ldmdb rn!, <ra, rb, rc>
328 static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
329                                       MachineBasicBlock::iterator MBBI,
330                                       bool &Advance,
331                                       MachineBasicBlock::iterator &I) {
332   MachineInstr *MI = MBBI;
333   unsigned Base = MI->getOperand(0).getReg();
334   unsigned Bytes = getLSMultipleTransferSize(MI);
335   unsigned PredReg = 0;
336   ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
337   int Opcode = MI->getOpcode();
338   bool isAM4 = Opcode == ARM::LDM || Opcode == ARM::STM;
339
340   if (isAM4) {
341     if (ARM_AM::getAM4WBFlag(MI->getOperand(1).getImm()))
342       return false;
343
344     // Can't use the updating AM4 sub-mode if the base register is also a dest
345     // register. e.g. ldmdb r0!, {r0, r1, r2}. The behavior is undefined.
346     for (unsigned i = 3, e = MI->getNumOperands(); i != e; ++i) {
347       if (MI->getOperand(i).getReg() == Base)
348         return false;
349     }
350
351     ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(1).getImm());
352     if (MBBI != MBB.begin()) {
353       MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
354       if (Mode == ARM_AM::ia &&
355           isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) {
356         MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::db, true));
357         MBB.erase(PrevMBBI);
358         return true;
359       } else if (Mode == ARM_AM::ib &&
360                  isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) {
361         MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::da, true));
362         MBB.erase(PrevMBBI);
363         return true;
364       }
365     }
366
367     if (MBBI != MBB.end()) {
368       MachineBasicBlock::iterator NextMBBI = next(MBBI);
369       if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) &&
370           isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg)) {
371         MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
372         if (NextMBBI == I) {
373           Advance = true;
374           ++I;
375         }
376         MBB.erase(NextMBBI);
377         return true;
378       } else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) &&
379                  isMatchingDecrement(NextMBBI, Base, Bytes, Pred, PredReg)) {
380         MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
381         if (NextMBBI == I) {
382           Advance = true;
383           ++I;
384         }
385         MBB.erase(NextMBBI);
386         return true;
387       }
388     }
389   } else {
390     // FLDM{D|S}, FSTM{D|S} addressing mode 5 ops.
391     if (ARM_AM::getAM5WBFlag(MI->getOperand(1).getImm()))
392       return false;
393
394     ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MI->getOperand(1).getImm());
395     unsigned Offset = ARM_AM::getAM5Offset(MI->getOperand(1).getImm());
396     if (MBBI != MBB.begin()) {
397       MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
398       if (Mode == ARM_AM::ia &&
399           isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) {
400         MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::db, true, Offset));
401         MBB.erase(PrevMBBI);
402         return true;
403       }
404     }
405
406     if (MBBI != MBB.end()) {
407       MachineBasicBlock::iterator NextMBBI = next(MBBI);
408       if (Mode == ARM_AM::ia &&
409           isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg)) {
410         MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::ia, true, Offset));
411         if (NextMBBI == I) {
412           Advance = true;
413           ++I;
414         }
415         MBB.erase(NextMBBI);
416       }
417       return true;
418     }
419   }
420
421   return false;
422 }
423
424 static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) {
425   switch (Opc) {
426   case ARM::LDR: return ARM::LDR_PRE;
427   case ARM::STR: return ARM::STR_PRE;
428   case ARM::FLDS: return ARM::FLDMS;
429   case ARM::FLDD: return ARM::FLDMD;
430   case ARM::FSTS: return ARM::FSTMS;
431   case ARM::FSTD: return ARM::FSTMD;
432   default: abort();
433   }
434   return 0;
435 }
436
437 static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc) {
438   switch (Opc) {
439   case ARM::LDR: return ARM::LDR_POST;
440   case ARM::STR: return ARM::STR_POST;
441   case ARM::FLDS: return ARM::FLDMS;
442   case ARM::FLDD: return ARM::FLDMD;
443   case ARM::FSTS: return ARM::FSTMS;
444   case ARM::FSTD: return ARM::FSTMD;
445   default: abort();
446   }
447   return 0;
448 }
449
450 /// mergeBaseUpdateLoadStore - Fold proceeding/trailing inc/dec of base
451 /// register into the LDR/STR/FLD{D|S}/FST{D|S} op when possible:
452 static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
453                                      MachineBasicBlock::iterator MBBI,
454                                      const TargetInstrInfo *TII,
455                                      bool &Advance,
456                                      MachineBasicBlock::iterator &I) {
457   MachineInstr *MI = MBBI;
458   unsigned Base = MI->getOperand(1).getReg();
459   bool BaseKill = MI->getOperand(1).isKill();
460   unsigned Bytes = getLSMultipleTransferSize(MI);
461   int Opcode = MI->getOpcode();
462   DebugLoc dl = MI->getDebugLoc();
463   bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
464   if ((isAM2 && ARM_AM::getAM2Offset(MI->getOperand(3).getImm()) != 0) ||
465       (!isAM2 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0))
466     return false;
467
468   bool isLd = Opcode == ARM::LDR || Opcode == ARM::FLDS || Opcode == ARM::FLDD;
469   // Can't do the merge if the destination register is the same as the would-be
470   // writeback register.
471   if (isLd && MI->getOperand(0).getReg() == Base)
472     return false;
473
474   unsigned PredReg = 0;
475   ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
476   bool DoMerge = false;
477   ARM_AM::AddrOpc AddSub = ARM_AM::add;
478   unsigned NewOpc = 0;
479   if (MBBI != MBB.begin()) {
480     MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
481     if (isMatchingDecrement(PrevMBBI, Base, Bytes, Pred, PredReg)) {
482       DoMerge = true;
483       AddSub = ARM_AM::sub;
484       NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
485     } else if (isAM2 && isMatchingIncrement(PrevMBBI, Base, Bytes,
486                                             Pred, PredReg)) {
487       DoMerge = true;
488       NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
489     }
490     if (DoMerge)
491       MBB.erase(PrevMBBI);
492   }
493
494   if (!DoMerge && MBBI != MBB.end()) {
495     MachineBasicBlock::iterator NextMBBI = next(MBBI);
496     if (isAM2 && isMatchingDecrement(NextMBBI, Base, Bytes, Pred, PredReg)) {
497       DoMerge = true;
498       AddSub = ARM_AM::sub;
499       NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
500     } else if (isMatchingIncrement(NextMBBI, Base, Bytes, Pred, PredReg)) {
501       DoMerge = true;
502       NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
503     }
504     if (DoMerge) {
505       if (NextMBBI == I) {
506         Advance = true;
507         ++I;
508       }
509       MBB.erase(NextMBBI);
510     }
511   }
512
513   if (!DoMerge)
514     return false;
515
516   bool isDPR = NewOpc == ARM::FLDMD || NewOpc == ARM::FSTMD;
517   unsigned Offset = isAM2 ? ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift)
518     : ARM_AM::getAM5Opc((AddSub == ARM_AM::sub) ? ARM_AM::db : ARM_AM::ia,
519                         true, isDPR ? 2 : 1);
520   if (isLd) {
521     if (isAM2)
522       // LDR_PRE, LDR_POST;
523       BuildMI(MBB, MBBI, dl, TII->get(NewOpc), MI->getOperand(0).getReg())
524         .addReg(Base, RegState::Define)
525         .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
526     else
527       // FLDMS, FLDMD
528       BuildMI(MBB, MBBI, dl, TII->get(NewOpc))
529         .addReg(Base, getKillRegState(BaseKill))
530         .addImm(Offset).addImm(Pred).addReg(PredReg)
531         .addReg(MI->getOperand(0).getReg(), RegState::Define);
532   } else {
533     MachineOperand &MO = MI->getOperand(0);
534     if (isAM2)
535       // STR_PRE, STR_POST;
536       BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base)
537         .addReg(MO.getReg(), getKillRegState(MO.isKill()))
538         .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
539     else
540       // FSTMS, FSTMD
541       BuildMI(MBB, MBBI, dl, TII->get(NewOpc)).addReg(Base).addImm(Offset)
542         .addImm(Pred).addReg(PredReg)
543         .addReg(MO.getReg(), getKillRegState(MO.isKill()));
544   }
545   MBB.erase(MBBI);
546
547   return true;
548 }
549
550 /// isMemoryOp - Returns true if instruction is a memory operations (that this
551 /// pass is capable of operating on).
552 static bool isMemoryOp(MachineInstr *MI) {
553   int Opcode = MI->getOpcode();
554   switch (Opcode) {
555   default: break;
556   case ARM::LDR:
557   case ARM::STR:
558     return MI->getOperand(1).isReg() && MI->getOperand(2).getReg() == 0;
559   case ARM::FLDS:
560   case ARM::FSTS:
561     return MI->getOperand(1).isReg();
562   case ARM::FLDD:
563   case ARM::FSTD:
564     return MI->getOperand(1).isReg();
565   }
566   return false;
567 }
568
569 /// AdvanceRS - Advance register scavenger to just before the earliest memory
570 /// op that is being merged.
571 void ARMLoadStoreOpt::AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps) {
572   MachineBasicBlock::iterator Loc = MemOps[0].MBBI;
573   unsigned Position = MemOps[0].Position;
574   for (unsigned i = 1, e = MemOps.size(); i != e; ++i) {
575     if (MemOps[i].Position < Position) {
576       Position = MemOps[i].Position;
577       Loc = MemOps[i].MBBI;
578     }
579   }
580
581   if (Loc != MBB.begin())
582     RS->forward(prior(Loc));
583 }
584
585 /// LoadStoreMultipleOpti - An optimization pass to turn multiple LDR / STR
586 /// ops of the same base and incrementing offset into LDM / STM ops.
587 bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
588   unsigned NumMerges = 0;
589   unsigned NumMemOps = 0;
590   MemOpQueue MemOps;
591   unsigned CurrBase = 0;
592   int CurrOpc = -1;
593   unsigned CurrSize = 0;
594   ARMCC::CondCodes CurrPred = ARMCC::AL;
595   unsigned CurrPredReg = 0;
596   unsigned Position = 0;
597   SmallVector<MachineBasicBlock::iterator,4> Merges;
598
599   RS->enterBasicBlock(&MBB);
600   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
601   while (MBBI != E) {
602     bool Advance  = false;
603     bool TryMerge = false;
604     bool Clobber  = false;
605
606     bool isMemOp = isMemoryOp(MBBI);
607     if (isMemOp) {
608       int Opcode = MBBI->getOpcode();
609       bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
610       unsigned Size = getLSMultipleTransferSize(MBBI);
611       unsigned Base = MBBI->getOperand(1).getReg();
612       unsigned PredReg = 0;
613       ARMCC::CondCodes Pred = getInstrPredicate(MBBI, PredReg);
614       unsigned NumOperands = MBBI->getDesc().getNumOperands();
615       unsigned OffField = MBBI->getOperand(NumOperands-3).getImm();
616       int Offset = isAM2
617         ? ARM_AM::getAM2Offset(OffField) : ARM_AM::getAM5Offset(OffField) * 4;
618       if (isAM2) {
619         if (ARM_AM::getAM2Op(OffField) == ARM_AM::sub)
620           Offset = -Offset;
621       } else {
622         if (ARM_AM::getAM5Op(OffField) == ARM_AM::sub)
623           Offset = -Offset;
624       }
625       // Watch out for:
626       // r4 := ldr [r5]
627       // r5 := ldr [r5, #4]
628       // r6 := ldr [r5, #8]
629       //
630       // The second ldr has effectively broken the chain even though it
631       // looks like the later ldr(s) use the same base register. Try to
632       // merge the ldr's so far, including this one. But don't try to
633       // combine the following ldr(s).
634       Clobber = (Opcode == ARM::LDR && Base == MBBI->getOperand(0).getReg());
635       if (CurrBase == 0 && !Clobber) {
636         // Start of a new chain.
637         CurrBase = Base;
638         CurrOpc  = Opcode;
639         CurrSize = Size;
640         CurrPred = Pred;
641         CurrPredReg = PredReg;
642         MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI));
643         NumMemOps++;
644         Advance = true;
645       } else {
646         if (Clobber) {
647           TryMerge = true;
648           Advance = true;
649         }
650
651         if (CurrOpc == Opcode && CurrBase == Base && CurrPred == Pred) {
652           // No need to match PredReg.
653           // Continue adding to the queue.
654           if (Offset > MemOps.back().Offset) {
655             MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI));
656             NumMemOps++;
657             Advance = true;
658           } else {
659             for (MemOpQueueIter I = MemOps.begin(), E = MemOps.end();
660                  I != E; ++I) {
661               if (Offset < I->Offset) {
662                 MemOps.insert(I, MemOpQueueEntry(Offset, Position, MBBI));
663                 NumMemOps++;
664                 Advance = true;
665                 break;
666               } else if (Offset == I->Offset) {
667                 // Collision! This can't be merged!
668                 break;
669               }
670             }
671           }
672         }
673       }
674     }
675
676     if (Advance) {
677       ++Position;
678       ++MBBI;
679     } else
680       TryMerge = true;
681
682     if (TryMerge) {
683       if (NumMemOps > 1) {
684         // Try to find a free register to use as a new base in case it's needed.
685         // First advance to the instruction just before the start of the chain.
686         AdvanceRS(MBB, MemOps);
687         // Find a scratch register. Make sure it's a call clobbered register or
688         // a spilled callee-saved register.
689         unsigned Scratch = RS->FindUnusedReg(&ARM::GPRRegClass, true);
690         if (!Scratch)
691           Scratch = RS->FindUnusedReg(&ARM::GPRRegClass,
692                                       AFI->getSpilledCSRegisters());
693         // Process the load / store instructions.
694         RS->forward(prior(MBBI));
695
696         // Merge ops.
697         Merges.clear();
698         MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize,
699                      CurrPred, CurrPredReg, Scratch, MemOps, Merges);
700
701         // Try folding preceeding/trailing base inc/dec into the generated
702         // LDM/STM ops.
703         for (unsigned i = 0, e = Merges.size(); i < e; ++i)
704           if (mergeBaseUpdateLSMultiple(MBB, Merges[i], Advance, MBBI))
705             ++NumMerges;
706         NumMerges += Merges.size();
707
708         // Try folding preceeding/trailing base inc/dec into those load/store
709         // that were not merged to form LDM/STM ops.
710         for (unsigned i = 0; i != NumMemOps; ++i)
711           if (!MemOps[i].Merged)
712             if (mergeBaseUpdateLoadStore(MBB, MemOps[i].MBBI, TII,Advance,MBBI))
713               ++NumMerges;
714
715         // RS may be pointing to an instruction that's deleted. 
716         RS->skipTo(prior(MBBI));
717       } else if (NumMemOps == 1) {
718         // Try folding preceeding/trailing base inc/dec into the single
719         // load/store.
720         if (mergeBaseUpdateLoadStore(MBB, MemOps[0].MBBI, TII, Advance, MBBI)) {
721           ++NumMerges;
722           RS->forward(prior(MBBI));
723         }
724       }
725
726       CurrBase = 0;
727       CurrOpc = -1;
728       CurrSize = 0;
729       CurrPred = ARMCC::AL;
730       CurrPredReg = 0;
731       if (NumMemOps) {
732         MemOps.clear();
733         NumMemOps = 0;
734       }
735
736       // If iterator hasn't been advanced and this is not a memory op, skip it.
737       // It can't start a new chain anyway.
738       if (!Advance && !isMemOp && MBBI != E) {
739         ++Position;
740         ++MBBI;
741       }
742     }
743   }
744   return NumMerges > 0;
745 }
746
747 /// MergeReturnIntoLDM - If this is a exit BB, try merging the return op
748 /// (bx lr) into the preceeding stack restore so it directly restore the value
749 /// of LR into pc.
750 ///   ldmfd sp!, {r7, lr}
751 ///   bx lr
752 /// =>
753 ///   ldmfd sp!, {r7, pc}
754 bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) {
755   if (MBB.empty()) return false;
756
757   MachineBasicBlock::iterator MBBI = prior(MBB.end());
758   if (MBBI->getOpcode() == ARM::BX_RET && MBBI != MBB.begin()) {
759     MachineInstr *PrevMI = prior(MBBI);
760     if (PrevMI->getOpcode() == ARM::LDM) {
761       MachineOperand &MO = PrevMI->getOperand(PrevMI->getNumOperands()-1);
762       if (MO.getReg() == ARM::LR) {
763         PrevMI->setDesc(TII->get(ARM::LDM_RET));
764         MO.setReg(ARM::PC);
765         MBB.erase(MBBI);
766         return true;
767       }
768     }
769   }
770   return false;
771 }
772
773 bool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
774   const TargetMachine &TM = Fn.getTarget();
775   AFI = Fn.getInfo<ARMFunctionInfo>();
776   TII = TM.getInstrInfo();
777   TRI = TM.getRegisterInfo();
778   RS = new RegScavenger();
779
780   bool Modified = false;
781   for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
782        ++MFI) {
783     MachineBasicBlock &MBB = *MFI;
784     Modified |= LoadStoreMultipleOpti(MBB);
785     Modified |= MergeReturnIntoLDM(MBB);
786   }
787
788   delete RS;
789   return Modified;
790 }