Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:25

0001 //== llvm/CodeGen/GlobalISel/LoadStoreOpt.h - LoadStoreOpt -------*- C++ -*-==//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 /// This is an optimization pass for GlobalISel generic memory operations.
0010 /// Specifically, it focuses on merging stores and loads to consecutive
0011 /// addresses.
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CODEGEN_GLOBALISEL_LOADSTOREOPT_H
0015 #define LLVM_CODEGEN_GLOBALISEL_LOADSTOREOPT_H
0016 
0017 #include "llvm/ADT/BitVector.h"
0018 #include "llvm/ADT/SmallPtrSet.h"
0019 #include "llvm/ADT/SmallSet.h"
0020 #include "llvm/ADT/SmallVector.h"
0021 #include "llvm/Analysis/AliasAnalysis.h"
0022 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
0023 #include "llvm/CodeGen/MachineFunction.h"
0024 #include "llvm/CodeGen/MachineFunctionPass.h"
0025 
0026 namespace llvm {
0027 // Forward declarations.
0028 class AnalysisUsage;
0029 class GStore;
0030 class LegalizerInfo;
0031 class MachineBasicBlock;
0032 class MachineInstr;
0033 class TargetLowering;
0034 struct LegalityQuery;
0035 class MachineRegisterInfo;
0036 namespace GISelAddressing {
0037 /// Helper struct to store a base, index and offset that forms an address
0038 class BaseIndexOffset {
0039 private:
0040   Register BaseReg;
0041   Register IndexReg;
0042   std::optional<int64_t> Offset;
0043 
0044 public:
0045   BaseIndexOffset() = default;
0046   Register getBase() { return BaseReg; }
0047   Register getBase() const { return BaseReg; }
0048   Register getIndex() { return IndexReg; }
0049   Register getIndex() const { return IndexReg; }
0050   void setBase(Register NewBase) { BaseReg = NewBase; }
0051   void setIndex(Register NewIndex) { IndexReg = NewIndex; }
0052   void setOffset(std::optional<int64_t> NewOff) { Offset = NewOff; }
0053   bool hasValidOffset() const { return Offset.has_value(); }
0054   int64_t getOffset() const { return *Offset; }
0055 };
0056 
0057 /// Returns a BaseIndexOffset which describes the pointer in \p Ptr.
0058 BaseIndexOffset getPointerInfo(Register Ptr, MachineRegisterInfo &MRI);
0059 
0060 /// Compute whether or not a memory access at \p MI1 aliases with an access at
0061 /// \p MI2 \returns true if either alias/no-alias is known. Sets \p IsAlias
0062 /// accordingly.
0063 bool aliasIsKnownForLoadStore(const MachineInstr &MI1, const MachineInstr &MI2,
0064                               bool &IsAlias, MachineRegisterInfo &MRI);
0065 
0066 /// Returns true if the instruction \p MI may alias \p Other.
0067 /// This function uses multiple strategies to detect aliasing, whereas
0068 /// aliasIsKnownForLoadStore just looks at the addresses of load/stores and is
0069 /// tries to reason about base/index/offsets.
0070 bool instMayAlias(const MachineInstr &MI, const MachineInstr &Other,
0071                   MachineRegisterInfo &MRI, AliasAnalysis *AA);
0072 } // namespace GISelAddressing
0073 
0074 using namespace GISelAddressing;
0075 
0076 class LoadStoreOpt : public MachineFunctionPass {
0077 public:
0078   static char ID;
0079 
0080 private:
0081   /// An input function to decide if the pass should run or not
0082   /// on the given MachineFunction.
0083   std::function<bool(const MachineFunction &)> DoNotRunPass;
0084 
0085   MachineRegisterInfo *MRI = nullptr;
0086   const TargetLowering *TLI = nullptr;
0087   MachineFunction *MF = nullptr;
0088   AliasAnalysis *AA = nullptr;
0089   const LegalizerInfo *LI = nullptr;
0090 
0091   MachineIRBuilder Builder;
0092 
0093   /// Initialize the field members using \p MF.
0094   void init(MachineFunction &MF);
0095 
0096   class StoreMergeCandidate {
0097   public:
0098     // The base pointer used as the base for all stores in this candidate.
0099     Register BasePtr;
0100     // Our algorithm is very simple at the moment. We assume that in instruction
0101     // order stores are writing to incremeneting consecutive addresses. So when
0102     // we walk the block in reverse order, the next eligible store must write to
0103     // an offset one store width lower than CurrentLowestOffset.
0104     int64_t CurrentLowestOffset;
0105     SmallVector<GStore *> Stores;
0106     // A vector of MachineInstr/unsigned pairs to denote potential aliases that
0107     // need to be checked before the candidate is considered safe to merge. The
0108     // unsigned value is an index into the Stores vector. The indexed store is
0109     // the highest-indexed store that has already been checked to not have an
0110     // alias with the instruction. We record this so we don't have to repeat
0111     // alias checks that have been already done, only those with stores added
0112     // after the potential alias is recorded.
0113     SmallVector<std::pair<MachineInstr *, unsigned>> PotentialAliases;
0114 
0115     void addPotentialAlias(MachineInstr &MI);
0116 
0117     /// Reset this candidate back to an empty one.
0118     void reset() {
0119       Stores.clear();
0120       PotentialAliases.clear();
0121       CurrentLowestOffset = 0;
0122       BasePtr = Register();
0123     }
0124   };
0125 
0126   bool isLegalOrBeforeLegalizer(const LegalityQuery &Query,
0127                                 MachineFunction &MF) const;
0128   /// If the given store is valid to be a member of the candidate, add it and
0129   /// return true. Otherwise, returns false.
0130   bool addStoreToCandidate(GStore &MI, StoreMergeCandidate &C);
0131   /// Returns true if the instruction \p MI would potentially alias with any
0132   /// stores in the candidate \p C.
0133   bool operationAliasesWithCandidate(MachineInstr &MI, StoreMergeCandidate &C);
0134   /// Merges the stores in the given vector into a wide store.
0135   /// \p returns true if at least some of the stores were merged.
0136   /// This may decide not to merge stores if heuristics predict it will not be
0137   /// worth it.
0138   bool mergeStores(SmallVectorImpl<GStore *> &StoresToMerge);
0139   /// Perform a merge of all the stores in \p Stores into a single store.
0140   /// Erases the old stores from the block when finished.
0141   /// \returns true if merging was done. It may fail to perform a merge if
0142   /// there are issues with materializing legal wide values.
0143   bool doSingleStoreMerge(SmallVectorImpl<GStore *> &Stores);
0144   bool processMergeCandidate(StoreMergeCandidate &C);
0145   bool mergeBlockStores(MachineBasicBlock &MBB);
0146   bool mergeFunctionStores(MachineFunction &MF);
0147 
0148   bool mergeTruncStore(GStore &StoreMI,
0149                        SmallPtrSetImpl<GStore *> &DeletedStores);
0150   bool mergeTruncStoresBlock(MachineBasicBlock &MBB);
0151 
0152   /// Initialize some target-specific data structures for the store merging
0153   /// optimization. \p AddrSpace indicates which address space to use when
0154   /// probing the legalizer info for legal stores.
0155   void initializeStoreMergeTargetInfo(unsigned AddrSpace = 0);
0156   /// A map between address space numbers and a bitvector of supported stores
0157   /// sizes. Each bit in the bitvector represents whether a store size of
0158   /// that bit's value is legal. E.g. if bit 64 is set, then 64 bit scalar
0159   /// stores are legal.
0160   DenseMap<unsigned, BitVector> LegalStoreSizes;
0161   bool IsPreLegalizer = false;
0162   /// Contains instructions to be erased at the end of a block scan.
0163   SmallSet<MachineInstr *, 16> InstsToErase;
0164 
0165 public:
0166   LoadStoreOpt();
0167   LoadStoreOpt(std::function<bool(const MachineFunction &)>);
0168 
0169   StringRef getPassName() const override { return "LoadStoreOpt"; }
0170 
0171   MachineFunctionProperties getRequiredProperties() const override {
0172     return MachineFunctionProperties()
0173         .set(MachineFunctionProperties::Property::IsSSA);
0174   }
0175 
0176   void getAnalysisUsage(AnalysisUsage &AU) const override;
0177 
0178   bool runOnMachineFunction(MachineFunction &MF) override;
0179 };
0180 
0181 } // End namespace llvm.
0182 
0183 #endif