xref: /aosp_15_r20/external/llvm/lib/Target/Hexagon/HexagonStoreWidening.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===--- HexagonStoreWidening.cpp------------------------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker // Replace sequences of "narrow" stores to adjacent memory locations with
10*9880d681SAndroid Build Coastguard Worker // a fewer "wide" stores that have the same effect.
11*9880d681SAndroid Build Coastguard Worker // For example, replace:
12*9880d681SAndroid Build Coastguard Worker //   S4_storeirb_io  %vreg100, 0, 0   ; store-immediate-byte
13*9880d681SAndroid Build Coastguard Worker //   S4_storeirb_io  %vreg100, 1, 0   ; store-immediate-byte
14*9880d681SAndroid Build Coastguard Worker // with
15*9880d681SAndroid Build Coastguard Worker //   S4_storeirh_io  %vreg100, 0, 0   ; store-immediate-halfword
16*9880d681SAndroid Build Coastguard Worker // The above is the general idea.  The actual cases handled by the code
17*9880d681SAndroid Build Coastguard Worker // may be a bit more complex.
18*9880d681SAndroid Build Coastguard Worker // The purpose of this pass is to reduce the number of outstanding stores,
19*9880d681SAndroid Build Coastguard Worker // or as one could say, "reduce store queue pressure".  Also, wide stores
20*9880d681SAndroid Build Coastguard Worker // mean fewer stores, and since there are only two memory instructions allowed
21*9880d681SAndroid Build Coastguard Worker // per packet, it also means fewer packets, and ultimately fewer cycles.
22*9880d681SAndroid Build Coastguard Worker //===---------------------------------------------------------------------===//
23*9880d681SAndroid Build Coastguard Worker 
24*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "hexagon-widen-stores"
25*9880d681SAndroid Build Coastguard Worker 
26*9880d681SAndroid Build Coastguard Worker #include "HexagonTargetMachine.h"
27*9880d681SAndroid Build Coastguard Worker 
28*9880d681SAndroid Build Coastguard Worker #include "llvm/PassSupport.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AliasAnalysis.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrDesc.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
41*9880d681SAndroid Build Coastguard Worker 
42*9880d681SAndroid Build Coastguard Worker #include <algorithm>
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker 
45*9880d681SAndroid Build Coastguard Worker using namespace llvm;
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker namespace llvm {
48*9880d681SAndroid Build Coastguard Worker   FunctionPass *createHexagonStoreWidening();
49*9880d681SAndroid Build Coastguard Worker   void initializeHexagonStoreWideningPass(PassRegistry&);
50*9880d681SAndroid Build Coastguard Worker }
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker namespace {
53*9880d681SAndroid Build Coastguard Worker   struct HexagonStoreWidening : public MachineFunctionPass {
54*9880d681SAndroid Build Coastguard Worker     const HexagonInstrInfo      *TII;
55*9880d681SAndroid Build Coastguard Worker     const HexagonRegisterInfo   *TRI;
56*9880d681SAndroid Build Coastguard Worker     const MachineRegisterInfo   *MRI;
57*9880d681SAndroid Build Coastguard Worker     AliasAnalysis               *AA;
58*9880d681SAndroid Build Coastguard Worker     MachineFunction             *MF;
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker   public:
61*9880d681SAndroid Build Coastguard Worker     static char ID;
HexagonStoreWidening__anon30608da30111::HexagonStoreWidening62*9880d681SAndroid Build Coastguard Worker     HexagonStoreWidening() : MachineFunctionPass(ID) {
63*9880d681SAndroid Build Coastguard Worker       initializeHexagonStoreWideningPass(*PassRegistry::getPassRegistry());
64*9880d681SAndroid Build Coastguard Worker     }
65*9880d681SAndroid Build Coastguard Worker 
66*9880d681SAndroid Build Coastguard Worker     bool runOnMachineFunction(MachineFunction &MF) override;
67*9880d681SAndroid Build Coastguard Worker 
getPassName__anon30608da30111::HexagonStoreWidening68*9880d681SAndroid Build Coastguard Worker     const char *getPassName() const override {
69*9880d681SAndroid Build Coastguard Worker       return "Hexagon Store Widening";
70*9880d681SAndroid Build Coastguard Worker     }
71*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage__anon30608da30111::HexagonStoreWidening72*9880d681SAndroid Build Coastguard Worker     void getAnalysisUsage(AnalysisUsage &AU) const override {
73*9880d681SAndroid Build Coastguard Worker       AU.addRequired<AAResultsWrapperPass>();
74*9880d681SAndroid Build Coastguard Worker       AU.addPreserved<AAResultsWrapperPass>();
75*9880d681SAndroid Build Coastguard Worker       MachineFunctionPass::getAnalysisUsage(AU);
76*9880d681SAndroid Build Coastguard Worker     }
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker     static bool handledStoreType(const MachineInstr *MI);
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker   private:
81*9880d681SAndroid Build Coastguard Worker     static const int MaxWideSize = 4;
82*9880d681SAndroid Build Coastguard Worker 
83*9880d681SAndroid Build Coastguard Worker     typedef std::vector<MachineInstr*> InstrGroup;
84*9880d681SAndroid Build Coastguard Worker     typedef std::vector<InstrGroup> InstrGroupList;
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker     bool instrAliased(InstrGroup &Stores, const MachineMemOperand &MMO);
87*9880d681SAndroid Build Coastguard Worker     bool instrAliased(InstrGroup &Stores, const MachineInstr *MI);
88*9880d681SAndroid Build Coastguard Worker     void createStoreGroup(MachineInstr *BaseStore, InstrGroup::iterator Begin,
89*9880d681SAndroid Build Coastguard Worker         InstrGroup::iterator End, InstrGroup &Group);
90*9880d681SAndroid Build Coastguard Worker     void createStoreGroups(MachineBasicBlock &MBB,
91*9880d681SAndroid Build Coastguard Worker         InstrGroupList &StoreGroups);
92*9880d681SAndroid Build Coastguard Worker     bool processBasicBlock(MachineBasicBlock &MBB);
93*9880d681SAndroid Build Coastguard Worker     bool processStoreGroup(InstrGroup &Group);
94*9880d681SAndroid Build Coastguard Worker     bool selectStores(InstrGroup::iterator Begin, InstrGroup::iterator End,
95*9880d681SAndroid Build Coastguard Worker         InstrGroup &OG, unsigned &TotalSize, unsigned MaxSize);
96*9880d681SAndroid Build Coastguard Worker     bool createWideStores(InstrGroup &OG, InstrGroup &NG, unsigned TotalSize);
97*9880d681SAndroid Build Coastguard Worker     bool replaceStores(InstrGroup &OG, InstrGroup &NG);
98*9880d681SAndroid Build Coastguard Worker     bool storesAreAdjacent(const MachineInstr *S1, const MachineInstr *S2);
99*9880d681SAndroid Build Coastguard Worker   };
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker } // namespace
102*9880d681SAndroid Build Coastguard Worker 
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker namespace {
105*9880d681SAndroid Build Coastguard Worker 
106*9880d681SAndroid Build Coastguard Worker // Some local helper functions...
getBaseAddressRegister(const MachineInstr * MI)107*9880d681SAndroid Build Coastguard Worker unsigned getBaseAddressRegister(const MachineInstr *MI) {
108*9880d681SAndroid Build Coastguard Worker   const MachineOperand &MO = MI->getOperand(0);
109*9880d681SAndroid Build Coastguard Worker   assert(MO.isReg() && "Expecting register operand");
110*9880d681SAndroid Build Coastguard Worker   return MO.getReg();
111*9880d681SAndroid Build Coastguard Worker }
112*9880d681SAndroid Build Coastguard Worker 
getStoreOffset(const MachineInstr * MI)113*9880d681SAndroid Build Coastguard Worker int64_t getStoreOffset(const MachineInstr *MI) {
114*9880d681SAndroid Build Coastguard Worker   unsigned OpC = MI->getOpcode();
115*9880d681SAndroid Build Coastguard Worker   assert(HexagonStoreWidening::handledStoreType(MI) && "Unhandled opcode");
116*9880d681SAndroid Build Coastguard Worker 
117*9880d681SAndroid Build Coastguard Worker   switch (OpC) {
118*9880d681SAndroid Build Coastguard Worker     case Hexagon::S4_storeirb_io:
119*9880d681SAndroid Build Coastguard Worker     case Hexagon::S4_storeirh_io:
120*9880d681SAndroid Build Coastguard Worker     case Hexagon::S4_storeiri_io: {
121*9880d681SAndroid Build Coastguard Worker       const MachineOperand &MO = MI->getOperand(1);
122*9880d681SAndroid Build Coastguard Worker       assert(MO.isImm() && "Expecting immediate offset");
123*9880d681SAndroid Build Coastguard Worker       return MO.getImm();
124*9880d681SAndroid Build Coastguard Worker     }
125*9880d681SAndroid Build Coastguard Worker   }
126*9880d681SAndroid Build Coastguard Worker   dbgs() << *MI;
127*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Store offset calculation missing for a handled opcode");
128*9880d681SAndroid Build Coastguard Worker   return 0;
129*9880d681SAndroid Build Coastguard Worker }
130*9880d681SAndroid Build Coastguard Worker 
getStoreTarget(const MachineInstr * MI)131*9880d681SAndroid Build Coastguard Worker const MachineMemOperand &getStoreTarget(const MachineInstr *MI) {
132*9880d681SAndroid Build Coastguard Worker   assert(!MI->memoperands_empty() && "Expecting memory operands");
133*9880d681SAndroid Build Coastguard Worker   return **MI->memoperands_begin();
134*9880d681SAndroid Build Coastguard Worker }
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker } // namespace
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker 
139*9880d681SAndroid Build Coastguard Worker char HexagonStoreWidening::ID = 0;
140*9880d681SAndroid Build Coastguard Worker 
141*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(HexagonStoreWidening, "hexagon-widen-stores",
142*9880d681SAndroid Build Coastguard Worker                 "Hexason Store Widening", false, false)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)143*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
144*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(HexagonStoreWidening, "hexagon-widen-stores",
145*9880d681SAndroid Build Coastguard Worker                 "Hexagon Store Widening", false, false)
146*9880d681SAndroid Build Coastguard Worker 
147*9880d681SAndroid Build Coastguard Worker 
148*9880d681SAndroid Build Coastguard Worker // Filtering function: any stores whose opcodes are not "approved" of by
149*9880d681SAndroid Build Coastguard Worker // this function will not be subjected to widening.
150*9880d681SAndroid Build Coastguard Worker inline bool HexagonStoreWidening::handledStoreType(const MachineInstr *MI) {
151*9880d681SAndroid Build Coastguard Worker   // For now, only handle stores of immediate values.
152*9880d681SAndroid Build Coastguard Worker   // Also, reject stores to stack slots.
153*9880d681SAndroid Build Coastguard Worker   unsigned Opc = MI->getOpcode();
154*9880d681SAndroid Build Coastguard Worker   switch (Opc) {
155*9880d681SAndroid Build Coastguard Worker     case Hexagon::S4_storeirb_io:
156*9880d681SAndroid Build Coastguard Worker     case Hexagon::S4_storeirh_io:
157*9880d681SAndroid Build Coastguard Worker     case Hexagon::S4_storeiri_io:
158*9880d681SAndroid Build Coastguard Worker       // Base address must be a register. (Implement FI later.)
159*9880d681SAndroid Build Coastguard Worker       return MI->getOperand(0).isReg();
160*9880d681SAndroid Build Coastguard Worker     default:
161*9880d681SAndroid Build Coastguard Worker       return false;
162*9880d681SAndroid Build Coastguard Worker   }
163*9880d681SAndroid Build Coastguard Worker }
164*9880d681SAndroid Build Coastguard Worker 
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker // Check if the machine memory operand MMO is aliased with any of the
167*9880d681SAndroid Build Coastguard Worker // stores in the store group Stores.
instrAliased(InstrGroup & Stores,const MachineMemOperand & MMO)168*9880d681SAndroid Build Coastguard Worker bool HexagonStoreWidening::instrAliased(InstrGroup &Stores,
169*9880d681SAndroid Build Coastguard Worker       const MachineMemOperand &MMO) {
170*9880d681SAndroid Build Coastguard Worker   if (!MMO.getValue())
171*9880d681SAndroid Build Coastguard Worker     return true;
172*9880d681SAndroid Build Coastguard Worker 
173*9880d681SAndroid Build Coastguard Worker   MemoryLocation L(MMO.getValue(), MMO.getSize(), MMO.getAAInfo());
174*9880d681SAndroid Build Coastguard Worker 
175*9880d681SAndroid Build Coastguard Worker   for (auto SI : Stores) {
176*9880d681SAndroid Build Coastguard Worker     const MachineMemOperand &SMO = getStoreTarget(SI);
177*9880d681SAndroid Build Coastguard Worker     if (!SMO.getValue())
178*9880d681SAndroid Build Coastguard Worker       return true;
179*9880d681SAndroid Build Coastguard Worker 
180*9880d681SAndroid Build Coastguard Worker     MemoryLocation SL(SMO.getValue(), SMO.getSize(), SMO.getAAInfo());
181*9880d681SAndroid Build Coastguard Worker     if (AA->alias(L, SL))
182*9880d681SAndroid Build Coastguard Worker       return true;
183*9880d681SAndroid Build Coastguard Worker   }
184*9880d681SAndroid Build Coastguard Worker 
185*9880d681SAndroid Build Coastguard Worker   return false;
186*9880d681SAndroid Build Coastguard Worker }
187*9880d681SAndroid Build Coastguard Worker 
188*9880d681SAndroid Build Coastguard Worker 
189*9880d681SAndroid Build Coastguard Worker // Check if the machine instruction MI accesses any storage aliased with
190*9880d681SAndroid Build Coastguard Worker // any store in the group Stores.
instrAliased(InstrGroup & Stores,const MachineInstr * MI)191*9880d681SAndroid Build Coastguard Worker bool HexagonStoreWidening::instrAliased(InstrGroup &Stores,
192*9880d681SAndroid Build Coastguard Worker       const MachineInstr *MI) {
193*9880d681SAndroid Build Coastguard Worker   for (auto &I : MI->memoperands())
194*9880d681SAndroid Build Coastguard Worker     if (instrAliased(Stores, *I))
195*9880d681SAndroid Build Coastguard Worker       return true;
196*9880d681SAndroid Build Coastguard Worker   return false;
197*9880d681SAndroid Build Coastguard Worker }
198*9880d681SAndroid Build Coastguard Worker 
199*9880d681SAndroid Build Coastguard Worker 
200*9880d681SAndroid Build Coastguard Worker // Inspect a machine basic block, and generate store groups out of stores
201*9880d681SAndroid Build Coastguard Worker // encountered in the block.
202*9880d681SAndroid Build Coastguard Worker //
203*9880d681SAndroid Build Coastguard Worker // A store group is a group of stores that use the same base register,
204*9880d681SAndroid Build Coastguard Worker // and which can be reordered within that group without altering the
205*9880d681SAndroid Build Coastguard Worker // semantics of the program.  A single store group could be widened as
206*9880d681SAndroid Build Coastguard Worker // a whole, if there existed a single store instruction with the same
207*9880d681SAndroid Build Coastguard Worker // semantics as the entire group.  In many cases, a single store group
208*9880d681SAndroid Build Coastguard Worker // may need more than one wide store.
createStoreGroups(MachineBasicBlock & MBB,InstrGroupList & StoreGroups)209*9880d681SAndroid Build Coastguard Worker void HexagonStoreWidening::createStoreGroups(MachineBasicBlock &MBB,
210*9880d681SAndroid Build Coastguard Worker       InstrGroupList &StoreGroups) {
211*9880d681SAndroid Build Coastguard Worker   InstrGroup AllInsns;
212*9880d681SAndroid Build Coastguard Worker 
213*9880d681SAndroid Build Coastguard Worker   // Copy all instruction pointers from the basic block to a temporary
214*9880d681SAndroid Build Coastguard Worker   // list.  This will allow operating on the list, and modifying its
215*9880d681SAndroid Build Coastguard Worker   // elements without affecting the basic block.
216*9880d681SAndroid Build Coastguard Worker   for (auto &I : MBB)
217*9880d681SAndroid Build Coastguard Worker     AllInsns.push_back(&I);
218*9880d681SAndroid Build Coastguard Worker 
219*9880d681SAndroid Build Coastguard Worker   // Traverse all instructions in the AllInsns list, and if we encounter
220*9880d681SAndroid Build Coastguard Worker   // a store, then try to create a store group starting at that instruction
221*9880d681SAndroid Build Coastguard Worker   // i.e. a sequence of independent stores that can be widened.
222*9880d681SAndroid Build Coastguard Worker   for (auto I = AllInsns.begin(), E = AllInsns.end(); I != E; ++I) {
223*9880d681SAndroid Build Coastguard Worker     MachineInstr *MI = *I;
224*9880d681SAndroid Build Coastguard Worker     // Skip null pointers (processed instructions).
225*9880d681SAndroid Build Coastguard Worker     if (!MI || !handledStoreType(MI))
226*9880d681SAndroid Build Coastguard Worker       continue;
227*9880d681SAndroid Build Coastguard Worker 
228*9880d681SAndroid Build Coastguard Worker     // Found a store.  Try to create a store group.
229*9880d681SAndroid Build Coastguard Worker     InstrGroup G;
230*9880d681SAndroid Build Coastguard Worker     createStoreGroup(MI, I+1, E, G);
231*9880d681SAndroid Build Coastguard Worker     if (G.size() > 1)
232*9880d681SAndroid Build Coastguard Worker       StoreGroups.push_back(G);
233*9880d681SAndroid Build Coastguard Worker   }
234*9880d681SAndroid Build Coastguard Worker }
235*9880d681SAndroid Build Coastguard Worker 
236*9880d681SAndroid Build Coastguard Worker 
237*9880d681SAndroid Build Coastguard Worker // Create a single store group.  The stores need to be independent between
238*9880d681SAndroid Build Coastguard Worker // themselves, and also there cannot be other instructions between them
239*9880d681SAndroid Build Coastguard Worker // that could read or modify storage being stored into.
createStoreGroup(MachineInstr * BaseStore,InstrGroup::iterator Begin,InstrGroup::iterator End,InstrGroup & Group)240*9880d681SAndroid Build Coastguard Worker void HexagonStoreWidening::createStoreGroup(MachineInstr *BaseStore,
241*9880d681SAndroid Build Coastguard Worker       InstrGroup::iterator Begin, InstrGroup::iterator End, InstrGroup &Group) {
242*9880d681SAndroid Build Coastguard Worker   assert(handledStoreType(BaseStore) && "Unexpected instruction");
243*9880d681SAndroid Build Coastguard Worker   unsigned BaseReg = getBaseAddressRegister(BaseStore);
244*9880d681SAndroid Build Coastguard Worker   InstrGroup Other;
245*9880d681SAndroid Build Coastguard Worker 
246*9880d681SAndroid Build Coastguard Worker   Group.push_back(BaseStore);
247*9880d681SAndroid Build Coastguard Worker 
248*9880d681SAndroid Build Coastguard Worker   for (auto I = Begin; I != End; ++I) {
249*9880d681SAndroid Build Coastguard Worker     MachineInstr *MI = *I;
250*9880d681SAndroid Build Coastguard Worker     if (!MI)
251*9880d681SAndroid Build Coastguard Worker       continue;
252*9880d681SAndroid Build Coastguard Worker 
253*9880d681SAndroid Build Coastguard Worker     if (handledStoreType(MI)) {
254*9880d681SAndroid Build Coastguard Worker       // If this store instruction is aliased with anything already in the
255*9880d681SAndroid Build Coastguard Worker       // group, terminate the group now.
256*9880d681SAndroid Build Coastguard Worker       if (instrAliased(Group, getStoreTarget(MI)))
257*9880d681SAndroid Build Coastguard Worker         return;
258*9880d681SAndroid Build Coastguard Worker       // If this store is aliased to any of the memory instructions we have
259*9880d681SAndroid Build Coastguard Worker       // seen so far (that are not a part of this group), terminate the group.
260*9880d681SAndroid Build Coastguard Worker       if (instrAliased(Other, getStoreTarget(MI)))
261*9880d681SAndroid Build Coastguard Worker         return;
262*9880d681SAndroid Build Coastguard Worker 
263*9880d681SAndroid Build Coastguard Worker       unsigned BR = getBaseAddressRegister(MI);
264*9880d681SAndroid Build Coastguard Worker       if (BR == BaseReg) {
265*9880d681SAndroid Build Coastguard Worker         Group.push_back(MI);
266*9880d681SAndroid Build Coastguard Worker         *I = 0;
267*9880d681SAndroid Build Coastguard Worker         continue;
268*9880d681SAndroid Build Coastguard Worker       }
269*9880d681SAndroid Build Coastguard Worker     }
270*9880d681SAndroid Build Coastguard Worker 
271*9880d681SAndroid Build Coastguard Worker     // Assume calls are aliased to everything.
272*9880d681SAndroid Build Coastguard Worker     if (MI->isCall() || MI->hasUnmodeledSideEffects())
273*9880d681SAndroid Build Coastguard Worker       return;
274*9880d681SAndroid Build Coastguard Worker 
275*9880d681SAndroid Build Coastguard Worker     if (MI->mayLoad() || MI->mayStore()) {
276*9880d681SAndroid Build Coastguard Worker       if (MI->hasOrderedMemoryRef() || instrAliased(Group, MI))
277*9880d681SAndroid Build Coastguard Worker         return;
278*9880d681SAndroid Build Coastguard Worker       Other.push_back(MI);
279*9880d681SAndroid Build Coastguard Worker     }
280*9880d681SAndroid Build Coastguard Worker   } // for
281*9880d681SAndroid Build Coastguard Worker }
282*9880d681SAndroid Build Coastguard Worker 
283*9880d681SAndroid Build Coastguard Worker 
284*9880d681SAndroid Build Coastguard Worker // Check if store instructions S1 and S2 are adjacent.  More precisely,
285*9880d681SAndroid Build Coastguard Worker // S2 has to access memory immediately following that accessed by S1.
storesAreAdjacent(const MachineInstr * S1,const MachineInstr * S2)286*9880d681SAndroid Build Coastguard Worker bool HexagonStoreWidening::storesAreAdjacent(const MachineInstr *S1,
287*9880d681SAndroid Build Coastguard Worker       const MachineInstr *S2) {
288*9880d681SAndroid Build Coastguard Worker   if (!handledStoreType(S1) || !handledStoreType(S2))
289*9880d681SAndroid Build Coastguard Worker     return false;
290*9880d681SAndroid Build Coastguard Worker 
291*9880d681SAndroid Build Coastguard Worker   const MachineMemOperand &S1MO = getStoreTarget(S1);
292*9880d681SAndroid Build Coastguard Worker 
293*9880d681SAndroid Build Coastguard Worker   // Currently only handling immediate stores.
294*9880d681SAndroid Build Coastguard Worker   int Off1 = S1->getOperand(1).getImm();
295*9880d681SAndroid Build Coastguard Worker   int Off2 = S2->getOperand(1).getImm();
296*9880d681SAndroid Build Coastguard Worker 
297*9880d681SAndroid Build Coastguard Worker   return (Off1 >= 0) ? Off1+S1MO.getSize() == unsigned(Off2)
298*9880d681SAndroid Build Coastguard Worker                      : int(Off1+S1MO.getSize()) == Off2;
299*9880d681SAndroid Build Coastguard Worker }
300*9880d681SAndroid Build Coastguard Worker 
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker /// Given a sequence of adjacent stores, and a maximum size of a single wide
303*9880d681SAndroid Build Coastguard Worker /// store, pick a group of stores that  can be replaced by a single store
304*9880d681SAndroid Build Coastguard Worker /// of size not exceeding MaxSize.  The selected sequence will be recorded
305*9880d681SAndroid Build Coastguard Worker /// in OG ("old group" of instructions).
306*9880d681SAndroid Build Coastguard Worker /// OG should be empty on entry, and should be left empty if the function
307*9880d681SAndroid Build Coastguard Worker /// fails.
selectStores(InstrGroup::iterator Begin,InstrGroup::iterator End,InstrGroup & OG,unsigned & TotalSize,unsigned MaxSize)308*9880d681SAndroid Build Coastguard Worker bool HexagonStoreWidening::selectStores(InstrGroup::iterator Begin,
309*9880d681SAndroid Build Coastguard Worker       InstrGroup::iterator End, InstrGroup &OG, unsigned &TotalSize,
310*9880d681SAndroid Build Coastguard Worker       unsigned MaxSize) {
311*9880d681SAndroid Build Coastguard Worker   assert(Begin != End && "No instructions to analyze");
312*9880d681SAndroid Build Coastguard Worker   assert(OG.empty() && "Old group not empty on entry");
313*9880d681SAndroid Build Coastguard Worker 
314*9880d681SAndroid Build Coastguard Worker   if (std::distance(Begin, End) <= 1)
315*9880d681SAndroid Build Coastguard Worker     return false;
316*9880d681SAndroid Build Coastguard Worker 
317*9880d681SAndroid Build Coastguard Worker   MachineInstr *FirstMI = *Begin;
318*9880d681SAndroid Build Coastguard Worker   assert(!FirstMI->memoperands_empty() && "Expecting some memory operands");
319*9880d681SAndroid Build Coastguard Worker   const MachineMemOperand &FirstMMO = getStoreTarget(FirstMI);
320*9880d681SAndroid Build Coastguard Worker   unsigned Alignment = FirstMMO.getAlignment();
321*9880d681SAndroid Build Coastguard Worker   unsigned SizeAccum = FirstMMO.getSize();
322*9880d681SAndroid Build Coastguard Worker   unsigned FirstOffset = getStoreOffset(FirstMI);
323*9880d681SAndroid Build Coastguard Worker 
324*9880d681SAndroid Build Coastguard Worker   // The initial value of SizeAccum should always be a power of 2.
325*9880d681SAndroid Build Coastguard Worker   assert(isPowerOf2_32(SizeAccum) && "First store size not a power of 2");
326*9880d681SAndroid Build Coastguard Worker 
327*9880d681SAndroid Build Coastguard Worker   // If the size of the first store equals to or exceeds the limit, do nothing.
328*9880d681SAndroid Build Coastguard Worker   if (SizeAccum >= MaxSize)
329*9880d681SAndroid Build Coastguard Worker     return false;
330*9880d681SAndroid Build Coastguard Worker 
331*9880d681SAndroid Build Coastguard Worker   // If the size of the first store is greater than or equal to the address
332*9880d681SAndroid Build Coastguard Worker   // stored to, then the store cannot be made any wider.
333*9880d681SAndroid Build Coastguard Worker   if (SizeAccum >= Alignment)
334*9880d681SAndroid Build Coastguard Worker     return false;
335*9880d681SAndroid Build Coastguard Worker 
336*9880d681SAndroid Build Coastguard Worker   // The offset of a store will put restrictions on how wide the store can be.
337*9880d681SAndroid Build Coastguard Worker   // Offsets in stores of size 2^n bytes need to have the n lowest bits be 0.
338*9880d681SAndroid Build Coastguard Worker   // If the first store already exhausts the offset limits, quit.  Test this
339*9880d681SAndroid Build Coastguard Worker   // by checking if the next wider size would exceed the limit.
340*9880d681SAndroid Build Coastguard Worker   if ((2*SizeAccum-1) & FirstOffset)
341*9880d681SAndroid Build Coastguard Worker     return false;
342*9880d681SAndroid Build Coastguard Worker 
343*9880d681SAndroid Build Coastguard Worker   OG.push_back(FirstMI);
344*9880d681SAndroid Build Coastguard Worker   MachineInstr *S1 = FirstMI, *S2 = *(Begin+1);
345*9880d681SAndroid Build Coastguard Worker   InstrGroup::iterator I = Begin+1;
346*9880d681SAndroid Build Coastguard Worker 
347*9880d681SAndroid Build Coastguard Worker   // Pow2Num will be the largest number of elements in OG such that the sum
348*9880d681SAndroid Build Coastguard Worker   // of sizes of stores 0...Pow2Num-1 will be a power of 2.
349*9880d681SAndroid Build Coastguard Worker   unsigned Pow2Num = 1;
350*9880d681SAndroid Build Coastguard Worker   unsigned Pow2Size = SizeAccum;
351*9880d681SAndroid Build Coastguard Worker 
352*9880d681SAndroid Build Coastguard Worker   // Be greedy: keep accumulating stores as long as they are to adjacent
353*9880d681SAndroid Build Coastguard Worker   // memory locations, and as long as the total number of bytes stored
354*9880d681SAndroid Build Coastguard Worker   // does not exceed the limit (MaxSize).
355*9880d681SAndroid Build Coastguard Worker   // Keep track of when the total size covered is a power of 2, since
356*9880d681SAndroid Build Coastguard Worker   // this is a size a single store can cover.
357*9880d681SAndroid Build Coastguard Worker   while (I != End) {
358*9880d681SAndroid Build Coastguard Worker     S2 = *I;
359*9880d681SAndroid Build Coastguard Worker     // Stores are sorted, so if S1 and S2 are not adjacent, there won't be
360*9880d681SAndroid Build Coastguard Worker     // any other store to fill the "hole".
361*9880d681SAndroid Build Coastguard Worker     if (!storesAreAdjacent(S1, S2))
362*9880d681SAndroid Build Coastguard Worker       break;
363*9880d681SAndroid Build Coastguard Worker 
364*9880d681SAndroid Build Coastguard Worker     unsigned S2Size = getStoreTarget(S2).getSize();
365*9880d681SAndroid Build Coastguard Worker     if (SizeAccum + S2Size > std::min(MaxSize, Alignment))
366*9880d681SAndroid Build Coastguard Worker       break;
367*9880d681SAndroid Build Coastguard Worker 
368*9880d681SAndroid Build Coastguard Worker     OG.push_back(S2);
369*9880d681SAndroid Build Coastguard Worker     SizeAccum += S2Size;
370*9880d681SAndroid Build Coastguard Worker     if (isPowerOf2_32(SizeAccum)) {
371*9880d681SAndroid Build Coastguard Worker       Pow2Num = OG.size();
372*9880d681SAndroid Build Coastguard Worker       Pow2Size = SizeAccum;
373*9880d681SAndroid Build Coastguard Worker     }
374*9880d681SAndroid Build Coastguard Worker     if ((2*Pow2Size-1) & FirstOffset)
375*9880d681SAndroid Build Coastguard Worker       break;
376*9880d681SAndroid Build Coastguard Worker 
377*9880d681SAndroid Build Coastguard Worker     S1 = S2;
378*9880d681SAndroid Build Coastguard Worker     ++I;
379*9880d681SAndroid Build Coastguard Worker   }
380*9880d681SAndroid Build Coastguard Worker 
381*9880d681SAndroid Build Coastguard Worker   // The stores don't add up to anything that can be widened.  Clean up.
382*9880d681SAndroid Build Coastguard Worker   if (Pow2Num <= 1) {
383*9880d681SAndroid Build Coastguard Worker     OG.clear();
384*9880d681SAndroid Build Coastguard Worker     return false;
385*9880d681SAndroid Build Coastguard Worker   }
386*9880d681SAndroid Build Coastguard Worker 
387*9880d681SAndroid Build Coastguard Worker   // Only leave the stored being widened.
388*9880d681SAndroid Build Coastguard Worker   OG.resize(Pow2Num);
389*9880d681SAndroid Build Coastguard Worker   TotalSize = Pow2Size;
390*9880d681SAndroid Build Coastguard Worker   return true;
391*9880d681SAndroid Build Coastguard Worker }
392*9880d681SAndroid Build Coastguard Worker 
393*9880d681SAndroid Build Coastguard Worker 
394*9880d681SAndroid Build Coastguard Worker /// Given an "old group" OG of stores, create a "new group" NG of instructions
395*9880d681SAndroid Build Coastguard Worker /// to replace them.  Ideally, NG would only have a single instruction in it,
396*9880d681SAndroid Build Coastguard Worker /// but that may only be possible for store-immediate.
createWideStores(InstrGroup & OG,InstrGroup & NG,unsigned TotalSize)397*9880d681SAndroid Build Coastguard Worker bool HexagonStoreWidening::createWideStores(InstrGroup &OG, InstrGroup &NG,
398*9880d681SAndroid Build Coastguard Worker       unsigned TotalSize) {
399*9880d681SAndroid Build Coastguard Worker   // XXX Current limitations:
400*9880d681SAndroid Build Coastguard Worker   // - only expect stores of immediate values in OG,
401*9880d681SAndroid Build Coastguard Worker   // - only handle a TotalSize of up to 4.
402*9880d681SAndroid Build Coastguard Worker 
403*9880d681SAndroid Build Coastguard Worker   if (TotalSize > 4)
404*9880d681SAndroid Build Coastguard Worker     return false;
405*9880d681SAndroid Build Coastguard Worker 
406*9880d681SAndroid Build Coastguard Worker   unsigned Acc = 0;  // Value accumulator.
407*9880d681SAndroid Build Coastguard Worker   unsigned Shift = 0;
408*9880d681SAndroid Build Coastguard Worker 
409*9880d681SAndroid Build Coastguard Worker   for (InstrGroup::iterator I = OG.begin(), E = OG.end(); I != E; ++I) {
410*9880d681SAndroid Build Coastguard Worker     MachineInstr *MI = *I;
411*9880d681SAndroid Build Coastguard Worker     const MachineMemOperand &MMO = getStoreTarget(MI);
412*9880d681SAndroid Build Coastguard Worker     MachineOperand &SO = MI->getOperand(2);  // Source.
413*9880d681SAndroid Build Coastguard Worker     assert(SO.isImm() && "Expecting an immediate operand");
414*9880d681SAndroid Build Coastguard Worker 
415*9880d681SAndroid Build Coastguard Worker     unsigned NBits = MMO.getSize()*8;
416*9880d681SAndroid Build Coastguard Worker     unsigned Mask = (0xFFFFFFFFU >> (32-NBits));
417*9880d681SAndroid Build Coastguard Worker     unsigned Val = (SO.getImm() & Mask) << Shift;
418*9880d681SAndroid Build Coastguard Worker     Acc |= Val;
419*9880d681SAndroid Build Coastguard Worker     Shift += NBits;
420*9880d681SAndroid Build Coastguard Worker   }
421*9880d681SAndroid Build Coastguard Worker 
422*9880d681SAndroid Build Coastguard Worker 
423*9880d681SAndroid Build Coastguard Worker   MachineInstr *FirstSt = OG.front();
424*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = OG.back()->getDebugLoc();
425*9880d681SAndroid Build Coastguard Worker   const MachineMemOperand &OldM = getStoreTarget(FirstSt);
426*9880d681SAndroid Build Coastguard Worker   MachineMemOperand *NewM =
427*9880d681SAndroid Build Coastguard Worker     MF->getMachineMemOperand(OldM.getPointerInfo(), OldM.getFlags(),
428*9880d681SAndroid Build Coastguard Worker                              TotalSize, OldM.getAlignment(),
429*9880d681SAndroid Build Coastguard Worker                              OldM.getAAInfo());
430*9880d681SAndroid Build Coastguard Worker 
431*9880d681SAndroid Build Coastguard Worker   if (Acc < 0x10000) {
432*9880d681SAndroid Build Coastguard Worker     // Create mem[hw] = #Acc
433*9880d681SAndroid Build Coastguard Worker     unsigned WOpc = (TotalSize == 2) ? Hexagon::S4_storeirh_io :
434*9880d681SAndroid Build Coastguard Worker                     (TotalSize == 4) ? Hexagon::S4_storeiri_io : 0;
435*9880d681SAndroid Build Coastguard Worker     assert(WOpc && "Unexpected size");
436*9880d681SAndroid Build Coastguard Worker 
437*9880d681SAndroid Build Coastguard Worker     int Val = (TotalSize == 2) ? int16_t(Acc) : int(Acc);
438*9880d681SAndroid Build Coastguard Worker     const MCInstrDesc &StD = TII->get(WOpc);
439*9880d681SAndroid Build Coastguard Worker     MachineOperand &MR = FirstSt->getOperand(0);
440*9880d681SAndroid Build Coastguard Worker     int64_t Off = FirstSt->getOperand(1).getImm();
441*9880d681SAndroid Build Coastguard Worker     MachineInstr *StI = BuildMI(*MF, DL, StD)
442*9880d681SAndroid Build Coastguard Worker                           .addReg(MR.getReg(), getKillRegState(MR.isKill()))
443*9880d681SAndroid Build Coastguard Worker                           .addImm(Off)
444*9880d681SAndroid Build Coastguard Worker                           .addImm(Val);
445*9880d681SAndroid Build Coastguard Worker     StI->addMemOperand(*MF, NewM);
446*9880d681SAndroid Build Coastguard Worker     NG.push_back(StI);
447*9880d681SAndroid Build Coastguard Worker   } else {
448*9880d681SAndroid Build Coastguard Worker     // Create vreg = A2_tfrsi #Acc; mem[hw] = vreg
449*9880d681SAndroid Build Coastguard Worker     const MCInstrDesc &TfrD = TII->get(Hexagon::A2_tfrsi);
450*9880d681SAndroid Build Coastguard Worker     const TargetRegisterClass *RC = TII->getRegClass(TfrD, 0, TRI, *MF);
451*9880d681SAndroid Build Coastguard Worker     unsigned VReg = MF->getRegInfo().createVirtualRegister(RC);
452*9880d681SAndroid Build Coastguard Worker     MachineInstr *TfrI = BuildMI(*MF, DL, TfrD, VReg)
453*9880d681SAndroid Build Coastguard Worker                            .addImm(int(Acc));
454*9880d681SAndroid Build Coastguard Worker     NG.push_back(TfrI);
455*9880d681SAndroid Build Coastguard Worker 
456*9880d681SAndroid Build Coastguard Worker     unsigned WOpc = (TotalSize == 2) ? Hexagon::S2_storerh_io :
457*9880d681SAndroid Build Coastguard Worker                     (TotalSize == 4) ? Hexagon::S2_storeri_io : 0;
458*9880d681SAndroid Build Coastguard Worker     assert(WOpc && "Unexpected size");
459*9880d681SAndroid Build Coastguard Worker 
460*9880d681SAndroid Build Coastguard Worker     const MCInstrDesc &StD = TII->get(WOpc);
461*9880d681SAndroid Build Coastguard Worker     MachineOperand &MR = FirstSt->getOperand(0);
462*9880d681SAndroid Build Coastguard Worker     int64_t Off = FirstSt->getOperand(1).getImm();
463*9880d681SAndroid Build Coastguard Worker     MachineInstr *StI = BuildMI(*MF, DL, StD)
464*9880d681SAndroid Build Coastguard Worker                           .addReg(MR.getReg(), getKillRegState(MR.isKill()))
465*9880d681SAndroid Build Coastguard Worker                           .addImm(Off)
466*9880d681SAndroid Build Coastguard Worker                           .addReg(VReg, RegState::Kill);
467*9880d681SAndroid Build Coastguard Worker     StI->addMemOperand(*MF, NewM);
468*9880d681SAndroid Build Coastguard Worker     NG.push_back(StI);
469*9880d681SAndroid Build Coastguard Worker   }
470*9880d681SAndroid Build Coastguard Worker 
471*9880d681SAndroid Build Coastguard Worker   return true;
472*9880d681SAndroid Build Coastguard Worker }
473*9880d681SAndroid Build Coastguard Worker 
474*9880d681SAndroid Build Coastguard Worker 
475*9880d681SAndroid Build Coastguard Worker // Replace instructions from the old group OG with instructions from the
476*9880d681SAndroid Build Coastguard Worker // new group NG.  Conceptually, remove all instructions in OG, and then
477*9880d681SAndroid Build Coastguard Worker // insert all instructions in NG, starting at where the first instruction
478*9880d681SAndroid Build Coastguard Worker // from OG was (in the order in which they appeared in the basic block).
479*9880d681SAndroid Build Coastguard Worker // (The ordering in OG does not have to match the order in the basic block.)
replaceStores(InstrGroup & OG,InstrGroup & NG)480*9880d681SAndroid Build Coastguard Worker bool HexagonStoreWidening::replaceStores(InstrGroup &OG, InstrGroup &NG) {
481*9880d681SAndroid Build Coastguard Worker   DEBUG({
482*9880d681SAndroid Build Coastguard Worker     dbgs() << "Replacing:\n";
483*9880d681SAndroid Build Coastguard Worker     for (auto I : OG)
484*9880d681SAndroid Build Coastguard Worker       dbgs() << "  " << *I;
485*9880d681SAndroid Build Coastguard Worker     dbgs() << "with\n";
486*9880d681SAndroid Build Coastguard Worker     for (auto I : NG)
487*9880d681SAndroid Build Coastguard Worker       dbgs() << "  " << *I;
488*9880d681SAndroid Build Coastguard Worker   });
489*9880d681SAndroid Build Coastguard Worker 
490*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB = OG.back()->getParent();
491*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator InsertAt = MBB->end();
492*9880d681SAndroid Build Coastguard Worker 
493*9880d681SAndroid Build Coastguard Worker   // Need to establish the insertion point.  The best one is right before
494*9880d681SAndroid Build Coastguard Worker   // the first store in the OG, but in the order in which the stores occur
495*9880d681SAndroid Build Coastguard Worker   // in the program list.  Since the ordering in OG does not correspond
496*9880d681SAndroid Build Coastguard Worker   // to the order in the program list, we need to do some work to find
497*9880d681SAndroid Build Coastguard Worker   // the insertion point.
498*9880d681SAndroid Build Coastguard Worker 
499*9880d681SAndroid Build Coastguard Worker   // Create a set of all instructions in OG (for quick lookup).
500*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<MachineInstr*, 4> InstrSet;
501*9880d681SAndroid Build Coastguard Worker   for (auto I : OG)
502*9880d681SAndroid Build Coastguard Worker     InstrSet.insert(I);
503*9880d681SAndroid Build Coastguard Worker 
504*9880d681SAndroid Build Coastguard Worker   // Traverse the block, until we hit an instruction from OG.
505*9880d681SAndroid Build Coastguard Worker   for (auto &I : *MBB) {
506*9880d681SAndroid Build Coastguard Worker     if (InstrSet.count(&I)) {
507*9880d681SAndroid Build Coastguard Worker       InsertAt = I;
508*9880d681SAndroid Build Coastguard Worker       break;
509*9880d681SAndroid Build Coastguard Worker     }
510*9880d681SAndroid Build Coastguard Worker   }
511*9880d681SAndroid Build Coastguard Worker 
512*9880d681SAndroid Build Coastguard Worker   assert((InsertAt != MBB->end()) && "Cannot locate any store from the group");
513*9880d681SAndroid Build Coastguard Worker 
514*9880d681SAndroid Build Coastguard Worker   bool AtBBStart = false;
515*9880d681SAndroid Build Coastguard Worker 
516*9880d681SAndroid Build Coastguard Worker   // InsertAt points at the first instruction that will be removed.  We need
517*9880d681SAndroid Build Coastguard Worker   // to move it out of the way, so it remains valid after removing all the
518*9880d681SAndroid Build Coastguard Worker   // old stores, and so we are able to recover it back to the proper insertion
519*9880d681SAndroid Build Coastguard Worker   // position.
520*9880d681SAndroid Build Coastguard Worker   if (InsertAt != MBB->begin())
521*9880d681SAndroid Build Coastguard Worker     --InsertAt;
522*9880d681SAndroid Build Coastguard Worker   else
523*9880d681SAndroid Build Coastguard Worker     AtBBStart = true;
524*9880d681SAndroid Build Coastguard Worker 
525*9880d681SAndroid Build Coastguard Worker   for (auto I : OG)
526*9880d681SAndroid Build Coastguard Worker     I->eraseFromParent();
527*9880d681SAndroid Build Coastguard Worker 
528*9880d681SAndroid Build Coastguard Worker   if (!AtBBStart)
529*9880d681SAndroid Build Coastguard Worker     ++InsertAt;
530*9880d681SAndroid Build Coastguard Worker   else
531*9880d681SAndroid Build Coastguard Worker     InsertAt = MBB->begin();
532*9880d681SAndroid Build Coastguard Worker 
533*9880d681SAndroid Build Coastguard Worker   for (auto I : NG)
534*9880d681SAndroid Build Coastguard Worker     MBB->insert(InsertAt, I);
535*9880d681SAndroid Build Coastguard Worker 
536*9880d681SAndroid Build Coastguard Worker   return true;
537*9880d681SAndroid Build Coastguard Worker }
538*9880d681SAndroid Build Coastguard Worker 
539*9880d681SAndroid Build Coastguard Worker 
540*9880d681SAndroid Build Coastguard Worker // Break up the group into smaller groups, each of which can be replaced by
541*9880d681SAndroid Build Coastguard Worker // a single wide store.  Widen each such smaller group and replace the old
542*9880d681SAndroid Build Coastguard Worker // instructions with the widened ones.
processStoreGroup(InstrGroup & Group)543*9880d681SAndroid Build Coastguard Worker bool HexagonStoreWidening::processStoreGroup(InstrGroup &Group) {
544*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
545*9880d681SAndroid Build Coastguard Worker   InstrGroup::iterator I = Group.begin(), E = Group.end();
546*9880d681SAndroid Build Coastguard Worker   InstrGroup OG, NG;   // Old and new groups.
547*9880d681SAndroid Build Coastguard Worker   unsigned CollectedSize;
548*9880d681SAndroid Build Coastguard Worker 
549*9880d681SAndroid Build Coastguard Worker   while (I != E) {
550*9880d681SAndroid Build Coastguard Worker     OG.clear();
551*9880d681SAndroid Build Coastguard Worker     NG.clear();
552*9880d681SAndroid Build Coastguard Worker 
553*9880d681SAndroid Build Coastguard Worker     bool Succ = selectStores(I++, E, OG, CollectedSize, MaxWideSize) &&
554*9880d681SAndroid Build Coastguard Worker                 createWideStores(OG, NG, CollectedSize)              &&
555*9880d681SAndroid Build Coastguard Worker                 replaceStores(OG, NG);
556*9880d681SAndroid Build Coastguard Worker     if (!Succ)
557*9880d681SAndroid Build Coastguard Worker       continue;
558*9880d681SAndroid Build Coastguard Worker 
559*9880d681SAndroid Build Coastguard Worker     assert(OG.size() > 1 && "Created invalid group");
560*9880d681SAndroid Build Coastguard Worker     assert(distance(I, E)+1 >= int(OG.size()) && "Too many elements");
561*9880d681SAndroid Build Coastguard Worker     I += OG.size()-1;
562*9880d681SAndroid Build Coastguard Worker 
563*9880d681SAndroid Build Coastguard Worker     Changed = true;
564*9880d681SAndroid Build Coastguard Worker   }
565*9880d681SAndroid Build Coastguard Worker 
566*9880d681SAndroid Build Coastguard Worker   return Changed;
567*9880d681SAndroid Build Coastguard Worker }
568*9880d681SAndroid Build Coastguard Worker 
569*9880d681SAndroid Build Coastguard Worker 
570*9880d681SAndroid Build Coastguard Worker // Process a single basic block: create the store groups, and replace them
571*9880d681SAndroid Build Coastguard Worker // with the widened stores, if possible.  Processing of each basic block
572*9880d681SAndroid Build Coastguard Worker // is independent from processing of any other basic block.  This transfor-
573*9880d681SAndroid Build Coastguard Worker // mation could be stopped after having processed any basic block without
574*9880d681SAndroid Build Coastguard Worker // any ill effects (other than not having performed widening in the unpro-
575*9880d681SAndroid Build Coastguard Worker // cessed blocks).  Also, the basic blocks can be processed in any order.
processBasicBlock(MachineBasicBlock & MBB)576*9880d681SAndroid Build Coastguard Worker bool HexagonStoreWidening::processBasicBlock(MachineBasicBlock &MBB) {
577*9880d681SAndroid Build Coastguard Worker   InstrGroupList SGs;
578*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
579*9880d681SAndroid Build Coastguard Worker 
580*9880d681SAndroid Build Coastguard Worker   createStoreGroups(MBB, SGs);
581*9880d681SAndroid Build Coastguard Worker 
582*9880d681SAndroid Build Coastguard Worker   auto Less = [] (const MachineInstr *A, const MachineInstr *B) -> bool {
583*9880d681SAndroid Build Coastguard Worker     return getStoreOffset(A) < getStoreOffset(B);
584*9880d681SAndroid Build Coastguard Worker   };
585*9880d681SAndroid Build Coastguard Worker   for (auto &G : SGs) {
586*9880d681SAndroid Build Coastguard Worker     assert(G.size() > 1 && "Store group with fewer than 2 elements");
587*9880d681SAndroid Build Coastguard Worker     std::sort(G.begin(), G.end(), Less);
588*9880d681SAndroid Build Coastguard Worker 
589*9880d681SAndroid Build Coastguard Worker     Changed |= processStoreGroup(G);
590*9880d681SAndroid Build Coastguard Worker   }
591*9880d681SAndroid Build Coastguard Worker 
592*9880d681SAndroid Build Coastguard Worker   return Changed;
593*9880d681SAndroid Build Coastguard Worker }
594*9880d681SAndroid Build Coastguard Worker 
595*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction(MachineFunction & MFn)596*9880d681SAndroid Build Coastguard Worker bool HexagonStoreWidening::runOnMachineFunction(MachineFunction &MFn) {
597*9880d681SAndroid Build Coastguard Worker   if (skipFunction(*MFn.getFunction()))
598*9880d681SAndroid Build Coastguard Worker     return false;
599*9880d681SAndroid Build Coastguard Worker 
600*9880d681SAndroid Build Coastguard Worker   MF = &MFn;
601*9880d681SAndroid Build Coastguard Worker   auto &ST = MFn.getSubtarget<HexagonSubtarget>();
602*9880d681SAndroid Build Coastguard Worker   TII = ST.getInstrInfo();
603*9880d681SAndroid Build Coastguard Worker   TRI = ST.getRegisterInfo();
604*9880d681SAndroid Build Coastguard Worker   MRI = &MFn.getRegInfo();
605*9880d681SAndroid Build Coastguard Worker   AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
606*9880d681SAndroid Build Coastguard Worker 
607*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
608*9880d681SAndroid Build Coastguard Worker 
609*9880d681SAndroid Build Coastguard Worker   for (auto &B : MFn)
610*9880d681SAndroid Build Coastguard Worker     Changed |= processBasicBlock(B);
611*9880d681SAndroid Build Coastguard Worker 
612*9880d681SAndroid Build Coastguard Worker   return Changed;
613*9880d681SAndroid Build Coastguard Worker }
614*9880d681SAndroid Build Coastguard Worker 
615*9880d681SAndroid Build Coastguard Worker 
createHexagonStoreWidening()616*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createHexagonStoreWidening() {
617*9880d681SAndroid Build Coastguard Worker   return new HexagonStoreWidening();
618*9880d681SAndroid Build Coastguard Worker }
619*9880d681SAndroid Build Coastguard Worker 
620