24 #define DEBUG_TYPE "hexagon-widen-stores"
81 StringRef getPassName()
const override {
return "Hexagon Store Widening"; }
92 static const int MaxWideSize = 4;
94 typedef std::vector<MachineInstr*> InstrGroup;
95 typedef std::vector<InstrGroup> InstrGroupList;
99 void createStoreGroup(
MachineInstr *BaseStore, InstrGroup::iterator Begin,
100 InstrGroup::iterator
End, InstrGroup &Group);
102 InstrGroupList &StoreGroups);
104 bool processStoreGroup(InstrGroup &Group);
105 bool selectStores(InstrGroup::iterator Begin, InstrGroup::iterator
End,
106 InstrGroup &OG,
unsigned &TotalSize,
unsigned MaxSize);
107 bool createWideStores(InstrGroup &OG, InstrGroup &NG,
unsigned TotalSize);
108 bool replaceStores(InstrGroup &OG, InstrGroup &NG);
119 assert(MO.
isReg() &&
"Expecting register operand");
125 assert(HexagonStoreWidening::handledStoreType(MI) &&
"Unhandled opcode");
128 case Hexagon::S4_storeirb_io:
129 case Hexagon::S4_storeirh_io:
130 case Hexagon::S4_storeiri_io: {
132 assert(MO.
isImm() &&
"Expecting immediate offset");
147 "Hexason Store Widening",
false,
false)
157 unsigned Opc = MI->getOpcode();
159 case Hexagon::S4_storeirb_io:
160 case Hexagon::S4_storeirh_io:
161 case Hexagon::S4_storeiri_io:
163 return MI->getOperand(0).isReg();
171 bool HexagonStoreWidening::instrAliased(InstrGroup &Stores,
178 for (
auto SI : Stores) {
184 if (AA->alias(
L, SL))
193 bool HexagonStoreWidening::instrAliased(InstrGroup &Stores,
196 if (instrAliased(Stores, *
I))
211 InstrGroupList &StoreGroups) {
218 AllInsns.push_back(&
I);
223 for (
auto I = AllInsns.begin(),
E = AllInsns.end();
I !=
E; ++
I) {
226 if (!MI || !handledStoreType(MI))
231 createStoreGroup(MI,
I+1,
E, G);
233 StoreGroups.push_back(G);
240 void HexagonStoreWidening::createStoreGroup(
MachineInstr *BaseStore,
241 InstrGroup::iterator Begin, InstrGroup::iterator
End, InstrGroup &Group) {
242 assert(handledStoreType(BaseStore) &&
"Unexpected instruction");
246 Group.push_back(BaseStore);
248 for (
auto I = Begin;
I !=
End; ++
I) {
253 if (handledStoreType(MI)) {
285 bool HexagonStoreWidening::storesAreAdjacent(
const MachineInstr *S1,
287 if (!handledStoreType(S1) || !handledStoreType(S2))
297 : int(Off1+S1MO.getSize()) == Off2;
306 bool HexagonStoreWidening::selectStores(InstrGroup::iterator Begin,
307 InstrGroup::iterator End, InstrGroup &OG,
unsigned &TotalSize,
309 assert(Begin != End &&
"No instructions to analyze");
310 assert(OG.empty() &&
"Old group not empty on entry");
312 if (std::distance(Begin, End) <= 1)
318 unsigned Alignment = FirstMMO.getAlignment();
319 unsigned SizeAccum = FirstMMO.getSize();
326 if (SizeAccum >= MaxSize)
331 if (SizeAccum >= Alignment)
338 if ((2*SizeAccum-1) & FirstOffset)
341 OG.push_back(FirstMI);
343 InstrGroup::iterator
I = Begin+1;
347 unsigned Pow2Num = 1;
348 unsigned Pow2Size = SizeAccum;
359 if (!storesAreAdjacent(S1, S2))
363 if (SizeAccum + S2Size >
std::min(MaxSize, Alignment))
370 Pow2Size = SizeAccum;
372 if ((2*Pow2Size-1) & FirstOffset)
387 TotalSize = Pow2Size;
394 bool HexagonStoreWidening::createWideStores(InstrGroup &OG, InstrGroup &NG,
395 unsigned TotalSize) {
406 for (InstrGroup::iterator I = OG.begin(),
E = OG.end(); I !=
E; ++
I) {
410 assert(SO.
isImm() &&
"Expecting an immediate operand");
412 unsigned NBits = MMO.
getSize()*8;
413 unsigned Mask = (0xFFFFFFFFU >> (32-NBits));
429 unsigned WOpc = (TotalSize == 2) ? Hexagon::S4_storeirh_io :
430 (TotalSize == 4) ? Hexagon::S4_storeiri_io : 0;
431 assert(WOpc &&
"Unexpected size");
433 int Val = (TotalSize == 2) ? int16_t(Acc) : int(Acc);
447 unsigned VReg = MF->getRegInfo().createVirtualRegister(RC);
452 unsigned WOpc = (TotalSize == 2) ? Hexagon::S2_storerh_io :
453 (TotalSize == 4) ? Hexagon::S2_storeri_io : 0;
454 assert(WOpc &&
"Unexpected size");
475 bool HexagonStoreWidening::replaceStores(InstrGroup &OG, InstrGroup &NG) {
477 dbgs() <<
"Replacing:\n";
500 for (
auto &I : *MBB) {
501 if (InstrSet.
count(&I)) {
507 assert((InsertAt != MBB->end()) &&
"Cannot locate any store from the group");
509 bool AtBBStart =
false;
515 if (InsertAt != MBB->begin())
521 I->eraseFromParent();
526 InsertAt = MBB->begin();
529 MBB->insert(InsertAt, I);
537 bool HexagonStoreWidening::processStoreGroup(InstrGroup &Group) {
538 bool Changed =
false;
539 InstrGroup::iterator I = Group.begin(),
E = Group.end();
541 unsigned CollectedSize;
547 bool Succ = selectStores(I++,
E, OG, CollectedSize, MaxWideSize) &&
548 createWideStores(OG, NG, CollectedSize) &&
549 replaceStores(OG, NG);
553 assert(OG.size() > 1 &&
"Created invalid group");
554 assert(distance(I,
E)+1 >=
int(OG.size()) &&
"Too many elements");
571 bool Changed =
false;
573 createStoreGroups(MBB, SGs);
578 for (
auto &
G : SGs) {
579 assert(
G.size() > 1 &&
"Store group with fewer than 2 elements");
580 std::sort(
G.begin(),
G.end(),
Less);
582 Changed |= processStoreGroup(
G);
588 bool HexagonStoreWidening::runOnMachineFunction(
MachineFunction &MFn) {
594 TII =
ST.getInstrInfo();
595 TRI =
ST.getRegisterInfo();
597 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
599 bool Changed =
false;
602 Changed |= processBasicBlock(
B);
608 return new HexagonStoreWidening();
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Flags getFlags() const
Return the raw flags of the source value,.
static const MachineMemOperand & getStoreTarget(const MachineInstr *MI)
Describe properties that are true of each instruction in the target description file.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
iterator_range< mmo_iterator > memoperands()
const MachinePointerInfo & getPointerInfo() const
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
A description of a memory reference used in the backend.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
uint64_t getAlignment() const
Return the minimum known alignment in bytes of the actual memory reference.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
hexagon widen Hexagon Store Widening
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
unsigned getKillRegState(bool B)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
const MachineBasicBlock * getParent() const
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Control flow instructions. These all have token chains.
unsigned const MachineRegisterInfo * MRI
constexpr bool isPowerOf2_32(uint32_t Value)
isPowerOf2_32 - This function returns true if the argument is a power of two > 0. ...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
AAMDNodes getAAInfo() const
Return the AA tags for the memory reference.
static int64_t getStoreOffset(const MachineInstr *MI)
const MachineOperand & getOperand(unsigned i) const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Represent the analysis usage information of a pass.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
static const unsigned End
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore...
FunctionPass class - This class is used to implement most global optimizations.
FunctionPass * createHexagonStoreWidening()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Representation for a specific memory location.
bool memoperands_empty() const
Return true if we don't have any memory operands which described the the memory access done by this i...
static unsigned getBaseAddressRegister(const MachineInstr *MI)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
hexagon widen Hexagon Store false
MachineOperand class - Representation of each machine instruction operand.
void initializeHexagonStoreWideningPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
INITIALIZE_PASS_BEGIN(HexagonStoreWidening,"hexagon-widen-stores","Hexason Store Widening", false, false) INITIALIZE_PASS_END(HexagonStoreWidening
const Value * getValue() const
Return the base address of the memory access.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
This file provides utility analysis objects describing memory locations.
bool isCall(QueryType Type=AnyInBundle) const
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
uint64_t getSize() const
Return the size in bytes of the memory reference.
StringRef - Represent a constant reference to a string, i.e.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.