1*9880d681SAndroid Build Coastguard Worker //=- AArch64LoadStoreOptimizer.cpp - AArch64 load/store opt. pass -*- C++ -*-=//
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 //
10*9880d681SAndroid Build Coastguard Worker // This file contains a pass that performs load / store related peephole
11*9880d681SAndroid Build Coastguard Worker // optimizations. This pass should be run after register allocation.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "AArch64InstrInfo.h"
16*9880d681SAndroid Build Coastguard Worker #include "AArch64Subtarget.h"
17*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AArch64AddressingModes.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/BitVector.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineBasicBlock.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstr.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
32*9880d681SAndroid Build Coastguard Worker using namespace llvm;
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "aarch64-ldst-opt"
35*9880d681SAndroid Build Coastguard Worker
36*9880d681SAndroid Build Coastguard Worker STATISTIC(NumPairCreated, "Number of load/store pair instructions generated");
37*9880d681SAndroid Build Coastguard Worker STATISTIC(NumPostFolded, "Number of post-index updates folded");
38*9880d681SAndroid Build Coastguard Worker STATISTIC(NumPreFolded, "Number of pre-index updates folded");
39*9880d681SAndroid Build Coastguard Worker STATISTIC(NumUnscaledPairCreated,
40*9880d681SAndroid Build Coastguard Worker "Number of load/store from unscaled generated");
41*9880d681SAndroid Build Coastguard Worker STATISTIC(NumNarrowLoadsPromoted, "Number of narrow loads promoted");
42*9880d681SAndroid Build Coastguard Worker STATISTIC(NumZeroStoresPromoted, "Number of narrow zero stores promoted");
43*9880d681SAndroid Build Coastguard Worker STATISTIC(NumLoadsFromStoresPromoted, "Number of loads from stores promoted");
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker // The LdStLimit limits how far we search for load/store pairs.
46*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned> LdStLimit("aarch64-load-store-scan-limit",
47*9880d681SAndroid Build Coastguard Worker cl::init(20), cl::Hidden);
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker // The UpdateLimit limits how far we search for update instructions when we form
50*9880d681SAndroid Build Coastguard Worker // pre-/post-index instructions.
51*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned> UpdateLimit("aarch64-update-scan-limit", cl::init(100),
52*9880d681SAndroid Build Coastguard Worker cl::Hidden);
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> EnableNarrowLdMerge("enable-narrow-ld-merge", cl::Hidden,
55*9880d681SAndroid Build Coastguard Worker cl::init(false),
56*9880d681SAndroid Build Coastguard Worker cl::desc("Enable narrow load merge"));
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Worker namespace llvm {
59*9880d681SAndroid Build Coastguard Worker void initializeAArch64LoadStoreOptPass(PassRegistry &);
60*9880d681SAndroid Build Coastguard Worker }
61*9880d681SAndroid Build Coastguard Worker
62*9880d681SAndroid Build Coastguard Worker #define AARCH64_LOAD_STORE_OPT_NAME "AArch64 load / store optimization pass"
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker namespace {
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker typedef struct LdStPairFlags {
67*9880d681SAndroid Build Coastguard Worker // If a matching instruction is found, MergeForward is set to true if the
68*9880d681SAndroid Build Coastguard Worker // merge is to remove the first instruction and replace the second with
69*9880d681SAndroid Build Coastguard Worker // a pair-wise insn, and false if the reverse is true.
70*9880d681SAndroid Build Coastguard Worker bool MergeForward;
71*9880d681SAndroid Build Coastguard Worker
72*9880d681SAndroid Build Coastguard Worker // SExtIdx gives the index of the result of the load pair that must be
73*9880d681SAndroid Build Coastguard Worker // extended. The value of SExtIdx assumes that the paired load produces the
74*9880d681SAndroid Build Coastguard Worker // value in this order: (I, returned iterator), i.e., -1 means no value has
75*9880d681SAndroid Build Coastguard Worker // to be extended, 0 means I, and 1 means the returned iterator.
76*9880d681SAndroid Build Coastguard Worker int SExtIdx;
77*9880d681SAndroid Build Coastguard Worker
LdStPairFlags__anondcfcb6af0111::LdStPairFlags78*9880d681SAndroid Build Coastguard Worker LdStPairFlags() : MergeForward(false), SExtIdx(-1) {}
79*9880d681SAndroid Build Coastguard Worker
setMergeForward__anondcfcb6af0111::LdStPairFlags80*9880d681SAndroid Build Coastguard Worker void setMergeForward(bool V = true) { MergeForward = V; }
getMergeForward__anondcfcb6af0111::LdStPairFlags81*9880d681SAndroid Build Coastguard Worker bool getMergeForward() const { return MergeForward; }
82*9880d681SAndroid Build Coastguard Worker
setSExtIdx__anondcfcb6af0111::LdStPairFlags83*9880d681SAndroid Build Coastguard Worker void setSExtIdx(int V) { SExtIdx = V; }
getSExtIdx__anondcfcb6af0111::LdStPairFlags84*9880d681SAndroid Build Coastguard Worker int getSExtIdx() const { return SExtIdx; }
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker } LdStPairFlags;
87*9880d681SAndroid Build Coastguard Worker
88*9880d681SAndroid Build Coastguard Worker struct AArch64LoadStoreOpt : public MachineFunctionPass {
89*9880d681SAndroid Build Coastguard Worker static char ID;
AArch64LoadStoreOpt__anondcfcb6af0111::AArch64LoadStoreOpt90*9880d681SAndroid Build Coastguard Worker AArch64LoadStoreOpt() : MachineFunctionPass(ID) {
91*9880d681SAndroid Build Coastguard Worker initializeAArch64LoadStoreOptPass(*PassRegistry::getPassRegistry());
92*9880d681SAndroid Build Coastguard Worker }
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker const AArch64InstrInfo *TII;
95*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI;
96*9880d681SAndroid Build Coastguard Worker const AArch64Subtarget *Subtarget;
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker // Track which registers have been modified and used.
99*9880d681SAndroid Build Coastguard Worker BitVector ModifiedRegs, UsedRegs;
100*9880d681SAndroid Build Coastguard Worker
101*9880d681SAndroid Build Coastguard Worker // Scan the instructions looking for a load/store that can be combined
102*9880d681SAndroid Build Coastguard Worker // with the current instruction into a load/store pair.
103*9880d681SAndroid Build Coastguard Worker // Return the matching instruction if one is found, else MBB->end().
104*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator findMatchingInsn(MachineBasicBlock::iterator I,
105*9880d681SAndroid Build Coastguard Worker LdStPairFlags &Flags,
106*9880d681SAndroid Build Coastguard Worker unsigned Limit,
107*9880d681SAndroid Build Coastguard Worker bool FindNarrowMerge);
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker // Scan the instructions looking for a store that writes to the address from
110*9880d681SAndroid Build Coastguard Worker // which the current load instruction reads. Return true if one is found.
111*9880d681SAndroid Build Coastguard Worker bool findMatchingStore(MachineBasicBlock::iterator I, unsigned Limit,
112*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator &StoreI);
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker // Merge the two instructions indicated into a wider instruction.
115*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
116*9880d681SAndroid Build Coastguard Worker mergeNarrowInsns(MachineBasicBlock::iterator I,
117*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MergeMI,
118*9880d681SAndroid Build Coastguard Worker const LdStPairFlags &Flags);
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker // Merge the two instructions indicated into a single pair-wise instruction.
121*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
122*9880d681SAndroid Build Coastguard Worker mergePairedInsns(MachineBasicBlock::iterator I,
123*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator Paired,
124*9880d681SAndroid Build Coastguard Worker const LdStPairFlags &Flags);
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Worker // Promote the load that reads directly from the address stored to.
127*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
128*9880d681SAndroid Build Coastguard Worker promoteLoadFromStore(MachineBasicBlock::iterator LoadI,
129*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator StoreI);
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker // Scan the instruction list to find a base register update that can
132*9880d681SAndroid Build Coastguard Worker // be combined with the current instruction (a load or store) using
133*9880d681SAndroid Build Coastguard Worker // pre or post indexed addressing with writeback. Scan forwards.
134*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
135*9880d681SAndroid Build Coastguard Worker findMatchingUpdateInsnForward(MachineBasicBlock::iterator I,
136*9880d681SAndroid Build Coastguard Worker int UnscaledOffset, unsigned Limit);
137*9880d681SAndroid Build Coastguard Worker
138*9880d681SAndroid Build Coastguard Worker // Scan the instruction list to find a base register update that can
139*9880d681SAndroid Build Coastguard Worker // be combined with the current instruction (a load or store) using
140*9880d681SAndroid Build Coastguard Worker // pre or post indexed addressing with writeback. Scan backwards.
141*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
142*9880d681SAndroid Build Coastguard Worker findMatchingUpdateInsnBackward(MachineBasicBlock::iterator I, unsigned Limit);
143*9880d681SAndroid Build Coastguard Worker
144*9880d681SAndroid Build Coastguard Worker // Find an instruction that updates the base register of the ld/st
145*9880d681SAndroid Build Coastguard Worker // instruction.
146*9880d681SAndroid Build Coastguard Worker bool isMatchingUpdateInsn(MachineInstr &MemMI, MachineInstr &MI,
147*9880d681SAndroid Build Coastguard Worker unsigned BaseReg, int Offset);
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker // Merge a pre- or post-index base register update into a ld/st instruction.
150*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
151*9880d681SAndroid Build Coastguard Worker mergeUpdateInsn(MachineBasicBlock::iterator I,
152*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator Update, bool IsPreIdx);
153*9880d681SAndroid Build Coastguard Worker
154*9880d681SAndroid Build Coastguard Worker // Find and merge foldable ldr/str instructions.
155*9880d681SAndroid Build Coastguard Worker bool tryToMergeLdStInst(MachineBasicBlock::iterator &MBBI);
156*9880d681SAndroid Build Coastguard Worker
157*9880d681SAndroid Build Coastguard Worker // Find and pair ldr/str instructions.
158*9880d681SAndroid Build Coastguard Worker bool tryToPairLdStInst(MachineBasicBlock::iterator &MBBI);
159*9880d681SAndroid Build Coastguard Worker
160*9880d681SAndroid Build Coastguard Worker // Find and promote load instructions which read directly from store.
161*9880d681SAndroid Build Coastguard Worker bool tryToPromoteLoadFromStore(MachineBasicBlock::iterator &MBBI);
162*9880d681SAndroid Build Coastguard Worker
163*9880d681SAndroid Build Coastguard Worker bool optimizeBlock(MachineBasicBlock &MBB, bool enableNarrowLdOpt);
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &Fn) override;
166*9880d681SAndroid Build Coastguard Worker
getRequiredProperties__anondcfcb6af0111::AArch64LoadStoreOpt167*9880d681SAndroid Build Coastguard Worker MachineFunctionProperties getRequiredProperties() const override {
168*9880d681SAndroid Build Coastguard Worker return MachineFunctionProperties().set(
169*9880d681SAndroid Build Coastguard Worker MachineFunctionProperties::Property::AllVRegsAllocated);
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker
getPassName__anondcfcb6af0111::AArch64LoadStoreOpt172*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override {
173*9880d681SAndroid Build Coastguard Worker return AARCH64_LOAD_STORE_OPT_NAME;
174*9880d681SAndroid Build Coastguard Worker }
175*9880d681SAndroid Build Coastguard Worker };
176*9880d681SAndroid Build Coastguard Worker char AArch64LoadStoreOpt::ID = 0;
177*9880d681SAndroid Build Coastguard Worker } // namespace
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(AArch64LoadStoreOpt, "aarch64-ldst-opt",
180*9880d681SAndroid Build Coastguard Worker AARCH64_LOAD_STORE_OPT_NAME, false, false)
181*9880d681SAndroid Build Coastguard Worker
getBitExtrOpcode(MachineInstr & MI)182*9880d681SAndroid Build Coastguard Worker static unsigned getBitExtrOpcode(MachineInstr &MI) {
183*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
184*9880d681SAndroid Build Coastguard Worker default:
185*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected opcode.");
186*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
187*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBBi:
188*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
189*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHHi:
190*9880d681SAndroid Build Coastguard Worker return AArch64::UBFMWri;
191*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBWui:
192*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBWi:
193*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHWui:
194*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHWi:
195*9880d681SAndroid Build Coastguard Worker return AArch64::SBFMWri;
196*9880d681SAndroid Build Coastguard Worker }
197*9880d681SAndroid Build Coastguard Worker }
198*9880d681SAndroid Build Coastguard Worker
isNarrowStore(unsigned Opc)199*9880d681SAndroid Build Coastguard Worker static bool isNarrowStore(unsigned Opc) {
200*9880d681SAndroid Build Coastguard Worker switch (Opc) {
201*9880d681SAndroid Build Coastguard Worker default:
202*9880d681SAndroid Build Coastguard Worker return false;
203*9880d681SAndroid Build Coastguard Worker case AArch64::STRBBui:
204*9880d681SAndroid Build Coastguard Worker case AArch64::STURBBi:
205*9880d681SAndroid Build Coastguard Worker case AArch64::STRHHui:
206*9880d681SAndroid Build Coastguard Worker case AArch64::STURHHi:
207*9880d681SAndroid Build Coastguard Worker return true;
208*9880d681SAndroid Build Coastguard Worker }
209*9880d681SAndroid Build Coastguard Worker }
210*9880d681SAndroid Build Coastguard Worker
isNarrowLoad(unsigned Opc)211*9880d681SAndroid Build Coastguard Worker static bool isNarrowLoad(unsigned Opc) {
212*9880d681SAndroid Build Coastguard Worker switch (Opc) {
213*9880d681SAndroid Build Coastguard Worker default:
214*9880d681SAndroid Build Coastguard Worker return false;
215*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
216*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHHi:
217*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
218*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBBi:
219*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHWui:
220*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHWi:
221*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBWui:
222*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBWi:
223*9880d681SAndroid Build Coastguard Worker return true;
224*9880d681SAndroid Build Coastguard Worker }
225*9880d681SAndroid Build Coastguard Worker }
226*9880d681SAndroid Build Coastguard Worker
isNarrowLoad(MachineInstr & MI)227*9880d681SAndroid Build Coastguard Worker static bool isNarrowLoad(MachineInstr &MI) {
228*9880d681SAndroid Build Coastguard Worker return isNarrowLoad(MI.getOpcode());
229*9880d681SAndroid Build Coastguard Worker }
230*9880d681SAndroid Build Coastguard Worker
isNarrowLoadOrStore(unsigned Opc)231*9880d681SAndroid Build Coastguard Worker static bool isNarrowLoadOrStore(unsigned Opc) {
232*9880d681SAndroid Build Coastguard Worker return isNarrowLoad(Opc) || isNarrowStore(Opc);
233*9880d681SAndroid Build Coastguard Worker }
234*9880d681SAndroid Build Coastguard Worker
235*9880d681SAndroid Build Coastguard Worker // Scaling factor for unscaled load or store.
getMemScale(MachineInstr & MI)236*9880d681SAndroid Build Coastguard Worker static int getMemScale(MachineInstr &MI) {
237*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
238*9880d681SAndroid Build Coastguard Worker default:
239*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Opcode has unknown scale!");
240*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
241*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBBi:
242*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBWui:
243*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBWi:
244*9880d681SAndroid Build Coastguard Worker case AArch64::STRBBui:
245*9880d681SAndroid Build Coastguard Worker case AArch64::STURBBi:
246*9880d681SAndroid Build Coastguard Worker return 1;
247*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
248*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHHi:
249*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHWui:
250*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHWi:
251*9880d681SAndroid Build Coastguard Worker case AArch64::STRHHui:
252*9880d681SAndroid Build Coastguard Worker case AArch64::STURHHi:
253*9880d681SAndroid Build Coastguard Worker return 2;
254*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSui:
255*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSi:
256*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWui:
257*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSWi:
258*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
259*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
260*9880d681SAndroid Build Coastguard Worker case AArch64::STRSui:
261*9880d681SAndroid Build Coastguard Worker case AArch64::STURSi:
262*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
263*9880d681SAndroid Build Coastguard Worker case AArch64::STURWi:
264*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSi:
265*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSWi:
266*9880d681SAndroid Build Coastguard Worker case AArch64::LDPWi:
267*9880d681SAndroid Build Coastguard Worker case AArch64::STPSi:
268*9880d681SAndroid Build Coastguard Worker case AArch64::STPWi:
269*9880d681SAndroid Build Coastguard Worker return 4;
270*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDui:
271*9880d681SAndroid Build Coastguard Worker case AArch64::LDURDi:
272*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
273*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi:
274*9880d681SAndroid Build Coastguard Worker case AArch64::STRDui:
275*9880d681SAndroid Build Coastguard Worker case AArch64::STURDi:
276*9880d681SAndroid Build Coastguard Worker case AArch64::STRXui:
277*9880d681SAndroid Build Coastguard Worker case AArch64::STURXi:
278*9880d681SAndroid Build Coastguard Worker case AArch64::LDPDi:
279*9880d681SAndroid Build Coastguard Worker case AArch64::LDPXi:
280*9880d681SAndroid Build Coastguard Worker case AArch64::STPDi:
281*9880d681SAndroid Build Coastguard Worker case AArch64::STPXi:
282*9880d681SAndroid Build Coastguard Worker return 8;
283*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
284*9880d681SAndroid Build Coastguard Worker case AArch64::LDURQi:
285*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
286*9880d681SAndroid Build Coastguard Worker case AArch64::STURQi:
287*9880d681SAndroid Build Coastguard Worker case AArch64::LDPQi:
288*9880d681SAndroid Build Coastguard Worker case AArch64::STPQi:
289*9880d681SAndroid Build Coastguard Worker return 16;
290*9880d681SAndroid Build Coastguard Worker }
291*9880d681SAndroid Build Coastguard Worker }
292*9880d681SAndroid Build Coastguard Worker
getMatchingNonSExtOpcode(unsigned Opc,bool * IsValidLdStrOpc=nullptr)293*9880d681SAndroid Build Coastguard Worker static unsigned getMatchingNonSExtOpcode(unsigned Opc,
294*9880d681SAndroid Build Coastguard Worker bool *IsValidLdStrOpc = nullptr) {
295*9880d681SAndroid Build Coastguard Worker if (IsValidLdStrOpc)
296*9880d681SAndroid Build Coastguard Worker *IsValidLdStrOpc = true;
297*9880d681SAndroid Build Coastguard Worker switch (Opc) {
298*9880d681SAndroid Build Coastguard Worker default:
299*9880d681SAndroid Build Coastguard Worker if (IsValidLdStrOpc)
300*9880d681SAndroid Build Coastguard Worker *IsValidLdStrOpc = false;
301*9880d681SAndroid Build Coastguard Worker return UINT_MAX;
302*9880d681SAndroid Build Coastguard Worker case AArch64::STRDui:
303*9880d681SAndroid Build Coastguard Worker case AArch64::STURDi:
304*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
305*9880d681SAndroid Build Coastguard Worker case AArch64::STURQi:
306*9880d681SAndroid Build Coastguard Worker case AArch64::STRBBui:
307*9880d681SAndroid Build Coastguard Worker case AArch64::STURBBi:
308*9880d681SAndroid Build Coastguard Worker case AArch64::STRHHui:
309*9880d681SAndroid Build Coastguard Worker case AArch64::STURHHi:
310*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
311*9880d681SAndroid Build Coastguard Worker case AArch64::STURWi:
312*9880d681SAndroid Build Coastguard Worker case AArch64::STRXui:
313*9880d681SAndroid Build Coastguard Worker case AArch64::STURXi:
314*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDui:
315*9880d681SAndroid Build Coastguard Worker case AArch64::LDURDi:
316*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
317*9880d681SAndroid Build Coastguard Worker case AArch64::LDURQi:
318*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
319*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
320*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
321*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi:
322*9880d681SAndroid Build Coastguard Worker case AArch64::STRSui:
323*9880d681SAndroid Build Coastguard Worker case AArch64::STURSi:
324*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSui:
325*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSi:
326*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
327*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHHi:
328*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
329*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBBi:
330*9880d681SAndroid Build Coastguard Worker return Opc;
331*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWui:
332*9880d681SAndroid Build Coastguard Worker return AArch64::LDRWui;
333*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSWi:
334*9880d681SAndroid Build Coastguard Worker return AArch64::LDURWi;
335*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBWui:
336*9880d681SAndroid Build Coastguard Worker return AArch64::LDRBBui;
337*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHWui:
338*9880d681SAndroid Build Coastguard Worker return AArch64::LDRHHui;
339*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBWi:
340*9880d681SAndroid Build Coastguard Worker return AArch64::LDURBBi;
341*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHWi:
342*9880d681SAndroid Build Coastguard Worker return AArch64::LDURHHi;
343*9880d681SAndroid Build Coastguard Worker }
344*9880d681SAndroid Build Coastguard Worker }
345*9880d681SAndroid Build Coastguard Worker
getMatchingWideOpcode(unsigned Opc)346*9880d681SAndroid Build Coastguard Worker static unsigned getMatchingWideOpcode(unsigned Opc) {
347*9880d681SAndroid Build Coastguard Worker switch (Opc) {
348*9880d681SAndroid Build Coastguard Worker default:
349*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Opcode has no wide equivalent!");
350*9880d681SAndroid Build Coastguard Worker case AArch64::STRBBui:
351*9880d681SAndroid Build Coastguard Worker return AArch64::STRHHui;
352*9880d681SAndroid Build Coastguard Worker case AArch64::STRHHui:
353*9880d681SAndroid Build Coastguard Worker return AArch64::STRWui;
354*9880d681SAndroid Build Coastguard Worker case AArch64::STURBBi:
355*9880d681SAndroid Build Coastguard Worker return AArch64::STURHHi;
356*9880d681SAndroid Build Coastguard Worker case AArch64::STURHHi:
357*9880d681SAndroid Build Coastguard Worker return AArch64::STURWi;
358*9880d681SAndroid Build Coastguard Worker case AArch64::STURWi:
359*9880d681SAndroid Build Coastguard Worker return AArch64::STURXi;
360*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
361*9880d681SAndroid Build Coastguard Worker return AArch64::STRXui;
362*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
363*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSHWui:
364*9880d681SAndroid Build Coastguard Worker return AArch64::LDRWui;
365*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHHi:
366*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSHWi:
367*9880d681SAndroid Build Coastguard Worker return AArch64::LDURWi;
368*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
369*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSBWui:
370*9880d681SAndroid Build Coastguard Worker return AArch64::LDRHHui;
371*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBBi:
372*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSBWi:
373*9880d681SAndroid Build Coastguard Worker return AArch64::LDURHHi;
374*9880d681SAndroid Build Coastguard Worker }
375*9880d681SAndroid Build Coastguard Worker }
376*9880d681SAndroid Build Coastguard Worker
getMatchingPairOpcode(unsigned Opc)377*9880d681SAndroid Build Coastguard Worker static unsigned getMatchingPairOpcode(unsigned Opc) {
378*9880d681SAndroid Build Coastguard Worker switch (Opc) {
379*9880d681SAndroid Build Coastguard Worker default:
380*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Opcode has no pairwise equivalent!");
381*9880d681SAndroid Build Coastguard Worker case AArch64::STRSui:
382*9880d681SAndroid Build Coastguard Worker case AArch64::STURSi:
383*9880d681SAndroid Build Coastguard Worker return AArch64::STPSi;
384*9880d681SAndroid Build Coastguard Worker case AArch64::STRDui:
385*9880d681SAndroid Build Coastguard Worker case AArch64::STURDi:
386*9880d681SAndroid Build Coastguard Worker return AArch64::STPDi;
387*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
388*9880d681SAndroid Build Coastguard Worker case AArch64::STURQi:
389*9880d681SAndroid Build Coastguard Worker return AArch64::STPQi;
390*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
391*9880d681SAndroid Build Coastguard Worker case AArch64::STURWi:
392*9880d681SAndroid Build Coastguard Worker return AArch64::STPWi;
393*9880d681SAndroid Build Coastguard Worker case AArch64::STRXui:
394*9880d681SAndroid Build Coastguard Worker case AArch64::STURXi:
395*9880d681SAndroid Build Coastguard Worker return AArch64::STPXi;
396*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSui:
397*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSi:
398*9880d681SAndroid Build Coastguard Worker return AArch64::LDPSi;
399*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDui:
400*9880d681SAndroid Build Coastguard Worker case AArch64::LDURDi:
401*9880d681SAndroid Build Coastguard Worker return AArch64::LDPDi;
402*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
403*9880d681SAndroid Build Coastguard Worker case AArch64::LDURQi:
404*9880d681SAndroid Build Coastguard Worker return AArch64::LDPQi;
405*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
406*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
407*9880d681SAndroid Build Coastguard Worker return AArch64::LDPWi;
408*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
409*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi:
410*9880d681SAndroid Build Coastguard Worker return AArch64::LDPXi;
411*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWui:
412*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSWi:
413*9880d681SAndroid Build Coastguard Worker return AArch64::LDPSWi;
414*9880d681SAndroid Build Coastguard Worker }
415*9880d681SAndroid Build Coastguard Worker }
416*9880d681SAndroid Build Coastguard Worker
isMatchingStore(MachineInstr & LoadInst,MachineInstr & StoreInst)417*9880d681SAndroid Build Coastguard Worker static unsigned isMatchingStore(MachineInstr &LoadInst,
418*9880d681SAndroid Build Coastguard Worker MachineInstr &StoreInst) {
419*9880d681SAndroid Build Coastguard Worker unsigned LdOpc = LoadInst.getOpcode();
420*9880d681SAndroid Build Coastguard Worker unsigned StOpc = StoreInst.getOpcode();
421*9880d681SAndroid Build Coastguard Worker switch (LdOpc) {
422*9880d681SAndroid Build Coastguard Worker default:
423*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unsupported load instruction!");
424*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
425*9880d681SAndroid Build Coastguard Worker return StOpc == AArch64::STRBBui || StOpc == AArch64::STRHHui ||
426*9880d681SAndroid Build Coastguard Worker StOpc == AArch64::STRWui || StOpc == AArch64::STRXui;
427*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBBi:
428*9880d681SAndroid Build Coastguard Worker return StOpc == AArch64::STURBBi || StOpc == AArch64::STURHHi ||
429*9880d681SAndroid Build Coastguard Worker StOpc == AArch64::STURWi || StOpc == AArch64::STURXi;
430*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
431*9880d681SAndroid Build Coastguard Worker return StOpc == AArch64::STRHHui || StOpc == AArch64::STRWui ||
432*9880d681SAndroid Build Coastguard Worker StOpc == AArch64::STRXui;
433*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHHi:
434*9880d681SAndroid Build Coastguard Worker return StOpc == AArch64::STURHHi || StOpc == AArch64::STURWi ||
435*9880d681SAndroid Build Coastguard Worker StOpc == AArch64::STURXi;
436*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
437*9880d681SAndroid Build Coastguard Worker return StOpc == AArch64::STRWui || StOpc == AArch64::STRXui;
438*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
439*9880d681SAndroid Build Coastguard Worker return StOpc == AArch64::STURWi || StOpc == AArch64::STURXi;
440*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
441*9880d681SAndroid Build Coastguard Worker return StOpc == AArch64::STRXui;
442*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi:
443*9880d681SAndroid Build Coastguard Worker return StOpc == AArch64::STURXi;
444*9880d681SAndroid Build Coastguard Worker }
445*9880d681SAndroid Build Coastguard Worker }
446*9880d681SAndroid Build Coastguard Worker
getPreIndexedOpcode(unsigned Opc)447*9880d681SAndroid Build Coastguard Worker static unsigned getPreIndexedOpcode(unsigned Opc) {
448*9880d681SAndroid Build Coastguard Worker switch (Opc) {
449*9880d681SAndroid Build Coastguard Worker default:
450*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Opcode has no pre-indexed equivalent!");
451*9880d681SAndroid Build Coastguard Worker case AArch64::STRSui:
452*9880d681SAndroid Build Coastguard Worker return AArch64::STRSpre;
453*9880d681SAndroid Build Coastguard Worker case AArch64::STRDui:
454*9880d681SAndroid Build Coastguard Worker return AArch64::STRDpre;
455*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
456*9880d681SAndroid Build Coastguard Worker return AArch64::STRQpre;
457*9880d681SAndroid Build Coastguard Worker case AArch64::STRBBui:
458*9880d681SAndroid Build Coastguard Worker return AArch64::STRBBpre;
459*9880d681SAndroid Build Coastguard Worker case AArch64::STRHHui:
460*9880d681SAndroid Build Coastguard Worker return AArch64::STRHHpre;
461*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
462*9880d681SAndroid Build Coastguard Worker return AArch64::STRWpre;
463*9880d681SAndroid Build Coastguard Worker case AArch64::STRXui:
464*9880d681SAndroid Build Coastguard Worker return AArch64::STRXpre;
465*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSui:
466*9880d681SAndroid Build Coastguard Worker return AArch64::LDRSpre;
467*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDui:
468*9880d681SAndroid Build Coastguard Worker return AArch64::LDRDpre;
469*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
470*9880d681SAndroid Build Coastguard Worker return AArch64::LDRQpre;
471*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
472*9880d681SAndroid Build Coastguard Worker return AArch64::LDRBBpre;
473*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
474*9880d681SAndroid Build Coastguard Worker return AArch64::LDRHHpre;
475*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
476*9880d681SAndroid Build Coastguard Worker return AArch64::LDRWpre;
477*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
478*9880d681SAndroid Build Coastguard Worker return AArch64::LDRXpre;
479*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWui:
480*9880d681SAndroid Build Coastguard Worker return AArch64::LDRSWpre;
481*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSi:
482*9880d681SAndroid Build Coastguard Worker return AArch64::LDPSpre;
483*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSWi:
484*9880d681SAndroid Build Coastguard Worker return AArch64::LDPSWpre;
485*9880d681SAndroid Build Coastguard Worker case AArch64::LDPDi:
486*9880d681SAndroid Build Coastguard Worker return AArch64::LDPDpre;
487*9880d681SAndroid Build Coastguard Worker case AArch64::LDPQi:
488*9880d681SAndroid Build Coastguard Worker return AArch64::LDPQpre;
489*9880d681SAndroid Build Coastguard Worker case AArch64::LDPWi:
490*9880d681SAndroid Build Coastguard Worker return AArch64::LDPWpre;
491*9880d681SAndroid Build Coastguard Worker case AArch64::LDPXi:
492*9880d681SAndroid Build Coastguard Worker return AArch64::LDPXpre;
493*9880d681SAndroid Build Coastguard Worker case AArch64::STPSi:
494*9880d681SAndroid Build Coastguard Worker return AArch64::STPSpre;
495*9880d681SAndroid Build Coastguard Worker case AArch64::STPDi:
496*9880d681SAndroid Build Coastguard Worker return AArch64::STPDpre;
497*9880d681SAndroid Build Coastguard Worker case AArch64::STPQi:
498*9880d681SAndroid Build Coastguard Worker return AArch64::STPQpre;
499*9880d681SAndroid Build Coastguard Worker case AArch64::STPWi:
500*9880d681SAndroid Build Coastguard Worker return AArch64::STPWpre;
501*9880d681SAndroid Build Coastguard Worker case AArch64::STPXi:
502*9880d681SAndroid Build Coastguard Worker return AArch64::STPXpre;
503*9880d681SAndroid Build Coastguard Worker }
504*9880d681SAndroid Build Coastguard Worker }
505*9880d681SAndroid Build Coastguard Worker
getPostIndexedOpcode(unsigned Opc)506*9880d681SAndroid Build Coastguard Worker static unsigned getPostIndexedOpcode(unsigned Opc) {
507*9880d681SAndroid Build Coastguard Worker switch (Opc) {
508*9880d681SAndroid Build Coastguard Worker default:
509*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Opcode has no post-indexed wise equivalent!");
510*9880d681SAndroid Build Coastguard Worker case AArch64::STRSui:
511*9880d681SAndroid Build Coastguard Worker return AArch64::STRSpost;
512*9880d681SAndroid Build Coastguard Worker case AArch64::STRDui:
513*9880d681SAndroid Build Coastguard Worker return AArch64::STRDpost;
514*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
515*9880d681SAndroid Build Coastguard Worker return AArch64::STRQpost;
516*9880d681SAndroid Build Coastguard Worker case AArch64::STRBBui:
517*9880d681SAndroid Build Coastguard Worker return AArch64::STRBBpost;
518*9880d681SAndroid Build Coastguard Worker case AArch64::STRHHui:
519*9880d681SAndroid Build Coastguard Worker return AArch64::STRHHpost;
520*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
521*9880d681SAndroid Build Coastguard Worker return AArch64::STRWpost;
522*9880d681SAndroid Build Coastguard Worker case AArch64::STRXui:
523*9880d681SAndroid Build Coastguard Worker return AArch64::STRXpost;
524*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSui:
525*9880d681SAndroid Build Coastguard Worker return AArch64::LDRSpost;
526*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDui:
527*9880d681SAndroid Build Coastguard Worker return AArch64::LDRDpost;
528*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
529*9880d681SAndroid Build Coastguard Worker return AArch64::LDRQpost;
530*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
531*9880d681SAndroid Build Coastguard Worker return AArch64::LDRBBpost;
532*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
533*9880d681SAndroid Build Coastguard Worker return AArch64::LDRHHpost;
534*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
535*9880d681SAndroid Build Coastguard Worker return AArch64::LDRWpost;
536*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
537*9880d681SAndroid Build Coastguard Worker return AArch64::LDRXpost;
538*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWui:
539*9880d681SAndroid Build Coastguard Worker return AArch64::LDRSWpost;
540*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSi:
541*9880d681SAndroid Build Coastguard Worker return AArch64::LDPSpost;
542*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSWi:
543*9880d681SAndroid Build Coastguard Worker return AArch64::LDPSWpost;
544*9880d681SAndroid Build Coastguard Worker case AArch64::LDPDi:
545*9880d681SAndroid Build Coastguard Worker return AArch64::LDPDpost;
546*9880d681SAndroid Build Coastguard Worker case AArch64::LDPQi:
547*9880d681SAndroid Build Coastguard Worker return AArch64::LDPQpost;
548*9880d681SAndroid Build Coastguard Worker case AArch64::LDPWi:
549*9880d681SAndroid Build Coastguard Worker return AArch64::LDPWpost;
550*9880d681SAndroid Build Coastguard Worker case AArch64::LDPXi:
551*9880d681SAndroid Build Coastguard Worker return AArch64::LDPXpost;
552*9880d681SAndroid Build Coastguard Worker case AArch64::STPSi:
553*9880d681SAndroid Build Coastguard Worker return AArch64::STPSpost;
554*9880d681SAndroid Build Coastguard Worker case AArch64::STPDi:
555*9880d681SAndroid Build Coastguard Worker return AArch64::STPDpost;
556*9880d681SAndroid Build Coastguard Worker case AArch64::STPQi:
557*9880d681SAndroid Build Coastguard Worker return AArch64::STPQpost;
558*9880d681SAndroid Build Coastguard Worker case AArch64::STPWi:
559*9880d681SAndroid Build Coastguard Worker return AArch64::STPWpost;
560*9880d681SAndroid Build Coastguard Worker case AArch64::STPXi:
561*9880d681SAndroid Build Coastguard Worker return AArch64::STPXpost;
562*9880d681SAndroid Build Coastguard Worker }
563*9880d681SAndroid Build Coastguard Worker }
564*9880d681SAndroid Build Coastguard Worker
isPairedLdSt(const MachineInstr & MI)565*9880d681SAndroid Build Coastguard Worker static bool isPairedLdSt(const MachineInstr &MI) {
566*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
567*9880d681SAndroid Build Coastguard Worker default:
568*9880d681SAndroid Build Coastguard Worker return false;
569*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSi:
570*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSWi:
571*9880d681SAndroid Build Coastguard Worker case AArch64::LDPDi:
572*9880d681SAndroid Build Coastguard Worker case AArch64::LDPQi:
573*9880d681SAndroid Build Coastguard Worker case AArch64::LDPWi:
574*9880d681SAndroid Build Coastguard Worker case AArch64::LDPXi:
575*9880d681SAndroid Build Coastguard Worker case AArch64::STPSi:
576*9880d681SAndroid Build Coastguard Worker case AArch64::STPDi:
577*9880d681SAndroid Build Coastguard Worker case AArch64::STPQi:
578*9880d681SAndroid Build Coastguard Worker case AArch64::STPWi:
579*9880d681SAndroid Build Coastguard Worker case AArch64::STPXi:
580*9880d681SAndroid Build Coastguard Worker return true;
581*9880d681SAndroid Build Coastguard Worker }
582*9880d681SAndroid Build Coastguard Worker }
583*9880d681SAndroid Build Coastguard Worker
getLdStRegOp(const MachineInstr & MI,unsigned PairedRegOp=0)584*9880d681SAndroid Build Coastguard Worker static const MachineOperand &getLdStRegOp(const MachineInstr &MI,
585*9880d681SAndroid Build Coastguard Worker unsigned PairedRegOp = 0) {
586*9880d681SAndroid Build Coastguard Worker assert(PairedRegOp < 2 && "Unexpected register operand idx.");
587*9880d681SAndroid Build Coastguard Worker unsigned Idx = isPairedLdSt(MI) ? PairedRegOp : 0;
588*9880d681SAndroid Build Coastguard Worker return MI.getOperand(Idx);
589*9880d681SAndroid Build Coastguard Worker }
590*9880d681SAndroid Build Coastguard Worker
getLdStBaseOp(const MachineInstr & MI)591*9880d681SAndroid Build Coastguard Worker static const MachineOperand &getLdStBaseOp(const MachineInstr &MI) {
592*9880d681SAndroid Build Coastguard Worker unsigned Idx = isPairedLdSt(MI) ? 2 : 1;
593*9880d681SAndroid Build Coastguard Worker return MI.getOperand(Idx);
594*9880d681SAndroid Build Coastguard Worker }
595*9880d681SAndroid Build Coastguard Worker
getLdStOffsetOp(const MachineInstr & MI)596*9880d681SAndroid Build Coastguard Worker static const MachineOperand &getLdStOffsetOp(const MachineInstr &MI) {
597*9880d681SAndroid Build Coastguard Worker unsigned Idx = isPairedLdSt(MI) ? 3 : 2;
598*9880d681SAndroid Build Coastguard Worker return MI.getOperand(Idx);
599*9880d681SAndroid Build Coastguard Worker }
600*9880d681SAndroid Build Coastguard Worker
isLdOffsetInRangeOfSt(MachineInstr & LoadInst,MachineInstr & StoreInst,const AArch64InstrInfo * TII)601*9880d681SAndroid Build Coastguard Worker static bool isLdOffsetInRangeOfSt(MachineInstr &LoadInst,
602*9880d681SAndroid Build Coastguard Worker MachineInstr &StoreInst,
603*9880d681SAndroid Build Coastguard Worker const AArch64InstrInfo *TII) {
604*9880d681SAndroid Build Coastguard Worker assert(isMatchingStore(LoadInst, StoreInst) && "Expect only matched ld/st.");
605*9880d681SAndroid Build Coastguard Worker int LoadSize = getMemScale(LoadInst);
606*9880d681SAndroid Build Coastguard Worker int StoreSize = getMemScale(StoreInst);
607*9880d681SAndroid Build Coastguard Worker int UnscaledStOffset = TII->isUnscaledLdSt(StoreInst)
608*9880d681SAndroid Build Coastguard Worker ? getLdStOffsetOp(StoreInst).getImm()
609*9880d681SAndroid Build Coastguard Worker : getLdStOffsetOp(StoreInst).getImm() * StoreSize;
610*9880d681SAndroid Build Coastguard Worker int UnscaledLdOffset = TII->isUnscaledLdSt(LoadInst)
611*9880d681SAndroid Build Coastguard Worker ? getLdStOffsetOp(LoadInst).getImm()
612*9880d681SAndroid Build Coastguard Worker : getLdStOffsetOp(LoadInst).getImm() * LoadSize;
613*9880d681SAndroid Build Coastguard Worker return (UnscaledStOffset <= UnscaledLdOffset) &&
614*9880d681SAndroid Build Coastguard Worker (UnscaledLdOffset + LoadSize <= (UnscaledStOffset + StoreSize));
615*9880d681SAndroid Build Coastguard Worker }
616*9880d681SAndroid Build Coastguard Worker
isPromotableZeroStoreOpcode(unsigned Opc)617*9880d681SAndroid Build Coastguard Worker static bool isPromotableZeroStoreOpcode(unsigned Opc) {
618*9880d681SAndroid Build Coastguard Worker return isNarrowStore(Opc) || Opc == AArch64::STRWui || Opc == AArch64::STURWi;
619*9880d681SAndroid Build Coastguard Worker }
620*9880d681SAndroid Build Coastguard Worker
isPromotableZeroStoreOpcode(MachineInstr & MI)621*9880d681SAndroid Build Coastguard Worker static bool isPromotableZeroStoreOpcode(MachineInstr &MI) {
622*9880d681SAndroid Build Coastguard Worker return isPromotableZeroStoreOpcode(MI.getOpcode());
623*9880d681SAndroid Build Coastguard Worker }
624*9880d681SAndroid Build Coastguard Worker
isPromotableZeroStoreInst(MachineInstr & MI)625*9880d681SAndroid Build Coastguard Worker static bool isPromotableZeroStoreInst(MachineInstr &MI) {
626*9880d681SAndroid Build Coastguard Worker return (isPromotableZeroStoreOpcode(MI)) &&
627*9880d681SAndroid Build Coastguard Worker getLdStRegOp(MI).getReg() == AArch64::WZR;
628*9880d681SAndroid Build Coastguard Worker }
629*9880d681SAndroid Build Coastguard Worker
630*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
mergeNarrowInsns(MachineBasicBlock::iterator I,MachineBasicBlock::iterator MergeMI,const LdStPairFlags & Flags)631*9880d681SAndroid Build Coastguard Worker AArch64LoadStoreOpt::mergeNarrowInsns(MachineBasicBlock::iterator I,
632*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MergeMI,
633*9880d681SAndroid Build Coastguard Worker const LdStPairFlags &Flags) {
634*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NextI = I;
635*9880d681SAndroid Build Coastguard Worker ++NextI;
636*9880d681SAndroid Build Coastguard Worker // If NextI is the second of the two instructions to be merged, we need
637*9880d681SAndroid Build Coastguard Worker // to skip one further. Either way we merge will invalidate the iterator,
638*9880d681SAndroid Build Coastguard Worker // and we don't need to scan the new instruction, as it's a pairwise
639*9880d681SAndroid Build Coastguard Worker // instruction, which we're not considering for further action anyway.
640*9880d681SAndroid Build Coastguard Worker if (NextI == MergeMI)
641*9880d681SAndroid Build Coastguard Worker ++NextI;
642*9880d681SAndroid Build Coastguard Worker
643*9880d681SAndroid Build Coastguard Worker unsigned Opc = I->getOpcode();
644*9880d681SAndroid Build Coastguard Worker bool IsScaled = !TII->isUnscaledLdSt(Opc);
645*9880d681SAndroid Build Coastguard Worker int OffsetStride = IsScaled ? 1 : getMemScale(*I);
646*9880d681SAndroid Build Coastguard Worker
647*9880d681SAndroid Build Coastguard Worker bool MergeForward = Flags.getMergeForward();
648*9880d681SAndroid Build Coastguard Worker // Insert our new paired instruction after whichever of the paired
649*9880d681SAndroid Build Coastguard Worker // instructions MergeForward indicates.
650*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator InsertionPoint = MergeForward ? MergeMI : I;
651*9880d681SAndroid Build Coastguard Worker // Also based on MergeForward is from where we copy the base register operand
652*9880d681SAndroid Build Coastguard Worker // so we get the flags compatible with the input code.
653*9880d681SAndroid Build Coastguard Worker const MachineOperand &BaseRegOp =
654*9880d681SAndroid Build Coastguard Worker MergeForward ? getLdStBaseOp(*MergeMI) : getLdStBaseOp(*I);
655*9880d681SAndroid Build Coastguard Worker
656*9880d681SAndroid Build Coastguard Worker // Which register is Rt and which is Rt2 depends on the offset order.
657*9880d681SAndroid Build Coastguard Worker MachineInstr *RtMI, *Rt2MI;
658*9880d681SAndroid Build Coastguard Worker if (getLdStOffsetOp(*I).getImm() ==
659*9880d681SAndroid Build Coastguard Worker getLdStOffsetOp(*MergeMI).getImm() + OffsetStride) {
660*9880d681SAndroid Build Coastguard Worker RtMI = &*MergeMI;
661*9880d681SAndroid Build Coastguard Worker Rt2MI = &*I;
662*9880d681SAndroid Build Coastguard Worker } else {
663*9880d681SAndroid Build Coastguard Worker RtMI = &*I;
664*9880d681SAndroid Build Coastguard Worker Rt2MI = &*MergeMI;
665*9880d681SAndroid Build Coastguard Worker }
666*9880d681SAndroid Build Coastguard Worker
667*9880d681SAndroid Build Coastguard Worker int OffsetImm = getLdStOffsetOp(*RtMI).getImm();
668*9880d681SAndroid Build Coastguard Worker // Change the scaled offset from small to large type.
669*9880d681SAndroid Build Coastguard Worker if (IsScaled) {
670*9880d681SAndroid Build Coastguard Worker assert(((OffsetImm & 1) == 0) && "Unexpected offset to merge");
671*9880d681SAndroid Build Coastguard Worker OffsetImm /= 2;
672*9880d681SAndroid Build Coastguard Worker }
673*9880d681SAndroid Build Coastguard Worker
674*9880d681SAndroid Build Coastguard Worker DebugLoc DL = I->getDebugLoc();
675*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = I->getParent();
676*9880d681SAndroid Build Coastguard Worker if (isNarrowLoad(Opc)) {
677*9880d681SAndroid Build Coastguard Worker MachineInstr *RtNewDest = &*(MergeForward ? I : MergeMI);
678*9880d681SAndroid Build Coastguard Worker // When merging small (< 32 bit) loads for big-endian targets, the order of
679*9880d681SAndroid Build Coastguard Worker // the component parts gets swapped.
680*9880d681SAndroid Build Coastguard Worker if (!Subtarget->isLittleEndian())
681*9880d681SAndroid Build Coastguard Worker std::swap(RtMI, Rt2MI);
682*9880d681SAndroid Build Coastguard Worker // Construct the new load instruction.
683*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMemMI, *BitExtMI1, *BitExtMI2;
684*9880d681SAndroid Build Coastguard Worker NewMemMI =
685*9880d681SAndroid Build Coastguard Worker BuildMI(*MBB, InsertionPoint, DL, TII->get(getMatchingWideOpcode(Opc)))
686*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*RtNewDest))
687*9880d681SAndroid Build Coastguard Worker .addOperand(BaseRegOp)
688*9880d681SAndroid Build Coastguard Worker .addImm(OffsetImm)
689*9880d681SAndroid Build Coastguard Worker .setMemRefs(I->mergeMemRefsWith(*MergeMI));
690*9880d681SAndroid Build Coastguard Worker (void)NewMemMI;
691*9880d681SAndroid Build Coastguard Worker
692*9880d681SAndroid Build Coastguard Worker DEBUG(
693*9880d681SAndroid Build Coastguard Worker dbgs()
694*9880d681SAndroid Build Coastguard Worker << "Creating the new load and extract. Replacing instructions:\n ");
695*9880d681SAndroid Build Coastguard Worker DEBUG(I->print(dbgs()));
696*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " ");
697*9880d681SAndroid Build Coastguard Worker DEBUG(MergeMI->print(dbgs()));
698*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " with instructions:\n ");
699*9880d681SAndroid Build Coastguard Worker DEBUG((NewMemMI)->print(dbgs()));
700*9880d681SAndroid Build Coastguard Worker
701*9880d681SAndroid Build Coastguard Worker int Width = getMemScale(*I) == 1 ? 8 : 16;
702*9880d681SAndroid Build Coastguard Worker int LSBLow = 0;
703*9880d681SAndroid Build Coastguard Worker int LSBHigh = Width;
704*9880d681SAndroid Build Coastguard Worker int ImmsLow = LSBLow + Width - 1;
705*9880d681SAndroid Build Coastguard Worker int ImmsHigh = LSBHigh + Width - 1;
706*9880d681SAndroid Build Coastguard Worker MachineInstr *ExtDestMI = &*(MergeForward ? MergeMI : I);
707*9880d681SAndroid Build Coastguard Worker if ((ExtDestMI == Rt2MI) == Subtarget->isLittleEndian()) {
708*9880d681SAndroid Build Coastguard Worker // Create the bitfield extract for high bits.
709*9880d681SAndroid Build Coastguard Worker BitExtMI1 =
710*9880d681SAndroid Build Coastguard Worker BuildMI(*MBB, InsertionPoint, DL, TII->get(getBitExtrOpcode(*Rt2MI)))
711*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*Rt2MI))
712*9880d681SAndroid Build Coastguard Worker .addReg(getLdStRegOp(*RtNewDest).getReg())
713*9880d681SAndroid Build Coastguard Worker .addImm(LSBHigh)
714*9880d681SAndroid Build Coastguard Worker .addImm(ImmsHigh);
715*9880d681SAndroid Build Coastguard Worker // Create the bitfield extract for low bits.
716*9880d681SAndroid Build Coastguard Worker if (RtMI->getOpcode() == getMatchingNonSExtOpcode(RtMI->getOpcode())) {
717*9880d681SAndroid Build Coastguard Worker // For unsigned, prefer to use AND for low bits.
718*9880d681SAndroid Build Coastguard Worker BitExtMI2 = BuildMI(*MBB, InsertionPoint, DL, TII->get(AArch64::ANDWri))
719*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*RtMI))
720*9880d681SAndroid Build Coastguard Worker .addReg(getLdStRegOp(*RtNewDest).getReg())
721*9880d681SAndroid Build Coastguard Worker .addImm(ImmsLow);
722*9880d681SAndroid Build Coastguard Worker } else {
723*9880d681SAndroid Build Coastguard Worker BitExtMI2 =
724*9880d681SAndroid Build Coastguard Worker BuildMI(*MBB, InsertionPoint, DL, TII->get(getBitExtrOpcode(*RtMI)))
725*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*RtMI))
726*9880d681SAndroid Build Coastguard Worker .addReg(getLdStRegOp(*RtNewDest).getReg())
727*9880d681SAndroid Build Coastguard Worker .addImm(LSBLow)
728*9880d681SAndroid Build Coastguard Worker .addImm(ImmsLow);
729*9880d681SAndroid Build Coastguard Worker }
730*9880d681SAndroid Build Coastguard Worker } else {
731*9880d681SAndroid Build Coastguard Worker // Create the bitfield extract for low bits.
732*9880d681SAndroid Build Coastguard Worker if (RtMI->getOpcode() == getMatchingNonSExtOpcode(RtMI->getOpcode())) {
733*9880d681SAndroid Build Coastguard Worker // For unsigned, prefer to use AND for low bits.
734*9880d681SAndroid Build Coastguard Worker BitExtMI1 = BuildMI(*MBB, InsertionPoint, DL, TII->get(AArch64::ANDWri))
735*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*RtMI))
736*9880d681SAndroid Build Coastguard Worker .addReg(getLdStRegOp(*RtNewDest).getReg())
737*9880d681SAndroid Build Coastguard Worker .addImm(ImmsLow);
738*9880d681SAndroid Build Coastguard Worker } else {
739*9880d681SAndroid Build Coastguard Worker BitExtMI1 =
740*9880d681SAndroid Build Coastguard Worker BuildMI(*MBB, InsertionPoint, DL, TII->get(getBitExtrOpcode(*RtMI)))
741*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*RtMI))
742*9880d681SAndroid Build Coastguard Worker .addReg(getLdStRegOp(*RtNewDest).getReg())
743*9880d681SAndroid Build Coastguard Worker .addImm(LSBLow)
744*9880d681SAndroid Build Coastguard Worker .addImm(ImmsLow);
745*9880d681SAndroid Build Coastguard Worker }
746*9880d681SAndroid Build Coastguard Worker
747*9880d681SAndroid Build Coastguard Worker // Create the bitfield extract for high bits.
748*9880d681SAndroid Build Coastguard Worker BitExtMI2 =
749*9880d681SAndroid Build Coastguard Worker BuildMI(*MBB, InsertionPoint, DL, TII->get(getBitExtrOpcode(*Rt2MI)))
750*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*Rt2MI))
751*9880d681SAndroid Build Coastguard Worker .addReg(getLdStRegOp(*RtNewDest).getReg())
752*9880d681SAndroid Build Coastguard Worker .addImm(LSBHigh)
753*9880d681SAndroid Build Coastguard Worker .addImm(ImmsHigh);
754*9880d681SAndroid Build Coastguard Worker }
755*9880d681SAndroid Build Coastguard Worker (void)BitExtMI1;
756*9880d681SAndroid Build Coastguard Worker (void)BitExtMI2;
757*9880d681SAndroid Build Coastguard Worker
758*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " ");
759*9880d681SAndroid Build Coastguard Worker DEBUG((BitExtMI1)->print(dbgs()));
760*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " ");
761*9880d681SAndroid Build Coastguard Worker DEBUG((BitExtMI2)->print(dbgs()));
762*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n");
763*9880d681SAndroid Build Coastguard Worker
764*9880d681SAndroid Build Coastguard Worker // Erase the old instructions.
765*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
766*9880d681SAndroid Build Coastguard Worker MergeMI->eraseFromParent();
767*9880d681SAndroid Build Coastguard Worker return NextI;
768*9880d681SAndroid Build Coastguard Worker }
769*9880d681SAndroid Build Coastguard Worker assert(isPromotableZeroStoreInst(*I) && isPromotableZeroStoreInst(*MergeMI) &&
770*9880d681SAndroid Build Coastguard Worker "Expected promotable zero store");
771*9880d681SAndroid Build Coastguard Worker
772*9880d681SAndroid Build Coastguard Worker // Construct the new instruction.
773*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB;
774*9880d681SAndroid Build Coastguard Worker MIB = BuildMI(*MBB, InsertionPoint, DL, TII->get(getMatchingWideOpcode(Opc)))
775*9880d681SAndroid Build Coastguard Worker .addReg(isNarrowStore(Opc) ? AArch64::WZR : AArch64::XZR)
776*9880d681SAndroid Build Coastguard Worker .addOperand(BaseRegOp)
777*9880d681SAndroid Build Coastguard Worker .addImm(OffsetImm)
778*9880d681SAndroid Build Coastguard Worker .setMemRefs(I->mergeMemRefsWith(*MergeMI));
779*9880d681SAndroid Build Coastguard Worker (void)MIB;
780*9880d681SAndroid Build Coastguard Worker
781*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Creating wider load/store. Replacing instructions:\n ");
782*9880d681SAndroid Build Coastguard Worker DEBUG(I->print(dbgs()));
783*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " ");
784*9880d681SAndroid Build Coastguard Worker DEBUG(MergeMI->print(dbgs()));
785*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " with instruction:\n ");
786*9880d681SAndroid Build Coastguard Worker DEBUG(((MachineInstr *)MIB)->print(dbgs()));
787*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n");
788*9880d681SAndroid Build Coastguard Worker
789*9880d681SAndroid Build Coastguard Worker // Erase the old instructions.
790*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
791*9880d681SAndroid Build Coastguard Worker MergeMI->eraseFromParent();
792*9880d681SAndroid Build Coastguard Worker return NextI;
793*9880d681SAndroid Build Coastguard Worker }
794*9880d681SAndroid Build Coastguard Worker
795*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
mergePairedInsns(MachineBasicBlock::iterator I,MachineBasicBlock::iterator Paired,const LdStPairFlags & Flags)796*9880d681SAndroid Build Coastguard Worker AArch64LoadStoreOpt::mergePairedInsns(MachineBasicBlock::iterator I,
797*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator Paired,
798*9880d681SAndroid Build Coastguard Worker const LdStPairFlags &Flags) {
799*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NextI = I;
800*9880d681SAndroid Build Coastguard Worker ++NextI;
801*9880d681SAndroid Build Coastguard Worker // If NextI is the second of the two instructions to be merged, we need
802*9880d681SAndroid Build Coastguard Worker // to skip one further. Either way we merge will invalidate the iterator,
803*9880d681SAndroid Build Coastguard Worker // and we don't need to scan the new instruction, as it's a pairwise
804*9880d681SAndroid Build Coastguard Worker // instruction, which we're not considering for further action anyway.
805*9880d681SAndroid Build Coastguard Worker if (NextI == Paired)
806*9880d681SAndroid Build Coastguard Worker ++NextI;
807*9880d681SAndroid Build Coastguard Worker
808*9880d681SAndroid Build Coastguard Worker int SExtIdx = Flags.getSExtIdx();
809*9880d681SAndroid Build Coastguard Worker unsigned Opc =
810*9880d681SAndroid Build Coastguard Worker SExtIdx == -1 ? I->getOpcode() : getMatchingNonSExtOpcode(I->getOpcode());
811*9880d681SAndroid Build Coastguard Worker bool IsUnscaled = TII->isUnscaledLdSt(Opc);
812*9880d681SAndroid Build Coastguard Worker int OffsetStride = IsUnscaled ? getMemScale(*I) : 1;
813*9880d681SAndroid Build Coastguard Worker
814*9880d681SAndroid Build Coastguard Worker bool MergeForward = Flags.getMergeForward();
815*9880d681SAndroid Build Coastguard Worker // Insert our new paired instruction after whichever of the paired
816*9880d681SAndroid Build Coastguard Worker // instructions MergeForward indicates.
817*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator InsertionPoint = MergeForward ? Paired : I;
818*9880d681SAndroid Build Coastguard Worker // Also based on MergeForward is from where we copy the base register operand
819*9880d681SAndroid Build Coastguard Worker // so we get the flags compatible with the input code.
820*9880d681SAndroid Build Coastguard Worker const MachineOperand &BaseRegOp =
821*9880d681SAndroid Build Coastguard Worker MergeForward ? getLdStBaseOp(*Paired) : getLdStBaseOp(*I);
822*9880d681SAndroid Build Coastguard Worker
823*9880d681SAndroid Build Coastguard Worker int Offset = getLdStOffsetOp(*I).getImm();
824*9880d681SAndroid Build Coastguard Worker int PairedOffset = getLdStOffsetOp(*Paired).getImm();
825*9880d681SAndroid Build Coastguard Worker bool PairedIsUnscaled = TII->isUnscaledLdSt(Paired->getOpcode());
826*9880d681SAndroid Build Coastguard Worker if (IsUnscaled != PairedIsUnscaled) {
827*9880d681SAndroid Build Coastguard Worker // We're trying to pair instructions that differ in how they are scaled. If
828*9880d681SAndroid Build Coastguard Worker // I is scaled then scale the offset of Paired accordingly. Otherwise, do
829*9880d681SAndroid Build Coastguard Worker // the opposite (i.e., make Paired's offset unscaled).
830*9880d681SAndroid Build Coastguard Worker int MemSize = getMemScale(*Paired);
831*9880d681SAndroid Build Coastguard Worker if (PairedIsUnscaled) {
832*9880d681SAndroid Build Coastguard Worker // If the unscaled offset isn't a multiple of the MemSize, we can't
833*9880d681SAndroid Build Coastguard Worker // pair the operations together.
834*9880d681SAndroid Build Coastguard Worker assert(!(PairedOffset % getMemScale(*Paired)) &&
835*9880d681SAndroid Build Coastguard Worker "Offset should be a multiple of the stride!");
836*9880d681SAndroid Build Coastguard Worker PairedOffset /= MemSize;
837*9880d681SAndroid Build Coastguard Worker } else {
838*9880d681SAndroid Build Coastguard Worker PairedOffset *= MemSize;
839*9880d681SAndroid Build Coastguard Worker }
840*9880d681SAndroid Build Coastguard Worker }
841*9880d681SAndroid Build Coastguard Worker
842*9880d681SAndroid Build Coastguard Worker // Which register is Rt and which is Rt2 depends on the offset order.
843*9880d681SAndroid Build Coastguard Worker MachineInstr *RtMI, *Rt2MI;
844*9880d681SAndroid Build Coastguard Worker if (Offset == PairedOffset + OffsetStride) {
845*9880d681SAndroid Build Coastguard Worker RtMI = &*Paired;
846*9880d681SAndroid Build Coastguard Worker Rt2MI = &*I;
847*9880d681SAndroid Build Coastguard Worker // Here we swapped the assumption made for SExtIdx.
848*9880d681SAndroid Build Coastguard Worker // I.e., we turn ldp I, Paired into ldp Paired, I.
849*9880d681SAndroid Build Coastguard Worker // Update the index accordingly.
850*9880d681SAndroid Build Coastguard Worker if (SExtIdx != -1)
851*9880d681SAndroid Build Coastguard Worker SExtIdx = (SExtIdx + 1) % 2;
852*9880d681SAndroid Build Coastguard Worker } else {
853*9880d681SAndroid Build Coastguard Worker RtMI = &*I;
854*9880d681SAndroid Build Coastguard Worker Rt2MI = &*Paired;
855*9880d681SAndroid Build Coastguard Worker }
856*9880d681SAndroid Build Coastguard Worker int OffsetImm = getLdStOffsetOp(*RtMI).getImm();
857*9880d681SAndroid Build Coastguard Worker // Scale the immediate offset, if necessary.
858*9880d681SAndroid Build Coastguard Worker if (TII->isUnscaledLdSt(RtMI->getOpcode())) {
859*9880d681SAndroid Build Coastguard Worker assert(!(OffsetImm % getMemScale(*RtMI)) &&
860*9880d681SAndroid Build Coastguard Worker "Unscaled offset cannot be scaled.");
861*9880d681SAndroid Build Coastguard Worker OffsetImm /= getMemScale(*RtMI);
862*9880d681SAndroid Build Coastguard Worker }
863*9880d681SAndroid Build Coastguard Worker
864*9880d681SAndroid Build Coastguard Worker // Construct the new instruction.
865*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB;
866*9880d681SAndroid Build Coastguard Worker DebugLoc DL = I->getDebugLoc();
867*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = I->getParent();
868*9880d681SAndroid Build Coastguard Worker MIB = BuildMI(*MBB, InsertionPoint, DL, TII->get(getMatchingPairOpcode(Opc)))
869*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*RtMI))
870*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*Rt2MI))
871*9880d681SAndroid Build Coastguard Worker .addOperand(BaseRegOp)
872*9880d681SAndroid Build Coastguard Worker .addImm(OffsetImm)
873*9880d681SAndroid Build Coastguard Worker .setMemRefs(I->mergeMemRefsWith(*Paired));
874*9880d681SAndroid Build Coastguard Worker
875*9880d681SAndroid Build Coastguard Worker (void)MIB;
876*9880d681SAndroid Build Coastguard Worker
877*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Creating pair load/store. Replacing instructions:\n ");
878*9880d681SAndroid Build Coastguard Worker DEBUG(I->print(dbgs()));
879*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " ");
880*9880d681SAndroid Build Coastguard Worker DEBUG(Paired->print(dbgs()));
881*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " with instruction:\n ");
882*9880d681SAndroid Build Coastguard Worker if (SExtIdx != -1) {
883*9880d681SAndroid Build Coastguard Worker // Generate the sign extension for the proper result of the ldp.
884*9880d681SAndroid Build Coastguard Worker // I.e., with X1, that would be:
885*9880d681SAndroid Build Coastguard Worker // %W1<def> = KILL %W1, %X1<imp-def>
886*9880d681SAndroid Build Coastguard Worker // %X1<def> = SBFMXri %X1<kill>, 0, 31
887*9880d681SAndroid Build Coastguard Worker MachineOperand &DstMO = MIB->getOperand(SExtIdx);
888*9880d681SAndroid Build Coastguard Worker // Right now, DstMO has the extended register, since it comes from an
889*9880d681SAndroid Build Coastguard Worker // extended opcode.
890*9880d681SAndroid Build Coastguard Worker unsigned DstRegX = DstMO.getReg();
891*9880d681SAndroid Build Coastguard Worker // Get the W variant of that register.
892*9880d681SAndroid Build Coastguard Worker unsigned DstRegW = TRI->getSubReg(DstRegX, AArch64::sub_32);
893*9880d681SAndroid Build Coastguard Worker // Update the result of LDP to use the W instead of the X variant.
894*9880d681SAndroid Build Coastguard Worker DstMO.setReg(DstRegW);
895*9880d681SAndroid Build Coastguard Worker DEBUG(((MachineInstr *)MIB)->print(dbgs()));
896*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n");
897*9880d681SAndroid Build Coastguard Worker // Make the machine verifier happy by providing a definition for
898*9880d681SAndroid Build Coastguard Worker // the X register.
899*9880d681SAndroid Build Coastguard Worker // Insert this definition right after the generated LDP, i.e., before
900*9880d681SAndroid Build Coastguard Worker // InsertionPoint.
901*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIBKill =
902*9880d681SAndroid Build Coastguard Worker BuildMI(*MBB, InsertionPoint, DL, TII->get(TargetOpcode::KILL), DstRegW)
903*9880d681SAndroid Build Coastguard Worker .addReg(DstRegW)
904*9880d681SAndroid Build Coastguard Worker .addReg(DstRegX, RegState::Define);
905*9880d681SAndroid Build Coastguard Worker MIBKill->getOperand(2).setImplicit();
906*9880d681SAndroid Build Coastguard Worker // Create the sign extension.
907*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIBSXTW =
908*9880d681SAndroid Build Coastguard Worker BuildMI(*MBB, InsertionPoint, DL, TII->get(AArch64::SBFMXri), DstRegX)
909*9880d681SAndroid Build Coastguard Worker .addReg(DstRegX)
910*9880d681SAndroid Build Coastguard Worker .addImm(0)
911*9880d681SAndroid Build Coastguard Worker .addImm(31);
912*9880d681SAndroid Build Coastguard Worker (void)MIBSXTW;
913*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Extend operand:\n ");
914*9880d681SAndroid Build Coastguard Worker DEBUG(((MachineInstr *)MIBSXTW)->print(dbgs()));
915*9880d681SAndroid Build Coastguard Worker } else {
916*9880d681SAndroid Build Coastguard Worker DEBUG(((MachineInstr *)MIB)->print(dbgs()));
917*9880d681SAndroid Build Coastguard Worker }
918*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n");
919*9880d681SAndroid Build Coastguard Worker
920*9880d681SAndroid Build Coastguard Worker // Erase the old instructions.
921*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
922*9880d681SAndroid Build Coastguard Worker Paired->eraseFromParent();
923*9880d681SAndroid Build Coastguard Worker
924*9880d681SAndroid Build Coastguard Worker return NextI;
925*9880d681SAndroid Build Coastguard Worker }
926*9880d681SAndroid Build Coastguard Worker
927*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
promoteLoadFromStore(MachineBasicBlock::iterator LoadI,MachineBasicBlock::iterator StoreI)928*9880d681SAndroid Build Coastguard Worker AArch64LoadStoreOpt::promoteLoadFromStore(MachineBasicBlock::iterator LoadI,
929*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator StoreI) {
930*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NextI = LoadI;
931*9880d681SAndroid Build Coastguard Worker ++NextI;
932*9880d681SAndroid Build Coastguard Worker
933*9880d681SAndroid Build Coastguard Worker int LoadSize = getMemScale(*LoadI);
934*9880d681SAndroid Build Coastguard Worker int StoreSize = getMemScale(*StoreI);
935*9880d681SAndroid Build Coastguard Worker unsigned LdRt = getLdStRegOp(*LoadI).getReg();
936*9880d681SAndroid Build Coastguard Worker unsigned StRt = getLdStRegOp(*StoreI).getReg();
937*9880d681SAndroid Build Coastguard Worker bool IsStoreXReg = TRI->getRegClass(AArch64::GPR64RegClassID)->contains(StRt);
938*9880d681SAndroid Build Coastguard Worker
939*9880d681SAndroid Build Coastguard Worker assert((IsStoreXReg ||
940*9880d681SAndroid Build Coastguard Worker TRI->getRegClass(AArch64::GPR32RegClassID)->contains(StRt)) &&
941*9880d681SAndroid Build Coastguard Worker "Unexpected RegClass");
942*9880d681SAndroid Build Coastguard Worker
943*9880d681SAndroid Build Coastguard Worker MachineInstr *BitExtMI;
944*9880d681SAndroid Build Coastguard Worker if (LoadSize == StoreSize && (LoadSize == 4 || LoadSize == 8)) {
945*9880d681SAndroid Build Coastguard Worker // Remove the load, if the destination register of the loads is the same
946*9880d681SAndroid Build Coastguard Worker // register for stored value.
947*9880d681SAndroid Build Coastguard Worker if (StRt == LdRt && LoadSize == 8) {
948*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Remove load instruction:\n ");
949*9880d681SAndroid Build Coastguard Worker DEBUG(LoadI->print(dbgs()));
950*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n");
951*9880d681SAndroid Build Coastguard Worker LoadI->eraseFromParent();
952*9880d681SAndroid Build Coastguard Worker return NextI;
953*9880d681SAndroid Build Coastguard Worker }
954*9880d681SAndroid Build Coastguard Worker // Replace the load with a mov if the load and store are in the same size.
955*9880d681SAndroid Build Coastguard Worker BitExtMI =
956*9880d681SAndroid Build Coastguard Worker BuildMI(*LoadI->getParent(), LoadI, LoadI->getDebugLoc(),
957*9880d681SAndroid Build Coastguard Worker TII->get(IsStoreXReg ? AArch64::ORRXrs : AArch64::ORRWrs), LdRt)
958*9880d681SAndroid Build Coastguard Worker .addReg(IsStoreXReg ? AArch64::XZR : AArch64::WZR)
959*9880d681SAndroid Build Coastguard Worker .addReg(StRt)
960*9880d681SAndroid Build Coastguard Worker .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, 0));
961*9880d681SAndroid Build Coastguard Worker } else {
962*9880d681SAndroid Build Coastguard Worker // FIXME: Currently we disable this transformation in big-endian targets as
963*9880d681SAndroid Build Coastguard Worker // performance and correctness are verified only in little-endian.
964*9880d681SAndroid Build Coastguard Worker if (!Subtarget->isLittleEndian())
965*9880d681SAndroid Build Coastguard Worker return NextI;
966*9880d681SAndroid Build Coastguard Worker bool IsUnscaled = TII->isUnscaledLdSt(*LoadI);
967*9880d681SAndroid Build Coastguard Worker assert(IsUnscaled == TII->isUnscaledLdSt(*StoreI) &&
968*9880d681SAndroid Build Coastguard Worker "Unsupported ld/st match");
969*9880d681SAndroid Build Coastguard Worker assert(LoadSize <= StoreSize && "Invalid load size");
970*9880d681SAndroid Build Coastguard Worker int UnscaledLdOffset = IsUnscaled
971*9880d681SAndroid Build Coastguard Worker ? getLdStOffsetOp(*LoadI).getImm()
972*9880d681SAndroid Build Coastguard Worker : getLdStOffsetOp(*LoadI).getImm() * LoadSize;
973*9880d681SAndroid Build Coastguard Worker int UnscaledStOffset = IsUnscaled
974*9880d681SAndroid Build Coastguard Worker ? getLdStOffsetOp(*StoreI).getImm()
975*9880d681SAndroid Build Coastguard Worker : getLdStOffsetOp(*StoreI).getImm() * StoreSize;
976*9880d681SAndroid Build Coastguard Worker int Width = LoadSize * 8;
977*9880d681SAndroid Build Coastguard Worker int Immr = 8 * (UnscaledLdOffset - UnscaledStOffset);
978*9880d681SAndroid Build Coastguard Worker int Imms = Immr + Width - 1;
979*9880d681SAndroid Build Coastguard Worker unsigned DestReg = IsStoreXReg
980*9880d681SAndroid Build Coastguard Worker ? TRI->getMatchingSuperReg(LdRt, AArch64::sub_32,
981*9880d681SAndroid Build Coastguard Worker &AArch64::GPR64RegClass)
982*9880d681SAndroid Build Coastguard Worker : LdRt;
983*9880d681SAndroid Build Coastguard Worker
984*9880d681SAndroid Build Coastguard Worker assert((UnscaledLdOffset >= UnscaledStOffset &&
985*9880d681SAndroid Build Coastguard Worker (UnscaledLdOffset + LoadSize) <= UnscaledStOffset + StoreSize) &&
986*9880d681SAndroid Build Coastguard Worker "Invalid offset");
987*9880d681SAndroid Build Coastguard Worker
988*9880d681SAndroid Build Coastguard Worker Immr = 8 * (UnscaledLdOffset - UnscaledStOffset);
989*9880d681SAndroid Build Coastguard Worker Imms = Immr + Width - 1;
990*9880d681SAndroid Build Coastguard Worker if (UnscaledLdOffset == UnscaledStOffset) {
991*9880d681SAndroid Build Coastguard Worker uint32_t AndMaskEncoded = ((IsStoreXReg ? 1 : 0) << 12) // N
992*9880d681SAndroid Build Coastguard Worker | ((Immr) << 6) // immr
993*9880d681SAndroid Build Coastguard Worker | ((Imms) << 0) // imms
994*9880d681SAndroid Build Coastguard Worker ;
995*9880d681SAndroid Build Coastguard Worker
996*9880d681SAndroid Build Coastguard Worker BitExtMI =
997*9880d681SAndroid Build Coastguard Worker BuildMI(*LoadI->getParent(), LoadI, LoadI->getDebugLoc(),
998*9880d681SAndroid Build Coastguard Worker TII->get(IsStoreXReg ? AArch64::ANDXri : AArch64::ANDWri),
999*9880d681SAndroid Build Coastguard Worker DestReg)
1000*9880d681SAndroid Build Coastguard Worker .addReg(StRt)
1001*9880d681SAndroid Build Coastguard Worker .addImm(AndMaskEncoded);
1002*9880d681SAndroid Build Coastguard Worker } else {
1003*9880d681SAndroid Build Coastguard Worker BitExtMI =
1004*9880d681SAndroid Build Coastguard Worker BuildMI(*LoadI->getParent(), LoadI, LoadI->getDebugLoc(),
1005*9880d681SAndroid Build Coastguard Worker TII->get(IsStoreXReg ? AArch64::UBFMXri : AArch64::UBFMWri),
1006*9880d681SAndroid Build Coastguard Worker DestReg)
1007*9880d681SAndroid Build Coastguard Worker .addReg(StRt)
1008*9880d681SAndroid Build Coastguard Worker .addImm(Immr)
1009*9880d681SAndroid Build Coastguard Worker .addImm(Imms);
1010*9880d681SAndroid Build Coastguard Worker }
1011*9880d681SAndroid Build Coastguard Worker }
1012*9880d681SAndroid Build Coastguard Worker (void)BitExtMI;
1013*9880d681SAndroid Build Coastguard Worker
1014*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Promoting load by replacing :\n ");
1015*9880d681SAndroid Build Coastguard Worker DEBUG(StoreI->print(dbgs()));
1016*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " ");
1017*9880d681SAndroid Build Coastguard Worker DEBUG(LoadI->print(dbgs()));
1018*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " with instructions:\n ");
1019*9880d681SAndroid Build Coastguard Worker DEBUG(StoreI->print(dbgs()));
1020*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " ");
1021*9880d681SAndroid Build Coastguard Worker DEBUG((BitExtMI)->print(dbgs()));
1022*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n");
1023*9880d681SAndroid Build Coastguard Worker
1024*9880d681SAndroid Build Coastguard Worker // Erase the old instructions.
1025*9880d681SAndroid Build Coastguard Worker LoadI->eraseFromParent();
1026*9880d681SAndroid Build Coastguard Worker return NextI;
1027*9880d681SAndroid Build Coastguard Worker }
1028*9880d681SAndroid Build Coastguard Worker
1029*9880d681SAndroid Build Coastguard Worker /// trackRegDefsUses - Remember what registers the specified instruction uses
1030*9880d681SAndroid Build Coastguard Worker /// and modifies.
trackRegDefsUses(const MachineInstr & MI,BitVector & ModifiedRegs,BitVector & UsedRegs,const TargetRegisterInfo * TRI)1031*9880d681SAndroid Build Coastguard Worker static void trackRegDefsUses(const MachineInstr &MI, BitVector &ModifiedRegs,
1032*9880d681SAndroid Build Coastguard Worker BitVector &UsedRegs,
1033*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI) {
1034*9880d681SAndroid Build Coastguard Worker for (const MachineOperand &MO : MI.operands()) {
1035*9880d681SAndroid Build Coastguard Worker if (MO.isRegMask())
1036*9880d681SAndroid Build Coastguard Worker ModifiedRegs.setBitsNotInMask(MO.getRegMask());
1037*9880d681SAndroid Build Coastguard Worker
1038*9880d681SAndroid Build Coastguard Worker if (!MO.isReg())
1039*9880d681SAndroid Build Coastguard Worker continue;
1040*9880d681SAndroid Build Coastguard Worker unsigned Reg = MO.getReg();
1041*9880d681SAndroid Build Coastguard Worker if (!Reg)
1042*9880d681SAndroid Build Coastguard Worker continue;
1043*9880d681SAndroid Build Coastguard Worker if (MO.isDef()) {
1044*9880d681SAndroid Build Coastguard Worker for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
1045*9880d681SAndroid Build Coastguard Worker ModifiedRegs.set(*AI);
1046*9880d681SAndroid Build Coastguard Worker } else {
1047*9880d681SAndroid Build Coastguard Worker assert(MO.isUse() && "Reg operand not a def and not a use?!?");
1048*9880d681SAndroid Build Coastguard Worker for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
1049*9880d681SAndroid Build Coastguard Worker UsedRegs.set(*AI);
1050*9880d681SAndroid Build Coastguard Worker }
1051*9880d681SAndroid Build Coastguard Worker }
1052*9880d681SAndroid Build Coastguard Worker }
1053*9880d681SAndroid Build Coastguard Worker
inBoundsForPair(bool IsUnscaled,int Offset,int OffsetStride)1054*9880d681SAndroid Build Coastguard Worker static bool inBoundsForPair(bool IsUnscaled, int Offset, int OffsetStride) {
1055*9880d681SAndroid Build Coastguard Worker // Convert the byte-offset used by unscaled into an "element" offset used
1056*9880d681SAndroid Build Coastguard Worker // by the scaled pair load/store instructions.
1057*9880d681SAndroid Build Coastguard Worker if (IsUnscaled) {
1058*9880d681SAndroid Build Coastguard Worker // If the byte-offset isn't a multiple of the stride, there's no point
1059*9880d681SAndroid Build Coastguard Worker // trying to match it.
1060*9880d681SAndroid Build Coastguard Worker if (Offset % OffsetStride)
1061*9880d681SAndroid Build Coastguard Worker return false;
1062*9880d681SAndroid Build Coastguard Worker Offset /= OffsetStride;
1063*9880d681SAndroid Build Coastguard Worker }
1064*9880d681SAndroid Build Coastguard Worker return Offset <= 63 && Offset >= -64;
1065*9880d681SAndroid Build Coastguard Worker }
1066*9880d681SAndroid Build Coastguard Worker
1067*9880d681SAndroid Build Coastguard Worker // Do alignment, specialized to power of 2 and for signed ints,
1068*9880d681SAndroid Build Coastguard Worker // avoiding having to do a C-style cast from uint_64t to int when
1069*9880d681SAndroid Build Coastguard Worker // using alignTo from include/llvm/Support/MathExtras.h.
1070*9880d681SAndroid Build Coastguard Worker // FIXME: Move this function to include/MathExtras.h?
alignTo(int Num,int PowOf2)1071*9880d681SAndroid Build Coastguard Worker static int alignTo(int Num, int PowOf2) {
1072*9880d681SAndroid Build Coastguard Worker return (Num + PowOf2 - 1) & ~(PowOf2 - 1);
1073*9880d681SAndroid Build Coastguard Worker }
1074*9880d681SAndroid Build Coastguard Worker
mayAlias(MachineInstr & MIa,MachineInstr & MIb,const AArch64InstrInfo * TII)1075*9880d681SAndroid Build Coastguard Worker static bool mayAlias(MachineInstr &MIa, MachineInstr &MIb,
1076*9880d681SAndroid Build Coastguard Worker const AArch64InstrInfo *TII) {
1077*9880d681SAndroid Build Coastguard Worker // One of the instructions must modify memory.
1078*9880d681SAndroid Build Coastguard Worker if (!MIa.mayStore() && !MIb.mayStore())
1079*9880d681SAndroid Build Coastguard Worker return false;
1080*9880d681SAndroid Build Coastguard Worker
1081*9880d681SAndroid Build Coastguard Worker // Both instructions must be memory operations.
1082*9880d681SAndroid Build Coastguard Worker if (!MIa.mayLoadOrStore() && !MIb.mayLoadOrStore())
1083*9880d681SAndroid Build Coastguard Worker return false;
1084*9880d681SAndroid Build Coastguard Worker
1085*9880d681SAndroid Build Coastguard Worker return !TII->areMemAccessesTriviallyDisjoint(MIa, MIb);
1086*9880d681SAndroid Build Coastguard Worker }
1087*9880d681SAndroid Build Coastguard Worker
mayAlias(MachineInstr & MIa,SmallVectorImpl<MachineInstr * > & MemInsns,const AArch64InstrInfo * TII)1088*9880d681SAndroid Build Coastguard Worker static bool mayAlias(MachineInstr &MIa,
1089*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<MachineInstr *> &MemInsns,
1090*9880d681SAndroid Build Coastguard Worker const AArch64InstrInfo *TII) {
1091*9880d681SAndroid Build Coastguard Worker for (MachineInstr *MIb : MemInsns)
1092*9880d681SAndroid Build Coastguard Worker if (mayAlias(MIa, *MIb, TII))
1093*9880d681SAndroid Build Coastguard Worker return true;
1094*9880d681SAndroid Build Coastguard Worker
1095*9880d681SAndroid Build Coastguard Worker return false;
1096*9880d681SAndroid Build Coastguard Worker }
1097*9880d681SAndroid Build Coastguard Worker
findMatchingStore(MachineBasicBlock::iterator I,unsigned Limit,MachineBasicBlock::iterator & StoreI)1098*9880d681SAndroid Build Coastguard Worker bool AArch64LoadStoreOpt::findMatchingStore(
1099*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I, unsigned Limit,
1100*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator &StoreI) {
1101*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator B = I->getParent()->begin();
1102*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MBBI = I;
1103*9880d681SAndroid Build Coastguard Worker MachineInstr &LoadMI = *I;
1104*9880d681SAndroid Build Coastguard Worker unsigned BaseReg = getLdStBaseOp(LoadMI).getReg();
1105*9880d681SAndroid Build Coastguard Worker
1106*9880d681SAndroid Build Coastguard Worker // If the load is the first instruction in the block, there's obviously
1107*9880d681SAndroid Build Coastguard Worker // not any matching store.
1108*9880d681SAndroid Build Coastguard Worker if (MBBI == B)
1109*9880d681SAndroid Build Coastguard Worker return false;
1110*9880d681SAndroid Build Coastguard Worker
1111*9880d681SAndroid Build Coastguard Worker // Track which registers have been modified and used between the first insn
1112*9880d681SAndroid Build Coastguard Worker // and the second insn.
1113*9880d681SAndroid Build Coastguard Worker ModifiedRegs.reset();
1114*9880d681SAndroid Build Coastguard Worker UsedRegs.reset();
1115*9880d681SAndroid Build Coastguard Worker
1116*9880d681SAndroid Build Coastguard Worker unsigned Count = 0;
1117*9880d681SAndroid Build Coastguard Worker do {
1118*9880d681SAndroid Build Coastguard Worker --MBBI;
1119*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
1120*9880d681SAndroid Build Coastguard Worker
1121*9880d681SAndroid Build Coastguard Worker // Don't count DBG_VALUE instructions towards the search limit.
1122*9880d681SAndroid Build Coastguard Worker if (!MI.isDebugValue())
1123*9880d681SAndroid Build Coastguard Worker ++Count;
1124*9880d681SAndroid Build Coastguard Worker
1125*9880d681SAndroid Build Coastguard Worker // If the load instruction reads directly from the address to which the
1126*9880d681SAndroid Build Coastguard Worker // store instruction writes and the stored value is not modified, we can
1127*9880d681SAndroid Build Coastguard Worker // promote the load. Since we do not handle stores with pre-/post-index,
1128*9880d681SAndroid Build Coastguard Worker // it's unnecessary to check if BaseReg is modified by the store itself.
1129*9880d681SAndroid Build Coastguard Worker if (MI.mayStore() && isMatchingStore(LoadMI, MI) &&
1130*9880d681SAndroid Build Coastguard Worker BaseReg == getLdStBaseOp(MI).getReg() &&
1131*9880d681SAndroid Build Coastguard Worker isLdOffsetInRangeOfSt(LoadMI, MI, TII) &&
1132*9880d681SAndroid Build Coastguard Worker !ModifiedRegs[getLdStRegOp(MI).getReg()]) {
1133*9880d681SAndroid Build Coastguard Worker StoreI = MBBI;
1134*9880d681SAndroid Build Coastguard Worker return true;
1135*9880d681SAndroid Build Coastguard Worker }
1136*9880d681SAndroid Build Coastguard Worker
1137*9880d681SAndroid Build Coastguard Worker if (MI.isCall())
1138*9880d681SAndroid Build Coastguard Worker return false;
1139*9880d681SAndroid Build Coastguard Worker
1140*9880d681SAndroid Build Coastguard Worker // Update modified / uses register lists.
1141*9880d681SAndroid Build Coastguard Worker trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
1142*9880d681SAndroid Build Coastguard Worker
1143*9880d681SAndroid Build Coastguard Worker // Otherwise, if the base register is modified, we have no match, so
1144*9880d681SAndroid Build Coastguard Worker // return early.
1145*9880d681SAndroid Build Coastguard Worker if (ModifiedRegs[BaseReg])
1146*9880d681SAndroid Build Coastguard Worker return false;
1147*9880d681SAndroid Build Coastguard Worker
1148*9880d681SAndroid Build Coastguard Worker // If we encounter a store aliased with the load, return early.
1149*9880d681SAndroid Build Coastguard Worker if (MI.mayStore() && mayAlias(LoadMI, MI, TII))
1150*9880d681SAndroid Build Coastguard Worker return false;
1151*9880d681SAndroid Build Coastguard Worker } while (MBBI != B && Count < Limit);
1152*9880d681SAndroid Build Coastguard Worker return false;
1153*9880d681SAndroid Build Coastguard Worker }
1154*9880d681SAndroid Build Coastguard Worker
1155*9880d681SAndroid Build Coastguard Worker // Returns true if FirstMI and MI are candidates for merging or pairing.
1156*9880d681SAndroid Build Coastguard Worker // Otherwise, returns false.
areCandidatesToMergeOrPair(MachineInstr & FirstMI,MachineInstr & MI,LdStPairFlags & Flags,const AArch64InstrInfo * TII)1157*9880d681SAndroid Build Coastguard Worker static bool areCandidatesToMergeOrPair(MachineInstr &FirstMI, MachineInstr &MI,
1158*9880d681SAndroid Build Coastguard Worker LdStPairFlags &Flags,
1159*9880d681SAndroid Build Coastguard Worker const AArch64InstrInfo *TII) {
1160*9880d681SAndroid Build Coastguard Worker // If this is volatile or if pairing is suppressed, not a candidate.
1161*9880d681SAndroid Build Coastguard Worker if (MI.hasOrderedMemoryRef() || TII->isLdStPairSuppressed(MI))
1162*9880d681SAndroid Build Coastguard Worker return false;
1163*9880d681SAndroid Build Coastguard Worker
1164*9880d681SAndroid Build Coastguard Worker // We should have already checked FirstMI for pair suppression and volatility.
1165*9880d681SAndroid Build Coastguard Worker assert(!FirstMI.hasOrderedMemoryRef() &&
1166*9880d681SAndroid Build Coastguard Worker !TII->isLdStPairSuppressed(FirstMI) &&
1167*9880d681SAndroid Build Coastguard Worker "FirstMI shouldn't get here if either of these checks are true.");
1168*9880d681SAndroid Build Coastguard Worker
1169*9880d681SAndroid Build Coastguard Worker unsigned OpcA = FirstMI.getOpcode();
1170*9880d681SAndroid Build Coastguard Worker unsigned OpcB = MI.getOpcode();
1171*9880d681SAndroid Build Coastguard Worker
1172*9880d681SAndroid Build Coastguard Worker // Opcodes match: nothing more to check.
1173*9880d681SAndroid Build Coastguard Worker if (OpcA == OpcB)
1174*9880d681SAndroid Build Coastguard Worker return true;
1175*9880d681SAndroid Build Coastguard Worker
1176*9880d681SAndroid Build Coastguard Worker // Try to match a sign-extended load/store with a zero-extended load/store.
1177*9880d681SAndroid Build Coastguard Worker bool IsValidLdStrOpc, PairIsValidLdStrOpc;
1178*9880d681SAndroid Build Coastguard Worker unsigned NonSExtOpc = getMatchingNonSExtOpcode(OpcA, &IsValidLdStrOpc);
1179*9880d681SAndroid Build Coastguard Worker assert(IsValidLdStrOpc &&
1180*9880d681SAndroid Build Coastguard Worker "Given Opc should be a Load or Store with an immediate");
1181*9880d681SAndroid Build Coastguard Worker // OpcA will be the first instruction in the pair.
1182*9880d681SAndroid Build Coastguard Worker if (NonSExtOpc == getMatchingNonSExtOpcode(OpcB, &PairIsValidLdStrOpc)) {
1183*9880d681SAndroid Build Coastguard Worker Flags.setSExtIdx(NonSExtOpc == (unsigned)OpcA ? 1 : 0);
1184*9880d681SAndroid Build Coastguard Worker return true;
1185*9880d681SAndroid Build Coastguard Worker }
1186*9880d681SAndroid Build Coastguard Worker
1187*9880d681SAndroid Build Coastguard Worker // If the second instruction isn't even a load/store, bail out.
1188*9880d681SAndroid Build Coastguard Worker if (!PairIsValidLdStrOpc)
1189*9880d681SAndroid Build Coastguard Worker return false;
1190*9880d681SAndroid Build Coastguard Worker
1191*9880d681SAndroid Build Coastguard Worker // FIXME: We don't support merging narrow loads/stores with mixed
1192*9880d681SAndroid Build Coastguard Worker // scaled/unscaled offsets.
1193*9880d681SAndroid Build Coastguard Worker if (isNarrowLoadOrStore(OpcA) || isNarrowLoadOrStore(OpcB))
1194*9880d681SAndroid Build Coastguard Worker return false;
1195*9880d681SAndroid Build Coastguard Worker
1196*9880d681SAndroid Build Coastguard Worker // Try to match an unscaled load/store with a scaled load/store.
1197*9880d681SAndroid Build Coastguard Worker return TII->isUnscaledLdSt(OpcA) != TII->isUnscaledLdSt(OpcB) &&
1198*9880d681SAndroid Build Coastguard Worker getMatchingPairOpcode(OpcA) == getMatchingPairOpcode(OpcB);
1199*9880d681SAndroid Build Coastguard Worker
1200*9880d681SAndroid Build Coastguard Worker // FIXME: Can we also match a mixed sext/zext unscaled/scaled pair?
1201*9880d681SAndroid Build Coastguard Worker }
1202*9880d681SAndroid Build Coastguard Worker
1203*9880d681SAndroid Build Coastguard Worker /// Scan the instructions looking for a load/store that can be combined with the
1204*9880d681SAndroid Build Coastguard Worker /// current instruction into a wider equivalent or a load/store pair.
1205*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
findMatchingInsn(MachineBasicBlock::iterator I,LdStPairFlags & Flags,unsigned Limit,bool FindNarrowMerge)1206*9880d681SAndroid Build Coastguard Worker AArch64LoadStoreOpt::findMatchingInsn(MachineBasicBlock::iterator I,
1207*9880d681SAndroid Build Coastguard Worker LdStPairFlags &Flags, unsigned Limit,
1208*9880d681SAndroid Build Coastguard Worker bool FindNarrowMerge) {
1209*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator E = I->getParent()->end();
1210*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MBBI = I;
1211*9880d681SAndroid Build Coastguard Worker MachineInstr &FirstMI = *I;
1212*9880d681SAndroid Build Coastguard Worker ++MBBI;
1213*9880d681SAndroid Build Coastguard Worker
1214*9880d681SAndroid Build Coastguard Worker bool MayLoad = FirstMI.mayLoad();
1215*9880d681SAndroid Build Coastguard Worker bool IsUnscaled = TII->isUnscaledLdSt(FirstMI);
1216*9880d681SAndroid Build Coastguard Worker unsigned Reg = getLdStRegOp(FirstMI).getReg();
1217*9880d681SAndroid Build Coastguard Worker unsigned BaseReg = getLdStBaseOp(FirstMI).getReg();
1218*9880d681SAndroid Build Coastguard Worker int Offset = getLdStOffsetOp(FirstMI).getImm();
1219*9880d681SAndroid Build Coastguard Worker int OffsetStride = IsUnscaled ? getMemScale(FirstMI) : 1;
1220*9880d681SAndroid Build Coastguard Worker bool IsPromotableZeroStore = isPromotableZeroStoreInst(FirstMI);
1221*9880d681SAndroid Build Coastguard Worker
1222*9880d681SAndroid Build Coastguard Worker // Track which registers have been modified and used between the first insn
1223*9880d681SAndroid Build Coastguard Worker // (inclusive) and the second insn.
1224*9880d681SAndroid Build Coastguard Worker ModifiedRegs.reset();
1225*9880d681SAndroid Build Coastguard Worker UsedRegs.reset();
1226*9880d681SAndroid Build Coastguard Worker
1227*9880d681SAndroid Build Coastguard Worker // Remember any instructions that read/write memory between FirstMI and MI.
1228*9880d681SAndroid Build Coastguard Worker SmallVector<MachineInstr *, 4> MemInsns;
1229*9880d681SAndroid Build Coastguard Worker
1230*9880d681SAndroid Build Coastguard Worker for (unsigned Count = 0; MBBI != E && Count < Limit; ++MBBI) {
1231*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
1232*9880d681SAndroid Build Coastguard Worker // Skip DBG_VALUE instructions. Otherwise debug info can affect the
1233*9880d681SAndroid Build Coastguard Worker // optimization by changing how far we scan.
1234*9880d681SAndroid Build Coastguard Worker if (MI.isDebugValue())
1235*9880d681SAndroid Build Coastguard Worker continue;
1236*9880d681SAndroid Build Coastguard Worker
1237*9880d681SAndroid Build Coastguard Worker // Now that we know this is a real instruction, count it.
1238*9880d681SAndroid Build Coastguard Worker ++Count;
1239*9880d681SAndroid Build Coastguard Worker
1240*9880d681SAndroid Build Coastguard Worker Flags.setSExtIdx(-1);
1241*9880d681SAndroid Build Coastguard Worker if (areCandidatesToMergeOrPair(FirstMI, MI, Flags, TII) &&
1242*9880d681SAndroid Build Coastguard Worker getLdStOffsetOp(MI).isImm()) {
1243*9880d681SAndroid Build Coastguard Worker assert(MI.mayLoadOrStore() && "Expected memory operation.");
1244*9880d681SAndroid Build Coastguard Worker // If we've found another instruction with the same opcode, check to see
1245*9880d681SAndroid Build Coastguard Worker // if the base and offset are compatible with our starting instruction.
1246*9880d681SAndroid Build Coastguard Worker // These instructions all have scaled immediate operands, so we just
1247*9880d681SAndroid Build Coastguard Worker // check for +1/-1. Make sure to check the new instruction offset is
1248*9880d681SAndroid Build Coastguard Worker // actually an immediate and not a symbolic reference destined for
1249*9880d681SAndroid Build Coastguard Worker // a relocation.
1250*9880d681SAndroid Build Coastguard Worker unsigned MIBaseReg = getLdStBaseOp(MI).getReg();
1251*9880d681SAndroid Build Coastguard Worker int MIOffset = getLdStOffsetOp(MI).getImm();
1252*9880d681SAndroid Build Coastguard Worker bool MIIsUnscaled = TII->isUnscaledLdSt(MI);
1253*9880d681SAndroid Build Coastguard Worker if (IsUnscaled != MIIsUnscaled) {
1254*9880d681SAndroid Build Coastguard Worker // We're trying to pair instructions that differ in how they are scaled.
1255*9880d681SAndroid Build Coastguard Worker // If FirstMI is scaled then scale the offset of MI accordingly.
1256*9880d681SAndroid Build Coastguard Worker // Otherwise, do the opposite (i.e., make MI's offset unscaled).
1257*9880d681SAndroid Build Coastguard Worker int MemSize = getMemScale(MI);
1258*9880d681SAndroid Build Coastguard Worker if (MIIsUnscaled) {
1259*9880d681SAndroid Build Coastguard Worker // If the unscaled offset isn't a multiple of the MemSize, we can't
1260*9880d681SAndroid Build Coastguard Worker // pair the operations together: bail and keep looking.
1261*9880d681SAndroid Build Coastguard Worker if (MIOffset % MemSize)
1262*9880d681SAndroid Build Coastguard Worker continue;
1263*9880d681SAndroid Build Coastguard Worker MIOffset /= MemSize;
1264*9880d681SAndroid Build Coastguard Worker } else {
1265*9880d681SAndroid Build Coastguard Worker MIOffset *= MemSize;
1266*9880d681SAndroid Build Coastguard Worker }
1267*9880d681SAndroid Build Coastguard Worker }
1268*9880d681SAndroid Build Coastguard Worker
1269*9880d681SAndroid Build Coastguard Worker if (BaseReg == MIBaseReg && ((Offset == MIOffset + OffsetStride) ||
1270*9880d681SAndroid Build Coastguard Worker (Offset + OffsetStride == MIOffset))) {
1271*9880d681SAndroid Build Coastguard Worker int MinOffset = Offset < MIOffset ? Offset : MIOffset;
1272*9880d681SAndroid Build Coastguard Worker if (FindNarrowMerge) {
1273*9880d681SAndroid Build Coastguard Worker // If the alignment requirements of the scaled wide load/store
1274*9880d681SAndroid Build Coastguard Worker // instruction can't express the offset of the scaled narrow input,
1275*9880d681SAndroid Build Coastguard Worker // bail and keep looking. For promotable zero stores, allow only when
1276*9880d681SAndroid Build Coastguard Worker // the stored value is the same (i.e., WZR).
1277*9880d681SAndroid Build Coastguard Worker if ((!IsUnscaled && alignTo(MinOffset, 2) != MinOffset) ||
1278*9880d681SAndroid Build Coastguard Worker (IsPromotableZeroStore && Reg != getLdStRegOp(MI).getReg())) {
1279*9880d681SAndroid Build Coastguard Worker trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
1280*9880d681SAndroid Build Coastguard Worker MemInsns.push_back(&MI);
1281*9880d681SAndroid Build Coastguard Worker continue;
1282*9880d681SAndroid Build Coastguard Worker }
1283*9880d681SAndroid Build Coastguard Worker } else {
1284*9880d681SAndroid Build Coastguard Worker // Pairwise instructions have a 7-bit signed offset field. Single
1285*9880d681SAndroid Build Coastguard Worker // insns have a 12-bit unsigned offset field. If the resultant
1286*9880d681SAndroid Build Coastguard Worker // immediate offset of merging these instructions is out of range for
1287*9880d681SAndroid Build Coastguard Worker // a pairwise instruction, bail and keep looking.
1288*9880d681SAndroid Build Coastguard Worker if (!inBoundsForPair(IsUnscaled, MinOffset, OffsetStride)) {
1289*9880d681SAndroid Build Coastguard Worker trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
1290*9880d681SAndroid Build Coastguard Worker MemInsns.push_back(&MI);
1291*9880d681SAndroid Build Coastguard Worker continue;
1292*9880d681SAndroid Build Coastguard Worker }
1293*9880d681SAndroid Build Coastguard Worker // If the alignment requirements of the paired (scaled) instruction
1294*9880d681SAndroid Build Coastguard Worker // can't express the offset of the unscaled input, bail and keep
1295*9880d681SAndroid Build Coastguard Worker // looking.
1296*9880d681SAndroid Build Coastguard Worker if (IsUnscaled && (alignTo(MinOffset, OffsetStride) != MinOffset)) {
1297*9880d681SAndroid Build Coastguard Worker trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
1298*9880d681SAndroid Build Coastguard Worker MemInsns.push_back(&MI);
1299*9880d681SAndroid Build Coastguard Worker continue;
1300*9880d681SAndroid Build Coastguard Worker }
1301*9880d681SAndroid Build Coastguard Worker }
1302*9880d681SAndroid Build Coastguard Worker // If the destination register of the loads is the same register, bail
1303*9880d681SAndroid Build Coastguard Worker // and keep looking. A load-pair instruction with both destination
1304*9880d681SAndroid Build Coastguard Worker // registers the same is UNPREDICTABLE and will result in an exception.
1305*9880d681SAndroid Build Coastguard Worker if (MayLoad && Reg == getLdStRegOp(MI).getReg()) {
1306*9880d681SAndroid Build Coastguard Worker trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
1307*9880d681SAndroid Build Coastguard Worker MemInsns.push_back(&MI);
1308*9880d681SAndroid Build Coastguard Worker continue;
1309*9880d681SAndroid Build Coastguard Worker }
1310*9880d681SAndroid Build Coastguard Worker
1311*9880d681SAndroid Build Coastguard Worker // If the Rt of the second instruction was not modified or used between
1312*9880d681SAndroid Build Coastguard Worker // the two instructions and none of the instructions between the second
1313*9880d681SAndroid Build Coastguard Worker // and first alias with the second, we can combine the second into the
1314*9880d681SAndroid Build Coastguard Worker // first.
1315*9880d681SAndroid Build Coastguard Worker if (!ModifiedRegs[getLdStRegOp(MI).getReg()] &&
1316*9880d681SAndroid Build Coastguard Worker !(MI.mayLoad() && UsedRegs[getLdStRegOp(MI).getReg()]) &&
1317*9880d681SAndroid Build Coastguard Worker !mayAlias(MI, MemInsns, TII)) {
1318*9880d681SAndroid Build Coastguard Worker Flags.setMergeForward(false);
1319*9880d681SAndroid Build Coastguard Worker return MBBI;
1320*9880d681SAndroid Build Coastguard Worker }
1321*9880d681SAndroid Build Coastguard Worker
1322*9880d681SAndroid Build Coastguard Worker // Likewise, if the Rt of the first instruction is not modified or used
1323*9880d681SAndroid Build Coastguard Worker // between the two instructions and none of the instructions between the
1324*9880d681SAndroid Build Coastguard Worker // first and the second alias with the first, we can combine the first
1325*9880d681SAndroid Build Coastguard Worker // into the second.
1326*9880d681SAndroid Build Coastguard Worker if (!ModifiedRegs[getLdStRegOp(FirstMI).getReg()] &&
1327*9880d681SAndroid Build Coastguard Worker !(MayLoad && UsedRegs[getLdStRegOp(FirstMI).getReg()]) &&
1328*9880d681SAndroid Build Coastguard Worker !mayAlias(FirstMI, MemInsns, TII)) {
1329*9880d681SAndroid Build Coastguard Worker Flags.setMergeForward(true);
1330*9880d681SAndroid Build Coastguard Worker return MBBI;
1331*9880d681SAndroid Build Coastguard Worker }
1332*9880d681SAndroid Build Coastguard Worker // Unable to combine these instructions due to interference in between.
1333*9880d681SAndroid Build Coastguard Worker // Keep looking.
1334*9880d681SAndroid Build Coastguard Worker }
1335*9880d681SAndroid Build Coastguard Worker }
1336*9880d681SAndroid Build Coastguard Worker
1337*9880d681SAndroid Build Coastguard Worker // If the instruction wasn't a matching load or store. Stop searching if we
1338*9880d681SAndroid Build Coastguard Worker // encounter a call instruction that might modify memory.
1339*9880d681SAndroid Build Coastguard Worker if (MI.isCall())
1340*9880d681SAndroid Build Coastguard Worker return E;
1341*9880d681SAndroid Build Coastguard Worker
1342*9880d681SAndroid Build Coastguard Worker // Update modified / uses register lists.
1343*9880d681SAndroid Build Coastguard Worker trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
1344*9880d681SAndroid Build Coastguard Worker
1345*9880d681SAndroid Build Coastguard Worker // Otherwise, if the base register is modified, we have no match, so
1346*9880d681SAndroid Build Coastguard Worker // return early.
1347*9880d681SAndroid Build Coastguard Worker if (ModifiedRegs[BaseReg])
1348*9880d681SAndroid Build Coastguard Worker return E;
1349*9880d681SAndroid Build Coastguard Worker
1350*9880d681SAndroid Build Coastguard Worker // Update list of instructions that read/write memory.
1351*9880d681SAndroid Build Coastguard Worker if (MI.mayLoadOrStore())
1352*9880d681SAndroid Build Coastguard Worker MemInsns.push_back(&MI);
1353*9880d681SAndroid Build Coastguard Worker }
1354*9880d681SAndroid Build Coastguard Worker return E;
1355*9880d681SAndroid Build Coastguard Worker }
1356*9880d681SAndroid Build Coastguard Worker
1357*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator
mergeUpdateInsn(MachineBasicBlock::iterator I,MachineBasicBlock::iterator Update,bool IsPreIdx)1358*9880d681SAndroid Build Coastguard Worker AArch64LoadStoreOpt::mergeUpdateInsn(MachineBasicBlock::iterator I,
1359*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator Update,
1360*9880d681SAndroid Build Coastguard Worker bool IsPreIdx) {
1361*9880d681SAndroid Build Coastguard Worker assert((Update->getOpcode() == AArch64::ADDXri ||
1362*9880d681SAndroid Build Coastguard Worker Update->getOpcode() == AArch64::SUBXri) &&
1363*9880d681SAndroid Build Coastguard Worker "Unexpected base register update instruction to merge!");
1364*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator NextI = I;
1365*9880d681SAndroid Build Coastguard Worker // Return the instruction following the merged instruction, which is
1366*9880d681SAndroid Build Coastguard Worker // the instruction following our unmerged load. Unless that's the add/sub
1367*9880d681SAndroid Build Coastguard Worker // instruction we're merging, in which case it's the one after that.
1368*9880d681SAndroid Build Coastguard Worker if (++NextI == Update)
1369*9880d681SAndroid Build Coastguard Worker ++NextI;
1370*9880d681SAndroid Build Coastguard Worker
1371*9880d681SAndroid Build Coastguard Worker int Value = Update->getOperand(2).getImm();
1372*9880d681SAndroid Build Coastguard Worker assert(AArch64_AM::getShiftValue(Update->getOperand(3).getImm()) == 0 &&
1373*9880d681SAndroid Build Coastguard Worker "Can't merge 1 << 12 offset into pre-/post-indexed load / store");
1374*9880d681SAndroid Build Coastguard Worker if (Update->getOpcode() == AArch64::SUBXri)
1375*9880d681SAndroid Build Coastguard Worker Value = -Value;
1376*9880d681SAndroid Build Coastguard Worker
1377*9880d681SAndroid Build Coastguard Worker unsigned NewOpc = IsPreIdx ? getPreIndexedOpcode(I->getOpcode())
1378*9880d681SAndroid Build Coastguard Worker : getPostIndexedOpcode(I->getOpcode());
1379*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB;
1380*9880d681SAndroid Build Coastguard Worker if (!isPairedLdSt(*I)) {
1381*9880d681SAndroid Build Coastguard Worker // Non-paired instruction.
1382*9880d681SAndroid Build Coastguard Worker MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), TII->get(NewOpc))
1383*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*Update))
1384*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*I))
1385*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStBaseOp(*I))
1386*9880d681SAndroid Build Coastguard Worker .addImm(Value)
1387*9880d681SAndroid Build Coastguard Worker .setMemRefs(I->memoperands_begin(), I->memoperands_end());
1388*9880d681SAndroid Build Coastguard Worker } else {
1389*9880d681SAndroid Build Coastguard Worker // Paired instruction.
1390*9880d681SAndroid Build Coastguard Worker int Scale = getMemScale(*I);
1391*9880d681SAndroid Build Coastguard Worker MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), TII->get(NewOpc))
1392*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*Update))
1393*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*I, 0))
1394*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStRegOp(*I, 1))
1395*9880d681SAndroid Build Coastguard Worker .addOperand(getLdStBaseOp(*I))
1396*9880d681SAndroid Build Coastguard Worker .addImm(Value / Scale)
1397*9880d681SAndroid Build Coastguard Worker .setMemRefs(I->memoperands_begin(), I->memoperands_end());
1398*9880d681SAndroid Build Coastguard Worker }
1399*9880d681SAndroid Build Coastguard Worker (void)MIB;
1400*9880d681SAndroid Build Coastguard Worker
1401*9880d681SAndroid Build Coastguard Worker if (IsPreIdx)
1402*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Creating pre-indexed load/store.");
1403*9880d681SAndroid Build Coastguard Worker else
1404*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Creating post-indexed load/store.");
1405*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Replacing instructions:\n ");
1406*9880d681SAndroid Build Coastguard Worker DEBUG(I->print(dbgs()));
1407*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " ");
1408*9880d681SAndroid Build Coastguard Worker DEBUG(Update->print(dbgs()));
1409*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " with instruction:\n ");
1410*9880d681SAndroid Build Coastguard Worker DEBUG(((MachineInstr *)MIB)->print(dbgs()));
1411*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n");
1412*9880d681SAndroid Build Coastguard Worker
1413*9880d681SAndroid Build Coastguard Worker // Erase the old instructions for the block.
1414*9880d681SAndroid Build Coastguard Worker I->eraseFromParent();
1415*9880d681SAndroid Build Coastguard Worker Update->eraseFromParent();
1416*9880d681SAndroid Build Coastguard Worker
1417*9880d681SAndroid Build Coastguard Worker return NextI;
1418*9880d681SAndroid Build Coastguard Worker }
1419*9880d681SAndroid Build Coastguard Worker
isMatchingUpdateInsn(MachineInstr & MemMI,MachineInstr & MI,unsigned BaseReg,int Offset)1420*9880d681SAndroid Build Coastguard Worker bool AArch64LoadStoreOpt::isMatchingUpdateInsn(MachineInstr &MemMI,
1421*9880d681SAndroid Build Coastguard Worker MachineInstr &MI,
1422*9880d681SAndroid Build Coastguard Worker unsigned BaseReg, int Offset) {
1423*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1424*9880d681SAndroid Build Coastguard Worker default:
1425*9880d681SAndroid Build Coastguard Worker break;
1426*9880d681SAndroid Build Coastguard Worker case AArch64::SUBXri:
1427*9880d681SAndroid Build Coastguard Worker // Negate the offset for a SUB instruction.
1428*9880d681SAndroid Build Coastguard Worker Offset *= -1;
1429*9880d681SAndroid Build Coastguard Worker // FALLTHROUGH
1430*9880d681SAndroid Build Coastguard Worker case AArch64::ADDXri:
1431*9880d681SAndroid Build Coastguard Worker // Make sure it's a vanilla immediate operand, not a relocation or
1432*9880d681SAndroid Build Coastguard Worker // anything else we can't handle.
1433*9880d681SAndroid Build Coastguard Worker if (!MI.getOperand(2).isImm())
1434*9880d681SAndroid Build Coastguard Worker break;
1435*9880d681SAndroid Build Coastguard Worker // Watch out for 1 << 12 shifted value.
1436*9880d681SAndroid Build Coastguard Worker if (AArch64_AM::getShiftValue(MI.getOperand(3).getImm()))
1437*9880d681SAndroid Build Coastguard Worker break;
1438*9880d681SAndroid Build Coastguard Worker
1439*9880d681SAndroid Build Coastguard Worker // The update instruction source and destination register must be the
1440*9880d681SAndroid Build Coastguard Worker // same as the load/store base register.
1441*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(0).getReg() != BaseReg ||
1442*9880d681SAndroid Build Coastguard Worker MI.getOperand(1).getReg() != BaseReg)
1443*9880d681SAndroid Build Coastguard Worker break;
1444*9880d681SAndroid Build Coastguard Worker
1445*9880d681SAndroid Build Coastguard Worker bool IsPairedInsn = isPairedLdSt(MemMI);
1446*9880d681SAndroid Build Coastguard Worker int UpdateOffset = MI.getOperand(2).getImm();
1447*9880d681SAndroid Build Coastguard Worker // For non-paired load/store instructions, the immediate must fit in a
1448*9880d681SAndroid Build Coastguard Worker // signed 9-bit integer.
1449*9880d681SAndroid Build Coastguard Worker if (!IsPairedInsn && (UpdateOffset > 255 || UpdateOffset < -256))
1450*9880d681SAndroid Build Coastguard Worker break;
1451*9880d681SAndroid Build Coastguard Worker
1452*9880d681SAndroid Build Coastguard Worker // For paired load/store instructions, the immediate must be a multiple of
1453*9880d681SAndroid Build Coastguard Worker // the scaling factor. The scaled offset must also fit into a signed 7-bit
1454*9880d681SAndroid Build Coastguard Worker // integer.
1455*9880d681SAndroid Build Coastguard Worker if (IsPairedInsn) {
1456*9880d681SAndroid Build Coastguard Worker int Scale = getMemScale(MemMI);
1457*9880d681SAndroid Build Coastguard Worker if (UpdateOffset % Scale != 0)
1458*9880d681SAndroid Build Coastguard Worker break;
1459*9880d681SAndroid Build Coastguard Worker
1460*9880d681SAndroid Build Coastguard Worker int ScaledOffset = UpdateOffset / Scale;
1461*9880d681SAndroid Build Coastguard Worker if (ScaledOffset > 64 || ScaledOffset < -64)
1462*9880d681SAndroid Build Coastguard Worker break;
1463*9880d681SAndroid Build Coastguard Worker }
1464*9880d681SAndroid Build Coastguard Worker
1465*9880d681SAndroid Build Coastguard Worker // If we have a non-zero Offset, we check that it matches the amount
1466*9880d681SAndroid Build Coastguard Worker // we're adding to the register.
1467*9880d681SAndroid Build Coastguard Worker if (!Offset || Offset == MI.getOperand(2).getImm())
1468*9880d681SAndroid Build Coastguard Worker return true;
1469*9880d681SAndroid Build Coastguard Worker break;
1470*9880d681SAndroid Build Coastguard Worker }
1471*9880d681SAndroid Build Coastguard Worker return false;
1472*9880d681SAndroid Build Coastguard Worker }
1473*9880d681SAndroid Build Coastguard Worker
findMatchingUpdateInsnForward(MachineBasicBlock::iterator I,int UnscaledOffset,unsigned Limit)1474*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator AArch64LoadStoreOpt::findMatchingUpdateInsnForward(
1475*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I, int UnscaledOffset, unsigned Limit) {
1476*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator E = I->getParent()->end();
1477*9880d681SAndroid Build Coastguard Worker MachineInstr &MemMI = *I;
1478*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MBBI = I;
1479*9880d681SAndroid Build Coastguard Worker
1480*9880d681SAndroid Build Coastguard Worker unsigned BaseReg = getLdStBaseOp(MemMI).getReg();
1481*9880d681SAndroid Build Coastguard Worker int MIUnscaledOffset = getLdStOffsetOp(MemMI).getImm() * getMemScale(MemMI);
1482*9880d681SAndroid Build Coastguard Worker
1483*9880d681SAndroid Build Coastguard Worker // Scan forward looking for post-index opportunities. Updating instructions
1484*9880d681SAndroid Build Coastguard Worker // can't be formed if the memory instruction doesn't have the offset we're
1485*9880d681SAndroid Build Coastguard Worker // looking for.
1486*9880d681SAndroid Build Coastguard Worker if (MIUnscaledOffset != UnscaledOffset)
1487*9880d681SAndroid Build Coastguard Worker return E;
1488*9880d681SAndroid Build Coastguard Worker
1489*9880d681SAndroid Build Coastguard Worker // If the base register overlaps a destination register, we can't
1490*9880d681SAndroid Build Coastguard Worker // merge the update.
1491*9880d681SAndroid Build Coastguard Worker bool IsPairedInsn = isPairedLdSt(MemMI);
1492*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = IsPairedInsn ? 2 : 1; i != e; ++i) {
1493*9880d681SAndroid Build Coastguard Worker unsigned DestReg = getLdStRegOp(MemMI, i).getReg();
1494*9880d681SAndroid Build Coastguard Worker if (DestReg == BaseReg || TRI->isSubRegister(BaseReg, DestReg))
1495*9880d681SAndroid Build Coastguard Worker return E;
1496*9880d681SAndroid Build Coastguard Worker }
1497*9880d681SAndroid Build Coastguard Worker
1498*9880d681SAndroid Build Coastguard Worker // Track which registers have been modified and used between the first insn
1499*9880d681SAndroid Build Coastguard Worker // (inclusive) and the second insn.
1500*9880d681SAndroid Build Coastguard Worker ModifiedRegs.reset();
1501*9880d681SAndroid Build Coastguard Worker UsedRegs.reset();
1502*9880d681SAndroid Build Coastguard Worker ++MBBI;
1503*9880d681SAndroid Build Coastguard Worker for (unsigned Count = 0; MBBI != E && Count < Limit; ++MBBI) {
1504*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
1505*9880d681SAndroid Build Coastguard Worker // Skip DBG_VALUE instructions.
1506*9880d681SAndroid Build Coastguard Worker if (MI.isDebugValue())
1507*9880d681SAndroid Build Coastguard Worker continue;
1508*9880d681SAndroid Build Coastguard Worker
1509*9880d681SAndroid Build Coastguard Worker // Now that we know this is a real instruction, count it.
1510*9880d681SAndroid Build Coastguard Worker ++Count;
1511*9880d681SAndroid Build Coastguard Worker
1512*9880d681SAndroid Build Coastguard Worker // If we found a match, return it.
1513*9880d681SAndroid Build Coastguard Worker if (isMatchingUpdateInsn(*I, MI, BaseReg, UnscaledOffset))
1514*9880d681SAndroid Build Coastguard Worker return MBBI;
1515*9880d681SAndroid Build Coastguard Worker
1516*9880d681SAndroid Build Coastguard Worker // Update the status of what the instruction clobbered and used.
1517*9880d681SAndroid Build Coastguard Worker trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
1518*9880d681SAndroid Build Coastguard Worker
1519*9880d681SAndroid Build Coastguard Worker // Otherwise, if the base register is used or modified, we have no match, so
1520*9880d681SAndroid Build Coastguard Worker // return early.
1521*9880d681SAndroid Build Coastguard Worker if (ModifiedRegs[BaseReg] || UsedRegs[BaseReg])
1522*9880d681SAndroid Build Coastguard Worker return E;
1523*9880d681SAndroid Build Coastguard Worker }
1524*9880d681SAndroid Build Coastguard Worker return E;
1525*9880d681SAndroid Build Coastguard Worker }
1526*9880d681SAndroid Build Coastguard Worker
findMatchingUpdateInsnBackward(MachineBasicBlock::iterator I,unsigned Limit)1527*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator AArch64LoadStoreOpt::findMatchingUpdateInsnBackward(
1528*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I, unsigned Limit) {
1529*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator B = I->getParent()->begin();
1530*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator E = I->getParent()->end();
1531*9880d681SAndroid Build Coastguard Worker MachineInstr &MemMI = *I;
1532*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MBBI = I;
1533*9880d681SAndroid Build Coastguard Worker
1534*9880d681SAndroid Build Coastguard Worker unsigned BaseReg = getLdStBaseOp(MemMI).getReg();
1535*9880d681SAndroid Build Coastguard Worker int Offset = getLdStOffsetOp(MemMI).getImm();
1536*9880d681SAndroid Build Coastguard Worker
1537*9880d681SAndroid Build Coastguard Worker // If the load/store is the first instruction in the block, there's obviously
1538*9880d681SAndroid Build Coastguard Worker // not any matching update. Ditto if the memory offset isn't zero.
1539*9880d681SAndroid Build Coastguard Worker if (MBBI == B || Offset != 0)
1540*9880d681SAndroid Build Coastguard Worker return E;
1541*9880d681SAndroid Build Coastguard Worker // If the base register overlaps a destination register, we can't
1542*9880d681SAndroid Build Coastguard Worker // merge the update.
1543*9880d681SAndroid Build Coastguard Worker bool IsPairedInsn = isPairedLdSt(MemMI);
1544*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = IsPairedInsn ? 2 : 1; i != e; ++i) {
1545*9880d681SAndroid Build Coastguard Worker unsigned DestReg = getLdStRegOp(MemMI, i).getReg();
1546*9880d681SAndroid Build Coastguard Worker if (DestReg == BaseReg || TRI->isSubRegister(BaseReg, DestReg))
1547*9880d681SAndroid Build Coastguard Worker return E;
1548*9880d681SAndroid Build Coastguard Worker }
1549*9880d681SAndroid Build Coastguard Worker
1550*9880d681SAndroid Build Coastguard Worker // Track which registers have been modified and used between the first insn
1551*9880d681SAndroid Build Coastguard Worker // (inclusive) and the second insn.
1552*9880d681SAndroid Build Coastguard Worker ModifiedRegs.reset();
1553*9880d681SAndroid Build Coastguard Worker UsedRegs.reset();
1554*9880d681SAndroid Build Coastguard Worker unsigned Count = 0;
1555*9880d681SAndroid Build Coastguard Worker do {
1556*9880d681SAndroid Build Coastguard Worker --MBBI;
1557*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
1558*9880d681SAndroid Build Coastguard Worker
1559*9880d681SAndroid Build Coastguard Worker // Don't count DBG_VALUE instructions towards the search limit.
1560*9880d681SAndroid Build Coastguard Worker if (!MI.isDebugValue())
1561*9880d681SAndroid Build Coastguard Worker ++Count;
1562*9880d681SAndroid Build Coastguard Worker
1563*9880d681SAndroid Build Coastguard Worker // If we found a match, return it.
1564*9880d681SAndroid Build Coastguard Worker if (isMatchingUpdateInsn(*I, MI, BaseReg, Offset))
1565*9880d681SAndroid Build Coastguard Worker return MBBI;
1566*9880d681SAndroid Build Coastguard Worker
1567*9880d681SAndroid Build Coastguard Worker // Update the status of what the instruction clobbered and used.
1568*9880d681SAndroid Build Coastguard Worker trackRegDefsUses(MI, ModifiedRegs, UsedRegs, TRI);
1569*9880d681SAndroid Build Coastguard Worker
1570*9880d681SAndroid Build Coastguard Worker // Otherwise, if the base register is used or modified, we have no match, so
1571*9880d681SAndroid Build Coastguard Worker // return early.
1572*9880d681SAndroid Build Coastguard Worker if (ModifiedRegs[BaseReg] || UsedRegs[BaseReg])
1573*9880d681SAndroid Build Coastguard Worker return E;
1574*9880d681SAndroid Build Coastguard Worker } while (MBBI != B && Count < Limit);
1575*9880d681SAndroid Build Coastguard Worker return E;
1576*9880d681SAndroid Build Coastguard Worker }
1577*9880d681SAndroid Build Coastguard Worker
tryToPromoteLoadFromStore(MachineBasicBlock::iterator & MBBI)1578*9880d681SAndroid Build Coastguard Worker bool AArch64LoadStoreOpt::tryToPromoteLoadFromStore(
1579*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator &MBBI) {
1580*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
1581*9880d681SAndroid Build Coastguard Worker // If this is a volatile load, don't mess with it.
1582*9880d681SAndroid Build Coastguard Worker if (MI.hasOrderedMemoryRef())
1583*9880d681SAndroid Build Coastguard Worker return false;
1584*9880d681SAndroid Build Coastguard Worker
1585*9880d681SAndroid Build Coastguard Worker // Make sure this is a reg+imm.
1586*9880d681SAndroid Build Coastguard Worker // FIXME: It is possible to extend it to handle reg+reg cases.
1587*9880d681SAndroid Build Coastguard Worker if (!getLdStOffsetOp(MI).isImm())
1588*9880d681SAndroid Build Coastguard Worker return false;
1589*9880d681SAndroid Build Coastguard Worker
1590*9880d681SAndroid Build Coastguard Worker // Look backward up to LdStLimit instructions.
1591*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator StoreI;
1592*9880d681SAndroid Build Coastguard Worker if (findMatchingStore(MBBI, LdStLimit, StoreI)) {
1593*9880d681SAndroid Build Coastguard Worker ++NumLoadsFromStoresPromoted;
1594*9880d681SAndroid Build Coastguard Worker // Promote the load. Keeping the iterator straight is a
1595*9880d681SAndroid Build Coastguard Worker // pain, so we let the merge routine tell us what the next instruction
1596*9880d681SAndroid Build Coastguard Worker // is after it's done mucking about.
1597*9880d681SAndroid Build Coastguard Worker MBBI = promoteLoadFromStore(MBBI, StoreI);
1598*9880d681SAndroid Build Coastguard Worker return true;
1599*9880d681SAndroid Build Coastguard Worker }
1600*9880d681SAndroid Build Coastguard Worker return false;
1601*9880d681SAndroid Build Coastguard Worker }
1602*9880d681SAndroid Build Coastguard Worker
1603*9880d681SAndroid Build Coastguard Worker // Find narrow loads that can be converted into a single wider load with
1604*9880d681SAndroid Build Coastguard Worker // bitfield extract instructions. Also merge adjacent zero stores into a wider
1605*9880d681SAndroid Build Coastguard Worker // store.
tryToMergeLdStInst(MachineBasicBlock::iterator & MBBI)1606*9880d681SAndroid Build Coastguard Worker bool AArch64LoadStoreOpt::tryToMergeLdStInst(
1607*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator &MBBI) {
1608*9880d681SAndroid Build Coastguard Worker assert((isNarrowLoad(*MBBI) || isPromotableZeroStoreOpcode(*MBBI)) &&
1609*9880d681SAndroid Build Coastguard Worker "Expected narrow op.");
1610*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
1611*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator E = MI.getParent()->end();
1612*9880d681SAndroid Build Coastguard Worker
1613*9880d681SAndroid Build Coastguard Worker if (!TII->isCandidateToMergeOrPair(MI))
1614*9880d681SAndroid Build Coastguard Worker return false;
1615*9880d681SAndroid Build Coastguard Worker
1616*9880d681SAndroid Build Coastguard Worker // For promotable zero stores, the stored value should be WZR.
1617*9880d681SAndroid Build Coastguard Worker if (isPromotableZeroStoreOpcode(MI) &&
1618*9880d681SAndroid Build Coastguard Worker getLdStRegOp(MI).getReg() != AArch64::WZR)
1619*9880d681SAndroid Build Coastguard Worker return false;
1620*9880d681SAndroid Build Coastguard Worker
1621*9880d681SAndroid Build Coastguard Worker // Look ahead up to LdStLimit instructions for a mergable instruction.
1622*9880d681SAndroid Build Coastguard Worker LdStPairFlags Flags;
1623*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MergeMI =
1624*9880d681SAndroid Build Coastguard Worker findMatchingInsn(MBBI, Flags, LdStLimit, /* FindNarrowMerge = */ true);
1625*9880d681SAndroid Build Coastguard Worker if (MergeMI != E) {
1626*9880d681SAndroid Build Coastguard Worker if (isNarrowLoad(MI)) {
1627*9880d681SAndroid Build Coastguard Worker ++NumNarrowLoadsPromoted;
1628*9880d681SAndroid Build Coastguard Worker } else if (isPromotableZeroStoreInst(MI)) {
1629*9880d681SAndroid Build Coastguard Worker ++NumZeroStoresPromoted;
1630*9880d681SAndroid Build Coastguard Worker }
1631*9880d681SAndroid Build Coastguard Worker // Keeping the iterator straight is a pain, so we let the merge routine tell
1632*9880d681SAndroid Build Coastguard Worker // us what the next instruction is after it's done mucking about.
1633*9880d681SAndroid Build Coastguard Worker MBBI = mergeNarrowInsns(MBBI, MergeMI, Flags);
1634*9880d681SAndroid Build Coastguard Worker return true;
1635*9880d681SAndroid Build Coastguard Worker }
1636*9880d681SAndroid Build Coastguard Worker return false;
1637*9880d681SAndroid Build Coastguard Worker }
1638*9880d681SAndroid Build Coastguard Worker
1639*9880d681SAndroid Build Coastguard Worker // Find loads and stores that can be merged into a single load or store pair
1640*9880d681SAndroid Build Coastguard Worker // instruction.
tryToPairLdStInst(MachineBasicBlock::iterator & MBBI)1641*9880d681SAndroid Build Coastguard Worker bool AArch64LoadStoreOpt::tryToPairLdStInst(MachineBasicBlock::iterator &MBBI) {
1642*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
1643*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator E = MI.getParent()->end();
1644*9880d681SAndroid Build Coastguard Worker
1645*9880d681SAndroid Build Coastguard Worker if (!TII->isCandidateToMergeOrPair(MI))
1646*9880d681SAndroid Build Coastguard Worker return false;
1647*9880d681SAndroid Build Coastguard Worker
1648*9880d681SAndroid Build Coastguard Worker // Early exit if the offset is not possible to match. (6 bits of positive
1649*9880d681SAndroid Build Coastguard Worker // range, plus allow an extra one in case we find a later insn that matches
1650*9880d681SAndroid Build Coastguard Worker // with Offset-1)
1651*9880d681SAndroid Build Coastguard Worker bool IsUnscaled = TII->isUnscaledLdSt(MI);
1652*9880d681SAndroid Build Coastguard Worker int Offset = getLdStOffsetOp(MI).getImm();
1653*9880d681SAndroid Build Coastguard Worker int OffsetStride = IsUnscaled ? getMemScale(MI) : 1;
1654*9880d681SAndroid Build Coastguard Worker if (!inBoundsForPair(IsUnscaled, Offset, OffsetStride))
1655*9880d681SAndroid Build Coastguard Worker return false;
1656*9880d681SAndroid Build Coastguard Worker
1657*9880d681SAndroid Build Coastguard Worker // Look ahead up to LdStLimit instructions for a pairable instruction.
1658*9880d681SAndroid Build Coastguard Worker LdStPairFlags Flags;
1659*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator Paired =
1660*9880d681SAndroid Build Coastguard Worker findMatchingInsn(MBBI, Flags, LdStLimit, /* FindNarrowMerge = */ false);
1661*9880d681SAndroid Build Coastguard Worker if (Paired != E) {
1662*9880d681SAndroid Build Coastguard Worker ++NumPairCreated;
1663*9880d681SAndroid Build Coastguard Worker if (TII->isUnscaledLdSt(MI))
1664*9880d681SAndroid Build Coastguard Worker ++NumUnscaledPairCreated;
1665*9880d681SAndroid Build Coastguard Worker // Keeping the iterator straight is a pain, so we let the merge routine tell
1666*9880d681SAndroid Build Coastguard Worker // us what the next instruction is after it's done mucking about.
1667*9880d681SAndroid Build Coastguard Worker MBBI = mergePairedInsns(MBBI, Paired, Flags);
1668*9880d681SAndroid Build Coastguard Worker return true;
1669*9880d681SAndroid Build Coastguard Worker }
1670*9880d681SAndroid Build Coastguard Worker return false;
1671*9880d681SAndroid Build Coastguard Worker }
1672*9880d681SAndroid Build Coastguard Worker
optimizeBlock(MachineBasicBlock & MBB,bool enableNarrowLdOpt)1673*9880d681SAndroid Build Coastguard Worker bool AArch64LoadStoreOpt::optimizeBlock(MachineBasicBlock &MBB,
1674*9880d681SAndroid Build Coastguard Worker bool enableNarrowLdOpt) {
1675*9880d681SAndroid Build Coastguard Worker bool Modified = false;
1676*9880d681SAndroid Build Coastguard Worker // Four tranformations to do here:
1677*9880d681SAndroid Build Coastguard Worker // 1) Find loads that directly read from stores and promote them by
1678*9880d681SAndroid Build Coastguard Worker // replacing with mov instructions. If the store is wider than the load,
1679*9880d681SAndroid Build Coastguard Worker // the load will be replaced with a bitfield extract.
1680*9880d681SAndroid Build Coastguard Worker // e.g.,
1681*9880d681SAndroid Build Coastguard Worker // str w1, [x0, #4]
1682*9880d681SAndroid Build Coastguard Worker // ldrh w2, [x0, #6]
1683*9880d681SAndroid Build Coastguard Worker // ; becomes
1684*9880d681SAndroid Build Coastguard Worker // str w1, [x0, #4]
1685*9880d681SAndroid Build Coastguard Worker // lsr w2, w1, #16
1686*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
1687*9880d681SAndroid Build Coastguard Worker MBBI != E;) {
1688*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
1689*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1690*9880d681SAndroid Build Coastguard Worker default:
1691*9880d681SAndroid Build Coastguard Worker // Just move on to the next instruction.
1692*9880d681SAndroid Build Coastguard Worker ++MBBI;
1693*9880d681SAndroid Build Coastguard Worker break;
1694*9880d681SAndroid Build Coastguard Worker // Scaled instructions.
1695*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
1696*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
1697*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
1698*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
1699*9880d681SAndroid Build Coastguard Worker // Unscaled instructions.
1700*9880d681SAndroid Build Coastguard Worker case AArch64::LDURBBi:
1701*9880d681SAndroid Build Coastguard Worker case AArch64::LDURHHi:
1702*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
1703*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi: {
1704*9880d681SAndroid Build Coastguard Worker if (tryToPromoteLoadFromStore(MBBI)) {
1705*9880d681SAndroid Build Coastguard Worker Modified = true;
1706*9880d681SAndroid Build Coastguard Worker break;
1707*9880d681SAndroid Build Coastguard Worker }
1708*9880d681SAndroid Build Coastguard Worker ++MBBI;
1709*9880d681SAndroid Build Coastguard Worker break;
1710*9880d681SAndroid Build Coastguard Worker }
1711*9880d681SAndroid Build Coastguard Worker }
1712*9880d681SAndroid Build Coastguard Worker }
1713*9880d681SAndroid Build Coastguard Worker // 2) Find narrow loads that can be converted into a single wider load
1714*9880d681SAndroid Build Coastguard Worker // with bitfield extract instructions.
1715*9880d681SAndroid Build Coastguard Worker // e.g.,
1716*9880d681SAndroid Build Coastguard Worker // ldrh w0, [x2]
1717*9880d681SAndroid Build Coastguard Worker // ldrh w1, [x2, #2]
1718*9880d681SAndroid Build Coastguard Worker // ; becomes
1719*9880d681SAndroid Build Coastguard Worker // ldr w0, [x2]
1720*9880d681SAndroid Build Coastguard Worker // ubfx w1, w0, #16, #16
1721*9880d681SAndroid Build Coastguard Worker // and w0, w0, #ffff
1722*9880d681SAndroid Build Coastguard Worker //
1723*9880d681SAndroid Build Coastguard Worker // Also merge adjacent zero stores into a wider store.
1724*9880d681SAndroid Build Coastguard Worker // e.g.,
1725*9880d681SAndroid Build Coastguard Worker // strh wzr, [x0]
1726*9880d681SAndroid Build Coastguard Worker // strh wzr, [x0, #2]
1727*9880d681SAndroid Build Coastguard Worker // ; becomes
1728*9880d681SAndroid Build Coastguard Worker // str wzr, [x0]
1729*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
1730*9880d681SAndroid Build Coastguard Worker enableNarrowLdOpt && MBBI != E;) {
1731*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
1732*9880d681SAndroid Build Coastguard Worker unsigned Opc = MI.getOpcode();
1733*9880d681SAndroid Build Coastguard Worker if (isPromotableZeroStoreOpcode(Opc) ||
1734*9880d681SAndroid Build Coastguard Worker (EnableNarrowLdMerge && isNarrowLoad(Opc))) {
1735*9880d681SAndroid Build Coastguard Worker if (tryToMergeLdStInst(MBBI)) {
1736*9880d681SAndroid Build Coastguard Worker Modified = true;
1737*9880d681SAndroid Build Coastguard Worker } else
1738*9880d681SAndroid Build Coastguard Worker ++MBBI;
1739*9880d681SAndroid Build Coastguard Worker } else
1740*9880d681SAndroid Build Coastguard Worker ++MBBI;
1741*9880d681SAndroid Build Coastguard Worker }
1742*9880d681SAndroid Build Coastguard Worker
1743*9880d681SAndroid Build Coastguard Worker // 3) Find loads and stores that can be merged into a single load or store
1744*9880d681SAndroid Build Coastguard Worker // pair instruction.
1745*9880d681SAndroid Build Coastguard Worker // e.g.,
1746*9880d681SAndroid Build Coastguard Worker // ldr x0, [x2]
1747*9880d681SAndroid Build Coastguard Worker // ldr x1, [x2, #8]
1748*9880d681SAndroid Build Coastguard Worker // ; becomes
1749*9880d681SAndroid Build Coastguard Worker // ldp x0, x1, [x2]
1750*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
1751*9880d681SAndroid Build Coastguard Worker MBBI != E;) {
1752*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
1753*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1754*9880d681SAndroid Build Coastguard Worker default:
1755*9880d681SAndroid Build Coastguard Worker // Just move on to the next instruction.
1756*9880d681SAndroid Build Coastguard Worker ++MBBI;
1757*9880d681SAndroid Build Coastguard Worker break;
1758*9880d681SAndroid Build Coastguard Worker // Scaled instructions.
1759*9880d681SAndroid Build Coastguard Worker case AArch64::STRSui:
1760*9880d681SAndroid Build Coastguard Worker case AArch64::STRDui:
1761*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
1762*9880d681SAndroid Build Coastguard Worker case AArch64::STRXui:
1763*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
1764*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSui:
1765*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDui:
1766*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
1767*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
1768*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
1769*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSWui:
1770*9880d681SAndroid Build Coastguard Worker // Unscaled instructions.
1771*9880d681SAndroid Build Coastguard Worker case AArch64::STURSi:
1772*9880d681SAndroid Build Coastguard Worker case AArch64::STURDi:
1773*9880d681SAndroid Build Coastguard Worker case AArch64::STURQi:
1774*9880d681SAndroid Build Coastguard Worker case AArch64::STURWi:
1775*9880d681SAndroid Build Coastguard Worker case AArch64::STURXi:
1776*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSi:
1777*9880d681SAndroid Build Coastguard Worker case AArch64::LDURDi:
1778*9880d681SAndroid Build Coastguard Worker case AArch64::LDURQi:
1779*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
1780*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi:
1781*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSWi: {
1782*9880d681SAndroid Build Coastguard Worker if (tryToPairLdStInst(MBBI)) {
1783*9880d681SAndroid Build Coastguard Worker Modified = true;
1784*9880d681SAndroid Build Coastguard Worker break;
1785*9880d681SAndroid Build Coastguard Worker }
1786*9880d681SAndroid Build Coastguard Worker ++MBBI;
1787*9880d681SAndroid Build Coastguard Worker break;
1788*9880d681SAndroid Build Coastguard Worker }
1789*9880d681SAndroid Build Coastguard Worker }
1790*9880d681SAndroid Build Coastguard Worker }
1791*9880d681SAndroid Build Coastguard Worker // 4) Find base register updates that can be merged into the load or store
1792*9880d681SAndroid Build Coastguard Worker // as a base-reg writeback.
1793*9880d681SAndroid Build Coastguard Worker // e.g.,
1794*9880d681SAndroid Build Coastguard Worker // ldr x0, [x2]
1795*9880d681SAndroid Build Coastguard Worker // add x2, x2, #4
1796*9880d681SAndroid Build Coastguard Worker // ; becomes
1797*9880d681SAndroid Build Coastguard Worker // ldr x0, [x2], #4
1798*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
1799*9880d681SAndroid Build Coastguard Worker MBBI != E;) {
1800*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MBBI;
1801*9880d681SAndroid Build Coastguard Worker // Do update merging. It's simpler to keep this separate from the above
1802*9880d681SAndroid Build Coastguard Worker // switchs, though not strictly necessary.
1803*9880d681SAndroid Build Coastguard Worker unsigned Opc = MI.getOpcode();
1804*9880d681SAndroid Build Coastguard Worker switch (Opc) {
1805*9880d681SAndroid Build Coastguard Worker default:
1806*9880d681SAndroid Build Coastguard Worker // Just move on to the next instruction.
1807*9880d681SAndroid Build Coastguard Worker ++MBBI;
1808*9880d681SAndroid Build Coastguard Worker break;
1809*9880d681SAndroid Build Coastguard Worker // Scaled instructions.
1810*9880d681SAndroid Build Coastguard Worker case AArch64::STRSui:
1811*9880d681SAndroid Build Coastguard Worker case AArch64::STRDui:
1812*9880d681SAndroid Build Coastguard Worker case AArch64::STRQui:
1813*9880d681SAndroid Build Coastguard Worker case AArch64::STRXui:
1814*9880d681SAndroid Build Coastguard Worker case AArch64::STRWui:
1815*9880d681SAndroid Build Coastguard Worker case AArch64::STRHHui:
1816*9880d681SAndroid Build Coastguard Worker case AArch64::STRBBui:
1817*9880d681SAndroid Build Coastguard Worker case AArch64::LDRSui:
1818*9880d681SAndroid Build Coastguard Worker case AArch64::LDRDui:
1819*9880d681SAndroid Build Coastguard Worker case AArch64::LDRQui:
1820*9880d681SAndroid Build Coastguard Worker case AArch64::LDRXui:
1821*9880d681SAndroid Build Coastguard Worker case AArch64::LDRWui:
1822*9880d681SAndroid Build Coastguard Worker case AArch64::LDRHHui:
1823*9880d681SAndroid Build Coastguard Worker case AArch64::LDRBBui:
1824*9880d681SAndroid Build Coastguard Worker // Unscaled instructions.
1825*9880d681SAndroid Build Coastguard Worker case AArch64::STURSi:
1826*9880d681SAndroid Build Coastguard Worker case AArch64::STURDi:
1827*9880d681SAndroid Build Coastguard Worker case AArch64::STURQi:
1828*9880d681SAndroid Build Coastguard Worker case AArch64::STURWi:
1829*9880d681SAndroid Build Coastguard Worker case AArch64::STURXi:
1830*9880d681SAndroid Build Coastguard Worker case AArch64::LDURSi:
1831*9880d681SAndroid Build Coastguard Worker case AArch64::LDURDi:
1832*9880d681SAndroid Build Coastguard Worker case AArch64::LDURQi:
1833*9880d681SAndroid Build Coastguard Worker case AArch64::LDURWi:
1834*9880d681SAndroid Build Coastguard Worker case AArch64::LDURXi:
1835*9880d681SAndroid Build Coastguard Worker // Paired instructions.
1836*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSi:
1837*9880d681SAndroid Build Coastguard Worker case AArch64::LDPSWi:
1838*9880d681SAndroid Build Coastguard Worker case AArch64::LDPDi:
1839*9880d681SAndroid Build Coastguard Worker case AArch64::LDPQi:
1840*9880d681SAndroid Build Coastguard Worker case AArch64::LDPWi:
1841*9880d681SAndroid Build Coastguard Worker case AArch64::LDPXi:
1842*9880d681SAndroid Build Coastguard Worker case AArch64::STPSi:
1843*9880d681SAndroid Build Coastguard Worker case AArch64::STPDi:
1844*9880d681SAndroid Build Coastguard Worker case AArch64::STPQi:
1845*9880d681SAndroid Build Coastguard Worker case AArch64::STPWi:
1846*9880d681SAndroid Build Coastguard Worker case AArch64::STPXi: {
1847*9880d681SAndroid Build Coastguard Worker // Make sure this is a reg+imm (as opposed to an address reloc).
1848*9880d681SAndroid Build Coastguard Worker if (!getLdStOffsetOp(MI).isImm()) {
1849*9880d681SAndroid Build Coastguard Worker ++MBBI;
1850*9880d681SAndroid Build Coastguard Worker break;
1851*9880d681SAndroid Build Coastguard Worker }
1852*9880d681SAndroid Build Coastguard Worker // Look forward to try to form a post-index instruction. For example,
1853*9880d681SAndroid Build Coastguard Worker // ldr x0, [x20]
1854*9880d681SAndroid Build Coastguard Worker // add x20, x20, #32
1855*9880d681SAndroid Build Coastguard Worker // merged into:
1856*9880d681SAndroid Build Coastguard Worker // ldr x0, [x20], #32
1857*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator Update =
1858*9880d681SAndroid Build Coastguard Worker findMatchingUpdateInsnForward(MBBI, 0, UpdateLimit);
1859*9880d681SAndroid Build Coastguard Worker if (Update != E) {
1860*9880d681SAndroid Build Coastguard Worker // Merge the update into the ld/st.
1861*9880d681SAndroid Build Coastguard Worker MBBI = mergeUpdateInsn(MBBI, Update, /*IsPreIdx=*/false);
1862*9880d681SAndroid Build Coastguard Worker Modified = true;
1863*9880d681SAndroid Build Coastguard Worker ++NumPostFolded;
1864*9880d681SAndroid Build Coastguard Worker break;
1865*9880d681SAndroid Build Coastguard Worker }
1866*9880d681SAndroid Build Coastguard Worker // Don't know how to handle pre/post-index versions, so move to the next
1867*9880d681SAndroid Build Coastguard Worker // instruction.
1868*9880d681SAndroid Build Coastguard Worker if (TII->isUnscaledLdSt(Opc)) {
1869*9880d681SAndroid Build Coastguard Worker ++MBBI;
1870*9880d681SAndroid Build Coastguard Worker break;
1871*9880d681SAndroid Build Coastguard Worker }
1872*9880d681SAndroid Build Coastguard Worker
1873*9880d681SAndroid Build Coastguard Worker // Look back to try to find a pre-index instruction. For example,
1874*9880d681SAndroid Build Coastguard Worker // add x0, x0, #8
1875*9880d681SAndroid Build Coastguard Worker // ldr x1, [x0]
1876*9880d681SAndroid Build Coastguard Worker // merged into:
1877*9880d681SAndroid Build Coastguard Worker // ldr x1, [x0, #8]!
1878*9880d681SAndroid Build Coastguard Worker Update = findMatchingUpdateInsnBackward(MBBI, UpdateLimit);
1879*9880d681SAndroid Build Coastguard Worker if (Update != E) {
1880*9880d681SAndroid Build Coastguard Worker // Merge the update into the ld/st.
1881*9880d681SAndroid Build Coastguard Worker MBBI = mergeUpdateInsn(MBBI, Update, /*IsPreIdx=*/true);
1882*9880d681SAndroid Build Coastguard Worker Modified = true;
1883*9880d681SAndroid Build Coastguard Worker ++NumPreFolded;
1884*9880d681SAndroid Build Coastguard Worker break;
1885*9880d681SAndroid Build Coastguard Worker }
1886*9880d681SAndroid Build Coastguard Worker // The immediate in the load/store is scaled by the size of the memory
1887*9880d681SAndroid Build Coastguard Worker // operation. The immediate in the add we're looking for,
1888*9880d681SAndroid Build Coastguard Worker // however, is not, so adjust here.
1889*9880d681SAndroid Build Coastguard Worker int UnscaledOffset = getLdStOffsetOp(MI).getImm() * getMemScale(MI);
1890*9880d681SAndroid Build Coastguard Worker
1891*9880d681SAndroid Build Coastguard Worker // Look forward to try to find a post-index instruction. For example,
1892*9880d681SAndroid Build Coastguard Worker // ldr x1, [x0, #64]
1893*9880d681SAndroid Build Coastguard Worker // add x0, x0, #64
1894*9880d681SAndroid Build Coastguard Worker // merged into:
1895*9880d681SAndroid Build Coastguard Worker // ldr x1, [x0, #64]!
1896*9880d681SAndroid Build Coastguard Worker Update = findMatchingUpdateInsnForward(MBBI, UnscaledOffset, UpdateLimit);
1897*9880d681SAndroid Build Coastguard Worker if (Update != E) {
1898*9880d681SAndroid Build Coastguard Worker // Merge the update into the ld/st.
1899*9880d681SAndroid Build Coastguard Worker MBBI = mergeUpdateInsn(MBBI, Update, /*IsPreIdx=*/true);
1900*9880d681SAndroid Build Coastguard Worker Modified = true;
1901*9880d681SAndroid Build Coastguard Worker ++NumPreFolded;
1902*9880d681SAndroid Build Coastguard Worker break;
1903*9880d681SAndroid Build Coastguard Worker }
1904*9880d681SAndroid Build Coastguard Worker
1905*9880d681SAndroid Build Coastguard Worker // Nothing found. Just move to the next instruction.
1906*9880d681SAndroid Build Coastguard Worker ++MBBI;
1907*9880d681SAndroid Build Coastguard Worker break;
1908*9880d681SAndroid Build Coastguard Worker }
1909*9880d681SAndroid Build Coastguard Worker }
1910*9880d681SAndroid Build Coastguard Worker }
1911*9880d681SAndroid Build Coastguard Worker
1912*9880d681SAndroid Build Coastguard Worker return Modified;
1913*9880d681SAndroid Build Coastguard Worker }
1914*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & Fn)1915*9880d681SAndroid Build Coastguard Worker bool AArch64LoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
1916*9880d681SAndroid Build Coastguard Worker if (skipFunction(*Fn.getFunction()))
1917*9880d681SAndroid Build Coastguard Worker return false;
1918*9880d681SAndroid Build Coastguard Worker
1919*9880d681SAndroid Build Coastguard Worker Subtarget = &static_cast<const AArch64Subtarget &>(Fn.getSubtarget());
1920*9880d681SAndroid Build Coastguard Worker TII = static_cast<const AArch64InstrInfo *>(Subtarget->getInstrInfo());
1921*9880d681SAndroid Build Coastguard Worker TRI = Subtarget->getRegisterInfo();
1922*9880d681SAndroid Build Coastguard Worker
1923*9880d681SAndroid Build Coastguard Worker // Resize the modified and used register bitfield trackers. We do this once
1924*9880d681SAndroid Build Coastguard Worker // per function and then clear the bitfield each time we optimize a load or
1925*9880d681SAndroid Build Coastguard Worker // store.
1926*9880d681SAndroid Build Coastguard Worker ModifiedRegs.resize(TRI->getNumRegs());
1927*9880d681SAndroid Build Coastguard Worker UsedRegs.resize(TRI->getNumRegs());
1928*9880d681SAndroid Build Coastguard Worker
1929*9880d681SAndroid Build Coastguard Worker bool Modified = false;
1930*9880d681SAndroid Build Coastguard Worker bool enableNarrowLdOpt =
1931*9880d681SAndroid Build Coastguard Worker Subtarget->mergeNarrowLoads() && !Subtarget->requiresStrictAlign();
1932*9880d681SAndroid Build Coastguard Worker for (auto &MBB : Fn)
1933*9880d681SAndroid Build Coastguard Worker Modified |= optimizeBlock(MBB, enableNarrowLdOpt);
1934*9880d681SAndroid Build Coastguard Worker
1935*9880d681SAndroid Build Coastguard Worker return Modified;
1936*9880d681SAndroid Build Coastguard Worker }
1937*9880d681SAndroid Build Coastguard Worker
1938*9880d681SAndroid Build Coastguard Worker // FIXME: Do we need/want a pre-alloc pass like ARM has to try to keep
1939*9880d681SAndroid Build Coastguard Worker // loads and stores near one another?
1940*9880d681SAndroid Build Coastguard Worker
1941*9880d681SAndroid Build Coastguard Worker // FIXME: When pairing store instructions it's very possible for this pass to
1942*9880d681SAndroid Build Coastguard Worker // hoist a store with a KILL marker above another use (without a KILL marker).
1943*9880d681SAndroid Build Coastguard Worker // The resulting IR is invalid, but nothing uses the KILL markers after this
1944*9880d681SAndroid Build Coastguard Worker // pass, so it's never caused a problem in practice.
1945*9880d681SAndroid Build Coastguard Worker
1946*9880d681SAndroid Build Coastguard Worker /// createAArch64LoadStoreOptimizationPass - returns an instance of the
1947*9880d681SAndroid Build Coastguard Worker /// load / store optimization pass.
createAArch64LoadStoreOptimizationPass()1948*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createAArch64LoadStoreOptimizationPass() {
1949*9880d681SAndroid Build Coastguard Worker return new AArch64LoadStoreOpt();
1950*9880d681SAndroid Build Coastguard Worker }
1951