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