1 //== llvm/CodeGen/GlobalISel/LoadStoreOpt.h - LoadStoreOpt -------*- C++ -*-==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// This is an optimization pass for GlobalISel generic memory operations.
10 /// Specifically, it focuses on merging stores and loads to consecutive
11 /// addresses.
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CODEGEN_GLOBALISEL_LOADSTOREOPT_H
15 #define LLVM_CODEGEN_GLOBALISEL_LOADSTOREOPT_H
16 
17 #include "llvm/ADT/BitVector.h"
18 #include "llvm/ADT/SmallPtrSet.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/Analysis/AliasAnalysis.h"
21 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
22 #include "llvm/CodeGen/MachineFunction.h"
23 #include "llvm/CodeGen/MachineFunctionPass.h"
24 
25 namespace llvm {
26 // Forward declarations.
27 class AnalysisUsage;
28 class GStore;
29 class LegalizerInfo;
30 class MachineBasicBlock;
31 class MachineInstr;
32 class TargetLowering;
33 struct LegalityQuery;
34 class MachineRegisterInfo;
35 namespace GISelAddressing {
36 /// Helper struct to store a base, index and offset that forms an address
37 struct BaseIndexOffset {
38   Register BaseReg;
39   Register IndexReg;
40   int64_t Offset = 0;
41   bool IsIndexSignExt = false;
42 };
43 
44 /// Returns a BaseIndexOffset which describes the pointer in \p Ptr.
45 BaseIndexOffset getPointerInfo(Register Ptr, MachineRegisterInfo &MRI);
46 
47 /// Compute whether or not a memory access at \p MI1 aliases with an access at
48 /// \p MI2 \returns true if either alias/no-alias is known. Sets \p IsAlias
49 /// accordingly.
50 bool aliasIsKnownForLoadStore(const MachineInstr &MI1, const MachineInstr &MI2,
51                               bool &IsAlias, MachineRegisterInfo &MRI);
52 
53 /// Returns true if the instruction \p MI may alias \p Other.
54 /// This function uses multiple strategies to detect aliasing, whereas
55 /// aliasIsKnownForLoadStore just looks at the addresses of load/stores and is
56 /// tries to reason about base/index/offsets.
57 bool instMayAlias(const MachineInstr &MI, const MachineInstr &Other,
58                   MachineRegisterInfo &MRI, AliasAnalysis *AA);
59 } // namespace GISelAddressing
60 
61 using namespace GISelAddressing;
62 
63 class LoadStoreOpt : public MachineFunctionPass {
64 public:
65   static char ID;
66 
67 private:
68   /// An input function to decide if the pass should run or not
69   /// on the given MachineFunction.
70   std::function<bool(const MachineFunction &)> DoNotRunPass;
71 
72   MachineRegisterInfo *MRI = nullptr;
73   const TargetLowering *TLI = nullptr;
74   MachineFunction *MF = nullptr;
75   AliasAnalysis *AA = nullptr;
76   const LegalizerInfo *LI = nullptr;
77 
78   MachineIRBuilder Builder;
79 
80   /// Initialize the field members using \p MF.
81   void init(MachineFunction &MF);
82 
83   class StoreMergeCandidate {
84   public:
85     // The base pointer used as the base for all stores in this candidate.
86     Register BasePtr;
87     // Our algorithm is very simple at the moment. We assume that in instruction
88     // order stores are writing to incremeneting consecutive addresses. So when
89     // we walk the block in reverse order, the next eligible store must write to
90     // an offset one store width lower than CurrentLowestOffset.
91     uint64_t CurrentLowestOffset;
92     SmallVector<GStore *> Stores;
93     // A vector of MachineInstr/unsigned pairs to denote potential aliases that
94     // need to be checked before the candidate is considered safe to merge. The
95     // unsigned value is an index into the Stores vector. The indexed store is
96     // the highest-indexed store that has already been checked to not have an
97     // alias with the instruction. We record this so we don't have to repeat
98     // alias checks that have been already done, only those with stores added
99     // after the potential alias is recorded.
100     SmallVector<std::pair<MachineInstr *, unsigned>> PotentialAliases;
101 
102     void addPotentialAlias(MachineInstr &MI);
103 
104     /// Reset this candidate back to an empty one.
105     void reset() {
106       Stores.clear();
107       PotentialAliases.clear();
108       CurrentLowestOffset = 0;
109       BasePtr = Register();
110     }
111   };
112 
113   bool isLegalOrBeforeLegalizer(const LegalityQuery &Query,
114                                 MachineFunction &MF) const;
115   /// If the given store is valid to be a member of the candidate, add it and
116   /// return true. Otherwise, returns false.
117   bool addStoreToCandidate(GStore &MI, StoreMergeCandidate &C);
118   /// Returns true if the instruction \p MI would potentially alias with any
119   /// stores in the candidate \p C.
120   bool operationAliasesWithCandidate(MachineInstr &MI, StoreMergeCandidate &C);
121   /// Merges the stores in the given vector into a wide store.
122   /// \p returns true if at least some of the stores were merged.
123   /// This may decide not to merge stores if heuristics predict it will not be
124   /// worth it.
125   bool mergeStores(SmallVectorImpl<GStore *> &StoresToMerge);
126   /// Perform a merge of all the stores in \p Stores into a single store.
127   /// Erases the old stores from the block when finished.
128   /// \returns true if merging was done. It may fail to perform a merge if
129   /// there are issues with materializing legal wide values.
130   bool doSingleStoreMerge(SmallVectorImpl<GStore *> &Stores);
131   bool processMergeCandidate(StoreMergeCandidate &C);
132   bool mergeBlockStores(MachineBasicBlock &MBB);
133   bool mergeFunctionStores(MachineFunction &MF);
134 
135   bool mergeTruncStore(GStore &StoreMI,
136                        SmallPtrSetImpl<GStore *> &DeletedStores);
137   bool mergeTruncStoresBlock(MachineBasicBlock &MBB);
138 
139   /// Initialize some target-specific data structures for the store merging
140   /// optimization. \p AddrSpace indicates which address space to use when
141   /// probing the legalizer info for legal stores.
142   void initializeStoreMergeTargetInfo(unsigned AddrSpace = 0);
143   /// A map between address space numbers and a bitvector of supported stores
144   /// sizes. Each bit in the bitvector represents whether a store size of
145   /// that bit's value is legal. E.g. if bit 64 is set, then 64 bit scalar
146   /// stores are legal.
147   DenseMap<unsigned, BitVector> LegalStoreSizes;
148   bool IsPreLegalizer = false;
149   /// Contains instructions to be erased at the end of a block scan.
150   SmallSet<MachineInstr *, 16> InstsToErase;
151 
152 public:
153   LoadStoreOpt();
154   LoadStoreOpt(std::function<bool(const MachineFunction &)>);
155 
156   StringRef getPassName() const override { return "LoadStoreOpt"; }
157 
158   MachineFunctionProperties getRequiredProperties() const override {
159     return MachineFunctionProperties()
160         .set(MachineFunctionProperties::Property::IsSSA);
161   }
162 
163   void getAnalysisUsage(AnalysisUsage &AU) const override;
164 
165   bool runOnMachineFunction(MachineFunction &MF) override;
166 };
167 
168 } // End namespace llvm.
169 
170 #endif
171