51#define DEBUG_TYPE "hexagon-widen-stores"
91 static const int MaxWideSize = 4;
93 using InstrGroup = std::vector<MachineInstr *>;
94 using InstrGroupList = std::vector<InstrGroup>;
98 void createStoreGroup(
MachineInstr *BaseStore, InstrGroup::iterator Begin,
99 InstrGroup::iterator
End, InstrGroup &Group);
101 InstrGroupList &StoreGroups);
103 bool processStoreGroup(InstrGroup &Group);
104 bool selectStores(InstrGroup::iterator Begin, InstrGroup::iterator
End,
105 InstrGroup &OG,
unsigned &TotalSize,
unsigned MaxSize);
106 bool createWideStores(InstrGroup &OG, InstrGroup &NG,
unsigned TotalSize);
107 bool replaceStores(InstrGroup &OG, InstrGroup &NG);
113char HexagonStoreWidening::ID = 0;
116 "Hexason Store Widening",
false,
false)
124 assert(MO.
isReg() &&
"Expecting register operand");
129 unsigned OpC =
MI->getOpcode();
130 assert(HexagonStoreWidening::handledStoreType(
MI) &&
"Unhandled opcode");
133 case Hexagon::S4_storeirb_io:
134 case Hexagon::S4_storeirh_io:
135 case Hexagon::S4_storeiri_io: {
137 assert(MO.
isImm() &&
"Expecting immediate offset");
147 assert(!
MI->memoperands_empty() &&
"Expecting memory operands");
148 return **
MI->memoperands_begin();
153inline bool HexagonStoreWidening::handledStoreType(
const MachineInstr *
MI) {
156 unsigned Opc =
MI->getOpcode();
158 case Hexagon::S4_storeirb_io:
159 case Hexagon::S4_storeirh_io:
160 case Hexagon::S4_storeiri_io:
162 return MI->getOperand(0).isReg();
170bool HexagonStoreWidening::instrAliased(InstrGroup &Stores,
177 for (
auto *SI : Stores) {
183 if (!AA->isNoAlias(L, SL))
192bool HexagonStoreWidening::instrAliased(InstrGroup &Stores,
194 for (
auto &
I :
MI->memoperands())
195 if (instrAliased(Stores, *
I))
210 InstrGroupList &StoreGroups) {
217 AllInsns.push_back(&
I);
222 for (
auto I = AllInsns.begin(), E = AllInsns.end();
I != E; ++
I) {
225 if (!
MI || !handledStoreType(
MI))
230 createStoreGroup(
MI,
I+1, E,
G);
232 StoreGroups.push_back(
G);
239void HexagonStoreWidening::createStoreGroup(
MachineInstr *BaseStore,
240 InstrGroup::iterator Begin, InstrGroup::iterator
End, InstrGroup &Group) {
241 assert(handledStoreType(BaseStore) &&
"Unexpected instruction");
245 Group.push_back(BaseStore);
247 for (
auto I = Begin;
I !=
End; ++
I) {
252 if (handledStoreType(
MI)) {
271 if (
MI->isCall() ||
MI->hasUnmodeledSideEffects())
274 if (
MI->mayLoadOrStore()) {
275 if (
MI->hasOrderedMemoryRef() || instrAliased(Group,
MI))
284bool HexagonStoreWidening::storesAreAdjacent(
const MachineInstr *
S1,
286 if (!handledStoreType(
S1) || !handledStoreType(S2))
292 int Off1 =
S1->getOperand(1).getImm();
296 : int(Off1 + S1MO.
getSize().getValue()) == Off2;
305bool HexagonStoreWidening::selectStores(InstrGroup::iterator Begin,
306 InstrGroup::iterator
End, InstrGroup &OG,
unsigned &TotalSize,
308 assert(Begin !=
End &&
"No instructions to analyze");
309 assert(OG.empty() &&
"Old group not empty on entry");
311 if (std::distance(Begin,
End) <= 1)
325 if (SizeAccum >= MaxSize)
330 if (SizeAccum >= Alignment)
337 if ((2*SizeAccum-1) & FirstOffset)
340 OG.push_back(FirstMI);
345 unsigned Pow2Num = 1;
346 unsigned Pow2Size = SizeAccum;
353 for (InstrGroup::iterator
I = Begin + 1;
I !=
End; ++
I) {
357 if (!storesAreAdjacent(
S1, S2))
361 if (SizeAccum + S2Size > std::min(MaxSize, Alignment))
368 Pow2Size = SizeAccum;
370 if ((2*Pow2Size-1) & FirstOffset)
384 TotalSize = Pow2Size;
391bool HexagonStoreWidening::createWideStores(InstrGroup &OG, InstrGroup &NG,
392 unsigned TotalSize) {
406 assert(SO.
isImm() &&
"Expecting an immediate operand");
409 unsigned Mask = (0xFFFFFFFFU >> (32-NBits));
424 unsigned WOpc = (TotalSize == 2) ? Hexagon::S4_storeirh_io :
425 (TotalSize == 4) ? Hexagon::S4_storeiri_io : 0;
426 assert(WOpc &&
"Unexpected size");
428 int Val = (TotalSize == 2) ? int16_t(Acc) : int(Acc);
443 Register VReg = MF->getRegInfo().createVirtualRegister(RC);
448 unsigned WOpc = (TotalSize == 2) ? Hexagon::S2_storerh_io :
449 (TotalSize == 4) ? Hexagon::S2_storeri_io : 0;
450 assert(WOpc &&
"Unexpected size");
472bool HexagonStoreWidening::replaceStores(InstrGroup &OG, InstrGroup &NG) {
474 dbgs() <<
"Replacing:\n";
497 for (
auto &
I : *
MBB) {
504 assert((InsertAt !=
MBB->
end()) &&
"Cannot locate any store from the group");
506 bool AtBBStart =
false;
518 I->eraseFromParent();
534bool HexagonStoreWidening::processStoreGroup(InstrGroup &Group) {
535 bool Changed =
false;
536 InstrGroup::iterator
I = Group.begin(), E = Group.end();
538 unsigned CollectedSize;
544 bool Succ = selectStores(
I++, E, OG, CollectedSize, MaxWideSize) &&
545 createWideStores(OG, NG, CollectedSize) &&
546 replaceStores(OG, NG);
550 assert(OG.size() > 1 &&
"Created invalid group");
551 assert(distance(
I, E)+1 >=
int(OG.size()) &&
"Too many elements");
568 bool Changed =
false;
570 createStoreGroups(
MBB, SGs);
575 for (
auto &
G : SGs) {
576 assert(
G.size() > 1 &&
"Store group with fewer than 2 elements");
579 Changed |= processStoreGroup(
G);
591 TII =
ST.getInstrInfo();
592 TRI =
ST.getRegisterInfo();
594 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
596 bool Changed =
false;
599 Changed |= processBasicBlock(
B);
605 return new HexagonStoreWidening();
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
std::optional< std::vector< StOtherPiece > > Other
const HexagonInstrInfo * TII
static const MachineMemOperand & getStoreTarget(const MachineInstr *MI)
hexagon widen Hexagon Store static false unsigned getBaseAddressRegister(const MachineInstr *MI)
static int64_t getStoreOffset(const MachineInstr *MI)
hexagon widen Hexagon Store Widening
unsigned const TargetRegisterInfo * TRI
This file provides utility analysis objects describing memory locations.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
static unsigned getSize(unsigned Kind)
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
FunctionPass class - This class is used to implement most global optimizations.
TypeSize getValue() const
Describe properties that are true of each instruction in the target description file.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
bool memoperands_empty() const
Return true if we don't have any memory operands which described the memory access done by this instr...
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
const MachinePointerInfo & getPointerInfo() const
Flags getFlags() const
Return the raw flags of the source value,.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
AAMDNodes getAAInfo() const
Return the AA tags for the memory reference.
const Value * getValue() const
Return the base address of the memory access.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Representation for a specific memory location.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
StringRef - Represent a constant reference to a string, i.e.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ BR
Control flow instructions. These all have token chains.
@ Kill
The last use of a register.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void initializeHexagonStoreWideningPass(PassRegistry &)
unsigned getKillRegState(bool B)
FunctionPass * createHexagonStoreWidening()
uint64_t value() const
This is a hole in the type system and should not be abused.