10b57cec5SDimitry Andric //===- HexagonPacketizer.cpp - VLIW packetizer ----------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This implements a simple VLIW packetizer using DFA. The packetizer works on 100b57cec5SDimitry Andric // machine basic blocks. For each instruction I in BB, the packetizer consults 110b57cec5SDimitry Andric // the DFA to see if machine resources are available to execute I. If so, the 120b57cec5SDimitry Andric // packetizer checks if I depends on any instruction J in the current packet. 130b57cec5SDimitry Andric // If no dependency is found, I is added to current packet and machine resource 140b57cec5SDimitry Andric // is marked as taken. If any dependency is found, a target API call is made to 150b57cec5SDimitry Andric // prune the dependence. 160b57cec5SDimitry Andric // 170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "HexagonVLIWPacketizer.h" 200b57cec5SDimitry Andric #include "Hexagon.h" 210b57cec5SDimitry Andric #include "HexagonInstrInfo.h" 220b57cec5SDimitry Andric #include "HexagonRegisterInfo.h" 230b57cec5SDimitry Andric #include "HexagonSubtarget.h" 240b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 250b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 260b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 278bcb0991SDimitry Andric #include "llvm/ADT/StringExtras.h" 280b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 350b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 360b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h" 370b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 380b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 390b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h" 400b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 410b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 420b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 43480093f4SDimitry Andric #include "llvm/InitializePasses.h" 440b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 450b57cec5SDimitry Andric #include "llvm/Pass.h" 460b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 470b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 480b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 490b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 500b57cec5SDimitry Andric #include <cassert> 510b57cec5SDimitry Andric #include <cstdint> 520b57cec5SDimitry Andric #include <iterator> 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric using namespace llvm; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric #define DEBUG_TYPE "packets" 570b57cec5SDimitry Andric 5881ad6265SDimitry Andric static cl::opt<bool> 5981ad6265SDimitry Andric DisablePacketizer("disable-packetizer", cl::Hidden, 600b57cec5SDimitry Andric cl::desc("Disable Hexagon packetizer pass")); 610b57cec5SDimitry Andric 628bcb0991SDimitry Andric static cl::opt<bool> Slot1Store("slot1-store-slot0-load", cl::Hidden, 6381ad6265SDimitry Andric cl::init(true), 640b57cec5SDimitry Andric cl::desc("Allow slot1 store and slot0 load")); 650b57cec5SDimitry Andric 6681ad6265SDimitry Andric static cl::opt<bool> PacketizeVolatiles( 6781ad6265SDimitry Andric "hexagon-packetize-volatiles", cl::Hidden, cl::init(true), 680b57cec5SDimitry Andric cl::desc("Allow non-solo packetization of volatile memory references")); 690b57cec5SDimitry Andric 7081ad6265SDimitry Andric static cl::opt<bool> 7181ad6265SDimitry Andric EnableGenAllInsnClass("enable-gen-insn", cl::Hidden, 7281ad6265SDimitry Andric cl::desc("Generate all instruction with TC")); 730b57cec5SDimitry Andric 7481ad6265SDimitry Andric static cl::opt<bool> 7581ad6265SDimitry Andric DisableVecDblNVStores("disable-vecdbl-nv-stores", cl::Hidden, 760b57cec5SDimitry Andric cl::desc("Disable vector double new-value-stores")); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric extern cl::opt<bool> ScheduleInlineAsm; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric namespace llvm { 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric FunctionPass *createHexagonPacketizer(bool Minimal); 830b57cec5SDimitry Andric void initializeHexagonPacketizerPass(PassRegistry&); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric } // end namespace llvm 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric namespace { 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric class HexagonPacketizer : public MachineFunctionPass { 900b57cec5SDimitry Andric public: 910b57cec5SDimitry Andric static char ID; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric HexagonPacketizer(bool Min = false) 940b57cec5SDimitry Andric : MachineFunctionPass(ID), Minimal(Min) {} 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 970b57cec5SDimitry Andric AU.setPreservesCFG(); 980b57cec5SDimitry Andric AU.addRequired<AAResultsWrapperPass>(); 99*0fca6ea1SDimitry Andric AU.addRequired<MachineBranchProbabilityInfoWrapperPass>(); 100*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>(); 101*0fca6ea1SDimitry Andric AU.addRequired<MachineLoopInfoWrapperPass>(); 102*0fca6ea1SDimitry Andric AU.addPreserved<MachineDominatorTreeWrapperPass>(); 103*0fca6ea1SDimitry Andric AU.addPreserved<MachineLoopInfoWrapperPass>(); 1040b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric StringRef getPassName() const override { return "Hexagon Packetizer"; } 1080b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 1110b57cec5SDimitry Andric return MachineFunctionProperties().set( 1120b57cec5SDimitry Andric MachineFunctionProperties::Property::NoVRegs); 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric private: 116480093f4SDimitry Andric const HexagonInstrInfo *HII = nullptr; 117480093f4SDimitry Andric const HexagonRegisterInfo *HRI = nullptr; 118480093f4SDimitry Andric const bool Minimal = false; 1190b57cec5SDimitry Andric }; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric } // end anonymous namespace 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric char HexagonPacketizer::ID = 0; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(HexagonPacketizer, "hexagon-packetizer", 1260b57cec5SDimitry Andric "Hexagon Packetizer", false, false) 127*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) 128*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass) 129*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass) 1300b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) 1310b57cec5SDimitry Andric INITIALIZE_PASS_END(HexagonPacketizer, "hexagon-packetizer", 1320b57cec5SDimitry Andric "Hexagon Packetizer", false, false) 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric HexagonPacketizerList::HexagonPacketizerList(MachineFunction &MF, 1358bcb0991SDimitry Andric MachineLoopInfo &MLI, AAResults *AA, 1360b57cec5SDimitry Andric const MachineBranchProbabilityInfo *MBPI, bool Minimal) 1370b57cec5SDimitry Andric : VLIWPacketizerList(MF, MLI, AA), MBPI(MBPI), MLI(&MLI), 1380b57cec5SDimitry Andric Minimal(Minimal) { 1390b57cec5SDimitry Andric HII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo(); 1400b57cec5SDimitry Andric HRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo(); 1410b57cec5SDimitry Andric 1428bcb0991SDimitry Andric addMutation(std::make_unique<HexagonSubtarget::UsrOverflowMutation>()); 1438bcb0991SDimitry Andric addMutation(std::make_unique<HexagonSubtarget::HVXMemLatencyMutation>()); 1448bcb0991SDimitry Andric addMutation(std::make_unique<HexagonSubtarget::BankConflictMutation>()); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric // Check if FirstI modifies a register that SecondI reads. 1480b57cec5SDimitry Andric static bool hasWriteToReadDep(const MachineInstr &FirstI, 1490b57cec5SDimitry Andric const MachineInstr &SecondI, 1500b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 1510b57cec5SDimitry Andric for (auto &MO : FirstI.operands()) { 1520b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef()) 1530b57cec5SDimitry Andric continue; 1548bcb0991SDimitry Andric Register R = MO.getReg(); 1550b57cec5SDimitry Andric if (SecondI.readsRegister(R, TRI)) 1560b57cec5SDimitry Andric return true; 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric return false; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric static MachineBasicBlock::iterator moveInstrOut(MachineInstr &MI, 1630b57cec5SDimitry Andric MachineBasicBlock::iterator BundleIt, bool Before) { 1640b57cec5SDimitry Andric MachineBasicBlock::instr_iterator InsertPt; 1650b57cec5SDimitry Andric if (Before) 1660b57cec5SDimitry Andric InsertPt = BundleIt.getInstrIterator(); 1670b57cec5SDimitry Andric else 1680b57cec5SDimitry Andric InsertPt = std::next(BundleIt).getInstrIterator(); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric MachineBasicBlock &B = *MI.getParent(); 1710b57cec5SDimitry Andric // The instruction should at least be bundled with the preceding instruction 1720b57cec5SDimitry Andric // (there will always be one, i.e. BUNDLE, if nothing else). 1730b57cec5SDimitry Andric assert(MI.isBundledWithPred()); 1740b57cec5SDimitry Andric if (MI.isBundledWithSucc()) { 1750b57cec5SDimitry Andric MI.clearFlag(MachineInstr::BundledSucc); 1760b57cec5SDimitry Andric MI.clearFlag(MachineInstr::BundledPred); 1770b57cec5SDimitry Andric } else { 1780b57cec5SDimitry Andric // If it's not bundled with the successor (i.e. it is the last one 1790b57cec5SDimitry Andric // in the bundle), then we can simply unbundle it from the predecessor, 1800b57cec5SDimitry Andric // which will take care of updating the predecessor's flag. 1810b57cec5SDimitry Andric MI.unbundleFromPred(); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric B.splice(InsertPt, &B, MI.getIterator()); 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric // Get the size of the bundle without asserting. 1860b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator I = BundleIt.getInstrIterator(); 1870b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator E = B.instr_end(); 1880b57cec5SDimitry Andric unsigned Size = 0; 1890b57cec5SDimitry Andric for (++I; I != E && I->isBundledWithPred(); ++I) 1900b57cec5SDimitry Andric ++Size; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric // If there are still two or more instructions, then there is nothing 1930b57cec5SDimitry Andric // else to be done. 1940b57cec5SDimitry Andric if (Size > 1) 1950b57cec5SDimitry Andric return BundleIt; 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric // Otherwise, extract the single instruction out and delete the bundle. 1980b57cec5SDimitry Andric MachineBasicBlock::iterator NextIt = std::next(BundleIt); 1990b57cec5SDimitry Andric MachineInstr &SingleI = *BundleIt->getNextNode(); 2000b57cec5SDimitry Andric SingleI.unbundleFromPred(); 2010b57cec5SDimitry Andric assert(!SingleI.isBundledWithSucc()); 2020b57cec5SDimitry Andric BundleIt->eraseFromParent(); 2030b57cec5SDimitry Andric return NextIt; 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric bool HexagonPacketizer::runOnMachineFunction(MachineFunction &MF) { 207349cc55cSDimitry Andric // FIXME: This pass causes verification failures. 208349cc55cSDimitry Andric MF.getProperties().set( 209349cc55cSDimitry Andric MachineFunctionProperties::Property::FailsVerification); 210349cc55cSDimitry Andric 2110b57cec5SDimitry Andric auto &HST = MF.getSubtarget<HexagonSubtarget>(); 2120b57cec5SDimitry Andric HII = HST.getInstrInfo(); 2130b57cec5SDimitry Andric HRI = HST.getRegisterInfo(); 214*0fca6ea1SDimitry Andric auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI(); 2150b57cec5SDimitry Andric auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); 216*0fca6ea1SDimitry Andric auto *MBPI = 217*0fca6ea1SDimitry Andric &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI(); 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric if (EnableGenAllInsnClass) 2200b57cec5SDimitry Andric HII->genAllInsnTimingClasses(MF); 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric // Instantiate the packetizer. 2230b57cec5SDimitry Andric bool MinOnly = Minimal || DisablePacketizer || !HST.usePackets() || 2240b57cec5SDimitry Andric skipFunction(MF.getFunction()); 2250b57cec5SDimitry Andric HexagonPacketizerList Packetizer(MF, MLI, AA, MBPI, MinOnly); 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric // DFA state table should not be empty. 2280b57cec5SDimitry Andric assert(Packetizer.getResourceTracker() && "Empty DFA table!"); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric // Loop over all basic blocks and remove KILL pseudo-instructions 2310b57cec5SDimitry Andric // These instructions confuse the dependence analysis. Consider: 2320b57cec5SDimitry Andric // D0 = ... (Insn 0) 2330b57cec5SDimitry Andric // R0 = KILL R0, D0 (Insn 1) 2340b57cec5SDimitry Andric // R0 = ... (Insn 2) 2350b57cec5SDimitry Andric // Here, Insn 1 will result in the dependence graph not emitting an output 2360b57cec5SDimitry Andric // dependence between Insn 0 and Insn 2. This can lead to incorrect 2370b57cec5SDimitry Andric // packetization 2380b57cec5SDimitry Andric for (MachineBasicBlock &MB : MF) { 239349cc55cSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(MB)) 240349cc55cSDimitry Andric if (MI.isKill()) 241349cc55cSDimitry Andric MB.erase(&MI); 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric 2445ffd83dbSDimitry Andric // TinyCore with Duplexes: Translate to big-instructions. 2455ffd83dbSDimitry Andric if (HST.isTinyCoreWithDuplex()) 2465ffd83dbSDimitry Andric HII->translateInstrsForDup(MF, true); 2475ffd83dbSDimitry Andric 2480b57cec5SDimitry Andric // Loop over all of the basic blocks. 2490b57cec5SDimitry Andric for (auto &MB : MF) { 2500b57cec5SDimitry Andric auto Begin = MB.begin(), End = MB.end(); 2510b57cec5SDimitry Andric while (Begin != End) { 2520b57cec5SDimitry Andric // Find the first non-boundary starting from the end of the last 2530b57cec5SDimitry Andric // scheduling region. 2540b57cec5SDimitry Andric MachineBasicBlock::iterator RB = Begin; 2550b57cec5SDimitry Andric while (RB != End && HII->isSchedulingBoundary(*RB, &MB, MF)) 2560b57cec5SDimitry Andric ++RB; 2570b57cec5SDimitry Andric // Find the first boundary starting from the beginning of the new 2580b57cec5SDimitry Andric // region. 2590b57cec5SDimitry Andric MachineBasicBlock::iterator RE = RB; 2600b57cec5SDimitry Andric while (RE != End && !HII->isSchedulingBoundary(*RE, &MB, MF)) 2610b57cec5SDimitry Andric ++RE; 2620b57cec5SDimitry Andric // Add the scheduling boundary if it's not block end. 2630b57cec5SDimitry Andric if (RE != End) 2640b57cec5SDimitry Andric ++RE; 2650b57cec5SDimitry Andric // If RB == End, then RE == End. 2660b57cec5SDimitry Andric if (RB != End) 2670b57cec5SDimitry Andric Packetizer.PacketizeMIs(&MB, RB, RE); 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric Begin = RE; 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 2735ffd83dbSDimitry Andric // TinyCore with Duplexes: Translate to tiny-instructions. 2745ffd83dbSDimitry Andric if (HST.isTinyCoreWithDuplex()) 2755ffd83dbSDimitry Andric HII->translateInstrsForDup(MF, false); 2765ffd83dbSDimitry Andric 2770b57cec5SDimitry Andric Packetizer.unpacketizeSoloInstrs(MF); 2780b57cec5SDimitry Andric return true; 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric // Reserve resources for a constant extender. Trigger an assertion if the 2820b57cec5SDimitry Andric // reservation fails. 2830b57cec5SDimitry Andric void HexagonPacketizerList::reserveResourcesForConstExt() { 2840b57cec5SDimitry Andric if (!tryAllocateResourcesForConstExt(true)) 2850b57cec5SDimitry Andric llvm_unreachable("Resources not available"); 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric bool HexagonPacketizerList::canReserveResourcesForConstExt() { 2890b57cec5SDimitry Andric return tryAllocateResourcesForConstExt(false); 2900b57cec5SDimitry Andric } 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric // Allocate resources (i.e. 4 bytes) for constant extender. If succeeded, 2930b57cec5SDimitry Andric // return true, otherwise, return false. 2940b57cec5SDimitry Andric bool HexagonPacketizerList::tryAllocateResourcesForConstExt(bool Reserve) { 2950b57cec5SDimitry Andric auto *ExtMI = MF.CreateMachineInstr(HII->get(Hexagon::A4_ext), DebugLoc()); 2960b57cec5SDimitry Andric bool Avail = ResourceTracker->canReserveResources(*ExtMI); 2970b57cec5SDimitry Andric if (Reserve && Avail) 2980b57cec5SDimitry Andric ResourceTracker->reserveResources(*ExtMI); 2990eae32dcSDimitry Andric MF.deleteMachineInstr(ExtMI); 3000b57cec5SDimitry Andric return Avail; 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric bool HexagonPacketizerList::isCallDependent(const MachineInstr &MI, 3040b57cec5SDimitry Andric SDep::Kind DepType, unsigned DepReg) { 3050b57cec5SDimitry Andric // Check for LR dependence. 3060b57cec5SDimitry Andric if (DepReg == HRI->getRARegister()) 3070b57cec5SDimitry Andric return true; 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric if (HII->isDeallocRet(MI)) 3100b57cec5SDimitry Andric if (DepReg == HRI->getFrameRegister() || DepReg == HRI->getStackRegister()) 3110b57cec5SDimitry Andric return true; 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // Call-like instructions can be packetized with preceding instructions 3140b57cec5SDimitry Andric // that define registers implicitly used or modified by the call. Explicit 3150b57cec5SDimitry Andric // uses are still prohibited, as in the case of indirect calls: 3160b57cec5SDimitry Andric // r0 = ... 3170b57cec5SDimitry Andric // J2_jumpr r0 3180b57cec5SDimitry Andric if (DepType == SDep::Data) { 319480093f4SDimitry Andric for (const MachineOperand &MO : MI.operands()) 3200b57cec5SDimitry Andric if (MO.isReg() && MO.getReg() == DepReg && !MO.isImplicit()) 3210b57cec5SDimitry Andric return true; 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric return false; 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric static bool isRegDependence(const SDep::Kind DepType) { 3280b57cec5SDimitry Andric return DepType == SDep::Data || DepType == SDep::Anti || 3290b57cec5SDimitry Andric DepType == SDep::Output; 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric static bool isDirectJump(const MachineInstr &MI) { 3330b57cec5SDimitry Andric return MI.getOpcode() == Hexagon::J2_jump; 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric static bool isSchedBarrier(const MachineInstr &MI) { 3370b57cec5SDimitry Andric switch (MI.getOpcode()) { 3380b57cec5SDimitry Andric case Hexagon::Y2_barrier: 3390b57cec5SDimitry Andric return true; 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric return false; 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric static bool isControlFlow(const MachineInstr &MI) { 3450b57cec5SDimitry Andric return MI.getDesc().isTerminator() || MI.getDesc().isCall(); 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric /// Returns true if the instruction modifies a callee-saved register. 3490b57cec5SDimitry Andric static bool doesModifyCalleeSavedReg(const MachineInstr &MI, 3500b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 3510b57cec5SDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent(); 3520b57cec5SDimitry Andric for (auto *CSR = TRI->getCalleeSavedRegs(&MF); CSR && *CSR; ++CSR) 3530b57cec5SDimitry Andric if (MI.modifiesRegister(*CSR, TRI)) 3540b57cec5SDimitry Andric return true; 3550b57cec5SDimitry Andric return false; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric // Returns true if an instruction can be promoted to .new predicate or 3590b57cec5SDimitry Andric // new-value store. 3600b57cec5SDimitry Andric bool HexagonPacketizerList::isNewifiable(const MachineInstr &MI, 3610b57cec5SDimitry Andric const TargetRegisterClass *NewRC) { 3620b57cec5SDimitry Andric // Vector stores can be predicated, and can be new-value stores, but 3630b57cec5SDimitry Andric // they cannot be predicated on a .new predicate value. 3640b57cec5SDimitry Andric if (NewRC == &Hexagon::PredRegsRegClass) { 3650b57cec5SDimitry Andric if (HII->isHVXVec(MI) && MI.mayStore()) 3660b57cec5SDimitry Andric return false; 3670b57cec5SDimitry Andric return HII->isPredicated(MI) && HII->getDotNewPredOp(MI, nullptr) > 0; 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric // If the class is not PredRegs, it could only apply to new-value stores. 3700b57cec5SDimitry Andric return HII->mayBeNewStore(MI); 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric // Promote an instructiont to its .cur form. 3740b57cec5SDimitry Andric // At this time, we have already made a call to canPromoteToDotCur and made 3750b57cec5SDimitry Andric // sure that it can *indeed* be promoted. 3760b57cec5SDimitry Andric bool HexagonPacketizerList::promoteToDotCur(MachineInstr &MI, 3770b57cec5SDimitry Andric SDep::Kind DepType, MachineBasicBlock::iterator &MII, 3780b57cec5SDimitry Andric const TargetRegisterClass* RC) { 3790b57cec5SDimitry Andric assert(DepType == SDep::Data); 3800b57cec5SDimitry Andric int CurOpcode = HII->getDotCurOp(MI); 3810b57cec5SDimitry Andric MI.setDesc(HII->get(CurOpcode)); 3820b57cec5SDimitry Andric return true; 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric void HexagonPacketizerList::cleanUpDotCur() { 3860b57cec5SDimitry Andric MachineInstr *MI = nullptr; 387bdd1243dSDimitry Andric for (auto *BI : CurrentPacketMIs) { 3880b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Cleanup packet has "; BI->dump();); 3890b57cec5SDimitry Andric if (HII->isDotCurInst(*BI)) { 3900b57cec5SDimitry Andric MI = BI; 3910b57cec5SDimitry Andric continue; 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric if (MI) { 3940b57cec5SDimitry Andric for (auto &MO : BI->operands()) 3950b57cec5SDimitry Andric if (MO.isReg() && MO.getReg() == MI->getOperand(0).getReg()) 3960b57cec5SDimitry Andric return; 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric if (!MI) 4000b57cec5SDimitry Andric return; 4010b57cec5SDimitry Andric // We did not find a use of the CUR, so de-cur it. 4020b57cec5SDimitry Andric MI->setDesc(HII->get(HII->getNonDotCurOp(*MI))); 4030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Demoted CUR "; MI->dump();); 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric // Check to see if an instruction can be dot cur. 4070b57cec5SDimitry Andric bool HexagonPacketizerList::canPromoteToDotCur(const MachineInstr &MI, 4080b57cec5SDimitry Andric const SUnit *PacketSU, unsigned DepReg, MachineBasicBlock::iterator &MII, 4090b57cec5SDimitry Andric const TargetRegisterClass *RC) { 4100b57cec5SDimitry Andric if (!HII->isHVXVec(MI)) 4110b57cec5SDimitry Andric return false; 4120b57cec5SDimitry Andric if (!HII->isHVXVec(*MII)) 4130b57cec5SDimitry Andric return false; 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric // Already a dot new instruction. 4160b57cec5SDimitry Andric if (HII->isDotCurInst(MI) && !HII->mayBeCurLoad(MI)) 4170b57cec5SDimitry Andric return false; 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric if (!HII->mayBeCurLoad(MI)) 4200b57cec5SDimitry Andric return false; 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric // The "cur value" cannot come from inline asm. 4230b57cec5SDimitry Andric if (PacketSU->getInstr()->isInlineAsm()) 4240b57cec5SDimitry Andric return false; 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric // Make sure candidate instruction uses cur. 4270b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Can we DOT Cur Vector MI\n"; MI.dump(); 4280b57cec5SDimitry Andric dbgs() << "in packet\n";); 4290b57cec5SDimitry Andric MachineInstr &MJ = *MII; 4300b57cec5SDimitry Andric LLVM_DEBUG({ 4310b57cec5SDimitry Andric dbgs() << "Checking CUR against "; 4320b57cec5SDimitry Andric MJ.dump(); 4330b57cec5SDimitry Andric }); 4348bcb0991SDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 4350b57cec5SDimitry Andric bool FoundMatch = false; 4360b57cec5SDimitry Andric for (auto &MO : MJ.operands()) 4370b57cec5SDimitry Andric if (MO.isReg() && MO.getReg() == DestReg) 4380b57cec5SDimitry Andric FoundMatch = true; 4390b57cec5SDimitry Andric if (!FoundMatch) 4400b57cec5SDimitry Andric return false; 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric // Check for existing uses of a vector register within the packet which 4430b57cec5SDimitry Andric // would be affected by converting a vector load into .cur formt. 444bdd1243dSDimitry Andric for (auto *BI : CurrentPacketMIs) { 4450b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "packet has "; BI->dump();); 4460b57cec5SDimitry Andric if (BI->readsRegister(DepReg, MF.getSubtarget().getRegisterInfo())) 4470b57cec5SDimitry Andric return false; 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Can Dot CUR MI\n"; MI.dump();); 4510b57cec5SDimitry Andric // We can convert the opcode into a .cur. 4520b57cec5SDimitry Andric return true; 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric // Promote an instruction to its .new form. At this time, we have already 4560b57cec5SDimitry Andric // made a call to canPromoteToDotNew and made sure that it can *indeed* be 4570b57cec5SDimitry Andric // promoted. 4580b57cec5SDimitry Andric bool HexagonPacketizerList::promoteToDotNew(MachineInstr &MI, 4590b57cec5SDimitry Andric SDep::Kind DepType, MachineBasicBlock::iterator &MII, 4600b57cec5SDimitry Andric const TargetRegisterClass* RC) { 4610b57cec5SDimitry Andric assert(DepType == SDep::Data); 4620b57cec5SDimitry Andric int NewOpcode; 4630b57cec5SDimitry Andric if (RC == &Hexagon::PredRegsRegClass) 4640b57cec5SDimitry Andric NewOpcode = HII->getDotNewPredOp(MI, MBPI); 4650b57cec5SDimitry Andric else 4660b57cec5SDimitry Andric NewOpcode = HII->getDotNewOp(MI); 4670b57cec5SDimitry Andric MI.setDesc(HII->get(NewOpcode)); 4680b57cec5SDimitry Andric return true; 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric bool HexagonPacketizerList::demoteToDotOld(MachineInstr &MI) { 4720b57cec5SDimitry Andric int NewOpcode = HII->getDotOldOp(MI); 4730b57cec5SDimitry Andric MI.setDesc(HII->get(NewOpcode)); 4740b57cec5SDimitry Andric return true; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric bool HexagonPacketizerList::useCallersSP(MachineInstr &MI) { 4780b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 4790b57cec5SDimitry Andric switch (Opc) { 4800b57cec5SDimitry Andric case Hexagon::S2_storerd_io: 4810b57cec5SDimitry Andric case Hexagon::S2_storeri_io: 4820b57cec5SDimitry Andric case Hexagon::S2_storerh_io: 4830b57cec5SDimitry Andric case Hexagon::S2_storerb_io: 4840b57cec5SDimitry Andric break; 4850b57cec5SDimitry Andric default: 4860b57cec5SDimitry Andric llvm_unreachable("Unexpected instruction"); 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric unsigned FrameSize = MF.getFrameInfo().getStackSize(); 4890b57cec5SDimitry Andric MachineOperand &Off = MI.getOperand(1); 4900b57cec5SDimitry Andric int64_t NewOff = Off.getImm() - (FrameSize + HEXAGON_LRFP_SIZE); 4910b57cec5SDimitry Andric if (HII->isValidOffset(Opc, NewOff, HRI)) { 4920b57cec5SDimitry Andric Off.setImm(NewOff); 4930b57cec5SDimitry Andric return true; 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric return false; 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric void HexagonPacketizerList::useCalleesSP(MachineInstr &MI) { 4990b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 5000b57cec5SDimitry Andric switch (Opc) { 5010b57cec5SDimitry Andric case Hexagon::S2_storerd_io: 5020b57cec5SDimitry Andric case Hexagon::S2_storeri_io: 5030b57cec5SDimitry Andric case Hexagon::S2_storerh_io: 5040b57cec5SDimitry Andric case Hexagon::S2_storerb_io: 5050b57cec5SDimitry Andric break; 5060b57cec5SDimitry Andric default: 5070b57cec5SDimitry Andric llvm_unreachable("Unexpected instruction"); 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric unsigned FrameSize = MF.getFrameInfo().getStackSize(); 5100b57cec5SDimitry Andric MachineOperand &Off = MI.getOperand(1); 5110b57cec5SDimitry Andric Off.setImm(Off.getImm() + FrameSize + HEXAGON_LRFP_SIZE); 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric /// Return true if we can update the offset in MI so that MI and MJ 5150b57cec5SDimitry Andric /// can be packetized together. 5160b57cec5SDimitry Andric bool HexagonPacketizerList::updateOffset(SUnit *SUI, SUnit *SUJ) { 5170b57cec5SDimitry Andric assert(SUI->getInstr() && SUJ->getInstr()); 5180b57cec5SDimitry Andric MachineInstr &MI = *SUI->getInstr(); 5190b57cec5SDimitry Andric MachineInstr &MJ = *SUJ->getInstr(); 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric unsigned BPI, OPI; 5220b57cec5SDimitry Andric if (!HII->getBaseAndOffsetPosition(MI, BPI, OPI)) 5230b57cec5SDimitry Andric return false; 5240b57cec5SDimitry Andric unsigned BPJ, OPJ; 5250b57cec5SDimitry Andric if (!HII->getBaseAndOffsetPosition(MJ, BPJ, OPJ)) 5260b57cec5SDimitry Andric return false; 5278bcb0991SDimitry Andric Register Reg = MI.getOperand(BPI).getReg(); 5280b57cec5SDimitry Andric if (Reg != MJ.getOperand(BPJ).getReg()) 5290b57cec5SDimitry Andric return false; 5300b57cec5SDimitry Andric // Make sure that the dependences do not restrict adding MI to the packet. 5310b57cec5SDimitry Andric // That is, ignore anti dependences, and make sure the only data dependence 5320b57cec5SDimitry Andric // involves the specific register. 5330b57cec5SDimitry Andric for (const auto &PI : SUI->Preds) 5340b57cec5SDimitry Andric if (PI.getKind() != SDep::Anti && 5350b57cec5SDimitry Andric (PI.getKind() != SDep::Data || PI.getReg() != Reg)) 5360b57cec5SDimitry Andric return false; 5370b57cec5SDimitry Andric int Incr; 5380b57cec5SDimitry Andric if (!HII->getIncrementValue(MJ, Incr)) 5390b57cec5SDimitry Andric return false; 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric int64_t Offset = MI.getOperand(OPI).getImm(); 5420b57cec5SDimitry Andric if (!HII->isValidOffset(MI.getOpcode(), Offset+Incr, HRI)) 5430b57cec5SDimitry Andric return false; 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric MI.getOperand(OPI).setImm(Offset + Incr); 5460b57cec5SDimitry Andric ChangedOffset = Offset; 5470b57cec5SDimitry Andric return true; 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric /// Undo the changed offset. This is needed if the instruction cannot be 5510b57cec5SDimitry Andric /// added to the current packet due to a different instruction. 5520b57cec5SDimitry Andric void HexagonPacketizerList::undoChangedOffset(MachineInstr &MI) { 5530b57cec5SDimitry Andric unsigned BP, OP; 5540b57cec5SDimitry Andric if (!HII->getBaseAndOffsetPosition(MI, BP, OP)) 5550b57cec5SDimitry Andric llvm_unreachable("Unable to find base and offset operands."); 5560b57cec5SDimitry Andric MI.getOperand(OP).setImm(ChangedOffset); 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric enum PredicateKind { 5600b57cec5SDimitry Andric PK_False, 5610b57cec5SDimitry Andric PK_True, 5620b57cec5SDimitry Andric PK_Unknown 5630b57cec5SDimitry Andric }; 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric /// Returns true if an instruction is predicated on p0 and false if it's 5660b57cec5SDimitry Andric /// predicated on !p0. 5670b57cec5SDimitry Andric static PredicateKind getPredicateSense(const MachineInstr &MI, 5680b57cec5SDimitry Andric const HexagonInstrInfo *HII) { 5690b57cec5SDimitry Andric if (!HII->isPredicated(MI)) 5700b57cec5SDimitry Andric return PK_Unknown; 5710b57cec5SDimitry Andric if (HII->isPredicatedTrue(MI)) 5720b57cec5SDimitry Andric return PK_True; 5730b57cec5SDimitry Andric return PK_False; 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric static const MachineOperand &getPostIncrementOperand(const MachineInstr &MI, 5770b57cec5SDimitry Andric const HexagonInstrInfo *HII) { 5780b57cec5SDimitry Andric assert(HII->isPostIncrement(MI) && "Not a post increment operation."); 5790b57cec5SDimitry Andric #ifndef NDEBUG 5800b57cec5SDimitry Andric // Post Increment means duplicates. Use dense map to find duplicates in the 5810b57cec5SDimitry Andric // list. Caution: Densemap initializes with the minimum of 64 buckets, 5820b57cec5SDimitry Andric // whereas there are at most 5 operands in the post increment. 5830b57cec5SDimitry Andric DenseSet<unsigned> DefRegsSet; 5840b57cec5SDimitry Andric for (auto &MO : MI.operands()) 5850b57cec5SDimitry Andric if (MO.isReg() && MO.isDef()) 5860b57cec5SDimitry Andric DefRegsSet.insert(MO.getReg()); 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric for (auto &MO : MI.operands()) 5890b57cec5SDimitry Andric if (MO.isReg() && MO.isUse() && DefRegsSet.count(MO.getReg())) 5900b57cec5SDimitry Andric return MO; 5910b57cec5SDimitry Andric #else 5920b57cec5SDimitry Andric if (MI.mayLoad()) { 5930b57cec5SDimitry Andric const MachineOperand &Op1 = MI.getOperand(1); 5940b57cec5SDimitry Andric // The 2nd operand is always the post increment operand in load. 5950b57cec5SDimitry Andric assert(Op1.isReg() && "Post increment operand has be to a register."); 5960b57cec5SDimitry Andric return Op1; 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric if (MI.getDesc().mayStore()) { 5990b57cec5SDimitry Andric const MachineOperand &Op0 = MI.getOperand(0); 6000b57cec5SDimitry Andric // The 1st operand is always the post increment operand in store. 6010b57cec5SDimitry Andric assert(Op0.isReg() && "Post increment operand has be to a register."); 6020b57cec5SDimitry Andric return Op0; 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric #endif 6050b57cec5SDimitry Andric // we should never come here. 6060b57cec5SDimitry Andric llvm_unreachable("mayLoad or mayStore not set for Post Increment operation"); 6070b57cec5SDimitry Andric } 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric // Get the value being stored. 6100b57cec5SDimitry Andric static const MachineOperand& getStoreValueOperand(const MachineInstr &MI) { 6110b57cec5SDimitry Andric // value being stored is always the last operand. 6120b57cec5SDimitry Andric return MI.getOperand(MI.getNumOperands()-1); 6130b57cec5SDimitry Andric } 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric static bool isLoadAbsSet(const MachineInstr &MI) { 6160b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 6170b57cec5SDimitry Andric switch (Opc) { 6180b57cec5SDimitry Andric case Hexagon::L4_loadrd_ap: 6190b57cec5SDimitry Andric case Hexagon::L4_loadrb_ap: 6200b57cec5SDimitry Andric case Hexagon::L4_loadrh_ap: 6210b57cec5SDimitry Andric case Hexagon::L4_loadrub_ap: 6220b57cec5SDimitry Andric case Hexagon::L4_loadruh_ap: 6230b57cec5SDimitry Andric case Hexagon::L4_loadri_ap: 6240b57cec5SDimitry Andric return true; 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric return false; 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric static const MachineOperand &getAbsSetOperand(const MachineInstr &MI) { 6300b57cec5SDimitry Andric assert(isLoadAbsSet(MI)); 6310b57cec5SDimitry Andric return MI.getOperand(1); 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric // Can be new value store? 6350b57cec5SDimitry Andric // Following restrictions are to be respected in convert a store into 6360b57cec5SDimitry Andric // a new value store. 6370b57cec5SDimitry Andric // 1. If an instruction uses auto-increment, its address register cannot 6380b57cec5SDimitry Andric // be a new-value register. Arch Spec 5.4.2.1 6390b57cec5SDimitry Andric // 2. If an instruction uses absolute-set addressing mode, its address 6400b57cec5SDimitry Andric // register cannot be a new-value register. Arch Spec 5.4.2.1. 6410b57cec5SDimitry Andric // 3. If an instruction produces a 64-bit result, its registers cannot be used 6420b57cec5SDimitry Andric // as new-value registers. Arch Spec 5.4.2.2. 6430b57cec5SDimitry Andric // 4. If the instruction that sets the new-value register is conditional, then 6440b57cec5SDimitry Andric // the instruction that uses the new-value register must also be conditional, 6450b57cec5SDimitry Andric // and both must always have their predicates evaluate identically. 6460b57cec5SDimitry Andric // Arch Spec 5.4.2.3. 6470b57cec5SDimitry Andric // 5. There is an implied restriction that a packet cannot have another store, 6480b57cec5SDimitry Andric // if there is a new value store in the packet. Corollary: if there is 6490b57cec5SDimitry Andric // already a store in a packet, there can not be a new value store. 6500b57cec5SDimitry Andric // Arch Spec: 3.4.4.2 6510b57cec5SDimitry Andric bool HexagonPacketizerList::canPromoteToNewValueStore(const MachineInstr &MI, 6520b57cec5SDimitry Andric const MachineInstr &PacketMI, unsigned DepReg) { 6530b57cec5SDimitry Andric // Make sure we are looking at the store, that can be promoted. 6540b57cec5SDimitry Andric if (!HII->mayBeNewStore(MI)) 6550b57cec5SDimitry Andric return false; 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric // Make sure there is dependency and can be new value'd. 6580b57cec5SDimitry Andric const MachineOperand &Val = getStoreValueOperand(MI); 6590b57cec5SDimitry Andric if (Val.isReg() && Val.getReg() != DepReg) 6600b57cec5SDimitry Andric return false; 6610b57cec5SDimitry Andric 6620b57cec5SDimitry Andric const MCInstrDesc& MCID = PacketMI.getDesc(); 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric // First operand is always the result. 6650b57cec5SDimitry Andric const TargetRegisterClass *PacketRC = HII->getRegClass(MCID, 0, HRI, MF); 6660b57cec5SDimitry Andric // Double regs can not feed into new value store: PRM section: 5.4.2.2. 6670b57cec5SDimitry Andric if (PacketRC == &Hexagon::DoubleRegsRegClass) 6680b57cec5SDimitry Andric return false; 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric // New-value stores are of class NV (slot 0), dual stores require class ST 6710b57cec5SDimitry Andric // in slot 0 (PRM 5.5). 672bdd1243dSDimitry Andric for (auto *I : CurrentPacketMIs) { 6730b57cec5SDimitry Andric SUnit *PacketSU = MIToSUnit.find(I)->second; 6740b57cec5SDimitry Andric if (PacketSU->getInstr()->mayStore()) 6750b57cec5SDimitry Andric return false; 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric // Make sure it's NOT the post increment register that we are going to 6790b57cec5SDimitry Andric // new value. 6800b57cec5SDimitry Andric if (HII->isPostIncrement(MI) && 6810b57cec5SDimitry Andric getPostIncrementOperand(MI, HII).getReg() == DepReg) { 6820b57cec5SDimitry Andric return false; 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric if (HII->isPostIncrement(PacketMI) && PacketMI.mayLoad() && 6860b57cec5SDimitry Andric getPostIncrementOperand(PacketMI, HII).getReg() == DepReg) { 6870b57cec5SDimitry Andric // If source is post_inc, or absolute-set addressing, it can not feed 6880b57cec5SDimitry Andric // into new value store 6890b57cec5SDimitry Andric // r3 = memw(r2++#4) 6900b57cec5SDimitry Andric // memw(r30 + #-1404) = r2.new -> can not be new value store 6910b57cec5SDimitry Andric // arch spec section: 5.4.2.1. 6920b57cec5SDimitry Andric return false; 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric if (isLoadAbsSet(PacketMI) && getAbsSetOperand(PacketMI).getReg() == DepReg) 6960b57cec5SDimitry Andric return false; 6970b57cec5SDimitry Andric 6980b57cec5SDimitry Andric // If the source that feeds the store is predicated, new value store must 6990b57cec5SDimitry Andric // also be predicated. 7000b57cec5SDimitry Andric if (HII->isPredicated(PacketMI)) { 7010b57cec5SDimitry Andric if (!HII->isPredicated(MI)) 7020b57cec5SDimitry Andric return false; 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric // Check to make sure that they both will have their predicates 7050b57cec5SDimitry Andric // evaluate identically. 7060b57cec5SDimitry Andric unsigned predRegNumSrc = 0; 7070b57cec5SDimitry Andric unsigned predRegNumDst = 0; 7080b57cec5SDimitry Andric const TargetRegisterClass* predRegClass = nullptr; 7090b57cec5SDimitry Andric 7100b57cec5SDimitry Andric // Get predicate register used in the source instruction. 7110b57cec5SDimitry Andric for (auto &MO : PacketMI.operands()) { 7120b57cec5SDimitry Andric if (!MO.isReg()) 7130b57cec5SDimitry Andric continue; 7140b57cec5SDimitry Andric predRegNumSrc = MO.getReg(); 7150b57cec5SDimitry Andric predRegClass = HRI->getMinimalPhysRegClass(predRegNumSrc); 7160b57cec5SDimitry Andric if (predRegClass == &Hexagon::PredRegsRegClass) 7170b57cec5SDimitry Andric break; 7180b57cec5SDimitry Andric } 7190b57cec5SDimitry Andric assert((predRegClass == &Hexagon::PredRegsRegClass) && 7200b57cec5SDimitry Andric "predicate register not found in a predicated PacketMI instruction"); 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric // Get predicate register used in new-value store instruction. 7230b57cec5SDimitry Andric for (auto &MO : MI.operands()) { 7240b57cec5SDimitry Andric if (!MO.isReg()) 7250b57cec5SDimitry Andric continue; 7260b57cec5SDimitry Andric predRegNumDst = MO.getReg(); 7270b57cec5SDimitry Andric predRegClass = HRI->getMinimalPhysRegClass(predRegNumDst); 7280b57cec5SDimitry Andric if (predRegClass == &Hexagon::PredRegsRegClass) 7290b57cec5SDimitry Andric break; 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric assert((predRegClass == &Hexagon::PredRegsRegClass) && 7320b57cec5SDimitry Andric "predicate register not found in a predicated MI instruction"); 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric // New-value register producer and user (store) need to satisfy these 7350b57cec5SDimitry Andric // constraints: 7360b57cec5SDimitry Andric // 1) Both instructions should be predicated on the same register. 7370b57cec5SDimitry Andric // 2) If producer of the new-value register is .new predicated then store 7380b57cec5SDimitry Andric // should also be .new predicated and if producer is not .new predicated 7390b57cec5SDimitry Andric // then store should not be .new predicated. 7400b57cec5SDimitry Andric // 3) Both new-value register producer and user should have same predicate 7410b57cec5SDimitry Andric // sense, i.e, either both should be negated or both should be non-negated. 7420b57cec5SDimitry Andric if (predRegNumDst != predRegNumSrc || 7430b57cec5SDimitry Andric HII->isDotNewInst(PacketMI) != HII->isDotNewInst(MI) || 7440b57cec5SDimitry Andric getPredicateSense(MI, HII) != getPredicateSense(PacketMI, HII)) 7450b57cec5SDimitry Andric return false; 7460b57cec5SDimitry Andric } 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric // Make sure that other than the new-value register no other store instruction 7490b57cec5SDimitry Andric // register has been modified in the same packet. Predicate registers can be 7500b57cec5SDimitry Andric // modified by they should not be modified between the producer and the store 7510b57cec5SDimitry Andric // instruction as it will make them both conditional on different values. 7520b57cec5SDimitry Andric // We already know this to be true for all the instructions before and 7530b57cec5SDimitry Andric // including PacketMI. Howerver, we need to perform the check for the 7540b57cec5SDimitry Andric // remaining instructions in the packet. 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric unsigned StartCheck = 0; 7570b57cec5SDimitry Andric 758bdd1243dSDimitry Andric for (auto *I : CurrentPacketMIs) { 7590b57cec5SDimitry Andric SUnit *TempSU = MIToSUnit.find(I)->second; 7600b57cec5SDimitry Andric MachineInstr &TempMI = *TempSU->getInstr(); 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric // Following condition is true for all the instructions until PacketMI is 7630b57cec5SDimitry Andric // reached (StartCheck is set to 0 before the for loop). 7640b57cec5SDimitry Andric // StartCheck flag is 1 for all the instructions after PacketMI. 7650b57cec5SDimitry Andric if (&TempMI != &PacketMI && !StartCheck) // Start processing only after 7660b57cec5SDimitry Andric continue; // encountering PacketMI. 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric StartCheck = 1; 7690b57cec5SDimitry Andric if (&TempMI == &PacketMI) // We don't want to check PacketMI for dependence. 7700b57cec5SDimitry Andric continue; 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric for (auto &MO : MI.operands()) 7730b57cec5SDimitry Andric if (MO.isReg() && TempSU->getInstr()->modifiesRegister(MO.getReg(), HRI)) 7740b57cec5SDimitry Andric return false; 7750b57cec5SDimitry Andric } 7760b57cec5SDimitry Andric 7770b57cec5SDimitry Andric // Make sure that for non-POST_INC stores: 7780b57cec5SDimitry Andric // 1. The only use of reg is DepReg and no other registers. 7790b57cec5SDimitry Andric // This handles base+index registers. 7800b57cec5SDimitry Andric // The following store can not be dot new. 7810b57cec5SDimitry Andric // Eg. r0 = add(r0, #3) 7820b57cec5SDimitry Andric // memw(r1+r0<<#2) = r0 7830b57cec5SDimitry Andric if (!HII->isPostIncrement(MI)) { 7840b57cec5SDimitry Andric for (unsigned opNum = 0; opNum < MI.getNumOperands()-1; opNum++) { 7850b57cec5SDimitry Andric const MachineOperand &MO = MI.getOperand(opNum); 7860b57cec5SDimitry Andric if (MO.isReg() && MO.getReg() == DepReg) 7870b57cec5SDimitry Andric return false; 7880b57cec5SDimitry Andric } 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric // If data definition is because of implicit definition of the register, 7920b57cec5SDimitry Andric // do not newify the store. Eg. 7930b57cec5SDimitry Andric // %r9 = ZXTH %r12, implicit %d6, implicit-def %r12 7940b57cec5SDimitry Andric // S2_storerh_io %r8, 2, killed %r12; mem:ST2[%scevgep343] 7950b57cec5SDimitry Andric for (auto &MO : PacketMI.operands()) { 7960b57cec5SDimitry Andric if (MO.isRegMask() && MO.clobbersPhysReg(DepReg)) 7970b57cec5SDimitry Andric return false; 7980b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef() || !MO.isImplicit()) 7990b57cec5SDimitry Andric continue; 8008bcb0991SDimitry Andric Register R = MO.getReg(); 8010b57cec5SDimitry Andric if (R == DepReg || HRI->isSuperRegister(DepReg, R)) 8020b57cec5SDimitry Andric return false; 8030b57cec5SDimitry Andric } 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric // Handle imp-use of super reg case. There is a target independent side 8060b57cec5SDimitry Andric // change that should prevent this situation but I am handling it for 8070b57cec5SDimitry Andric // just-in-case. For example, we cannot newify R2 in the following case: 8080b57cec5SDimitry Andric // %r3 = A2_tfrsi 0; 8090b57cec5SDimitry Andric // S2_storeri_io killed %r0, 0, killed %r2, implicit killed %d1; 8100b57cec5SDimitry Andric for (auto &MO : MI.operands()) { 8110b57cec5SDimitry Andric if (MO.isReg() && MO.isUse() && MO.isImplicit() && MO.getReg() == DepReg) 8120b57cec5SDimitry Andric return false; 8130b57cec5SDimitry Andric } 8140b57cec5SDimitry Andric 8150b57cec5SDimitry Andric // Can be dot new store. 8160b57cec5SDimitry Andric return true; 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric // Can this MI to promoted to either new value store or new value jump. 8200b57cec5SDimitry Andric bool HexagonPacketizerList::canPromoteToNewValue(const MachineInstr &MI, 8210b57cec5SDimitry Andric const SUnit *PacketSU, unsigned DepReg, 8220b57cec5SDimitry Andric MachineBasicBlock::iterator &MII) { 8230b57cec5SDimitry Andric if (!HII->mayBeNewStore(MI)) 8240b57cec5SDimitry Andric return false; 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric // Check to see the store can be new value'ed. 8270b57cec5SDimitry Andric MachineInstr &PacketMI = *PacketSU->getInstr(); 8280b57cec5SDimitry Andric if (canPromoteToNewValueStore(MI, PacketMI, DepReg)) 8290b57cec5SDimitry Andric return true; 8300b57cec5SDimitry Andric 8310b57cec5SDimitry Andric // Check to see the compare/jump can be new value'ed. 8320b57cec5SDimitry Andric // This is done as a pass on its own. Don't need to check it here. 8330b57cec5SDimitry Andric return false; 8340b57cec5SDimitry Andric } 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric static bool isImplicitDependency(const MachineInstr &I, bool CheckDef, 8370b57cec5SDimitry Andric unsigned DepReg) { 8380b57cec5SDimitry Andric for (auto &MO : I.operands()) { 8390b57cec5SDimitry Andric if (CheckDef && MO.isRegMask() && MO.clobbersPhysReg(DepReg)) 8400b57cec5SDimitry Andric return true; 8410b57cec5SDimitry Andric if (!MO.isReg() || MO.getReg() != DepReg || !MO.isImplicit()) 8420b57cec5SDimitry Andric continue; 8430b57cec5SDimitry Andric if (CheckDef == MO.isDef()) 8440b57cec5SDimitry Andric return true; 8450b57cec5SDimitry Andric } 8460b57cec5SDimitry Andric return false; 8470b57cec5SDimitry Andric } 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric // Check to see if an instruction can be dot new. 8500b57cec5SDimitry Andric bool HexagonPacketizerList::canPromoteToDotNew(const MachineInstr &MI, 8510b57cec5SDimitry Andric const SUnit *PacketSU, unsigned DepReg, MachineBasicBlock::iterator &MII, 8520b57cec5SDimitry Andric const TargetRegisterClass* RC) { 8530b57cec5SDimitry Andric // Already a dot new instruction. 8540b57cec5SDimitry Andric if (HII->isDotNewInst(MI) && !HII->mayBeNewStore(MI)) 8550b57cec5SDimitry Andric return false; 8560b57cec5SDimitry Andric 8570b57cec5SDimitry Andric if (!isNewifiable(MI, RC)) 8580b57cec5SDimitry Andric return false; 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric const MachineInstr &PI = *PacketSU->getInstr(); 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric // The "new value" cannot come from inline asm. 8630b57cec5SDimitry Andric if (PI.isInlineAsm()) 8640b57cec5SDimitry Andric return false; 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric // IMPLICIT_DEFs won't materialize as real instructions, so .new makes no 8670b57cec5SDimitry Andric // sense. 8680b57cec5SDimitry Andric if (PI.isImplicitDef()) 8690b57cec5SDimitry Andric return false; 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric // If dependency is trough an implicitly defined register, we should not 8720b57cec5SDimitry Andric // newify the use. 8730b57cec5SDimitry Andric if (isImplicitDependency(PI, true, DepReg) || 8740b57cec5SDimitry Andric isImplicitDependency(MI, false, DepReg)) 8750b57cec5SDimitry Andric return false; 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric const MCInstrDesc& MCID = PI.getDesc(); 8780b57cec5SDimitry Andric const TargetRegisterClass *VecRC = HII->getRegClass(MCID, 0, HRI, MF); 8790b57cec5SDimitry Andric if (DisableVecDblNVStores && VecRC == &Hexagon::HvxWRRegClass) 8800b57cec5SDimitry Andric return false; 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric // predicate .new 8830b57cec5SDimitry Andric if (RC == &Hexagon::PredRegsRegClass) 8840b57cec5SDimitry Andric return HII->predCanBeUsedAsDotNew(PI, DepReg); 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric if (RC != &Hexagon::PredRegsRegClass && !HII->mayBeNewStore(MI)) 8870b57cec5SDimitry Andric return false; 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric // Create a dot new machine instruction to see if resources can be 8900b57cec5SDimitry Andric // allocated. If not, bail out now. 89104eeddc0SDimitry Andric int NewOpcode = (RC != &Hexagon::PredRegsRegClass) ? HII->getDotNewOp(MI) : 89204eeddc0SDimitry Andric HII->getDotNewPredOp(MI, MBPI); 8930b57cec5SDimitry Andric const MCInstrDesc &D = HII->get(NewOpcode); 8940b57cec5SDimitry Andric MachineInstr *NewMI = MF.CreateMachineInstr(D, DebugLoc()); 8950b57cec5SDimitry Andric bool ResourcesAvailable = ResourceTracker->canReserveResources(*NewMI); 8960eae32dcSDimitry Andric MF.deleteMachineInstr(NewMI); 8970b57cec5SDimitry Andric if (!ResourcesAvailable) 8980b57cec5SDimitry Andric return false; 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric // New Value Store only. New Value Jump generated as a separate pass. 9010b57cec5SDimitry Andric if (!canPromoteToNewValue(MI, PacketSU, DepReg, MII)) 9020b57cec5SDimitry Andric return false; 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric return true; 9050b57cec5SDimitry Andric } 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric // Go through the packet instructions and search for an anti dependency between 9080b57cec5SDimitry Andric // them and DepReg from MI. Consider this case: 9090b57cec5SDimitry Andric // Trying to add 9100b57cec5SDimitry Andric // a) %r1 = TFRI_cdNotPt %p3, 2 9110b57cec5SDimitry Andric // to this packet: 9120b57cec5SDimitry Andric // { 9130b57cec5SDimitry Andric // b) %p0 = C2_or killed %p3, killed %p0 9140b57cec5SDimitry Andric // c) %p3 = C2_tfrrp %r23 9150b57cec5SDimitry Andric // d) %r1 = C2_cmovenewit %p3, 4 9160b57cec5SDimitry Andric // } 9170b57cec5SDimitry Andric // The P3 from a) and d) will be complements after 9180b57cec5SDimitry Andric // a)'s P3 is converted to .new form 9190b57cec5SDimitry Andric // Anti-dep between c) and b) is irrelevant for this case 9200b57cec5SDimitry Andric bool HexagonPacketizerList::restrictingDepExistInPacket(MachineInstr &MI, 9210b57cec5SDimitry Andric unsigned DepReg) { 9220b57cec5SDimitry Andric SUnit *PacketSUDep = MIToSUnit.find(&MI)->second; 9230b57cec5SDimitry Andric 924bdd1243dSDimitry Andric for (auto *I : CurrentPacketMIs) { 9250b57cec5SDimitry Andric // We only care for dependencies to predicated instructions 9260b57cec5SDimitry Andric if (!HII->isPredicated(*I)) 9270b57cec5SDimitry Andric continue; 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric // Scheduling Unit for current insn in the packet 9300b57cec5SDimitry Andric SUnit *PacketSU = MIToSUnit.find(I)->second; 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric // Look at dependencies between current members of the packet and 9330b57cec5SDimitry Andric // predicate defining instruction MI. Make sure that dependency is 9340b57cec5SDimitry Andric // on the exact register we care about. 9350b57cec5SDimitry Andric if (PacketSU->isSucc(PacketSUDep)) { 9360b57cec5SDimitry Andric for (unsigned i = 0; i < PacketSU->Succs.size(); ++i) { 9370b57cec5SDimitry Andric auto &Dep = PacketSU->Succs[i]; 9380b57cec5SDimitry Andric if (Dep.getSUnit() == PacketSUDep && Dep.getKind() == SDep::Anti && 9390b57cec5SDimitry Andric Dep.getReg() == DepReg) 9400b57cec5SDimitry Andric return true; 9410b57cec5SDimitry Andric } 9420b57cec5SDimitry Andric } 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric return false; 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric 9480b57cec5SDimitry Andric /// Gets the predicate register of a predicated instruction. 9490b57cec5SDimitry Andric static unsigned getPredicatedRegister(MachineInstr &MI, 9500b57cec5SDimitry Andric const HexagonInstrInfo *QII) { 9510b57cec5SDimitry Andric /// We use the following rule: The first predicate register that is a use is 9520b57cec5SDimitry Andric /// the predicate register of a predicated instruction. 9530b57cec5SDimitry Andric assert(QII->isPredicated(MI) && "Must be predicated instruction"); 9540b57cec5SDimitry Andric 9550b57cec5SDimitry Andric for (auto &Op : MI.operands()) { 9560b57cec5SDimitry Andric if (Op.isReg() && Op.getReg() && Op.isUse() && 9570b57cec5SDimitry Andric Hexagon::PredRegsRegClass.contains(Op.getReg())) 9580b57cec5SDimitry Andric return Op.getReg(); 9590b57cec5SDimitry Andric } 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric llvm_unreachable("Unknown instruction operand layout"); 9620b57cec5SDimitry Andric return 0; 9630b57cec5SDimitry Andric } 9640b57cec5SDimitry Andric 9650b57cec5SDimitry Andric // Given two predicated instructions, this function detects whether 9660b57cec5SDimitry Andric // the predicates are complements. 9670b57cec5SDimitry Andric bool HexagonPacketizerList::arePredicatesComplements(MachineInstr &MI1, 9680b57cec5SDimitry Andric MachineInstr &MI2) { 9690b57cec5SDimitry Andric // If we don't know the predicate sense of the instructions bail out early, we 9700b57cec5SDimitry Andric // need it later. 9710b57cec5SDimitry Andric if (getPredicateSense(MI1, HII) == PK_Unknown || 9720b57cec5SDimitry Andric getPredicateSense(MI2, HII) == PK_Unknown) 9730b57cec5SDimitry Andric return false; 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric // Scheduling unit for candidate. 9760b57cec5SDimitry Andric SUnit *SU = MIToSUnit[&MI1]; 9770b57cec5SDimitry Andric 9780b57cec5SDimitry Andric // One corner case deals with the following scenario: 9790b57cec5SDimitry Andric // Trying to add 9800b57cec5SDimitry Andric // a) %r24 = A2_tfrt %p0, %r25 9810b57cec5SDimitry Andric // to this packet: 9820b57cec5SDimitry Andric // { 9830b57cec5SDimitry Andric // b) %r25 = A2_tfrf %p0, %r24 9840b57cec5SDimitry Andric // c) %p0 = C2_cmpeqi %r26, 1 9850b57cec5SDimitry Andric // } 9860b57cec5SDimitry Andric // 9870b57cec5SDimitry Andric // On general check a) and b) are complements, but presence of c) will 9880b57cec5SDimitry Andric // convert a) to .new form, and then it is not a complement. 9890b57cec5SDimitry Andric // We attempt to detect it by analyzing existing dependencies in the packet. 9900b57cec5SDimitry Andric 9910b57cec5SDimitry Andric // Analyze relationships between all existing members of the packet. 9920b57cec5SDimitry Andric // Look for Anti dependecy on the same predicate reg as used in the 9930b57cec5SDimitry Andric // candidate. 994bdd1243dSDimitry Andric for (auto *I : CurrentPacketMIs) { 9950b57cec5SDimitry Andric // Scheduling Unit for current insn in the packet. 9960b57cec5SDimitry Andric SUnit *PacketSU = MIToSUnit.find(I)->second; 9970b57cec5SDimitry Andric 9980b57cec5SDimitry Andric // If this instruction in the packet is succeeded by the candidate... 9990b57cec5SDimitry Andric if (PacketSU->isSucc(SU)) { 10000b57cec5SDimitry Andric for (unsigned i = 0; i < PacketSU->Succs.size(); ++i) { 10010b57cec5SDimitry Andric auto Dep = PacketSU->Succs[i]; 10020b57cec5SDimitry Andric // The corner case exist when there is true data dependency between 10030b57cec5SDimitry Andric // candidate and one of current packet members, this dep is on 10040b57cec5SDimitry Andric // predicate reg, and there already exist anti dep on the same pred in 10050b57cec5SDimitry Andric // the packet. 10060b57cec5SDimitry Andric if (Dep.getSUnit() == SU && Dep.getKind() == SDep::Data && 10070b57cec5SDimitry Andric Hexagon::PredRegsRegClass.contains(Dep.getReg())) { 10080b57cec5SDimitry Andric // Here I know that I is predicate setting instruction with true 10090b57cec5SDimitry Andric // data dep to candidate on the register we care about - c) in the 10100b57cec5SDimitry Andric // above example. Now I need to see if there is an anti dependency 10110b57cec5SDimitry Andric // from c) to any other instruction in the same packet on the pred 10120b57cec5SDimitry Andric // reg of interest. 10130b57cec5SDimitry Andric if (restrictingDepExistInPacket(*I, Dep.getReg())) 10140b57cec5SDimitry Andric return false; 10150b57cec5SDimitry Andric } 10160b57cec5SDimitry Andric } 10170b57cec5SDimitry Andric } 10180b57cec5SDimitry Andric } 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric // If the above case does not apply, check regular complement condition. 10210b57cec5SDimitry Andric // Check that the predicate register is the same and that the predicate 10220b57cec5SDimitry Andric // sense is different We also need to differentiate .old vs. .new: !p0 10230b57cec5SDimitry Andric // is not complementary to p0.new. 10240b57cec5SDimitry Andric unsigned PReg1 = getPredicatedRegister(MI1, HII); 10250b57cec5SDimitry Andric unsigned PReg2 = getPredicatedRegister(MI2, HII); 10260b57cec5SDimitry Andric return PReg1 == PReg2 && 10270b57cec5SDimitry Andric Hexagon::PredRegsRegClass.contains(PReg1) && 10280b57cec5SDimitry Andric Hexagon::PredRegsRegClass.contains(PReg2) && 10290b57cec5SDimitry Andric getPredicateSense(MI1, HII) != getPredicateSense(MI2, HII) && 10300b57cec5SDimitry Andric HII->isDotNewInst(MI1) == HII->isDotNewInst(MI2); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric // Initialize packetizer flags. 10340b57cec5SDimitry Andric void HexagonPacketizerList::initPacketizerState() { 10350b57cec5SDimitry Andric Dependence = false; 10360b57cec5SDimitry Andric PromotedToDotNew = false; 10370b57cec5SDimitry Andric GlueToNewValueJump = false; 10380b57cec5SDimitry Andric GlueAllocframeStore = false; 10390b57cec5SDimitry Andric FoundSequentialDependence = false; 10400b57cec5SDimitry Andric ChangedOffset = INT64_MAX; 10410b57cec5SDimitry Andric } 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andric // Ignore bundling of pseudo instructions. 10440b57cec5SDimitry Andric bool HexagonPacketizerList::ignorePseudoInstruction(const MachineInstr &MI, 10450b57cec5SDimitry Andric const MachineBasicBlock *) { 10460b57cec5SDimitry Andric if (MI.isDebugInstr()) 10470b57cec5SDimitry Andric return true; 10480b57cec5SDimitry Andric 10490b57cec5SDimitry Andric if (MI.isCFIInstruction()) 10500b57cec5SDimitry Andric return false; 10510b57cec5SDimitry Andric 10520b57cec5SDimitry Andric // We must print out inline assembly. 10530b57cec5SDimitry Andric if (MI.isInlineAsm()) 10540b57cec5SDimitry Andric return false; 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andric if (MI.isImplicitDef()) 10570b57cec5SDimitry Andric return false; 10580b57cec5SDimitry Andric 10590b57cec5SDimitry Andric // We check if MI has any functional units mapped to it. If it doesn't, 10600b57cec5SDimitry Andric // we ignore the instruction. 10610b57cec5SDimitry Andric const MCInstrDesc& TID = MI.getDesc(); 10620b57cec5SDimitry Andric auto *IS = ResourceTracker->getInstrItins()->beginStage(TID.getSchedClass()); 10635ffd83dbSDimitry Andric return !IS->getUnits(); 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric bool HexagonPacketizerList::isSoloInstruction(const MachineInstr &MI) { 10675ffd83dbSDimitry Andric // Ensure any bundles created by gather packetize remain separate. 10680b57cec5SDimitry Andric if (MI.isBundle()) 10690b57cec5SDimitry Andric return true; 10700b57cec5SDimitry Andric 10710b57cec5SDimitry Andric if (MI.isEHLabel() || MI.isCFIInstruction()) 10720b57cec5SDimitry Andric return true; 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric // Consider inline asm to not be a solo instruction by default. 10750b57cec5SDimitry Andric // Inline asm will be put in a packet temporarily, but then it will be 10760b57cec5SDimitry Andric // removed, and placed outside of the packet (before or after, depending 10770b57cec5SDimitry Andric // on dependencies). This is to reduce the impact of inline asm as a 10780b57cec5SDimitry Andric // "packet splitting" instruction. 10790b57cec5SDimitry Andric if (MI.isInlineAsm() && !ScheduleInlineAsm) 10800b57cec5SDimitry Andric return true; 10810b57cec5SDimitry Andric 10820b57cec5SDimitry Andric if (isSchedBarrier(MI)) 10830b57cec5SDimitry Andric return true; 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric if (HII->isSolo(MI)) 10860b57cec5SDimitry Andric return true; 10870b57cec5SDimitry Andric 10880eae32dcSDimitry Andric if (MI.getOpcode() == Hexagon::PATCHABLE_FUNCTION_ENTER || 10890eae32dcSDimitry Andric MI.getOpcode() == Hexagon::PATCHABLE_FUNCTION_EXIT || 10900eae32dcSDimitry Andric MI.getOpcode() == Hexagon::PATCHABLE_TAIL_CALL) 10910eae32dcSDimitry Andric return true; 10920eae32dcSDimitry Andric 10930b57cec5SDimitry Andric if (MI.getOpcode() == Hexagon::A2_nop) 10940b57cec5SDimitry Andric return true; 10950b57cec5SDimitry Andric 10960b57cec5SDimitry Andric return false; 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric 10990b57cec5SDimitry Andric // Quick check if instructions MI and MJ cannot coexist in the same packet. 11000b57cec5SDimitry Andric // Limit the tests to be "one-way", e.g. "if MI->isBranch and MJ->isInlineAsm", 11010b57cec5SDimitry Andric // but not the symmetric case: "if MJ->isBranch and MI->isInlineAsm". 11020b57cec5SDimitry Andric // For full test call this function twice: 11030b57cec5SDimitry Andric // cannotCoexistAsymm(MI, MJ) || cannotCoexistAsymm(MJ, MI) 11040b57cec5SDimitry Andric // Doing the test only one way saves the amount of code in this function, 11050b57cec5SDimitry Andric // since every test would need to be repeated with the MI and MJ reversed. 11060b57cec5SDimitry Andric static bool cannotCoexistAsymm(const MachineInstr &MI, const MachineInstr &MJ, 11070b57cec5SDimitry Andric const HexagonInstrInfo &HII) { 11080b57cec5SDimitry Andric const MachineFunction *MF = MI.getParent()->getParent(); 11090b57cec5SDimitry Andric if (MF->getSubtarget<HexagonSubtarget>().hasV60OpsOnly() && 11100b57cec5SDimitry Andric HII.isHVXMemWithAIndirect(MI, MJ)) 11110b57cec5SDimitry Andric return true; 11120b57cec5SDimitry Andric 111304eeddc0SDimitry Andric // Don't allow a store and an instruction that must be in slot0 and 111404eeddc0SDimitry Andric // doesn't allow a slot1 instruction. 111504eeddc0SDimitry Andric if (MI.mayStore() && HII.isRestrictNoSlot1Store(MJ) && HII.isPureSlot0(MJ)) 111604eeddc0SDimitry Andric return true; 111704eeddc0SDimitry Andric 11180b57cec5SDimitry Andric // An inline asm cannot be together with a branch, because we may not be 11190b57cec5SDimitry Andric // able to remove the asm out after packetizing (i.e. if the asm must be 11200b57cec5SDimitry Andric // moved past the bundle). Similarly, two asms cannot be together to avoid 11210b57cec5SDimitry Andric // complications when determining their relative order outside of a bundle. 11220b57cec5SDimitry Andric if (MI.isInlineAsm()) 11230b57cec5SDimitry Andric return MJ.isInlineAsm() || MJ.isBranch() || MJ.isBarrier() || 11240b57cec5SDimitry Andric MJ.isCall() || MJ.isTerminator(); 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric // New-value stores cannot coexist with any other stores. 11270b57cec5SDimitry Andric if (HII.isNewValueStore(MI) && MJ.mayStore()) 11280b57cec5SDimitry Andric return true; 11290b57cec5SDimitry Andric 11300b57cec5SDimitry Andric switch (MI.getOpcode()) { 11310b57cec5SDimitry Andric case Hexagon::S2_storew_locked: 11320b57cec5SDimitry Andric case Hexagon::S4_stored_locked: 11330b57cec5SDimitry Andric case Hexagon::L2_loadw_locked: 11340b57cec5SDimitry Andric case Hexagon::L4_loadd_locked: 11350b57cec5SDimitry Andric case Hexagon::Y2_dccleana: 11360b57cec5SDimitry Andric case Hexagon::Y2_dccleaninva: 11370b57cec5SDimitry Andric case Hexagon::Y2_dcinva: 11380b57cec5SDimitry Andric case Hexagon::Y2_dczeroa: 11390b57cec5SDimitry Andric case Hexagon::Y4_l2fetch: 11400b57cec5SDimitry Andric case Hexagon::Y5_l2fetch: { 11410b57cec5SDimitry Andric // These instructions can only be grouped with ALU32 or non-floating-point 11420b57cec5SDimitry Andric // XTYPE instructions. Since there is no convenient way of identifying fp 11430b57cec5SDimitry Andric // XTYPE instructions, only allow grouping with ALU32 for now. 11440b57cec5SDimitry Andric unsigned TJ = HII.getType(MJ); 11450b57cec5SDimitry Andric if (TJ != HexagonII::TypeALU32_2op && 11460b57cec5SDimitry Andric TJ != HexagonII::TypeALU32_3op && 11470b57cec5SDimitry Andric TJ != HexagonII::TypeALU32_ADDI) 11480b57cec5SDimitry Andric return true; 11490b57cec5SDimitry Andric break; 11500b57cec5SDimitry Andric } 11510b57cec5SDimitry Andric default: 11520b57cec5SDimitry Andric break; 11530b57cec5SDimitry Andric } 11540b57cec5SDimitry Andric 11550b57cec5SDimitry Andric // "False" really means that the quick check failed to determine if 11560b57cec5SDimitry Andric // I and J cannot coexist. 11570b57cec5SDimitry Andric return false; 11580b57cec5SDimitry Andric } 11590b57cec5SDimitry Andric 11600b57cec5SDimitry Andric // Full, symmetric check. 11610b57cec5SDimitry Andric bool HexagonPacketizerList::cannotCoexist(const MachineInstr &MI, 11620b57cec5SDimitry Andric const MachineInstr &MJ) { 11630b57cec5SDimitry Andric return cannotCoexistAsymm(MI, MJ, *HII) || cannotCoexistAsymm(MJ, MI, *HII); 11640b57cec5SDimitry Andric } 11650b57cec5SDimitry Andric 11660b57cec5SDimitry Andric void HexagonPacketizerList::unpacketizeSoloInstrs(MachineFunction &MF) { 11670b57cec5SDimitry Andric for (auto &B : MF) { 11680b57cec5SDimitry Andric MachineBasicBlock::iterator BundleIt; 1169349cc55cSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(B.instrs())) { 11700b57cec5SDimitry Andric if (MI.isBundle()) 1171349cc55cSDimitry Andric BundleIt = MI.getIterator(); 11720b57cec5SDimitry Andric if (!MI.isInsideBundle()) 11730b57cec5SDimitry Andric continue; 11740b57cec5SDimitry Andric 11750b57cec5SDimitry Andric // Decide on where to insert the instruction that we are pulling out. 11760b57cec5SDimitry Andric // Debug instructions always go before the bundle, but the placement of 11770b57cec5SDimitry Andric // INLINE_ASM depends on potential dependencies. By default, try to 11780b57cec5SDimitry Andric // put it before the bundle, but if the asm writes to a register that 11790b57cec5SDimitry Andric // other instructions in the bundle read, then we need to place it 11800b57cec5SDimitry Andric // after the bundle (to preserve the bundle semantics). 11810b57cec5SDimitry Andric bool InsertBeforeBundle; 11820b57cec5SDimitry Andric if (MI.isInlineAsm()) 11830b57cec5SDimitry Andric InsertBeforeBundle = !hasWriteToReadDep(MI, *BundleIt, HRI); 1184*0fca6ea1SDimitry Andric else if (MI.isDebugInstr()) 11850b57cec5SDimitry Andric InsertBeforeBundle = true; 11860b57cec5SDimitry Andric else 11870b57cec5SDimitry Andric continue; 11880b57cec5SDimitry Andric 11890b57cec5SDimitry Andric BundleIt = moveInstrOut(MI, BundleIt, InsertBeforeBundle); 11900b57cec5SDimitry Andric } 11910b57cec5SDimitry Andric } 11920b57cec5SDimitry Andric } 11930b57cec5SDimitry Andric 11940b57cec5SDimitry Andric // Check if a given instruction is of class "system". 11950b57cec5SDimitry Andric static bool isSystemInstr(const MachineInstr &MI) { 11960b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 11970b57cec5SDimitry Andric switch (Opc) { 11980b57cec5SDimitry Andric case Hexagon::Y2_barrier: 11990b57cec5SDimitry Andric case Hexagon::Y2_dcfetchbo: 12000b57cec5SDimitry Andric case Hexagon::Y4_l2fetch: 12010b57cec5SDimitry Andric case Hexagon::Y5_l2fetch: 12020b57cec5SDimitry Andric return true; 12030b57cec5SDimitry Andric } 12040b57cec5SDimitry Andric return false; 12050b57cec5SDimitry Andric } 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric bool HexagonPacketizerList::hasDeadDependence(const MachineInstr &I, 12080b57cec5SDimitry Andric const MachineInstr &J) { 12090b57cec5SDimitry Andric // The dependence graph may not include edges between dead definitions, 12100b57cec5SDimitry Andric // so without extra checks, we could end up packetizing two instruction 12110b57cec5SDimitry Andric // defining the same (dead) register. 12120b57cec5SDimitry Andric if (I.isCall() || J.isCall()) 12130b57cec5SDimitry Andric return false; 12140b57cec5SDimitry Andric if (HII->isPredicated(I) || HII->isPredicated(J)) 12150b57cec5SDimitry Andric return false; 12160b57cec5SDimitry Andric 12170b57cec5SDimitry Andric BitVector DeadDefs(Hexagon::NUM_TARGET_REGS); 12180b57cec5SDimitry Andric for (auto &MO : I.operands()) { 12190b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef() || !MO.isDead()) 12200b57cec5SDimitry Andric continue; 12210b57cec5SDimitry Andric DeadDefs[MO.getReg()] = true; 12220b57cec5SDimitry Andric } 12230b57cec5SDimitry Andric 12240b57cec5SDimitry Andric for (auto &MO : J.operands()) { 12250b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef() || !MO.isDead()) 12260b57cec5SDimitry Andric continue; 12278bcb0991SDimitry Andric Register R = MO.getReg(); 12280b57cec5SDimitry Andric if (R != Hexagon::USR_OVF && DeadDefs[R]) 12290b57cec5SDimitry Andric return true; 12300b57cec5SDimitry Andric } 12310b57cec5SDimitry Andric return false; 12320b57cec5SDimitry Andric } 12330b57cec5SDimitry Andric 12340b57cec5SDimitry Andric bool HexagonPacketizerList::hasControlDependence(const MachineInstr &I, 12350b57cec5SDimitry Andric const MachineInstr &J) { 12360b57cec5SDimitry Andric // A save callee-save register function call can only be in a packet 12370b57cec5SDimitry Andric // with instructions that don't write to the callee-save registers. 12380b57cec5SDimitry Andric if ((HII->isSaveCalleeSavedRegsCall(I) && 12390b57cec5SDimitry Andric doesModifyCalleeSavedReg(J, HRI)) || 12400b57cec5SDimitry Andric (HII->isSaveCalleeSavedRegsCall(J) && 12410b57cec5SDimitry Andric doesModifyCalleeSavedReg(I, HRI))) 12420b57cec5SDimitry Andric return true; 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric // Two control flow instructions cannot go in the same packet. 12450b57cec5SDimitry Andric if (isControlFlow(I) && isControlFlow(J)) 12460b57cec5SDimitry Andric return true; 12470b57cec5SDimitry Andric 12480b57cec5SDimitry Andric // \ref-manual (7.3.4) A loop setup packet in loopN or spNloop0 cannot 12490b57cec5SDimitry Andric // contain a speculative indirect jump, 12500b57cec5SDimitry Andric // a new-value compare jump or a dealloc_return. 12510b57cec5SDimitry Andric auto isBadForLoopN = [this] (const MachineInstr &MI) -> bool { 12520b57cec5SDimitry Andric if (MI.isCall() || HII->isDeallocRet(MI) || HII->isNewValueJump(MI)) 12530b57cec5SDimitry Andric return true; 12540b57cec5SDimitry Andric if (HII->isPredicated(MI) && HII->isPredicatedNew(MI) && HII->isJumpR(MI)) 12550b57cec5SDimitry Andric return true; 12560b57cec5SDimitry Andric return false; 12570b57cec5SDimitry Andric }; 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andric if (HII->isLoopN(I) && isBadForLoopN(J)) 12600b57cec5SDimitry Andric return true; 12610b57cec5SDimitry Andric if (HII->isLoopN(J) && isBadForLoopN(I)) 12620b57cec5SDimitry Andric return true; 12630b57cec5SDimitry Andric 12640b57cec5SDimitry Andric // dealloc_return cannot appear in the same packet as a conditional or 12650b57cec5SDimitry Andric // unconditional jump. 12660b57cec5SDimitry Andric return HII->isDeallocRet(I) && 12670b57cec5SDimitry Andric (J.isBranch() || J.isCall() || J.isBarrier()); 12680b57cec5SDimitry Andric } 12690b57cec5SDimitry Andric 12700b57cec5SDimitry Andric bool HexagonPacketizerList::hasRegMaskDependence(const MachineInstr &I, 12710b57cec5SDimitry Andric const MachineInstr &J) { 12720b57cec5SDimitry Andric // Adding I to a packet that has J. 12730b57cec5SDimitry Andric 12740b57cec5SDimitry Andric // Regmasks are not reflected in the scheduling dependency graph, so 12750b57cec5SDimitry Andric // we need to check them manually. This code assumes that regmasks only 12760b57cec5SDimitry Andric // occur on calls, and the problematic case is when we add an instruction 12770b57cec5SDimitry Andric // defining a register R to a packet that has a call that clobbers R via 12780b57cec5SDimitry Andric // a regmask. Those cannot be packetized together, because the call will 12790b57cec5SDimitry Andric // be executed last. That's also a reson why it is ok to add a call 12800b57cec5SDimitry Andric // clobbering R to a packet that defines R. 12810b57cec5SDimitry Andric 12820b57cec5SDimitry Andric // Look for regmasks in J. 12830b57cec5SDimitry Andric for (const MachineOperand &OpJ : J.operands()) { 12840b57cec5SDimitry Andric if (!OpJ.isRegMask()) 12850b57cec5SDimitry Andric continue; 12860b57cec5SDimitry Andric assert((J.isCall() || HII->isTailCall(J)) && "Regmask on a non-call"); 12870b57cec5SDimitry Andric for (const MachineOperand &OpI : I.operands()) { 12880b57cec5SDimitry Andric if (OpI.isReg()) { 12890b57cec5SDimitry Andric if (OpJ.clobbersPhysReg(OpI.getReg())) 12900b57cec5SDimitry Andric return true; 12910b57cec5SDimitry Andric } else if (OpI.isRegMask()) { 12920b57cec5SDimitry Andric // Both are regmasks. Assume that they intersect. 12930b57cec5SDimitry Andric return true; 12940b57cec5SDimitry Andric } 12950b57cec5SDimitry Andric } 12960b57cec5SDimitry Andric } 12970b57cec5SDimitry Andric return false; 12980b57cec5SDimitry Andric } 12990b57cec5SDimitry Andric 13000b57cec5SDimitry Andric bool HexagonPacketizerList::hasDualStoreDependence(const MachineInstr &I, 13010b57cec5SDimitry Andric const MachineInstr &J) { 13020b57cec5SDimitry Andric bool SysI = isSystemInstr(I), SysJ = isSystemInstr(J); 13030b57cec5SDimitry Andric bool StoreI = I.mayStore(), StoreJ = J.mayStore(); 13040b57cec5SDimitry Andric if ((SysI && StoreJ) || (SysJ && StoreI)) 13050b57cec5SDimitry Andric return true; 13060b57cec5SDimitry Andric 13070b57cec5SDimitry Andric if (StoreI && StoreJ) { 13080b57cec5SDimitry Andric if (HII->isNewValueInst(J) || HII->isMemOp(J) || HII->isMemOp(I)) 13090b57cec5SDimitry Andric return true; 13100b57cec5SDimitry Andric } else { 13110b57cec5SDimitry Andric // A memop cannot be in the same packet with another memop or a store. 13120b57cec5SDimitry Andric // Two stores can be together, but here I and J cannot both be stores. 13130b57cec5SDimitry Andric bool MopStI = HII->isMemOp(I) || StoreI; 13140b57cec5SDimitry Andric bool MopStJ = HII->isMemOp(J) || StoreJ; 13150b57cec5SDimitry Andric if (MopStI && MopStJ) 13160b57cec5SDimitry Andric return true; 13170b57cec5SDimitry Andric } 13180b57cec5SDimitry Andric 13190b57cec5SDimitry Andric return (StoreJ && HII->isDeallocRet(I)) || (StoreI && HII->isDeallocRet(J)); 13200b57cec5SDimitry Andric } 13210b57cec5SDimitry Andric 13220b57cec5SDimitry Andric // SUI is the current instruction that is outside of the current packet. 13230b57cec5SDimitry Andric // SUJ is the current instruction inside the current packet against which that 13240b57cec5SDimitry Andric // SUI will be packetized. 13250b57cec5SDimitry Andric bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { 13260b57cec5SDimitry Andric assert(SUI->getInstr() && SUJ->getInstr()); 13270b57cec5SDimitry Andric MachineInstr &I = *SUI->getInstr(); 13280b57cec5SDimitry Andric MachineInstr &J = *SUJ->getInstr(); 13290b57cec5SDimitry Andric 13300b57cec5SDimitry Andric // Clear IgnoreDepMIs when Packet starts. 13310b57cec5SDimitry Andric if (CurrentPacketMIs.size() == 1) 13320b57cec5SDimitry Andric IgnoreDepMIs.clear(); 13330b57cec5SDimitry Andric 13340b57cec5SDimitry Andric MachineBasicBlock::iterator II = I.getIterator(); 13350b57cec5SDimitry Andric 13360b57cec5SDimitry Andric // Solo instructions cannot go in the packet. 13370b57cec5SDimitry Andric assert(!isSoloInstruction(I) && "Unexpected solo instr!"); 13380b57cec5SDimitry Andric 13390b57cec5SDimitry Andric if (cannotCoexist(I, J)) 13400b57cec5SDimitry Andric return false; 13410b57cec5SDimitry Andric 13420b57cec5SDimitry Andric Dependence = hasDeadDependence(I, J) || hasControlDependence(I, J); 13430b57cec5SDimitry Andric if (Dependence) 13440b57cec5SDimitry Andric return false; 13450b57cec5SDimitry Andric 13460b57cec5SDimitry Andric // Regmasks are not accounted for in the scheduling graph, so we need 13470b57cec5SDimitry Andric // to explicitly check for dependencies caused by them. They should only 13480b57cec5SDimitry Andric // appear on calls, so it's not too pessimistic to reject all regmask 13490b57cec5SDimitry Andric // dependencies. 13500b57cec5SDimitry Andric Dependence = hasRegMaskDependence(I, J); 13510b57cec5SDimitry Andric if (Dependence) 13520b57cec5SDimitry Andric return false; 13530b57cec5SDimitry Andric 13540b57cec5SDimitry Andric // Dual-store does not allow second store, if the first store is not 13550b57cec5SDimitry Andric // in SLOT0. New value store, new value jump, dealloc_return and memop 13560b57cec5SDimitry Andric // always take SLOT0. Arch spec 3.4.4.2. 13570b57cec5SDimitry Andric Dependence = hasDualStoreDependence(I, J); 13580b57cec5SDimitry Andric if (Dependence) 13590b57cec5SDimitry Andric return false; 13600b57cec5SDimitry Andric 13610b57cec5SDimitry Andric // If an instruction feeds new value jump, glue it. 13620b57cec5SDimitry Andric MachineBasicBlock::iterator NextMII = I.getIterator(); 13630b57cec5SDimitry Andric ++NextMII; 13640b57cec5SDimitry Andric if (NextMII != I.getParent()->end() && HII->isNewValueJump(*NextMII)) { 13650b57cec5SDimitry Andric MachineInstr &NextMI = *NextMII; 13660b57cec5SDimitry Andric 13670b57cec5SDimitry Andric bool secondRegMatch = false; 13680b57cec5SDimitry Andric const MachineOperand &NOp0 = NextMI.getOperand(0); 13690b57cec5SDimitry Andric const MachineOperand &NOp1 = NextMI.getOperand(1); 13700b57cec5SDimitry Andric 13710b57cec5SDimitry Andric if (NOp1.isReg() && I.getOperand(0).getReg() == NOp1.getReg()) 13720b57cec5SDimitry Andric secondRegMatch = true; 13730b57cec5SDimitry Andric 13740b57cec5SDimitry Andric for (MachineInstr *PI : CurrentPacketMIs) { 13750b57cec5SDimitry Andric // NVJ can not be part of the dual jump - Arch Spec: section 7.8. 13760b57cec5SDimitry Andric if (PI->isCall()) { 13770b57cec5SDimitry Andric Dependence = true; 13780b57cec5SDimitry Andric break; 13790b57cec5SDimitry Andric } 13800b57cec5SDimitry Andric // Validate: 13810b57cec5SDimitry Andric // 1. Packet does not have a store in it. 13820b57cec5SDimitry Andric // 2. If the first operand of the nvj is newified, and the second 13830b57cec5SDimitry Andric // operand is also a reg, it (second reg) is not defined in 13840b57cec5SDimitry Andric // the same packet. 13850b57cec5SDimitry Andric // 3. If the second operand of the nvj is newified, (which means 13860b57cec5SDimitry Andric // first operand is also a reg), first reg is not defined in 13870b57cec5SDimitry Andric // the same packet. 13880b57cec5SDimitry Andric if (PI->getOpcode() == Hexagon::S2_allocframe || PI->mayStore() || 13890b57cec5SDimitry Andric HII->isLoopN(*PI)) { 13900b57cec5SDimitry Andric Dependence = true; 13910b57cec5SDimitry Andric break; 13920b57cec5SDimitry Andric } 13930b57cec5SDimitry Andric // Check #2/#3. 13940b57cec5SDimitry Andric const MachineOperand &OpR = secondRegMatch ? NOp0 : NOp1; 13950b57cec5SDimitry Andric if (OpR.isReg() && PI->modifiesRegister(OpR.getReg(), HRI)) { 13960b57cec5SDimitry Andric Dependence = true; 13970b57cec5SDimitry Andric break; 13980b57cec5SDimitry Andric } 13990b57cec5SDimitry Andric } 14000b57cec5SDimitry Andric 14010b57cec5SDimitry Andric GlueToNewValueJump = true; 14020b57cec5SDimitry Andric if (Dependence) 14030b57cec5SDimitry Andric return false; 14040b57cec5SDimitry Andric } 14050b57cec5SDimitry Andric 14060b57cec5SDimitry Andric // There no dependency between a prolog instruction and its successor. 14070b57cec5SDimitry Andric if (!SUJ->isSucc(SUI)) 14080b57cec5SDimitry Andric return true; 14090b57cec5SDimitry Andric 14100b57cec5SDimitry Andric for (unsigned i = 0; i < SUJ->Succs.size(); ++i) { 14110b57cec5SDimitry Andric if (FoundSequentialDependence) 14120b57cec5SDimitry Andric break; 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric if (SUJ->Succs[i].getSUnit() != SUI) 14150b57cec5SDimitry Andric continue; 14160b57cec5SDimitry Andric 14170b57cec5SDimitry Andric SDep::Kind DepType = SUJ->Succs[i].getKind(); 14180b57cec5SDimitry Andric // For direct calls: 14190b57cec5SDimitry Andric // Ignore register dependences for call instructions for packetization 14200b57cec5SDimitry Andric // purposes except for those due to r31 and predicate registers. 14210b57cec5SDimitry Andric // 14220b57cec5SDimitry Andric // For indirect calls: 14230b57cec5SDimitry Andric // Same as direct calls + check for true dependences to the register 14240b57cec5SDimitry Andric // used in the indirect call. 14250b57cec5SDimitry Andric // 14260b57cec5SDimitry Andric // We completely ignore Order dependences for call instructions. 14270b57cec5SDimitry Andric // 14280b57cec5SDimitry Andric // For returns: 14290b57cec5SDimitry Andric // Ignore register dependences for return instructions like jumpr, 14300b57cec5SDimitry Andric // dealloc return unless we have dependencies on the explicit uses 14310b57cec5SDimitry Andric // of the registers used by jumpr (like r31) or dealloc return 14320b57cec5SDimitry Andric // (like r29 or r30). 14330b57cec5SDimitry Andric unsigned DepReg = 0; 14340b57cec5SDimitry Andric const TargetRegisterClass *RC = nullptr; 14350b57cec5SDimitry Andric if (DepType == SDep::Data) { 14360b57cec5SDimitry Andric DepReg = SUJ->Succs[i].getReg(); 14370b57cec5SDimitry Andric RC = HRI->getMinimalPhysRegClass(DepReg); 14380b57cec5SDimitry Andric } 14390b57cec5SDimitry Andric 14400b57cec5SDimitry Andric if (I.isCall() || HII->isJumpR(I) || I.isReturn() || HII->isTailCall(I)) { 14410b57cec5SDimitry Andric if (!isRegDependence(DepType)) 14420b57cec5SDimitry Andric continue; 14430b57cec5SDimitry Andric if (!isCallDependent(I, DepType, SUJ->Succs[i].getReg())) 14440b57cec5SDimitry Andric continue; 14450b57cec5SDimitry Andric } 14460b57cec5SDimitry Andric 14470b57cec5SDimitry Andric if (DepType == SDep::Data) { 14480b57cec5SDimitry Andric if (canPromoteToDotCur(J, SUJ, DepReg, II, RC)) 14490b57cec5SDimitry Andric if (promoteToDotCur(J, DepType, II, RC)) 14500b57cec5SDimitry Andric continue; 14510b57cec5SDimitry Andric } 14520b57cec5SDimitry Andric 14530b57cec5SDimitry Andric // Data dpendence ok if we have load.cur. 14540b57cec5SDimitry Andric if (DepType == SDep::Data && HII->isDotCurInst(J)) { 14550b57cec5SDimitry Andric if (HII->isHVXVec(I)) 14560b57cec5SDimitry Andric continue; 14570b57cec5SDimitry Andric } 14580b57cec5SDimitry Andric 14590b57cec5SDimitry Andric // For instructions that can be promoted to dot-new, try to promote. 14600b57cec5SDimitry Andric if (DepType == SDep::Data) { 14610b57cec5SDimitry Andric if (canPromoteToDotNew(I, SUJ, DepReg, II, RC)) { 14620b57cec5SDimitry Andric if (promoteToDotNew(I, DepType, II, RC)) { 14630b57cec5SDimitry Andric PromotedToDotNew = true; 14640b57cec5SDimitry Andric if (cannotCoexist(I, J)) 14650b57cec5SDimitry Andric FoundSequentialDependence = true; 14660b57cec5SDimitry Andric continue; 14670b57cec5SDimitry Andric } 14680b57cec5SDimitry Andric } 14690b57cec5SDimitry Andric if (HII->isNewValueJump(I)) 14700b57cec5SDimitry Andric continue; 14710b57cec5SDimitry Andric } 14720b57cec5SDimitry Andric 14730b57cec5SDimitry Andric // For predicated instructions, if the predicates are complements then 14740b57cec5SDimitry Andric // there can be no dependence. 14750b57cec5SDimitry Andric if (HII->isPredicated(I) && HII->isPredicated(J) && 14760b57cec5SDimitry Andric arePredicatesComplements(I, J)) { 14770b57cec5SDimitry Andric // Not always safe to do this translation. 14780b57cec5SDimitry Andric // DAG Builder attempts to reduce dependence edges using transitive 14790b57cec5SDimitry Andric // nature of dependencies. Here is an example: 14800b57cec5SDimitry Andric // 14810b57cec5SDimitry Andric // r0 = tfr_pt ... (1) 14820b57cec5SDimitry Andric // r0 = tfr_pf ... (2) 14830b57cec5SDimitry Andric // r0 = tfr_pt ... (3) 14840b57cec5SDimitry Andric // 14850b57cec5SDimitry Andric // There will be an output dependence between (1)->(2) and (2)->(3). 14860b57cec5SDimitry Andric // However, there is no dependence edge between (1)->(3). This results 14870b57cec5SDimitry Andric // in all 3 instructions going in the same packet. We ignore dependce 14880b57cec5SDimitry Andric // only once to avoid this situation. 14890b57cec5SDimitry Andric auto Itr = find(IgnoreDepMIs, &J); 14900b57cec5SDimitry Andric if (Itr != IgnoreDepMIs.end()) { 14910b57cec5SDimitry Andric Dependence = true; 14920b57cec5SDimitry Andric return false; 14930b57cec5SDimitry Andric } 14940b57cec5SDimitry Andric IgnoreDepMIs.push_back(&I); 14950b57cec5SDimitry Andric continue; 14960b57cec5SDimitry Andric } 14970b57cec5SDimitry Andric 14980b57cec5SDimitry Andric // Ignore Order dependences between unconditional direct branches 14990b57cec5SDimitry Andric // and non-control-flow instructions. 15000b57cec5SDimitry Andric if (isDirectJump(I) && !J.isBranch() && !J.isCall() && 15010b57cec5SDimitry Andric DepType == SDep::Order) 15020b57cec5SDimitry Andric continue; 15030b57cec5SDimitry Andric 15040b57cec5SDimitry Andric // Ignore all dependences for jumps except for true and output 15050b57cec5SDimitry Andric // dependences. 15060b57cec5SDimitry Andric if (I.isConditionalBranch() && DepType != SDep::Data && 15070b57cec5SDimitry Andric DepType != SDep::Output) 15080b57cec5SDimitry Andric continue; 15090b57cec5SDimitry Andric 15100b57cec5SDimitry Andric if (DepType == SDep::Output) { 15110b57cec5SDimitry Andric FoundSequentialDependence = true; 15120b57cec5SDimitry Andric break; 15130b57cec5SDimitry Andric } 15140b57cec5SDimitry Andric 15150b57cec5SDimitry Andric // For Order dependences: 15160b57cec5SDimitry Andric // 1. Volatile loads/stores can be packetized together, unless other 15170b57cec5SDimitry Andric // rules prevent is. 15180b57cec5SDimitry Andric // 2. Store followed by a load is not allowed. 15190b57cec5SDimitry Andric // 3. Store followed by a store is valid. 15200b57cec5SDimitry Andric // 4. Load followed by any memory operation is allowed. 15210b57cec5SDimitry Andric if (DepType == SDep::Order) { 15220b57cec5SDimitry Andric if (!PacketizeVolatiles) { 15230b57cec5SDimitry Andric bool OrdRefs = I.hasOrderedMemoryRef() || J.hasOrderedMemoryRef(); 15240b57cec5SDimitry Andric if (OrdRefs) { 15250b57cec5SDimitry Andric FoundSequentialDependence = true; 15260b57cec5SDimitry Andric break; 15270b57cec5SDimitry Andric } 15280b57cec5SDimitry Andric } 15290b57cec5SDimitry Andric // J is first, I is second. 15300b57cec5SDimitry Andric bool LoadJ = J.mayLoad(), StoreJ = J.mayStore(); 15310b57cec5SDimitry Andric bool LoadI = I.mayLoad(), StoreI = I.mayStore(); 15320b57cec5SDimitry Andric bool NVStoreJ = HII->isNewValueStore(J); 15330b57cec5SDimitry Andric bool NVStoreI = HII->isNewValueStore(I); 15340b57cec5SDimitry Andric bool IsVecJ = HII->isHVXVec(J); 15350b57cec5SDimitry Andric bool IsVecI = HII->isHVXVec(I); 15360b57cec5SDimitry Andric 153704eeddc0SDimitry Andric // Don't reorder the loads if there is an order dependence. This would 153804eeddc0SDimitry Andric // occur if the first instruction must go in slot0. 153904eeddc0SDimitry Andric if (LoadJ && LoadI && HII->isPureSlot0(J)) { 154004eeddc0SDimitry Andric FoundSequentialDependence = true; 154104eeddc0SDimitry Andric break; 154204eeddc0SDimitry Andric } 154304eeddc0SDimitry Andric 15440b57cec5SDimitry Andric if (Slot1Store && MF.getSubtarget<HexagonSubtarget>().hasV65Ops() && 15450b57cec5SDimitry Andric ((LoadJ && StoreI && !NVStoreI) || 15460b57cec5SDimitry Andric (StoreJ && LoadI && !NVStoreJ)) && 15470b57cec5SDimitry Andric (J.getOpcode() != Hexagon::S2_allocframe && 15480b57cec5SDimitry Andric I.getOpcode() != Hexagon::S2_allocframe) && 15490b57cec5SDimitry Andric (J.getOpcode() != Hexagon::L2_deallocframe && 15500b57cec5SDimitry Andric I.getOpcode() != Hexagon::L2_deallocframe) && 15510b57cec5SDimitry Andric (!HII->isMemOp(J) && !HII->isMemOp(I)) && (!IsVecJ && !IsVecI)) 15520b57cec5SDimitry Andric setmemShufDisabled(true); 15530b57cec5SDimitry Andric else 15540b57cec5SDimitry Andric if (StoreJ && LoadI && alias(J, I)) { 15550b57cec5SDimitry Andric FoundSequentialDependence = true; 15560b57cec5SDimitry Andric break; 15570b57cec5SDimitry Andric } 15580b57cec5SDimitry Andric 15590b57cec5SDimitry Andric if (!StoreJ) 15600b57cec5SDimitry Andric if (!LoadJ || (!LoadI && !StoreI)) { 15610b57cec5SDimitry Andric // If J is neither load nor store, assume a dependency. 15620b57cec5SDimitry Andric // If J is a load, but I is neither, also assume a dependency. 15630b57cec5SDimitry Andric FoundSequentialDependence = true; 15640b57cec5SDimitry Andric break; 15650b57cec5SDimitry Andric } 15660b57cec5SDimitry Andric // Store followed by store: not OK on V2. 15670b57cec5SDimitry Andric // Store followed by load: not OK on all. 15680b57cec5SDimitry Andric // Load followed by store: OK on all. 15690b57cec5SDimitry Andric // Load followed by load: OK on all. 15700b57cec5SDimitry Andric continue; 15710b57cec5SDimitry Andric } 15720b57cec5SDimitry Andric 15730b57cec5SDimitry Andric // Special case for ALLOCFRAME: even though there is dependency 15740b57cec5SDimitry Andric // between ALLOCFRAME and subsequent store, allow it to be packetized 15750b57cec5SDimitry Andric // in a same packet. This implies that the store is using the caller's 15760b57cec5SDimitry Andric // SP. Hence, offset needs to be updated accordingly. 15770b57cec5SDimitry Andric if (DepType == SDep::Data && J.getOpcode() == Hexagon::S2_allocframe) { 15780b57cec5SDimitry Andric unsigned Opc = I.getOpcode(); 15790b57cec5SDimitry Andric switch (Opc) { 15800b57cec5SDimitry Andric case Hexagon::S2_storerd_io: 15810b57cec5SDimitry Andric case Hexagon::S2_storeri_io: 15820b57cec5SDimitry Andric case Hexagon::S2_storerh_io: 15830b57cec5SDimitry Andric case Hexagon::S2_storerb_io: 15840b57cec5SDimitry Andric if (I.getOperand(0).getReg() == HRI->getStackRegister()) { 15850b57cec5SDimitry Andric // Since this store is to be glued with allocframe in the same 15860b57cec5SDimitry Andric // packet, it will use SP of the previous stack frame, i.e. 15870b57cec5SDimitry Andric // caller's SP. Therefore, we need to recalculate offset 15880b57cec5SDimitry Andric // according to this change. 15890b57cec5SDimitry Andric GlueAllocframeStore = useCallersSP(I); 15900b57cec5SDimitry Andric if (GlueAllocframeStore) 15910b57cec5SDimitry Andric continue; 15920b57cec5SDimitry Andric } 15930b57cec5SDimitry Andric break; 15940b57cec5SDimitry Andric default: 15950b57cec5SDimitry Andric break; 15960b57cec5SDimitry Andric } 15970b57cec5SDimitry Andric } 15980b57cec5SDimitry Andric 15990b57cec5SDimitry Andric // There are certain anti-dependencies that cannot be ignored. 16000b57cec5SDimitry Andric // Specifically: 16010b57cec5SDimitry Andric // J2_call ... implicit-def %r0 ; SUJ 16020b57cec5SDimitry Andric // R0 = ... ; SUI 16030b57cec5SDimitry Andric // Those cannot be packetized together, since the call will observe 16040b57cec5SDimitry Andric // the effect of the assignment to R0. 16050b57cec5SDimitry Andric if ((DepType == SDep::Anti || DepType == SDep::Output) && J.isCall()) { 16060b57cec5SDimitry Andric // Check if I defines any volatile register. We should also check 16070b57cec5SDimitry Andric // registers that the call may read, but these happen to be a 16080b57cec5SDimitry Andric // subset of the volatile register set. 16090b57cec5SDimitry Andric for (const MachineOperand &Op : I.operands()) { 16100b57cec5SDimitry Andric if (Op.isReg() && Op.isDef()) { 16118bcb0991SDimitry Andric Register R = Op.getReg(); 16120b57cec5SDimitry Andric if (!J.readsRegister(R, HRI) && !J.modifiesRegister(R, HRI)) 16130b57cec5SDimitry Andric continue; 16140b57cec5SDimitry Andric } else if (!Op.isRegMask()) { 16150b57cec5SDimitry Andric // If I has a regmask assume dependency. 16160b57cec5SDimitry Andric continue; 16170b57cec5SDimitry Andric } 16180b57cec5SDimitry Andric FoundSequentialDependence = true; 16190b57cec5SDimitry Andric break; 16200b57cec5SDimitry Andric } 16210b57cec5SDimitry Andric } 16220b57cec5SDimitry Andric 16230b57cec5SDimitry Andric // Skip over remaining anti-dependences. Two instructions that are 16240b57cec5SDimitry Andric // anti-dependent can share a packet, since in most such cases all 16250b57cec5SDimitry Andric // operands are read before any modifications take place. 16260b57cec5SDimitry Andric // The exceptions are branch and call instructions, since they are 16270b57cec5SDimitry Andric // executed after all other instructions have completed (at least 16280b57cec5SDimitry Andric // conceptually). 16290b57cec5SDimitry Andric if (DepType != SDep::Anti) { 16300b57cec5SDimitry Andric FoundSequentialDependence = true; 16310b57cec5SDimitry Andric break; 16320b57cec5SDimitry Andric } 16330b57cec5SDimitry Andric } 16340b57cec5SDimitry Andric 16350b57cec5SDimitry Andric if (FoundSequentialDependence) { 16360b57cec5SDimitry Andric Dependence = true; 16370b57cec5SDimitry Andric return false; 16380b57cec5SDimitry Andric } 16390b57cec5SDimitry Andric 16400b57cec5SDimitry Andric return true; 16410b57cec5SDimitry Andric } 16420b57cec5SDimitry Andric 16430b57cec5SDimitry Andric bool HexagonPacketizerList::isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) { 16440b57cec5SDimitry Andric assert(SUI->getInstr() && SUJ->getInstr()); 16450b57cec5SDimitry Andric MachineInstr &I = *SUI->getInstr(); 16460b57cec5SDimitry Andric MachineInstr &J = *SUJ->getInstr(); 16470b57cec5SDimitry Andric 16480b57cec5SDimitry Andric bool Coexist = !cannotCoexist(I, J); 16490b57cec5SDimitry Andric 16500b57cec5SDimitry Andric if (Coexist && !Dependence) 16510b57cec5SDimitry Andric return true; 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric // Check if the instruction was promoted to a dot-new. If so, demote it 16540b57cec5SDimitry Andric // back into a dot-old. 16550b57cec5SDimitry Andric if (PromotedToDotNew) 16560b57cec5SDimitry Andric demoteToDotOld(I); 16570b57cec5SDimitry Andric 16580b57cec5SDimitry Andric cleanUpDotCur(); 16590b57cec5SDimitry Andric // Check if the instruction (must be a store) was glued with an allocframe 16600b57cec5SDimitry Andric // instruction. If so, restore its offset to its original value, i.e. use 16610b57cec5SDimitry Andric // current SP instead of caller's SP. 16620b57cec5SDimitry Andric if (GlueAllocframeStore) { 16630b57cec5SDimitry Andric useCalleesSP(I); 16640b57cec5SDimitry Andric GlueAllocframeStore = false; 16650b57cec5SDimitry Andric } 16660b57cec5SDimitry Andric 16670b57cec5SDimitry Andric if (ChangedOffset != INT64_MAX) 16680b57cec5SDimitry Andric undoChangedOffset(I); 16690b57cec5SDimitry Andric 16700b57cec5SDimitry Andric if (GlueToNewValueJump) { 16710b57cec5SDimitry Andric // Putting I and J together would prevent the new-value jump from being 16720b57cec5SDimitry Andric // packetized with the producer. In that case I and J must be separated. 16730b57cec5SDimitry Andric GlueToNewValueJump = false; 16740b57cec5SDimitry Andric return false; 16750b57cec5SDimitry Andric } 16760b57cec5SDimitry Andric 16770b57cec5SDimitry Andric if (!Coexist) 16780b57cec5SDimitry Andric return false; 16790b57cec5SDimitry Andric 16800b57cec5SDimitry Andric if (ChangedOffset == INT64_MAX && updateOffset(SUI, SUJ)) { 16810b57cec5SDimitry Andric FoundSequentialDependence = false; 16820b57cec5SDimitry Andric Dependence = false; 16830b57cec5SDimitry Andric return true; 16840b57cec5SDimitry Andric } 16850b57cec5SDimitry Andric 16860b57cec5SDimitry Andric return false; 16870b57cec5SDimitry Andric } 16880b57cec5SDimitry Andric 16890b57cec5SDimitry Andric 16900b57cec5SDimitry Andric bool HexagonPacketizerList::foundLSInPacket() { 16910b57cec5SDimitry Andric bool FoundLoad = false; 16920b57cec5SDimitry Andric bool FoundStore = false; 16930b57cec5SDimitry Andric 1694bdd1243dSDimitry Andric for (auto *MJ : CurrentPacketMIs) { 16950b57cec5SDimitry Andric unsigned Opc = MJ->getOpcode(); 16960b57cec5SDimitry Andric if (Opc == Hexagon::S2_allocframe || Opc == Hexagon::L2_deallocframe) 16970b57cec5SDimitry Andric continue; 16980b57cec5SDimitry Andric if (HII->isMemOp(*MJ)) 16990b57cec5SDimitry Andric continue; 17000b57cec5SDimitry Andric if (MJ->mayLoad()) 17010b57cec5SDimitry Andric FoundLoad = true; 17020b57cec5SDimitry Andric if (MJ->mayStore() && !HII->isNewValueStore(*MJ)) 17030b57cec5SDimitry Andric FoundStore = true; 17040b57cec5SDimitry Andric } 17050b57cec5SDimitry Andric return FoundLoad && FoundStore; 17060b57cec5SDimitry Andric } 17070b57cec5SDimitry Andric 17080b57cec5SDimitry Andric 17090b57cec5SDimitry Andric MachineBasicBlock::iterator 17100b57cec5SDimitry Andric HexagonPacketizerList::addToPacket(MachineInstr &MI) { 17110b57cec5SDimitry Andric MachineBasicBlock::iterator MII = MI.getIterator(); 17120b57cec5SDimitry Andric MachineBasicBlock *MBB = MI.getParent(); 17130b57cec5SDimitry Andric 171404eeddc0SDimitry Andric if (CurrentPacketMIs.empty()) { 17150b57cec5SDimitry Andric PacketStalls = false; 171604eeddc0SDimitry Andric PacketStallCycles = 0; 171704eeddc0SDimitry Andric } 17180b57cec5SDimitry Andric PacketStalls |= producesStall(MI); 171904eeddc0SDimitry Andric PacketStallCycles = std::max(PacketStallCycles, calcStall(MI)); 17200b57cec5SDimitry Andric 17210b57cec5SDimitry Andric if (MI.isImplicitDef()) { 17220b57cec5SDimitry Andric // Add to the packet to allow subsequent instructions to be checked 17230b57cec5SDimitry Andric // properly. 17240b57cec5SDimitry Andric CurrentPacketMIs.push_back(&MI); 17250b57cec5SDimitry Andric return MII; 17260b57cec5SDimitry Andric } 17270b57cec5SDimitry Andric assert(ResourceTracker->canReserveResources(MI)); 17280b57cec5SDimitry Andric 17290b57cec5SDimitry Andric bool ExtMI = HII->isExtended(MI) || HII->isConstExtended(MI); 17300b57cec5SDimitry Andric bool Good = true; 17310b57cec5SDimitry Andric 17320b57cec5SDimitry Andric if (GlueToNewValueJump) { 17330b57cec5SDimitry Andric MachineInstr &NvjMI = *++MII; 17340b57cec5SDimitry Andric // We need to put both instructions in the same packet: MI and NvjMI. 17350b57cec5SDimitry Andric // Either of them can require a constant extender. Try to add both to 17360b57cec5SDimitry Andric // the current packet, and if that fails, end the packet and start a 17370b57cec5SDimitry Andric // new one. 17380b57cec5SDimitry Andric ResourceTracker->reserveResources(MI); 17390b57cec5SDimitry Andric if (ExtMI) 17400b57cec5SDimitry Andric Good = tryAllocateResourcesForConstExt(true); 17410b57cec5SDimitry Andric 17420b57cec5SDimitry Andric bool ExtNvjMI = HII->isExtended(NvjMI) || HII->isConstExtended(NvjMI); 17430b57cec5SDimitry Andric if (Good) { 17440b57cec5SDimitry Andric if (ResourceTracker->canReserveResources(NvjMI)) 17450b57cec5SDimitry Andric ResourceTracker->reserveResources(NvjMI); 17460b57cec5SDimitry Andric else 17470b57cec5SDimitry Andric Good = false; 17480b57cec5SDimitry Andric } 17490b57cec5SDimitry Andric if (Good && ExtNvjMI) 17500b57cec5SDimitry Andric Good = tryAllocateResourcesForConstExt(true); 17510b57cec5SDimitry Andric 17520b57cec5SDimitry Andric if (!Good) { 17530b57cec5SDimitry Andric endPacket(MBB, MI); 17540b57cec5SDimitry Andric assert(ResourceTracker->canReserveResources(MI)); 17550b57cec5SDimitry Andric ResourceTracker->reserveResources(MI); 17560b57cec5SDimitry Andric if (ExtMI) { 17570b57cec5SDimitry Andric assert(canReserveResourcesForConstExt()); 17580b57cec5SDimitry Andric tryAllocateResourcesForConstExt(true); 17590b57cec5SDimitry Andric } 17600b57cec5SDimitry Andric assert(ResourceTracker->canReserveResources(NvjMI)); 17610b57cec5SDimitry Andric ResourceTracker->reserveResources(NvjMI); 17620b57cec5SDimitry Andric if (ExtNvjMI) { 17630b57cec5SDimitry Andric assert(canReserveResourcesForConstExt()); 17640b57cec5SDimitry Andric reserveResourcesForConstExt(); 17650b57cec5SDimitry Andric } 17660b57cec5SDimitry Andric } 17670b57cec5SDimitry Andric CurrentPacketMIs.push_back(&MI); 17680b57cec5SDimitry Andric CurrentPacketMIs.push_back(&NvjMI); 17690b57cec5SDimitry Andric return MII; 17700b57cec5SDimitry Andric } 17710b57cec5SDimitry Andric 17720b57cec5SDimitry Andric ResourceTracker->reserveResources(MI); 17730b57cec5SDimitry Andric if (ExtMI && !tryAllocateResourcesForConstExt(true)) { 17740b57cec5SDimitry Andric endPacket(MBB, MI); 17750b57cec5SDimitry Andric if (PromotedToDotNew) 17760b57cec5SDimitry Andric demoteToDotOld(MI); 17770b57cec5SDimitry Andric if (GlueAllocframeStore) { 17780b57cec5SDimitry Andric useCalleesSP(MI); 17790b57cec5SDimitry Andric GlueAllocframeStore = false; 17800b57cec5SDimitry Andric } 17810b57cec5SDimitry Andric ResourceTracker->reserveResources(MI); 17820b57cec5SDimitry Andric reserveResourcesForConstExt(); 17830b57cec5SDimitry Andric } 17840b57cec5SDimitry Andric 17850b57cec5SDimitry Andric CurrentPacketMIs.push_back(&MI); 17860b57cec5SDimitry Andric return MII; 17870b57cec5SDimitry Andric } 17880b57cec5SDimitry Andric 17890b57cec5SDimitry Andric void HexagonPacketizerList::endPacket(MachineBasicBlock *MBB, 17900b57cec5SDimitry Andric MachineBasicBlock::iterator EndMI) { 17910b57cec5SDimitry Andric // Replace VLIWPacketizerList::endPacket(MBB, EndMI). 17928bcb0991SDimitry Andric LLVM_DEBUG({ 17938bcb0991SDimitry Andric if (!CurrentPacketMIs.empty()) { 17948bcb0991SDimitry Andric dbgs() << "Finalizing packet:\n"; 17958bcb0991SDimitry Andric unsigned Idx = 0; 17968bcb0991SDimitry Andric for (MachineInstr *MI : CurrentPacketMIs) { 17978bcb0991SDimitry Andric unsigned R = ResourceTracker->getUsedResources(Idx++); 17988bcb0991SDimitry Andric dbgs() << " * [res:0x" << utohexstr(R) << "] " << *MI; 17998bcb0991SDimitry Andric } 18008bcb0991SDimitry Andric } 18018bcb0991SDimitry Andric }); 18020b57cec5SDimitry Andric 18030b57cec5SDimitry Andric bool memShufDisabled = getmemShufDisabled(); 18040b57cec5SDimitry Andric if (memShufDisabled && !foundLSInPacket()) { 18050b57cec5SDimitry Andric setmemShufDisabled(false); 18060b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " Not added to NoShufPacket\n"); 18070b57cec5SDimitry Andric } 18080b57cec5SDimitry Andric memShufDisabled = getmemShufDisabled(); 18090b57cec5SDimitry Andric 18100b57cec5SDimitry Andric OldPacketMIs.clear(); 18110b57cec5SDimitry Andric for (MachineInstr *MI : CurrentPacketMIs) { 18120b57cec5SDimitry Andric MachineBasicBlock::instr_iterator NextMI = std::next(MI->getIterator()); 18130b57cec5SDimitry Andric for (auto &I : make_range(HII->expandVGatherPseudo(*MI), NextMI)) 18140b57cec5SDimitry Andric OldPacketMIs.push_back(&I); 18150b57cec5SDimitry Andric } 18160b57cec5SDimitry Andric CurrentPacketMIs.clear(); 18170b57cec5SDimitry Andric 18180b57cec5SDimitry Andric if (OldPacketMIs.size() > 1) { 18190b57cec5SDimitry Andric MachineBasicBlock::instr_iterator FirstMI(OldPacketMIs.front()); 18200b57cec5SDimitry Andric MachineBasicBlock::instr_iterator LastMI(EndMI.getInstrIterator()); 18210b57cec5SDimitry Andric finalizeBundle(*MBB, FirstMI, LastMI); 18220b57cec5SDimitry Andric auto BundleMII = std::prev(FirstMI); 18230b57cec5SDimitry Andric if (memShufDisabled) 18240b57cec5SDimitry Andric HII->setBundleNoShuf(BundleMII); 18250b57cec5SDimitry Andric 18260b57cec5SDimitry Andric setmemShufDisabled(false); 18270b57cec5SDimitry Andric } 18280b57cec5SDimitry Andric 18295ffd83dbSDimitry Andric PacketHasDuplex = false; 18305ffd83dbSDimitry Andric PacketHasSLOT0OnlyInsn = false; 18310b57cec5SDimitry Andric ResourceTracker->clearResources(); 18320b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "End packet\n"); 18330b57cec5SDimitry Andric } 18340b57cec5SDimitry Andric 18350b57cec5SDimitry Andric bool HexagonPacketizerList::shouldAddToPacket(const MachineInstr &MI) { 18360b57cec5SDimitry Andric if (Minimal) 18370b57cec5SDimitry Andric return false; 18385ffd83dbSDimitry Andric 18395ffd83dbSDimitry Andric if (producesStall(MI)) 18405ffd83dbSDimitry Andric return false; 18415ffd83dbSDimitry Andric 18425ffd83dbSDimitry Andric // If TinyCore with Duplexes is enabled, check if this MI can form a Duplex 18435ffd83dbSDimitry Andric // with any other instruction in the existing packet. 18445ffd83dbSDimitry Andric auto &HST = MI.getParent()->getParent()->getSubtarget<HexagonSubtarget>(); 18455ffd83dbSDimitry Andric // Constraint 1: Only one duplex allowed per packet. 18465ffd83dbSDimitry Andric // Constraint 2: Consider duplex checks only if there is atleast one 18475ffd83dbSDimitry Andric // instruction in a packet. 18485ffd83dbSDimitry Andric // Constraint 3: If one of the existing instructions in the packet has a 18495ffd83dbSDimitry Andric // SLOT0 only instruction that can not be duplexed, do not attempt to form 18505ffd83dbSDimitry Andric // duplexes. (TODO: This will invalidate the L4_return* instructions to form a 18515ffd83dbSDimitry Andric // duplex) 18525ffd83dbSDimitry Andric if (HST.isTinyCoreWithDuplex() && CurrentPacketMIs.size() > 0 && 18535ffd83dbSDimitry Andric !PacketHasDuplex) { 18545ffd83dbSDimitry Andric // Check for SLOT0 only non-duplexable instruction in packet. 18555ffd83dbSDimitry Andric for (auto &MJ : CurrentPacketMIs) 18565ffd83dbSDimitry Andric PacketHasSLOT0OnlyInsn |= HII->isPureSlot0(*MJ); 18575ffd83dbSDimitry Andric // Get the Big Core Opcode (dup_*). 18585ffd83dbSDimitry Andric int Opcode = HII->getDuplexOpcode(MI, false); 18595ffd83dbSDimitry Andric if (Opcode >= 0) { 18605ffd83dbSDimitry Andric // We now have an instruction that can be duplexed. 18615ffd83dbSDimitry Andric for (auto &MJ : CurrentPacketMIs) { 18625ffd83dbSDimitry Andric if (HII->isDuplexPair(MI, *MJ) && !PacketHasSLOT0OnlyInsn) { 18635ffd83dbSDimitry Andric PacketHasDuplex = true; 18645ffd83dbSDimitry Andric return true; 18655ffd83dbSDimitry Andric } 18665ffd83dbSDimitry Andric } 18675ffd83dbSDimitry Andric // If it can not be duplexed, check if there is a valid transition in DFA 18685ffd83dbSDimitry Andric // with the original opcode. 18695ffd83dbSDimitry Andric MachineInstr &MIRef = const_cast<MachineInstr &>(MI); 18705ffd83dbSDimitry Andric MIRef.setDesc(HII->get(Opcode)); 18715ffd83dbSDimitry Andric return ResourceTracker->canReserveResources(MIRef); 18725ffd83dbSDimitry Andric } 18735ffd83dbSDimitry Andric } 18745ffd83dbSDimitry Andric 18755ffd83dbSDimitry Andric return true; 18765ffd83dbSDimitry Andric } 18775ffd83dbSDimitry Andric 18780b57cec5SDimitry Andric // V60 forward scheduling. 187904eeddc0SDimitry Andric unsigned int HexagonPacketizerList::calcStall(const MachineInstr &I) { 18800b57cec5SDimitry Andric // Check whether the previous packet is in a different loop. If this is the 18810b57cec5SDimitry Andric // case, there is little point in trying to avoid a stall because that would 18820b57cec5SDimitry Andric // favor the rare case (loop entry) over the common case (loop iteration). 18830b57cec5SDimitry Andric // 18840b57cec5SDimitry Andric // TODO: We should really be able to check all the incoming edges if this is 18850b57cec5SDimitry Andric // the first packet in a basic block, so we can avoid stalls from the loop 18860b57cec5SDimitry Andric // backedge. 18870b57cec5SDimitry Andric if (!OldPacketMIs.empty()) { 18880b57cec5SDimitry Andric auto *OldBB = OldPacketMIs.front()->getParent(); 18890b57cec5SDimitry Andric auto *ThisBB = I.getParent(); 18900b57cec5SDimitry Andric if (MLI->getLoopFor(OldBB) != MLI->getLoopFor(ThisBB)) 189104eeddc0SDimitry Andric return 0; 18920b57cec5SDimitry Andric } 18930b57cec5SDimitry Andric 18940b57cec5SDimitry Andric SUnit *SUI = MIToSUnit[const_cast<MachineInstr *>(&I)]; 189504eeddc0SDimitry Andric if (!SUI) 189604eeddc0SDimitry Andric return 0; 18970b57cec5SDimitry Andric 18980b57cec5SDimitry Andric // If the latency is 0 and there is a data dependence between this 18990b57cec5SDimitry Andric // instruction and any instruction in the current packet, we disregard any 19000b57cec5SDimitry Andric // potential stalls due to the instructions in the previous packet. Most of 19010b57cec5SDimitry Andric // the instruction pairs that can go together in the same packet have 0 19020b57cec5SDimitry Andric // latency between them. The exceptions are 19030b57cec5SDimitry Andric // 1. NewValueJumps as they're generated much later and the latencies can't 19040b57cec5SDimitry Andric // be changed at that point. 19050b57cec5SDimitry Andric // 2. .cur instructions, if its consumer has a 0 latency successor (such as 19060b57cec5SDimitry Andric // .new). In this case, the latency between .cur and the consumer stays 19070b57cec5SDimitry Andric // non-zero even though we can have both .cur and .new in the same packet. 19080b57cec5SDimitry Andric // Changing the latency to 0 is not an option as it causes software pipeliner 19090b57cec5SDimitry Andric // to not pipeline in some cases. 19100b57cec5SDimitry Andric 19110b57cec5SDimitry Andric // For Example: 19120b57cec5SDimitry Andric // { 19130b57cec5SDimitry Andric // I1: v6.cur = vmem(r0++#1) 19140b57cec5SDimitry Andric // I2: v7 = valign(v6,v4,r2) 19150b57cec5SDimitry Andric // I3: vmem(r5++#1) = v7.new 19160b57cec5SDimitry Andric // } 19170b57cec5SDimitry Andric // Here I2 and I3 has 0 cycle latency, but I1 and I2 has 2. 19180b57cec5SDimitry Andric 1919bdd1243dSDimitry Andric for (auto *J : CurrentPacketMIs) { 19200b57cec5SDimitry Andric SUnit *SUJ = MIToSUnit[J]; 19210b57cec5SDimitry Andric for (auto &Pred : SUI->Preds) 19220b57cec5SDimitry Andric if (Pred.getSUnit() == SUJ) 19230b57cec5SDimitry Andric if ((Pred.getLatency() == 0 && Pred.isAssignedRegDep()) || 19240b57cec5SDimitry Andric HII->isNewValueJump(I) || HII->isToBeScheduledASAP(*J, I)) 192504eeddc0SDimitry Andric return 0; 19260b57cec5SDimitry Andric } 19270b57cec5SDimitry Andric 19280b57cec5SDimitry Andric // Check if the latency is greater than one between this instruction and any 19290b57cec5SDimitry Andric // instruction in the previous packet. 1930bdd1243dSDimitry Andric for (auto *J : OldPacketMIs) { 19310b57cec5SDimitry Andric SUnit *SUJ = MIToSUnit[J]; 19320b57cec5SDimitry Andric for (auto &Pred : SUI->Preds) 19330b57cec5SDimitry Andric if (Pred.getSUnit() == SUJ && Pred.getLatency() > 1) 193404eeddc0SDimitry Andric return Pred.getLatency(); 19350b57cec5SDimitry Andric } 19360b57cec5SDimitry Andric 193704eeddc0SDimitry Andric return 0; 193804eeddc0SDimitry Andric } 193904eeddc0SDimitry Andric 194004eeddc0SDimitry Andric bool HexagonPacketizerList::producesStall(const MachineInstr &I) { 194104eeddc0SDimitry Andric unsigned int Latency = calcStall(I); 194204eeddc0SDimitry Andric if (Latency == 0) 19430b57cec5SDimitry Andric return false; 194404eeddc0SDimitry Andric // Ignore stall unless it stalls more than previous instruction in packet 194504eeddc0SDimitry Andric if (PacketStalls) 194604eeddc0SDimitry Andric return Latency > PacketStallCycles; 194704eeddc0SDimitry Andric return true; 19480b57cec5SDimitry Andric } 19490b57cec5SDimitry Andric 19500b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 19510b57cec5SDimitry Andric // Public Constructor Functions 19520b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 19530b57cec5SDimitry Andric 19540b57cec5SDimitry Andric FunctionPass *llvm::createHexagonPacketizer(bool Minimal) { 19550b57cec5SDimitry Andric return new HexagonPacketizer(Minimal); 19560b57cec5SDimitry Andric } 1957