| File: | llvm/include/llvm/CodeGen/MachineInstrBuilder.h |
| Warning: | line 216, column 5 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | //===- HexagonOptAddrMode.cpp ---------------------------------------------===// | ||||
| 2 | // | ||||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | ||||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
| 6 | // | ||||
| 7 | //===----------------------------------------------------------------------===// | ||||
| 8 | // This implements a Hexagon-specific pass to optimize addressing mode for | ||||
| 9 | // load/store instructions. | ||||
| 10 | //===----------------------------------------------------------------------===// | ||||
| 11 | |||||
| 12 | #include "HexagonInstrInfo.h" | ||||
| 13 | #include "HexagonSubtarget.h" | ||||
| 14 | #include "MCTargetDesc/HexagonBaseInfo.h" | ||||
| 15 | #include "RDFGraph.h" | ||||
| 16 | #include "RDFLiveness.h" | ||||
| 17 | #include "RDFRegisters.h" | ||||
| 18 | #include "llvm/ADT/DenseMap.h" | ||||
| 19 | #include "llvm/ADT/DenseSet.h" | ||||
| 20 | #include "llvm/ADT/StringRef.h" | ||||
| 21 | #include "llvm/CodeGen/MachineBasicBlock.h" | ||||
| 22 | #include "llvm/CodeGen/MachineDominanceFrontier.h" | ||||
| 23 | #include "llvm/CodeGen/MachineDominators.h" | ||||
| 24 | #include "llvm/CodeGen/MachineFunction.h" | ||||
| 25 | #include "llvm/CodeGen/MachineFunctionPass.h" | ||||
| 26 | #include "llvm/CodeGen/MachineInstr.h" | ||||
| 27 | #include "llvm/CodeGen/MachineInstrBuilder.h" | ||||
| 28 | #include "llvm/CodeGen/MachineOperand.h" | ||||
| 29 | #include "llvm/CodeGen/MachineRegisterInfo.h" | ||||
| 30 | #include "llvm/CodeGen/TargetSubtargetInfo.h" | ||||
| 31 | #include "llvm/InitializePasses.h" | ||||
| 32 | #include "llvm/MC/MCInstrDesc.h" | ||||
| 33 | #include "llvm/Pass.h" | ||||
| 34 | #include "llvm/Support/CommandLine.h" | ||||
| 35 | #include "llvm/Support/Debug.h" | ||||
| 36 | #include "llvm/Support/ErrorHandling.h" | ||||
| 37 | #include "llvm/Support/raw_ostream.h" | ||||
| 38 | #include <cassert> | ||||
| 39 | #include <cstdint> | ||||
| 40 | |||||
| 41 | #define DEBUG_TYPE"opt-addr-mode" "opt-addr-mode" | ||||
| 42 | |||||
| 43 | using namespace llvm; | ||||
| 44 | using namespace rdf; | ||||
| 45 | |||||
| 46 | static cl::opt<int> CodeGrowthLimit("hexagon-amode-growth-limit", | ||||
| 47 | cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode " | ||||
| 48 | "optimization")); | ||||
| 49 | |||||
| 50 | namespace llvm { | ||||
| 51 | |||||
| 52 | FunctionPass *createHexagonOptAddrMode(); | ||||
| 53 | void initializeHexagonOptAddrModePass(PassRegistry&); | ||||
| 54 | |||||
| 55 | } // end namespace llvm | ||||
| 56 | |||||
| 57 | namespace { | ||||
| 58 | |||||
| 59 | class HexagonOptAddrMode : public MachineFunctionPass { | ||||
| 60 | public: | ||||
| 61 | static char ID; | ||||
| 62 | |||||
| 63 | HexagonOptAddrMode() : MachineFunctionPass(ID) {} | ||||
| 64 | |||||
| 65 | StringRef getPassName() const override { | ||||
| 66 | return "Optimize addressing mode of load/store"; | ||||
| 67 | } | ||||
| 68 | |||||
| 69 | void getAnalysisUsage(AnalysisUsage &AU) const override { | ||||
| 70 | MachineFunctionPass::getAnalysisUsage(AU); | ||||
| 71 | AU.addRequired<MachineDominatorTree>(); | ||||
| 72 | AU.addRequired<MachineDominanceFrontier>(); | ||||
| 73 | AU.setPreservesAll(); | ||||
| 74 | } | ||||
| 75 | |||||
| 76 | bool runOnMachineFunction(MachineFunction &MF) override; | ||||
| 77 | |||||
| 78 | private: | ||||
| 79 | using MISetType = DenseSet<MachineInstr *>; | ||||
| 80 | using InstrEvalMap = DenseMap<MachineInstr *, bool>; | ||||
| 81 | |||||
| 82 | MachineRegisterInfo *MRI = nullptr; | ||||
| 83 | const HexagonInstrInfo *HII = nullptr; | ||||
| 84 | const HexagonRegisterInfo *HRI = nullptr; | ||||
| 85 | MachineDominatorTree *MDT = nullptr; | ||||
| 86 | DataFlowGraph *DFG = nullptr; | ||||
| 87 | DataFlowGraph::DefStackMap DefM; | ||||
| 88 | Liveness *LV = nullptr; | ||||
| 89 | MISetType Deleted; | ||||
| 90 | |||||
| 91 | bool processBlock(NodeAddr<BlockNode *> BA); | ||||
| 92 | bool xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI, | ||||
| 93 | NodeAddr<UseNode *> UseN, unsigned UseMOnum); | ||||
| 94 | bool processAddUses(NodeAddr<StmtNode *> AddSN, MachineInstr *AddMI, | ||||
| 95 | const NodeList &UNodeList); | ||||
| 96 | bool updateAddUses(MachineInstr *AddMI, MachineInstr *UseMI); | ||||
| 97 | bool analyzeUses(unsigned DefR, const NodeList &UNodeList, | ||||
| 98 | InstrEvalMap &InstrEvalResult, short &SizeInc); | ||||
| 99 | bool hasRepForm(MachineInstr &MI, unsigned TfrDefR); | ||||
| 100 | bool canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, MachineInstr &MI, | ||||
| 101 | const NodeList &UNodeList); | ||||
| 102 | bool isSafeToExtLR(NodeAddr<StmtNode *> SN, MachineInstr *MI, | ||||
| 103 | unsigned LRExtReg, const NodeList &UNodeList); | ||||
| 104 | void getAllRealUses(NodeAddr<StmtNode *> SN, NodeList &UNodeList); | ||||
| 105 | bool allValidCandidates(NodeAddr<StmtNode *> SA, NodeList &UNodeList); | ||||
| 106 | short getBaseWithLongOffset(const MachineInstr &MI) const; | ||||
| 107 | bool changeStore(MachineInstr *OldMI, MachineOperand ImmOp, | ||||
| 108 | unsigned ImmOpNum); | ||||
| 109 | bool changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, unsigned ImmOpNum); | ||||
| 110 | bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI, | ||||
| 111 | const MachineOperand &ImmOp, unsigned ImmOpNum); | ||||
| 112 | bool isValidOffset(MachineInstr *MI, int Offset); | ||||
| 113 | }; | ||||
| 114 | |||||
| 115 | } // end anonymous namespace | ||||
| 116 | |||||
| 117 | char HexagonOptAddrMode::ID = 0; | ||||
| 118 | |||||
| 119 | INITIALIZE_PASS_BEGIN(HexagonOptAddrMode, "amode-opt",static void *initializeHexagonOptAddrModePassOnce(PassRegistry &Registry) { | ||||
| 120 | "Optimize addressing mode", false, false)static void *initializeHexagonOptAddrModePassOnce(PassRegistry &Registry) { | ||||
| 121 | INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)initializeMachineDominatorTreePass(Registry); | ||||
| 122 | INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier)initializeMachineDominanceFrontierPass(Registry); | ||||
| 123 | INITIALIZE_PASS_END(HexagonOptAddrMode, "amode-opt", "Optimize addressing mode",PassInfo *PI = new PassInfo( "Optimize addressing mode", "amode-opt" , &HexagonOptAddrMode::ID, PassInfo::NormalCtor_t(callDefaultCtor <HexagonOptAddrMode>), false, false); Registry.registerPass (*PI, true); return PI; } static llvm::once_flag InitializeHexagonOptAddrModePassFlag ; void llvm::initializeHexagonOptAddrModePass(PassRegistry & Registry) { llvm::call_once(InitializeHexagonOptAddrModePassFlag , initializeHexagonOptAddrModePassOnce, std::ref(Registry)); } | ||||
| 124 | false, false)PassInfo *PI = new PassInfo( "Optimize addressing mode", "amode-opt" , &HexagonOptAddrMode::ID, PassInfo::NormalCtor_t(callDefaultCtor <HexagonOptAddrMode>), false, false); Registry.registerPass (*PI, true); return PI; } static llvm::once_flag InitializeHexagonOptAddrModePassFlag ; void llvm::initializeHexagonOptAddrModePass(PassRegistry & Registry) { llvm::call_once(InitializeHexagonOptAddrModePassFlag , initializeHexagonOptAddrModePassOnce, std::ref(Registry)); } | ||||
| 125 | |||||
| 126 | bool HexagonOptAddrMode::hasRepForm(MachineInstr &MI, unsigned TfrDefR) { | ||||
| 127 | const MCInstrDesc &MID = MI.getDesc(); | ||||
| 128 | |||||
| 129 | if ((!MID.mayStore() && !MID.mayLoad()) || HII->isPredicated(MI)) | ||||
| 130 | return false; | ||||
| 131 | |||||
| 132 | if (MID.mayStore()) { | ||||
| 133 | MachineOperand StOp = MI.getOperand(MI.getNumOperands() - 1); | ||||
| 134 | if (StOp.isReg() && StOp.getReg() == TfrDefR) | ||||
| 135 | return false; | ||||
| 136 | } | ||||
| 137 | |||||
| 138 | if (HII->getAddrMode(MI) == HexagonII::BaseRegOffset) | ||||
| 139 | // Tranform to Absolute plus register offset. | ||||
| 140 | return (HII->changeAddrMode_rr_ur(MI) >= 0); | ||||
| 141 | else if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset) | ||||
| 142 | // Tranform to absolute addressing mode. | ||||
| 143 | return (HII->changeAddrMode_io_abs(MI) >= 0); | ||||
| 144 | |||||
| 145 | return false; | ||||
| 146 | } | ||||
| 147 | |||||
| 148 | // Check if addasl instruction can be removed. This is possible only | ||||
| 149 | // if it's feeding to only load/store instructions with base + register | ||||
| 150 | // offset as these instruction can be tranformed to use 'absolute plus | ||||
| 151 | // shifted register offset'. | ||||
| 152 | // ex: | ||||
| 153 | // Rs = ##foo | ||||
| 154 | // Rx = addasl(Rs, Rt, #2) | ||||
| 155 | // Rd = memw(Rx + #28) | ||||
| 156 | // Above three instructions can be replaced with Rd = memw(Rt<<#2 + ##foo+28) | ||||
| 157 | |||||
| 158 | bool HexagonOptAddrMode::canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, | ||||
| 159 | MachineInstr &MI, | ||||
| 160 | const NodeList &UNodeList) { | ||||
| 161 | // check offset size in addasl. if 'offset > 3' return false | ||||
| 162 | const MachineOperand &OffsetOp = MI.getOperand(3); | ||||
| 163 | if (!OffsetOp.isImm() || OffsetOp.getImm() > 3) | ||||
| 164 | return false; | ||||
| 165 | |||||
| 166 | Register OffsetReg = MI.getOperand(2).getReg(); | ||||
| 167 | RegisterRef OffsetRR; | ||||
| 168 | NodeId OffsetRegRD = 0; | ||||
| 169 | for (NodeAddr<UseNode *> UA : AddAslSN.Addr->members_if(DFG->IsUse, *DFG)) { | ||||
| 170 | RegisterRef RR = UA.Addr->getRegRef(*DFG); | ||||
| 171 | if (OffsetReg == RR.Reg) { | ||||
| 172 | OffsetRR = RR; | ||||
| 173 | OffsetRegRD = UA.Addr->getReachingDef(); | ||||
| 174 | } | ||||
| 175 | } | ||||
| 176 | |||||
| 177 | for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { | ||||
| 178 | NodeAddr<UseNode *> UA = *I; | ||||
| 179 | NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG); | ||||
| 180 | if (UA.Addr->getFlags() & NodeAttrs::PhiRef) | ||||
| 181 | return false; | ||||
| 182 | NodeAddr<RefNode*> AA = LV->getNearestAliasedRef(OffsetRR, IA); | ||||
| 183 | if ((DFG->IsDef(AA) && AA.Id != OffsetRegRD) || | ||||
| 184 | AA.Addr->getReachingDef() != OffsetRegRD) | ||||
| 185 | return false; | ||||
| 186 | |||||
| 187 | MachineInstr &UseMI = *NodeAddr<StmtNode *>(IA).Addr->getCode(); | ||||
| 188 | NodeAddr<DefNode *> OffsetRegDN = DFG->addr<DefNode *>(OffsetRegRD); | ||||
| 189 | // Reaching Def to an offset register can't be a phi. | ||||
| 190 | if ((OffsetRegDN.Addr->getFlags() & NodeAttrs::PhiRef) && | ||||
| 191 | MI.getParent() != UseMI.getParent()) | ||||
| 192 | return false; | ||||
| 193 | |||||
| 194 | const MCInstrDesc &UseMID = UseMI.getDesc(); | ||||
| 195 | if ((!UseMID.mayLoad() && !UseMID.mayStore()) || | ||||
| 196 | HII->getAddrMode(UseMI) != HexagonII::BaseImmOffset || | ||||
| 197 | getBaseWithLongOffset(UseMI) < 0) | ||||
| 198 | return false; | ||||
| 199 | |||||
| 200 | // Addasl output can't be a store value. | ||||
| 201 | if (UseMID.mayStore() && UseMI.getOperand(2).isReg() && | ||||
| 202 | UseMI.getOperand(2).getReg() == MI.getOperand(0).getReg()) | ||||
| 203 | return false; | ||||
| 204 | |||||
| 205 | for (auto &Mo : UseMI.operands()) | ||||
| 206 | if (Mo.isFI()) | ||||
| 207 | return false; | ||||
| 208 | } | ||||
| 209 | return true; | ||||
| 210 | } | ||||
| 211 | |||||
| 212 | bool HexagonOptAddrMode::allValidCandidates(NodeAddr<StmtNode *> SA, | ||||
| 213 | NodeList &UNodeList) { | ||||
| 214 | for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { | ||||
| 215 | NodeAddr<UseNode *> UN = *I; | ||||
| 216 | RegisterRef UR = UN.Addr->getRegRef(*DFG); | ||||
| 217 | NodeSet Visited, Defs; | ||||
| 218 | const auto &P = LV->getAllReachingDefsRec(UR, UN, Visited, Defs); | ||||
| 219 | if (!P.second) { | ||||
| 220 | LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Unable to collect all reaching defs for use ***\n" << PrintNode<UseNode*>(UN, *DFG) << '\n' << "The program's complexity may exceed the limits.\n"; }; } } while (false) | ||||
| 221 | dbgs() << "*** Unable to collect all reaching defs for use ***\n"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Unable to collect all reaching defs for use ***\n" << PrintNode<UseNode*>(UN, *DFG) << '\n' << "The program's complexity may exceed the limits.\n"; }; } } while (false) | ||||
| 222 | << PrintNode<UseNode*>(UN, *DFG) << '\n'do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Unable to collect all reaching defs for use ***\n" << PrintNode<UseNode*>(UN, *DFG) << '\n' << "The program's complexity may exceed the limits.\n"; }; } } while (false) | ||||
| 223 | << "The program's complexity may exceed the limits.\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Unable to collect all reaching defs for use ***\n" << PrintNode<UseNode*>(UN, *DFG) << '\n' << "The program's complexity may exceed the limits.\n"; }; } } while (false) | ||||
| 224 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Unable to collect all reaching defs for use ***\n" << PrintNode<UseNode*>(UN, *DFG) << '\n' << "The program's complexity may exceed the limits.\n"; }; } } while (false); | ||||
| 225 | return false; | ||||
| 226 | } | ||||
| 227 | const auto &ReachingDefs = P.first; | ||||
| 228 | if (ReachingDefs.size() > 1) { | ||||
| 229 | LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Multiple Reaching Defs found!!! ***\n" ; for (auto DI : ReachingDefs) { NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI); NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG); dbgs() << "\t\t[Reaching Def]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; } }; } } while (false) | ||||
| 230 | dbgs() << "*** Multiple Reaching Defs found!!! ***\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Multiple Reaching Defs found!!! ***\n" ; for (auto DI : ReachingDefs) { NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI); NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG); dbgs() << "\t\t[Reaching Def]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; } }; } } while (false) | ||||
| 231 | for (auto DI : ReachingDefs) {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Multiple Reaching Defs found!!! ***\n" ; for (auto DI : ReachingDefs) { NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI); NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG); dbgs() << "\t\t[Reaching Def]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; } }; } } while (false) | ||||
| 232 | NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI);do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Multiple Reaching Defs found!!! ***\n" ; for (auto DI : ReachingDefs) { NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI); NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG); dbgs() << "\t\t[Reaching Def]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; } }; } } while (false) | ||||
| 233 | NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG);do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Multiple Reaching Defs found!!! ***\n" ; for (auto DI : ReachingDefs) { NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI); NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG); dbgs() << "\t\t[Reaching Def]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; } }; } } while (false) | ||||
| 234 | dbgs() << "\t\t[Reaching Def]: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Multiple Reaching Defs found!!! ***\n" ; for (auto DI : ReachingDefs) { NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI); NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG); dbgs() << "\t\t[Reaching Def]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; } }; } } while (false) | ||||
| 235 | << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Multiple Reaching Defs found!!! ***\n" ; for (auto DI : ReachingDefs) { NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI); NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG); dbgs() << "\t\t[Reaching Def]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; } }; } } while (false) | ||||
| 236 | }do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Multiple Reaching Defs found!!! ***\n" ; for (auto DI : ReachingDefs) { NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI); NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG); dbgs() << "\t\t[Reaching Def]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; } }; } } while (false) | ||||
| 237 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { dbgs() << "*** Multiple Reaching Defs found!!! ***\n" ; for (auto DI : ReachingDefs) { NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI); NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG); dbgs() << "\t\t[Reaching Def]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; } }; } } while (false); | ||||
| 238 | return false; | ||||
| 239 | } | ||||
| 240 | } | ||||
| 241 | return true; | ||||
| 242 | } | ||||
| 243 | |||||
| 244 | void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA, | ||||
| 245 | NodeList &UNodeList) { | ||||
| 246 | for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) { | ||||
| 247 | LLVM_DEBUG(dbgs() << "\t\t[DefNode]: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\t\t[DefNode]: " << Print<NodeAddr<DefNode *>>(DA, *DFG) << "\n" ; } } while (false) | ||||
| 248 | << Print<NodeAddr<DefNode *>>(DA, *DFG) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\t\t[DefNode]: " << Print<NodeAddr<DefNode *>>(DA, *DFG) << "\n" ; } } while (false); | ||||
| 249 | RegisterRef DR = DFG->getPRI().normalize(DA.Addr->getRegRef(*DFG)); | ||||
| 250 | |||||
| 251 | auto UseSet = LV->getAllReachedUses(DR, DA); | ||||
| 252 | |||||
| 253 | for (auto UI : UseSet) { | ||||
| 254 | NodeAddr<UseNode *> UA = DFG->addr<UseNode *>(UI); | ||||
| 255 | LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { NodeAddr<StmtNode *> TempIA = UA .Addr->getOwner(*DFG); dbgs() << "\t\t\t[Reached Use]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; }; } } while (false) | ||||
| 256 | NodeAddr<StmtNode *> TempIA = UA.Addr->getOwner(*DFG);do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { NodeAddr<StmtNode *> TempIA = UA .Addr->getOwner(*DFG); dbgs() << "\t\t\t[Reached Use]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; }; } } while (false) | ||||
| 257 | dbgs() << "\t\t\t[Reached Use]: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { NodeAddr<StmtNode *> TempIA = UA .Addr->getOwner(*DFG); dbgs() << "\t\t\t[Reached Use]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; }; } } while (false) | ||||
| 258 | << Print<NodeAddr<InstrNode *>>(TempIA, *DFG) << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { NodeAddr<StmtNode *> TempIA = UA .Addr->getOwner(*DFG); dbgs() << "\t\t\t[Reached Use]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; }; } } while (false) | ||||
| 259 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { { NodeAddr<StmtNode *> TempIA = UA .Addr->getOwner(*DFG); dbgs() << "\t\t\t[Reached Use]: " << Print<NodeAddr<InstrNode *>>(TempIA, *DFG ) << "\n"; }; } } while (false); | ||||
| 260 | |||||
| 261 | if (UA.Addr->getFlags() & NodeAttrs::PhiRef) { | ||||
| 262 | NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*DFG); | ||||
| 263 | NodeId id = PA.Id; | ||||
| 264 | const Liveness::RefMap &phiUse = LV->getRealUses(id); | ||||
| 265 | LLVM_DEBUG(dbgs() << "\t\t\t\tphi real Uses"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\t\t\t\tphi real Uses" << Print<Liveness::RefMap>(phiUse, *DFG) << "\n"; } } while (false) | ||||
| 266 | << Print<Liveness::RefMap>(phiUse, *DFG) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\t\t\t\tphi real Uses" << Print<Liveness::RefMap>(phiUse, *DFG) << "\n"; } } while (false); | ||||
| 267 | if (!phiUse.empty()) { | ||||
| 268 | for (auto I : phiUse) { | ||||
| 269 | if (!DFG->getPRI().alias(RegisterRef(I.first), DR)) | ||||
| 270 | continue; | ||||
| 271 | auto phiUseSet = I.second; | ||||
| 272 | for (auto phiUI : phiUseSet) { | ||||
| 273 | NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI.first); | ||||
| 274 | UNodeList.push_back(phiUA); | ||||
| 275 | } | ||||
| 276 | } | ||||
| 277 | } | ||||
| 278 | } else | ||||
| 279 | UNodeList.push_back(UA); | ||||
| 280 | } | ||||
| 281 | } | ||||
| 282 | } | ||||
| 283 | |||||
| 284 | bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr<StmtNode *> SN, | ||||
| 285 | MachineInstr *MI, unsigned LRExtReg, | ||||
| 286 | const NodeList &UNodeList) { | ||||
| 287 | RegisterRef LRExtRR; | ||||
| 288 | NodeId LRExtRegRD = 0; | ||||
| 289 | // Iterate through all the UseNodes in SN and find the reaching def | ||||
| 290 | // for the LRExtReg. | ||||
| 291 | for (NodeAddr<UseNode *> UA : SN.Addr->members_if(DFG->IsUse, *DFG)) { | ||||
| 292 | RegisterRef RR = UA.Addr->getRegRef(*DFG); | ||||
| 293 | if (LRExtReg == RR.Reg) { | ||||
| 294 | LRExtRR = RR; | ||||
| 295 | LRExtRegRD = UA.Addr->getReachingDef(); | ||||
| 296 | } | ||||
| 297 | } | ||||
| 298 | |||||
| 299 | for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { | ||||
| 300 | NodeAddr<UseNode *> UA = *I; | ||||
| 301 | NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG); | ||||
| 302 | // The reaching def of LRExtRR at load/store node should be same as the | ||||
| 303 | // one reaching at the SN. | ||||
| 304 | if (UA.Addr->getFlags() & NodeAttrs::PhiRef) | ||||
| 305 | return false; | ||||
| 306 | NodeAddr<RefNode*> AA = LV->getNearestAliasedRef(LRExtRR, IA); | ||||
| 307 | if ((DFG->IsDef(AA) && AA.Id != LRExtRegRD) || | ||||
| 308 | AA.Addr->getReachingDef() != LRExtRegRD) { | ||||
| 309 | LLVM_DEBUG(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "isSafeToExtLR: Returning false; another reaching def\n" ; } } while (false) | ||||
| 310 | dbgs() << "isSafeToExtLR: Returning false; another reaching def\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "isSafeToExtLR: Returning false; another reaching def\n" ; } } while (false); | ||||
| 311 | return false; | ||||
| 312 | } | ||||
| 313 | |||||
| 314 | MachineInstr *UseMI = NodeAddr<StmtNode *>(IA).Addr->getCode(); | ||||
| 315 | NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD); | ||||
| 316 | // Reaching Def to LRExtReg can't be a phi. | ||||
| 317 | if ((LRExtRegDN.Addr->getFlags() & NodeAttrs::PhiRef) && | ||||
| 318 | MI->getParent() != UseMI->getParent()) | ||||
| 319 | return false; | ||||
| 320 | } | ||||
| 321 | return true; | ||||
| 322 | } | ||||
| 323 | |||||
| 324 | bool HexagonOptAddrMode::isValidOffset(MachineInstr *MI, int Offset) { | ||||
| 325 | unsigned AlignMask = 0; | ||||
| 326 | switch (HII->getMemAccessSize(*MI)) { | ||||
| 327 | case HexagonII::MemAccessSize::DoubleWordAccess: | ||||
| 328 | AlignMask = 0x7; | ||||
| 329 | break; | ||||
| 330 | case HexagonII::MemAccessSize::WordAccess: | ||||
| 331 | AlignMask = 0x3; | ||||
| 332 | break; | ||||
| 333 | case HexagonII::MemAccessSize::HalfWordAccess: | ||||
| 334 | AlignMask = 0x1; | ||||
| 335 | break; | ||||
| 336 | case HexagonII::MemAccessSize::ByteAccess: | ||||
| 337 | AlignMask = 0x0; | ||||
| 338 | break; | ||||
| 339 | default: | ||||
| 340 | return false; | ||||
| 341 | } | ||||
| 342 | |||||
| 343 | if ((AlignMask & Offset) != 0) | ||||
| 344 | return false; | ||||
| 345 | return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false); | ||||
| 346 | } | ||||
| 347 | |||||
| 348 | bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN, | ||||
| 349 | MachineInstr *AddMI, | ||||
| 350 | const NodeList &UNodeList) { | ||||
| 351 | |||||
| 352 | Register AddDefR = AddMI->getOperand(0).getReg(); | ||||
| 353 | for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { | ||||
| 354 | NodeAddr<UseNode *> UN = *I; | ||||
| 355 | NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG); | ||||
| 356 | MachineInstr *MI = SN.Addr->getCode(); | ||||
| 357 | const MCInstrDesc &MID = MI->getDesc(); | ||||
| 358 | if ((!MID.mayLoad() && !MID.mayStore()) || | ||||
| 359 | HII->getAddrMode(*MI) != HexagonII::BaseImmOffset || | ||||
| 360 | HII->isHVXVec(*MI)) | ||||
| 361 | return false; | ||||
| 362 | |||||
| 363 | MachineOperand BaseOp = MID.mayLoad() ? MI->getOperand(1) | ||||
| 364 | : MI->getOperand(0); | ||||
| 365 | |||||
| 366 | if (!BaseOp.isReg() || BaseOp.getReg() != AddDefR) | ||||
| 367 | return false; | ||||
| 368 | |||||
| 369 | MachineOperand OffsetOp = MID.mayLoad() ? MI->getOperand(2) | ||||
| 370 | : MI->getOperand(1); | ||||
| 371 | if (!OffsetOp.isImm()) | ||||
| 372 | return false; | ||||
| 373 | |||||
| 374 | int64_t newOffset = OffsetOp.getImm() + AddMI->getOperand(2).getImm(); | ||||
| 375 | if (!isValidOffset(MI, newOffset)) | ||||
| 376 | return false; | ||||
| 377 | |||||
| 378 | // Since we'll be extending the live range of Rt in the following example, | ||||
| 379 | // make sure that is safe. another definition of Rt doesn't exist between 'add' | ||||
| 380 | // and load/store instruction. | ||||
| 381 | // | ||||
| 382 | // Ex: Rx= add(Rt,#10) | ||||
| 383 | // memw(Rx+#0) = Rs | ||||
| 384 | // will be replaced with => memw(Rt+#10) = Rs | ||||
| 385 | Register BaseReg = AddMI->getOperand(1).getReg(); | ||||
| 386 | if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList)) | ||||
| 387 | return false; | ||||
| 388 | } | ||||
| 389 | |||||
| 390 | // Update all the uses of 'add' with the appropriate base and offset | ||||
| 391 | // values. | ||||
| 392 | bool Changed = false; | ||||
| 393 | for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { | ||||
| 394 | NodeAddr<UseNode *> UseN = *I; | ||||
| 395 | assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) &&((!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) && "Found a PhiRef node as a real reached use!!") ? static_cast <void> (0) : __assert_fail ("!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) && \"Found a PhiRef node as a real reached use!!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 396, __PRETTY_FUNCTION__)) | ||||
| 396 | "Found a PhiRef node as a real reached use!!")((!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) && "Found a PhiRef node as a real reached use!!") ? static_cast <void> (0) : __assert_fail ("!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) && \"Found a PhiRef node as a real reached use!!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 396, __PRETTY_FUNCTION__)); | ||||
| 397 | |||||
| 398 | NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG); | ||||
| 399 | MachineInstr *UseMI = OwnerN.Addr->getCode(); | ||||
| 400 | LLVM_DEBUG(dbgs() << "\t\t[MI <BB#" << UseMI->getParent()->getNumber()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\t\t[MI <BB#" << UseMI->getParent()->getNumber() << ">]: " << *UseMI << "\n"; } } while (false) | ||||
| 401 | << ">]: " << *UseMI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\t\t[MI <BB#" << UseMI->getParent()->getNumber() << ">]: " << *UseMI << "\n"; } } while (false); | ||||
| 402 | Changed |= updateAddUses(AddMI, UseMI); | ||||
| 403 | } | ||||
| 404 | |||||
| 405 | if (Changed) | ||||
| 406 | Deleted.insert(AddMI); | ||||
| 407 | |||||
| 408 | return Changed; | ||||
| 409 | } | ||||
| 410 | |||||
| 411 | bool HexagonOptAddrMode::updateAddUses(MachineInstr *AddMI, | ||||
| 412 | MachineInstr *UseMI) { | ||||
| 413 | const MachineOperand ImmOp = AddMI->getOperand(2); | ||||
| 414 | const MachineOperand AddRegOp = AddMI->getOperand(1); | ||||
| 415 | Register newReg = AddRegOp.getReg(); | ||||
| 416 | const MCInstrDesc &MID = UseMI->getDesc(); | ||||
| 417 | |||||
| 418 | MachineOperand &BaseOp = MID.mayLoad() ? UseMI->getOperand(1) | ||||
| 419 | : UseMI->getOperand(0); | ||||
| 420 | MachineOperand &OffsetOp = MID.mayLoad() ? UseMI->getOperand(2) | ||||
| 421 | : UseMI->getOperand(1); | ||||
| 422 | BaseOp.setReg(newReg); | ||||
| 423 | BaseOp.setIsUndef(AddRegOp.isUndef()); | ||||
| 424 | BaseOp.setImplicit(AddRegOp.isImplicit()); | ||||
| 425 | OffsetOp.setImm(ImmOp.getImm() + OffsetOp.getImm()); | ||||
| 426 | MRI->clearKillFlags(newReg); | ||||
| 427 | |||||
| 428 | return true; | ||||
| 429 | } | ||||
| 430 | |||||
| 431 | bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR, | ||||
| 432 | const NodeList &UNodeList, | ||||
| 433 | InstrEvalMap &InstrEvalResult, | ||||
| 434 | short &SizeInc) { | ||||
| 435 | bool KeepTfr = false; | ||||
| 436 | bool HasRepInstr = false; | ||||
| 437 | InstrEvalResult.clear(); | ||||
| 438 | |||||
| 439 | for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { | ||||
| 440 | bool CanBeReplaced = false; | ||||
| 441 | NodeAddr<UseNode *> UN = *I; | ||||
| 442 | NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG); | ||||
| 443 | MachineInstr &MI = *SN.Addr->getCode(); | ||||
| 444 | const MCInstrDesc &MID = MI.getDesc(); | ||||
| 445 | if ((MID.mayLoad() || MID.mayStore())) { | ||||
| 446 | if (!hasRepForm(MI, tfrDefR)) { | ||||
| 447 | KeepTfr = true; | ||||
| 448 | continue; | ||||
| 449 | } | ||||
| 450 | SizeInc++; | ||||
| 451 | CanBeReplaced = true; | ||||
| 452 | } else if (MI.getOpcode() == Hexagon::S2_addasl_rrri) { | ||||
| 453 | NodeList AddaslUseList; | ||||
| 454 | |||||
| 455 | LLVM_DEBUG(dbgs() << "\nGetting ReachedUses for === " << MI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\nGetting ReachedUses for === " << MI << "\n"; } } while (false); | ||||
| 456 | getAllRealUses(SN, AddaslUseList); | ||||
| 457 | // Process phi nodes. | ||||
| 458 | if (allValidCandidates(SN, AddaslUseList) && | ||||
| 459 | canRemoveAddasl(SN, MI, AddaslUseList)) { | ||||
| 460 | SizeInc += AddaslUseList.size(); | ||||
| 461 | SizeInc -= 1; // Reduce size by 1 as addasl itself can be removed. | ||||
| 462 | CanBeReplaced = true; | ||||
| 463 | } else | ||||
| 464 | SizeInc++; | ||||
| 465 | } else | ||||
| 466 | // Currently, only load/store and addasl are handled. | ||||
| 467 | // Some other instructions to consider - | ||||
| 468 | // A2_add -> A2_addi | ||||
| 469 | // M4_mpyrr_addr -> M4_mpyrr_addi | ||||
| 470 | KeepTfr = true; | ||||
| 471 | |||||
| 472 | InstrEvalResult[&MI] = CanBeReplaced; | ||||
| 473 | HasRepInstr |= CanBeReplaced; | ||||
| 474 | } | ||||
| 475 | |||||
| 476 | // Reduce total size by 2 if original tfr can be deleted. | ||||
| 477 | if (!KeepTfr) | ||||
| 478 | SizeInc -= 2; | ||||
| 479 | |||||
| 480 | return HasRepInstr; | ||||
| 481 | } | ||||
| 482 | |||||
| 483 | bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, | ||||
| 484 | unsigned ImmOpNum) { | ||||
| 485 | bool Changed = false; | ||||
| 486 | MachineBasicBlock *BB = OldMI->getParent(); | ||||
| 487 | auto UsePos = MachineBasicBlock::iterator(OldMI); | ||||
| 488 | MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator(); | ||||
| 489 | ++InsertPt; | ||||
| 490 | unsigned OpStart; | ||||
| 491 | unsigned OpEnd = OldMI->getNumOperands(); | ||||
| 492 | MachineInstrBuilder MIB; | ||||
| 493 | |||||
| 494 | if (ImmOpNum == 1) { | ||||
| 495 | if (HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset) { | ||||
| 496 | short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI); | ||||
| 497 | assert(NewOpCode >= 0 && "Invalid New opcode\n")((NewOpCode >= 0 && "Invalid New opcode\n") ? static_cast <void> (0) : __assert_fail ("NewOpCode >= 0 && \"Invalid New opcode\\n\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 497, __PRETTY_FUNCTION__)); | ||||
| 498 | MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)); | ||||
| 499 | MIB.add(OldMI->getOperand(0)); | ||||
| 500 | MIB.add(OldMI->getOperand(2)); | ||||
| 501 | MIB.add(OldMI->getOperand(3)); | ||||
| 502 | MIB.add(ImmOp); | ||||
| 503 | OpStart = 4; | ||||
| 504 | Changed = true; | ||||
| 505 | } else if (HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset && | ||||
| 506 | OldMI->getOperand(2).isImm()) { | ||||
| 507 | short NewOpCode = HII->changeAddrMode_io_abs(*OldMI); | ||||
| 508 | assert(NewOpCode >= 0 && "Invalid New opcode\n")((NewOpCode >= 0 && "Invalid New opcode\n") ? static_cast <void> (0) : __assert_fail ("NewOpCode >= 0 && \"Invalid New opcode\\n\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 508, __PRETTY_FUNCTION__)); | ||||
| 509 | MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)) | ||||
| 510 | .add(OldMI->getOperand(0)); | ||||
| 511 | const GlobalValue *GV = ImmOp.getGlobal(); | ||||
| 512 | int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(2).getImm(); | ||||
| 513 | |||||
| 514 | MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags()); | ||||
| 515 | OpStart = 3; | ||||
| 516 | Changed = true; | ||||
| 517 | } else | ||||
| 518 | Changed = false; | ||||
| 519 | |||||
| 520 | LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[Changing]: " << * OldMI << "\n"; } } while (false); | ||||
| 521 | LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[TO]: " << *MIB << "\n"; } } while (false); | ||||
| 522 | } else if (ImmOpNum == 2) { | ||||
| 523 | if (OldMI->getOperand(3).isImm() && OldMI->getOperand(3).getImm() == 0) { | ||||
| 524 | short NewOpCode = HII->changeAddrMode_rr_io(*OldMI); | ||||
| 525 | assert(NewOpCode >= 0 && "Invalid New opcode\n")((NewOpCode >= 0 && "Invalid New opcode\n") ? static_cast <void> (0) : __assert_fail ("NewOpCode >= 0 && \"Invalid New opcode\\n\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 525, __PRETTY_FUNCTION__)); | ||||
| 526 | MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)); | ||||
| 527 | MIB.add(OldMI->getOperand(0)); | ||||
| 528 | MIB.add(OldMI->getOperand(1)); | ||||
| 529 | MIB.add(ImmOp); | ||||
| 530 | OpStart = 4; | ||||
| 531 | Changed = true; | ||||
| 532 | LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[Changing]: " << * OldMI << "\n"; } } while (false); | ||||
| 533 | LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[TO]: " << *MIB << "\n"; } } while (false); | ||||
| 534 | } | ||||
| 535 | } | ||||
| 536 | |||||
| 537 | if (Changed) | ||||
| 538 | for (unsigned i = OpStart; i < OpEnd; ++i) | ||||
| 539 | MIB.add(OldMI->getOperand(i)); | ||||
| 540 | |||||
| 541 | return Changed; | ||||
| 542 | } | ||||
| 543 | |||||
| 544 | bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp, | ||||
| 545 | unsigned ImmOpNum) { | ||||
| 546 | bool Changed = false; | ||||
| 547 | unsigned OpStart = 0; | ||||
| 548 | unsigned OpEnd = OldMI->getNumOperands(); | ||||
| 549 | MachineBasicBlock *BB = OldMI->getParent(); | ||||
| 550 | auto UsePos = MachineBasicBlock::iterator(OldMI); | ||||
| 551 | MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator(); | ||||
| 552 | ++InsertPt; | ||||
| 553 | MachineInstrBuilder MIB; | ||||
| 554 | if (ImmOpNum == 0) { | ||||
| 555 | if (HII->getAddrMode(*OldMI) == HexagonII::BaseRegOffset) { | ||||
| 556 | short NewOpCode = HII->changeAddrMode_rr_ur(*OldMI); | ||||
| 557 | assert(NewOpCode >= 0 && "Invalid New opcode\n")((NewOpCode >= 0 && "Invalid New opcode\n") ? static_cast <void> (0) : __assert_fail ("NewOpCode >= 0 && \"Invalid New opcode\\n\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 557, __PRETTY_FUNCTION__)); | ||||
| 558 | MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)); | ||||
| 559 | MIB.add(OldMI->getOperand(1)); | ||||
| 560 | MIB.add(OldMI->getOperand(2)); | ||||
| 561 | MIB.add(ImmOp); | ||||
| 562 | MIB.add(OldMI->getOperand(3)); | ||||
| 563 | OpStart = 4; | ||||
| 564 | } else if (HII->getAddrMode(*OldMI) == HexagonII::BaseImmOffset) { | ||||
| 565 | short NewOpCode = HII->changeAddrMode_io_abs(*OldMI); | ||||
| 566 | assert(NewOpCode >= 0 && "Invalid New opcode\n")((NewOpCode >= 0 && "Invalid New opcode\n") ? static_cast <void> (0) : __assert_fail ("NewOpCode >= 0 && \"Invalid New opcode\\n\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 566, __PRETTY_FUNCTION__)); | ||||
| 567 | MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)); | ||||
| 568 | const GlobalValue *GV = ImmOp.getGlobal(); | ||||
| 569 | int64_t Offset = ImmOp.getOffset() + OldMI->getOperand(1).getImm(); | ||||
| 570 | MIB.addGlobalAddress(GV, Offset, ImmOp.getTargetFlags()); | ||||
| 571 | MIB.add(OldMI->getOperand(2)); | ||||
| 572 | OpStart = 3; | ||||
| 573 | } | ||||
| 574 | Changed = true; | ||||
| 575 | LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[Changing]: " << * OldMI << "\n"; } } while (false); | ||||
| 576 | LLVM_DEBUG
("opt-addr-mode")) { dbgs() << "[TO]: " << *MIB << "\n"; } } while (false); | ||||
| 577 | } else if (ImmOpNum == 1 && OldMI->getOperand(2).getImm() == 0) { | ||||
| 578 | short NewOpCode = HII->changeAddrMode_rr_io(*OldMI); | ||||
| 579 | assert(NewOpCode >= 0 && "Invalid New opcode\n")((NewOpCode >= 0 && "Invalid New opcode\n") ? static_cast <void> (0) : __assert_fail ("NewOpCode >= 0 && \"Invalid New opcode\\n\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 579, __PRETTY_FUNCTION__)); | ||||
| 580 | MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode)); | ||||
| 581 | MIB.add(OldMI->getOperand(0)); | ||||
| 582 | MIB.add(ImmOp); | ||||
| 583 | OpStart = 3; | ||||
| 584 | Changed = true; | ||||
| 585 | LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[Changing]: " << * OldMI << "\n"; } } while (false); | ||||
| 586 | LLVM_DEBUG(dbgs() << "[TO]: " << *MIB << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[TO]: " << *MIB << "\n"; } } while (false); | ||||
| 587 | } | ||||
| 588 | if (Changed
| ||||
| 589 | for (unsigned i = OpStart; i < OpEnd; ++i) | ||||
| 590 | MIB.add(OldMI->getOperand(i)); | ||||
| 591 | |||||
| 592 | return Changed; | ||||
| 593 | } | ||||
| 594 | |||||
| 595 | short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr &MI) const { | ||||
| 596 | if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset) { | ||||
| 597 | short TempOpCode = HII->changeAddrMode_io_rr(MI); | ||||
| 598 | return HII->changeAddrMode_rr_ur(TempOpCode); | ||||
| 599 | } | ||||
| 600 | return HII->changeAddrMode_rr_ur(MI); | ||||
| 601 | } | ||||
| 602 | |||||
| 603 | bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN, | ||||
| 604 | MachineInstr *AddAslMI, | ||||
| 605 | const MachineOperand &ImmOp, | ||||
| 606 | unsigned ImmOpNum) { | ||||
| 607 | NodeAddr<StmtNode *> SA = AddAslUN.Addr->getOwner(*DFG); | ||||
| 608 | |||||
| 609 | LLVM_DEBUG(dbgs() << "Processing addasl :" << *AddAslMI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "Processing addasl :" << *AddAslMI << "\n"; } } while (false); | ||||
| 610 | |||||
| 611 | NodeList UNodeList; | ||||
| 612 | getAllRealUses(SA, UNodeList); | ||||
| 613 | |||||
| 614 | for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { | ||||
| 615 | NodeAddr<UseNode *> UseUN = *I; | ||||
| 616 | assert(!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) &&((!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) && "Can't transform this 'AddAsl' instruction!") ? static_cast< void> (0) : __assert_fail ("!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) && \"Can't transform this 'AddAsl' instruction!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 617, __PRETTY_FUNCTION__)) | ||||
| 617 | "Can't transform this 'AddAsl' instruction!")((!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) && "Can't transform this 'AddAsl' instruction!") ? static_cast< void> (0) : __assert_fail ("!(UseUN.Addr->getFlags() & NodeAttrs::PhiRef) && \"Can't transform this 'AddAsl' instruction!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 617, __PRETTY_FUNCTION__)); | ||||
| 618 | |||||
| 619 | NodeAddr<StmtNode *> UseIA = UseUN.Addr->getOwner(*DFG); | ||||
| 620 | LLVM_DEBUG(dbgs() << "[InstrNode]: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[InstrNode]: " << Print<NodeAddr<InstrNode *>>(UseIA, *DFG) << "\n"; } } while (false) | ||||
| 621 | << Print<NodeAddr<InstrNode *>>(UseIA, *DFG) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[InstrNode]: " << Print<NodeAddr<InstrNode *>>(UseIA, *DFG) << "\n"; } } while (false); | ||||
| 622 | MachineInstr *UseMI = UseIA.Addr->getCode(); | ||||
| 623 | LLVM_DEBUG(dbgs() << "[MI <" << printMBBReference(*UseMI->getParent())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[MI <" << printMBBReference (*UseMI->getParent()) << ">]: " << *UseMI << "\n"; } } while (false) | ||||
| 624 | << ">]: " << *UseMI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[MI <" << printMBBReference (*UseMI->getParent()) << ">]: " << *UseMI << "\n"; } } while (false); | ||||
| 625 | const MCInstrDesc &UseMID = UseMI->getDesc(); | ||||
| 626 | assert(HII->getAddrMode(*UseMI) == HexagonII::BaseImmOffset)((HII->getAddrMode(*UseMI) == HexagonII::BaseImmOffset) ? static_cast <void> (0) : __assert_fail ("HII->getAddrMode(*UseMI) == HexagonII::BaseImmOffset" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 626, __PRETTY_FUNCTION__)); | ||||
| 627 | |||||
| 628 | auto UsePos = MachineBasicBlock::iterator(UseMI); | ||||
| 629 | MachineBasicBlock::instr_iterator InsertPt = UsePos.getInstrIterator(); | ||||
| 630 | short NewOpCode = getBaseWithLongOffset(*UseMI); | ||||
| 631 | assert(NewOpCode >= 0 && "Invalid New opcode\n")((NewOpCode >= 0 && "Invalid New opcode\n") ? static_cast <void> (0) : __assert_fail ("NewOpCode >= 0 && \"Invalid New opcode\\n\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 631, __PRETTY_FUNCTION__)); | ||||
| 632 | |||||
| 633 | unsigned OpStart; | ||||
| 634 | unsigned OpEnd = UseMI->getNumOperands(); | ||||
| 635 | |||||
| 636 | MachineBasicBlock *BB = UseMI->getParent(); | ||||
| 637 | MachineInstrBuilder MIB = | ||||
| 638 | BuildMI(*BB, InsertPt, UseMI->getDebugLoc(), HII->get(NewOpCode)); | ||||
| 639 | // change mem(Rs + # ) -> mem(Rt << # + ##) | ||||
| 640 | if (UseMID.mayLoad()) { | ||||
| 641 | MIB.add(UseMI->getOperand(0)); | ||||
| 642 | MIB.add(AddAslMI->getOperand(2)); | ||||
| 643 | MIB.add(AddAslMI->getOperand(3)); | ||||
| 644 | const GlobalValue *GV = ImmOp.getGlobal(); | ||||
| 645 | MIB.addGlobalAddress(GV, UseMI->getOperand(2).getImm()+ImmOp.getOffset(), | ||||
| 646 | ImmOp.getTargetFlags()); | ||||
| 647 | OpStart = 3; | ||||
| 648 | } else if (UseMID.mayStore()) { | ||||
| 649 | MIB.add(AddAslMI->getOperand(2)); | ||||
| 650 | MIB.add(AddAslMI->getOperand(3)); | ||||
| 651 | const GlobalValue *GV = ImmOp.getGlobal(); | ||||
| 652 | MIB.addGlobalAddress(GV, UseMI->getOperand(1).getImm()+ImmOp.getOffset(), | ||||
| 653 | ImmOp.getTargetFlags()); | ||||
| 654 | MIB.add(UseMI->getOperand(2)); | ||||
| 655 | OpStart = 3; | ||||
| 656 | } else | ||||
| 657 | llvm_unreachable("Unhandled instruction")::llvm::llvm_unreachable_internal("Unhandled instruction", "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 657); | ||||
| 658 | |||||
| 659 | for (unsigned i = OpStart; i < OpEnd; ++i) | ||||
| 660 | MIB.add(UseMI->getOperand(i)); | ||||
| 661 | |||||
| 662 | Deleted.insert(UseMI); | ||||
| 663 | } | ||||
| 664 | |||||
| 665 | return true; | ||||
| 666 | } | ||||
| 667 | |||||
| 668 | bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI, | ||||
| 669 | NodeAddr<UseNode *> UseN, | ||||
| 670 | unsigned UseMOnum) { | ||||
| 671 | const MachineOperand ImmOp = TfrMI->getOperand(1); | ||||
| 672 | const MCInstrDesc &MID = UseMI->getDesc(); | ||||
| 673 | unsigned Changed = false; | ||||
| 674 | if (MID.mayLoad()) | ||||
| |||||
| 675 | Changed = changeLoad(UseMI, ImmOp, UseMOnum); | ||||
| 676 | else if (MID.mayStore()) | ||||
| 677 | Changed = changeStore(UseMI, ImmOp, UseMOnum); | ||||
| 678 | else if (UseMI->getOpcode() == Hexagon::S2_addasl_rrri) | ||||
| 679 | Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum); | ||||
| 680 | |||||
| 681 | if (Changed) | ||||
| 682 | Deleted.insert(UseMI); | ||||
| 683 | |||||
| 684 | return Changed; | ||||
| 685 | } | ||||
| 686 | |||||
| 687 | bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) { | ||||
| 688 | bool Changed = false; | ||||
| 689 | |||||
| 690 | for (auto IA : BA.Addr->members(*DFG)) { | ||||
| 691 | if (!DFG->IsCode<NodeAttrs::Stmt>(IA)) | ||||
| 692 | continue; | ||||
| 693 | |||||
| 694 | NodeAddr<StmtNode *> SA = IA; | ||||
| 695 | MachineInstr *MI = SA.Addr->getCode(); | ||||
| 696 | if ((MI->getOpcode() != Hexagon::A2_tfrsi || | ||||
| 697 | !MI->getOperand(1).isGlobal()) && | ||||
| 698 | (MI->getOpcode() != Hexagon::A2_addi || | ||||
| 699 | !MI->getOperand(2).isImm() || HII->isConstExtended(*MI))) | ||||
| 700 | continue; | ||||
| 701 | |||||
| 702 | LLVM_DEBUG(dbgs() << "[Analyzing " << HII->getName(MI->getOpcode())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[Analyzing " << HII ->getName(MI->getOpcode()) << "]: " << *MI << "\n\t[InstrNode]: " << Print<NodeAddr<InstrNode * >>(IA, *DFG) << '\n'; } } while (false) | ||||
| 703 | << "]: " << *MI << "\n\t[InstrNode]: "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[Analyzing " << HII ->getName(MI->getOpcode()) << "]: " << *MI << "\n\t[InstrNode]: " << Print<NodeAddr<InstrNode * >>(IA, *DFG) << '\n'; } } while (false) | ||||
| 704 | << Print<NodeAddr<InstrNode *>>(IA, *DFG) << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "[Analyzing " << HII ->getName(MI->getOpcode()) << "]: " << *MI << "\n\t[InstrNode]: " << Print<NodeAddr<InstrNode * >>(IA, *DFG) << '\n'; } } while (false); | ||||
| 705 | |||||
| 706 | NodeList UNodeList; | ||||
| 707 | getAllRealUses(SA, UNodeList); | ||||
| 708 | |||||
| 709 | if (!allValidCandidates(SA, UNodeList)) | ||||
| 710 | continue; | ||||
| 711 | |||||
| 712 | // Analyze all uses of 'add'. If the output of 'add' is used as an address | ||||
| 713 | // in the base+immediate addressing mode load/store instructions, see if | ||||
| 714 | // they can be updated to use the immediate value as an offet. Thus, | ||||
| 715 | // providing us the opportunity to eliminate 'add'. | ||||
| 716 | // Ex: Rx= add(Rt,#12) | ||||
| 717 | // memw(Rx+#0) = Rs | ||||
| 718 | // This can be replaced with memw(Rt+#12) = Rs | ||||
| 719 | // | ||||
| 720 | // This transformation is only performed if all uses can be updated and | ||||
| 721 | // the offset isn't required to be constant extended. | ||||
| 722 | if (MI->getOpcode() == Hexagon::A2_addi) { | ||||
| 723 | Changed |= processAddUses(SA, MI, UNodeList); | ||||
| 724 | continue; | ||||
| 725 | } | ||||
| 726 | |||||
| 727 | short SizeInc = 0; | ||||
| 728 | Register DefR = MI->getOperand(0).getReg(); | ||||
| 729 | InstrEvalMap InstrEvalResult; | ||||
| 730 | |||||
| 731 | // Analyze all uses and calculate increase in size. Perform the optimization | ||||
| 732 | // only if there is no increase in size. | ||||
| 733 | if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc)) | ||||
| 734 | continue; | ||||
| 735 | if (SizeInc > CodeGrowthLimit) | ||||
| 736 | continue; | ||||
| 737 | |||||
| 738 | bool KeepTfr = false; | ||||
| 739 | |||||
| 740 | LLVM_DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList.size()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\t[Total reached uses] : " << UNodeList.size() << "\n"; } } while (false) | ||||
| 741 | << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\t[Total reached uses] : " << UNodeList.size() << "\n"; } } while (false); | ||||
| 742 | LLVM_DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\t[Processing Reached Uses] ===\n" ; } } while (false); | ||||
| 743 | for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) { | ||||
| 744 | NodeAddr<UseNode *> UseN = *I; | ||||
| 745 | assert(!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) &&((!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) && "Found a PhiRef node as a real reached use!!") ? static_cast <void> (0) : __assert_fail ("!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) && \"Found a PhiRef node as a real reached use!!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 746, __PRETTY_FUNCTION__)) | ||||
| 746 | "Found a PhiRef node as a real reached use!!")((!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) && "Found a PhiRef node as a real reached use!!") ? static_cast <void> (0) : __assert_fail ("!(UseN.Addr->getFlags() & NodeAttrs::PhiRef) && \"Found a PhiRef node as a real reached use!!\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp" , 746, __PRETTY_FUNCTION__)); | ||||
| 747 | |||||
| 748 | NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG); | ||||
| 749 | MachineInstr *UseMI = OwnerN.Addr->getCode(); | ||||
| 750 | LLVM_DEBUG(dbgs() << "\t\t[MI <" << printMBBReference(*UseMI->getParent())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\t\t[MI <" << printMBBReference (*UseMI->getParent()) << ">]: " << *UseMI << "\n"; } } while (false) | ||||
| 751 | << ">]: " << *UseMI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "\t\t[MI <" << printMBBReference (*UseMI->getParent()) << ">]: " << *UseMI << "\n"; } } while (false); | ||||
| 752 | |||||
| 753 | int UseMOnum = -1; | ||||
| 754 | unsigned NumOperands = UseMI->getNumOperands(); | ||||
| 755 | for (unsigned j = 0; j < NumOperands - 1; ++j) { | ||||
| 756 | const MachineOperand &op = UseMI->getOperand(j); | ||||
| 757 | if (op.isReg() && op.isUse() && DefR == op.getReg()) | ||||
| 758 | UseMOnum = j; | ||||
| 759 | } | ||||
| 760 | // It is possible that the register will not be found in any operand. | ||||
| 761 | // This could happen, for example, when DefR = R4, but the used | ||||
| 762 | // register is D2. | ||||
| 763 | |||||
| 764 | // Change UseMI if replacement is possible. If any replacement failed, | ||||
| 765 | // or wasn't attempted, make sure to keep the TFR. | ||||
| 766 | bool Xformed = false; | ||||
| 767 | if (UseMOnum >= 0 && InstrEvalResult[UseMI]) | ||||
| 768 | Xformed = xformUseMI(MI, UseMI, UseN, UseMOnum); | ||||
| 769 | Changed |= Xformed; | ||||
| 770 | KeepTfr |= !Xformed; | ||||
| 771 | } | ||||
| 772 | if (!KeepTfr) | ||||
| 773 | Deleted.insert(MI); | ||||
| 774 | } | ||||
| 775 | return Changed; | ||||
| 776 | } | ||||
| 777 | |||||
| 778 | bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) { | ||||
| 779 | if (skipFunction(MF.getFunction())) | ||||
| 780 | return false; | ||||
| 781 | |||||
| 782 | bool Changed = false; | ||||
| 783 | auto &HST = MF.getSubtarget<HexagonSubtarget>(); | ||||
| 784 | MRI = &MF.getRegInfo(); | ||||
| 785 | HII = HST.getInstrInfo(); | ||||
| 786 | HRI = HST.getRegisterInfo(); | ||||
| 787 | const auto &MDF = getAnalysis<MachineDominanceFrontier>(); | ||||
| 788 | MDT = &getAnalysis<MachineDominatorTree>(); | ||||
| 789 | const TargetOperandInfo TOI(*HII); | ||||
| 790 | |||||
| 791 | DataFlowGraph G(MF, *HII, *HRI, *MDT, MDF, TOI); | ||||
| 792 | // Need to keep dead phis because we can propagate uses of registers into | ||||
| 793 | // nodes dominated by those would-be phis. | ||||
| 794 | G.build(BuildOptions::KeepDeadPhis); | ||||
| 795 | DFG = &G; | ||||
| 796 | |||||
| 797 | Liveness L(*MRI, *DFG); | ||||
| 798 | L.computePhiInfo(); | ||||
| 799 | LV = &L; | ||||
| 800 | |||||
| 801 | Deleted.clear(); | ||||
| 802 | NodeAddr<FuncNode *> FA = DFG->getFunc(); | ||||
| 803 | LLVM_DEBUG(dbgs() << "==== [RefMap#]=====:\n "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "==== [RefMap#]=====:\n " << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n"; } } while (false) | ||||
| 804 | << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("opt-addr-mode")) { dbgs() << "==== [RefMap#]=====:\n " << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n"; } } while (false); | ||||
| 805 | |||||
| 806 | for (NodeAddr<BlockNode *> BA : FA.Addr->members(*DFG)) | ||||
| 807 | Changed |= processBlock(BA); | ||||
| 808 | |||||
| 809 | for (auto MI : Deleted) | ||||
| 810 | MI->eraseFromParent(); | ||||
| 811 | |||||
| 812 | if (Changed) { | ||||
| 813 | G.build(); | ||||
| 814 | L.computeLiveIns(); | ||||
| 815 | L.resetLiveIns(); | ||||
| 816 | L.resetKills(); | ||||
| 817 | } | ||||
| 818 | |||||
| 819 | return Changed; | ||||
| 820 | } | ||||
| 821 | |||||
| 822 | //===----------------------------------------------------------------------===// | ||||
| 823 | // Public Constructor Functions | ||||
| 824 | //===----------------------------------------------------------------------===// | ||||
| 825 | |||||
| 826 | FunctionPass *llvm::createHexagonOptAddrMode() { | ||||
| 827 | return new HexagonOptAddrMode(); | ||||
| 828 | } |
| 1 | //===- CodeGen/MachineInstrBuilder.h - Simplify creation of MIs --*- C++ -*-===// | |||
| 2 | // | |||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
| 6 | // | |||
| 7 | //===----------------------------------------------------------------------===// | |||
| 8 | // | |||
| 9 | // This file exposes a function named BuildMI, which is useful for dramatically | |||
| 10 | // simplifying how MachineInstr's are created. It allows use of code like this: | |||
| 11 | // | |||
| 12 | // M = BuildMI(MBB, MI, DL, TII.get(X86::ADD8rr), Dst) | |||
| 13 | // .addReg(argVal1) | |||
| 14 | // .addReg(argVal2); | |||
| 15 | // | |||
| 16 | //===----------------------------------------------------------------------===// | |||
| 17 | ||||
| 18 | #ifndef LLVM_CODEGEN_MACHINEINSTRBUILDER_H | |||
| 19 | #define LLVM_CODEGEN_MACHINEINSTRBUILDER_H | |||
| 20 | ||||
| 21 | #include "llvm/ADT/ArrayRef.h" | |||
| 22 | #include "llvm/CodeGen/GlobalISel/Utils.h" | |||
| 23 | #include "llvm/CodeGen/MachineBasicBlock.h" | |||
| 24 | #include "llvm/CodeGen/MachineFunction.h" | |||
| 25 | #include "llvm/CodeGen/MachineInstr.h" | |||
| 26 | #include "llvm/CodeGen/MachineInstrBundle.h" | |||
| 27 | #include "llvm/CodeGen/MachineOperand.h" | |||
| 28 | #include "llvm/CodeGen/TargetRegisterInfo.h" | |||
| 29 | #include "llvm/IR/InstrTypes.h" | |||
| 30 | #include "llvm/IR/Intrinsics.h" | |||
| 31 | #include "llvm/Support/ErrorHandling.h" | |||
| 32 | #include <cassert> | |||
| 33 | #include <cstdint> | |||
| 34 | #include <utility> | |||
| 35 | ||||
| 36 | namespace llvm { | |||
| 37 | ||||
| 38 | class MCInstrDesc; | |||
| 39 | class MDNode; | |||
| 40 | ||||
| 41 | namespace RegState { | |||
| 42 | ||||
| 43 | enum { | |||
| 44 | Define = 0x2, | |||
| 45 | Implicit = 0x4, | |||
| 46 | Kill = 0x8, | |||
| 47 | Dead = 0x10, | |||
| 48 | Undef = 0x20, | |||
| 49 | EarlyClobber = 0x40, | |||
| 50 | Debug = 0x80, | |||
| 51 | InternalRead = 0x100, | |||
| 52 | Renamable = 0x200, | |||
| 53 | DefineNoRead = Define | Undef, | |||
| 54 | ImplicitDefine = Implicit | Define, | |||
| 55 | ImplicitKill = Implicit | Kill | |||
| 56 | }; | |||
| 57 | ||||
| 58 | } // end namespace RegState | |||
| 59 | ||||
| 60 | class MachineInstrBuilder { | |||
| 61 | MachineFunction *MF = nullptr; | |||
| 62 | MachineInstr *MI = nullptr; | |||
| 63 | ||||
| 64 | public: | |||
| 65 | MachineInstrBuilder() = default; | |||
| 66 | ||||
| 67 | /// Create a MachineInstrBuilder for manipulating an existing instruction. | |||
| 68 | /// F must be the machine function that was used to allocate I. | |||
| 69 | MachineInstrBuilder(MachineFunction &F, MachineInstr *I) : MF(&F), MI(I) {} | |||
| 70 | MachineInstrBuilder(MachineFunction &F, MachineBasicBlock::iterator I) | |||
| 71 | : MF(&F), MI(&*I) {} | |||
| 72 | ||||
| 73 | /// Allow automatic conversion to the machine instruction we are working on. | |||
| 74 | operator MachineInstr*() const { return MI; } | |||
| 75 | MachineInstr *operator->() const { return MI; } | |||
| 76 | operator MachineBasicBlock::iterator() const { return MI; } | |||
| 77 | ||||
| 78 | /// If conversion operators fail, use this method to get the MachineInstr | |||
| 79 | /// explicitly. | |||
| 80 | MachineInstr *getInstr() const { return MI; } | |||
| 81 | ||||
| 82 | /// Get the register for the operand index. | |||
| 83 | /// The operand at the index should be a register (asserted by | |||
| 84 | /// MachineOperand). | |||
| 85 | Register getReg(unsigned Idx) const { return MI->getOperand(Idx).getReg(); } | |||
| 86 | ||||
| 87 | /// Add a new virtual register operand. | |||
| 88 | const MachineInstrBuilder &addReg(Register RegNo, unsigned flags = 0, | |||
| 89 | unsigned SubReg = 0) const { | |||
| 90 | assert((flags & 0x1) == 0 &&(((flags & 0x1) == 0 && "Passing in 'true' to addReg is forbidden! Use enums instead." ) ? static_cast<void> (0) : __assert_fail ("(flags & 0x1) == 0 && \"Passing in 'true' to addReg is forbidden! Use enums instead.\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 91, __PRETTY_FUNCTION__)) | |||
| 91 | "Passing in 'true' to addReg is forbidden! Use enums instead.")(((flags & 0x1) == 0 && "Passing in 'true' to addReg is forbidden! Use enums instead." ) ? static_cast<void> (0) : __assert_fail ("(flags & 0x1) == 0 && \"Passing in 'true' to addReg is forbidden! Use enums instead.\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 91, __PRETTY_FUNCTION__)); | |||
| 92 | MI->addOperand(*MF, MachineOperand::CreateReg(RegNo, | |||
| 93 | flags & RegState::Define, | |||
| 94 | flags & RegState::Implicit, | |||
| 95 | flags & RegState::Kill, | |||
| 96 | flags & RegState::Dead, | |||
| 97 | flags & RegState::Undef, | |||
| 98 | flags & RegState::EarlyClobber, | |||
| 99 | SubReg, | |||
| 100 | flags & RegState::Debug, | |||
| 101 | flags & RegState::InternalRead, | |||
| 102 | flags & RegState::Renamable)); | |||
| 103 | return *this; | |||
| 104 | } | |||
| 105 | ||||
| 106 | /// Add a virtual register definition operand. | |||
| 107 | const MachineInstrBuilder &addDef(Register RegNo, unsigned Flags = 0, | |||
| 108 | unsigned SubReg = 0) const { | |||
| 109 | return addReg(RegNo, Flags | RegState::Define, SubReg); | |||
| 110 | } | |||
| 111 | ||||
| 112 | /// Add a virtual register use operand. It is an error for Flags to contain | |||
| 113 | /// `RegState::Define` when calling this function. | |||
| 114 | const MachineInstrBuilder &addUse(Register RegNo, unsigned Flags = 0, | |||
| 115 | unsigned SubReg = 0) const { | |||
| 116 | assert(!(Flags & RegState::Define) &&((!(Flags & RegState::Define) && "Misleading addUse defines register, use addReg instead." ) ? static_cast<void> (0) : __assert_fail ("!(Flags & RegState::Define) && \"Misleading addUse defines register, use addReg instead.\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 117, __PRETTY_FUNCTION__)) | |||
| 117 | "Misleading addUse defines register, use addReg instead.")((!(Flags & RegState::Define) && "Misleading addUse defines register, use addReg instead." ) ? static_cast<void> (0) : __assert_fail ("!(Flags & RegState::Define) && \"Misleading addUse defines register, use addReg instead.\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 117, __PRETTY_FUNCTION__)); | |||
| 118 | return addReg(RegNo, Flags, SubReg); | |||
| 119 | } | |||
| 120 | ||||
| 121 | /// Add a new immediate operand. | |||
| 122 | const MachineInstrBuilder &addImm(int64_t Val) const { | |||
| 123 | MI->addOperand(*MF, MachineOperand::CreateImm(Val)); | |||
| 124 | return *this; | |||
| 125 | } | |||
| 126 | ||||
| 127 | const MachineInstrBuilder &addCImm(const ConstantInt *Val) const { | |||
| 128 | MI->addOperand(*MF, MachineOperand::CreateCImm(Val)); | |||
| 129 | return *this; | |||
| 130 | } | |||
| 131 | ||||
| 132 | const MachineInstrBuilder &addFPImm(const ConstantFP *Val) const { | |||
| 133 | MI->addOperand(*MF, MachineOperand::CreateFPImm(Val)); | |||
| 134 | return *this; | |||
| 135 | } | |||
| 136 | ||||
| 137 | const MachineInstrBuilder &addMBB(MachineBasicBlock *MBB, | |||
| 138 | unsigned TargetFlags = 0) const { | |||
| 139 | MI->addOperand(*MF, MachineOperand::CreateMBB(MBB, TargetFlags)); | |||
| 140 | return *this; | |||
| 141 | } | |||
| 142 | ||||
| 143 | const MachineInstrBuilder &addFrameIndex(int Idx) const { | |||
| 144 | MI->addOperand(*MF, MachineOperand::CreateFI(Idx)); | |||
| 145 | return *this; | |||
| 146 | } | |||
| 147 | ||||
| 148 | const MachineInstrBuilder & | |||
| 149 | addConstantPoolIndex(unsigned Idx, int Offset = 0, | |||
| 150 | unsigned TargetFlags = 0) const { | |||
| 151 | MI->addOperand(*MF, MachineOperand::CreateCPI(Idx, Offset, TargetFlags)); | |||
| 152 | return *this; | |||
| 153 | } | |||
| 154 | ||||
| 155 | const MachineInstrBuilder &addTargetIndex(unsigned Idx, int64_t Offset = 0, | |||
| 156 | unsigned TargetFlags = 0) const { | |||
| 157 | MI->addOperand(*MF, MachineOperand::CreateTargetIndex(Idx, Offset, | |||
| 158 | TargetFlags)); | |||
| 159 | return *this; | |||
| 160 | } | |||
| 161 | ||||
| 162 | const MachineInstrBuilder &addJumpTableIndex(unsigned Idx, | |||
| 163 | unsigned TargetFlags = 0) const { | |||
| 164 | MI->addOperand(*MF, MachineOperand::CreateJTI(Idx, TargetFlags)); | |||
| 165 | return *this; | |||
| 166 | } | |||
| 167 | ||||
| 168 | const MachineInstrBuilder &addGlobalAddress(const GlobalValue *GV, | |||
| 169 | int64_t Offset = 0, | |||
| 170 | unsigned TargetFlags = 0) const { | |||
| 171 | MI->addOperand(*MF, MachineOperand::CreateGA(GV, Offset, TargetFlags)); | |||
| 172 | return *this; | |||
| 173 | } | |||
| 174 | ||||
| 175 | const MachineInstrBuilder &addExternalSymbol(const char *FnName, | |||
| 176 | unsigned TargetFlags = 0) const { | |||
| 177 | MI->addOperand(*MF, MachineOperand::CreateES(FnName, TargetFlags)); | |||
| 178 | return *this; | |||
| 179 | } | |||
| 180 | ||||
| 181 | const MachineInstrBuilder &addBlockAddress(const BlockAddress *BA, | |||
| 182 | int64_t Offset = 0, | |||
| 183 | unsigned TargetFlags = 0) const { | |||
| 184 | MI->addOperand(*MF, MachineOperand::CreateBA(BA, Offset, TargetFlags)); | |||
| 185 | return *this; | |||
| 186 | } | |||
| 187 | ||||
| 188 | const MachineInstrBuilder &addRegMask(const uint32_t *Mask) const { | |||
| 189 | MI->addOperand(*MF, MachineOperand::CreateRegMask(Mask)); | |||
| 190 | return *this; | |||
| 191 | } | |||
| 192 | ||||
| 193 | const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const { | |||
| 194 | MI->addMemOperand(*MF, MMO); | |||
| 195 | return *this; | |||
| 196 | } | |||
| 197 | ||||
| 198 | const MachineInstrBuilder & | |||
| 199 | setMemRefs(ArrayRef<MachineMemOperand *> MMOs) const { | |||
| 200 | MI->setMemRefs(*MF, MMOs); | |||
| 201 | return *this; | |||
| 202 | } | |||
| 203 | ||||
| 204 | const MachineInstrBuilder &cloneMemRefs(const MachineInstr &OtherMI) const { | |||
| 205 | MI->cloneMemRefs(*MF, OtherMI); | |||
| 206 | return *this; | |||
| 207 | } | |||
| 208 | ||||
| 209 | const MachineInstrBuilder & | |||
| 210 | cloneMergedMemRefs(ArrayRef<const MachineInstr *> OtherMIs) const { | |||
| 211 | MI->cloneMergedMemRefs(*MF, OtherMIs); | |||
| 212 | return *this; | |||
| 213 | } | |||
| 214 | ||||
| 215 | const MachineInstrBuilder &add(const MachineOperand &MO) const { | |||
| 216 | MI->addOperand(*MF, MO); | |||
| ||||
| 217 | return *this; | |||
| 218 | } | |||
| 219 | ||||
| 220 | const MachineInstrBuilder &add(ArrayRef<MachineOperand> MOs) const { | |||
| 221 | for (const MachineOperand &MO : MOs) { | |||
| 222 | MI->addOperand(*MF, MO); | |||
| 223 | } | |||
| 224 | return *this; | |||
| 225 | } | |||
| 226 | ||||
| 227 | const MachineInstrBuilder &addMetadata(const MDNode *MD) const { | |||
| 228 | MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); | |||
| 229 | assert((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable())(((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable ()) : true) && "first MDNode argument of a DBG_VALUE not a variable" ) ? static_cast<void> (0) : __assert_fail ("(MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable()) : true) && \"first MDNode argument of a DBG_VALUE not a variable\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 231, __PRETTY_FUNCTION__)) | |||
| 230 | : true) &&(((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable ()) : true) && "first MDNode argument of a DBG_VALUE not a variable" ) ? static_cast<void> (0) : __assert_fail ("(MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable()) : true) && \"first MDNode argument of a DBG_VALUE not a variable\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 231, __PRETTY_FUNCTION__)) | |||
| 231 | "first MDNode argument of a DBG_VALUE not a variable")(((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable ()) : true) && "first MDNode argument of a DBG_VALUE not a variable" ) ? static_cast<void> (0) : __assert_fail ("(MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable()) : true) && \"first MDNode argument of a DBG_VALUE not a variable\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 231, __PRETTY_FUNCTION__)); | |||
| 232 | assert((MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel())(((MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel ()) : true) && "first MDNode argument of a DBG_LABEL not a label" ) ? static_cast<void> (0) : __assert_fail ("(MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel()) : true) && \"first MDNode argument of a DBG_LABEL not a label\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 234, __PRETTY_FUNCTION__)) | |||
| 233 | : true) &&(((MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel ()) : true) && "first MDNode argument of a DBG_LABEL not a label" ) ? static_cast<void> (0) : __assert_fail ("(MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel()) : true) && \"first MDNode argument of a DBG_LABEL not a label\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 234, __PRETTY_FUNCTION__)) | |||
| 234 | "first MDNode argument of a DBG_LABEL not a label")(((MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel ()) : true) && "first MDNode argument of a DBG_LABEL not a label" ) ? static_cast<void> (0) : __assert_fail ("(MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel()) : true) && \"first MDNode argument of a DBG_LABEL not a label\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 234, __PRETTY_FUNCTION__)); | |||
| 235 | return *this; | |||
| 236 | } | |||
| 237 | ||||
| 238 | const MachineInstrBuilder &addCFIIndex(unsigned CFIIndex) const { | |||
| 239 | MI->addOperand(*MF, MachineOperand::CreateCFIIndex(CFIIndex)); | |||
| 240 | return *this; | |||
| 241 | } | |||
| 242 | ||||
| 243 | const MachineInstrBuilder &addIntrinsicID(Intrinsic::ID ID) const { | |||
| 244 | MI->addOperand(*MF, MachineOperand::CreateIntrinsicID(ID)); | |||
| 245 | return *this; | |||
| 246 | } | |||
| 247 | ||||
| 248 | const MachineInstrBuilder &addPredicate(CmpInst::Predicate Pred) const { | |||
| 249 | MI->addOperand(*MF, MachineOperand::CreatePredicate(Pred)); | |||
| 250 | return *this; | |||
| 251 | } | |||
| 252 | ||||
| 253 | const MachineInstrBuilder &addShuffleMask(const Constant *Val) const { | |||
| 254 | MI->addOperand(*MF, MachineOperand::CreateShuffleMask(Val)); | |||
| 255 | return *this; | |||
| 256 | } | |||
| 257 | ||||
| 258 | const MachineInstrBuilder &addSym(MCSymbol *Sym, | |||
| 259 | unsigned char TargetFlags = 0) const { | |||
| 260 | MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym, TargetFlags)); | |||
| 261 | return *this; | |||
| 262 | } | |||
| 263 | ||||
| 264 | const MachineInstrBuilder &setMIFlags(unsigned Flags) const { | |||
| 265 | MI->setFlags(Flags); | |||
| 266 | return *this; | |||
| 267 | } | |||
| 268 | ||||
| 269 | const MachineInstrBuilder &setMIFlag(MachineInstr::MIFlag Flag) const { | |||
| 270 | MI->setFlag(Flag); | |||
| 271 | return *this; | |||
| 272 | } | |||
| 273 | ||||
| 274 | // Add a displacement from an existing MachineOperand with an added offset. | |||
| 275 | const MachineInstrBuilder &addDisp(const MachineOperand &Disp, int64_t off, | |||
| 276 | unsigned char TargetFlags = 0) const { | |||
| 277 | // If caller specifies new TargetFlags then use it, otherwise the | |||
| 278 | // default behavior is to copy the target flags from the existing | |||
| 279 | // MachineOperand. This means if the caller wants to clear the | |||
| 280 | // target flags it needs to do so explicitly. | |||
| 281 | if (0 == TargetFlags) | |||
| 282 | TargetFlags = Disp.getTargetFlags(); | |||
| 283 | ||||
| 284 | switch (Disp.getType()) { | |||
| 285 | default: | |||
| 286 | llvm_unreachable("Unhandled operand type in addDisp()")::llvm::llvm_unreachable_internal("Unhandled operand type in addDisp()" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 286); | |||
| 287 | case MachineOperand::MO_Immediate: | |||
| 288 | return addImm(Disp.getImm() + off); | |||
| 289 | case MachineOperand::MO_ConstantPoolIndex: | |||
| 290 | return addConstantPoolIndex(Disp.getIndex(), Disp.getOffset() + off, | |||
| 291 | TargetFlags); | |||
| 292 | case MachineOperand::MO_GlobalAddress: | |||
| 293 | return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off, | |||
| 294 | TargetFlags); | |||
| 295 | case MachineOperand::MO_BlockAddress: | |||
| 296 | return addBlockAddress(Disp.getBlockAddress(), Disp.getOffset() + off, | |||
| 297 | TargetFlags); | |||
| 298 | } | |||
| 299 | } | |||
| 300 | ||||
| 301 | /// Copy all the implicit operands from OtherMI onto this one. | |||
| 302 | const MachineInstrBuilder & | |||
| 303 | copyImplicitOps(const MachineInstr &OtherMI) const { | |||
| 304 | MI->copyImplicitOps(*MF, OtherMI); | |||
| 305 | return *this; | |||
| 306 | } | |||
| 307 | ||||
| 308 | bool constrainAllUses(const TargetInstrInfo &TII, | |||
| 309 | const TargetRegisterInfo &TRI, | |||
| 310 | const RegisterBankInfo &RBI) const { | |||
| 311 | return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); | |||
| 312 | } | |||
| 313 | }; | |||
| 314 | ||||
| 315 | /// Builder interface. Specify how to create the initial instruction itself. | |||
| 316 | inline MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, | |||
| 317 | const MCInstrDesc &MCID) { | |||
| 318 | return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL)); | |||
| 319 | } | |||
| 320 | ||||
| 321 | /// This version of the builder sets up the first operand as a | |||
| 322 | /// destination virtual register. | |||
| 323 | inline MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, | |||
| 324 | const MCInstrDesc &MCID, Register DestReg) { | |||
| 325 | return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL)) | |||
| 326 | .addReg(DestReg, RegState::Define); | |||
| 327 | } | |||
| 328 | ||||
| 329 | /// This version of the builder inserts the newly-built instruction before | |||
| 330 | /// the given position in the given MachineBasicBlock, and sets up the first | |||
| 331 | /// operand as a destination virtual register. | |||
| 332 | inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, | |||
| 333 | MachineBasicBlock::iterator I, | |||
| 334 | const DebugLoc &DL, const MCInstrDesc &MCID, | |||
| 335 | Register DestReg) { | |||
| 336 | MachineFunction &MF = *BB.getParent(); | |||
| 337 | MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); | |||
| 338 | BB.insert(I, MI); | |||
| 339 | return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define); | |||
| 340 | } | |||
| 341 | ||||
| 342 | /// This version of the builder inserts the newly-built instruction before | |||
| 343 | /// the given position in the given MachineBasicBlock, and sets up the first | |||
| 344 | /// operand as a destination virtual register. | |||
| 345 | /// | |||
| 346 | /// If \c I is inside a bundle, then the newly inserted \a MachineInstr is | |||
| 347 | /// added to the same bundle. | |||
| 348 | inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, | |||
| 349 | MachineBasicBlock::instr_iterator I, | |||
| 350 | const DebugLoc &DL, const MCInstrDesc &MCID, | |||
| 351 | Register DestReg) { | |||
| 352 | MachineFunction &MF = *BB.getParent(); | |||
| 353 | MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); | |||
| 354 | BB.insert(I, MI); | |||
| 355 | return MachineInstrBuilder(MF, MI).addReg(DestReg, RegState::Define); | |||
| 356 | } | |||
| 357 | ||||
| 358 | inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr &I, | |||
| 359 | const DebugLoc &DL, const MCInstrDesc &MCID, | |||
| 360 | Register DestReg) { | |||
| 361 | // Calling the overload for instr_iterator is always correct. However, the | |||
| 362 | // definition is not available in headers, so inline the check. | |||
| 363 | if (I.isInsideBundle()) | |||
| 364 | return BuildMI(BB, MachineBasicBlock::instr_iterator(I), DL, MCID, DestReg); | |||
| 365 | return BuildMI(BB, MachineBasicBlock::iterator(I), DL, MCID, DestReg); | |||
| 366 | } | |||
| 367 | ||||
| 368 | inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr *I, | |||
| 369 | const DebugLoc &DL, const MCInstrDesc &MCID, | |||
| 370 | Register DestReg) { | |||
| 371 | return BuildMI(BB, *I, DL, MCID, DestReg); | |||
| 372 | } | |||
| 373 | ||||
| 374 | /// This version of the builder inserts the newly-built instruction before the | |||
| 375 | /// given position in the given MachineBasicBlock, and does NOT take a | |||
| 376 | /// destination register. | |||
| 377 | inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, | |||
| 378 | MachineBasicBlock::iterator I, | |||
| 379 | const DebugLoc &DL, | |||
| 380 | const MCInstrDesc &MCID) { | |||
| 381 | MachineFunction &MF = *BB.getParent(); | |||
| 382 | MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); | |||
| 383 | BB.insert(I, MI); | |||
| 384 | return MachineInstrBuilder(MF, MI); | |||
| 385 | } | |||
| 386 | ||||
| 387 | inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, | |||
| 388 | MachineBasicBlock::instr_iterator I, | |||
| 389 | const DebugLoc &DL, | |||
| 390 | const MCInstrDesc &MCID) { | |||
| 391 | MachineFunction &MF = *BB.getParent(); | |||
| 392 | MachineInstr *MI = MF.CreateMachineInstr(MCID, DL); | |||
| 393 | BB.insert(I, MI); | |||
| 394 | return MachineInstrBuilder(MF, MI); | |||
| 395 | } | |||
| 396 | ||||
| 397 | inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr &I, | |||
| 398 | const DebugLoc &DL, | |||
| 399 | const MCInstrDesc &MCID) { | |||
| 400 | // Calling the overload for instr_iterator is always correct. However, the | |||
| 401 | // definition is not available in headers, so inline the check. | |||
| 402 | if (I.isInsideBundle()) | |||
| 403 | return BuildMI(BB, MachineBasicBlock::instr_iterator(I), DL, MCID); | |||
| 404 | return BuildMI(BB, MachineBasicBlock::iterator(I), DL, MCID); | |||
| 405 | } | |||
| 406 | ||||
| 407 | inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineInstr *I, | |||
| 408 | const DebugLoc &DL, | |||
| 409 | const MCInstrDesc &MCID) { | |||
| 410 | return BuildMI(BB, *I, DL, MCID); | |||
| 411 | } | |||
| 412 | ||||
| 413 | /// This version of the builder inserts the newly-built instruction at the end | |||
| 414 | /// of the given MachineBasicBlock, and does NOT take a destination register. | |||
| 415 | inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, const DebugLoc &DL, | |||
| 416 | const MCInstrDesc &MCID) { | |||
| 417 | return BuildMI(*BB, BB->end(), DL, MCID); | |||
| 418 | } | |||
| 419 | ||||
| 420 | /// This version of the builder inserts the newly-built instruction at the | |||
| 421 | /// end of the given MachineBasicBlock, and sets up the first operand as a | |||
| 422 | /// destination virtual register. | |||
| 423 | inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, const DebugLoc &DL, | |||
| 424 | const MCInstrDesc &MCID, Register DestReg) { | |||
| 425 | return BuildMI(*BB, BB->end(), DL, MCID, DestReg); | |||
| 426 | } | |||
| 427 | ||||
| 428 | /// This version of the builder builds a DBG_VALUE intrinsic | |||
| 429 | /// for either a value in a register or a register-indirect | |||
| 430 | /// address. The convention is that a DBG_VALUE is indirect iff the | |||
| 431 | /// second operand is an immediate. | |||
| 432 | MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, | |||
| 433 | const MCInstrDesc &MCID, bool IsIndirect, | |||
| 434 | Register Reg, const MDNode *Variable, | |||
| 435 | const MDNode *Expr); | |||
| 436 | ||||
| 437 | /// This version of the builder builds a DBG_VALUE intrinsic | |||
| 438 | /// for a MachineOperand. | |||
| 439 | MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, | |||
| 440 | const MCInstrDesc &MCID, bool IsIndirect, | |||
| 441 | MachineOperand &MO, const MDNode *Variable, | |||
| 442 | const MDNode *Expr); | |||
| 443 | ||||
| 444 | /// This version of the builder builds a DBG_VALUE intrinsic | |||
| 445 | /// for either a value in a register or a register-indirect | |||
| 446 | /// address and inserts it at position I. | |||
| 447 | MachineInstrBuilder BuildMI(MachineBasicBlock &BB, | |||
| 448 | MachineBasicBlock::iterator I, const DebugLoc &DL, | |||
| 449 | const MCInstrDesc &MCID, bool IsIndirect, | |||
| 450 | Register Reg, const MDNode *Variable, | |||
| 451 | const MDNode *Expr); | |||
| 452 | ||||
| 453 | /// This version of the builder builds a DBG_VALUE intrinsic | |||
| 454 | /// for a machine operand and inserts it at position I. | |||
| 455 | MachineInstrBuilder BuildMI(MachineBasicBlock &BB, | |||
| 456 | MachineBasicBlock::iterator I, const DebugLoc &DL, | |||
| 457 | const MCInstrDesc &MCID, bool IsIndirect, | |||
| 458 | MachineOperand &MO, const MDNode *Variable, | |||
| 459 | const MDNode *Expr); | |||
| 460 | ||||
| 461 | /// Clone a DBG_VALUE whose value has been spilled to FrameIndex. | |||
| 462 | MachineInstr *buildDbgValueForSpill(MachineBasicBlock &BB, | |||
| 463 | MachineBasicBlock::iterator I, | |||
| 464 | const MachineInstr &Orig, int FrameIndex); | |||
| 465 | ||||
| 466 | /// Update a DBG_VALUE whose value has been spilled to FrameIndex. Useful when | |||
| 467 | /// modifying an instruction in place while iterating over a basic block. | |||
| 468 | void updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex); | |||
| 469 | ||||
| 470 | inline unsigned getDefRegState(bool B) { | |||
| 471 | return B ? RegState::Define : 0; | |||
| 472 | } | |||
| 473 | inline unsigned getImplRegState(bool B) { | |||
| 474 | return B ? RegState::Implicit : 0; | |||
| 475 | } | |||
| 476 | inline unsigned getKillRegState(bool B) { | |||
| 477 | return B ? RegState::Kill : 0; | |||
| 478 | } | |||
| 479 | inline unsigned getDeadRegState(bool B) { | |||
| 480 | return B ? RegState::Dead : 0; | |||
| 481 | } | |||
| 482 | inline unsigned getUndefRegState(bool B) { | |||
| 483 | return B ? RegState::Undef : 0; | |||
| 484 | } | |||
| 485 | inline unsigned getInternalReadRegState(bool B) { | |||
| 486 | return B ? RegState::InternalRead : 0; | |||
| 487 | } | |||
| 488 | inline unsigned getDebugRegState(bool B) { | |||
| 489 | return B ? RegState::Debug : 0; | |||
| 490 | } | |||
| 491 | inline unsigned getRenamableRegState(bool B) { | |||
| 492 | return B ? RegState::Renamable : 0; | |||
| 493 | } | |||
| 494 | ||||
| 495 | /// Get all register state flags from machine operand \p RegOp. | |||
| 496 | inline unsigned getRegState(const MachineOperand &RegOp) { | |||
| 497 | assert(RegOp.isReg() && "Not a register operand")((RegOp.isReg() && "Not a register operand") ? static_cast <void> (0) : __assert_fail ("RegOp.isReg() && \"Not a register operand\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 497, __PRETTY_FUNCTION__)); | |||
| 498 | return getDefRegState(RegOp.isDef()) | getImplRegState(RegOp.isImplicit()) | | |||
| 499 | getKillRegState(RegOp.isKill()) | getDeadRegState(RegOp.isDead()) | | |||
| 500 | getUndefRegState(RegOp.isUndef()) | | |||
| 501 | getInternalReadRegState(RegOp.isInternalRead()) | | |||
| 502 | getDebugRegState(RegOp.isDebug()) | | |||
| 503 | getRenamableRegState(Register::isPhysicalRegister(RegOp.getReg()) && | |||
| 504 | RegOp.isRenamable()); | |||
| 505 | } | |||
| 506 | ||||
| 507 | /// Helper class for constructing bundles of MachineInstrs. | |||
| 508 | /// | |||
| 509 | /// MIBundleBuilder can create a bundle from scratch by inserting new | |||
| 510 | /// MachineInstrs one at a time, or it can create a bundle from a sequence of | |||
| 511 | /// existing MachineInstrs in a basic block. | |||
| 512 | class MIBundleBuilder { | |||
| 513 | MachineBasicBlock &MBB; | |||
| 514 | MachineBasicBlock::instr_iterator Begin; | |||
| 515 | MachineBasicBlock::instr_iterator End; | |||
| 516 | ||||
| 517 | public: | |||
| 518 | /// Create an MIBundleBuilder that inserts instructions into a new bundle in | |||
| 519 | /// BB above the bundle or instruction at Pos. | |||
| 520 | MIBundleBuilder(MachineBasicBlock &BB, MachineBasicBlock::iterator Pos) | |||
| 521 | : MBB(BB), Begin(Pos.getInstrIterator()), End(Begin) {} | |||
| 522 | ||||
| 523 | /// Create a bundle from the sequence of instructions between B and E. | |||
| 524 | MIBundleBuilder(MachineBasicBlock &BB, MachineBasicBlock::iterator B, | |||
| 525 | MachineBasicBlock::iterator E) | |||
| 526 | : MBB(BB), Begin(B.getInstrIterator()), End(E.getInstrIterator()) { | |||
| 527 | assert(B != E && "No instructions to bundle")((B != E && "No instructions to bundle") ? static_cast <void> (0) : __assert_fail ("B != E && \"No instructions to bundle\"" , "/build/llvm-toolchain-snapshot-10~++20200112100611+7fa5290d5bd/llvm/include/llvm/CodeGen/MachineInstrBuilder.h" , 527, __PRETTY_FUNCTION__)); | |||
| 528 | ++B; | |||
| 529 | while (B != E) { | |||
| 530 | MachineInstr &MI = *B; | |||
| 531 | ++B; | |||
| 532 | MI.bundleWithPred(); | |||
| 533 | } | |||
| 534 | } | |||
| 535 | ||||
| 536 | /// Create an MIBundleBuilder representing an existing instruction or bundle | |||
| 537 | /// that has MI as its head. | |||
| 538 | explicit MIBundleBuilder(MachineInstr *MI) | |||
| 539 | : MBB(*MI->getParent()), Begin(MI), | |||
| 540 | End(getBundleEnd(MI->getIterator())) {} | |||
| 541 | ||||
| 542 | /// Return a reference to the basic block containing this bundle. | |||
| 543 | MachineBasicBlock &getMBB() const { return MBB; } | |||
| 544 | ||||
| 545 | /// Return true if no instructions have been inserted in this bundle yet. | |||
| 546 | /// Empty bundles aren't representable in a MachineBasicBlock. | |||
| 547 | bool empty() const { return Begin == End; } | |||
| 548 | ||||
| 549 | /// Return an iterator to the first bundled instruction. | |||
| 550 | MachineBasicBlock::instr_iterator begin() const { return Begin; } | |||
| 551 | ||||
| 552 | /// Return an iterator beyond the last bundled instruction. | |||
| 553 | MachineBasicBlock::instr_iterator end() const { return End; } | |||
| 554 | ||||
| 555 | /// Insert MI into this bundle before I which must point to an instruction in | |||
| 556 | /// the bundle, or end(). | |||
| 557 | MIBundleBuilder &insert(MachineBasicBlock::instr_iterator I, | |||
| 558 | MachineInstr *MI) { | |||
| 559 | MBB.insert(I, MI); | |||
| 560 | if (I == Begin) { | |||
| 561 | if (!empty()) | |||
| 562 | MI->bundleWithSucc(); | |||
| 563 | Begin = MI->getIterator(); | |||
| 564 | return *this; | |||
| 565 | } | |||
| 566 | if (I == End) { | |||
| 567 | MI->bundleWithPred(); | |||
| 568 | return *this; | |||
| 569 | } | |||
| 570 | // MI was inserted in the middle of the bundle, so its neighbors' flags are | |||
| 571 | // already fine. Update MI's bundle flags manually. | |||
| 572 | MI->setFlag(MachineInstr::BundledPred); | |||
| 573 | MI->setFlag(MachineInstr::BundledSucc); | |||
| 574 | return *this; | |||
| 575 | } | |||
| 576 | ||||
| 577 | /// Insert MI into MBB by prepending it to the instructions in the bundle. | |||
| 578 | /// MI will become the first instruction in the bundle. | |||
| 579 | MIBundleBuilder &prepend(MachineInstr *MI) { | |||
| 580 | return insert(begin(), MI); | |||
| 581 | } | |||
| 582 | ||||
| 583 | /// Insert MI into MBB by appending it to the instructions in the bundle. | |||
| 584 | /// MI will become the last instruction in the bundle. | |||
| 585 | MIBundleBuilder &append(MachineInstr *MI) { | |||
| 586 | return insert(end(), MI); | |||
| 587 | } | |||
| 588 | }; | |||
| 589 | ||||
| 590 | } // end namespace llvm | |||
| 591 | ||||
| 592 | #endif // LLVM_CODEGEN_MACHINEINSTRBUILDER_H |