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 |