/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- HexagonInstrInfo.cpp - Hexagon Instruction Information -------------===// |
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 contains the Hexagon implementation of the TargetInstrInfo class. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "HexagonInstrInfo.h" |
14 | | #include "Hexagon.h" |
15 | | #include "HexagonFrameLowering.h" |
16 | | #include "HexagonHazardRecognizer.h" |
17 | | #include "HexagonRegisterInfo.h" |
18 | | #include "HexagonSubtarget.h" |
19 | | #include "llvm/ADT/ArrayRef.h" |
20 | | #include "llvm/ADT/SmallPtrSet.h" |
21 | | #include "llvm/ADT/SmallVector.h" |
22 | | #include "llvm/ADT/StringRef.h" |
23 | | #include "llvm/CodeGen/DFAPacketizer.h" |
24 | | #include "llvm/CodeGen/LivePhysRegs.h" |
25 | | #include "llvm/CodeGen/MachineBasicBlock.h" |
26 | | #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" |
27 | | #include "llvm/CodeGen/MachineFrameInfo.h" |
28 | | #include "llvm/CodeGen/MachineFunction.h" |
29 | | #include "llvm/CodeGen/MachineInstr.h" |
30 | | #include "llvm/CodeGen/MachineInstrBuilder.h" |
31 | | #include "llvm/CodeGen/MachineInstrBundle.h" |
32 | | #include "llvm/CodeGen/MachineLoopInfo.h" |
33 | | #include "llvm/CodeGen/MachineMemOperand.h" |
34 | | #include "llvm/CodeGen/MachineOperand.h" |
35 | | #include "llvm/CodeGen/MachineRegisterInfo.h" |
36 | | #include "llvm/CodeGen/ScheduleDAG.h" |
37 | | #include "llvm/CodeGen/TargetInstrInfo.h" |
38 | | #include "llvm/CodeGen/TargetOpcodes.h" |
39 | | #include "llvm/CodeGen/TargetRegisterInfo.h" |
40 | | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
41 | | #include "llvm/IR/DebugLoc.h" |
42 | | #include "llvm/MC/MCAsmInfo.h" |
43 | | #include "llvm/MC/MCInstrDesc.h" |
44 | | #include "llvm/MC/MCInstrItineraries.h" |
45 | | #include "llvm/MC/MCRegisterInfo.h" |
46 | | #include "llvm/Support/BranchProbability.h" |
47 | | #include "llvm/Support/CommandLine.h" |
48 | | #include "llvm/Support/Debug.h" |
49 | | #include "llvm/Support/ErrorHandling.h" |
50 | | #include "llvm/Support/MachineValueType.h" |
51 | | #include "llvm/Support/MathExtras.h" |
52 | | #include "llvm/Support/raw_ostream.h" |
53 | | #include "llvm/Target/TargetMachine.h" |
54 | | #include <cassert> |
55 | | #include <cctype> |
56 | | #include <cstdint> |
57 | | #include <cstring> |
58 | | #include <iterator> |
59 | | #include <string> |
60 | | #include <utility> |
61 | | |
62 | | using namespace llvm; |
63 | | |
64 | | #define DEBUG_TYPE "hexagon-instrinfo" |
65 | | |
66 | | #define GET_INSTRINFO_CTOR_DTOR |
67 | | #define GET_INSTRMAP_INFO |
68 | | #include "HexagonDepTimingClasses.h" |
69 | | #include "HexagonGenDFAPacketizer.inc" |
70 | | #include "HexagonGenInstrInfo.inc" |
71 | | |
72 | | cl::opt<bool> ScheduleInlineAsm("hexagon-sched-inline-asm", cl::Hidden, |
73 | | cl::init(false), cl::desc("Do not consider inline-asm a scheduling/" |
74 | | "packetization boundary.")); |
75 | | |
76 | | static cl::opt<bool> EnableBranchPrediction("hexagon-enable-branch-prediction", |
77 | | cl::Hidden, cl::init(true), cl::desc("Enable branch prediction")); |
78 | | |
79 | | static cl::opt<bool> DisableNVSchedule("disable-hexagon-nv-schedule", |
80 | | cl::Hidden, cl::ZeroOrMore, cl::init(false), |
81 | | cl::desc("Disable schedule adjustment for new value stores.")); |
82 | | |
83 | | static cl::opt<bool> EnableTimingClassLatency( |
84 | | "enable-timing-class-latency", cl::Hidden, cl::init(false), |
85 | | cl::desc("Enable timing class latency")); |
86 | | |
87 | | static cl::opt<bool> EnableALUForwarding( |
88 | | "enable-alu-forwarding", cl::Hidden, cl::init(true), |
89 | | cl::desc("Enable vec alu forwarding")); |
90 | | |
91 | | static cl::opt<bool> EnableACCForwarding( |
92 | | "enable-acc-forwarding", cl::Hidden, cl::init(true), |
93 | | cl::desc("Enable vec acc forwarding")); |
94 | | |
95 | | static cl::opt<bool> BranchRelaxAsmLarge("branch-relax-asm-large", |
96 | | cl::init(true), cl::Hidden, cl::ZeroOrMore, cl::desc("branch relax asm")); |
97 | | |
98 | | static cl::opt<bool> UseDFAHazardRec("dfa-hazard-rec", |
99 | | cl::init(true), cl::Hidden, cl::ZeroOrMore, |
100 | | cl::desc("Use the DFA based hazard recognizer.")); |
101 | | |
102 | | /// Constants for Hexagon instructions. |
103 | | const int Hexagon_MEMW_OFFSET_MAX = 4095; |
104 | | const int Hexagon_MEMW_OFFSET_MIN = -4096; |
105 | | const int Hexagon_MEMD_OFFSET_MAX = 8191; |
106 | | const int Hexagon_MEMD_OFFSET_MIN = -8192; |
107 | | const int Hexagon_MEMH_OFFSET_MAX = 2047; |
108 | | const int Hexagon_MEMH_OFFSET_MIN = -2048; |
109 | | const int Hexagon_MEMB_OFFSET_MAX = 1023; |
110 | | const int Hexagon_MEMB_OFFSET_MIN = -1024; |
111 | | const int Hexagon_ADDI_OFFSET_MAX = 32767; |
112 | | const int Hexagon_ADDI_OFFSET_MIN = -32768; |
113 | | |
114 | | // Pin the vtable to this file. |
115 | 0 | void HexagonInstrInfo::anchor() {} |
116 | | |
117 | | HexagonInstrInfo::HexagonInstrInfo(HexagonSubtarget &ST) |
118 | | : HexagonGenInstrInfo(Hexagon::ADJCALLSTACKDOWN, Hexagon::ADJCALLSTACKUP), |
119 | 1.01k | Subtarget(ST) {} |
120 | | |
121 | 0 | static bool isIntRegForSubInst(unsigned Reg) { |
122 | 0 | return (Reg >= Hexagon::R0 && Reg <= Hexagon::R7) || |
123 | 0 | (Reg >= Hexagon::R16 && Reg <= Hexagon::R23); |
124 | 0 | } |
125 | | |
126 | 0 | static bool isDblRegForSubInst(unsigned Reg, const HexagonRegisterInfo &HRI) { |
127 | 0 | return isIntRegForSubInst(HRI.getSubReg(Reg, Hexagon::isub_lo)) && |
128 | 0 | isIntRegForSubInst(HRI.getSubReg(Reg, Hexagon::isub_hi)); |
129 | 0 | } |
130 | | |
131 | | /// Calculate number of instructions excluding the debug instructions. |
132 | | static unsigned nonDbgMICount(MachineBasicBlock::const_instr_iterator MIB, |
133 | 4.94k | MachineBasicBlock::const_instr_iterator MIE) { |
134 | 4.94k | unsigned Count = 0; |
135 | 29.3k | for (; MIB != MIE; ++MIB24.4k ) { |
136 | 24.4k | if (!MIB->isDebugInstr()) |
137 | 24.4k | ++Count; |
138 | 24.4k | } |
139 | 4.94k | return Count; |
140 | 4.94k | } |
141 | | |
142 | | /// Find the hardware loop instruction used to set-up the specified loop. |
143 | | /// On Hexagon, we have two instructions used to set-up the hardware loop |
144 | | /// (LOOP0, LOOP1) with corresponding endloop (ENDLOOP0, ENDLOOP1) instructions |
145 | | /// to indicate the end of a loop. |
146 | | MachineInstr *HexagonInstrInfo::findLoopInstr(MachineBasicBlock *BB, |
147 | | unsigned EndLoopOp, MachineBasicBlock *TargetBB, |
148 | 555 | SmallPtrSet<MachineBasicBlock *, 8> &Visited) const { |
149 | 555 | unsigned LOOPi; |
150 | 555 | unsigned LOOPr; |
151 | 555 | if (EndLoopOp == Hexagon::ENDLOOP0) { |
152 | 548 | LOOPi = Hexagon::J2_loop0i; |
153 | 548 | LOOPr = Hexagon::J2_loop0r; |
154 | 548 | } else { // EndLoopOp == Hexagon::EndLOOP1 |
155 | 7 | LOOPi = Hexagon::J2_loop1i; |
156 | 7 | LOOPr = Hexagon::J2_loop1r; |
157 | 7 | } |
158 | 555 | |
159 | 555 | // The loop set-up instruction will be in a predecessor block |
160 | 568 | for (MachineBasicBlock *PB : BB->predecessors()) { |
161 | 568 | // If this has been visited, already skip it. |
162 | 568 | if (!Visited.insert(PB).second) |
163 | 1 | continue; |
164 | 567 | if (PB == BB) |
165 | 12 | continue; |
166 | 1.65k | for (auto I = PB->instr_rbegin(), E = PB->instr_rend(); 555 I != E; ++I1.09k ) { |
167 | 1.42k | unsigned Opc = I->getOpcode(); |
168 | 1.42k | if (Opc == LOOPi || Opc == LOOPr1.35k ) |
169 | 327 | return &*I; |
170 | 1.09k | // We've reached a different loop, which means the loop01 has been |
171 | 1.09k | // removed. |
172 | 1.09k | if (Opc == EndLoopOp && I->getOperand(0).getMBB() != TargetBB0 ) |
173 | 0 | return nullptr; |
174 | 1.09k | } |
175 | 555 | // Check the predecessors for the LOOP instruction. |
176 | 555 | if (MachineInstr *228 Loop228 = findLoopInstr(PB, EndLoopOp, TargetBB, Visited)) |
177 | 228 | return Loop; |
178 | 228 | } |
179 | 555 | return nullptr0 ; |
180 | 555 | } |
181 | | |
182 | | /// Gather register def/uses from MI. |
183 | | /// This treats possible (predicated) defs as actually happening ones |
184 | | /// (conservatively). |
185 | | static inline void parseOperands(const MachineInstr &MI, |
186 | 0 | SmallVector<unsigned, 4> &Defs, SmallVector<unsigned, 8> &Uses) { |
187 | 0 | Defs.clear(); |
188 | 0 | Uses.clear(); |
189 | 0 |
|
190 | 0 | for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { |
191 | 0 | const MachineOperand &MO = MI.getOperand(i); |
192 | 0 |
|
193 | 0 | if (!MO.isReg()) |
194 | 0 | continue; |
195 | 0 | |
196 | 0 | unsigned Reg = MO.getReg(); |
197 | 0 | if (!Reg) |
198 | 0 | continue; |
199 | 0 | |
200 | 0 | if (MO.isUse()) |
201 | 0 | Uses.push_back(MO.getReg()); |
202 | 0 |
|
203 | 0 | if (MO.isDef()) |
204 | 0 | Defs.push_back(MO.getReg()); |
205 | 0 | } |
206 | 0 | } |
207 | | |
208 | | // Position dependent, so check twice for swap. |
209 | 0 | static bool isDuplexPairMatch(unsigned Ga, unsigned Gb) { |
210 | 0 | switch (Ga) { |
211 | 0 | case HexagonII::HSIG_None: |
212 | 0 | default: |
213 | 0 | return false; |
214 | 0 | case HexagonII::HSIG_L1: |
215 | 0 | return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_A); |
216 | 0 | case HexagonII::HSIG_L2: |
217 | 0 | return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 || |
218 | 0 | Gb == HexagonII::HSIG_A); |
219 | 0 | case HexagonII::HSIG_S1: |
220 | 0 | return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 || |
221 | 0 | Gb == HexagonII::HSIG_S1 || Gb == HexagonII::HSIG_A); |
222 | 0 | case HexagonII::HSIG_S2: |
223 | 0 | return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 || |
224 | 0 | Gb == HexagonII::HSIG_S1 || Gb == HexagonII::HSIG_S2 || |
225 | 0 | Gb == HexagonII::HSIG_A); |
226 | 0 | case HexagonII::HSIG_A: |
227 | 0 | return (Gb == HexagonII::HSIG_A); |
228 | 0 | case HexagonII::HSIG_Compound: |
229 | 0 | return (Gb == HexagonII::HSIG_Compound); |
230 | 0 | } |
231 | 0 | return false; |
232 | 0 | } |
233 | | |
234 | | /// isLoadFromStackSlot - If the specified machine instruction is a direct |
235 | | /// load from a stack slot, return the virtual or physical register number of |
236 | | /// the destination along with the FrameIndex of the loaded stack slot. If |
237 | | /// not, return 0. This predicate must return 0 if the instruction has |
238 | | /// any side effects other than loading from the stack slot. |
239 | | unsigned HexagonInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, |
240 | 43.1k | int &FrameIndex) const { |
241 | 43.1k | switch (MI.getOpcode()) { |
242 | 43.1k | default: |
243 | 39.3k | break; |
244 | 43.1k | case Hexagon::L2_loadri_io: |
245 | 3.76k | case Hexagon::L2_loadrd_io: |
246 | 3.76k | case Hexagon::V6_vL32b_ai: |
247 | 3.76k | case Hexagon::V6_vL32b_nt_ai: |
248 | 3.76k | case Hexagon::V6_vL32Ub_ai: |
249 | 3.76k | case Hexagon::LDriw_pred: |
250 | 3.76k | case Hexagon::LDriw_ctr: |
251 | 3.76k | case Hexagon::PS_vloadrq_ai: |
252 | 3.76k | case Hexagon::PS_vloadrw_ai: |
253 | 3.76k | case Hexagon::PS_vloadrw_nt_ai: { |
254 | 3.76k | const MachineOperand OpFI = MI.getOperand(1); |
255 | 3.76k | if (!OpFI.isFI()) |
256 | 2.40k | return 0; |
257 | 1.36k | const MachineOperand OpOff = MI.getOperand(2); |
258 | 1.36k | if (!OpOff.isImm() || OpOff.getImm() != 0) |
259 | 20 | return 0; |
260 | 1.34k | FrameIndex = OpFI.getIndex(); |
261 | 1.34k | return MI.getOperand(0).getReg(); |
262 | 1.34k | } |
263 | 1.34k | |
264 | 1.34k | case Hexagon::L2_ploadrit_io: |
265 | 1 | case Hexagon::L2_ploadrif_io: |
266 | 1 | case Hexagon::L2_ploadrdt_io: |
267 | 1 | case Hexagon::L2_ploadrdf_io: { |
268 | 1 | const MachineOperand OpFI = MI.getOperand(2); |
269 | 1 | if (!OpFI.isFI()) |
270 | 1 | return 0; |
271 | 0 | const MachineOperand OpOff = MI.getOperand(3); |
272 | 0 | if (!OpOff.isImm() || OpOff.getImm() != 0) |
273 | 0 | return 0; |
274 | 0 | FrameIndex = OpFI.getIndex(); |
275 | 0 | return MI.getOperand(0).getReg(); |
276 | 0 | } |
277 | 39.3k | } |
278 | 39.3k | |
279 | 39.3k | return 0; |
280 | 39.3k | } |
281 | | |
282 | | /// isStoreToStackSlot - If the specified machine instruction is a direct |
283 | | /// store to a stack slot, return the virtual or physical register number of |
284 | | /// the source reg along with the FrameIndex of the loaded stack slot. If |
285 | | /// not, return 0. This predicate must return 0 if the instruction has |
286 | | /// any side effects other than storing to the stack slot. |
287 | | unsigned HexagonInstrInfo::isStoreToStackSlot(const MachineInstr &MI, |
288 | 34.3k | int &FrameIndex) const { |
289 | 34.3k | switch (MI.getOpcode()) { |
290 | 34.3k | default: |
291 | 32.2k | break; |
292 | 34.3k | case Hexagon::S2_storerb_io: |
293 | 2.09k | case Hexagon::S2_storerh_io: |
294 | 2.09k | case Hexagon::S2_storeri_io: |
295 | 2.09k | case Hexagon::S2_storerd_io: |
296 | 2.09k | case Hexagon::V6_vS32b_ai: |
297 | 2.09k | case Hexagon::V6_vS32Ub_ai: |
298 | 2.09k | case Hexagon::STriw_pred: |
299 | 2.09k | case Hexagon::STriw_ctr: |
300 | 2.09k | case Hexagon::PS_vstorerq_ai: |
301 | 2.09k | case Hexagon::PS_vstorerw_ai: { |
302 | 2.09k | const MachineOperand &OpFI = MI.getOperand(0); |
303 | 2.09k | if (!OpFI.isFI()) |
304 | 1.60k | return 0; |
305 | 498 | const MachineOperand &OpOff = MI.getOperand(1); |
306 | 498 | if (!OpOff.isImm() || OpOff.getImm() != 0) |
307 | 41 | return 0; |
308 | 457 | FrameIndex = OpFI.getIndex(); |
309 | 457 | return MI.getOperand(2).getReg(); |
310 | 457 | } |
311 | 457 | |
312 | 457 | case Hexagon::S2_pstorerbt_io: |
313 | 14 | case Hexagon::S2_pstorerbf_io: |
314 | 14 | case Hexagon::S2_pstorerht_io: |
315 | 14 | case Hexagon::S2_pstorerhf_io: |
316 | 14 | case Hexagon::S2_pstorerit_io: |
317 | 14 | case Hexagon::S2_pstorerif_io: |
318 | 14 | case Hexagon::S2_pstorerdt_io: |
319 | 14 | case Hexagon::S2_pstorerdf_io: { |
320 | 14 | const MachineOperand &OpFI = MI.getOperand(1); |
321 | 14 | if (!OpFI.isFI()) |
322 | 14 | return 0; |
323 | 0 | const MachineOperand &OpOff = MI.getOperand(2); |
324 | 0 | if (!OpOff.isImm() || OpOff.getImm() != 0) |
325 | 0 | return 0; |
326 | 0 | FrameIndex = OpFI.getIndex(); |
327 | 0 | return MI.getOperand(3).getReg(); |
328 | 0 | } |
329 | 32.2k | } |
330 | 32.2k | |
331 | 32.2k | return 0; |
332 | 32.2k | } |
333 | | |
334 | | /// This function checks if the instruction or bundle of instructions |
335 | | /// has load from stack slot and returns frameindex and machine memory |
336 | | /// operand of that instruction if true. |
337 | | bool HexagonInstrInfo::hasLoadFromStackSlot( |
338 | | const MachineInstr &MI, |
339 | 31.0k | SmallVectorImpl<const MachineMemOperand *> &Accesses) const { |
340 | 31.0k | if (MI.isBundle()) { |
341 | 8.80k | const MachineBasicBlock *MBB = MI.getParent(); |
342 | 8.80k | MachineBasicBlock::const_instr_iterator MII = MI.getIterator(); |
343 | 29.6k | for (++MII; MII != MBB->instr_end() && MII->isInsideBundle()26.0k ; ++MII20.8k ) |
344 | 21.1k | if (TargetInstrInfo::hasLoadFromStackSlot(*MII, Accesses)) |
345 | 250 | return true; |
346 | 8.80k | return false8.55k ; |
347 | 22.2k | } |
348 | 22.2k | |
349 | 22.2k | return TargetInstrInfo::hasLoadFromStackSlot(MI, Accesses); |
350 | 22.2k | } |
351 | | |
352 | | /// This function checks if the instruction or bundle of instructions |
353 | | /// has store to stack slot and returns frameindex and machine memory |
354 | | /// operand of that instruction if true. |
355 | | bool HexagonInstrInfo::hasStoreToStackSlot( |
356 | | const MachineInstr &MI, |
357 | 30.7k | SmallVectorImpl<const MachineMemOperand *> &Accesses) const { |
358 | 30.7k | if (MI.isBundle()) { |
359 | 8.55k | const MachineBasicBlock *MBB = MI.getParent(); |
360 | 8.55k | MachineBasicBlock::const_instr_iterator MII = MI.getIterator(); |
361 | 28.7k | for (++MII; MII != MBB->instr_end() && MII->isInsideBundle()25.1k ; ++MII20.2k ) |
362 | 20.4k | if (TargetInstrInfo::hasStoreToStackSlot(*MII, Accesses)) |
363 | 235 | return true; |
364 | 8.55k | return false8.31k ; |
365 | 22.1k | } |
366 | 22.1k | |
367 | 22.1k | return TargetInstrInfo::hasStoreToStackSlot(MI, Accesses); |
368 | 22.1k | } |
369 | | |
370 | | /// This function can analyze one/two way branching only and should (mostly) be |
371 | | /// called by target independent side. |
372 | | /// First entry is always the opcode of the branching instruction, except when |
373 | | /// the Cond vector is supposed to be empty, e.g., when AnalyzeBranch fails, a |
374 | | /// BB with only unconditional jump. Subsequent entries depend upon the opcode, |
375 | | /// e.g. Jump_c p will have |
376 | | /// Cond[0] = Jump_c |
377 | | /// Cond[1] = p |
378 | | /// HW-loop ENDLOOP: |
379 | | /// Cond[0] = ENDLOOP |
380 | | /// Cond[1] = MBB |
381 | | /// New value jump: |
382 | | /// Cond[0] = Hexagon::CMPEQri_f_Jumpnv_t_V4 -- specific opcode |
383 | | /// Cond[1] = R |
384 | | /// Cond[2] = Imm |
385 | | bool HexagonInstrInfo::analyzeBranch(MachineBasicBlock &MBB, |
386 | | MachineBasicBlock *&TBB, |
387 | | MachineBasicBlock *&FBB, |
388 | | SmallVectorImpl<MachineOperand> &Cond, |
389 | 76.9k | bool AllowModify) const { |
390 | 76.9k | TBB = nullptr; |
391 | 76.9k | FBB = nullptr; |
392 | 76.9k | Cond.clear(); |
393 | 76.9k | |
394 | 76.9k | // If the block has no terminators, it just falls into the block after it. |
395 | 76.9k | MachineBasicBlock::instr_iterator I = MBB.instr_end(); |
396 | 76.9k | if (I == MBB.instr_begin()) |
397 | 1.25k | return false; |
398 | 75.6k | |
399 | 75.6k | // A basic block may looks like this: |
400 | 75.6k | // |
401 | 75.6k | // [ insn |
402 | 75.6k | // EH_LABEL |
403 | 75.6k | // insn |
404 | 75.6k | // insn |
405 | 75.6k | // insn |
406 | 75.6k | // EH_LABEL |
407 | 75.6k | // insn ] |
408 | 75.6k | // |
409 | 75.6k | // It has two succs but does not have a terminator |
410 | 75.6k | // Don't know how to handle it. |
411 | 453k | do 75.6k { |
412 | 453k | --I; |
413 | 453k | if (I->isEHLabel()) |
414 | 500 | // Don't analyze EH branches. |
415 | 500 | return true; |
416 | 453k | } while (I != MBB.instr_begin()); |
417 | 75.6k | |
418 | 75.6k | I = MBB.instr_end(); |
419 | 75.1k | --I; |
420 | 75.1k | |
421 | 75.1k | while (I->isDebugInstr()) { |
422 | 14 | if (I == MBB.instr_begin()) |
423 | 0 | return false; |
424 | 14 | --I; |
425 | 14 | } |
426 | 75.1k | |
427 | 75.1k | bool JumpToBlock = I->getOpcode() == Hexagon::J2_jump && |
428 | 75.1k | I->getOperand(0).isMBB()9.82k ; |
429 | 75.1k | // Delete the J2_jump if it's equivalent to a fall-through. |
430 | 75.1k | if (AllowModify && JumpToBlock41.3k && |
431 | 75.1k | MBB.isLayoutSuccessor(I->getOperand(0).getMBB())4.17k ) { |
432 | 1.00k | LLVM_DEBUG(dbgs() << "\nErasing the jump to successor block\n";); |
433 | 1.00k | I->eraseFromParent(); |
434 | 1.00k | I = MBB.instr_end(); |
435 | 1.00k | if (I == MBB.instr_begin()) |
436 | 12 | return false; |
437 | 992 | --I; |
438 | 992 | } |
439 | 75.1k | if (75.1k !isUnpredicatedTerminator(*I)75.1k ) |
440 | 15.0k | return false; |
441 | 60.0k | |
442 | 60.0k | // Get the last instruction in the block. |
443 | 60.0k | MachineInstr *LastInst = &*I; |
444 | 60.0k | MachineInstr *SecondLastInst = nullptr; |
445 | 60.0k | // Find one more terminator if present. |
446 | 367k | while (true) { |
447 | 367k | if (&*I != LastInst && !I->isBundle()307k && isUnpredicatedTerminator(*I)307k ) { |
448 | 4.46k | if (!SecondLastInst) |
449 | 4.46k | SecondLastInst = &*I; |
450 | 0 | else |
451 | 0 | // This is a third branch. |
452 | 0 | return true; |
453 | 367k | } |
454 | 367k | if (I == MBB.instr_begin()) |
455 | 60.0k | break; |
456 | 307k | --I; |
457 | 307k | } |
458 | 60.0k | |
459 | 60.0k | int LastOpcode = LastInst->getOpcode(); |
460 | 60.0k | int SecLastOpcode = SecondLastInst ? SecondLastInst->getOpcode()4.46k : 055.5k ; |
461 | 60.0k | // If the branch target is not a basic block, it could be a tail call. |
462 | 60.0k | // (It is, if the target is a function.) |
463 | 60.0k | if (LastOpcode == Hexagon::J2_jump && !LastInst->getOperand(0).isMBB()8.82k ) |
464 | 259 | return true; |
465 | 59.7k | if (SecLastOpcode == Hexagon::J2_jump && |
466 | 59.7k | !SecondLastInst->getOperand(0).isMBB()0 ) |
467 | 0 | return true; |
468 | 59.7k | |
469 | 59.7k | bool LastOpcodeHasJMP_c = PredOpcodeHasJMP_c(LastOpcode); |
470 | 59.7k | bool LastOpcodeHasNVJump = isNewValueJump(*LastInst); |
471 | 59.7k | |
472 | 59.7k | if (LastOpcodeHasJMP_c && !LastInst->getOperand(1).isMBB()20.6k ) |
473 | 0 | return true; |
474 | 59.7k | |
475 | 59.7k | // If there is only one terminator instruction, process it. |
476 | 59.7k | if (LastInst && !SecondLastInst) { |
477 | 55.3k | if (LastOpcode == Hexagon::J2_jump) { |
478 | 4.09k | TBB = LastInst->getOperand(0).getMBB(); |
479 | 4.09k | return false; |
480 | 4.09k | } |
481 | 51.2k | if (isEndLoopN(LastOpcode)) { |
482 | 5.62k | TBB = LastInst->getOperand(0).getMBB(); |
483 | 5.62k | Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); |
484 | 5.62k | Cond.push_back(LastInst->getOperand(0)); |
485 | 5.62k | return false; |
486 | 5.62k | } |
487 | 45.5k | if (LastOpcodeHasJMP_c) { |
488 | 20.6k | TBB = LastInst->getOperand(1).getMBB(); |
489 | 20.6k | Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); |
490 | 20.6k | Cond.push_back(LastInst->getOperand(0)); |
491 | 20.6k | return false; |
492 | 20.6k | } |
493 | 24.9k | // Only supporting rr/ri versions of new-value jumps. |
494 | 24.9k | if (LastOpcodeHasNVJump && (LastInst->getNumExplicitOperands() == 3)131 ) { |
495 | 131 | TBB = LastInst->getOperand(2).getMBB(); |
496 | 131 | Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); |
497 | 131 | Cond.push_back(LastInst->getOperand(0)); |
498 | 131 | Cond.push_back(LastInst->getOperand(1)); |
499 | 131 | return false; |
500 | 131 | } |
501 | 24.8k | LLVM_DEBUG(dbgs() << "\nCant analyze " << printMBBReference(MBB) |
502 | 24.8k | << " with one jump\n";); |
503 | 24.8k | // Otherwise, don't know what this is. |
504 | 24.8k | return true; |
505 | 24.8k | } |
506 | 4.46k | |
507 | 4.46k | bool SecLastOpcodeHasJMP_c = PredOpcodeHasJMP_c(SecLastOpcode); |
508 | 4.46k | bool SecLastOpcodeHasNVJump = isNewValueJump(*SecondLastInst); |
509 | 4.46k | if (SecLastOpcodeHasJMP_c && (LastOpcode == Hexagon::J2_jump)3.78k ) { |
510 | 3.78k | if (!SecondLastInst->getOperand(1).isMBB()) |
511 | 0 | return true; |
512 | 3.78k | TBB = SecondLastInst->getOperand(1).getMBB(); |
513 | 3.78k | Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode())); |
514 | 3.78k | Cond.push_back(SecondLastInst->getOperand(0)); |
515 | 3.78k | FBB = LastInst->getOperand(0).getMBB(); |
516 | 3.78k | return false; |
517 | 3.78k | } |
518 | 681 | |
519 | 681 | // Only supporting rr/ri versions of new-value jumps. |
520 | 681 | if (SecLastOpcodeHasNVJump && |
521 | 681 | (SecondLastInst->getNumExplicitOperands() == 3)4 && |
522 | 681 | (LastOpcode == Hexagon::J2_jump)4 ) { |
523 | 4 | TBB = SecondLastInst->getOperand(2).getMBB(); |
524 | 4 | Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode())); |
525 | 4 | Cond.push_back(SecondLastInst->getOperand(0)); |
526 | 4 | Cond.push_back(SecondLastInst->getOperand(1)); |
527 | 4 | FBB = LastInst->getOperand(0).getMBB(); |
528 | 4 | return false; |
529 | 4 | } |
530 | 677 | |
531 | 677 | // If the block ends with two Hexagon:JMPs, handle it. The second one is not |
532 | 677 | // executed, so remove it. |
533 | 677 | if (SecLastOpcode == Hexagon::J2_jump && LastOpcode == Hexagon::J2_jump0 ) { |
534 | 0 | TBB = SecondLastInst->getOperand(0).getMBB(); |
535 | 0 | I = LastInst->getIterator(); |
536 | 0 | if (AllowModify) |
537 | 0 | I->eraseFromParent(); |
538 | 0 | return false; |
539 | 0 | } |
540 | 677 | |
541 | 677 | // If the block ends with an ENDLOOP, and J2_jump, handle it. |
542 | 677 | if (isEndLoopN(SecLastOpcode) && LastOpcode == Hexagon::J2_jump659 ) { |
543 | 659 | TBB = SecondLastInst->getOperand(0).getMBB(); |
544 | 659 | Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode())); |
545 | 659 | Cond.push_back(SecondLastInst->getOperand(0)); |
546 | 659 | FBB = LastInst->getOperand(0).getMBB(); |
547 | 659 | return false; |
548 | 659 | } |
549 | 18 | LLVM_DEBUG(dbgs() << "\nCant analyze " << printMBBReference(MBB) |
550 | 18 | << " with two jumps";); |
551 | 18 | // Otherwise, can't handle this. |
552 | 18 | return true; |
553 | 18 | } |
554 | | |
555 | | unsigned HexagonInstrInfo::removeBranch(MachineBasicBlock &MBB, |
556 | 5.15k | int *BytesRemoved) const { |
557 | 5.15k | assert(!BytesRemoved && "code size not handled"); |
558 | 5.15k | |
559 | 5.15k | LLVM_DEBUG(dbgs() << "\nRemoving branches out of " << printMBBReference(MBB)); |
560 | 5.15k | MachineBasicBlock::iterator I = MBB.end(); |
561 | 5.15k | unsigned Count = 0; |
562 | 10.6k | while (I != MBB.begin()) { |
563 | 10.3k | --I; |
564 | 10.3k | if (I->isDebugInstr()) |
565 | 0 | continue; |
566 | 10.3k | // Only removing branches from end of MBB. |
567 | 10.3k | if (!I->isBranch()) |
568 | 4.84k | return Count; |
569 | 5.48k | if (Count && (I->getOpcode() == Hexagon::J2_jump)539 ) |
570 | 5.48k | llvm_unreachable0 ("Malformed basic block: unconditional branch not last"); |
571 | 5.48k | MBB.erase(&MBB.back()); |
572 | 5.48k | I = MBB.end(); |
573 | 5.48k | ++Count; |
574 | 5.48k | } |
575 | 5.15k | return Count313 ; |
576 | 5.15k | } |
577 | | |
578 | | unsigned HexagonInstrInfo::insertBranch(MachineBasicBlock &MBB, |
579 | | MachineBasicBlock *TBB, |
580 | | MachineBasicBlock *FBB, |
581 | | ArrayRef<MachineOperand> Cond, |
582 | | const DebugLoc &DL, |
583 | 5.31k | int *BytesAdded) const { |
584 | 5.31k | unsigned BOpc = Hexagon::J2_jump; |
585 | 5.31k | unsigned BccOpc = Hexagon::J2_jumpt; |
586 | 5.31k | assert(validateBranchCond(Cond) && "Invalid branching condition"); |
587 | 5.31k | assert(TBB && "insertBranch must not be told to insert a fallthrough"); |
588 | 5.31k | assert(!BytesAdded && "code size not handled"); |
589 | 5.31k | |
590 | 5.31k | // Check if reverseBranchCondition has asked to reverse this branch |
591 | 5.31k | // If we want to reverse the branch an odd number of times, we want |
592 | 5.31k | // J2_jumpf. |
593 | 5.31k | if (!Cond.empty() && Cond[0].isImm()4.22k ) |
594 | 4.22k | BccOpc = Cond[0].getImm(); |
595 | 5.31k | |
596 | 5.31k | if (!FBB) { |
597 | 5.01k | if (Cond.empty()) { |
598 | 1.08k | // Due to a bug in TailMerging/CFG Optimization, we need to add a |
599 | 1.08k | // special case handling of a predicated jump followed by an |
600 | 1.08k | // unconditional jump. If not, Tail Merging and CFG Optimization go |
601 | 1.08k | // into an infinite loop. |
602 | 1.08k | MachineBasicBlock *NewTBB, *NewFBB; |
603 | 1.08k | SmallVector<MachineOperand, 4> Cond; |
604 | 1.08k | auto Term = MBB.getFirstTerminator(); |
605 | 1.08k | if (Term != MBB.end() && isPredicated(*Term)172 && |
606 | 1.08k | !analyzeBranch(MBB, NewTBB, NewFBB, Cond, false)107 && |
607 | 1.08k | MachineFunction::iterator(NewTBB) == ++MBB.getIterator()105 ) { |
608 | 0 | reverseBranchCondition(Cond); |
609 | 0 | removeBranch(MBB); |
610 | 0 | return insertBranch(MBB, TBB, nullptr, Cond, DL); |
611 | 0 | } |
612 | 1.08k | BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB); |
613 | 3.92k | } else if (isEndLoopN(Cond[0].getImm())) { |
614 | 30 | int EndLoopOp = Cond[0].getImm(); |
615 | 30 | assert(Cond[1].isMBB()); |
616 | 30 | // Since we're adding an ENDLOOP, there better be a LOOP instruction. |
617 | 30 | // Check for it, and change the BB target if needed. |
618 | 30 | SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs; |
619 | 30 | MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, Cond[1].getMBB(), |
620 | 30 | VisitedBBs); |
621 | 30 | assert(Loop != nullptr && "Inserting an ENDLOOP without a LOOP"); |
622 | 30 | Loop->getOperand(0).setMBB(TBB); |
623 | 30 | // Add the ENDLOOP after the finding the LOOP0. |
624 | 30 | BuildMI(&MBB, DL, get(EndLoopOp)).addMBB(TBB); |
625 | 3.89k | } else if (isNewValueJump(Cond[0].getImm())) { |
626 | 0 | assert((Cond.size() == 3) && "Only supporting rr/ri version of nvjump"); |
627 | 0 | // New value jump |
628 | 0 | // (ins IntRegs:$src1, IntRegs:$src2, brtarget:$offset) |
629 | 0 | // (ins IntRegs:$src1, u5Imm:$src2, brtarget:$offset) |
630 | 0 | unsigned Flags1 = getUndefRegState(Cond[1].isUndef()); |
631 | 0 | LLVM_DEBUG(dbgs() << "\nInserting NVJump for " |
632 | 0 | << printMBBReference(MBB);); |
633 | 0 | if (Cond[2].isReg()) { |
634 | 0 | unsigned Flags2 = getUndefRegState(Cond[2].isUndef()); |
635 | 0 | BuildMI(&MBB, DL, get(BccOpc)).addReg(Cond[1].getReg(), Flags1). |
636 | 0 | addReg(Cond[2].getReg(), Flags2).addMBB(TBB); |
637 | 0 | } else if(Cond[2].isImm()) { |
638 | 0 | BuildMI(&MBB, DL, get(BccOpc)).addReg(Cond[1].getReg(), Flags1). |
639 | 0 | addImm(Cond[2].getImm()).addMBB(TBB); |
640 | 0 | } else |
641 | 0 | llvm_unreachable("Invalid condition for branching"); |
642 | 3.89k | } else { |
643 | 3.89k | assert((Cond.size() == 2) && "Malformed cond vector"); |
644 | 3.89k | const MachineOperand &RO = Cond[1]; |
645 | 3.89k | unsigned Flags = getUndefRegState(RO.isUndef()); |
646 | 3.89k | BuildMI(&MBB, DL, get(BccOpc)).addReg(RO.getReg(), Flags).addMBB(TBB); |
647 | 3.89k | } |
648 | 5.01k | return 1; |
649 | 300 | } |
650 | 300 | assert((!Cond.empty()) && |
651 | 300 | "Cond. cannot be empty when multiple branchings are required"); |
652 | 300 | assert((!isNewValueJump(Cond[0].getImm())) && |
653 | 300 | "NV-jump cannot be inserted with another branch"); |
654 | 300 | // Special case for hardware loops. The condition is a basic block. |
655 | 300 | if (isEndLoopN(Cond[0].getImm())) { |
656 | 130 | int EndLoopOp = Cond[0].getImm(); |
657 | 130 | assert(Cond[1].isMBB()); |
658 | 130 | // Since we're adding an ENDLOOP, there better be a LOOP instruction. |
659 | 130 | // Check for it, and change the BB target if needed. |
660 | 130 | SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs; |
661 | 130 | MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, Cond[1].getMBB(), |
662 | 130 | VisitedBBs); |
663 | 130 | assert(Loop != nullptr && "Inserting an ENDLOOP without a LOOP"); |
664 | 130 | Loop->getOperand(0).setMBB(TBB); |
665 | 130 | // Add the ENDLOOP after the finding the LOOP0. |
666 | 130 | BuildMI(&MBB, DL, get(EndLoopOp)).addMBB(TBB); |
667 | 170 | } else { |
668 | 170 | const MachineOperand &RO = Cond[1]; |
669 | 170 | unsigned Flags = getUndefRegState(RO.isUndef()); |
670 | 170 | BuildMI(&MBB, DL, get(BccOpc)).addReg(RO.getReg(), Flags).addMBB(TBB); |
671 | 170 | } |
672 | 300 | BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB); |
673 | 300 | |
674 | 300 | return 2; |
675 | 300 | } |
676 | | |
677 | | /// Analyze the loop code to find the loop induction variable and compare used |
678 | | /// to compute the number of iterations. Currently, we analyze loop that are |
679 | | /// controlled using hardware loops. In this case, the induction variable |
680 | | /// instruction is null. For all other cases, this function returns true, which |
681 | | /// means we're unable to analyze it. |
682 | | bool HexagonInstrInfo::analyzeLoop(MachineLoop &L, |
683 | | MachineInstr *&IndVarInst, |
684 | 333 | MachineInstr *&CmpInst) const { |
685 | 333 | |
686 | 333 | MachineBasicBlock *LoopEnd = L.getBottomBlock(); |
687 | 333 | MachineBasicBlock::iterator I = LoopEnd->getFirstTerminator(); |
688 | 333 | // We really "analyze" only hardware loops right now. |
689 | 333 | if (I != LoopEnd->end() && isEndLoopN(I->getOpcode())) { |
690 | 191 | IndVarInst = nullptr; |
691 | 191 | CmpInst = &*I; |
692 | 191 | return false; |
693 | 191 | } |
694 | 142 | return true; |
695 | 142 | } |
696 | | |
697 | | /// Generate code to reduce the loop iteration by one and check if the loop is |
698 | | /// finished. Return the value/register of the new loop count. this function |
699 | | /// assumes the nth iteration is peeled first. |
700 | | unsigned HexagonInstrInfo::reduceLoopCount( |
701 | | MachineBasicBlock &MBB, MachineBasicBlock &PreHeader, MachineInstr *IndVar, |
702 | | MachineInstr &Cmp, SmallVectorImpl<MachineOperand> &Cond, |
703 | | SmallVectorImpl<MachineInstr *> &PrevInsts, unsigned Iter, |
704 | 167 | unsigned MaxIter) const { |
705 | 167 | // We expect a hardware loop currently. This means that IndVar is set |
706 | 167 | // to null, and the compare is the ENDLOOP instruction. |
707 | 167 | assert((!IndVar) && isEndLoopN(Cmp.getOpcode()) |
708 | 167 | && "Expecting a hardware loop"); |
709 | 167 | MachineFunction *MF = MBB.getParent(); |
710 | 167 | DebugLoc DL = Cmp.getDebugLoc(); |
711 | 167 | SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs; |
712 | 167 | MachineInstr *Loop = findLoopInstr(&MBB, Cmp.getOpcode(), |
713 | 167 | Cmp.getOperand(0).getMBB(), VisitedBBs); |
714 | 167 | if (!Loop) |
715 | 0 | return 0; |
716 | 167 | // If the loop trip count is a compile-time value, then just change the |
717 | 167 | // value. |
718 | 167 | if (Loop->getOpcode() == Hexagon::J2_loop0i || |
719 | 167 | Loop->getOpcode() == Hexagon::J2_loop1i129 ) { |
720 | 38 | int64_t Offset = Loop->getOperand(1).getImm(); |
721 | 38 | if (Offset <= 1) |
722 | 4 | Loop->eraseFromParent(); |
723 | 34 | else |
724 | 34 | Loop->getOperand(1).setImm(Offset - 1); |
725 | 38 | return Offset - 1; |
726 | 38 | } |
727 | 129 | // The loop trip count is a run-time value. We generate code to subtract |
728 | 129 | // one from the trip count, and update the loop instruction. |
729 | 129 | assert(Loop->getOpcode() == Hexagon::J2_loop0r && "Unexpected instruction"); |
730 | 129 | unsigned LoopCount = Loop->getOperand(1).getReg(); |
731 | 129 | // Check if we're done with the loop. |
732 | 129 | unsigned LoopEnd = createVR(MF, MVT::i1); |
733 | 129 | MachineInstr *NewCmp = BuildMI(&MBB, DL, get(Hexagon::C2_cmpgtui), LoopEnd). |
734 | 129 | addReg(LoopCount).addImm(1); |
735 | 129 | unsigned NewLoopCount = createVR(MF, MVT::i32); |
736 | 129 | MachineInstr *NewAdd = BuildMI(&MBB, DL, get(Hexagon::A2_addi), NewLoopCount). |
737 | 129 | addReg(LoopCount).addImm(-1); |
738 | 129 | const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); |
739 | 129 | // Update the previously generated instructions with the new loop counter. |
740 | 129 | for (SmallVectorImpl<MachineInstr *>::iterator I = PrevInsts.begin(), |
741 | 199 | E = PrevInsts.end(); I != E; ++I70 ) |
742 | 70 | (*I)->substituteRegister(LoopCount, NewLoopCount, 0, HRI); |
743 | 129 | PrevInsts.clear(); |
744 | 129 | PrevInsts.push_back(NewCmp); |
745 | 129 | PrevInsts.push_back(NewAdd); |
746 | 129 | // Insert the new loop instruction if this is the last time the loop is |
747 | 129 | // decremented. |
748 | 129 | if (Iter == MaxIter) |
749 | 94 | BuildMI(&MBB, DL, get(Hexagon::J2_loop0r)). |
750 | 94 | addMBB(Loop->getOperand(0).getMBB()).addReg(NewLoopCount); |
751 | 129 | // Delete the old loop instruction. |
752 | 129 | if (Iter == 0) |
753 | 94 | Loop->eraseFromParent(); |
754 | 129 | Cond.push_back(MachineOperand::CreateImm(Hexagon::J2_jumpf)); |
755 | 129 | Cond.push_back(NewCmp->getOperand(0)); |
756 | 129 | return NewLoopCount; |
757 | 129 | } |
758 | | |
759 | | bool HexagonInstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB, |
760 | | unsigned NumCycles, unsigned ExtraPredCycles, |
761 | 622 | BranchProbability Probability) const { |
762 | 622 | return nonDbgBBSize(&MBB) <= 3; |
763 | 622 | } |
764 | | |
765 | | bool HexagonInstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB, |
766 | | unsigned NumTCycles, unsigned ExtraTCycles, MachineBasicBlock &FMBB, |
767 | | unsigned NumFCycles, unsigned ExtraFCycles, BranchProbability Probability) |
768 | 17 | const { |
769 | 17 | return nonDbgBBSize(&TMBB) <= 3 && nonDbgBBSize(&FMBB) <= 315 ; |
770 | 17 | } |
771 | | |
772 | | bool HexagonInstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB, |
773 | 1.53k | unsigned NumInstrs, BranchProbability Probability) const { |
774 | 1.53k | return NumInstrs <= 4; |
775 | 1.53k | } |
776 | | |
777 | | void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB, |
778 | | MachineBasicBlock::iterator I, |
779 | | const DebugLoc &DL, unsigned DestReg, |
780 | 2.14k | unsigned SrcReg, bool KillSrc) const { |
781 | 2.14k | const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); |
782 | 2.14k | unsigned KillFlag = getKillRegState(KillSrc); |
783 | 2.14k | |
784 | 2.14k | if (Hexagon::IntRegsRegClass.contains(SrcReg, DestReg)) { |
785 | 868 | BuildMI(MBB, I, DL, get(Hexagon::A2_tfr), DestReg) |
786 | 868 | .addReg(SrcReg, KillFlag); |
787 | 868 | return; |
788 | 868 | } |
789 | 1.27k | if (Hexagon::DoubleRegsRegClass.contains(SrcReg, DestReg)) { |
790 | 424 | BuildMI(MBB, I, DL, get(Hexagon::A2_tfrp), DestReg) |
791 | 424 | .addReg(SrcReg, KillFlag); |
792 | 424 | return; |
793 | 424 | } |
794 | 849 | if (Hexagon::PredRegsRegClass.contains(SrcReg, DestReg)) { |
795 | 0 | // Map Pd = Ps to Pd = or(Ps, Ps). |
796 | 0 | BuildMI(MBB, I, DL, get(Hexagon::C2_or), DestReg) |
797 | 0 | .addReg(SrcReg).addReg(SrcReg, KillFlag); |
798 | 0 | return; |
799 | 0 | } |
800 | 849 | if (Hexagon::CtrRegsRegClass.contains(DestReg) && |
801 | 849 | Hexagon::IntRegsRegClass.contains(SrcReg)110 ) { |
802 | 110 | BuildMI(MBB, I, DL, get(Hexagon::A2_tfrrcr), DestReg) |
803 | 110 | .addReg(SrcReg, KillFlag); |
804 | 110 | return; |
805 | 110 | } |
806 | 739 | if (Hexagon::IntRegsRegClass.contains(DestReg) && |
807 | 739 | Hexagon::CtrRegsRegClass.contains(SrcReg)190 ) { |
808 | 5 | BuildMI(MBB, I, DL, get(Hexagon::A2_tfrcrr), DestReg) |
809 | 5 | .addReg(SrcReg, KillFlag); |
810 | 5 | return; |
811 | 5 | } |
812 | 734 | if (Hexagon::ModRegsRegClass.contains(DestReg) && |
813 | 734 | Hexagon::IntRegsRegClass.contains(SrcReg)0 ) { |
814 | 0 | BuildMI(MBB, I, DL, get(Hexagon::A2_tfrrcr), DestReg) |
815 | 0 | .addReg(SrcReg, KillFlag); |
816 | 0 | return; |
817 | 0 | } |
818 | 734 | if (Hexagon::PredRegsRegClass.contains(SrcReg) && |
819 | 734 | Hexagon::IntRegsRegClass.contains(DestReg)185 ) { |
820 | 185 | BuildMI(MBB, I, DL, get(Hexagon::C2_tfrpr), DestReg) |
821 | 185 | .addReg(SrcReg, KillFlag); |
822 | 185 | return; |
823 | 185 | } |
824 | 549 | if (Hexagon::IntRegsRegClass.contains(SrcReg) && |
825 | 549 | Hexagon::PredRegsRegClass.contains(DestReg)110 ) { |
826 | 110 | BuildMI(MBB, I, DL, get(Hexagon::C2_tfrrp), DestReg) |
827 | 110 | .addReg(SrcReg, KillFlag); |
828 | 110 | return; |
829 | 110 | } |
830 | 439 | if (Hexagon::PredRegsRegClass.contains(SrcReg) && |
831 | 439 | Hexagon::IntRegsRegClass.contains(DestReg)0 ) { |
832 | 0 | BuildMI(MBB, I, DL, get(Hexagon::C2_tfrpr), DestReg) |
833 | 0 | .addReg(SrcReg, KillFlag); |
834 | 0 | return; |
835 | 0 | } |
836 | 439 | if (Hexagon::HvxVRRegClass.contains(SrcReg, DestReg)) { |
837 | 397 | BuildMI(MBB, I, DL, get(Hexagon::V6_vassign), DestReg). |
838 | 397 | addReg(SrcReg, KillFlag); |
839 | 397 | return; |
840 | 397 | } |
841 | 42 | if (Hexagon::HvxWRRegClass.contains(SrcReg, DestReg)) { |
842 | 39 | unsigned LoSrc = HRI.getSubReg(SrcReg, Hexagon::vsub_lo); |
843 | 39 | unsigned HiSrc = HRI.getSubReg(SrcReg, Hexagon::vsub_hi); |
844 | 39 | BuildMI(MBB, I, DL, get(Hexagon::V6_vcombine), DestReg) |
845 | 39 | .addReg(HiSrc, KillFlag) |
846 | 39 | .addReg(LoSrc, KillFlag); |
847 | 39 | return; |
848 | 39 | } |
849 | 3 | if (Hexagon::HvxQRRegClass.contains(SrcReg, DestReg)) { |
850 | 3 | BuildMI(MBB, I, DL, get(Hexagon::V6_pred_and), DestReg) |
851 | 3 | .addReg(SrcReg) |
852 | 3 | .addReg(SrcReg, KillFlag); |
853 | 3 | return; |
854 | 3 | } |
855 | 0 | if (Hexagon::HvxQRRegClass.contains(SrcReg) && |
856 | 0 | Hexagon::HvxVRRegClass.contains(DestReg)) { |
857 | 0 | llvm_unreachable("Unimplemented pred to vec"); |
858 | 0 | return; |
859 | 0 | } |
860 | 0 | if (Hexagon::HvxQRRegClass.contains(DestReg) && |
861 | 0 | Hexagon::HvxVRRegClass.contains(SrcReg)) { |
862 | 0 | llvm_unreachable("Unimplemented vec to pred"); |
863 | 0 | return; |
864 | 0 | } |
865 | 0 | |
866 | | #ifndef NDEBUG |
867 | | // Show the invalid registers to ease debugging. |
868 | | dbgs() << "Invalid registers for copy in " << printMBBReference(MBB) << ": " |
869 | | << printReg(DestReg, &HRI) << " = " << printReg(SrcReg, &HRI) << '\n'; |
870 | | #endif |
871 | 0 | llvm_unreachable("Unimplemented"); |
872 | 0 | } |
873 | | |
874 | | void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, |
875 | | MachineBasicBlock::iterator I, unsigned SrcReg, bool isKill, int FI, |
876 | 394 | const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const { |
877 | 394 | DebugLoc DL = MBB.findDebugLoc(I); |
878 | 394 | MachineFunction &MF = *MBB.getParent(); |
879 | 394 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
880 | 394 | unsigned SlotAlign = MFI.getObjectAlignment(FI); |
881 | 394 | unsigned RegAlign = TRI->getSpillAlignment(*RC); |
882 | 394 | unsigned KillFlag = getKillRegState(isKill); |
883 | 394 | bool HasAlloca = MFI.hasVarSizedObjects(); |
884 | 394 | const HexagonFrameLowering &HFI = *Subtarget.getFrameLowering(); |
885 | 394 | |
886 | 394 | MachineMemOperand *MMO = MF.getMachineMemOperand( |
887 | 394 | MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore, |
888 | 394 | MFI.getObjectSize(FI), SlotAlign); |
889 | 394 | |
890 | 394 | if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) { |
891 | 91 | BuildMI(MBB, I, DL, get(Hexagon::S2_storeri_io)) |
892 | 91 | .addFrameIndex(FI).addImm(0) |
893 | 91 | .addReg(SrcReg, KillFlag).addMemOperand(MMO); |
894 | 303 | } else if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC)) { |
895 | 238 | BuildMI(MBB, I, DL, get(Hexagon::S2_storerd_io)) |
896 | 238 | .addFrameIndex(FI).addImm(0) |
897 | 238 | .addReg(SrcReg, KillFlag).addMemOperand(MMO); |
898 | 238 | } else if (65 Hexagon::PredRegsRegClass.hasSubClassEq(RC)65 ) { |
899 | 27 | BuildMI(MBB, I, DL, get(Hexagon::STriw_pred)) |
900 | 27 | .addFrameIndex(FI).addImm(0) |
901 | 27 | .addReg(SrcReg, KillFlag).addMemOperand(MMO); |
902 | 38 | } else if (Hexagon::ModRegsRegClass.hasSubClassEq(RC)) { |
903 | 0 | BuildMI(MBB, I, DL, get(Hexagon::STriw_ctr)) |
904 | 0 | .addFrameIndex(FI).addImm(0) |
905 | 0 | .addReg(SrcReg, KillFlag).addMemOperand(MMO); |
906 | 38 | } else if (Hexagon::HvxQRRegClass.hasSubClassEq(RC)) { |
907 | 7 | BuildMI(MBB, I, DL, get(Hexagon::PS_vstorerq_ai)) |
908 | 7 | .addFrameIndex(FI).addImm(0) |
909 | 7 | .addReg(SrcReg, KillFlag).addMemOperand(MMO); |
910 | 31 | } else if (Hexagon::HvxVRRegClass.hasSubClassEq(RC)) { |
911 | 28 | // If there are variable-sized objects, spills will not be aligned. |
912 | 28 | if (HasAlloca) |
913 | 2 | SlotAlign = HFI.getStackAlignment(); |
914 | 28 | unsigned Opc = SlotAlign < RegAlign ? Hexagon::V6_vS32Ub_ai2 |
915 | 28 | : Hexagon::V6_vS32b_ai26 ; |
916 | 28 | MachineMemOperand *MMOA = MF.getMachineMemOperand( |
917 | 28 | MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore, |
918 | 28 | MFI.getObjectSize(FI), SlotAlign); |
919 | 28 | BuildMI(MBB, I, DL, get(Opc)) |
920 | 28 | .addFrameIndex(FI).addImm(0) |
921 | 28 | .addReg(SrcReg, KillFlag).addMemOperand(MMOA); |
922 | 28 | } else if (3 Hexagon::HvxWRRegClass.hasSubClassEq(RC)3 ) { |
923 | 3 | // If there are variable-sized objects, spills will not be aligned. |
924 | 3 | if (HasAlloca) |
925 | 0 | SlotAlign = HFI.getStackAlignment(); |
926 | 3 | unsigned Opc = SlotAlign < RegAlign ? Hexagon::PS_vstorerwu_ai0 |
927 | 3 | : Hexagon::PS_vstorerw_ai; |
928 | 3 | MachineMemOperand *MMOA = MF.getMachineMemOperand( |
929 | 3 | MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore, |
930 | 3 | MFI.getObjectSize(FI), SlotAlign); |
931 | 3 | BuildMI(MBB, I, DL, get(Opc)) |
932 | 3 | .addFrameIndex(FI).addImm(0) |
933 | 3 | .addReg(SrcReg, KillFlag).addMemOperand(MMOA); |
934 | 3 | } else { |
935 | 0 | llvm_unreachable("Unimplemented"); |
936 | 0 | } |
937 | 394 | } |
938 | | |
939 | | void HexagonInstrInfo::loadRegFromStackSlot( |
940 | | MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DestReg, |
941 | | int FI, const TargetRegisterClass *RC, |
942 | 392 | const TargetRegisterInfo *TRI) const { |
943 | 392 | DebugLoc DL = MBB.findDebugLoc(I); |
944 | 392 | MachineFunction &MF = *MBB.getParent(); |
945 | 392 | MachineFrameInfo &MFI = MF.getFrameInfo(); |
946 | 392 | unsigned SlotAlign = MFI.getObjectAlignment(FI); |
947 | 392 | unsigned RegAlign = TRI->getSpillAlignment(*RC); |
948 | 392 | bool HasAlloca = MFI.hasVarSizedObjects(); |
949 | 392 | const HexagonFrameLowering &HFI = *Subtarget.getFrameLowering(); |
950 | 392 | |
951 | 392 | MachineMemOperand *MMO = MF.getMachineMemOperand( |
952 | 392 | MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad, |
953 | 392 | MFI.getObjectSize(FI), SlotAlign); |
954 | 392 | |
955 | 392 | if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) { |
956 | 95 | BuildMI(MBB, I, DL, get(Hexagon::L2_loadri_io), DestReg) |
957 | 95 | .addFrameIndex(FI).addImm(0).addMemOperand(MMO); |
958 | 297 | } else if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC)) { |
959 | 235 | BuildMI(MBB, I, DL, get(Hexagon::L2_loadrd_io), DestReg) |
960 | 235 | .addFrameIndex(FI).addImm(0).addMemOperand(MMO); |
961 | 235 | } else if (62 Hexagon::PredRegsRegClass.hasSubClassEq(RC)62 ) { |
962 | 26 | BuildMI(MBB, I, DL, get(Hexagon::LDriw_pred), DestReg) |
963 | 26 | .addFrameIndex(FI).addImm(0).addMemOperand(MMO); |
964 | 36 | } else if (Hexagon::ModRegsRegClass.hasSubClassEq(RC)) { |
965 | 0 | BuildMI(MBB, I, DL, get(Hexagon::LDriw_ctr), DestReg) |
966 | 0 | .addFrameIndex(FI).addImm(0).addMemOperand(MMO); |
967 | 36 | } else if (Hexagon::HvxQRRegClass.hasSubClassEq(RC)) { |
968 | 8 | BuildMI(MBB, I, DL, get(Hexagon::PS_vloadrq_ai), DestReg) |
969 | 8 | .addFrameIndex(FI).addImm(0).addMemOperand(MMO); |
970 | 28 | } else if (Hexagon::HvxVRRegClass.hasSubClassEq(RC)) { |
971 | 26 | // If there are variable-sized objects, spills will not be aligned. |
972 | 26 | if (HasAlloca) |
973 | 2 | SlotAlign = HFI.getStackAlignment(); |
974 | 26 | unsigned Opc = SlotAlign < RegAlign ? Hexagon::V6_vL32Ub_ai2 |
975 | 26 | : Hexagon::V6_vL32b_ai24 ; |
976 | 26 | MachineMemOperand *MMOA = MF.getMachineMemOperand( |
977 | 26 | MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad, |
978 | 26 | MFI.getObjectSize(FI), SlotAlign); |
979 | 26 | BuildMI(MBB, I, DL, get(Opc), DestReg) |
980 | 26 | .addFrameIndex(FI).addImm(0).addMemOperand(MMOA); |
981 | 26 | } else if (2 Hexagon::HvxWRRegClass.hasSubClassEq(RC)2 ) { |
982 | 2 | // If there are variable-sized objects, spills will not be aligned. |
983 | 2 | if (HasAlloca) |
984 | 0 | SlotAlign = HFI.getStackAlignment(); |
985 | 2 | unsigned Opc = SlotAlign < RegAlign ? Hexagon::PS_vloadrwu_ai0 |
986 | 2 | : Hexagon::PS_vloadrw_ai; |
987 | 2 | MachineMemOperand *MMOA = MF.getMachineMemOperand( |
988 | 2 | MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad, |
989 | 2 | MFI.getObjectSize(FI), SlotAlign); |
990 | 2 | BuildMI(MBB, I, DL, get(Opc), DestReg) |
991 | 2 | .addFrameIndex(FI).addImm(0).addMemOperand(MMOA); |
992 | 2 | } else { |
993 | 0 | llvm_unreachable("Can't store this register to stack slot"); |
994 | 0 | } |
995 | 392 | } |
996 | | |
997 | 10 | static void getLiveRegsAt(LivePhysRegs &Regs, const MachineInstr &MI) { |
998 | 10 | const MachineBasicBlock &B = *MI.getParent(); |
999 | 10 | Regs.addLiveOuts(B); |
1000 | 10 | auto E = ++MachineBasicBlock::const_iterator(MI.getIterator()).getReverse(); |
1001 | 62 | for (auto I = B.rbegin(); I != E; ++I52 ) |
1002 | 52 | Regs.stepBackward(*I); |
1003 | 10 | } |
1004 | | |
1005 | | /// expandPostRAPseudo - This function is called for all pseudo instructions |
1006 | | /// that remain after register allocation. Many pseudo instructions are |
1007 | | /// created to help register allocation. This is the place to convert them |
1008 | | /// into real instructions. The target can edit MI in place, or it can insert |
1009 | | /// new instructions and erase MI. The function should return true if |
1010 | | /// anything was changed. |
1011 | 3.05k | bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { |
1012 | 3.05k | MachineBasicBlock &MBB = *MI.getParent(); |
1013 | 3.05k | MachineFunction &MF = *MBB.getParent(); |
1014 | 3.05k | MachineRegisterInfo &MRI = MF.getRegInfo(); |
1015 | 3.05k | const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); |
1016 | 3.05k | DebugLoc DL = MI.getDebugLoc(); |
1017 | 3.05k | unsigned Opc = MI.getOpcode(); |
1018 | 3.05k | |
1019 | 3.05k | auto RealCirc = [&](unsigned Opc, bool HasImm, unsigned MxOp) { |
1020 | 22 | unsigned Mx = MI.getOperand(MxOp).getReg(); |
1021 | 22 | unsigned CSx = (Mx == Hexagon::M0 ? Hexagon::CS0 : Hexagon::CS10 ); |
1022 | 22 | BuildMI(MBB, MI, DL, get(Hexagon::A2_tfrrcr), CSx) |
1023 | 22 | .add(MI.getOperand((HasImm ? 511 : 411 ))); |
1024 | 22 | auto MIB = BuildMI(MBB, MI, DL, get(Opc)).add(MI.getOperand(0)) |
1025 | 22 | .add(MI.getOperand(1)).add(MI.getOperand(2)).add(MI.getOperand(3)); |
1026 | 22 | if (HasImm) |
1027 | 11 | MIB.add(MI.getOperand(4)); |
1028 | 22 | MIB.addReg(CSx, RegState::Implicit); |
1029 | 22 | MBB.erase(MI); |
1030 | 22 | return true; |
1031 | 22 | }; |
1032 | 3.05k | |
1033 | 3.05k | switch (Opc) { |
1034 | 3.05k | case TargetOpcode::COPY: { |
1035 | 2.15k | MachineOperand &MD = MI.getOperand(0); |
1036 | 2.15k | MachineOperand &MS = MI.getOperand(1); |
1037 | 2.15k | MachineBasicBlock::iterator MBBI = MI.getIterator(); |
1038 | 2.15k | if (MD.getReg() != MS.getReg() && !MS.isUndef()2.14k ) { |
1039 | 2.14k | copyPhysReg(MBB, MI, DL, MD.getReg(), MS.getReg(), MS.isKill()); |
1040 | 2.14k | std::prev(MBBI)->copyImplicitOps(*MBB.getParent(), MI); |
1041 | 2.14k | } |
1042 | 2.15k | MBB.erase(MBBI); |
1043 | 2.15k | return true; |
1044 | 3.05k | } |
1045 | 3.05k | case Hexagon::PS_aligna: |
1046 | 1 | BuildMI(MBB, MI, DL, get(Hexagon::A2_andir), MI.getOperand(0).getReg()) |
1047 | 1 | .addReg(HRI.getFrameRegister()) |
1048 | 1 | .addImm(-MI.getOperand(1).getImm()); |
1049 | 1 | MBB.erase(MI); |
1050 | 1 | return true; |
1051 | 3.05k | case Hexagon::V6_vassignp: { |
1052 | 2 | unsigned SrcReg = MI.getOperand(1).getReg(); |
1053 | 2 | unsigned DstReg = MI.getOperand(0).getReg(); |
1054 | 2 | unsigned Kill = getKillRegState(MI.getOperand(1).isKill()); |
1055 | 2 | BuildMI(MBB, MI, DL, get(Hexagon::V6_vcombine), DstReg) |
1056 | 2 | .addReg(HRI.getSubReg(SrcReg, Hexagon::vsub_hi), Kill) |
1057 | 2 | .addReg(HRI.getSubReg(SrcReg, Hexagon::vsub_lo), Kill); |
1058 | 2 | MBB.erase(MI); |
1059 | 2 | return true; |
1060 | 3.05k | } |
1061 | 3.05k | case Hexagon::V6_lo: { |
1062 | 0 | unsigned SrcReg = MI.getOperand(1).getReg(); |
1063 | 0 | unsigned DstReg = MI.getOperand(0).getReg(); |
1064 | 0 | unsigned SrcSubLo = HRI.getSubReg(SrcReg, Hexagon::vsub_lo); |
1065 | 0 | copyPhysReg(MBB, MI, DL, DstReg, SrcSubLo, MI.getOperand(1).isKill()); |
1066 | 0 | MBB.erase(MI); |
1067 | 0 | MRI.clearKillFlags(SrcSubLo); |
1068 | 0 | return true; |
1069 | 3.05k | } |
1070 | 3.05k | case Hexagon::V6_hi: { |
1071 | 0 | unsigned SrcReg = MI.getOperand(1).getReg(); |
1072 | 0 | unsigned DstReg = MI.getOperand(0).getReg(); |
1073 | 0 | unsigned SrcSubHi = HRI.getSubReg(SrcReg, Hexagon::vsub_hi); |
1074 | 0 | copyPhysReg(MBB, MI, DL, DstReg, SrcSubHi, MI.getOperand(1).isKill()); |
1075 | 0 | MBB.erase(MI); |
1076 | 0 | MRI.clearKillFlags(SrcSubHi); |
1077 | 0 | return true; |
1078 | 3.05k | } |
1079 | 3.05k | case Hexagon::PS_vstorerw_ai: |
1080 | 0 | case Hexagon::PS_vstorerwu_ai: { |
1081 | 0 | bool Aligned = Opc == Hexagon::PS_vstorerw_ai; |
1082 | 0 | unsigned SrcReg = MI.getOperand(2).getReg(); |
1083 | 0 | unsigned SrcSubHi = HRI.getSubReg(SrcReg, Hexagon::vsub_hi); |
1084 | 0 | unsigned SrcSubLo = HRI.getSubReg(SrcReg, Hexagon::vsub_lo); |
1085 | 0 | unsigned NewOpc = Aligned ? Hexagon::V6_vS32b_ai : Hexagon::V6_vS32Ub_ai; |
1086 | 0 | unsigned Offset = HRI.getSpillSize(Hexagon::HvxVRRegClass); |
1087 | 0 |
|
1088 | 0 | MachineInstr *MI1New = BuildMI(MBB, MI, DL, get(NewOpc)) |
1089 | 0 | .add(MI.getOperand(0)) |
1090 | 0 | .addImm(MI.getOperand(1).getImm()) |
1091 | 0 | .addReg(SrcSubLo) |
1092 | 0 | .cloneMemRefs(MI); |
1093 | 0 | MI1New->getOperand(0).setIsKill(false); |
1094 | 0 | BuildMI(MBB, MI, DL, get(NewOpc)) |
1095 | 0 | .add(MI.getOperand(0)) |
1096 | 0 | // The Vectors are indexed in multiples of vector size. |
1097 | 0 | .addImm(MI.getOperand(1).getImm() + Offset) |
1098 | 0 | .addReg(SrcSubHi) |
1099 | 0 | .cloneMemRefs(MI); |
1100 | 0 | MBB.erase(MI); |
1101 | 0 | return true; |
1102 | 0 | } |
1103 | 0 | case Hexagon::PS_vloadrw_ai: |
1104 | 0 | case Hexagon::PS_vloadrwu_ai: { |
1105 | 0 | bool Aligned = Opc == Hexagon::PS_vloadrw_ai; |
1106 | 0 | unsigned DstReg = MI.getOperand(0).getReg(); |
1107 | 0 | unsigned NewOpc = Aligned ? Hexagon::V6_vL32b_ai : Hexagon::V6_vL32Ub_ai; |
1108 | 0 | unsigned Offset = HRI.getSpillSize(Hexagon::HvxVRRegClass); |
1109 | 0 |
|
1110 | 0 | MachineInstr *MI1New = BuildMI(MBB, MI, DL, get(NewOpc), |
1111 | 0 | HRI.getSubReg(DstReg, Hexagon::vsub_lo)) |
1112 | 0 | .add(MI.getOperand(1)) |
1113 | 0 | .addImm(MI.getOperand(2).getImm()) |
1114 | 0 | .cloneMemRefs(MI); |
1115 | 0 | MI1New->getOperand(1).setIsKill(false); |
1116 | 0 | BuildMI(MBB, MI, DL, get(NewOpc), HRI.getSubReg(DstReg, Hexagon::vsub_hi)) |
1117 | 0 | .add(MI.getOperand(1)) |
1118 | 0 | // The Vectors are indexed in multiples of vector size. |
1119 | 0 | .addImm(MI.getOperand(2).getImm() + Offset) |
1120 | 0 | .cloneMemRefs(MI); |
1121 | 0 | MBB.erase(MI); |
1122 | 0 | return true; |
1123 | 0 | } |
1124 | 7 | case Hexagon::PS_true: { |
1125 | 7 | unsigned Reg = MI.getOperand(0).getReg(); |
1126 | 7 | BuildMI(MBB, MI, DL, get(Hexagon::C2_orn), Reg) |
1127 | 7 | .addReg(Reg, RegState::Undef) |
1128 | 7 | .addReg(Reg, RegState::Undef); |
1129 | 7 | MBB.erase(MI); |
1130 | 7 | return true; |
1131 | 0 | } |
1132 | 9 | case Hexagon::PS_false: { |
1133 | 9 | unsigned Reg = MI.getOperand(0).getReg(); |
1134 | 9 | BuildMI(MBB, MI, DL, get(Hexagon::C2_andn), Reg) |
1135 | 9 | .addReg(Reg, RegState::Undef) |
1136 | 9 | .addReg(Reg, RegState::Undef); |
1137 | 9 | MBB.erase(MI); |
1138 | 9 | return true; |
1139 | 0 | } |
1140 | 0 | case Hexagon::PS_qtrue: { |
1141 | 0 | BuildMI(MBB, MI, DL, get(Hexagon::V6_veqw), MI.getOperand(0).getReg()) |
1142 | 0 | .addReg(Hexagon::V0, RegState::Undef) |
1143 | 0 | .addReg(Hexagon::V0, RegState::Undef); |
1144 | 0 | MBB.erase(MI); |
1145 | 0 | return true; |
1146 | 0 | } |
1147 | 2 | case Hexagon::PS_qfalse: { |
1148 | 2 | BuildMI(MBB, MI, DL, get(Hexagon::V6_vgtw), MI.getOperand(0).getReg()) |
1149 | 2 | .addReg(Hexagon::V0, RegState::Undef) |
1150 | 2 | .addReg(Hexagon::V0, RegState::Undef); |
1151 | 2 | MBB.erase(MI); |
1152 | 2 | return true; |
1153 | 0 | } |
1154 | 10 | case Hexagon::PS_vdd0: { |
1155 | 10 | unsigned Vd = MI.getOperand(0).getReg(); |
1156 | 10 | BuildMI(MBB, MI, DL, get(Hexagon::V6_vsubw_dv), Vd) |
1157 | 10 | .addReg(Vd, RegState::Undef) |
1158 | 10 | .addReg(Vd, RegState::Undef); |
1159 | 10 | MBB.erase(MI); |
1160 | 10 | return true; |
1161 | 0 | } |
1162 | 2 | case Hexagon::PS_vmulw: { |
1163 | 2 | // Expand a 64-bit vector multiply into 2 32-bit scalar multiplies. |
1164 | 2 | unsigned DstReg = MI.getOperand(0).getReg(); |
1165 | 2 | unsigned Src1Reg = MI.getOperand(1).getReg(); |
1166 | 2 | unsigned Src2Reg = MI.getOperand(2).getReg(); |
1167 | 2 | unsigned Src1SubHi = HRI.getSubReg(Src1Reg, Hexagon::isub_hi); |
1168 | 2 | unsigned Src1SubLo = HRI.getSubReg(Src1Reg, Hexagon::isub_lo); |
1169 | 2 | unsigned Src2SubHi = HRI.getSubReg(Src2Reg, Hexagon::isub_hi); |
1170 | 2 | unsigned Src2SubLo = HRI.getSubReg(Src2Reg, Hexagon::isub_lo); |
1171 | 2 | BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_mpyi), |
1172 | 2 | HRI.getSubReg(DstReg, Hexagon::isub_hi)) |
1173 | 2 | .addReg(Src1SubHi) |
1174 | 2 | .addReg(Src2SubHi); |
1175 | 2 | BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_mpyi), |
1176 | 2 | HRI.getSubReg(DstReg, Hexagon::isub_lo)) |
1177 | 2 | .addReg(Src1SubLo) |
1178 | 2 | .addReg(Src2SubLo); |
1179 | 2 | MBB.erase(MI); |
1180 | 2 | MRI.clearKillFlags(Src1SubHi); |
1181 | 2 | MRI.clearKillFlags(Src1SubLo); |
1182 | 2 | MRI.clearKillFlags(Src2SubHi); |
1183 | 2 | MRI.clearKillFlags(Src2SubLo); |
1184 | 2 | return true; |
1185 | 0 | } |
1186 | 14 | case Hexagon::PS_vmulw_acc: { |
1187 | 14 | // Expand 64-bit vector multiply with addition into 2 scalar multiplies. |
1188 | 14 | unsigned DstReg = MI.getOperand(0).getReg(); |
1189 | 14 | unsigned Src1Reg = MI.getOperand(1).getReg(); |
1190 | 14 | unsigned Src2Reg = MI.getOperand(2).getReg(); |
1191 | 14 | unsigned Src3Reg = MI.getOperand(3).getReg(); |
1192 | 14 | unsigned Src1SubHi = HRI.getSubReg(Src1Reg, Hexagon::isub_hi); |
1193 | 14 | unsigned Src1SubLo = HRI.getSubReg(Src1Reg, Hexagon::isub_lo); |
1194 | 14 | unsigned Src2SubHi = HRI.getSubReg(Src2Reg, Hexagon::isub_hi); |
1195 | 14 | unsigned Src2SubLo = HRI.getSubReg(Src2Reg, Hexagon::isub_lo); |
1196 | 14 | unsigned Src3SubHi = HRI.getSubReg(Src3Reg, Hexagon::isub_hi); |
1197 | 14 | unsigned Src3SubLo = HRI.getSubReg(Src3Reg, Hexagon::isub_lo); |
1198 | 14 | BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_maci), |
1199 | 14 | HRI.getSubReg(DstReg, Hexagon::isub_hi)) |
1200 | 14 | .addReg(Src1SubHi) |
1201 | 14 | .addReg(Src2SubHi) |
1202 | 14 | .addReg(Src3SubHi); |
1203 | 14 | BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_maci), |
1204 | 14 | HRI.getSubReg(DstReg, Hexagon::isub_lo)) |
1205 | 14 | .addReg(Src1SubLo) |
1206 | 14 | .addReg(Src2SubLo) |
1207 | 14 | .addReg(Src3SubLo); |
1208 | 14 | MBB.erase(MI); |
1209 | 14 | MRI.clearKillFlags(Src1SubHi); |
1210 | 14 | MRI.clearKillFlags(Src1SubLo); |
1211 | 14 | MRI.clearKillFlags(Src2SubHi); |
1212 | 14 | MRI.clearKillFlags(Src2SubLo); |
1213 | 14 | MRI.clearKillFlags(Src3SubHi); |
1214 | 14 | MRI.clearKillFlags(Src3SubLo); |
1215 | 14 | return true; |
1216 | 0 | } |
1217 | 0 | case Hexagon::PS_pselect: { |
1218 | 0 | const MachineOperand &Op0 = MI.getOperand(0); |
1219 | 0 | const MachineOperand &Op1 = MI.getOperand(1); |
1220 | 0 | const MachineOperand &Op2 = MI.getOperand(2); |
1221 | 0 | const MachineOperand &Op3 = MI.getOperand(3); |
1222 | 0 | unsigned Rd = Op0.getReg(); |
1223 | 0 | unsigned Pu = Op1.getReg(); |
1224 | 0 | unsigned Rs = Op2.getReg(); |
1225 | 0 | unsigned Rt = Op3.getReg(); |
1226 | 0 | DebugLoc DL = MI.getDebugLoc(); |
1227 | 0 | unsigned K1 = getKillRegState(Op1.isKill()); |
1228 | 0 | unsigned K2 = getKillRegState(Op2.isKill()); |
1229 | 0 | unsigned K3 = getKillRegState(Op3.isKill()); |
1230 | 0 | if (Rd != Rs) |
1231 | 0 | BuildMI(MBB, MI, DL, get(Hexagon::A2_tfrpt), Rd) |
1232 | 0 | .addReg(Pu, (Rd == Rt) ? K1 : 0) |
1233 | 0 | .addReg(Rs, K2); |
1234 | 0 | if (Rd != Rt) |
1235 | 0 | BuildMI(MBB, MI, DL, get(Hexagon::A2_tfrpf), Rd) |
1236 | 0 | .addReg(Pu, K1) |
1237 | 0 | .addReg(Rt, K3); |
1238 | 0 | MBB.erase(MI); |
1239 | 0 | return true; |
1240 | 0 | } |
1241 | 9 | case Hexagon::PS_vselect: { |
1242 | 9 | const MachineOperand &Op0 = MI.getOperand(0); |
1243 | 9 | const MachineOperand &Op1 = MI.getOperand(1); |
1244 | 9 | const MachineOperand &Op2 = MI.getOperand(2); |
1245 | 9 | const MachineOperand &Op3 = MI.getOperand(3); |
1246 | 9 | LivePhysRegs LiveAtMI(HRI); |
1247 | 9 | getLiveRegsAt(LiveAtMI, MI); |
1248 | 9 | bool IsDestLive = !LiveAtMI.available(MRI, Op0.getReg()); |
1249 | 9 | unsigned PReg = Op1.getReg(); |
1250 | 9 | assert(Op1.getSubReg() == 0); |
1251 | 9 | unsigned PState = getRegState(Op1); |
1252 | 9 | |
1253 | 9 | if (Op0.getReg() != Op2.getReg()) { |
1254 | 7 | unsigned S = Op0.getReg() != Op3.getReg() ? PState & ~RegState::Kill1 |
1255 | 7 | : PState6 ; |
1256 | 7 | auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vcmov)) |
1257 | 7 | .add(Op0) |
1258 | 7 | .addReg(PReg, S) |
1259 | 7 | .add(Op2); |
1260 | 7 | if (IsDestLive) |
1261 | 6 | T.addReg(Op0.getReg(), RegState::Implicit); |
1262 | 7 | IsDestLive = true; |
1263 | 7 | } |
1264 | 9 | if (Op0.getReg() != Op3.getReg()) { |
1265 | 3 | auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vncmov)) |
1266 | 3 | .add(Op0) |
1267 | 3 | .addReg(PReg, PState) |
1268 | 3 | .add(Op3); |
1269 | 3 | if (IsDestLive) |
1270 | 3 | T.addReg(Op0.getReg(), RegState::Implicit); |
1271 | 3 | } |
1272 | 9 | MBB.erase(MI); |
1273 | 9 | return true; |
1274 | 0 | } |
1275 | 1 | case Hexagon::PS_wselect: { |
1276 | 1 | MachineOperand &Op0 = MI.getOperand(0); |
1277 | 1 | MachineOperand &Op1 = MI.getOperand(1); |
1278 | 1 | MachineOperand &Op2 = MI.getOperand(2); |
1279 | 1 | MachineOperand &Op3 = MI.getOperand(3); |
1280 | 1 | LivePhysRegs LiveAtMI(HRI); |
1281 | 1 | getLiveRegsAt(LiveAtMI, MI); |
1282 | 1 | bool IsDestLive = !LiveAtMI.available(MRI, Op0.getReg()); |
1283 | 1 | unsigned PReg = Op1.getReg(); |
1284 | 1 | assert(Op1.getSubReg() == 0); |
1285 | 1 | unsigned PState = getRegState(Op1); |
1286 | 1 | |
1287 | 1 | if (Op0.getReg() != Op2.getReg()) { |
1288 | 1 | unsigned S = Op0.getReg() != Op3.getReg() ? PState & ~RegState::Kill |
1289 | 1 | : PState0 ; |
1290 | 1 | unsigned SrcLo = HRI.getSubReg(Op2.getReg(), Hexagon::vsub_lo); |
1291 | 1 | unsigned SrcHi = HRI.getSubReg(Op2.getReg(), Hexagon::vsub_hi); |
1292 | 1 | auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vccombine)) |
1293 | 1 | .add(Op0) |
1294 | 1 | .addReg(PReg, S) |
1295 | 1 | .addReg(SrcHi) |
1296 | 1 | .addReg(SrcLo); |
1297 | 1 | if (IsDestLive) |
1298 | 0 | T.addReg(Op0.getReg(), RegState::Implicit); |
1299 | 1 | IsDestLive = true; |
1300 | 1 | } |
1301 | 1 | if (Op0.getReg() != Op3.getReg()) { |
1302 | 1 | unsigned SrcLo = HRI.getSubReg(Op3.getReg(), Hexagon::vsub_lo); |
1303 | 1 | unsigned SrcHi = HRI.getSubReg(Op3.getReg(), Hexagon::vsub_hi); |
1304 | 1 | auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vnccombine)) |
1305 | 1 | .add(Op0) |
1306 | 1 | .addReg(PReg, PState) |
1307 | 1 | .addReg(SrcHi) |
1308 | 1 | .addReg(SrcLo); |
1309 | 1 | if (IsDestLive) |
1310 | 1 | T.addReg(Op0.getReg(), RegState::Implicit); |
1311 | 1 | } |
1312 | 1 | MBB.erase(MI); |
1313 | 1 | return true; |
1314 | 0 | } |
1315 | 0 |
|
1316 | 14 | case Hexagon::PS_crash: { |
1317 | 14 | // Generate a misaligned load that is guaranteed to cause a crash. |
1318 | 14 | class CrashPseudoSourceValue : public PseudoSourceValue { |
1319 | 14 | public: |
1320 | 14 | CrashPseudoSourceValue(const TargetInstrInfo &TII) |
1321 | 14 | : PseudoSourceValue(TargetCustom, TII) {} |
1322 | 14 | |
1323 | 14 | bool isConstant(const MachineFrameInfo *) const override { |
1324 | 0 | return false; |
1325 | 0 | } |
1326 | 14 | bool isAliased(const MachineFrameInfo *) const override { |
1327 | 0 | return false; |
1328 | 0 | } |
1329 | 14 | bool mayAlias(const MachineFrameInfo *) const override { |
1330 | 0 | return false; |
1331 | 0 | } |
1332 | 14 | void printCustom(raw_ostream &OS) const override { |
1333 | 0 | OS << "MisalignedCrash"; |
1334 | 0 | } |
1335 | 14 | }; |
1336 | 14 | |
1337 | 14 | static const CrashPseudoSourceValue CrashPSV(*this); |
1338 | 14 | MachineMemOperand *MMO = MF.getMachineMemOperand( |
1339 | 14 | MachinePointerInfo(&CrashPSV), |
1340 | 14 | MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile, 8, 1); |
1341 | 14 | BuildMI(MBB, MI, DL, get(Hexagon::PS_loadrdabs), Hexagon::D13) |
1342 | 14 | .addImm(0xBADC0FEE) // Misaligned load. |
1343 | 14 | .addMemOperand(MMO); |
1344 | 14 | MBB.erase(MI); |
1345 | 14 | return true; |
1346 | 0 | } |
1347 | 0 |
|
1348 | 44 | case Hexagon::PS_tailcall_i: |
1349 | 44 | MI.setDesc(get(Hexagon::J2_jump)); |
1350 | 44 | return true; |
1351 | 0 | case Hexagon::PS_tailcall_r: |
1352 | 0 | case Hexagon::PS_jmpret: |
1353 | 0 | MI.setDesc(get(Hexagon::J2_jumpr)); |
1354 | 0 | return true; |
1355 | 0 | case Hexagon::PS_jmprett: |
1356 | 0 | MI.setDesc(get(Hexagon::J2_jumprt)); |
1357 | 0 | return true; |
1358 | 0 | case Hexagon::PS_jmpretf: |
1359 | 0 | MI.setDesc(get(Hexagon::J2_jumprf)); |
1360 | 0 | return true; |
1361 | 0 | case Hexagon::PS_jmprettnewpt: |
1362 | 0 | MI.setDesc(get(Hexagon::J2_jumprtnewpt)); |
1363 | 0 | return true; |
1364 | 0 | case Hexagon::PS_jmpretfnewpt: |
1365 | 0 | MI.setDesc(get(Hexagon::J2_jumprfnewpt)); |
1366 | 0 | return true; |
1367 | 0 | case Hexagon::PS_jmprettnew: |
1368 | 0 | MI.setDesc(get(Hexagon::J2_jumprtnew)); |
1369 | 0 | return true; |
1370 | 0 | case Hexagon::PS_jmpretfnew: |
1371 | 0 | MI.setDesc(get(Hexagon::J2_jumprfnew)); |
1372 | 0 | return true; |
1373 | 0 |
|
1374 | 1 | case Hexagon::PS_loadrub_pci: |
1375 | 1 | return RealCirc(Hexagon::L2_loadrub_pci, /*HasImm*/true, /*MxOp*/4); |
1376 | 1 | case Hexagon::PS_loadrb_pci: |
1377 | 1 | return RealCirc(Hexagon::L2_loadrb_pci, /*HasImm*/true, /*MxOp*/4); |
1378 | 1 | case Hexagon::PS_loadruh_pci: |
1379 | 1 | return RealCirc(Hexagon::L2_loadruh_pci, /*HasImm*/true, /*MxOp*/4); |
1380 | 1 | case Hexagon::PS_loadrh_pci: |
1381 | 1 | return RealCirc(Hexagon::L2_loadrh_pci, /*HasImm*/true, /*MxOp*/4); |
1382 | 1 | case Hexagon::PS_loadri_pci: |
1383 | 1 | return RealCirc(Hexagon::L2_loadri_pci, /*HasImm*/true, /*MxOp*/4); |
1384 | 1 | case Hexagon::PS_loadrd_pci: |
1385 | 1 | return RealCirc(Hexagon::L2_loadrd_pci, /*HasImm*/true, /*MxOp*/4); |
1386 | 1 | case Hexagon::PS_loadrub_pcr: |
1387 | 1 | return RealCirc(Hexagon::L2_loadrub_pcr, /*HasImm*/false, /*MxOp*/3); |
1388 | 1 | case Hexagon::PS_loadrb_pcr: |
1389 | 1 | return RealCirc(Hexagon::L2_loadrb_pcr, /*HasImm*/false, /*MxOp*/3); |
1390 | 1 | case Hexagon::PS_loadruh_pcr: |
1391 | 1 | return RealCirc(Hexagon::L2_loadruh_pcr, /*HasImm*/false, /*MxOp*/3); |
1392 | 1 | case Hexagon::PS_loadrh_pcr: |
1393 | 1 | return RealCirc(Hexagon::L2_loadrh_pcr, /*HasImm*/false, /*MxOp*/3); |
1394 | 1 | case Hexagon::PS_loadri_pcr: |
1395 | 1 | return RealCirc(Hexagon::L2_loadri_pcr, /*HasImm*/false, /*MxOp*/3); |
1396 | 1 | case Hexagon::PS_loadrd_pcr: |
1397 | 1 | return RealCirc(Hexagon::L2_loadrd_pcr, /*HasImm*/false, /*MxOp*/3); |
1398 | 1 | case Hexagon::PS_storerb_pci: |
1399 | 1 | return RealCirc(Hexagon::S2_storerb_pci, /*HasImm*/true, /*MxOp*/3); |
1400 | 1 | case Hexagon::PS_storerh_pci: |
1401 | 1 | return RealCirc(Hexagon::S2_storerh_pci, /*HasImm*/true, /*MxOp*/3); |
1402 | 1 | case Hexagon::PS_storerf_pci: |
1403 | 1 | return RealCirc(Hexagon::S2_storerf_pci, /*HasImm*/true, /*MxOp*/3); |
1404 | 1 | case Hexagon::PS_storeri_pci: |
1405 | 1 | return RealCirc(Hexagon::S2_storeri_pci, /*HasImm*/true, /*MxOp*/3); |
1406 | 1 | case Hexagon::PS_storerd_pci: |
1407 | 1 | return RealCirc(Hexagon::S2_storerd_pci, /*HasImm*/true, /*MxOp*/3); |
1408 | 1 | case Hexagon::PS_storerb_pcr: |
1409 | 1 | return RealCirc(Hexagon::S2_storerb_pcr, /*HasImm*/false, /*MxOp*/2); |
1410 | 1 | case Hexagon::PS_storerh_pcr: |
1411 | 1 | return RealCirc(Hexagon::S2_storerh_pcr, /*HasImm*/false, /*MxOp*/2); |
1412 | 1 | case Hexagon::PS_storerf_pcr: |
1413 | 1 | return RealCirc(Hexagon::S2_storerf_pcr, /*HasImm*/false, /*MxOp*/2); |
1414 | 1 | case Hexagon::PS_storeri_pcr: |
1415 | 1 | return RealCirc(Hexagon::S2_storeri_pcr, /*HasImm*/false, /*MxOp*/2); |
1416 | 1 | case Hexagon::PS_storerd_pcr: |
1417 | 1 | return RealCirc(Hexagon::S2_storerd_pcr, /*HasImm*/false, /*MxOp*/2); |
1418 | 768 | } |
1419 | 768 | |
1420 | 768 | return false; |
1421 | 768 | } |
1422 | | |
1423 | | MachineBasicBlock::instr_iterator |
1424 | 33.4k | HexagonInstrInfo::expandVGatherPseudo(MachineInstr &MI) const { |
1425 | 33.4k | MachineBasicBlock &MBB = *MI.getParent(); |
1426 | 33.4k | const DebugLoc &DL = MI.getDebugLoc(); |
1427 | 33.4k | unsigned Opc = MI.getOpcode(); |
1428 | 33.4k | MachineBasicBlock::iterator First; |
1429 | 33.4k | |
1430 | 33.4k | switch (Opc) { |
1431 | 33.4k | case Hexagon::V6_vgathermh_pseudo: |
1432 | 5 | First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermh)) |
1433 | 5 | .add(MI.getOperand(1)) |
1434 | 5 | .add(MI.getOperand(2)) |
1435 | 5 | .add(MI.getOperand(3)); |
1436 | 5 | BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) |
1437 | 5 | .add(MI.getOperand(0)) |
1438 | 5 | .addImm(0) |
1439 | 5 | .addReg(Hexagon::VTMP); |
1440 | 5 | MBB.erase(MI); |
1441 | 5 | return First.getInstrIterator(); |
1442 | 33.4k | |
1443 | 33.4k | case Hexagon::V6_vgathermw_pseudo: |
1444 | 5 | First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermw)) |
1445 | 5 | .add(MI.getOperand(1)) |
1446 | 5 | .add(MI.getOperand(2)) |
1447 | 5 | .add(MI.getOperand(3)); |
1448 | 5 | BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) |
1449 | 5 | .add(MI.getOperand(0)) |
1450 | 5 | .addImm(0) |
1451 | 5 | .addReg(Hexagon::VTMP); |
1452 | 5 | MBB.erase(MI); |
1453 | 5 | return First.getInstrIterator(); |
1454 | 33.4k | |
1455 | 33.4k | case Hexagon::V6_vgathermhw_pseudo: |
1456 | 3 | First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhw)) |
1457 | 3 | .add(MI.getOperand(1)) |
1458 | 3 | .add(MI.getOperand(2)) |
1459 | 3 | .add(MI.getOperand(3)); |
1460 | 3 | BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) |
1461 | 3 | .add(MI.getOperand(0)) |
1462 | 3 | .addImm(0) |
1463 | 3 | .addReg(Hexagon::VTMP); |
1464 | 3 | MBB.erase(MI); |
1465 | 3 | return First.getInstrIterator(); |
1466 | 33.4k | |
1467 | 33.4k | case Hexagon::V6_vgathermhq_pseudo: |
1468 | 2 | First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhq)) |
1469 | 2 | .add(MI.getOperand(1)) |
1470 | 2 | .add(MI.getOperand(2)) |
1471 | 2 | .add(MI.getOperand(3)) |
1472 | 2 | .add(MI.getOperand(4)); |
1473 | 2 | BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) |
1474 | 2 | .add(MI.getOperand(0)) |
1475 | 2 | .addImm(0) |
1476 | 2 | .addReg(Hexagon::VTMP); |
1477 | 2 | MBB.erase(MI); |
1478 | 2 | return First.getInstrIterator(); |
1479 | 33.4k | |
1480 | 33.4k | case Hexagon::V6_vgathermwq_pseudo: |
1481 | 2 | First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermwq)) |
1482 | 2 | .add(MI.getOperand(1)) |
1483 | 2 | .add(MI.getOperand(2)) |
1484 | 2 | .add(MI.getOperand(3)) |
1485 | 2 | .add(MI.getOperand(4)); |
1486 | 2 | BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) |
1487 | 2 | .add(MI.getOperand(0)) |
1488 | 2 | .addImm(0) |
1489 | 2 | .addReg(Hexagon::VTMP); |
1490 | 2 | MBB.erase(MI); |
1491 | 2 | return First.getInstrIterator(); |
1492 | 33.4k | |
1493 | 33.4k | case Hexagon::V6_vgathermhwq_pseudo: |
1494 | 2 | First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhwq)) |
1495 | 2 | .add(MI.getOperand(1)) |
1496 | 2 | .add(MI.getOperand(2)) |
1497 | 2 | .add(MI.getOperand(3)) |
1498 | 2 | .add(MI.getOperand(4)); |
1499 | 2 | BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai)) |
1500 | 2 | .add(MI.getOperand(0)) |
1501 | 2 | .addImm(0) |
1502 | 2 | .addReg(Hexagon::VTMP); |
1503 | 2 | MBB.erase(MI); |
1504 | 2 | return First.getInstrIterator(); |
1505 | 33.4k | } |
1506 | 33.4k | |
1507 | 33.4k | return MI.getIterator(); |
1508 | 33.4k | } |
1509 | | |
1510 | | // We indicate that we want to reverse the branch by |
1511 | | // inserting the reversed branching opcode. |
1512 | | bool HexagonInstrInfo::reverseBranchCondition( |
1513 | 5.67k | SmallVectorImpl<MachineOperand> &Cond) const { |
1514 | 5.67k | if (Cond.empty()) |
1515 | 0 | return true; |
1516 | 5.67k | assert(Cond[0].isImm() && "First entry in the cond vector not imm-val"); |
1517 | 5.67k | unsigned opcode = Cond[0].getImm(); |
1518 | 5.67k | //unsigned temp; |
1519 | 5.67k | assert(get(opcode).isBranch() && "Should be a branching condition."); |
1520 | 5.67k | if (isEndLoopN(opcode)) |
1521 | 348 | return true; |
1522 | 5.32k | unsigned NewOpcode = getInvertedPredicatedOpcode(opcode); |
1523 | 5.32k | Cond[0].setImm(NewOpcode); |
1524 | 5.32k | return false; |
1525 | 5.32k | } |
1526 | | |
1527 | | void HexagonInstrInfo::insertNoop(MachineBasicBlock &MBB, |
1528 | 0 | MachineBasicBlock::iterator MI) const { |
1529 | 0 | DebugLoc DL; |
1530 | 0 | BuildMI(MBB, MI, DL, get(Hexagon::A2_nop)); |
1531 | 0 | } |
1532 | | |
1533 | 165k | bool HexagonInstrInfo::isPostIncrement(const MachineInstr &MI) const { |
1534 | 165k | return getAddrMode(MI) == HexagonII::PostInc; |
1535 | 165k | } |
1536 | | |
1537 | | // Returns true if an instruction is predicated irrespective of the predicate |
1538 | | // sense. For example, all of the following will return true. |
1539 | | // if (p0) R1 = add(R2, R3) |
1540 | | // if (!p0) R1 = add(R2, R3) |
1541 | | // if (p0.new) R1 = add(R2, R3) |
1542 | | // if (!p0.new) R1 = add(R2, R3) |
1543 | | // Note: New-value stores are not included here as in the current |
1544 | | // implementation, we don't need to check their predicate sense. |
1545 | 374k | bool HexagonInstrInfo::isPredicated(const MachineInstr &MI) const { |
1546 | 374k | const uint64_t F = MI.getDesc().TSFlags; |
1547 | 374k | return (F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask; |
1548 | 374k | } |
1549 | | |
1550 | | bool HexagonInstrInfo::PredicateInstruction( |
1551 | 285 | MachineInstr &MI, ArrayRef<MachineOperand> Cond) const { |
1552 | 285 | if (Cond.empty() || isNewValueJump(Cond[0].getImm()) || |
1553 | 285 | isEndLoopN(Cond[0].getImm())) { |
1554 | 0 | LLVM_DEBUG(dbgs() << "\nCannot predicate:"; MI.dump();); |
1555 | 0 | return false; |
1556 | 0 | } |
1557 | 285 | int Opc = MI.getOpcode(); |
1558 | 285 | assert (isPredicable(MI) && "Expected predicable instruction"); |
1559 | 285 | bool invertJump = predOpcodeHasNot(Cond); |
1560 | 285 | |
1561 | 285 | // We have to predicate MI "in place", i.e. after this function returns, |
1562 | 285 | // MI will need to be transformed into a predicated form. To avoid com- |
1563 | 285 | // plicated manipulations with the operands (handling tied operands, |
1564 | 285 | // etc.), build a new temporary instruction, then overwrite MI with it. |
1565 | 285 | |
1566 | 285 | MachineBasicBlock &B = *MI.getParent(); |
1567 | 285 | DebugLoc DL = MI.getDebugLoc(); |
1568 | 285 | unsigned PredOpc = getCondOpcode(Opc, invertJump); |
1569 | 285 | MachineInstrBuilder T = BuildMI(B, MI, DL, get(PredOpc)); |
1570 | 285 | unsigned NOp = 0, NumOps = MI.getNumOperands(); |
1571 | 406 | while (NOp < NumOps) { |
1572 | 406 | MachineOperand &Op = MI.getOperand(NOp); |
1573 | 406 | if (!Op.isReg() || !Op.isDef()357 || Op.isImplicit()121 ) |
1574 | 285 | break; |
1575 | 121 | T.add(Op); |
1576 | 121 | NOp++; |
1577 | 121 | } |
1578 | 285 | |
1579 | 285 | unsigned PredReg, PredRegPos, PredRegFlags; |
1580 | 285 | bool GotPredReg = getPredReg(Cond, PredReg, PredRegPos, PredRegFlags); |
1581 | 285 | (void)GotPredReg; |
1582 | 285 | assert(GotPredReg); |
1583 | 285 | T.addReg(PredReg, PredRegFlags); |
1584 | 970 | while (NOp < NumOps) |
1585 | 685 | T.add(MI.getOperand(NOp++)); |
1586 | 285 | |
1587 | 285 | MI.setDesc(get(PredOpc)); |
1588 | 1.09k | while (unsigned n = MI.getNumOperands()) |
1589 | 806 | MI.RemoveOperand(n-1); |
1590 | 1.58k | for (unsigned i = 0, n = T->getNumOperands(); i < n; ++i1.29k ) |
1591 | 1.29k | MI.addOperand(T->getOperand(i)); |
1592 | 285 | |
1593 | 285 | MachineBasicBlock::instr_iterator TI = T->getIterator(); |
1594 | 285 | B.erase(TI); |
1595 | 285 | |
1596 | 285 | MachineRegisterInfo &MRI = B.getParent()->getRegInfo(); |
1597 | 285 | MRI.clearKillFlags(PredReg); |
1598 | 285 | return true; |
1599 | 285 | } |
1600 | | |
1601 | | bool HexagonInstrInfo::SubsumesPredicate(ArrayRef<MachineOperand> Pred1, |
1602 | 1 | ArrayRef<MachineOperand> Pred2) const { |
1603 | 1 | // TODO: Fix this |
1604 | 1 | return false; |
1605 | 1 | } |
1606 | | |
1607 | | bool HexagonInstrInfo::DefinesPredicate(MachineInstr &MI, |
1608 | 9.13k | std::vector<MachineOperand> &Pred) const { |
1609 | 9.13k | const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); |
1610 | 9.13k | |
1611 | 34.9k | for (unsigned oper = 0; oper < MI.getNumOperands(); ++oper25.8k ) { |
1612 | 26.5k | MachineOperand MO = MI.getOperand(oper); |
1613 | 26.5k | if (MO.isReg()) { |
1614 | 20.4k | if (!MO.isDef()) |
1615 | 11.5k | continue; |
1616 | 8.86k | const TargetRegisterClass* RC = HRI.getMinimalPhysRegClass(MO.getReg()); |
1617 | 8.86k | if (RC == &Hexagon::PredRegsRegClass) { |
1618 | 499 | Pred.push_back(MO); |
1619 | 499 | return true; |
1620 | 499 | } |
1621 | 8.36k | continue; |
1622 | 8.36k | } else if (6.08k MO.isRegMask()6.08k ) { |
1623 | 147 | for (unsigned PR : Hexagon::PredRegsRegClass) { |
1624 | 147 | if (!MI.modifiesRegister(PR, &HRI)) |
1625 | 0 | continue; |
1626 | 147 | Pred.push_back(MO); |
1627 | 147 | return true; |
1628 | 147 | } |
1629 | 147 | } |
1630 | 26.5k | } |
1631 | 9.13k | return false8.48k ; |
1632 | 9.13k | } |
1633 | | |
1634 | 9.58k | bool HexagonInstrInfo::isPredicable(const MachineInstr &MI) const { |
1635 | 9.58k | if (!MI.getDesc().isPredicable()) |
1636 | 4.11k | return false; |
1637 | 5.47k | |
1638 | 5.47k | if (MI.isCall() || isTailCall(MI)5.35k ) { |
1639 | 134 | if (!Subtarget.usePredicatedCalls()) |
1640 | 134 | return false; |
1641 | 5.33k | } |
1642 | 5.33k | |
1643 | 5.33k | // HVX loads are not predicable on v60, but are on v62. |
1644 | 5.33k | if (!Subtarget.hasV62Ops()) { |
1645 | 5.24k | switch (MI.getOpcode()) { |
1646 | 5.24k | case Hexagon::V6_vL32b_ai: |
1647 | 150 | case Hexagon::V6_vL32b_pi: |
1648 | 150 | case Hexagon::V6_vL32b_ppu: |
1649 | 150 | case Hexagon::V6_vL32b_cur_ai: |
1650 | 150 | case Hexagon::V6_vL32b_cur_pi: |
1651 | 150 | case Hexagon::V6_vL32b_cur_ppu: |
1652 | 150 | case Hexagon::V6_vL32b_nt_ai: |
1653 | 150 | case Hexagon::V6_vL32b_nt_pi: |
1654 | 150 | case Hexagon::V6_vL32b_nt_ppu: |
1655 | 150 | case Hexagon::V6_vL32b_tmp_ai: |
1656 | 150 | case Hexagon::V6_vL32b_tmp_pi: |
1657 | 150 | case Hexagon::V6_vL32b_tmp_ppu: |
1658 | 150 | case Hexagon::V6_vL32b_nt_cur_ai: |
1659 | 150 | case Hexagon::V6_vL32b_nt_cur_pi: |
1660 | 150 | case Hexagon::V6_vL32b_nt_cur_ppu: |
1661 | 150 | case Hexagon::V6_vL32b_nt_tmp_ai: |
1662 | 150 | case Hexagon::V6_vL32b_nt_tmp_pi: |
1663 | 150 | case Hexagon::V6_vL32b_nt_tmp_ppu: |
1664 | 150 | return false; |
1665 | 5.18k | } |
1666 | 5.18k | } |
1667 | 5.18k | return true; |
1668 | 5.18k | } |
1669 | | |
1670 | | bool HexagonInstrInfo::isSchedulingBoundary(const MachineInstr &MI, |
1671 | | const MachineBasicBlock *MBB, |
1672 | 102k | const MachineFunction &MF) const { |
1673 | 102k | // Debug info is never a scheduling boundary. It's necessary to be explicit |
1674 | 102k | // due to the special treatment of IT instructions below, otherwise a |
1675 | 102k | // dbg_value followed by an IT will result in the IT instruction being |
1676 | 102k | // considered a scheduling hazard, which is wrong. It should be the actual |
1677 | 102k | // instruction preceding the dbg_value instruction(s), just like it is |
1678 | 102k | // when debug info is not present. |
1679 | 102k | if (MI.isDebugInstr()) |
1680 | 66 | return false; |
1681 | 102k | |
1682 | 102k | // Throwing call is a boundary. |
1683 | 102k | if (MI.isCall()) { |
1684 | 751 | // Don't mess around with no return calls. |
1685 | 751 | if (doesNotReturn(MI)) |
1686 | 47 | return true; |
1687 | 704 | // If any of the block's successors is a landing pad, this could be a |
1688 | 704 | // throwing call. |
1689 | 704 | for (auto I : MBB->successors()) |
1690 | 570 | if (I->isEHPad()) |
1691 | 22 | return true; |
1692 | 704 | } |
1693 | 102k | |
1694 | 102k | // Terminators and labels can't be scheduled around. |
1695 | 102k | if (102k MI.getDesc().isTerminator()102k || MI.isPosition()86.4k ) |
1696 | 16.2k | return true; |
1697 | 86.3k | |
1698 | 86.3k | if (MI.isInlineAsm() && !ScheduleInlineAsm99 ) |
1699 | 99 | return true; |
1700 | 86.2k | |
1701 | 86.2k | return false; |
1702 | 86.2k | } |
1703 | | |
1704 | | /// Measure the specified inline asm to determine an approximation of its |
1705 | | /// length. |
1706 | | /// Comments (which run till the next SeparatorString or newline) do not |
1707 | | /// count as an instruction. |
1708 | | /// Any other non-whitespace text is considered an instruction, with |
1709 | | /// multiple instructions separated by SeparatorString or newlines. |
1710 | | /// Variable-length instructions are not handled here; this function |
1711 | | /// may be overloaded in the target code to do that. |
1712 | | /// Hexagon counts the number of ##'s and adjust for that many |
1713 | | /// constant exenders. |
1714 | | unsigned HexagonInstrInfo::getInlineAsmLength(const char *Str, |
1715 | | const MCAsmInfo &MAI, |
1716 | 99 | const TargetSubtargetInfo *STI) const { |
1717 | 99 | StringRef AStr(Str); |
1718 | 99 | // Count the number of instructions in the asm. |
1719 | 99 | bool atInsnStart = true; |
1720 | 99 | unsigned Length = 0; |
1721 | 99 | const unsigned MaxInstLength = MAI.getMaxInstLength(STI); |
1722 | 3.32k | for (; *Str; ++Str3.22k ) { |
1723 | 3.22k | if (*Str == '\n' || strncmp(Str, MAI.getSeparatorString(), |
1724 | 3.09k | strlen(MAI.getSeparatorString())) == 0) |
1725 | 168 | atInsnStart = true; |
1726 | 3.22k | if (atInsnStart && !std::isspace(static_cast<unsigned char>(*Str))735 ) { |
1727 | 213 | Length += MaxInstLength; |
1728 | 213 | atInsnStart = false; |
1729 | 213 | } |
1730 | 3.22k | if (atInsnStart && strncmp(Str, MAI.getCommentString().data(), |
1731 | 522 | MAI.getCommentString().size()) == 0) |
1732 | 0 | atInsnStart = false; |
1733 | 3.22k | } |
1734 | 99 | |
1735 | 99 | // Add to size number of constant extenders seen * 4. |
1736 | 99 | StringRef Occ("##"); |
1737 | 99 | Length += AStr.count(Occ)*4; |
1738 | 99 | return Length; |
1739 | 99 | } |
1740 | | |
1741 | | ScheduleHazardRecognizer* |
1742 | | HexagonInstrInfo::CreateTargetPostRAHazardRecognizer( |
1743 | 3.35k | const InstrItineraryData *II, const ScheduleDAG *DAG) const { |
1744 | 3.35k | if (UseDFAHazardRec) |
1745 | 3.35k | return new HexagonHazardRecognizer(II, this, Subtarget); |
1746 | 0 | return TargetInstrInfo::CreateTargetPostRAHazardRecognizer(II, DAG); |
1747 | 0 | } |
1748 | | |
1749 | | /// For a comparison instruction, return the source registers in |
1750 | | /// \p SrcReg and \p SrcReg2 if having two register operands, and the value it |
1751 | | /// compares against in CmpValue. Return true if the comparison instruction |
1752 | | /// can be analyzed. |
1753 | | bool HexagonInstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, |
1754 | | unsigned &SrcReg2, int &Mask, |
1755 | 1.92k | int &Value) const { |
1756 | 1.92k | unsigned Opc = MI.getOpcode(); |
1757 | 1.92k | |
1758 | 1.92k | // Set mask and the first source register. |
1759 | 1.92k | switch (Opc) { |
1760 | 1.92k | case Hexagon::C2_cmpeq: |
1761 | 1.66k | case Hexagon::C2_cmpeqp: |
1762 | 1.66k | case Hexagon::C2_cmpgt: |
1763 | 1.66k | case Hexagon::C2_cmpgtp: |
1764 | 1.66k | case Hexagon::C2_cmpgtu: |
1765 | 1.66k | case Hexagon::C2_cmpgtup: |
1766 | 1.66k | case Hexagon::C4_cmpneq: |
1767 | 1.66k | case Hexagon::C4_cmplte: |
1768 | 1.66k | case Hexagon::C4_cmplteu: |
1769 | 1.66k | case Hexagon::C2_cmpeqi: |
1770 | 1.66k | case Hexagon::C2_cmpgti: |
1771 | 1.66k | case Hexagon::C2_cmpgtui: |
1772 | 1.66k | case Hexagon::C4_cmpneqi: |
1773 | 1.66k | case Hexagon::C4_cmplteui: |
1774 | 1.66k | case Hexagon::C4_cmpltei: |
1775 | 1.66k | SrcReg = MI.getOperand(1).getReg(); |
1776 | 1.66k | Mask = ~0; |
1777 | 1.66k | break; |
1778 | 1.66k | case Hexagon::A4_cmpbeq: |
1779 | 15 | case Hexagon::A4_cmpbgt: |
1780 | 15 | case Hexagon::A4_cmpbgtu: |
1781 | 15 | case Hexagon::A4_cmpbeqi: |
1782 | 15 | case Hexagon::A4_cmpbgti: |
1783 | 15 | case Hexagon::A4_cmpbgtui: |
1784 | 15 | SrcReg = MI.getOperand(1).getReg(); |
1785 | 15 | Mask = 0xFF; |
1786 | 15 | break; |
1787 | 15 | case Hexagon::A4_cmpheq: |
1788 | 1 | case Hexagon::A4_cmphgt: |
1789 | 1 | case Hexagon::A4_cmphgtu: |
1790 | 1 | case Hexagon::A4_cmpheqi: |
1791 | 1 | case Hexagon::A4_cmphgti: |
1792 | 1 | case Hexagon::A4_cmphgtui: |
1793 | 1 | SrcReg = MI.getOperand(1).getReg(); |
1794 | 1 | Mask = 0xFFFF; |
1795 | 1 | break; |
1796 | 1.92k | } |
1797 | 1.92k | |
1798 | 1.92k | // Set the value/second source register. |
1799 | 1.92k | switch (Opc) { |
1800 | 1.92k | case Hexagon::C2_cmpeq: |
1801 | 467 | case Hexagon::C2_cmpeqp: |
1802 | 467 | case Hexagon::C2_cmpgt: |
1803 | 467 | case Hexagon::C2_cmpgtp: |
1804 | 467 | case Hexagon::C2_cmpgtu: |
1805 | 467 | case Hexagon::C2_cmpgtup: |
1806 | 467 | case Hexagon::A4_cmpbeq: |
1807 | 467 | case Hexagon::A4_cmpbgt: |
1808 | 467 | case Hexagon::A4_cmpbgtu: |
1809 | 467 | case Hexagon::A4_cmpheq: |
1810 | 467 | case Hexagon::A4_cmphgt: |
1811 | 467 | case Hexagon::A4_cmphgtu: |
1812 | 467 | case Hexagon::C4_cmpneq: |
1813 | 467 | case Hexagon::C4_cmplte: |
1814 | 467 | case Hexagon::C4_cmplteu: |
1815 | 467 | SrcReg2 = MI.getOperand(2).getReg(); |
1816 | 467 | return true; |
1817 | 467 | |
1818 | 1.21k | case Hexagon::C2_cmpeqi: |
1819 | 1.21k | case Hexagon::C2_cmpgtui: |
1820 | 1.21k | case Hexagon::C2_cmpgti: |
1821 | 1.21k | case Hexagon::C4_cmpneqi: |
1822 | 1.21k | case Hexagon::C4_cmplteui: |
1823 | 1.21k | case Hexagon::C4_cmpltei: |
1824 | 1.21k | case Hexagon::A4_cmpbeqi: |
1825 | 1.21k | case Hexagon::A4_cmpbgti: |
1826 | 1.21k | case Hexagon::A4_cmpbgtui: |
1827 | 1.21k | case Hexagon::A4_cmpheqi: |
1828 | 1.21k | case Hexagon::A4_cmphgti: |
1829 | 1.21k | case Hexagon::A4_cmphgtui: { |
1830 | 1.21k | SrcReg2 = 0; |
1831 | 1.21k | const MachineOperand &Op2 = MI.getOperand(2); |
1832 | 1.21k | if (!Op2.isImm()) |
1833 | 0 | return false; |
1834 | 1.21k | Value = MI.getOperand(2).getImm(); |
1835 | 1.21k | return true; |
1836 | 1.21k | } |
1837 | 244 | } |
1838 | 244 | |
1839 | 244 | return false; |
1840 | 244 | } |
1841 | | |
1842 | | unsigned HexagonInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, |
1843 | | const MachineInstr &MI, |
1844 | 128k | unsigned *PredCost) const { |
1845 | 128k | return getInstrTimingClassLatency(ItinData, MI); |
1846 | 128k | } |
1847 | | |
1848 | | DFAPacketizer *HexagonInstrInfo::CreateTargetScheduleState( |
1849 | 15.7k | const TargetSubtargetInfo &STI) const { |
1850 | 15.7k | const InstrItineraryData *II = STI.getInstrItineraryData(); |
1851 | 15.7k | return static_cast<const HexagonSubtarget&>(STI).createDFAPacketizer(II); |
1852 | 15.7k | } |
1853 | | |
1854 | | // Inspired by this pair: |
1855 | | // %r13 = L2_loadri_io %r29, 136; mem:LD4[FixedStack0] |
1856 | | // S2_storeri_io %r29, 132, killed %r1; flags: mem:ST4[FixedStack1] |
1857 | | // Currently AA considers the addresses in these instructions to be aliasing. |
1858 | | bool HexagonInstrInfo::areMemAccessesTriviallyDisjoint( |
1859 | | const MachineInstr &MIa, const MachineInstr &MIb, |
1860 | 35.5k | AliasAnalysis *AA) const { |
1861 | 35.5k | if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects() || |
1862 | 35.5k | MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef()) |
1863 | 0 | return false; |
1864 | 35.5k | |
1865 | 35.5k | // Instructions that are pure loads, not loads and stores like memops are not |
1866 | 35.5k | // dependent. |
1867 | 35.5k | if (MIa.mayLoad() && !isMemOp(MIa)8.23k && MIb.mayLoad()8.16k && !isMemOp(MIb)21 ) |
1868 | 3 | return true; |
1869 | 35.5k | |
1870 | 35.5k | // Get the base register in MIa. |
1871 | 35.5k | unsigned BasePosA, OffsetPosA; |
1872 | 35.5k | if (!getBaseAndOffsetPosition(MIa, BasePosA, OffsetPosA)) |
1873 | 2.59k | return false; |
1874 | 32.9k | const MachineOperand &BaseA = MIa.getOperand(BasePosA); |
1875 | 32.9k | unsigned BaseRegA = BaseA.getReg(); |
1876 | 32.9k | unsigned BaseSubA = BaseA.getSubReg(); |
1877 | 32.9k | |
1878 | 32.9k | // Get the base register in MIb. |
1879 | 32.9k | unsigned BasePosB, OffsetPosB; |
1880 | 32.9k | if (!getBaseAndOffsetPosition(MIb, BasePosB, OffsetPosB)) |
1881 | 1.07k | return false; |
1882 | 31.9k | const MachineOperand &BaseB = MIb.getOperand(BasePosB); |
1883 | 31.9k | unsigned BaseRegB = BaseB.getReg(); |
1884 | 31.9k | unsigned BaseSubB = BaseB.getSubReg(); |
1885 | 31.9k | |
1886 | 31.9k | if (BaseRegA != BaseRegB || BaseSubA != BaseSubB21.7k ) |
1887 | 10.2k | return false; |
1888 | 21.7k | |
1889 | 21.7k | // Get the access sizes. |
1890 | 21.7k | unsigned SizeA = getMemAccessSize(MIa); |
1891 | 21.7k | unsigned SizeB = getMemAccessSize(MIb); |
1892 | 21.7k | |
1893 | 21.7k | // Get the offsets. Handle immediates only for now. |
1894 | 21.7k | const MachineOperand &OffA = MIa.getOperand(OffsetPosA); |
1895 | 21.7k | const MachineOperand &OffB = MIb.getOperand(OffsetPosB); |
1896 | 21.7k | if (!MIa.getOperand(OffsetPosA).isImm() || |
1897 | 21.7k | !MIb.getOperand(OffsetPosB).isImm()) |
1898 | 0 | return false; |
1899 | 21.7k | int OffsetA = isPostIncrement(MIa) ? 034 : OffA.getImm()21.6k ; |
1900 | 21.7k | int OffsetB = isPostIncrement(MIb) ? 0142 : OffB.getImm()21.5k ; |
1901 | 21.7k | |
1902 | 21.7k | // This is a mem access with the same base register and known offsets from it. |
1903 | 21.7k | // Reason about it. |
1904 | 21.7k | if (OffsetA > OffsetB) { |
1905 | 6.59k | uint64_t OffDiff = (uint64_t)((int64_t)OffsetA - (int64_t)OffsetB); |
1906 | 6.59k | return SizeB <= OffDiff; |
1907 | 6.59k | } |
1908 | 15.1k | if (OffsetA < OffsetB) { |
1909 | 13.5k | uint64_t OffDiff = (uint64_t)((int64_t)OffsetB - (int64_t)OffsetA); |
1910 | 13.5k | return SizeA <= OffDiff; |
1911 | 13.5k | } |
1912 | 1.54k | |
1913 | 1.54k | return false; |
1914 | 1.54k | } |
1915 | | |
1916 | | /// If the instruction is an increment of a constant value, return the amount. |
1917 | | bool HexagonInstrInfo::getIncrementValue(const MachineInstr &MI, |
1918 | 1.34k | int &Value) const { |
1919 | 1.34k | if (isPostIncrement(MI)) { |
1920 | 518 | unsigned BasePos = 0, OffsetPos = 0; |
1921 | 518 | if (!getBaseAndOffsetPosition(MI, BasePos, OffsetPos)) |
1922 | 0 | return false; |
1923 | 518 | const MachineOperand &OffsetOp = MI.getOperand(OffsetPos); |
1924 | 518 | if (OffsetOp.isImm()) { |
1925 | 518 | Value = OffsetOp.getImm(); |
1926 | 518 | return true; |
1927 | 518 | } |
1928 | 822 | } else if (MI.getOpcode() == Hexagon::A2_addi) { |
1929 | 683 | const MachineOperand &AddOp = MI.getOperand(2); |
1930 | 683 | if (AddOp.isImm()) { |
1931 | 683 | Value = AddOp.getImm(); |
1932 | 683 | return true; |
1933 | 683 | } |
1934 | 139 | } |
1935 | 139 | |
1936 | 139 | return false; |
1937 | 139 | } |
1938 | | |
1939 | | std::pair<unsigned, unsigned> |
1940 | 16 | HexagonInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { |
1941 | 16 | return std::make_pair(TF & ~HexagonII::MO_Bitmasks, |
1942 | 16 | TF & HexagonII::MO_Bitmasks); |
1943 | 16 | } |
1944 | | |
1945 | | ArrayRef<std::pair<unsigned, const char*>> |
1946 | 17 | HexagonInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { |
1947 | 17 | using namespace HexagonII; |
1948 | 17 | |
1949 | 17 | static const std::pair<unsigned, const char*> Flags[] = { |
1950 | 17 | {MO_PCREL, "hexagon-pcrel"}, |
1951 | 17 | {MO_GOT, "hexagon-got"}, |
1952 | 17 | {MO_LO16, "hexagon-lo16"}, |
1953 | 17 | {MO_HI16, "hexagon-hi16"}, |
1954 | 17 | {MO_GPREL, "hexagon-gprel"}, |
1955 | 17 | {MO_GDGOT, "hexagon-gdgot"}, |
1956 | 17 | {MO_GDPLT, "hexagon-gdplt"}, |
1957 | 17 | {MO_IE, "hexagon-ie"}, |
1958 | 17 | {MO_IEGOT, "hexagon-iegot"}, |
1959 | 17 | {MO_TPREL, "hexagon-tprel"} |
1960 | 17 | }; |
1961 | 17 | return makeArrayRef(Flags); |
1962 | 17 | } |
1963 | | |
1964 | | ArrayRef<std::pair<unsigned, const char*>> |
1965 | 4 | HexagonInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const { |
1966 | 4 | using namespace HexagonII; |
1967 | 4 | |
1968 | 4 | static const std::pair<unsigned, const char*> Flags[] = { |
1969 | 4 | {HMOTF_ConstExtended, "hexagon-ext"} |
1970 | 4 | }; |
1971 | 4 | return makeArrayRef(Flags); |
1972 | 4 | } |
1973 | | |
1974 | 258 | unsigned HexagonInstrInfo::createVR(MachineFunction *MF, MVT VT) const { |
1975 | 258 | MachineRegisterInfo &MRI = MF->getRegInfo(); |
1976 | 258 | const TargetRegisterClass *TRC; |
1977 | 258 | if (VT == MVT::i1) { |
1978 | 129 | TRC = &Hexagon::PredRegsRegClass; |
1979 | 129 | } else if (VT == MVT::i32 || VT == MVT::f320 ) { |
1980 | 129 | TRC = &Hexagon::IntRegsRegClass; |
1981 | 129 | } else if (0 VT == MVT::i640 || VT == MVT::f640 ) { |
1982 | 0 | TRC = &Hexagon::DoubleRegsRegClass; |
1983 | 0 | } else { |
1984 | 0 | llvm_unreachable("Cannot handle this register class"); |
1985 | 0 | } |
1986 | 258 | |
1987 | 258 | unsigned NewReg = MRI.createVirtualRegister(TRC); |
1988 | 258 | return NewReg; |
1989 | 258 | } |
1990 | | |
1991 | 0 | bool HexagonInstrInfo::isAbsoluteSet(const MachineInstr &MI) const { |
1992 | 0 | return (getAddrMode(MI) == HexagonII::AbsoluteSet); |
1993 | 0 | } |
1994 | | |
1995 | 0 | bool HexagonInstrInfo::isAccumulator(const MachineInstr &MI) const { |
1996 | 0 | const uint64_t F = MI.getDesc().TSFlags; |
1997 | 0 | return((F >> HexagonII::AccumulatorPos) & HexagonII::AccumulatorMask); |
1998 | 0 | } |
1999 | | |
2000 | 0 | bool HexagonInstrInfo::isBaseImmOffset(const MachineInstr &MI) const { |
2001 | 0 | return getAddrMode(MI) == HexagonII::BaseImmOffset; |
2002 | 0 | } |
2003 | | |
2004 | 0 | bool HexagonInstrInfo::isComplex(const MachineInstr &MI) const { |
2005 | 0 | return !isTC1(MI) && !isTC2Early(MI) && !MI.getDesc().mayLoad() && |
2006 | 0 | !MI.getDesc().mayStore() && |
2007 | 0 | MI.getDesc().getOpcode() != Hexagon::S2_allocframe && |
2008 | 0 | MI.getDesc().getOpcode() != Hexagon::L2_deallocframe && |
2009 | 0 | !isMemOp(MI) && !MI.isBranch() && !MI.isReturn() && !MI.isCall(); |
2010 | 0 | } |
2011 | | |
2012 | | // Return true if the instruction is a compund branch instruction. |
2013 | 0 | bool HexagonInstrInfo::isCompoundBranchInstr(const MachineInstr &MI) const { |
2014 | 0 | return getType(MI) == HexagonII::TypeCJ && MI.isBranch(); |
2015 | 0 | } |
2016 | | |
2017 | | // TODO: In order to have isExtendable for fpimm/f32Ext, we need to handle |
2018 | | // isFPImm and later getFPImm as well. |
2019 | 160k | bool HexagonInstrInfo::isConstExtended(const MachineInstr &MI) const { |
2020 | 160k | const uint64_t F = MI.getDesc().TSFlags; |
2021 | 160k | unsigned isExtended = (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask; |
2022 | 160k | if (isExtended) // Instruction must be extended. |
2023 | 1.10k | return true; |
2024 | 159k | |
2025 | 159k | unsigned isExtendable = |
2026 | 159k | (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask; |
2027 | 159k | if (!isExtendable) |
2028 | 106k | return false; |
2029 | 53.2k | |
2030 | 53.2k | if (MI.isCall()) |
2031 | 3.36k | return false; |
2032 | 49.8k | |
2033 | 49.8k | short ExtOpNum = getCExtOpNum(MI); |
2034 | 49.8k | const MachineOperand &MO = MI.getOperand(ExtOpNum); |
2035 | 49.8k | // Use MO operand flags to determine if MO |
2036 | 49.8k | // has the HMOTF_ConstExtended flag set. |
2037 | 49.8k | if (MO.getTargetFlags() & HexagonII::HMOTF_ConstExtended) |
2038 | 6 | return true; |
2039 | 49.8k | // If this is a Machine BB address we are talking about, and it is |
2040 | 49.8k | // not marked as extended, say so. |
2041 | 49.8k | if (MO.isMBB()) |
2042 | 5.89k | return false; |
2043 | 43.9k | |
2044 | 43.9k | // We could be using an instruction with an extendable immediate and shoehorn |
2045 | 43.9k | // a global address into it. If it is a global address it will be constant |
2046 | 43.9k | // extended. We do this for COMBINE. |
2047 | 43.9k | if (MO.isGlobal() || MO.isSymbol()39.8k || MO.isBlockAddress()39.7k || |
2048 | 43.9k | MO.isJTI()39.7k || MO.isCPI()39.7k || MO.isFPImm()38.8k ) |
2049 | 5.07k | return true; |
2050 | 38.8k | |
2051 | 38.8k | // If the extendable operand is not 'Immediate' type, the instruction should |
2052 | 38.8k | // have 'isExtended' flag set. |
2053 | 38.8k | assert(MO.isImm() && "Extendable operand must be Immediate type"); |
2054 | 38.8k | |
2055 | 38.8k | int MinValue = getMinValue(MI); |
2056 | 38.8k | int MaxValue = getMaxValue(MI); |
2057 | 38.8k | int ImmValue = MO.getImm(); |
2058 | 38.8k | |
2059 | 38.8k | return (ImmValue < MinValue || ImmValue > MaxValue38.6k ); |
2060 | 38.8k | } |
2061 | | |
2062 | 33.9k | bool HexagonInstrInfo::isDeallocRet(const MachineInstr &MI) const { |
2063 | 33.9k | switch (MI.getOpcode()) { |
2064 | 33.9k | case Hexagon::L4_return: |
2065 | 469 | case Hexagon::L4_return_t: |
2066 | 469 | case Hexagon::L4_return_f: |
2067 | 469 | case Hexagon::L4_return_tnew_pnt: |
2068 | 469 | case Hexagon::L4_return_fnew_pnt: |
2069 | 469 | case Hexagon::L4_return_tnew_pt: |
2070 | 469 | case Hexagon::L4_return_fnew_pt: |
2071 | 469 | return true; |
2072 | 33.4k | } |
2073 | 33.4k | return false; |
2074 | 33.4k | } |
2075 | | |
2076 | | // Return true when ConsMI uses a register defined by ProdMI. |
2077 | | bool HexagonInstrInfo::isDependent(const MachineInstr &ProdMI, |
2078 | 0 | const MachineInstr &ConsMI) const { |
2079 | 0 | if (!ProdMI.getDesc().getNumDefs()) |
2080 | 0 | return false; |
2081 | 0 | const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); |
2082 | 0 |
|
2083 | 0 | SmallVector<unsigned, 4> DefsA; |
2084 | 0 | SmallVector<unsigned, 4> DefsB; |
2085 | 0 | SmallVector<unsigned, 8> UsesA; |
2086 | 0 | SmallVector<unsigned, 8> UsesB; |
2087 | 0 |
|
2088 | 0 | parseOperands(ProdMI, DefsA, UsesA); |
2089 | 0 | parseOperands(ConsMI, DefsB, UsesB); |
2090 | 0 |
|
2091 | 0 | for (auto &RegA : DefsA) |
2092 | 0 | for (auto &RegB : UsesB) { |
2093 | 0 | // True data dependency. |
2094 | 0 | if (RegA == RegB) |
2095 | 0 | return true; |
2096 | 0 | |
2097 | 0 | if (TargetRegisterInfo::isPhysicalRegister(RegA)) |
2098 | 0 | for (MCSubRegIterator SubRegs(RegA, &HRI); SubRegs.isValid(); ++SubRegs) |
2099 | 0 | if (RegB == *SubRegs) |
2100 | 0 | return true; |
2101 | 0 |
|
2102 | 0 | if (TargetRegisterInfo::isPhysicalRegister(RegB)) |
2103 | 0 | for (MCSubRegIterator SubRegs(RegB, &HRI); SubRegs.isValid(); ++SubRegs) |
2104 | 0 | if (RegA == *SubRegs) |
2105 | 0 | return true; |
2106 | 0 | } |
2107 | 0 |
|
2108 | 0 | return false; |
2109 | 0 | } |
2110 | | |
2111 | | // Returns true if the instruction is alread a .cur. |
2112 | 14.8k | bool HexagonInstrInfo::isDotCurInst(const MachineInstr &MI) const { |
2113 | 14.8k | switch (MI.getOpcode()) { |
2114 | 14.8k | case Hexagon::V6_vL32b_cur_pi: |
2115 | 157 | case Hexagon::V6_vL32b_cur_ai: |
2116 | 157 | return true; |
2117 | 14.6k | } |
2118 | 14.6k | return false; |
2119 | 14.6k | } |
2120 | | |
2121 | | // Returns true, if any one of the operands is a dot new |
2122 | | // insn, whether it is predicated dot new or register dot new. |
2123 | 5.20k | bool HexagonInstrInfo::isDotNewInst(const MachineInstr &MI) const { |
2124 | 5.20k | if (isNewValueInst(MI) || (5.10k isPredicated(MI)5.10k && isPredicatedNew(MI)818 )) |
2125 | 340 | return true; |
2126 | 4.86k | |
2127 | 4.86k | return false; |
2128 | 4.86k | } |
2129 | | |
2130 | | /// Symmetrical. See if these two instructions are fit for duplex pair. |
2131 | | bool HexagonInstrInfo::isDuplexPair(const MachineInstr &MIa, |
2132 | 0 | const MachineInstr &MIb) const { |
2133 | 0 | HexagonII::SubInstructionGroup MIaG = getDuplexCandidateGroup(MIa); |
2134 | 0 | HexagonII::SubInstructionGroup MIbG = getDuplexCandidateGroup(MIb); |
2135 | 0 | return (isDuplexPairMatch(MIaG, MIbG) || isDuplexPairMatch(MIbG, MIaG)); |
2136 | 0 | } |
2137 | | |
2138 | 0 | bool HexagonInstrInfo::isEarlySourceInstr(const MachineInstr &MI) const { |
2139 | 0 | if (MI.mayLoad() || MI.mayStore() || MI.isCompare()) |
2140 | 0 | return true; |
2141 | 0 | |
2142 | 0 | // Multiply |
2143 | 0 | unsigned SchedClass = MI.getDesc().getSchedClass(); |
2144 | 0 | return is_TC4x(SchedClass) || is_TC3x(SchedClass); |
2145 | 0 | } |
2146 | | |
2147 | 62.4k | bool HexagonInstrInfo::isEndLoopN(unsigned Opcode) const { |
2148 | 62.4k | return (Opcode == Hexagon::ENDLOOP0 || |
2149 | 62.4k | Opcode == Hexagon::ENDLOOP156.0k ); |
2150 | 62.4k | } |
2151 | | |
2152 | | bool HexagonInstrInfo::isExpr(unsigned OpType) const { |
2153 | | switch(OpType) { |
2154 | | case MachineOperand::MO_MachineBasicBlock: |
2155 | | case MachineOperand::MO_GlobalAddress: |
2156 | | case MachineOperand::MO_ExternalSymbol: |
2157 | | case MachineOperand::MO_JumpTableIndex: |
2158 | | case MachineOperand::MO_ConstantPoolIndex: |
2159 | | case MachineOperand::MO_BlockAddress: |
2160 | | return true; |
2161 | | default: |
2162 | | return false; |
2163 | | } |
2164 | | } |
2165 | | |
2166 | 4.52k | bool HexagonInstrInfo::isExtendable(const MachineInstr &MI) const { |
2167 | 4.52k | const MCInstrDesc &MID = MI.getDesc(); |
2168 | 4.52k | const uint64_t F = MID.TSFlags; |
2169 | 4.52k | if ((F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask) |
2170 | 896 | return true; |
2171 | 3.63k | |
2172 | 3.63k | // TODO: This is largely obsolete now. Will need to be removed |
2173 | 3.63k | // in consecutive patches. |
2174 | 3.63k | switch (MI.getOpcode()) { |
2175 | 3.63k | // PS_fi and PS_fia remain special cases. |
2176 | 3.63k | case Hexagon::PS_fi: |
2177 | 0 | case Hexagon::PS_fia: |
2178 | 0 | return true; |
2179 | 3.63k | default: |
2180 | 3.63k | return false; |
2181 | 0 | } |
2182 | 0 | return false; |
2183 | 0 | } |
2184 | | |
2185 | | // This returns true in two cases: |
2186 | | // - The OP code itself indicates that this is an extended instruction. |
2187 | | // - One of MOs has been marked with HMOTF_ConstExtended flag. |
2188 | 122k | bool HexagonInstrInfo::isExtended(const MachineInstr &MI) const { |
2189 | 122k | // First check if this is permanently extended op code. |
2190 | 122k | const uint64_t F = MI.getDesc().TSFlags; |
2191 | 122k | if ((F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask) |
2192 | 210 | return true; |
2193 | 122k | // Use MO operand flags to determine if one of MI's operands |
2194 | 122k | // has HMOTF_ConstExtended flag set. |
2195 | 122k | for (const MachineOperand &MO : MI.operands()) |
2196 | 424k | if (MO.getTargetFlags() & HexagonII::HMOTF_ConstExtended) |
2197 | 52 | return true; |
2198 | 122k | return false122k ; |
2199 | 122k | } |
2200 | | |
2201 | 136 | bool HexagonInstrInfo::isFloat(const MachineInstr &MI) const { |
2202 | 136 | unsigned Opcode = MI.getOpcode(); |
2203 | 136 | const uint64_t F = get(Opcode).TSFlags; |
2204 | 136 | return (F >> HexagonII::FPPos) & HexagonII::FPMask; |
2205 | 136 | } |
2206 | | |
2207 | | // No V60 HVX VMEM with A_INDIRECT. |
2208 | | bool HexagonInstrInfo::isHVXMemWithAIndirect(const MachineInstr &I, |
2209 | 48.7k | const MachineInstr &J) const { |
2210 | 48.7k | if (!isHVXVec(I)) |
2211 | 32.7k | return false; |
2212 | 16.0k | if (!I.mayLoad() && !I.mayStore()13.8k ) |
2213 | 11.6k | return false; |
2214 | 4.38k | return J.isIndirectBranch() || isIndirectCall(J)3.82k || isIndirectL4Return(J)3.82k ; |
2215 | 4.38k | } |
2216 | | |
2217 | 3.82k | bool HexagonInstrInfo::isIndirectCall(const MachineInstr &MI) const { |
2218 | 3.82k | switch (MI.getOpcode()) { |
2219 | 3.82k | case Hexagon::J2_callr: |
2220 | 0 | case Hexagon::J2_callrf: |
2221 | 0 | case Hexagon::J2_callrt: |
2222 | 0 | case Hexagon::PS_call_nr: |
2223 | 0 | return true; |
2224 | 3.82k | } |
2225 | 3.82k | return false; |
2226 | 3.82k | } |
2227 | | |
2228 | 3.82k | bool HexagonInstrInfo::isIndirectL4Return(const MachineInstr &MI) const { |
2229 | 3.82k | switch (MI.getOpcode()) { |
2230 | 3.82k | case Hexagon::L4_return: |
2231 | 0 | case Hexagon::L4_return_t: |
2232 | 0 | case Hexagon::L4_return_f: |
2233 | 0 | case Hexagon::L4_return_fnew_pnt: |
2234 | 0 | case Hexagon::L4_return_fnew_pt: |
2235 | 0 | case Hexagon::L4_return_tnew_pnt: |
2236 | 0 | case Hexagon::L4_return_tnew_pt: |
2237 | 0 | return true; |
2238 | 3.82k | } |
2239 | 3.82k | return false; |
2240 | 3.82k | } |
2241 | | |
2242 | 11.6k | bool HexagonInstrInfo::isJumpR(const MachineInstr &MI) const { |
2243 | 11.6k | switch (MI.getOpcode()) { |
2244 | 11.6k | case Hexagon::J2_jumpr: |
2245 | 10 | case Hexagon::J2_jumprt: |
2246 | 10 | case Hexagon::J2_jumprf: |
2247 | 10 | case Hexagon::J2_jumprtnewpt: |
2248 | 10 | case Hexagon::J2_jumprfnewpt: |
2249 | 10 | case Hexagon::J2_jumprtnew: |
2250 | 10 | case Hexagon::J2_jumprfnew: |
2251 | 10 | return true; |
2252 | 11.6k | } |
2253 | 11.6k | return false; |
2254 | 11.6k | } |
2255 | | |
2256 | | // Return true if a given MI can accommodate given offset. |
2257 | | // Use abs estimate as oppose to the exact number. |
2258 | | // TODO: This will need to be changed to use MC level |
2259 | | // definition of instruction extendable field size. |
2260 | | bool HexagonInstrInfo::isJumpWithinBranchRange(const MachineInstr &MI, |
2261 | 1.05k | unsigned offset) const { |
2262 | 1.05k | // This selection of jump instructions matches to that what |
2263 | 1.05k | // analyzeBranch can parse, plus NVJ. |
2264 | 1.05k | if (isNewValueJump(MI)) // r9:2 |
2265 | 108 | return isInt<11>(offset); |
2266 | 946 | |
2267 | 946 | switch (MI.getOpcode()) { |
2268 | 946 | // Still missing Jump to address condition on register value. |
2269 | 946 | default: |
2270 | 231 | return false; |
2271 | 946 | case Hexagon::J2_jump: // bits<24> dst; // r22:2 |
2272 | 199 | case Hexagon::J2_call: |
2273 | 199 | case Hexagon::PS_call_nr: |
2274 | 199 | return isInt<24>(offset); |
2275 | 516 | case Hexagon::J2_jumpt: //bits<17> dst; // r15:2 |
2276 | 516 | case Hexagon::J2_jumpf: |
2277 | 516 | case Hexagon::J2_jumptnew: |
2278 | 516 | case Hexagon::J2_jumptnewpt: |
2279 | 516 | case Hexagon::J2_jumpfnew: |
2280 | 516 | case Hexagon::J2_jumpfnewpt: |
2281 | 516 | case Hexagon::J2_callt: |
2282 | 516 | case Hexagon::J2_callf: |
2283 | 516 | return isInt<17>(offset); |
2284 | 516 | case Hexagon::J2_loop0i: |
2285 | 0 | case Hexagon::J2_loop0iext: |
2286 | 0 | case Hexagon::J2_loop0r: |
2287 | 0 | case Hexagon::J2_loop0rext: |
2288 | 0 | case Hexagon::J2_loop1i: |
2289 | 0 | case Hexagon::J2_loop1iext: |
2290 | 0 | case Hexagon::J2_loop1r: |
2291 | 0 | case Hexagon::J2_loop1rext: |
2292 | 0 | return isInt<9>(offset); |
2293 | 0 | // TODO: Add all the compound branches here. Can we do this in Relation model? |
2294 | 0 | case Hexagon::J4_cmpeqi_tp0_jump_nt: |
2295 | 0 | case Hexagon::J4_cmpeqi_tp1_jump_nt: |
2296 | 0 | case Hexagon::J4_cmpeqn1_tp0_jump_nt: |
2297 | 0 | case Hexagon::J4_cmpeqn1_tp1_jump_nt: |
2298 | 0 | return isInt<11>(offset); |
2299 | 946 | } |
2300 | 946 | } |
2301 | | |
2302 | | bool HexagonInstrInfo::isLateInstrFeedsEarlyInstr(const MachineInstr &LRMI, |
2303 | 0 | const MachineInstr &ESMI) const { |
2304 | 0 | bool isLate = isLateResultInstr(LRMI); |
2305 | 0 | bool isEarly = isEarlySourceInstr(ESMI); |
2306 | 0 |
|
2307 | 0 | LLVM_DEBUG(dbgs() << "V60" << (isLate ? "-LR " : " -- ")); |
2308 | 0 | LLVM_DEBUG(LRMI.dump()); |
2309 | 0 | LLVM_DEBUG(dbgs() << "V60" << (isEarly ? "-ES " : " -- ")); |
2310 | 0 | LLVM_DEBUG(ESMI.dump()); |
2311 | 0 |
|
2312 | 0 | if (isLate && isEarly) { |
2313 | 0 | LLVM_DEBUG(dbgs() << "++Is Late Result feeding Early Source\n"); |
2314 | 0 | return true; |
2315 | 0 | } |
2316 | 0 |
|
2317 | 0 | return false; |
2318 | 0 | } |
2319 | | |
2320 | 0 | bool HexagonInstrInfo::isLateResultInstr(const MachineInstr &MI) const { |
2321 | 0 | switch (MI.getOpcode()) { |
2322 | 0 | case TargetOpcode::EXTRACT_SUBREG: |
2323 | 0 | case TargetOpcode::INSERT_SUBREG: |
2324 | 0 | case TargetOpcode::SUBREG_TO_REG: |
2325 | 0 | case TargetOpcode::REG_SEQUENCE: |
2326 | 0 | case TargetOpcode::IMPLICIT_DEF: |
2327 | 0 | case TargetOpcode::COPY: |
2328 | 0 | case TargetOpcode::INLINEASM: |
2329 | 0 | case TargetOpcode::PHI: |
2330 | 0 | return false; |
2331 | 0 | default: |
2332 | 0 | break; |
2333 | 0 | } |
2334 | 0 | |
2335 | 0 | unsigned SchedClass = MI.getDesc().getSchedClass(); |
2336 | 0 | return !is_TC1(SchedClass); |
2337 | 0 | } |
2338 | | |
2339 | 0 | bool HexagonInstrInfo::isLateSourceInstr(const MachineInstr &MI) const { |
2340 | 0 | // Instructions with iclass A_CVI_VX and attribute A_CVI_LATE uses a multiply |
2341 | 0 | // resource, but all operands can be received late like an ALU instruction. |
2342 | 0 | return getType(MI) == HexagonII::TypeCVI_VX_LATE; |
2343 | 0 | } |
2344 | | |
2345 | 47.9k | bool HexagonInstrInfo::isLoopN(const MachineInstr &MI) const { |
2346 | 47.9k | unsigned Opcode = MI.getOpcode(); |
2347 | 47.9k | return Opcode == Hexagon::J2_loop0i || |
2348 | 47.9k | Opcode == Hexagon::J2_loop0r47.9k || |
2349 | 47.9k | Opcode == Hexagon::J2_loop0iext47.6k || |
2350 | 47.9k | Opcode == Hexagon::J2_loop0rext47.6k || |
2351 | 47.9k | Opcode == Hexagon::J2_loop1i47.6k || |
2352 | 47.9k | Opcode == Hexagon::J2_loop1r47.6k || |
2353 | 47.9k | Opcode == Hexagon::J2_loop1iext47.6k || |
2354 | 47.9k | Opcode == Hexagon::J2_loop1rext47.6k ; |
2355 | 47.9k | } |
2356 | | |
2357 | 143k | bool HexagonInstrInfo::isMemOp(const MachineInstr &MI) const { |
2358 | 143k | switch (MI.getOpcode()) { |
2359 | 143k | default: return false142k ; |
2360 | 143k | case Hexagon::L4_iadd_memopw_io: |
2361 | 970 | case Hexagon::L4_isub_memopw_io: |
2362 | 970 | case Hexagon::L4_add_memopw_io: |
2363 | 970 | case Hexagon::L4_sub_memopw_io: |
2364 | 970 | case Hexagon::L4_and_memopw_io: |
2365 | 970 | case Hexagon::L4_or_memopw_io: |
2366 | 970 | case Hexagon::L4_iadd_memoph_io: |
2367 | 970 | case Hexagon::L4_isub_memoph_io: |
2368 | 970 | case Hexagon::L4_add_memoph_io: |
2369 | 970 | case Hexagon::L4_sub_memoph_io: |
2370 | 970 | case Hexagon::L4_and_memoph_io: |
2371 | 970 | case Hexagon::L4_or_memoph_io: |
2372 | 970 | case Hexagon::L4_iadd_memopb_io: |
2373 | 970 | case Hexagon::L4_isub_memopb_io: |
2374 | 970 | case Hexagon::L4_add_memopb_io: |
2375 | 970 | case Hexagon::L4_sub_memopb_io: |
2376 | 970 | case Hexagon::L4_and_memopb_io: |
2377 | 970 | case Hexagon::L4_or_memopb_io: |
2378 | 970 | case Hexagon::L4_ior_memopb_io: |
2379 | 970 | case Hexagon::L4_ior_memoph_io: |
2380 | 970 | case Hexagon::L4_ior_memopw_io: |
2381 | 970 | case Hexagon::L4_iand_memopb_io: |
2382 | 970 | case Hexagon::L4_iand_memoph_io: |
2383 | 970 | case Hexagon::L4_iand_memopw_io: |
2384 | 970 | return true; |
2385 | 0 | } |
2386 | 0 | return false; |
2387 | 0 | } |
2388 | | |
2389 | 110k | bool HexagonInstrInfo::isNewValue(const MachineInstr &MI) const { |
2390 | 110k | const uint64_t F = MI.getDesc().TSFlags; |
2391 | 110k | return (F >> HexagonII::NewValuePos) & HexagonII::NewValueMask; |
2392 | 110k | } |
2393 | | |
2394 | 4.94k | bool HexagonInstrInfo::isNewValue(unsigned Opcode) const { |
2395 | 4.94k | const uint64_t F = get(Opcode).TSFlags; |
2396 | 4.94k | return (F >> HexagonII::NewValuePos) & HexagonII::NewValueMask; |
2397 | 4.94k | } |
2398 | | |
2399 | 5.63k | bool HexagonInstrInfo::isNewValueInst(const MachineInstr &MI) const { |
2400 | 5.63k | return isNewValueJump(MI) || isNewValueStore(MI)5.53k ; |
2401 | 5.63k | } |
2402 | | |
2403 | 110k | bool HexagonInstrInfo::isNewValueJump(const MachineInstr &MI) const { |
2404 | 110k | return isNewValue(MI) && MI.isBranch()848 ; |
2405 | 110k | } |
2406 | | |
2407 | 4.94k | bool HexagonInstrInfo::isNewValueJump(unsigned Opcode) const { |
2408 | 4.94k | return isNewValue(Opcode) && get(Opcode).isBranch()0 && isPredicated(Opcode)0 ; |
2409 | 4.94k | } |
2410 | | |
2411 | 68.8k | bool HexagonInstrInfo::isNewValueStore(const MachineInstr &MI) const { |
2412 | 68.8k | const uint64_t F = MI.getDesc().TSFlags; |
2413 | 68.8k | return (F >> HexagonII::NVStorePos) & HexagonII::NVStoreMask; |
2414 | 68.8k | } |
2415 | | |
2416 | 21 | bool HexagonInstrInfo::isNewValueStore(unsigned Opcode) const { |
2417 | 21 | const uint64_t F = get(Opcode).TSFlags; |
2418 | 21 | return (F >> HexagonII::NVStorePos) & HexagonII::NVStoreMask; |
2419 | 21 | } |
2420 | | |
2421 | | // Returns true if a particular operand is extendable for an instruction. |
2422 | | bool HexagonInstrInfo::isOperandExtended(const MachineInstr &MI, |
2423 | 0 | unsigned OperandNum) const { |
2424 | 0 | const uint64_t F = MI.getDesc().TSFlags; |
2425 | 0 | return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask) |
2426 | 0 | == OperandNum; |
2427 | 0 | } |
2428 | | |
2429 | 886 | bool HexagonInstrInfo::isPredicatedNew(const MachineInstr &MI) const { |
2430 | 886 | const uint64_t F = MI.getDesc().TSFlags; |
2431 | 886 | assert(isPredicated(MI)); |
2432 | 886 | return (F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask; |
2433 | 886 | } |
2434 | | |
2435 | 21 | bool HexagonInstrInfo::isPredicatedNew(unsigned Opcode) const { |
2436 | 21 | const uint64_t F = get(Opcode).TSFlags; |
2437 | 21 | assert(isPredicated(Opcode)); |
2438 | 21 | return (F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask; |
2439 | 21 | } |
2440 | | |
2441 | 824 | bool HexagonInstrInfo::isPredicatedTrue(const MachineInstr &MI) const { |
2442 | 824 | const uint64_t F = MI.getDesc().TSFlags; |
2443 | 824 | return !((F >> HexagonII::PredicatedFalsePos) & |
2444 | 824 | HexagonII::PredicatedFalseMask); |
2445 | 824 | } |
2446 | | |
2447 | 6.97k | bool HexagonInstrInfo::isPredicatedTrue(unsigned Opcode) const { |
2448 | 6.97k | const uint64_t F = get(Opcode).TSFlags; |
2449 | 6.97k | // Make sure that the instruction is predicated. |
2450 | 6.97k | assert((F>> HexagonII::PredicatedPos) & HexagonII::PredicatedMask); |
2451 | 6.97k | return !((F >> HexagonII::PredicatedFalsePos) & |
2452 | 6.97k | HexagonII::PredicatedFalseMask); |
2453 | 6.97k | } |
2454 | | |
2455 | 594 | bool HexagonInstrInfo::isPredicated(unsigned Opcode) const { |
2456 | 594 | const uint64_t F = get(Opcode).TSFlags; |
2457 | 594 | return (F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask; |
2458 | 594 | } |
2459 | | |
2460 | 0 | bool HexagonInstrInfo::isPredicateLate(unsigned Opcode) const { |
2461 | 0 | const uint64_t F = get(Opcode).TSFlags; |
2462 | 0 | return (F >> HexagonII::PredicateLatePos) & HexagonII::PredicateLateMask; |
2463 | 0 | } |
2464 | | |
2465 | 0 | bool HexagonInstrInfo::isPredictedTaken(unsigned Opcode) const { |
2466 | 0 | const uint64_t F = get(Opcode).TSFlags; |
2467 | 0 | assert(get(Opcode).isBranch() && |
2468 | 0 | (isPredicatedNew(Opcode) || isNewValue(Opcode))); |
2469 | 0 | return (F >> HexagonII::TakenPos) & HexagonII::TakenMask; |
2470 | 0 | } |
2471 | | |
2472 | 47.9k | bool HexagonInstrInfo::isSaveCalleeSavedRegsCall(const MachineInstr &MI) const { |
2473 | 47.9k | return MI.getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4 || |
2474 | 47.9k | MI.getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4_EXT47.9k || |
2475 | 47.9k | MI.getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4_PIC47.9k || |
2476 | 47.9k | MI.getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4_EXT_PIC47.9k ; |
2477 | 47.9k | } |
2478 | | |
2479 | 69 | bool HexagonInstrInfo::isSignExtendingLoad(const MachineInstr &MI) const { |
2480 | 69 | switch (MI.getOpcode()) { |
2481 | 69 | // Byte |
2482 | 69 | case Hexagon::L2_loadrb_io: |
2483 | 0 | case Hexagon::L4_loadrb_ur: |
2484 | 0 | case Hexagon::L4_loadrb_ap: |
2485 | 0 | case Hexagon::L2_loadrb_pr: |
2486 | 0 | case Hexagon::L2_loadrb_pbr: |
2487 | 0 | case Hexagon::L2_loadrb_pi: |
2488 | 0 | case Hexagon::L2_loadrb_pci: |
2489 | 0 | case Hexagon::L2_loadrb_pcr: |
2490 | 0 | case Hexagon::L2_loadbsw2_io: |
2491 | 0 | case Hexagon::L4_loadbsw2_ur: |
2492 | 0 | case Hexagon::L4_loadbsw2_ap: |
2493 | 0 | case Hexagon::L2_loadbsw2_pr: |
2494 | 0 | case Hexagon::L2_loadbsw2_pbr: |
2495 | 0 | case Hexagon::L2_loadbsw2_pi: |
2496 | 0 | case Hexagon::L2_loadbsw2_pci: |
2497 | 0 | case Hexagon::L2_loadbsw2_pcr: |
2498 | 0 | case Hexagon::L2_loadbsw4_io: |
2499 | 0 | case Hexagon::L4_loadbsw4_ur: |
2500 | 0 | case Hexagon::L4_loadbsw4_ap: |
2501 | 0 | case Hexagon::L2_loadbsw4_pr: |
2502 | 0 | case Hexagon::L2_loadbsw4_pbr: |
2503 | 0 | case Hexagon::L2_loadbsw4_pi: |
2504 | 0 | case Hexagon::L2_loadbsw4_pci: |
2505 | 0 | case Hexagon::L2_loadbsw4_pcr: |
2506 | 0 | case Hexagon::L4_loadrb_rr: |
2507 | 0 | case Hexagon::L2_ploadrbt_io: |
2508 | 0 | case Hexagon::L2_ploadrbt_pi: |
2509 | 0 | case Hexagon::L2_ploadrbf_io: |
2510 | 0 | case Hexagon::L2_ploadrbf_pi: |
2511 | 0 | case Hexagon::L2_ploadrbtnew_io: |
2512 | 0 | case Hexagon::L2_ploadrbfnew_io: |
2513 | 0 | case Hexagon::L4_ploadrbt_rr: |
2514 | 0 | case Hexagon::L4_ploadrbf_rr: |
2515 | 0 | case Hexagon::L4_ploadrbtnew_rr: |
2516 | 0 | case Hexagon::L4_ploadrbfnew_rr: |
2517 | 0 | case Hexagon::L2_ploadrbtnew_pi: |
2518 | 0 | case Hexagon::L2_ploadrbfnew_pi: |
2519 | 0 | case Hexagon::L4_ploadrbt_abs: |
2520 | 0 | case Hexagon::L4_ploadrbf_abs: |
2521 | 0 | case Hexagon::L4_ploadrbtnew_abs: |
2522 | 0 | case Hexagon::L4_ploadrbfnew_abs: |
2523 | 0 | case Hexagon::L2_loadrbgp: |
2524 | 0 | // Half |
2525 | 0 | case Hexagon::L2_loadrh_io: |
2526 | 0 | case Hexagon::L4_loadrh_ur: |
2527 | 0 | case Hexagon::L4_loadrh_ap: |
2528 | 0 | case Hexagon::L2_loadrh_pr: |
2529 | 0 | case Hexagon::L2_loadrh_pbr: |
2530 | 0 | case Hexagon::L2_loadrh_pi: |
2531 | 0 | case Hexagon::L2_loadrh_pci: |
2532 | 0 | case Hexagon::L2_loadrh_pcr: |
2533 | 0 | case Hexagon::L4_loadrh_rr: |
2534 | 0 | case Hexagon::L2_ploadrht_io: |
2535 | 0 | case Hexagon::L2_ploadrht_pi: |
2536 | 0 | case Hexagon::L2_ploadrhf_io: |
2537 | 0 | case Hexagon::L2_ploadrhf_pi: |
2538 | 0 | case Hexagon::L2_ploadrhtnew_io: |
2539 | 0 | case Hexagon::L2_ploadrhfnew_io: |
2540 | 0 | case Hexagon::L4_ploadrht_rr: |
2541 | 0 | case Hexagon::L4_ploadrhf_rr: |
2542 | 0 | case Hexagon::L4_ploadrhtnew_rr: |
2543 | 0 | case Hexagon::L4_ploadrhfnew_rr: |
2544 | 0 | case Hexagon::L2_ploadrhtnew_pi: |
2545 | 0 | case Hexagon::L2_ploadrhfnew_pi: |
2546 | 0 | case Hexagon::L4_ploadrht_abs: |
2547 | 0 | case Hexagon::L4_ploadrhf_abs: |
2548 | 0 | case Hexagon::L4_ploadrhtnew_abs: |
2549 | 0 | case Hexagon::L4_ploadrhfnew_abs: |
2550 | 0 | case Hexagon::L2_loadrhgp: |
2551 | 0 | return true; |
2552 | 69 | default: |
2553 | 69 | return false; |
2554 | 69 | } |
2555 | 69 | } |
2556 | | |
2557 | 33.6k | bool HexagonInstrInfo::isSolo(const MachineInstr &MI) const { |
2558 | 33.6k | const uint64_t F = MI.getDesc().TSFlags; |
2559 | 33.6k | return (F >> HexagonII::SoloPos) & HexagonII::SoloMask; |
2560 | 33.6k | } |
2561 | | |
2562 | | bool HexagonInstrInfo::isSpillPredRegOp(const MachineInstr &MI) const { |
2563 | | switch (MI.getOpcode()) { |
2564 | | case Hexagon::STriw_pred: |
2565 | | case Hexagon::LDriw_pred: |
2566 | | return true; |
2567 | | default: |
2568 | | return false; |
2569 | | } |
2570 | | } |
2571 | | |
2572 | 14.6k | bool HexagonInstrInfo::isTailCall(const MachineInstr &MI) const { |
2573 | 14.6k | if (!MI.isBranch()) |
2574 | 13.7k | return false; |
2575 | 918 | |
2576 | 918 | for (auto &Op : MI.operands()) |
2577 | 2.35k | if (Op.isGlobal() || Op.isSymbol()2.29k ) |
2578 | 61 | return true; |
2579 | 918 | return false857 ; |
2580 | 918 | } |
2581 | | |
2582 | | // Returns true when SU has a timing class TC1. |
2583 | 0 | bool HexagonInstrInfo::isTC1(const MachineInstr &MI) const { |
2584 | 0 | unsigned SchedClass = MI.getDesc().getSchedClass(); |
2585 | 0 | return is_TC1(SchedClass); |
2586 | 0 | } |
2587 | | |
2588 | 0 | bool HexagonInstrInfo::isTC2(const MachineInstr &MI) const { |
2589 | 0 | unsigned SchedClass = MI.getDesc().getSchedClass(); |
2590 | 0 | return is_TC2(SchedClass); |
2591 | 0 | } |
2592 | | |
2593 | 0 | bool HexagonInstrInfo::isTC2Early(const MachineInstr &MI) const { |
2594 | 0 | unsigned SchedClass = MI.getDesc().getSchedClass(); |
2595 | 0 | return is_TC2early(SchedClass); |
2596 | 0 | } |
2597 | | |
2598 | 0 | bool HexagonInstrInfo::isTC4x(const MachineInstr &MI) const { |
2599 | 0 | unsigned SchedClass = MI.getDesc().getSchedClass(); |
2600 | 0 | return is_TC4x(SchedClass); |
2601 | 0 | } |
2602 | | |
2603 | | // Schedule this ASAP. |
2604 | | bool HexagonInstrInfo::isToBeScheduledASAP(const MachineInstr &MI1, |
2605 | 94.7k | const MachineInstr &MI2) const { |
2606 | 94.7k | if (mayBeCurLoad(MI1)) { |
2607 | 9.50k | // if (result of SU is used in Next) return true; |
2608 | 9.50k | unsigned DstReg = MI1.getOperand(0).getReg(); |
2609 | 9.50k | int N = MI2.getNumOperands(); |
2610 | 25.8k | for (int I = 0; I < N; I++16.2k ) |
2611 | 23.5k | if (MI2.getOperand(I).isReg() && DstReg == MI2.getOperand(I).getReg()22.8k ) |
2612 | 7.20k | return true; |
2613 | 9.50k | } |
2614 | 94.7k | if (87.5k mayBeNewStore(MI2)87.5k ) |
2615 | 9.46k | if (MI2.getOpcode() == Hexagon::V6_vS32b_pi) |
2616 | 154 | if (MI1.getOperand(0).isReg() && MI2.getOperand(3).isReg() && |
2617 | 154 | MI1.getOperand(0).getReg() == MI2.getOperand(3).getReg()) |
2618 | 111 | return true; |
2619 | 87.4k | return false; |
2620 | 87.4k | } |
2621 | | |
2622 | 228k | bool HexagonInstrInfo::isHVXVec(const MachineInstr &MI) const { |
2623 | 228k | const uint64_t V = getType(MI); |
2624 | 228k | return HexagonII::TypeCVI_FIRST <= V && V <= HexagonII::TypeCVI_LAST138k ; |
2625 | 228k | } |
2626 | | |
2627 | | // Check if the Offset is a valid auto-inc imm by Load/Store Type. |
2628 | 1.70k | bool HexagonInstrInfo::isValidAutoIncImm(const EVT VT, int Offset) const { |
2629 | 1.70k | int Size = VT.getSizeInBits() / 8; |
2630 | 1.70k | if (Offset % Size != 0) |
2631 | 23 | return false; |
2632 | 1.68k | int Count = Offset / Size; |
2633 | 1.68k | |
2634 | 1.68k | switch (VT.getSimpleVT().SimpleTy) { |
2635 | 1.68k | // For scalars the auto-inc is s4 |
2636 | 1.68k | case MVT::i8: |
2637 | 1.37k | case MVT::i16: |
2638 | 1.37k | case MVT::i32: |
2639 | 1.37k | case MVT::i64: |
2640 | 1.37k | case MVT::f32: |
2641 | 1.37k | case MVT::f64: |
2642 | 1.37k | case MVT::v2i16: |
2643 | 1.37k | case MVT::v2i32: |
2644 | 1.37k | case MVT::v4i8: |
2645 | 1.37k | case MVT::v4i16: |
2646 | 1.37k | case MVT::v8i8: |
2647 | 1.37k | return isInt<4>(Count); |
2648 | 1.37k | // For HVX vectors the auto-inc is s3 |
2649 | 1.37k | case MVT::v64i8: |
2650 | 307 | case MVT::v32i16: |
2651 | 307 | case MVT::v16i32: |
2652 | 307 | case MVT::v8i64: |
2653 | 307 | case MVT::v128i8: |
2654 | 307 | case MVT::v64i16: |
2655 | 307 | case MVT::v32i32: |
2656 | 307 | case MVT::v16i64: |
2657 | 307 | return isInt<3>(Count); |
2658 | 307 | default: |
2659 | 0 | break; |
2660 | 0 | } |
2661 | 0 | |
2662 | 0 | llvm_unreachable("Not an valid type!"); |
2663 | 0 | } |
2664 | | |
2665 | | bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset, |
2666 | 1.96k | const TargetRegisterInfo *TRI, bool Extend) const { |
2667 | 1.96k | // This function is to check whether the "Offset" is in the correct range of |
2668 | 1.96k | // the given "Opcode". If "Offset" is not in the correct range, "A2_addi" is |
2669 | 1.96k | // inserted to calculate the final address. Due to this reason, the function |
2670 | 1.96k | // assumes that the "Offset" has correct alignment. |
2671 | 1.96k | // We used to assert if the offset was not properly aligned, however, |
2672 | 1.96k | // there are cases where a misaligned pointer recast can cause this |
2673 | 1.96k | // problem, and we need to allow for it. The front end warns of such |
2674 | 1.96k | // misaligns with respect to load size. |
2675 | 1.96k | switch (Opcode) { |
2676 | 1.96k | case Hexagon::PS_vstorerq_ai: |
2677 | 65 | case Hexagon::PS_vstorerw_ai: |
2678 | 65 | case Hexagon::PS_vstorerw_nt_ai: |
2679 | 65 | case Hexagon::PS_vloadrq_ai: |
2680 | 65 | case Hexagon::PS_vloadrw_ai: |
2681 | 65 | case Hexagon::PS_vloadrw_nt_ai: |
2682 | 65 | case Hexagon::V6_vL32b_ai: |
2683 | 65 | case Hexagon::V6_vS32b_ai: |
2684 | 65 | case Hexagon::V6_vL32b_nt_ai: |
2685 | 65 | case Hexagon::V6_vS32b_nt_ai: |
2686 | 65 | case Hexagon::V6_vL32Ub_ai: |
2687 | 65 | case Hexagon::V6_vS32Ub_ai: { |
2688 | 65 | unsigned VectorSize = TRI->getSpillSize(Hexagon::HvxVRRegClass); |
2689 | 65 | assert(isPowerOf2_32(VectorSize)); |
2690 | 65 | if (Offset & (VectorSize-1)) |
2691 | 3 | return false; |
2692 | 62 | return isInt<4>(Offset >> Log2_32(VectorSize)); |
2693 | 62 | } |
2694 | 62 | |
2695 | 78 | case Hexagon::J2_loop0i: |
2696 | 78 | case Hexagon::J2_loop1i: |
2697 | 78 | return isUInt<10>(Offset); |
2698 | 78 | |
2699 | 78 | case Hexagon::S4_storeirb_io: |
2700 | 5 | case Hexagon::S4_storeirbt_io: |
2701 | 5 | case Hexagon::S4_storeirbf_io: |
2702 | 5 | return isUInt<6>(Offset); |
2703 | 5 | |
2704 | 8 | case Hexagon::S4_storeirh_io: |
2705 | 8 | case Hexagon::S4_storeirht_io: |
2706 | 8 | case Hexagon::S4_storeirhf_io: |
2707 | 8 | return isShiftedUInt<6,1>(Offset); |
2708 | 8 | |
2709 | 97 | case Hexagon::S4_storeiri_io: |
2710 | 97 | case Hexagon::S4_storeirit_io: |
2711 | 97 | case Hexagon::S4_storeirif_io: |
2712 | 97 | return isShiftedUInt<6,2>(Offset); |
2713 | 1.71k | } |
2714 | 1.71k | |
2715 | 1.71k | if (Extend) |
2716 | 1.70k | return true; |
2717 | 7 | |
2718 | 7 | switch (Opcode) { |
2719 | 7 | case Hexagon::L2_loadri_io: |
2720 | 3 | case Hexagon::S2_storeri_io: |
2721 | 3 | return (Offset >= Hexagon_MEMW_OFFSET_MIN) && |
2722 | 3 | (Offset <= Hexagon_MEMW_OFFSET_MAX); |
2723 | 3 | |
2724 | 3 | case Hexagon::L2_loadrd_io: |
2725 | 0 | case Hexagon::S2_storerd_io: |
2726 | 0 | return (Offset >= Hexagon_MEMD_OFFSET_MIN) && |
2727 | 0 | (Offset <= Hexagon_MEMD_OFFSET_MAX); |
2728 | 0 |
|
2729 | 1 | case Hexagon::L2_loadrh_io: |
2730 | 1 | case Hexagon::L2_loadruh_io: |
2731 | 1 | case Hexagon::S2_storerh_io: |
2732 | 1 | case Hexagon::S2_storerf_io: |
2733 | 1 | return (Offset >= Hexagon_MEMH_OFFSET_MIN) && |
2734 | 1 | (Offset <= Hexagon_MEMH_OFFSET_MAX); |
2735 | 1 | |
2736 | 3 | case Hexagon::L2_loadrb_io: |
2737 | 3 | case Hexagon::L2_loadrub_io: |
2738 | 3 | case Hexagon::S2_storerb_io: |
2739 | 3 | return (Offset >= Hexagon_MEMB_OFFSET_MIN) && |
2740 | 3 | (Offset <= Hexagon_MEMB_OFFSET_MAX); |
2741 | 3 | |
2742 | 3 | case Hexagon::A2_addi: |
2743 | 0 | return (Offset >= Hexagon_ADDI_OFFSET_MIN) && |
2744 | 0 | (Offset <= Hexagon_ADDI_OFFSET_MAX); |
2745 | 3 | |
2746 | 3 | case Hexagon::L4_iadd_memopw_io: |
2747 | 0 | case Hexagon::L4_isub_memopw_io: |
2748 | 0 | case Hexagon::L4_add_memopw_io: |
2749 | 0 | case Hexagon::L4_sub_memopw_io: |
2750 | 0 | case Hexagon::L4_and_memopw_io: |
2751 | 0 | case Hexagon::L4_or_memopw_io: |
2752 | 0 | return (0 <= Offset && Offset <= 255); |
2753 | 0 |
|
2754 | 0 | case Hexagon::L4_iadd_memoph_io: |
2755 | 0 | case Hexagon::L4_isub_memoph_io: |
2756 | 0 | case Hexagon::L4_add_memoph_io: |
2757 | 0 | case Hexagon::L4_sub_memoph_io: |
2758 | 0 | case Hexagon::L4_and_memoph_io: |
2759 | 0 | case Hexagon::L4_or_memoph_io: |
2760 | 0 | return (0 <= Offset && Offset <= 127); |
2761 | 0 |
|
2762 | 0 | case Hexagon::L4_iadd_memopb_io: |
2763 | 0 | case Hexagon::L4_isub_memopb_io: |
2764 | 0 | case Hexagon::L4_add_memopb_io: |
2765 | 0 | case Hexagon::L4_sub_memopb_io: |
2766 | 0 | case Hexagon::L4_and_memopb_io: |
2767 | 0 | case Hexagon::L4_or_memopb_io: |
2768 | 0 | return (0 <= Offset && Offset <= 63); |
2769 | 0 |
|
2770 | 0 | // LDriw_xxx and STriw_xxx are pseudo operations, so it has to take offset of |
2771 | 0 | // any size. Later pass knows how to handle it. |
2772 | 0 | case Hexagon::STriw_pred: |
2773 | 0 | case Hexagon::LDriw_pred: |
2774 | 0 | case Hexagon::STriw_ctr: |
2775 | 0 | case Hexagon::LDriw_ctr: |
2776 | 0 | return true; |
2777 | 0 |
|
2778 | 0 | case Hexagon::PS_fi: |
2779 | 0 | case Hexagon::PS_fia: |
2780 | 0 | case Hexagon::INLINEASM: |
2781 | 0 | return true; |
2782 | 0 |
|
2783 | 0 | case Hexagon::L2_ploadrbt_io: |
2784 | 0 | case Hexagon::L2_ploadrbf_io: |
2785 | 0 | case Hexagon::L2_ploadrubt_io: |
2786 | 0 | case Hexagon::L2_ploadrubf_io: |
2787 | 0 | case Hexagon::S2_pstorerbt_io: |
2788 | 0 | case Hexagon::S2_pstorerbf_io: |
2789 | 0 | return isUInt<6>(Offset); |
2790 | 0 |
|
2791 | 0 | case Hexagon::L2_ploadrht_io: |
2792 | 0 | case Hexagon::L2_ploadrhf_io: |
2793 | 0 | case Hexagon::L2_ploadruht_io: |
2794 | 0 | case Hexagon::L2_ploadruhf_io: |
2795 | 0 | case Hexagon::S2_pstorerht_io: |
2796 | 0 | case Hexagon::S2_pstorerhf_io: |
2797 | 0 | return isShiftedUInt<6,1>(Offset); |
2798 | 0 |
|
2799 | 0 | case Hexagon::L2_ploadrit_io: |
2800 | 0 | case Hexagon::L2_ploadrif_io: |
2801 | 0 | case Hexagon::S2_pstorerit_io: |
2802 | 0 | case Hexagon::S2_pstorerif_io: |
2803 | 0 | return isShiftedUInt<6,2>(Offset); |
2804 | 0 |
|
2805 | 0 | case Hexagon::L2_ploadrdt_io: |
2806 | 0 | case Hexagon::L2_ploadrdf_io: |
2807 | 0 | case Hexagon::S2_pstorerdt_io: |
2808 | 0 | case Hexagon::S2_pstorerdf_io: |
2809 | 0 | return isShiftedUInt<6,3>(Offset); |
2810 | 0 | } // switch |
2811 | 0 | |
2812 | 0 | llvm_unreachable("No offset range is defined for this opcode. " |
2813 | 0 | "Please define it in the above switch statement!"); |
2814 | 0 | } |
2815 | | |
2816 | 0 | bool HexagonInstrInfo::isVecAcc(const MachineInstr &MI) const { |
2817 | 0 | return isHVXVec(MI) && isAccumulator(MI); |
2818 | 0 | } |
2819 | | |
2820 | 0 | bool HexagonInstrInfo::isVecALU(const MachineInstr &MI) const { |
2821 | 0 | const uint64_t F = get(MI.getOpcode()).TSFlags; |
2822 | 0 | const uint64_t V = ((F >> HexagonII::TypePos) & HexagonII::TypeMask); |
2823 | 0 | return |
2824 | 0 | V == HexagonII::TypeCVI_VA || |
2825 | 0 | V == HexagonII::TypeCVI_VA_DV; |
2826 | 0 | } |
2827 | | |
2828 | | bool HexagonInstrInfo::isVecUsableNextPacket(const MachineInstr &ProdMI, |
2829 | 0 | const MachineInstr &ConsMI) const { |
2830 | 0 | if (EnableACCForwarding && isVecAcc(ProdMI) && isVecAcc(ConsMI)) |
2831 | 0 | return true; |
2832 | 0 | |
2833 | 0 | if (EnableALUForwarding && (isVecALU(ConsMI) || isLateSourceInstr(ConsMI))) |
2834 | 0 | return true; |
2835 | 0 | |
2836 | 0 | if (mayBeNewStore(ConsMI)) |
2837 | 0 | return true; |
2838 | 0 | |
2839 | 0 | return false; |
2840 | 0 | } |
2841 | | |
2842 | 69 | bool HexagonInstrInfo::isZeroExtendingLoad(const MachineInstr &MI) const { |
2843 | 69 | switch (MI.getOpcode()) { |
2844 | 69 | // Byte |
2845 | 69 | case Hexagon::L2_loadrub_io: |
2846 | 0 | case Hexagon::L4_loadrub_ur: |
2847 | 0 | case Hexagon::L4_loadrub_ap: |
2848 | 0 | case Hexagon::L2_loadrub_pr: |
2849 | 0 | case Hexagon::L2_loadrub_pbr: |
2850 | 0 | case Hexagon::L2_loadrub_pi: |
2851 | 0 | case Hexagon::L2_loadrub_pci: |
2852 | 0 | case Hexagon::L2_loadrub_pcr: |
2853 | 0 | case Hexagon::L2_loadbzw2_io: |
2854 | 0 | case Hexagon::L4_loadbzw2_ur: |
2855 | 0 | case Hexagon::L4_loadbzw2_ap: |
2856 | 0 | case Hexagon::L2_loadbzw2_pr: |
2857 | 0 | case Hexagon::L2_loadbzw2_pbr: |
2858 | 0 | case Hexagon::L2_loadbzw2_pi: |
2859 | 0 | case Hexagon::L2_loadbzw2_pci: |
2860 | 0 | case Hexagon::L2_loadbzw2_pcr: |
2861 | 0 | case Hexagon::L2_loadbzw4_io: |
2862 | 0 | case Hexagon::L4_loadbzw4_ur: |
2863 | 0 | case Hexagon::L4_loadbzw4_ap: |
2864 | 0 | case Hexagon::L2_loadbzw4_pr: |
2865 | 0 | case Hexagon::L2_loadbzw4_pbr: |
2866 | 0 | case Hexagon::L2_loadbzw4_pi: |
2867 | 0 | case Hexagon::L2_loadbzw4_pci: |
2868 | 0 | case Hexagon::L2_loadbzw4_pcr: |
2869 | 0 | case Hexagon::L4_loadrub_rr: |
2870 | 0 | case Hexagon::L2_ploadrubt_io: |
2871 | 0 | case Hexagon::L2_ploadrubt_pi: |
2872 | 0 | case Hexagon::L2_ploadrubf_io: |
2873 | 0 | case Hexagon::L2_ploadrubf_pi: |
2874 | 0 | case Hexagon::L2_ploadrubtnew_io: |
2875 | 0 | case Hexagon::L2_ploadrubfnew_io: |
2876 | 0 | case Hexagon::L4_ploadrubt_rr: |
2877 | 0 | case Hexagon::L4_ploadrubf_rr: |
2878 | 0 | case Hexagon::L4_ploadrubtnew_rr: |
2879 | 0 | case Hexagon::L4_ploadrubfnew_rr: |
2880 | 0 | case Hexagon::L2_ploadrubtnew_pi: |
2881 | 0 | case Hexagon::L2_ploadrubfnew_pi: |
2882 | 0 | case Hexagon::L4_ploadrubt_abs: |
2883 | 0 | case Hexagon::L4_ploadrubf_abs: |
2884 | 0 | case Hexagon::L4_ploadrubtnew_abs: |
2885 | 0 | case Hexagon::L4_ploadrubfnew_abs: |
2886 | 0 | case Hexagon::L2_loadrubgp: |
2887 | 0 | // Half |
2888 | 0 | case Hexagon::L2_loadruh_io: |
2889 | 0 | case Hexagon::L4_loadruh_ur: |
2890 | 0 | case Hexagon::L4_loadruh_ap: |
2891 | 0 | case Hexagon::L2_loadruh_pr: |
2892 | 0 | case Hexagon::L2_loadruh_pbr: |
2893 | 0 | case Hexagon::L2_loadruh_pi: |
2894 | 0 | case Hexagon::L2_loadruh_pci: |
2895 | 0 | case Hexagon::L2_loadruh_pcr: |
2896 | 0 | case Hexagon::L4_loadruh_rr: |
2897 | 0 | case Hexagon::L2_ploadruht_io: |
2898 | 0 | case Hexagon::L2_ploadruht_pi: |
2899 | 0 | case Hexagon::L2_ploadruhf_io: |
2900 | 0 | case Hexagon::L2_ploadruhf_pi: |
2901 | 0 | case Hexagon::L2_ploadruhtnew_io: |
2902 | 0 | case Hexagon::L2_ploadruhfnew_io: |
2903 | 0 | case Hexagon::L4_ploadruht_rr: |
2904 | 0 | case Hexagon::L4_ploadruhf_rr: |
2905 | 0 | case Hexagon::L4_ploadruhtnew_rr: |
2906 | 0 | case Hexagon::L4_ploadruhfnew_rr: |
2907 | 0 | case Hexagon::L2_ploadruhtnew_pi: |
2908 | 0 | case Hexagon::L2_ploadruhfnew_pi: |
2909 | 0 | case Hexagon::L4_ploadruht_abs: |
2910 | 0 | case Hexagon::L4_ploadruhf_abs: |
2911 | 0 | case Hexagon::L4_ploadruhtnew_abs: |
2912 | 0 | case Hexagon::L4_ploadruhfnew_abs: |
2913 | 0 | case Hexagon::L2_loadruhgp: |
2914 | 0 | return true; |
2915 | 69 | default: |
2916 | 69 | return false; |
2917 | 69 | } |
2918 | 69 | } |
2919 | | |
2920 | | // Add latency to instruction. |
2921 | | bool HexagonInstrInfo::addLatencyToSchedule(const MachineInstr &MI1, |
2922 | 0 | const MachineInstr &MI2) const { |
2923 | 0 | if (isHVXVec(MI1) && isHVXVec(MI2)) |
2924 | 0 | if (!isVecUsableNextPacket(MI1, MI2)) |
2925 | 0 | return true; |
2926 | 0 | return false; |
2927 | 0 | } |
2928 | | |
2929 | | /// Get the base register and byte offset of a load/store instr. |
2930 | | bool HexagonInstrInfo::getMemOperandWithOffset( |
2931 | | const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset, |
2932 | 2.38k | const TargetRegisterInfo *TRI) const { |
2933 | 2.38k | unsigned AccessSize = 0; |
2934 | 2.38k | BaseOp = getBaseAndOffset(LdSt, Offset, AccessSize); |
2935 | 2.38k | assert((!BaseOp || BaseOp->isReg()) && |
2936 | 2.38k | "getMemOperandWithOffset only supports base " |
2937 | 2.38k | "operands of type register."); |
2938 | 2.38k | return BaseOp != nullptr; |
2939 | 2.38k | } |
2940 | | |
2941 | | /// Can these instructions execute at the same time in a bundle. |
2942 | | bool HexagonInstrInfo::canExecuteInBundle(const MachineInstr &First, |
2943 | 175k | const MachineInstr &Second) const { |
2944 | 175k | if (Second.mayStore() && First.getOpcode() == Hexagon::S2_allocframe30.2k ) { |
2945 | 1.68k | const MachineOperand &Op = Second.getOperand(0); |
2946 | 1.68k | if (Op.isReg() && Op.isUse() && Op.getReg() == Hexagon::R29) |
2947 | 1.63k | return true; |
2948 | 173k | } |
2949 | 173k | if (DisableNVSchedule) |
2950 | 0 | return false; |
2951 | 173k | if (mayBeNewStore(Second)) { |
2952 | 21.8k | // Make sure the definition of the first instruction is the value being |
2953 | 21.8k | // stored. |
2954 | 21.8k | const MachineOperand &Stored = |
2955 | 21.8k | Second.getOperand(Second.getNumOperands() - 1); |
2956 | 21.8k | if (!Stored.isReg()) |
2957 | 0 | return false; |
2958 | 54.0k | for (unsigned i = 0, e = First.getNumOperands(); 21.8k i < e; ++i32.2k ) { |
2959 | 42.5k | const MachineOperand &Op = First.getOperand(i); |
2960 | 42.5k | if (Op.isReg() && Op.isDef()32.8k && Op.getReg() == Stored.getReg()17.4k ) |
2961 | 10.2k | return true; |
2962 | 42.5k | } |
2963 | 21.8k | } |
2964 | 173k | return false163k ; |
2965 | 173k | } |
2966 | | |
2967 | 780 | bool HexagonInstrInfo::doesNotReturn(const MachineInstr &CallMI) const { |
2968 | 780 | unsigned Opc = CallMI.getOpcode(); |
2969 | 780 | return Opc == Hexagon::PS_call_nr || Opc == Hexagon::PS_callr_nr735 ; |
2970 | 780 | } |
2971 | | |
2972 | 0 | bool HexagonInstrInfo::hasEHLabel(const MachineBasicBlock *B) const { |
2973 | 0 | for (auto &I : *B) |
2974 | 0 | if (I.isEHLabel()) |
2975 | 0 | return true; |
2976 | 0 | return false; |
2977 | 0 | } |
2978 | | |
2979 | | // Returns true if an instruction can be converted into a non-extended |
2980 | | // equivalent instruction. |
2981 | 0 | bool HexagonInstrInfo::hasNonExtEquivalent(const MachineInstr &MI) const { |
2982 | 0 | short NonExtOpcode; |
2983 | 0 | // Check if the instruction has a register form that uses register in place |
2984 | 0 | // of the extended operand, if so return that as the non-extended form. |
2985 | 0 | if (Hexagon::getRegForm(MI.getOpcode()) >= 0) |
2986 | 0 | return true; |
2987 | 0 | |
2988 | 0 | if (MI.getDesc().mayLoad() || MI.getDesc().mayStore()) { |
2989 | 0 | // Check addressing mode and retrieve non-ext equivalent instruction. |
2990 | 0 |
|
2991 | 0 | switch (getAddrMode(MI)) { |
2992 | 0 | case HexagonII::Absolute: |
2993 | 0 | // Load/store with absolute addressing mode can be converted into |
2994 | 0 | // base+offset mode. |
2995 | 0 | NonExtOpcode = Hexagon::changeAddrMode_abs_io(MI.getOpcode()); |
2996 | 0 | break; |
2997 | 0 | case HexagonII::BaseImmOffset: |
2998 | 0 | // Load/store with base+offset addressing mode can be converted into |
2999 | 0 | // base+register offset addressing mode. However left shift operand should |
3000 | 0 | // be set to 0. |
3001 | 0 | NonExtOpcode = Hexagon::changeAddrMode_io_rr(MI.getOpcode()); |
3002 | 0 | break; |
3003 | 0 | case HexagonII::BaseLongOffset: |
3004 | 0 | NonExtOpcode = Hexagon::changeAddrMode_ur_rr(MI.getOpcode()); |
3005 | 0 | break; |
3006 | 0 | default: |
3007 | 0 | return false; |
3008 | 0 | } |
3009 | 0 | if (NonExtOpcode < 0) |
3010 | 0 | return false; |
3011 | 0 | return true; |
3012 | 0 | } |
3013 | 0 | return false; |
3014 | 0 | } |
3015 | | |
3016 | 0 | bool HexagonInstrInfo::hasPseudoInstrPair(const MachineInstr &MI) const { |
3017 | 0 | return Hexagon::getRealHWInstr(MI.getOpcode(), |
3018 | 0 | Hexagon::InstrType_Pseudo) >= 0; |
3019 | 0 | } |
3020 | | |
3021 | | bool HexagonInstrInfo::hasUncondBranch(const MachineBasicBlock *B) |
3022 | 0 | const { |
3023 | 0 | MachineBasicBlock::const_iterator I = B->getFirstTerminator(), E = B->end(); |
3024 | 0 | while (I != E) { |
3025 | 0 | if (I->isBarrier()) |
3026 | 0 | return true; |
3027 | 0 | ++I; |
3028 | 0 | } |
3029 | 0 | return false; |
3030 | 0 | } |
3031 | | |
3032 | | // Returns true, if a LD insn can be promoted to a cur load. |
3033 | 299k | bool HexagonInstrInfo::mayBeCurLoad(const MachineInstr &MI) const { |
3034 | 299k | const uint64_t F = MI.getDesc().TSFlags; |
3035 | 299k | return ((F >> HexagonII::mayCVLoadPos) & HexagonII::mayCVLoadMask) && |
3036 | 299k | Subtarget.hasV60Ops()14.7k ; |
3037 | 299k | } |
3038 | | |
3039 | | // Returns true, if a ST insn can be promoted to a new-value store. |
3040 | 309k | bool HexagonInstrInfo::mayBeNewStore(const MachineInstr &MI) const { |
3041 | 309k | if (MI.mayStore() && !Subtarget.useNewValueStores()55.3k ) |
3042 | 216 | return false; |
3043 | 308k | |
3044 | 308k | const uint64_t F = MI.getDesc().TSFlags; |
3045 | 308k | return (F >> HexagonII::mayNVStorePos) & HexagonII::mayNVStoreMask; |
3046 | 308k | } |
3047 | | |
3048 | | bool HexagonInstrInfo::producesStall(const MachineInstr &ProdMI, |
3049 | 0 | const MachineInstr &ConsMI) const { |
3050 | 0 | // There is no stall when ProdMI is not a V60 vector. |
3051 | 0 | if (!isHVXVec(ProdMI)) |
3052 | 0 | return false; |
3053 | 0 | |
3054 | 0 | // There is no stall when ProdMI and ConsMI are not dependent. |
3055 | 0 | if (!isDependent(ProdMI, ConsMI)) |
3056 | 0 | return false; |
3057 | 0 | |
3058 | 0 | // When Forward Scheduling is enabled, there is no stall if ProdMI and ConsMI |
3059 | 0 | // are scheduled in consecutive packets. |
3060 | 0 | if (isVecUsableNextPacket(ProdMI, ConsMI)) |
3061 | 0 | return false; |
3062 | 0 | |
3063 | 0 | return true; |
3064 | 0 | } |
3065 | | |
3066 | | bool HexagonInstrInfo::producesStall(const MachineInstr &MI, |
3067 | 0 | MachineBasicBlock::const_instr_iterator BII) const { |
3068 | 0 | // There is no stall when I is not a V60 vector. |
3069 | 0 | if (!isHVXVec(MI)) |
3070 | 0 | return false; |
3071 | 0 | |
3072 | 0 | MachineBasicBlock::const_instr_iterator MII = BII; |
3073 | 0 | MachineBasicBlock::const_instr_iterator MIE = MII->getParent()->instr_end(); |
3074 | 0 |
|
3075 | 0 | if (!MII->isBundle()) |
3076 | 0 | return producesStall(*MII, MI); |
3077 | 0 | |
3078 | 0 | for (++MII; MII != MIE && MII->isInsideBundle(); ++MII) { |
3079 | 0 | const MachineInstr &J = *MII; |
3080 | 0 | if (producesStall(J, MI)) |
3081 | 0 | return true; |
3082 | 0 | } |
3083 | 0 | return false; |
3084 | 0 | } |
3085 | | |
3086 | | bool HexagonInstrInfo::predCanBeUsedAsDotNew(const MachineInstr &MI, |
3087 | 498 | unsigned PredReg) const { |
3088 | 1.48k | for (const MachineOperand &MO : MI.operands()) { |
3089 | 1.48k | // Predicate register must be explicitly defined. |
3090 | 1.48k | if (MO.isRegMask() && MO.clobbersPhysReg(PredReg)0 ) |
3091 | 0 | return false; |
3092 | 1.48k | if (MO.isReg() && MO.isDef()1.14k && MO.isImplicit()498 && (MO.getReg() == PredReg)0 ) |
3093 | 0 | return false; |
3094 | 1.48k | } |
3095 | 498 | |
3096 | 498 | // Instruction that produce late predicate cannot be used as sources of |
3097 | 498 | // dot-new. |
3098 | 498 | switch (MI.getOpcode()) { |
3099 | 498 | case Hexagon::A4_addp_c: |
3100 | 0 | case Hexagon::A4_subp_c: |
3101 | 0 | case Hexagon::A4_tlbmatch: |
3102 | 0 | case Hexagon::A5_ACS: |
3103 | 0 | case Hexagon::F2_sfinvsqrta: |
3104 | 0 | case Hexagon::F2_sfrecipa: |
3105 | 0 | case Hexagon::J2_endloop0: |
3106 | 0 | case Hexagon::J2_endloop01: |
3107 | 0 | case Hexagon::J2_ploop1si: |
3108 | 0 | case Hexagon::J2_ploop1sr: |
3109 | 0 | case Hexagon::J2_ploop2si: |
3110 | 0 | case Hexagon::J2_ploop2sr: |
3111 | 0 | case Hexagon::J2_ploop3si: |
3112 | 0 | case Hexagon::J2_ploop3sr: |
3113 | 0 | case Hexagon::S2_cabacdecbin: |
3114 | 0 | case Hexagon::S2_storew_locked: |
3115 | 0 | case Hexagon::S4_stored_locked: |
3116 | 0 | return false; |
3117 | 498 | } |
3118 | 498 | return true; |
3119 | 498 | } |
3120 | | |
3121 | 64.6k | bool HexagonInstrInfo::PredOpcodeHasJMP_c(unsigned Opcode) const { |
3122 | 64.6k | return Opcode == Hexagon::J2_jumpt || |
3123 | 64.6k | Opcode == Hexagon::J2_jumptpt54.5k || |
3124 | 64.6k | Opcode == Hexagon::J2_jumpf54.5k || |
3125 | 64.6k | Opcode == Hexagon::J2_jumpfpt39.8k || |
3126 | 64.6k | Opcode == Hexagon::J2_jumptnew39.8k || |
3127 | 64.6k | Opcode == Hexagon::J2_jumpfnew39.8k || |
3128 | 64.6k | Opcode == Hexagon::J2_jumptnewpt39.8k || |
3129 | 64.6k | Opcode == Hexagon::J2_jumpfnewpt39.8k ; |
3130 | 64.6k | } |
3131 | | |
3132 | 577 | bool HexagonInstrInfo::predOpcodeHasNot(ArrayRef<MachineOperand> Cond) const { |
3133 | 577 | if (Cond.empty() || !isPredicated(Cond[0].getImm())573 ) |
3134 | 4 | return false; |
3135 | 573 | return !isPredicatedTrue(Cond[0].getImm()); |
3136 | 573 | } |
3137 | | |
3138 | 203k | unsigned HexagonInstrInfo::getAddrMode(const MachineInstr &MI) const { |
3139 | 203k | const uint64_t F = MI.getDesc().TSFlags; |
3140 | 203k | return (F >> HexagonII::AddrModePos) & HexagonII::AddrModeMask; |
3141 | 203k | } |
3142 | | |
3143 | | // Returns the base register in a memory access (load/store). The offset is |
3144 | | // returned in Offset and the access size is returned in AccessSize. |
3145 | | // If the base operand has a subregister or the offset field does not contain |
3146 | | // an immediate value, return nullptr. |
3147 | | MachineOperand *HexagonInstrInfo::getBaseAndOffset(const MachineInstr &MI, |
3148 | | int64_t &Offset, |
3149 | 15.5k | unsigned &AccessSize) const { |
3150 | 15.5k | // Return if it is not a base+offset type instruction or a MemOp. |
3151 | 15.5k | if (getAddrMode(MI) != HexagonII::BaseImmOffset && |
3152 | 15.5k | getAddrMode(MI) != HexagonII::BaseLongOffset1.02k && |
3153 | 15.5k | !isMemOp(MI)1.02k && !isPostIncrement(MI)1.02k ) |
3154 | 154 | return nullptr; |
3155 | 15.3k | |
3156 | 15.3k | AccessSize = getMemAccessSize(MI); |
3157 | 15.3k | |
3158 | 15.3k | unsigned BasePos = 0, OffsetPos = 0; |
3159 | 15.3k | if (!getBaseAndOffsetPosition(MI, BasePos, OffsetPos)) |
3160 | 36 | return nullptr; |
3161 | 15.3k | |
3162 | 15.3k | // Post increment updates its EA after the mem access, |
3163 | 15.3k | // so we need to treat its offset as zero. |
3164 | 15.3k | if (isPostIncrement(MI)) { |
3165 | 869 | Offset = 0; |
3166 | 14.4k | } else { |
3167 | 14.4k | const MachineOperand &OffsetOp = MI.getOperand(OffsetPos); |
3168 | 14.4k | if (!OffsetOp.isImm()) |
3169 | 0 | return nullptr; |
3170 | 14.4k | Offset = OffsetOp.getImm(); |
3171 | 14.4k | } |
3172 | 15.3k | |
3173 | 15.3k | const MachineOperand &BaseOp = MI.getOperand(BasePos); |
3174 | 15.3k | if (BaseOp.getSubReg() != 0) |
3175 | 0 | return nullptr; |
3176 | 15.3k | return &const_cast<MachineOperand&>(BaseOp); |
3177 | 15.3k | } |
3178 | | |
3179 | | /// Return the position of the base and offset operands for this instruction. |
3180 | | bool HexagonInstrInfo::getBaseAndOffsetPosition(const MachineInstr &MI, |
3181 | 95.9k | unsigned &BasePos, unsigned &OffsetPos) const { |
3182 | 95.9k | if (!isAddrModeWithOffset(MI) && !isPostIncrement(MI)12.4k ) |
3183 | 9.13k | return false; |
3184 | 86.8k | |
3185 | 86.8k | // Deal with memops first. |
3186 | 86.8k | if (isMemOp(MI)) { |
3187 | 372 | BasePos = 0; |
3188 | 372 | OffsetPos = 1; |
3189 | 86.4k | } else if (MI.mayStore()) { |
3190 | 58.1k | BasePos = 0; |
3191 | 58.1k | OffsetPos = 1; |
3192 | 58.1k | } else if (28.3k MI.mayLoad()28.3k ) { |
3193 | 28.3k | BasePos = 1; |
3194 | 28.3k | OffsetPos = 2; |
3195 | 28.3k | } else |
3196 | 8 | return false; |
3197 | 86.8k | |
3198 | 86.8k | if (isPredicated(MI)) { |
3199 | 229 | BasePos++; |
3200 | 229 | OffsetPos++; |
3201 | 229 | } |
3202 | 86.8k | if (isPostIncrement(MI)) { |
3203 | 3.30k | BasePos++; |
3204 | 3.30k | OffsetPos++; |
3205 | 3.30k | } |
3206 | 86.8k | |
3207 | 86.8k | if (!MI.getOperand(BasePos).isReg() || !MI.getOperand(OffsetPos).isImm()84.6k ) |
3208 | 3.81k | return false; |
3209 | 83.0k | |
3210 | 83.0k | return true; |
3211 | 83.0k | } |
3212 | | |
3213 | | // Inserts branching instructions in reverse order of their occurrence. |
3214 | | // e.g. jump_t t1 (i1) |
3215 | | // jump t2 (i2) |
3216 | | // Jumpers = {i2, i1} |
3217 | | SmallVector<MachineInstr*, 2> HexagonInstrInfo::getBranchingInstrs( |
3218 | 0 | MachineBasicBlock& MBB) const { |
3219 | 0 | SmallVector<MachineInstr*, 2> Jumpers; |
3220 | 0 | // If the block has no terminators, it just falls into the block after it. |
3221 | 0 | MachineBasicBlock::instr_iterator I = MBB.instr_end(); |
3222 | 0 | if (I == MBB.instr_begin()) |
3223 | 0 | return Jumpers; |
3224 | 0 | |
3225 | 0 | // A basic block may looks like this: |
3226 | 0 | // |
3227 | 0 | // [ insn |
3228 | 0 | // EH_LABEL |
3229 | 0 | // insn |
3230 | 0 | // insn |
3231 | 0 | // insn |
3232 | 0 | // EH_LABEL |
3233 | 0 | // insn ] |
3234 | 0 | // |
3235 | 0 | // It has two succs but does not have a terminator |
3236 | 0 | // Don't know how to handle it. |
3237 | 0 | do { |
3238 | 0 | --I; |
3239 | 0 | if (I->isEHLabel()) |
3240 | 0 | return Jumpers; |
3241 | 0 | } while (I != MBB.instr_begin()); |
3242 | 0 |
|
3243 | 0 | I = MBB.instr_end(); |
3244 | 0 | --I; |
3245 | 0 |
|
3246 | 0 | while (I->isDebugInstr()) { |
3247 | 0 | if (I == MBB.instr_begin()) |
3248 | 0 | return Jumpers; |
3249 | 0 | --I; |
3250 | 0 | } |
3251 | 0 | if (!isUnpredicatedTerminator(*I)) |
3252 | 0 | return Jumpers; |
3253 | 0 | |
3254 | 0 | // Get the last instruction in the block. |
3255 | 0 | MachineInstr *LastInst = &*I; |
3256 | 0 | Jumpers.push_back(LastInst); |
3257 | 0 | MachineInstr *SecondLastInst = nullptr; |
3258 | 0 | // Find one more terminator if present. |
3259 | 0 | do { |
3260 | 0 | if (&*I != LastInst && !I->isBundle() && isUnpredicatedTerminator(*I)) { |
3261 | 0 | if (!SecondLastInst) { |
3262 | 0 | SecondLastInst = &*I; |
3263 | 0 | Jumpers.push_back(SecondLastInst); |
3264 | 0 | } else // This is a third branch. |
3265 | 0 | return Jumpers; |
3266 | 0 | } |
3267 | 0 | if (I == MBB.instr_begin()) |
3268 | 0 | break; |
3269 | 0 | --I; |
3270 | 0 | } while (true); |
3271 | 0 | return Jumpers; |
3272 | 0 | } |
3273 | | |
3274 | | // Returns Operand Index for the constant extended instruction. |
3275 | 51.8k | unsigned HexagonInstrInfo::getCExtOpNum(const MachineInstr &MI) const { |
3276 | 51.8k | const uint64_t F = MI.getDesc().TSFlags; |
3277 | 51.8k | return (F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask; |
3278 | 51.8k | } |
3279 | | |
3280 | | // See if instruction could potentially be a duplex candidate. |
3281 | | // If so, return its group. Zero otherwise. |
3282 | | HexagonII::CompoundGroup HexagonInstrInfo::getCompoundCandidateGroup( |
3283 | 0 | const MachineInstr &MI) const { |
3284 | 0 | unsigned DstReg, SrcReg, Src1Reg, Src2Reg; |
3285 | 0 |
|
3286 | 0 | switch (MI.getOpcode()) { |
3287 | 0 | default: |
3288 | 0 | return HexagonII::HCG_None; |
3289 | 0 | // |
3290 | 0 | // Compound pairs. |
3291 | 0 | // "p0=cmp.eq(Rs16,Rt16); if (p0.new) jump:nt #r9:2" |
3292 | 0 | // "Rd16=#U6 ; jump #r9:2" |
3293 | 0 | // "Rd16=Rs16 ; jump #r9:2" |
3294 | 0 | // |
3295 | 0 | case Hexagon::C2_cmpeq: |
3296 | 0 | case Hexagon::C2_cmpgt: |
3297 | 0 | case Hexagon::C2_cmpgtu: |
3298 | 0 | DstReg = MI.getOperand(0).getReg(); |
3299 | 0 | Src1Reg = MI.getOperand(1).getReg(); |
3300 | 0 | Src2Reg = MI.getOperand(2).getReg(); |
3301 | 0 | if (Hexagon::PredRegsRegClass.contains(DstReg) && |
3302 | 0 | (Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) && |
3303 | 0 | isIntRegForSubInst(Src1Reg) && isIntRegForSubInst(Src2Reg)) |
3304 | 0 | return HexagonII::HCG_A; |
3305 | 0 | break; |
3306 | 0 | case Hexagon::C2_cmpeqi: |
3307 | 0 | case Hexagon::C2_cmpgti: |
3308 | 0 | case Hexagon::C2_cmpgtui: |
3309 | 0 | // P0 = cmp.eq(Rs,#u2) |
3310 | 0 | DstReg = MI.getOperand(0).getReg(); |
3311 | 0 | SrcReg = MI.getOperand(1).getReg(); |
3312 | 0 | if (Hexagon::PredRegsRegClass.contains(DstReg) && |
3313 | 0 | (Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) && |
3314 | 0 | isIntRegForSubInst(SrcReg) && MI.getOperand(2).isImm() && |
3315 | 0 | ((isUInt<5>(MI.getOperand(2).getImm())) || |
3316 | 0 | (MI.getOperand(2).getImm() == -1))) |
3317 | 0 | return HexagonII::HCG_A; |
3318 | 0 | break; |
3319 | 0 | case Hexagon::A2_tfr: |
3320 | 0 | // Rd = Rs |
3321 | 0 | DstReg = MI.getOperand(0).getReg(); |
3322 | 0 | SrcReg = MI.getOperand(1).getReg(); |
3323 | 0 | if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg)) |
3324 | 0 | return HexagonII::HCG_A; |
3325 | 0 | break; |
3326 | 0 | case Hexagon::A2_tfrsi: |
3327 | 0 | // Rd = #u6 |
3328 | 0 | // Do not test for #u6 size since the const is getting extended |
3329 | 0 | // regardless and compound could be formed. |
3330 | 0 | DstReg = MI.getOperand(0).getReg(); |
3331 | 0 | if (isIntRegForSubInst(DstReg)) |
3332 | 0 | return HexagonII::HCG_A; |
3333 | 0 | break; |
3334 | 0 | case Hexagon::S2_tstbit_i: |
3335 | 0 | DstReg = MI.getOperand(0).getReg(); |
3336 | 0 | Src1Reg = MI.getOperand(1).getReg(); |
3337 | 0 | if (Hexagon::PredRegsRegClass.contains(DstReg) && |
3338 | 0 | (Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) && |
3339 | 0 | MI.getOperand(2).isImm() && |
3340 | 0 | isIntRegForSubInst(Src1Reg) && (MI.getOperand(2).getImm() == 0)) |
3341 | 0 | return HexagonII::HCG_A; |
3342 | 0 | break; |
3343 | 0 | // The fact that .new form is used pretty much guarantees |
3344 | 0 | // that predicate register will match. Nevertheless, |
3345 | 0 | // there could be some false positives without additional |
3346 | 0 | // checking. |
3347 | 0 | case Hexagon::J2_jumptnew: |
3348 | 0 | case Hexagon::J2_jumpfnew: |
3349 | 0 | case Hexagon::J2_jumptnewpt: |
3350 | 0 | case Hexagon::J2_jumpfnewpt: |
3351 | 0 | Src1Reg = MI.getOperand(0).getReg(); |
3352 | 0 | if (Hexagon::PredRegsRegClass.contains(Src1Reg) && |
3353 | 0 | (Hexagon::P0 == Src1Reg || Hexagon::P1 == Src1Reg)) |
3354 | 0 | return HexagonII::HCG_B; |
3355 | 0 | break; |
3356 | 0 | // Transfer and jump: |
3357 | 0 | // Rd=#U6 ; jump #r9:2 |
3358 | 0 | // Rd=Rs ; jump #r9:2 |
3359 | 0 | // Do not test for jump range here. |
3360 | 0 | case Hexagon::J2_jump: |
3361 | 0 | case Hexagon::RESTORE_DEALLOC_RET_JMP_V4: |
3362 | 0 | case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC: |
3363 | 0 | return HexagonII::HCG_C; |
3364 | 0 | } |
3365 | 0 | |
3366 | 0 | return HexagonII::HCG_None; |
3367 | 0 | } |
3368 | | |
3369 | | // Returns -1 when there is no opcode found. |
3370 | | unsigned HexagonInstrInfo::getCompoundOpcode(const MachineInstr &GA, |
3371 | 0 | const MachineInstr &GB) const { |
3372 | 0 | assert(getCompoundCandidateGroup(GA) == HexagonII::HCG_A); |
3373 | 0 | assert(getCompoundCandidateGroup(GB) == HexagonII::HCG_B); |
3374 | 0 | if ((GA.getOpcode() != Hexagon::C2_cmpeqi) || |
3375 | 0 | (GB.getOpcode() != Hexagon::J2_jumptnew)) |
3376 | 0 | return -1u; |
3377 | 0 | unsigned DestReg = GA.getOperand(0).getReg(); |
3378 | 0 | if (!GB.readsRegister(DestReg)) |
3379 | 0 | return -1u; |
3380 | 0 | if (DestReg != Hexagon::P0 && DestReg != Hexagon::P1) |
3381 | 0 | return -1u; |
3382 | 0 | // The value compared against must be either u5 or -1. |
3383 | 0 | const MachineOperand &CmpOp = GA.getOperand(2); |
3384 | 0 | if (!CmpOp.isImm()) |
3385 | 0 | return -1u; |
3386 | 0 | int V = CmpOp.getImm(); |
3387 | 0 | if (V == -1) |
3388 | 0 | return DestReg == Hexagon::P0 ? Hexagon::J4_cmpeqn1_tp0_jump_nt |
3389 | 0 | : Hexagon::J4_cmpeqn1_tp1_jump_nt; |
3390 | 0 | if (!isUInt<5>(V)) |
3391 | 0 | return -1u; |
3392 | 0 | return DestReg == Hexagon::P0 ? Hexagon::J4_cmpeqi_tp0_jump_nt |
3393 | 0 | : Hexagon::J4_cmpeqi_tp1_jump_nt; |
3394 | 0 | } |
3395 | | |
3396 | 389 | int HexagonInstrInfo::getCondOpcode(int Opc, bool invertPredicate) const { |
3397 | 389 | enum Hexagon::PredSense inPredSense; |
3398 | 389 | inPredSense = invertPredicate ? Hexagon::PredSense_false167 : |
3399 | 389 | Hexagon::PredSense_true222 ; |
3400 | 389 | int CondOpcode = Hexagon::getPredOpcode(Opc, inPredSense); |
3401 | 389 | if (CondOpcode >= 0) // Valid Conditional opcode/instruction |
3402 | 389 | return CondOpcode; |
3403 | 0 | |
3404 | 0 | llvm_unreachable("Unexpected predicable instruction"); |
3405 | 0 | } |
3406 | | |
3407 | | // Return the cur value instruction for a given store. |
3408 | 405 | int HexagonInstrInfo::getDotCurOp(const MachineInstr &MI) const { |
3409 | 405 | switch (MI.getOpcode()) { |
3410 | 405 | default: 0 llvm_unreachable0 ("Unknown .cur type"); |
3411 | 405 | case Hexagon::V6_vL32b_pi: |
3412 | 31 | return Hexagon::V6_vL32b_cur_pi; |
3413 | 405 | case Hexagon::V6_vL32b_ai: |
3414 | 373 | return Hexagon::V6_vL32b_cur_ai; |
3415 | 405 | case Hexagon::V6_vL32b_nt_pi: |
3416 | 0 | return Hexagon::V6_vL32b_nt_cur_pi; |
3417 | 405 | case Hexagon::V6_vL32b_nt_ai: |
3418 | 1 | return Hexagon::V6_vL32b_nt_cur_ai; |
3419 | 0 | } |
3420 | 0 | return 0; |
3421 | 0 | } |
3422 | | |
3423 | | // Return the regular version of the .cur instruction. |
3424 | 0 | int HexagonInstrInfo::getNonDotCurOp(const MachineInstr &MI) const { |
3425 | 0 | switch (MI.getOpcode()) { |
3426 | 0 | default: llvm_unreachable("Unknown .cur type"); |
3427 | 0 | case Hexagon::V6_vL32b_cur_pi: |
3428 | 0 | return Hexagon::V6_vL32b_pi; |
3429 | 0 | case Hexagon::V6_vL32b_cur_ai: |
3430 | 0 | return Hexagon::V6_vL32b_ai; |
3431 | 0 | case Hexagon::V6_vL32b_nt_cur_pi: |
3432 | 0 | return Hexagon::V6_vL32b_nt_pi; |
3433 | 0 | case Hexagon::V6_vL32b_nt_cur_ai: |
3434 | 0 | return Hexagon::V6_vL32b_nt_ai; |
3435 | 0 | } |
3436 | 0 | return 0; |
3437 | 0 | } |
3438 | | |
3439 | | // The diagram below shows the steps involved in the conversion of a predicated |
3440 | | // store instruction to its .new predicated new-value form. |
3441 | | // |
3442 | | // Note: It doesn't include conditional new-value stores as they can't be |
3443 | | // converted to .new predicate. |
3444 | | // |
3445 | | // p.new NV store [ if(p0.new)memw(R0+#0)=R2.new ] |
3446 | | // ^ ^ |
3447 | | // / \ (not OK. it will cause new-value store to be |
3448 | | // / X conditional on p0.new while R2 producer is |
3449 | | // / \ on p0) |
3450 | | // / \. |
3451 | | // p.new store p.old NV store |
3452 | | // [if(p0.new)memw(R0+#0)=R2] [if(p0)memw(R0+#0)=R2.new] |
3453 | | // ^ ^ |
3454 | | // \ / |
3455 | | // \ / |
3456 | | // \ / |
3457 | | // p.old store |
3458 | | // [if (p0)memw(R0+#0)=R2] |
3459 | | // |
3460 | | // The following set of instructions further explains the scenario where |
3461 | | // conditional new-value store becomes invalid when promoted to .new predicate |
3462 | | // form. |
3463 | | // |
3464 | | // { 1) if (p0) r0 = add(r1, r2) |
3465 | | // 2) p0 = cmp.eq(r3, #0) } |
3466 | | // |
3467 | | // 3) if (p0) memb(r1+#0) = r0 --> this instruction can't be grouped with |
3468 | | // the first two instructions because in instr 1, r0 is conditional on old value |
3469 | | // of p0 but its use in instr 3 is conditional on p0 modified by instr 2 which |
3470 | | // is not valid for new-value stores. |
3471 | | // Predicated new value stores (i.e. if (p0) memw(..)=r0.new) are excluded |
3472 | | // from the "Conditional Store" list. Because a predicated new value store |
3473 | | // would NOT be promoted to a double dot new store. See diagram below: |
3474 | | // This function returns yes for those stores that are predicated but not |
3475 | | // yet promoted to predicate dot new instructions. |
3476 | | // |
3477 | | // +---------------------+ |
3478 | | // /-----| if (p0) memw(..)=r0 |---------\~ |
3479 | | // || +---------------------+ || |
3480 | | // promote || /\ /\ || promote |
3481 | | // || /||\ /||\ || |
3482 | | // \||/ demote || \||/ |
3483 | | // \/ || || \/ |
3484 | | // +-------------------------+ || +-------------------------+ |
3485 | | // | if (p0.new) memw(..)=r0 | || | if (p0) memw(..)=r0.new | |
3486 | | // +-------------------------+ || +-------------------------+ |
3487 | | // || || || |
3488 | | // || demote \||/ |
3489 | | // promote || \/ NOT possible |
3490 | | // || || /\~ |
3491 | | // \||/ || /||\~ |
3492 | | // \/ || || |
3493 | | // +-----------------------------+ |
3494 | | // | if (p0.new) memw(..)=r0.new | |
3495 | | // +-----------------------------+ |
3496 | | // Double Dot New Store |
3497 | | // |
3498 | | // Returns the most basic instruction for the .new predicated instructions and |
3499 | | // new-value stores. |
3500 | | // For example, all of the following instructions will be converted back to the |
3501 | | // same instruction: |
3502 | | // 1) if (p0.new) memw(R0+#0) = R1.new ---> |
3503 | | // 2) if (p0) memw(R0+#0)= R1.new -------> if (p0) memw(R0+#0) = R1 |
3504 | | // 3) if (p0.new) memw(R0+#0) = R1 ---> |
3505 | | // |
3506 | | // To understand the translation of instruction 1 to its original form, consider |
3507 | | // a packet with 3 instructions. |
3508 | | // { p0 = cmp.eq(R0,R1) |
3509 | | // if (p0.new) R2 = add(R3, R4) |
3510 | | // R5 = add (R3, R1) |
3511 | | // } |
3512 | | // if (p0) memw(R5+#0) = R2 <--- trying to include it in the previous packet |
3513 | | // |
3514 | | // This instruction can be part of the previous packet only if both p0 and R2 |
3515 | | // are promoted to .new values. This promotion happens in steps, first |
3516 | | // predicate register is promoted to .new and in the next iteration R2 is |
3517 | | // promoted. Therefore, in case of dependence check failure (due to R5) during |
3518 | | // next iteration, it should be converted back to its most basic form. |
3519 | | |
3520 | | // Return the new value instruction for a given store. |
3521 | 1.98k | int HexagonInstrInfo::getDotNewOp(const MachineInstr &MI) const { |
3522 | 1.98k | int NVOpcode = Hexagon::getNewValueOpcode(MI.getOpcode()); |
3523 | 1.98k | if (NVOpcode >= 0) // Valid new-value store instruction. |
3524 | 1.98k | return NVOpcode; |
3525 | 0 | |
3526 | 0 | switch (MI.getOpcode()) { |
3527 | 0 | default: |
3528 | 0 | report_fatal_error(std::string("Unknown .new type: ") + |
3529 | 0 | std::to_string(MI.getOpcode())); |
3530 | 0 | case Hexagon::S4_storerb_ur: |
3531 | 0 | return Hexagon::S4_storerbnew_ur; |
3532 | 0 |
|
3533 | 0 | case Hexagon::S2_storerb_pci: |
3534 | 0 | return Hexagon::S2_storerb_pci; |
3535 | 0 |
|
3536 | 0 | case Hexagon::S2_storeri_pci: |
3537 | 0 | return Hexagon::S2_storeri_pci; |
3538 | 0 |
|
3539 | 0 | case Hexagon::S2_storerh_pci: |
3540 | 0 | return Hexagon::S2_storerh_pci; |
3541 | 0 |
|
3542 | 0 | case Hexagon::S2_storerd_pci: |
3543 | 0 | return Hexagon::S2_storerd_pci; |
3544 | 0 |
|
3545 | 0 | case Hexagon::S2_storerf_pci: |
3546 | 0 | return Hexagon::S2_storerf_pci; |
3547 | 0 |
|
3548 | 0 | case Hexagon::V6_vS32b_ai: |
3549 | 0 | return Hexagon::V6_vS32b_new_ai; |
3550 | 0 |
|
3551 | 0 | case Hexagon::V6_vS32b_pi: |
3552 | 0 | return Hexagon::V6_vS32b_new_pi; |
3553 | 0 | } |
3554 | 0 | return 0; |
3555 | 0 | } |
3556 | | |
3557 | | // Returns the opcode to use when converting MI, which is a conditional jump, |
3558 | | // into a conditional instruction which uses the .new value of the predicate. |
3559 | | // We also use branch probabilities to add a hint to the jump. |
3560 | | // If MBPI is null, all edges will be treated as equally likely for the |
3561 | | // purposes of establishing a predication hint. |
3562 | | int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI, |
3563 | 352 | const MachineBranchProbabilityInfo *MBPI) const { |
3564 | 352 | // We assume that block can have at most two successors. |
3565 | 352 | const MachineBasicBlock *Src = MI.getParent(); |
3566 | 352 | const MachineOperand &BrTarget = MI.getOperand(1); |
3567 | 352 | bool Taken = false; |
3568 | 352 | const BranchProbability OneHalf(1, 2); |
3569 | 352 | |
3570 | 352 | auto getEdgeProbability = [MBPI] (const MachineBasicBlock *Src, |
3571 | 352 | const MachineBasicBlock *Dst) { |
3572 | 352 | if (MBPI) |
3573 | 176 | return MBPI->getEdgeProbability(Src, Dst); |
3574 | 176 | return BranchProbability(1, Src->succ_size()); |
3575 | 176 | }; |
3576 | 352 | |
3577 | 352 | if (BrTarget.isMBB()) { |
3578 | 352 | const MachineBasicBlock *Dst = BrTarget.getMBB(); |
3579 | 352 | Taken = getEdgeProbability(Src, Dst) >= OneHalf; |
3580 | 352 | } else { |
3581 | 0 | // The branch target is not a basic block (most likely a function). |
3582 | 0 | // Since BPI only gives probabilities for targets that are basic blocks, |
3583 | 0 | // try to identify another target of this branch (potentially a fall- |
3584 | 0 | // -through) and check the probability of that target. |
3585 | 0 | // |
3586 | 0 | // The only handled branch combinations are: |
3587 | 0 | // - one conditional branch, |
3588 | 0 | // - one conditional branch followed by one unconditional branch. |
3589 | 0 | // Otherwise, assume not-taken. |
3590 | 0 | assert(MI.isConditionalBranch()); |
3591 | 0 | const MachineBasicBlock &B = *MI.getParent(); |
3592 | 0 | bool SawCond = false, Bad = false; |
3593 | 0 | for (const MachineInstr &I : B) { |
3594 | 0 | if (!I.isBranch()) |
3595 | 0 | continue; |
3596 | 0 | if (I.isConditionalBranch()) { |
3597 | 0 | SawCond = true; |
3598 | 0 | if (&I != &MI) { |
3599 | 0 | Bad = true; |
3600 | 0 | break; |
3601 | 0 | } |
3602 | 0 | } |
3603 | 0 | if (I.isUnconditionalBranch() && !SawCond) { |
3604 | 0 | Bad = true; |
3605 | 0 | break; |
3606 | 0 | } |
3607 | 0 | } |
3608 | 0 | if (!Bad) { |
3609 | 0 | MachineBasicBlock::const_instr_iterator It(MI); |
3610 | 0 | MachineBasicBlock::const_instr_iterator NextIt = std::next(It); |
3611 | 0 | if (NextIt == B.instr_end()) { |
3612 | 0 | // If this branch is the last, look for the fall-through block. |
3613 | 0 | for (const MachineBasicBlock *SB : B.successors()) { |
3614 | 0 | if (!B.isLayoutSuccessor(SB)) |
3615 | 0 | continue; |
3616 | 0 | Taken = getEdgeProbability(Src, SB) < OneHalf; |
3617 | 0 | break; |
3618 | 0 | } |
3619 | 0 | } else { |
3620 | 0 | assert(NextIt->isUnconditionalBranch()); |
3621 | 0 | // Find the first MBB operand and assume it's the target. |
3622 | 0 | const MachineBasicBlock *BT = nullptr; |
3623 | 0 | for (const MachineOperand &Op : NextIt->operands()) { |
3624 | 0 | if (!Op.isMBB()) |
3625 | 0 | continue; |
3626 | 0 | BT = Op.getMBB(); |
3627 | 0 | break; |
3628 | 0 | } |
3629 | 0 | Taken = BT && getEdgeProbability(Src, BT) < OneHalf; |
3630 | 0 | } |
3631 | 0 | } // if (!Bad) |
3632 | 0 | } |
3633 | 352 | |
3634 | 352 | // The Taken flag should be set to something reasonable by this point. |
3635 | 352 | |
3636 | 352 | switch (MI.getOpcode()) { |
3637 | 352 | case Hexagon::J2_jumpt: |
3638 | 166 | return Taken ? Hexagon::J2_jumptnewpt120 : Hexagon::J2_jumptnew46 ; |
3639 | 352 | case Hexagon::J2_jumpf: |
3640 | 186 | return Taken ? Hexagon::J2_jumpfnewpt159 : Hexagon::J2_jumpfnew27 ; |
3641 | 352 | |
3642 | 352 | default: |
3643 | 0 | llvm_unreachable("Unexpected jump instruction."); |
3644 | 352 | } |
3645 | 352 | } |
3646 | | |
3647 | | // Return .new predicate version for an instruction. |
3648 | | int HexagonInstrInfo::getDotNewPredOp(const MachineInstr &MI, |
3649 | 999 | const MachineBranchProbabilityInfo *MBPI) const { |
3650 | 999 | switch (MI.getOpcode()) { |
3651 | 999 | // Condtional Jumps |
3652 | 999 | case Hexagon::J2_jumpt: |
3653 | 352 | case Hexagon::J2_jumpf: |
3654 | 352 | return getDotNewPredJumpOp(MI, MBPI); |
3655 | 647 | } |
3656 | 647 | |
3657 | 647 | int NewOpcode = Hexagon::getPredNewOpcode(MI.getOpcode()); |
3658 | 647 | if (NewOpcode >= 0) |
3659 | 644 | return NewOpcode; |
3660 | 3 | return 0; |
3661 | 3 | } |
3662 | | |
3663 | 21 | int HexagonInstrInfo::getDotOldOp(const MachineInstr &MI) const { |
3664 | 21 | int NewOp = MI.getOpcode(); |
3665 | 21 | if (isPredicated(NewOp) && isPredicatedNew(NewOp)) { // Get predicate old form |
3666 | 21 | NewOp = Hexagon::getPredOldOpcode(NewOp); |
3667 | 21 | // All Hexagon architectures have prediction bits on dot-new branches, |
3668 | 21 | // but only Hexagon V60+ has prediction bits on dot-old ones. Make sure |
3669 | 21 | // to pick the right opcode when converting back to dot-old. |
3670 | 21 | if (!Subtarget.getFeatureBits()[Hexagon::ArchV60]) { |
3671 | 4 | switch (NewOp) { |
3672 | 4 | case Hexagon::J2_jumptpt: |
3673 | 0 | NewOp = Hexagon::J2_jumpt; |
3674 | 0 | break; |
3675 | 4 | case Hexagon::J2_jumpfpt: |
3676 | 0 | NewOp = Hexagon::J2_jumpf; |
3677 | 0 | break; |
3678 | 4 | case Hexagon::J2_jumprtpt: |
3679 | 0 | NewOp = Hexagon::J2_jumprt; |
3680 | 0 | break; |
3681 | 4 | case Hexagon::J2_jumprfpt: |
3682 | 0 | NewOp = Hexagon::J2_jumprf; |
3683 | 0 | break; |
3684 | 21 | } |
3685 | 21 | } |
3686 | 21 | assert(NewOp >= 0 && |
3687 | 21 | "Couldn't change predicate new instruction to its old form."); |
3688 | 21 | } |
3689 | 21 | |
3690 | 21 | if (isNewValueStore(NewOp)) { // Convert into non-new-value format |
3691 | 0 | NewOp = Hexagon::getNonNVStore(NewOp); |
3692 | 0 | assert(NewOp >= 0 && "Couldn't change new-value store to its old form."); |
3693 | 0 | } |
3694 | 21 | |
3695 | 21 | if (Subtarget.hasV60Ops()) |
3696 | 17 | return NewOp; |
3697 | 4 | |
3698 | 4 | // Subtargets prior to V60 didn't support 'taken' forms of predicated jumps. |
3699 | 4 | switch (NewOp) { |
3700 | 4 | case Hexagon::J2_jumpfpt: |
3701 | 0 | return Hexagon::J2_jumpf; |
3702 | 4 | case Hexagon::J2_jumptpt: |
3703 | 0 | return Hexagon::J2_jumpt; |
3704 | 4 | case Hexagon::J2_jumprfpt: |
3705 | 0 | return Hexagon::J2_jumprf; |
3706 | 4 | case Hexagon::J2_jumprtpt: |
3707 | 0 | return Hexagon::J2_jumprt; |
3708 | 4 | } |
3709 | 4 | return NewOp; |
3710 | 4 | } |
3711 | | |
3712 | | // See if instruction could potentially be a duplex candidate. |
3713 | | // If so, return its group. Zero otherwise. |
3714 | | HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( |
3715 | 0 | const MachineInstr &MI) const { |
3716 | 0 | unsigned DstReg, SrcReg, Src1Reg, Src2Reg; |
3717 | 0 | const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); |
3718 | 0 |
|
3719 | 0 | switch (MI.getOpcode()) { |
3720 | 0 | default: |
3721 | 0 | return HexagonII::HSIG_None; |
3722 | 0 | // |
3723 | 0 | // Group L1: |
3724 | 0 | // |
3725 | 0 | // Rd = memw(Rs+#u4:2) |
3726 | 0 | // Rd = memub(Rs+#u4:0) |
3727 | 0 | case Hexagon::L2_loadri_io: |
3728 | 0 | DstReg = MI.getOperand(0).getReg(); |
3729 | 0 | SrcReg = MI.getOperand(1).getReg(); |
3730 | 0 | // Special case this one from Group L2. |
3731 | 0 | // Rd = memw(r29+#u5:2) |
3732 | 0 | if (isIntRegForSubInst(DstReg)) { |
3733 | 0 | if (Hexagon::IntRegsRegClass.contains(SrcReg) && |
3734 | 0 | HRI.getStackRegister() == SrcReg && |
3735 | 0 | MI.getOperand(2).isImm() && |
3736 | 0 | isShiftedUInt<5,2>(MI.getOperand(2).getImm())) |
3737 | 0 | return HexagonII::HSIG_L2; |
3738 | 0 | // Rd = memw(Rs+#u4:2) |
3739 | 0 | if (isIntRegForSubInst(SrcReg) && |
3740 | 0 | (MI.getOperand(2).isImm() && |
3741 | 0 | isShiftedUInt<4,2>(MI.getOperand(2).getImm()))) |
3742 | 0 | return HexagonII::HSIG_L1; |
3743 | 0 | } |
3744 | 0 | break; |
3745 | 0 | case Hexagon::L2_loadrub_io: |
3746 | 0 | // Rd = memub(Rs+#u4:0) |
3747 | 0 | DstReg = MI.getOperand(0).getReg(); |
3748 | 0 | SrcReg = MI.getOperand(1).getReg(); |
3749 | 0 | if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg) && |
3750 | 0 | MI.getOperand(2).isImm() && isUInt<4>(MI.getOperand(2).getImm())) |
3751 | 0 | return HexagonII::HSIG_L1; |
3752 | 0 | break; |
3753 | 0 | // |
3754 | 0 | // Group L2: |
3755 | 0 | // |
3756 | 0 | // Rd = memh/memuh(Rs+#u3:1) |
3757 | 0 | // Rd = memb(Rs+#u3:0) |
3758 | 0 | // Rd = memw(r29+#u5:2) - Handled above. |
3759 | 0 | // Rdd = memd(r29+#u5:3) |
3760 | 0 | // deallocframe |
3761 | 0 | // [if ([!]p0[.new])] dealloc_return |
3762 | 0 | // [if ([!]p0[.new])] jumpr r31 |
3763 | 0 | case Hexagon::L2_loadrh_io: |
3764 | 0 | case Hexagon::L2_loadruh_io: |
3765 | 0 | // Rd = memh/memuh(Rs+#u3:1) |
3766 | 0 | DstReg = MI.getOperand(0).getReg(); |
3767 | 0 | SrcReg = MI.getOperand(1).getReg(); |
3768 | 0 | if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg) && |
3769 | 0 | MI.getOperand(2).isImm() && |
3770 | 0 | isShiftedUInt<3,1>(MI.getOperand(2).getImm())) |
3771 | 0 | return HexagonII::HSIG_L2; |
3772 | 0 | break; |
3773 | 0 | case Hexagon::L2_loadrb_io: |
3774 | 0 | // Rd = memb(Rs+#u3:0) |
3775 | 0 | DstReg = MI.getOperand(0).getReg(); |
3776 | 0 | SrcReg = MI.getOperand(1).getReg(); |
3777 | 0 | if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg) && |
3778 | 0 | MI.getOperand(2).isImm() && |
3779 | 0 | isUInt<3>(MI.getOperand(2).getImm())) |
3780 | 0 | return HexagonII::HSIG_L2; |
3781 | 0 | break; |
3782 | 0 | case Hexagon::L2_loadrd_io: |
3783 | 0 | // Rdd = memd(r29+#u5:3) |
3784 | 0 | DstReg = MI.getOperand(0).getReg(); |
3785 | 0 | SrcReg = MI.getOperand(1).getReg(); |
3786 | 0 | if (isDblRegForSubInst(DstReg, HRI) && |
3787 | 0 | Hexagon::IntRegsRegClass.contains(SrcReg) && |
3788 | 0 | HRI.getStackRegister() == SrcReg && |
3789 | 0 | MI.getOperand(2).isImm() && |
3790 | 0 | isShiftedUInt<5,3>(MI.getOperand(2).getImm())) |
3791 | 0 | return HexagonII::HSIG_L2; |
3792 | 0 | break; |
3793 | 0 | // dealloc_return is not documented in Hexagon Manual, but marked |
3794 | 0 | // with A_SUBINSN attribute in iset_v4classic.py. |
3795 | 0 | case Hexagon::RESTORE_DEALLOC_RET_JMP_V4: |
3796 | 0 | case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC: |
3797 | 0 | case Hexagon::L4_return: |
3798 | 0 | case Hexagon::L2_deallocframe: |
3799 | 0 | return HexagonII::HSIG_L2; |
3800 | 0 | case Hexagon::EH_RETURN_JMPR: |
3801 | 0 | case Hexagon::PS_jmpret: |
3802 | 0 | case Hexagon::SL2_jumpr31: |
3803 | 0 | // jumpr r31 |
3804 | 0 | // Actual form JMPR implicit-def %pc, implicit %r31, implicit internal %r0 |
3805 | 0 | DstReg = MI.getOperand(0).getReg(); |
3806 | 0 | if (Hexagon::IntRegsRegClass.contains(DstReg) && (Hexagon::R31 == DstReg)) |
3807 | 0 | return HexagonII::HSIG_L2; |
3808 | 0 | break; |
3809 | 0 | case Hexagon::PS_jmprett: |
3810 | 0 | case Hexagon::PS_jmpretf: |
3811 | 0 | case Hexagon::PS_jmprettnewpt: |
3812 | 0 | case Hexagon::PS_jmpretfnewpt: |
3813 | 0 | case Hexagon::PS_jmprettnew: |
3814 | 0 | case Hexagon::PS_jmpretfnew: |
3815 | 0 | case Hexagon::SL2_jumpr31_t: |
3816 | 0 | case Hexagon::SL2_jumpr31_f: |
3817 | 0 | case Hexagon::SL2_jumpr31_tnew: |
3818 | 0 | DstReg = MI.getOperand(1).getReg(); |
3819 | 0 | SrcReg = MI.getOperand(0).getReg(); |
3820 | 0 | // [if ([!]p0[.new])] jumpr r31 |
3821 | 0 | if ((Hexagon::PredRegsRegClass.contains(SrcReg) && |
3822 | 0 | (Hexagon::P0 == SrcReg)) && |
3823 | 0 | (Hexagon::IntRegsRegClass.contains(DstReg) && (Hexagon::R31 == DstReg))) |
3824 | 0 | return HexagonII::HSIG_L2; |
3825 | 0 | break; |
3826 | 0 | case Hexagon::L4_return_t: |
3827 | 0 | case Hexagon::L4_return_f: |
3828 | 0 | case Hexagon::L4_return_tnew_pnt: |
3829 | 0 | case Hexagon::L4_return_fnew_pnt: |
3830 | 0 | case Hexagon::L4_return_tnew_pt: |
3831 | 0 | case Hexagon::L4_return_fnew_pt: |
3832 | 0 | // [if ([!]p0[.new])] dealloc_return |
3833 | 0 | SrcReg = MI.getOperand(0).getReg(); |
3834 | 0 | if (Hexagon::PredRegsRegClass.contains(SrcReg) && (Hexagon::P0 == SrcReg)) |
3835 | 0 | return HexagonII::HSIG_L2; |
3836 | 0 | break; |
3837 | 0 | // |
3838 | 0 | // Group S1: |
3839 | 0 | // |
3840 | 0 | // memw(Rs+#u4:2) = Rt |
3841 | 0 | // memb(Rs+#u4:0) = Rt |
3842 | 0 | case Hexagon::S2_storeri_io: |
3843 | 0 | // Special case this one from Group S2. |
3844 | 0 | // memw(r29+#u5:2) = Rt |
3845 | 0 | Src1Reg = MI.getOperand(0).getReg(); |
3846 | 0 | Src2Reg = MI.getOperand(2).getReg(); |
3847 | 0 | if (Hexagon::IntRegsRegClass.contains(Src1Reg) && |
3848 | 0 | isIntRegForSubInst(Src2Reg) && |
3849 | 0 | HRI.getStackRegister() == Src1Reg && MI.getOperand(1).isImm() && |
3850 | 0 | isShiftedUInt<5,2>(MI.getOperand(1).getImm())) |
3851 | 0 | return HexagonII::HSIG_S2; |
3852 | 0 | // memw(Rs+#u4:2) = Rt |
3853 | 0 | if (isIntRegForSubInst(Src1Reg) && isIntRegForSubInst(Src2Reg) && |
3854 | 0 | MI.getOperand(1).isImm() && |
3855 | 0 | isShiftedUInt<4,2>(MI.getOperand(1).getImm())) |
3856 | 0 | return HexagonII::HSIG_S1; |
3857 | 0 | break; |
3858 | 0 | case Hexagon::S2_storerb_io: |
3859 | 0 | // memb(Rs+#u4:0) = Rt |
3860 | 0 | Src1Reg = MI.getOperand(0).getReg(); |
3861 | 0 | Src2Reg = MI.getOperand(2).getReg(); |
3862 | 0 | if (isIntRegForSubInst(Src1Reg) && isIntRegForSubInst(Src2Reg) && |
3863 | 0 | MI.getOperand(1).isImm() && isUInt<4>(MI.getOperand(1).getImm())) |
3864 | 0 | return HexagonII::HSIG_S1; |
3865 | 0 | break; |
3866 | 0 | // |
3867 | 0 | // Group S2: |
3868 | 0 | // |
3869 | 0 | // memh(Rs+#u3:1) = Rt |
3870 | 0 | // memw(r29+#u5:2) = Rt |
3871 | 0 | // memd(r29+#s6:3) = Rtt |
3872 | 0 | // memw(Rs+#u4:2) = #U1 |
3873 | 0 | // memb(Rs+#u4) = #U1 |
3874 | 0 | // allocframe(#u5:3) |
3875 | 0 | case Hexagon::S2_storerh_io: |
3876 | 0 | // memh(Rs+#u3:1) = Rt |
3877 | 0 | Src1Reg = MI.getOperand(0).getReg(); |
3878 | 0 | Src2Reg = MI.getOperand(2).getReg(); |
3879 | 0 | if (isIntRegForSubInst(Src1Reg) && isIntRegForSubInst(Src2Reg) && |
3880 | 0 | MI.getOperand(1).isImm() && |
3881 | 0 | isShiftedUInt<3,1>(MI.getOperand(1).getImm())) |
3882 | 0 | return HexagonII::HSIG_S1; |
3883 | 0 | break; |
3884 | 0 | case Hexagon::S2_storerd_io: |
3885 | 0 | // memd(r29+#s6:3) = Rtt |
3886 | 0 | Src1Reg = MI.getOperand(0).getReg(); |
3887 | 0 | Src2Reg = MI.getOperand(2).getReg(); |
3888 | 0 | if (isDblRegForSubInst(Src2Reg, HRI) && |
3889 | 0 | Hexagon::IntRegsRegClass.contains(Src1Reg) && |
3890 | 0 | HRI.getStackRegister() == Src1Reg && MI.getOperand(1).isImm() && |
3891 | 0 | isShiftedInt<6,3>(MI.getOperand(1).getImm())) |
3892 | 0 | return HexagonII::HSIG_S2; |
3893 | 0 | break; |
3894 | 0 | case Hexagon::S4_storeiri_io: |
3895 | 0 | // memw(Rs+#u4:2) = #U1 |
3896 | 0 | Src1Reg = MI.getOperand(0).getReg(); |
3897 | 0 | if (isIntRegForSubInst(Src1Reg) && MI.getOperand(1).isImm() && |
3898 | 0 | isShiftedUInt<4,2>(MI.getOperand(1).getImm()) && |
3899 | 0 | MI.getOperand(2).isImm() && isUInt<1>(MI.getOperand(2).getImm())) |
3900 | 0 | return HexagonII::HSIG_S2; |
3901 | 0 | break; |
3902 | 0 | case Hexagon::S4_storeirb_io: |
3903 | 0 | // memb(Rs+#u4) = #U1 |
3904 | 0 | Src1Reg = MI.getOperand(0).getReg(); |
3905 | 0 | if (isIntRegForSubInst(Src1Reg) && |
3906 | 0 | MI.getOperand(1).isImm() && isUInt<4>(MI.getOperand(1).getImm()) && |
3907 | 0 | MI.getOperand(2).isImm() && isUInt<1>(MI.getOperand(2).getImm())) |
3908 | 0 | return HexagonII::HSIG_S2; |
3909 | 0 | break; |
3910 | 0 | case Hexagon::S2_allocframe: |
3911 | 0 | if (MI.getOperand(2).isImm() && |
3912 | 0 | isShiftedUInt<5,3>(MI.getOperand(2).getImm())) |
3913 | 0 | return HexagonII::HSIG_S1; |
3914 | 0 | break; |
3915 | 0 | // |
3916 | 0 | // Group A: |
3917 | 0 | // |
3918 | 0 | // Rx = add(Rx,#s7) |
3919 | 0 | // Rd = Rs |
3920 | 0 | // Rd = #u6 |
3921 | 0 | // Rd = #-1 |
3922 | 0 | // if ([!]P0[.new]) Rd = #0 |
3923 | 0 | // Rd = add(r29,#u6:2) |
3924 | 0 | // Rx = add(Rx,Rs) |
3925 | 0 | // P0 = cmp.eq(Rs,#u2) |
3926 | 0 | // Rdd = combine(#0,Rs) |
3927 | 0 | // Rdd = combine(Rs,#0) |
3928 | 0 | // Rdd = combine(#u2,#U2) |
3929 | 0 | // Rd = add(Rs,#1) |
3930 | 0 | // Rd = add(Rs,#-1) |
3931 | 0 | // Rd = sxth/sxtb/zxtb/zxth(Rs) |
3932 | 0 | // Rd = and(Rs,#1) |
3933 | 0 | case Hexagon::A2_addi: |
3934 | 0 | DstReg = MI.getOperand(0).getReg(); |
3935 | 0 | SrcReg = MI.getOperand(1).getReg(); |
3936 | 0 | if (isIntRegForSubInst(DstReg)) { |
3937 | 0 | // Rd = add(r29,#u6:2) |
3938 | 0 | if (Hexagon::IntRegsRegClass.contains(SrcReg) && |
3939 | 0 | HRI.getStackRegister() == SrcReg && MI.getOperand(2).isImm() && |
3940 | 0 | isShiftedUInt<6,2>(MI.getOperand(2).getImm())) |
3941 | 0 | return HexagonII::HSIG_A; |
3942 | 0 | // Rx = add(Rx,#s7) |
3943 | 0 | if ((DstReg == SrcReg) && MI.getOperand(2).isImm() && |
3944 | 0 | isInt<7>(MI.getOperand(2).getImm())) |
3945 | 0 | return HexagonII::HSIG_A; |
3946 | 0 | // Rd = add(Rs,#1) |
3947 | 0 | // Rd = add(Rs,#-1) |
3948 | 0 | if (isIntRegForSubInst(SrcReg) && MI.getOperand(2).isImm() && |
3949 | 0 | ((MI.getOperand(2).getImm() == 1) || |
3950 | 0 | (MI.getOperand(2).getImm() == -1))) |
3951 | 0 | return HexagonII::HSIG_A; |
3952 | 0 | } |
3953 | 0 | break; |
3954 | 0 | case Hexagon::A2_add: |
3955 | 0 | // Rx = add(Rx,Rs) |
3956 | 0 | DstReg = MI.getOperand(0).getReg(); |
3957 | 0 | Src1Reg = MI.getOperand(1).getReg(); |
3958 | 0 | Src2Reg = MI.getOperand(2).getReg(); |
3959 | 0 | if (isIntRegForSubInst(DstReg) && (DstReg == Src1Reg) && |
3960 | 0 | isIntRegForSubInst(Src2Reg)) |
3961 | 0 | return HexagonII::HSIG_A; |
3962 | 0 | break; |
3963 | 0 | case Hexagon::A2_andir: |
3964 | 0 | // Same as zxtb. |
3965 | 0 | // Rd16=and(Rs16,#255) |
3966 | 0 | // Rd16=and(Rs16,#1) |
3967 | 0 | DstReg = MI.getOperand(0).getReg(); |
3968 | 0 | SrcReg = MI.getOperand(1).getReg(); |
3969 | 0 | if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg) && |
3970 | 0 | MI.getOperand(2).isImm() && |
3971 | 0 | ((MI.getOperand(2).getImm() == 1) || |
3972 | 0 | (MI.getOperand(2).getImm() == 255))) |
3973 | 0 | return HexagonII::HSIG_A; |
3974 | 0 | break; |
3975 | 0 | case Hexagon::A2_tfr: |
3976 | 0 | // Rd = Rs |
3977 | 0 | DstReg = MI.getOperand(0).getReg(); |
3978 | 0 | SrcReg = MI.getOperand(1).getReg(); |
3979 | 0 | if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg)) |
3980 | 0 | return HexagonII::HSIG_A; |
3981 | 0 | break; |
3982 | 0 | case Hexagon::A2_tfrsi: |
3983 | 0 | // Rd = #u6 |
3984 | 0 | // Do not test for #u6 size since the const is getting extended |
3985 | 0 | // regardless and compound could be formed. |
3986 | 0 | // Rd = #-1 |
3987 | 0 | DstReg = MI.getOperand(0).getReg(); |
3988 | 0 | if (isIntRegForSubInst(DstReg)) |
3989 | 0 | return HexagonII::HSIG_A; |
3990 | 0 | break; |
3991 | 0 | case Hexagon::C2_cmoveit: |
3992 | 0 | case Hexagon::C2_cmovenewit: |
3993 | 0 | case Hexagon::C2_cmoveif: |
3994 | 0 | case Hexagon::C2_cmovenewif: |
3995 | 0 | // if ([!]P0[.new]) Rd = #0 |
3996 | 0 | // Actual form: |
3997 | 0 | // %r16 = C2_cmovenewit internal %p0, 0, implicit undef %r16; |
3998 | 0 | DstReg = MI.getOperand(0).getReg(); |
3999 | 0 | SrcReg = MI.getOperand(1).getReg(); |
4000 | 0 | if (isIntRegForSubInst(DstReg) && |
4001 | 0 | Hexagon::PredRegsRegClass.contains(SrcReg) && Hexagon::P0 == SrcReg && |
4002 | 0 | MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) |
4003 | 0 | return HexagonII::HSIG_A; |
4004 | 0 | break; |
4005 | 0 | case Hexagon::C2_cmpeqi: |
4006 | 0 | // P0 = cmp.eq(Rs,#u2) |
4007 | 0 | DstReg = MI.getOperand(0).getReg(); |
4008 | 0 | SrcReg = MI.getOperand(1).getReg(); |
4009 | 0 | if (Hexagon::PredRegsRegClass.contains(DstReg) && |
4010 | 0 | Hexagon::P0 == DstReg && isIntRegForSubInst(SrcReg) && |
4011 | 0 | MI.getOperand(2).isImm() && isUInt<2>(MI.getOperand(2).getImm())) |
4012 | 0 | return HexagonII::HSIG_A; |
4013 | 0 | break; |
4014 | 0 | case Hexagon::A2_combineii: |
4015 | 0 | case Hexagon::A4_combineii: |
4016 | 0 | // Rdd = combine(#u2,#U2) |
4017 | 0 | DstReg = MI.getOperand(0).getReg(); |
4018 | 0 | if (isDblRegForSubInst(DstReg, HRI) && |
4019 | 0 | ((MI.getOperand(1).isImm() && isUInt<2>(MI.getOperand(1).getImm())) || |
4020 | 0 | (MI.getOperand(1).isGlobal() && |
4021 | 0 | isUInt<2>(MI.getOperand(1).getOffset()))) && |
4022 | 0 | ((MI.getOperand(2).isImm() && isUInt<2>(MI.getOperand(2).getImm())) || |
4023 | 0 | (MI.getOperand(2).isGlobal() && |
4024 | 0 | isUInt<2>(MI.getOperand(2).getOffset())))) |
4025 | 0 | return HexagonII::HSIG_A; |
4026 | 0 | break; |
4027 | 0 | case Hexagon::A4_combineri: |
4028 | 0 | // Rdd = combine(Rs,#0) |
4029 | 0 | DstReg = MI.getOperand(0).getReg(); |
4030 | 0 | SrcReg = MI.getOperand(1).getReg(); |
4031 | 0 | if (isDblRegForSubInst(DstReg, HRI) && isIntRegForSubInst(SrcReg) && |
4032 | 0 | ((MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) || |
4033 | 0 | (MI.getOperand(2).isGlobal() && MI.getOperand(2).getOffset() == 0))) |
4034 | 0 | return HexagonII::HSIG_A; |
4035 | 0 | break; |
4036 | 0 | case Hexagon::A4_combineir: |
4037 | 0 | // Rdd = combine(#0,Rs) |
4038 | 0 | DstReg = MI.getOperand(0).getReg(); |
4039 | 0 | SrcReg = MI.getOperand(2).getReg(); |
4040 | 0 | if (isDblRegForSubInst(DstReg, HRI) && isIntRegForSubInst(SrcReg) && |
4041 | 0 | ((MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) || |
4042 | 0 | (MI.getOperand(1).isGlobal() && MI.getOperand(1).getOffset() == 0))) |
4043 | 0 | return HexagonII::HSIG_A; |
4044 | 0 | break; |
4045 | 0 | case Hexagon::A2_sxtb: |
4046 | 0 | case Hexagon::A2_sxth: |
4047 | 0 | case Hexagon::A2_zxtb: |
4048 | 0 | case Hexagon::A2_zxth: |
4049 | 0 | // Rd = sxth/sxtb/zxtb/zxth(Rs) |
4050 | 0 | DstReg = MI.getOperand(0).getReg(); |
4051 | 0 | SrcReg = MI.getOperand(1).getReg(); |
4052 | 0 | if (isIntRegForSubInst(DstReg) && isIntRegForSubInst(SrcReg)) |
4053 | 0 | return HexagonII::HSIG_A; |
4054 | 0 | break; |
4055 | 0 | } |
4056 | 0 | |
4057 | 0 | return HexagonII::HSIG_None; |
4058 | 0 | } |
4059 | | |
4060 | 0 | short HexagonInstrInfo::getEquivalentHWInstr(const MachineInstr &MI) const { |
4061 | 0 | return Hexagon::getRealHWInstr(MI.getOpcode(), Hexagon::InstrType_Real); |
4062 | 0 | } |
4063 | | |
4064 | | unsigned HexagonInstrInfo::getInstrTimingClassLatency( |
4065 | 128k | const InstrItineraryData *ItinData, const MachineInstr &MI) const { |
4066 | 128k | // Default to one cycle for no itinerary. However, an "empty" itinerary may |
4067 | 128k | // still have a MinLatency property, which getStageLatency checks. |
4068 | 128k | if (!ItinData) |
4069 | 0 | return getInstrLatency(ItinData, MI); |
4070 | 128k | |
4071 | 128k | if (MI.isTransient()) |
4072 | 21.7k | return 0; |
4073 | 106k | return ItinData->getStageLatency(MI.getDesc().getSchedClass()); |
4074 | 106k | } |
4075 | | |
4076 | | /// getOperandLatency - Compute and return the use operand latency of a given |
4077 | | /// pair of def and use. |
4078 | | /// In most cases, the static scheduling itinerary was enough to determine the |
4079 | | /// operand latency. But it may not be possible for instructions with variable |
4080 | | /// number of defs / uses. |
4081 | | /// |
4082 | | /// This is a raw interface to the itinerary that may be directly overriden by |
4083 | | /// a target. Use computeOperandLatency to get the best estimate of latency. |
4084 | | int HexagonInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, |
4085 | | const MachineInstr &DefMI, |
4086 | | unsigned DefIdx, |
4087 | | const MachineInstr &UseMI, |
4088 | 77.9k | unsigned UseIdx) const { |
4089 | 77.9k | const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); |
4090 | 77.9k | |
4091 | 77.9k | // Get DefIdx and UseIdx for super registers. |
4092 | 77.9k | const MachineOperand &DefMO = DefMI.getOperand(DefIdx); |
4093 | 77.9k | |
4094 | 77.9k | if (DefMO.isReg() && HRI.isPhysicalRegister(DefMO.getReg())) { |
4095 | 50.0k | if (DefMO.isImplicit()) { |
4096 | 5.88k | for (MCSuperRegIterator SR(DefMO.getReg(), &HRI); SR.isValid(); ++SR2.94k ) { |
4097 | 2.94k | int Idx = DefMI.findRegisterDefOperandIdx(*SR, false, false, &HRI); |
4098 | 2.94k | if (Idx != -1) { |
4099 | 0 | DefIdx = Idx; |
4100 | 0 | break; |
4101 | 0 | } |
4102 | 2.94k | } |
4103 | 2.94k | } |
4104 | 50.0k | |
4105 | 50.0k | const MachineOperand &UseMO = UseMI.getOperand(UseIdx); |
4106 | 50.0k | if (UseMO.isImplicit()) { |
4107 | 1.31k | for (MCSuperRegIterator SR(UseMO.getReg(), &HRI); SR.isValid(); ++SR0 ) { |
4108 | 1.14k | int Idx = UseMI.findRegisterUseOperandIdx(*SR, false, &HRI); |
4109 | 1.14k | if (Idx != -1) { |
4110 | 1.14k | UseIdx = Idx; |
4111 | 1.14k | break; |
4112 | 1.14k | } |
4113 | 1.14k | } |
4114 | 1.31k | } |
4115 | 50.0k | } |
4116 | 77.9k | |
4117 | 77.9k | int Latency = TargetInstrInfo::getOperandLatency(ItinData, DefMI, DefIdx, |
4118 | 77.9k | UseMI, UseIdx); |
4119 | 77.9k | if (!Latency) |
4120 | 63 | // We should never have 0 cycle latency between two instructions unless |
4121 | 63 | // they can be packetized together. However, this decision can't be made |
4122 | 63 | // here. |
4123 | 63 | Latency = 1; |
4124 | 77.9k | return Latency; |
4125 | 77.9k | } |
4126 | | |
4127 | | // inverts the predication logic. |
4128 | | // p -> NotP |
4129 | | // NotP -> P |
4130 | | bool HexagonInstrInfo::getInvertedPredSense( |
4131 | 0 | SmallVectorImpl<MachineOperand> &Cond) const { |
4132 | 0 | if (Cond.empty()) |
4133 | 0 | return false; |
4134 | 0 | unsigned Opc = getInvertedPredicatedOpcode(Cond[0].getImm()); |
4135 | 0 | Cond[0].setImm(Opc); |
4136 | 0 | return true; |
4137 | 0 | } |
4138 | | |
4139 | 5.89k | unsigned HexagonInstrInfo::getInvertedPredicatedOpcode(const int Opc) const { |
4140 | 5.89k | int InvPredOpcode; |
4141 | 5.89k | InvPredOpcode = isPredicatedTrue(Opc) ? Hexagon::getFalsePredOpcode(Opc)3.06k |
4142 | 5.89k | : Hexagon::getTruePredOpcode(Opc)2.83k ; |
4143 | 5.89k | if (InvPredOpcode >= 0) // Valid instruction with the inverted predicate. |
4144 | 5.89k | return InvPredOpcode; |
4145 | 0 | |
4146 | 0 | llvm_unreachable("Unexpected predicated instruction"); |
4147 | 0 | } |
4148 | | |
4149 | | // Returns the max value that doesn't need to be extended. |
4150 | 38.8k | int HexagonInstrInfo::getMaxValue(const MachineInstr &MI) const { |
4151 | 38.8k | const uint64_t F = MI.getDesc().TSFlags; |
4152 | 38.8k | unsigned isSigned = (F >> HexagonII::ExtentSignedPos) |
4153 | 38.8k | & HexagonII::ExtentSignedMask; |
4154 | 38.8k | unsigned bits = (F >> HexagonII::ExtentBitsPos) |
4155 | 38.8k | & HexagonII::ExtentBitsMask; |
4156 | 38.8k | |
4157 | 38.8k | if (isSigned) // if value is signed |
4158 | 35.9k | return ~(-1U << (bits - 1)); |
4159 | 2.97k | else |
4160 | 2.97k | return ~(-1U << bits); |
4161 | 38.8k | } |
4162 | | |
4163 | | |
4164 | 95.9k | bool HexagonInstrInfo::isAddrModeWithOffset(const MachineInstr &MI) const { |
4165 | 95.9k | switch (MI.getOpcode()) { |
4166 | 95.9k | case Hexagon::L2_loadrbgp: |
4167 | 278 | case Hexagon::L2_loadrdgp: |
4168 | 278 | case Hexagon::L2_loadrhgp: |
4169 | 278 | case Hexagon::L2_loadrigp: |
4170 | 278 | case Hexagon::L2_loadrubgp: |
4171 | 278 | case Hexagon::L2_loadruhgp: |
4172 | 278 | case Hexagon::S2_storerbgp: |
4173 | 278 | case Hexagon::S2_storerbnewgp: |
4174 | 278 | case Hexagon::S2_storerhgp: |
4175 | 278 | case Hexagon::S2_storerhnewgp: |
4176 | 278 | case Hexagon::S2_storerigp: |
4177 | 278 | case Hexagon::S2_storerinewgp: |
4178 | 278 | case Hexagon::S2_storerdgp: |
4179 | 278 | case Hexagon::S2_storerfgp: |
4180 | 278 | return true; |
4181 | 95.6k | } |
4182 | 95.6k | const uint64_t F = MI.getDesc().TSFlags; |
4183 | 95.6k | unsigned addrMode = |
4184 | 95.6k | ((F >> HexagonII::AddrModePos) & HexagonII::AddrModeMask); |
4185 | 95.6k | // Disallow any base+offset instruction. The assembler does not yet reorder |
4186 | 95.6k | // based up any zero offset instruction. |
4187 | 95.6k | return (addrMode == HexagonII::BaseRegOffset || |
4188 | 95.6k | addrMode == HexagonII::BaseImmOffset94.5k || |
4189 | 95.6k | addrMode == HexagonII::BaseLongOffset12.4k ); |
4190 | 95.6k | } |
4191 | | |
4192 | 59.7k | unsigned HexagonInstrInfo::getMemAccessSize(const MachineInstr &MI) const { |
4193 | 59.7k | using namespace HexagonII; |
4194 | 59.7k | |
4195 | 59.7k | const uint64_t F = MI.getDesc().TSFlags; |
4196 | 59.7k | unsigned S = (F >> MemAccessSizePos) & MemAccesSizeMask; |
4197 | 59.7k | unsigned Size = getMemAccessSizeInBytes(MemAccessSize(S)); |
4198 | 59.7k | if (Size != 0) |
4199 | 54.4k | return Size; |
4200 | 5.24k | |
4201 | 5.24k | // Handle vector access sizes. |
4202 | 5.24k | const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); |
4203 | 5.24k | switch (S) { |
4204 | 5.24k | case HexagonII::HVXVectorAccess: |
4205 | 5.24k | return HRI.getSpillSize(Hexagon::HvxVRRegClass); |
4206 | 5.24k | default: |
4207 | 0 | llvm_unreachable("Unexpected instruction"); |
4208 | 5.24k | } |
4209 | 5.24k | } |
4210 | | |
4211 | | // Returns the min value that doesn't need to be extended. |
4212 | 38.8k | int HexagonInstrInfo::getMinValue(const MachineInstr &MI) const { |
4213 | 38.8k | const uint64_t F = MI.getDesc().TSFlags; |
4214 | 38.8k | unsigned isSigned = (F >> HexagonII::ExtentSignedPos) |
4215 | 38.8k | & HexagonII::ExtentSignedMask; |
4216 | 38.8k | unsigned bits = (F >> HexagonII::ExtentBitsPos) |
4217 | 38.8k | & HexagonII::ExtentBitsMask; |
4218 | 38.8k | |
4219 | 38.8k | if (isSigned) // if value is signed |
4220 | 35.9k | return -1U << (bits - 1); |
4221 | 2.97k | else |
4222 | 2.97k | return 0; |
4223 | 38.8k | } |
4224 | | |
4225 | | // Returns opcode of the non-extended equivalent instruction. |
4226 | 0 | short HexagonInstrInfo::getNonExtOpcode(const MachineInstr &MI) const { |
4227 | 0 | // Check if the instruction has a register form that uses register in place |
4228 | 0 | // of the extended operand, if so return that as the non-extended form. |
4229 | 0 | short NonExtOpcode = Hexagon::getRegForm(MI.getOpcode()); |
4230 | 0 | if (NonExtOpcode >= 0) |
4231 | 0 | return NonExtOpcode; |
4232 | 0 | |
4233 | 0 | if (MI.getDesc().mayLoad() || MI.getDesc().mayStore()) { |
4234 | 0 | // Check addressing mode and retrieve non-ext equivalent instruction. |
4235 | 0 | switch (getAddrMode(MI)) { |
4236 | 0 | case HexagonII::Absolute: |
4237 | 0 | return Hexagon::changeAddrMode_abs_io(MI.getOpcode()); |
4238 | 0 | case HexagonII::BaseImmOffset: |
4239 | 0 | return Hexagon::changeAddrMode_io_rr(MI.getOpcode()); |
4240 | 0 | case HexagonII::BaseLongOffset: |
4241 | 0 | return Hexagon::changeAddrMode_ur_rr(MI.getOpcode()); |
4242 | 0 |
|
4243 | 0 | default: |
4244 | 0 | return -1; |
4245 | 0 | } |
4246 | 0 | } |
4247 | 0 | return -1; |
4248 | 0 | } |
4249 | | |
4250 | | bool HexagonInstrInfo::getPredReg(ArrayRef<MachineOperand> Cond, |
4251 | 765 | unsigned &PredReg, unsigned &PredRegPos, unsigned &PredRegFlags) const { |
4252 | 765 | if (Cond.empty()) |
4253 | 0 | return false; |
4254 | 765 | assert(Cond.size() == 2); |
4255 | 765 | if (isNewValueJump(Cond[0].getImm()) || Cond[1].isMBB()) { |
4256 | 0 | LLVM_DEBUG(dbgs() << "No predregs for new-value jumps/endloop"); |
4257 | 0 | return false; |
4258 | 0 | } |
4259 | 765 | PredReg = Cond[1].getReg(); |
4260 | 765 | PredRegPos = 1; |
4261 | 765 | // See IfConversion.cpp why we add RegState::Implicit | RegState::Undef |
4262 | 765 | PredRegFlags = 0; |
4263 | 765 | if (Cond[1].isImplicit()) |
4264 | 0 | PredRegFlags = RegState::Implicit; |
4265 | 765 | if (Cond[1].isUndef()) |
4266 | 34 | PredRegFlags |= RegState::Undef; |
4267 | 765 | return true; |
4268 | 765 | } |
4269 | | |
4270 | 0 | short HexagonInstrInfo::getPseudoInstrPair(const MachineInstr &MI) const { |
4271 | 0 | return Hexagon::getRealHWInstr(MI.getOpcode(), Hexagon::InstrType_Pseudo); |
4272 | 0 | } |
4273 | | |
4274 | 0 | short HexagonInstrInfo::getRegForm(const MachineInstr &MI) const { |
4275 | 0 | return Hexagon::getRegForm(MI.getOpcode()); |
4276 | 0 | } |
4277 | | |
4278 | | // Return the number of bytes required to encode the instruction. |
4279 | | // Hexagon instructions are fixed length, 4 bytes, unless they |
4280 | | // use a constant extender, which requires another 4 bytes. |
4281 | | // For debug instructions and prolog labels, return 0. |
4282 | 90.1k | unsigned HexagonInstrInfo::getSize(const MachineInstr &MI) const { |
4283 | 90.1k | if (MI.isDebugInstr() || MI.isPosition()90.1k ) |
4284 | 162 | return 0; |
4285 | 90.0k | |
4286 | 90.0k | unsigned Size = MI.getDesc().getSize(); |
4287 | 90.0k | if (!Size) |
4288 | 207 | // Assume the default insn size in case it cannot be determined |
4289 | 207 | // for whatever reason. |
4290 | 207 | Size = HEXAGON_INSTR_SIZE; |
4291 | 90.0k | |
4292 | 90.0k | if (isConstExtended(MI) || isExtended(MI)84.8k ) |
4293 | 5.23k | Size += HEXAGON_INSTR_SIZE; |
4294 | 90.0k | |
4295 | 90.0k | // Try and compute number of instructions in asm. |
4296 | 90.0k | if (BranchRelaxAsmLarge && MI.getOpcode() == Hexagon::INLINEASM) { |
4297 | 99 | const MachineBasicBlock &MBB = *MI.getParent(); |
4298 | 99 | const MachineFunction *MF = MBB.getParent(); |
4299 | 99 | const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo(); |
4300 | 99 | |
4301 | 99 | // Count the number of register definitions to find the asm string. |
4302 | 99 | unsigned NumDefs = 0; |
4303 | 99 | for (; MI.getOperand(NumDefs).isReg() && MI.getOperand(NumDefs).isDef()0 ; |
4304 | 99 | ++NumDefs0 ) |
4305 | 99 | assert(NumDefs != MI.getNumOperands()-2 && "No asm string?"); |
4306 | 99 | |
4307 | 99 | assert(MI.getOperand(NumDefs).isSymbol() && "No asm string?"); |
4308 | 99 | // Disassemble the AsmStr and approximate number of instructions. |
4309 | 99 | const char *AsmStr = MI.getOperand(NumDefs).getSymbolName(); |
4310 | 99 | Size = getInlineAsmLength(AsmStr, *MAI); |
4311 | 99 | } |
4312 | 90.0k | |
4313 | 90.0k | return Size; |
4314 | 90.0k | } |
4315 | | |
4316 | 228k | uint64_t HexagonInstrInfo::getType(const MachineInstr &MI) const { |
4317 | 228k | const uint64_t F = MI.getDesc().TSFlags; |
4318 | 228k | return (F >> HexagonII::TypePos) & HexagonII::TypeMask; |
4319 | 228k | } |
4320 | | |
4321 | 0 | unsigned HexagonInstrInfo::getUnits(const MachineInstr &MI) const { |
4322 | 0 | const InstrItineraryData &II = *Subtarget.getInstrItineraryData(); |
4323 | 0 | const InstrStage &IS = *II.beginStage(MI.getDesc().getSchedClass()); |
4324 | 0 |
|
4325 | 0 | return IS.getUnits(); |
4326 | 0 | } |
4327 | | |
4328 | | // Calculate size of the basic block without debug instructions. |
4329 | 4.94k | unsigned HexagonInstrInfo::nonDbgBBSize(const MachineBasicBlock *BB) const { |
4330 | 4.94k | return nonDbgMICount(BB->instr_begin(), BB->instr_end()); |
4331 | 4.94k | } |
4332 | | |
4333 | | unsigned HexagonInstrInfo::nonDbgBundleSize( |
4334 | 0 | MachineBasicBlock::const_iterator BundleHead) const { |
4335 | 0 | assert(BundleHead->isBundle() && "Not a bundle header"); |
4336 | 0 | auto MII = BundleHead.getInstrIterator(); |
4337 | 0 | // Skip the bundle header. |
4338 | 0 | return nonDbgMICount(++MII, getBundleEnd(BundleHead.getInstrIterator())); |
4339 | 0 | } |
4340 | | |
4341 | | /// immediateExtend - Changes the instruction in place to one using an immediate |
4342 | | /// extender. |
4343 | 0 | void HexagonInstrInfo::immediateExtend(MachineInstr &MI) const { |
4344 | 0 | assert((isExtendable(MI)||isConstExtended(MI)) && |
4345 | 0 | "Instruction must be extendable"); |
4346 | 0 | // Find which operand is extendable. |
4347 | 0 | short ExtOpNum = getCExtOpNum(MI); |
4348 | 0 | MachineOperand &MO = MI.getOperand(ExtOpNum); |
4349 | 0 | // This needs to be something we understand. |
4350 | 0 | assert((MO.isMBB() || MO.isImm()) && |
4351 | 0 | "Branch with unknown extendable field type"); |
4352 | 0 | // Mark given operand as extended. |
4353 | 0 | MO.addTargetFlag(HexagonII::HMOTF_ConstExtended); |
4354 | 0 | } |
4355 | | |
4356 | | bool HexagonInstrInfo::invertAndChangeJumpTarget( |
4357 | 0 | MachineInstr &MI, MachineBasicBlock *NewTarget) const { |
4358 | 0 | LLVM_DEBUG(dbgs() << "\n[invertAndChangeJumpTarget] to " |
4359 | 0 | << printMBBReference(*NewTarget); |
4360 | 0 | MI.dump();); |
4361 | 0 | assert(MI.isBranch()); |
4362 | 0 | unsigned NewOpcode = getInvertedPredicatedOpcode(MI.getOpcode()); |
4363 | 0 | int TargetPos = MI.getNumOperands() - 1; |
4364 | 0 | // In general branch target is the last operand, |
4365 | 0 | // but some implicit defs added at the end might change it. |
4366 | 0 | while ((TargetPos > -1) && !MI.getOperand(TargetPos).isMBB()) |
4367 | 0 | --TargetPos; |
4368 | 0 | assert((TargetPos >= 0) && MI.getOperand(TargetPos).isMBB()); |
4369 | 0 | MI.getOperand(TargetPos).setMBB(NewTarget); |
4370 | 0 | if (EnableBranchPrediction && isPredicatedNew(MI)) { |
4371 | 0 | NewOpcode = reversePrediction(NewOpcode); |
4372 | 0 | } |
4373 | 0 | MI.setDesc(get(NewOpcode)); |
4374 | 0 | return true; |
4375 | 0 | } |
4376 | | |
4377 | 0 | void HexagonInstrInfo::genAllInsnTimingClasses(MachineFunction &MF) const { |
4378 | 0 | /* +++ The code below is used to generate complete set of Hexagon Insn +++ */ |
4379 | 0 | MachineFunction::iterator A = MF.begin(); |
4380 | 0 | MachineBasicBlock &B = *A; |
4381 | 0 | MachineBasicBlock::iterator I = B.begin(); |
4382 | 0 | DebugLoc DL = I->getDebugLoc(); |
4383 | 0 | MachineInstr *NewMI; |
4384 | 0 |
|
4385 | 0 | for (unsigned insn = TargetOpcode::GENERIC_OP_END+1; |
4386 | 0 | insn < Hexagon::INSTRUCTION_LIST_END; ++insn) { |
4387 | 0 | NewMI = BuildMI(B, I, DL, get(insn)); |
4388 | 0 | LLVM_DEBUG(dbgs() << "\n" |
4389 | 0 | << getName(NewMI->getOpcode()) |
4390 | 0 | << " Class: " << NewMI->getDesc().getSchedClass()); |
4391 | 0 | NewMI->eraseFromParent(); |
4392 | 0 | } |
4393 | 0 | /* --- The code above is used to generate complete set of Hexagon Insn --- */ |
4394 | 0 | } |
4395 | | |
4396 | | // inverts the predication logic. |
4397 | | // p -> NotP |
4398 | | // NotP -> P |
4399 | 0 | bool HexagonInstrInfo::reversePredSense(MachineInstr &MI) const { |
4400 | 0 | LLVM_DEBUG(dbgs() << "\nTrying to reverse pred. sense of:"; MI.dump()); |
4401 | 0 | MI.setDesc(get(getInvertedPredicatedOpcode(MI.getOpcode()))); |
4402 | 0 | return true; |
4403 | 0 | } |
4404 | | |
4405 | | // Reverse the branch prediction. |
4406 | 0 | unsigned HexagonInstrInfo::reversePrediction(unsigned Opcode) const { |
4407 | 0 | int PredRevOpcode = -1; |
4408 | 0 | if (isPredictedTaken(Opcode)) |
4409 | 0 | PredRevOpcode = Hexagon::notTakenBranchPrediction(Opcode); |
4410 | 0 | else |
4411 | 0 | PredRevOpcode = Hexagon::takenBranchPrediction(Opcode); |
4412 | 0 | assert(PredRevOpcode > 0); |
4413 | 0 | return PredRevOpcode; |
4414 | 0 | } |
4415 | | |
4416 | | // TODO: Add more rigorous validation. |
4417 | | bool HexagonInstrInfo::validateBranchCond(const ArrayRef<MachineOperand> &Cond) |
4418 | 0 | const { |
4419 | 0 | return Cond.empty() || (Cond[0].isImm() && (Cond.size() != 1)); |
4420 | 0 | } |
4421 | | |
4422 | | void HexagonInstrInfo:: |
4423 | 1 | setBundleNoShuf(MachineBasicBlock::instr_iterator MIB) const { |
4424 | 1 | assert(MIB->isBundle()); |
4425 | 1 | MachineOperand &Operand = MIB->getOperand(0); |
4426 | 1 | if (Operand.isImm()) |
4427 | 0 | Operand.setImm(Operand.getImm() | memShufDisabledMask); |
4428 | 1 | else |
4429 | 1 | MIB->addOperand(MachineOperand::CreateImm(memShufDisabledMask)); |
4430 | 1 | } |
4431 | | |
4432 | 8.95k | bool HexagonInstrInfo::getBundleNoShuf(const MachineInstr &MIB) const { |
4433 | 8.95k | assert(MIB.isBundle()); |
4434 | 8.95k | const MachineOperand &Operand = MIB.getOperand(0); |
4435 | 8.95k | return (Operand.isImm() && (Operand.getImm() & memShufDisabledMask) != 01 ); |
4436 | 8.95k | } |
4437 | | |
4438 | | // Addressing mode relations. |
4439 | 0 | short HexagonInstrInfo::changeAddrMode_abs_io(short Opc) const { |
4440 | 0 | return Opc >= 0 ? Hexagon::changeAddrMode_abs_io(Opc) : Opc; |
4441 | 0 | } |
4442 | | |
4443 | 1.37k | short HexagonInstrInfo::changeAddrMode_io_abs(short Opc) const { |
4444 | 1.37k | return Opc >= 0 ? Hexagon::changeAddrMode_io_abs(Opc) : Opc0 ; |
4445 | 1.37k | } |
4446 | | |
4447 | 0 | short HexagonInstrInfo::changeAddrMode_io_pi(short Opc) const { |
4448 | 0 | return Opc >= 0 ? Hexagon::changeAddrMode_io_pi(Opc) : Opc; |
4449 | 0 | } |
4450 | | |
4451 | 4 | short HexagonInstrInfo::changeAddrMode_io_rr(short Opc) const { |
4452 | 4 | return Opc >= 0 ? Hexagon::changeAddrMode_io_rr(Opc) : Opc0 ; |
4453 | 4 | } |
4454 | | |
4455 | 0 | short HexagonInstrInfo::changeAddrMode_pi_io(short Opc) const { |
4456 | 0 | return Opc >= 0 ? Hexagon::changeAddrMode_pi_io(Opc) : Opc; |
4457 | 0 | } |
4458 | | |
4459 | 1 | short HexagonInstrInfo::changeAddrMode_rr_io(short Opc) const { |
4460 | 1 | return Opc >= 0 ? Hexagon::changeAddrMode_rr_io(Opc) : Opc0 ; |
4461 | 1 | } |
4462 | | |
4463 | 32 | short HexagonInstrInfo::changeAddrMode_rr_ur(short Opc) const { |
4464 | 32 | return Opc >= 0 ? Hexagon::changeAddrMode_rr_ur(Opc) : Opc0 ; |
4465 | 32 | } |
4466 | | |
4467 | 1 | short HexagonInstrInfo::changeAddrMode_ur_rr(short Opc) const { |
4468 | 1 | return Opc >= 0 ? Hexagon::changeAddrMode_ur_rr(Opc) : Opc0 ; |
4469 | 1 | } |