This is done.
[oota-llvm.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 was developed by Evan Cheng and is distributed under the
6 // University of Illinois Open Source 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 "ARMRegisterInfo.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/Statistic.h"
22 #include "llvm/CodeGen/MachineBasicBlock.h"
23 #include "llvm/CodeGen/MachineFunctionPass.h"
24 #include "llvm/CodeGen/MachineInstr.h"
25 #include "llvm/CodeGen/MachineInstrBuilder.h"
26 #include "llvm/Support/Compiler.h"
27 #include "llvm/Target/TargetInstrInfo.h"
28 #include "llvm/Target/TargetMachine.h"
29 using namespace llvm;
30
31 STATISTIC(NumLDMGened , "Number of ldm instructions generated");
32 STATISTIC(NumSTMGened , "Number of stm instructions generated");
33 STATISTIC(NumFLDMGened, "Number of fldm instructions generated");
34 STATISTIC(NumFSTMGened, "Number of fstm instructions generated");
35
36 namespace {
37   struct VISIBILITY_HIDDEN ARMLoadStoreOpt : public MachineFunctionPass {
38     const TargetInstrInfo *TII;
39
40     virtual bool runOnMachineFunction(MachineFunction &Fn);
41
42     virtual const char *getPassName() const {
43       return "ARM load / store optimization pass";
44     }
45
46   private:
47     struct MemOpQueueEntry {
48       int Offset;
49       unsigned Position;
50       MachineBasicBlock::iterator MBBI;
51       bool Merged;
52       MemOpQueueEntry(int o, int p, MachineBasicBlock::iterator i)
53         : Offset(o), Position(p), MBBI(i), Merged(false) {};
54     };
55     typedef SmallVector<MemOpQueueEntry,8> MemOpQueue;
56     typedef MemOpQueue::iterator MemOpQueueIter;
57
58     SmallVector<MachineBasicBlock::iterator, 4>
59     MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base,
60                  int Opcode, unsigned Size, MemOpQueue &MemOps);
61
62     bool LoadStoreMultipleOpti(MachineBasicBlock &MBB);
63     bool MergeReturnIntoLDM(MachineBasicBlock &MBB);
64   };
65 }
66
67 /// createARMLoadStoreOptimizationPass - returns an instance of the load / store
68 /// optimization pass.
69 FunctionPass *llvm::createARMLoadStoreOptimizationPass() {
70   return new ARMLoadStoreOpt();
71 }
72
73 static int getLoadStoreMultipleOpcode(int Opcode) {
74   switch (Opcode) {
75   case ARM::LDR:
76     NumLDMGened++;
77     return ARM::LDM;
78   case ARM::STR:
79     NumSTMGened++;
80     return ARM::STM;
81   case ARM::FLDS:
82     NumFLDMGened++;
83     return ARM::FLDMS;
84   case ARM::FSTS:
85     NumFSTMGened++;
86     return ARM::FSTMS;
87   case ARM::FLDD:
88     NumFLDMGened++;
89     return ARM::FLDMD;
90   case ARM::FSTD:
91     NumFSTMGened++;
92     return ARM::FSTMD;
93   default: abort();
94   }
95   return 0;
96 }
97
98 /// mergeOps - Create and insert a LDM or STM with Base as base register and
99 /// registers in Regs as the register operands that would be loaded / stored.
100 /// It returns true if the transformation is done. 
101 static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
102                      int Offset, unsigned Base, int Opcode,
103                      SmallVector<unsigned, 8> &Regs,
104                      const TargetInstrInfo *TII) {
105   // Only a single register to load / store. Don't bother.
106   unsigned NumRegs = Regs.size();
107   if (NumRegs <= 1)
108     return false;
109
110   ARM_AM::AMSubMode Mode = ARM_AM::ia;
111   bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
112   if (isAM4 && Offset == 4)
113     Mode = ARM_AM::ib;
114   else if (isAM4 && Offset == -4 * (int)NumRegs + 4)
115     Mode = ARM_AM::da;
116   else if (isAM4 && Offset == -4 * (int)NumRegs)
117     Mode = ARM_AM::db;
118   else if (Offset != 0) {
119     // If starting offset isn't zero, insert a MI to materialize a new base.
120     // But only do so if it is cost effective, i.e. merging more than two
121     // loads / stores.
122     if (NumRegs <= 2)
123       return false;
124
125     unsigned NewBase;
126     if (Opcode == ARM::LDR)
127       // If it is a load, then just use one of the destination register to
128       // use as the new base.
129       NewBase = Regs[NumRegs-1];
130     else {
131       // FIXME: Try scavenging a register to use as a new base.
132       NewBase = ARM::R12;
133     }
134     int BaseOpc = ARM::ADDri;
135     if (Offset < 0) {
136       BaseOpc = ARM::SUBri;
137       Offset = - Offset;
138     }
139     int ImmedOffset = ARM_AM::getSOImmVal(Offset);
140     if (ImmedOffset == -1)
141       return false;  // Probably not worth it then.
142     BuildMI(MBB, MBBI, TII->get(BaseOpc), NewBase).addReg(Base).addImm(ImmedOffset);
143     Base = NewBase;
144   }
145
146   bool isDPR = Opcode == ARM::FLDD || Opcode == ARM::FSTD;
147   bool isDef = Opcode == ARM::LDR || Opcode == ARM::FLDS || Opcode == ARM::FLDD;
148   Opcode = getLoadStoreMultipleOpcode(Opcode);
149   MachineInstrBuilder MIB = (isAM4)
150     ? BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base)
151         .addImm(ARM_AM::getAM4ModeImm(Mode))
152     : BuildMI(MBB, MBBI, TII->get(Opcode)).addReg(Base)
153         .addImm(ARM_AM::getAM5Opc(Mode, false, isDPR ? NumRegs<<1 : NumRegs));
154   for (unsigned i = 0; i != NumRegs; ++i)
155     MIB = MIB.addReg(Regs[i], Opcode == isDef);
156
157   return true;
158 }
159
160 SmallVector<MachineBasicBlock::iterator, 4>
161 ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB,
162                               unsigned SIndex, unsigned Base, int Opcode,
163                               unsigned Size, MemOpQueue &MemOps) {
164   bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
165   SmallVector<MachineBasicBlock::iterator, 4> Merges;
166   int Offset = MemOps[SIndex].Offset;
167   int SOffset = Offset;
168   unsigned Pos = MemOps[SIndex].Position;
169   MachineBasicBlock::iterator Loc = MemOps[SIndex].MBBI;
170   SmallVector<unsigned, 8> Regs;
171   unsigned PReg = MemOps[SIndex].MBBI->getOperand(0).getReg();
172   unsigned PRegNum = ARMRegisterInfo::getRegisterNumbering(PReg);
173   Regs.push_back(PReg);
174   for (unsigned i = SIndex+1, e = MemOps.size(); i != e; ++i) {
175     int NewOffset = MemOps[i].Offset;
176     unsigned Reg = MemOps[i].MBBI->getOperand(0).getReg();
177     unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
178     // AM4 - register numbers in ascending order.
179     // AM5 - consecutive register numbers in ascending order.
180     if (NewOffset == Offset + (int)Size &&
181         ((isAM4 && RegNum > PRegNum) || RegNum == PRegNum+1)) {
182       Offset += Size;
183       Regs.push_back(Reg);
184       PRegNum = RegNum;
185     } else {
186       // Can't merge this in. Try merge the earlier ones first.
187       if (mergeOps(MBB, ++Loc, SOffset, Base, Opcode, Regs, TII)) {
188         Merges.push_back(prior(Loc));
189         for (unsigned j = SIndex; j < i; ++j) {
190           MBB.erase(MemOps[j].MBBI);
191           MemOps[j].Merged = true;
192         }
193       }
194       SmallVector<MachineBasicBlock::iterator, 4> Merges2 =
195         MergeLDR_STR(MBB, i, Base, Opcode, Size, MemOps);
196       Merges.append(Merges2.begin(), Merges2.end());
197       return Merges;
198     }
199
200     if (MemOps[i].Position > Pos) {
201       Pos = MemOps[i].Position;
202       Loc = MemOps[i].MBBI;
203     }
204   }
205
206   if (mergeOps(MBB, ++Loc, SOffset, Base, Opcode, Regs, TII)) {
207     Merges.push_back(prior(Loc));
208     for (unsigned i = SIndex, e = MemOps.size(); i != e; ++i) {
209       MBB.erase(MemOps[i].MBBI);
210       MemOps[i].Merged = true;
211     }
212   }
213
214   return Merges;
215 }
216
217 static inline bool isMatchingDecrement(MachineInstr *MI, unsigned Base,
218                                        unsigned Bytes) {
219   return (MI && MI->getOpcode() == ARM::SUBri &&
220           MI->getOperand(0).getReg() == Base &&
221           MI->getOperand(1).getReg() == Base &&
222           ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes);
223 }
224
225 static inline bool isMatchingIncrement(MachineInstr *MI, unsigned Base,
226                                        unsigned Bytes) {
227   return (MI && MI->getOpcode() == ARM::ADDri &&
228           MI->getOperand(0).getReg() == Base &&
229           MI->getOperand(1).getReg() == Base &&
230           ARM_AM::getAM2Offset(MI->getOperand(2).getImm()) == Bytes);
231 }
232
233 static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) {
234   switch (MI->getOpcode()) {
235   default: return 0;
236   case ARM::LDR:
237   case ARM::STR:
238   case ARM::FLDS:
239   case ARM::FSTS:
240     return 4;
241   case ARM::FLDD:
242   case ARM::FSTD:
243     return 8;
244   case ARM::LDM:
245   case ARM::STM:
246     return (MI->getNumOperands() - 2) * 4;
247   case ARM::FLDMS:
248   case ARM::FSTMS:
249   case ARM::FLDMD:
250   case ARM::FSTMD:
251     return ARM_AM::getAM5Offset(MI->getOperand(1).getImm()) * 4;
252   }
253 }
254
255 /// mergeBaseUpdateLSMultiple - Fold proceeding/trailing inc/dec of base
256 /// register into the LDM/STM/FLDM{D|S}/FSTM{D|S} op when possible:
257 ///
258 /// stmia rn, <ra, rb, rc>
259 /// rn := rn + 4 * 3;
260 /// =>
261 /// stmia rn!, <ra, rb, rc>
262 ///
263 /// rn := rn - 4 * 3;
264 /// ldmia rn, <ra, rb, rc>
265 /// =>
266 /// ldmdb rn!, <ra, rb, rc>
267 static bool mergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
268                                       MachineBasicBlock::iterator MBBI) {
269   MachineInstr *MI = MBBI;
270   unsigned Base = MI->getOperand(0).getReg();
271   unsigned Bytes = getLSMultipleTransferSize(MI);
272   int Opcode = MI->getOpcode();
273   bool isAM4 = Opcode == ARM::LDM || Opcode == ARM::STM;
274
275   if (isAM4) {
276     if (ARM_AM::getAM4WBFlag(MI->getOperand(1).getImm()))
277       return false;
278
279     // Can't use the updating AM4 sub-mode if the base register is also a dest
280     // register. e.g. ldmdb r0!, {r0, r1, r2}. The behavior is undefined.
281     for (unsigned i = 2, e = MI->getNumOperands(); i != e; ++i) {
282       if (MI->getOperand(i).getReg() == Base)
283         return false;
284     }
285
286     ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(1).getImm());
287     if (MBBI != MBB.begin()) {
288       MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
289       if (Mode == ARM_AM::ia &&
290           isMatchingDecrement(PrevMBBI, Base, Bytes)) {
291         MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::db, true));
292         MBB.erase(PrevMBBI);
293         return true;
294       } else if (Mode == ARM_AM::ib &&
295                  isMatchingDecrement(PrevMBBI, Base, Bytes)) {
296         MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(ARM_AM::da, true));
297         MBB.erase(PrevMBBI);
298         return true;
299       }
300     }
301
302     if (MBBI != MBB.end()) {
303       MachineBasicBlock::iterator NextMBBI = next(MBBI);
304       if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) &&
305           isMatchingIncrement(NextMBBI, Base, Bytes)) {
306         MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
307         MBB.erase(NextMBBI);
308         return true;
309       } else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) &&
310                  isMatchingDecrement(NextMBBI, Base, Bytes)) {
311         MI->getOperand(1).setImm(ARM_AM::getAM4ModeImm(Mode, true));
312         MBB.erase(NextMBBI);
313         return true;
314       }
315     }
316   } else {
317     // FLDM{D|S}, FSTM{D|S} addressing mode 5 ops.
318     if (ARM_AM::getAM5WBFlag(MI->getOperand(1).getImm()))
319       return false;
320
321     ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MI->getOperand(1).getImm());
322     unsigned Offset = ARM_AM::getAM5Offset(MI->getOperand(1).getImm());
323     if (MBBI != MBB.begin()) {
324       MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
325       if (Mode == ARM_AM::ia &&
326           isMatchingDecrement(PrevMBBI, Base, Bytes)) {
327         MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::db, true, Offset));
328         MBB.erase(PrevMBBI);
329         return true;
330       }
331     }
332
333     if (MBBI != MBB.end()) {
334       MachineBasicBlock::iterator NextMBBI = next(MBBI);
335       if (Mode == ARM_AM::ia &&
336           isMatchingIncrement(NextMBBI, Base, Bytes)) {
337         MI->getOperand(1).setImm(ARM_AM::getAM5Opc(ARM_AM::ia, true, Offset));
338         MBB.erase(NextMBBI);
339       }
340       return true;
341     }
342   }
343
344   return false;
345 }
346
347 static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) {
348   switch (Opc) {
349   case ARM::LDR: return ARM::LDR_PRE;
350   case ARM::STR: return ARM::STR_PRE;
351   case ARM::FLDS: return ARM::FLDMS;
352   case ARM::FLDD: return ARM::FLDMD;
353   case ARM::FSTS: return ARM::FSTMS;
354   case ARM::FSTD: return ARM::FSTMD;
355   default: abort();
356   }
357   return 0;
358 }
359
360 static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc) {
361   switch (Opc) {
362   case ARM::LDR: return ARM::LDR_POST;
363   case ARM::STR: return ARM::STR_POST;
364   case ARM::FLDS: return ARM::FLDMS;
365   case ARM::FLDD: return ARM::FLDMD;
366   case ARM::FSTS: return ARM::FSTMS;
367   case ARM::FSTD: return ARM::FSTMD;
368   default: abort();
369   }
370   return 0;
371 }
372
373 /// mergeBaseUpdateLoadStore - Fold proceeding/trailing inc/dec of base
374 /// register into the LDR/STR/FLD{D|S}/FST{D|S} op when possible:
375 static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
376                                      MachineBasicBlock::iterator MBBI,
377                                      const TargetInstrInfo *TII) {
378   MachineInstr *MI = MBBI;
379   unsigned Base = MI->getOperand(1).getReg();
380   unsigned Bytes = getLSMultipleTransferSize(MI);
381   int Opcode = MI->getOpcode();
382   bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
383   if ((isAM2 && ARM_AM::getAM2Offset(MI->getOperand(3).getImm()) != 0) ||
384       (!isAM2 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0))
385     return false;
386
387   bool isLd = Opcode == ARM::LDR || Opcode == ARM::FLDS || Opcode == ARM::FLDD;
388   // Can't do the merge if the destination register is the same as the would-be
389   // writeback register.
390   if (isLd && MI->getOperand(0).getReg() == Base)
391     return false;
392
393   bool DoMerge = false;
394   ARM_AM::AddrOpc AddSub = ARM_AM::add;
395   unsigned NewOpc = 0;
396   if (MBBI != MBB.begin()) {
397     MachineBasicBlock::iterator PrevMBBI = prior(MBBI);
398     if (isMatchingDecrement(PrevMBBI, Base, Bytes)) {
399       DoMerge = true;
400       AddSub = ARM_AM::sub;
401       NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
402     } else if (isAM2 && isMatchingIncrement(PrevMBBI, Base, Bytes)) {
403       DoMerge = true;
404       NewOpc = getPreIndexedLoadStoreOpcode(Opcode);
405     }
406     if (DoMerge)
407       MBB.erase(PrevMBBI);
408   }
409
410   if (!DoMerge && MBBI != MBB.end()) {
411     MachineBasicBlock::iterator NextMBBI = next(MBBI);
412     if (isAM2 && isMatchingDecrement(NextMBBI, Base, Bytes)) {
413       DoMerge = true;
414       AddSub = ARM_AM::sub;
415       NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
416     } else if (isMatchingIncrement(NextMBBI, Base, Bytes)) {
417       DoMerge = true;
418       NewOpc = getPostIndexedLoadStoreOpcode(Opcode);
419     }
420     if (DoMerge)
421       MBB.erase(NextMBBI);
422   }
423
424   if (!DoMerge)
425     return false;
426
427   bool isDPR = NewOpc == ARM::FLDMD || NewOpc == ARM::FSTMD;
428   unsigned Offset = isAM2 ? ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift)
429     : ARM_AM::getAM5Opc((AddSub == ARM_AM::sub) ? ARM_AM::db : ARM_AM::ia,
430                         true, isDPR ? 2 : 1);
431   if (isLd) {
432     if (isAM2)
433       BuildMI(MBB, MBBI, TII->get(NewOpc), MI->getOperand(0).getReg())
434         .addReg(Base, true).addReg(Base).addReg(0).addImm(Offset);
435     else
436       BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base)
437         .addImm(Offset).addReg(MI->getOperand(0).getReg(), true);
438   } else {
439     if (isAM2)
440       BuildMI(MBB, MBBI, TII->get(NewOpc), Base).addReg(MI->getOperand(0).getReg())
441         .addReg(Base).addReg(0).addImm(Offset);
442     else
443       BuildMI(MBB, MBBI, TII->get(NewOpc)).addReg(Base)
444         .addImm(Offset).addReg(MI->getOperand(0).getReg(), false);
445   }
446   MBB.erase(MBBI);
447
448   return true;
449 }
450
451 /// LoadStoreMultipleOpti - An optimization pass to turn multiple LDR / STR
452 /// ops of the same base and incrementing offset into LDM / STM ops.
453 bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
454   unsigned NumMerges = 0;
455   unsigned NumMemOps = 0;
456   MemOpQueue MemOps;
457   unsigned CurrBase = 0;
458   int CurrOpc = -1;
459   unsigned CurrSize = 0;
460   unsigned Position = 0;
461   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
462   while (MBBI != E) {
463     bool Advance  = false;
464     bool TryMerge = false;
465     bool Clobber  = false;
466
467     int Opcode = MBBI->getOpcode();
468     bool isMemOp = false;
469     bool isAM2 = false;
470     unsigned Size = 4;
471     switch (Opcode) {
472     case ARM::LDR:
473     case ARM::STR:
474       isMemOp =
475         (MBBI->getOperand(1).isRegister() && MBBI->getOperand(2).getReg() == 0);
476       isAM2 = true;
477       break;
478     case ARM::FLDS:
479     case ARM::FSTS:
480       isMemOp = MBBI->getOperand(1).isRegister();
481       break;
482     case ARM::FLDD:
483     case ARM::FSTD:
484       isMemOp = MBBI->getOperand(1).isRegister();
485       Size = 8;
486       break;
487     }
488     if (isMemOp) {
489       unsigned Base = MBBI->getOperand(1).getReg();
490       unsigned OffIdx = MBBI->getNumOperands()-1;
491       unsigned OffField = MBBI->getOperand(OffIdx).getImm();
492       int Offset = isAM2
493         ? ARM_AM::getAM2Offset(OffField) : ARM_AM::getAM5Offset(OffField) * 4;
494       if (isAM2) {
495         if (ARM_AM::getAM2Op(OffField) == ARM_AM::sub)
496           Offset = -Offset;
497       } else {
498         if (ARM_AM::getAM5Op(OffField) == ARM_AM::sub)
499           Offset = -Offset;
500       }
501       // Watch out for:
502       // r4 := ldr [r5]
503       // r5 := ldr [r5, #4]
504       // r6 := ldr [r5, #8]
505       //
506       // The second ldr has effectively broken the chain even though it
507       // looks like the later ldr(s) use the same base register. Try to
508       // merge the ldr's so far, including this one. But don't try to
509       // combine the following ldr(s).
510       Clobber = (Opcode == ARM::LDR && Base == MBBI->getOperand(0).getReg());
511       if (CurrBase == 0 && !Clobber) {
512         // Start of a new chain.
513         CurrBase = Base;
514         CurrOpc  = Opcode;
515         CurrSize = Size;
516         MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI));
517         NumMemOps++;
518         Advance = true;
519       } else {
520         if (Clobber) {
521           TryMerge = true;
522           Advance = true;
523         }
524
525         if (CurrOpc == Opcode && CurrBase == Base) {
526           // Continue adding to the queue.
527           if (Offset > MemOps.back().Offset) {
528             MemOps.push_back(MemOpQueueEntry(Offset, Position, MBBI));
529             NumMemOps++;
530             Advance = true;
531           } else {
532             for (MemOpQueueIter I = MemOps.begin(), E = MemOps.end();
533                  I != E; ++I) {
534               if (Offset < I->Offset) {
535                 MemOps.insert(I, MemOpQueueEntry(Offset, Position, MBBI));
536                 NumMemOps++;
537                 Advance = true;
538                 break;
539               } else if (Offset == I->Offset) {
540                 // Collision! This can't be merged!
541                 break;
542               }
543             }
544           }
545         }
546       }
547     }
548
549     if (Advance) {
550       ++Position;
551       ++MBBI;
552     } else
553       TryMerge = true;
554
555     if (TryMerge) {
556       if (NumMemOps > 1) {
557         SmallVector<MachineBasicBlock::iterator,4> MBBII =
558           MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize,MemOps);
559         // Try folding preceeding/trailing base inc/dec into the generated
560         // LDM/STM ops.
561         for (unsigned i = 0, e = MBBII.size(); i < e; ++i)
562           if (mergeBaseUpdateLSMultiple(MBB, MBBII[i]))
563             NumMerges++;
564         NumMerges += MBBII.size();
565       }
566
567       // Try folding preceeding/trailing base inc/dec into those load/store
568       // that were not merged to form LDM/STM ops.
569       for (unsigned i = 0; i != NumMemOps; ++i)
570         if (!MemOps[i].Merged)
571           if (mergeBaseUpdateLoadStore(MBB, MemOps[i].MBBI, TII))
572             NumMerges++;
573
574       CurrBase = 0;
575       CurrOpc = -1;
576       if (NumMemOps) {
577         MemOps.clear();
578         NumMemOps = 0;
579       }
580
581       // If iterator hasn't been advanced and this is not a memory op, skip it.
582       // It can't start a new chain anyway.
583       if (!Advance && !isMemOp && MBBI != E) {
584         ++Position;
585         ++MBBI;
586       }
587     }
588   }
589   return NumMerges > 0;
590 }
591
592 /// MergeReturnIntoLDM - If this is a exit BB, try merging the return op
593 /// (bx lr) into the preceeding stack restore so it directly restore the value
594 /// of LR into pc.
595 ///   ldmfd sp!, {r7, lr}
596 ///   bx lr
597 /// =>
598 ///   ldmfd sp!, {r7, pc}
599 bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) {
600   if (MBB.empty()) return false;
601
602   MachineBasicBlock::iterator MBBI = prior(MBB.end());
603   if (MBBI->getOpcode() == ARM::BX_RET && MBBI != MBB.begin()) {
604     MachineInstr *PrevMI = prior(MBBI);
605     if (PrevMI->getOpcode() == ARM::LDM) {
606       MachineOperand &MO = PrevMI->getOperand(PrevMI->getNumOperands()-1);
607       if (MO.getReg() == ARM::LR) {
608         PrevMI->setInstrDescriptor(TII->get(ARM::LDM_RET));
609         MO.setReg(ARM::PC);
610         MBB.erase(MBBI);
611         return true;
612       }
613     }
614   }
615   return false;
616 }
617
618 bool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
619   TII = Fn.getTarget().getInstrInfo();
620   bool Modified = false;
621   for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
622        ++MFI) {
623     MachineBasicBlock &MBB = *MFI;
624     Modified |= LoadStoreMultipleOpti(MBB);
625     Modified |= MergeReturnIntoLDM(MBB);
626   }
627   return Modified;
628 }