1 | //===----- HexagonMCChecker.cpp - Instruction bundle checking -------------===// |
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 implements the checking of insns inside a bundle according to the |
10 | // packet constraint rules of the Hexagon ISA. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "MCTargetDesc/HexagonMCChecker.h" |
15 | #include "MCTargetDesc/HexagonBaseInfo.h" |
16 | #include "MCTargetDesc/HexagonMCInstrInfo.h" |
17 | #include "MCTargetDesc/HexagonMCShuffler.h" |
18 | #include "MCTargetDesc/HexagonMCTargetDesc.h" |
19 | |
20 | #include "llvm/ADT/Twine.h" |
21 | #include "llvm/MC/MCContext.h" |
22 | #include "llvm/MC/MCInst.h" |
23 | #include "llvm/MC/MCInstrDesc.h" |
24 | #include "llvm/MC/MCRegisterInfo.h" |
25 | #include "llvm/MC/MCSubtargetInfo.h" |
26 | #include "llvm/Support/CommandLine.h" |
27 | #include "llvm/Support/SourceMgr.h" |
28 | #include <cassert> |
29 | |
30 | using namespace llvm; |
31 | |
32 | static cl::opt<bool> |
33 | RelaxNVChecks("relax-nv-checks" , cl::Hidden, |
34 | cl::desc("Relax checks of new-value validity" )); |
35 | |
36 | const HexagonMCChecker::PredSense |
37 | HexagonMCChecker::Unconditional(Hexagon::NoRegister, false); |
38 | |
39 | void HexagonMCChecker::init() { |
40 | // Initialize read-only registers set. |
41 | ReadOnly.insert(x: Hexagon::PC); |
42 | ReadOnly.insert(x: Hexagon::C9_8); |
43 | |
44 | // Figure out the loop-registers definitions. |
45 | if (HexagonMCInstrInfo::isInnerLoop(MCI: MCB)) { |
46 | Defs[Hexagon::SA0].insert(x: Unconditional); // FIXME: define or change SA0? |
47 | Defs[Hexagon::LC0].insert(x: Unconditional); |
48 | } |
49 | if (HexagonMCInstrInfo::isOuterLoop(MCI: MCB)) { |
50 | Defs[Hexagon::SA1].insert(x: Unconditional); // FIXME: define or change SA0? |
51 | Defs[Hexagon::LC1].insert(x: Unconditional); |
52 | } |
53 | |
54 | if (HexagonMCInstrInfo::isBundle(MCI: MCB)) |
55 | // Unfurl a bundle. |
56 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCI: MCB)) { |
57 | MCInst const &Inst = *I.getInst(); |
58 | if (HexagonMCInstrInfo::isDuplex(MCII, MCI: Inst)) { |
59 | init(*Inst.getOperand(i: 0).getInst()); |
60 | init(*Inst.getOperand(i: 1).getInst()); |
61 | } else |
62 | init(Inst); |
63 | } |
64 | else |
65 | init(MCB); |
66 | } |
67 | |
68 | void HexagonMCChecker::initReg(MCInst const &MCI, unsigned R, unsigned &PredReg, |
69 | bool &isTrue) { |
70 | if (HexagonMCInstrInfo::isPredicated(MCII, MCI) && |
71 | HexagonMCInstrInfo::isPredReg(MRI: RI, Reg: R)) { |
72 | // Note an used predicate register. |
73 | PredReg = R; |
74 | isTrue = HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI); |
75 | |
76 | // Note use of new predicate register. |
77 | if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI)) |
78 | NewPreds.insert(x: PredReg); |
79 | } else |
80 | // Note register use. Super-registers are not tracked directly, |
81 | // but their components. |
82 | for (MCRegAliasIterator SRI(R, &RI, RI.subregs(Reg: R).empty()); SRI.isValid(); |
83 | ++SRI) |
84 | if (RI.subregs(Reg: *SRI).empty()) |
85 | // Skip super-registers used indirectly. |
86 | Uses.insert(x: *SRI); |
87 | |
88 | if (HexagonMCInstrInfo::IsReverseVecRegPair(VecReg: R)) |
89 | ReversePairs.insert(x: R); |
90 | } |
91 | |
92 | void HexagonMCChecker::init(MCInst const &MCI) { |
93 | const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MCI); |
94 | unsigned PredReg = Hexagon::NoRegister; |
95 | bool isTrue = false; |
96 | |
97 | // Get used registers. |
98 | for (unsigned i = MCID.getNumDefs(); i < MCID.getNumOperands(); ++i) |
99 | if (MCI.getOperand(i).isReg()) |
100 | initReg(MCI, R: MCI.getOperand(i).getReg(), PredReg, isTrue); |
101 | for (MCPhysReg ImpUse : MCID.implicit_uses()) |
102 | initReg(MCI, R: ImpUse, PredReg, isTrue); |
103 | |
104 | const bool IgnoreTmpDst = (HexagonMCInstrInfo::hasTmpDst(MCII, MCI) || |
105 | HexagonMCInstrInfo::hasHvxTmp(MCII, MCI)) && |
106 | STI.hasFeature(Feature: Hexagon::ArchV69); |
107 | |
108 | // Get implicit register definitions. |
109 | for (MCPhysReg R : MCID.implicit_defs()) { |
110 | if (Hexagon::R31 != R && MCID.isCall()) |
111 | // Any register other than the LR and the PC are actually volatile ones |
112 | // as defined by the ABI, not modified implicitly by the call insn. |
113 | continue; |
114 | if (Hexagon::PC == R) |
115 | // Branches are the only insns that can change the PC, |
116 | // otherwise a read-only register. |
117 | continue; |
118 | |
119 | if (Hexagon::USR_OVF == R) |
120 | // Many insns change the USR implicitly, but only one or another flag. |
121 | // The instruction table models the USR.OVF flag, which can be |
122 | // implicitly modified more than once, but cannot be modified in the |
123 | // same packet with an instruction that modifies is explicitly. Deal |
124 | // with such situations individually. |
125 | SoftDefs.insert(x: R); |
126 | else if (HexagonMCInstrInfo::isPredReg(MRI: RI, Reg: R) && |
127 | HexagonMCInstrInfo::isPredicateLate(MCII, MCI)) |
128 | // Include implicit late predicates. |
129 | LatePreds.insert(x: R); |
130 | else if (!IgnoreTmpDst) |
131 | Defs[R].insert(x: PredSense(PredReg, isTrue)); |
132 | } |
133 | |
134 | // Figure out explicit register definitions. |
135 | for (unsigned i = 0; i < MCID.getNumDefs(); ++i) { |
136 | unsigned R = MCI.getOperand(i).getReg(), S = Hexagon::NoRegister; |
137 | // USR has subregisters (while C8 does not for technical reasons), so |
138 | // reset R to USR, since we know how to handle multiple defs of USR, |
139 | // taking into account its subregisters. |
140 | if (R == Hexagon::C8) |
141 | R = Hexagon::USR; |
142 | |
143 | if (HexagonMCInstrInfo::IsReverseVecRegPair(VecReg: R)) |
144 | ReversePairs.insert(x: R); |
145 | |
146 | // Note register definitions, direct ones as well as indirect side-effects. |
147 | // Super-registers are not tracked directly, but their components. |
148 | for (MCRegAliasIterator SRI(R, &RI, RI.subregs(Reg: R).empty()); SRI.isValid(); |
149 | ++SRI) { |
150 | if (!RI.subregs(Reg: *SRI).empty()) |
151 | // Skip super-registers defined indirectly. |
152 | continue; |
153 | |
154 | if (R == *SRI) { |
155 | if (S == R) |
156 | // Avoid scoring the defined register multiple times. |
157 | continue; |
158 | else |
159 | // Note that the defined register has already been scored. |
160 | S = R; |
161 | } |
162 | |
163 | if (Hexagon::P3_0 != R && Hexagon::P3_0 == *SRI) |
164 | // P3:0 is a special case, since multiple predicate register definitions |
165 | // in a packet is allowed as the equivalent of their logical "and". |
166 | // Only an explicit definition of P3:0 is noted as such; if a |
167 | // side-effect, then note as a soft definition. |
168 | SoftDefs.insert(x: *SRI); |
169 | else if (HexagonMCInstrInfo::isPredicateLate(MCII, MCI) && |
170 | HexagonMCInstrInfo::isPredReg(MRI: RI, Reg: *SRI)) |
171 | // Some insns produce predicates too late to be used in the same packet. |
172 | LatePreds.insert(x: *SRI); |
173 | else if (i == 0 && HexagonMCInstrInfo::getType(MCII, MCI) == |
174 | HexagonII::TypeCVI_VM_TMP_LD) |
175 | // Temporary loads should be used in the same packet, but don't commit |
176 | // results, so it should be disregarded if another insn changes the same |
177 | // register. |
178 | // TODO: relies on the impossibility of a current and a temporary loads |
179 | // in the same packet. |
180 | TmpDefs.insert(x: *SRI); |
181 | else if (!IgnoreTmpDst) |
182 | Defs[*SRI].insert(x: PredSense(PredReg, isTrue)); |
183 | } |
184 | } |
185 | |
186 | // Figure out definitions of new predicate registers. |
187 | if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI)) |
188 | for (unsigned i = MCID.getNumDefs(); i < MCID.getNumOperands(); ++i) |
189 | if (MCI.getOperand(i).isReg()) { |
190 | unsigned P = MCI.getOperand(i).getReg(); |
191 | |
192 | if (HexagonMCInstrInfo::isPredReg(MRI: RI, Reg: P)) |
193 | NewPreds.insert(x: P); |
194 | } |
195 | } |
196 | |
197 | HexagonMCChecker::HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII, |
198 | MCSubtargetInfo const &STI, MCInst &mcb, |
199 | MCRegisterInfo const &ri, bool ReportErrors) |
200 | : Context(Context), MCB(mcb), RI(ri), MCII(MCII), STI(STI), |
201 | ReportErrors(ReportErrors) { |
202 | init(); |
203 | } |
204 | |
205 | HexagonMCChecker::HexagonMCChecker(HexagonMCChecker const &Other, |
206 | MCSubtargetInfo const &STI, |
207 | bool CopyReportErrors) |
208 | : Context(Other.Context), MCB(Other.MCB), RI(Other.RI), MCII(Other.MCII), |
209 | STI(STI), ReportErrors(CopyReportErrors ? Other.ReportErrors : false) { |
210 | init(); |
211 | } |
212 | |
213 | bool HexagonMCChecker::check(bool FullCheck) { |
214 | bool chkP = checkPredicates(); |
215 | bool chkNV = checkNewValues(); |
216 | bool chkR = checkRegisters(); |
217 | bool chkRRO = checkRegistersReadOnly(); |
218 | checkRegisterCurDefs(); |
219 | bool chkS = checkSolo(); |
220 | bool chkSh = true; |
221 | if (FullCheck) |
222 | chkSh = checkShuffle(); |
223 | bool chkSl = true; |
224 | if (FullCheck) |
225 | chkSl = checkSlots(); |
226 | bool chkAXOK = checkAXOK(); |
227 | bool chkCofMax1 = checkCOFMax1(); |
228 | bool chkHWLoop = checkHWLoop(); |
229 | bool chkValidTmpDst = FullCheck ? checkValidTmpDst() : true; |
230 | bool chkLegalVecRegPair = checkLegalVecRegPair(); |
231 | bool ChkHVXAccum = checkHVXAccum(); |
232 | bool chk = chkP && chkNV && chkR && chkRRO && chkS && chkSh && chkSl && |
233 | chkAXOK && chkCofMax1 && chkHWLoop && chkValidTmpDst && |
234 | chkLegalVecRegPair && ChkHVXAccum; |
235 | |
236 | return chk; |
237 | } |
238 | |
239 | static bool isDuplexAGroup(unsigned Opcode) { |
240 | switch (Opcode) { |
241 | case Hexagon::SA1_addi: |
242 | case Hexagon::SA1_addrx: |
243 | case Hexagon::SA1_addsp: |
244 | case Hexagon::SA1_and1: |
245 | case Hexagon::SA1_clrf: |
246 | case Hexagon::SA1_clrfnew: |
247 | case Hexagon::SA1_clrt: |
248 | case Hexagon::SA1_clrtnew: |
249 | case Hexagon::SA1_cmpeqi: |
250 | case Hexagon::SA1_combine0i: |
251 | case Hexagon::SA1_combine1i: |
252 | case Hexagon::SA1_combine2i: |
253 | case Hexagon::SA1_combine3i: |
254 | case Hexagon::SA1_combinerz: |
255 | case Hexagon::SA1_combinezr: |
256 | case Hexagon::SA1_dec: |
257 | case Hexagon::SA1_inc: |
258 | case Hexagon::SA1_seti: |
259 | case Hexagon::SA1_setin1: |
260 | case Hexagon::SA1_sxtb: |
261 | case Hexagon::SA1_sxth: |
262 | case Hexagon::SA1_tfr: |
263 | case Hexagon::SA1_zxtb: |
264 | case Hexagon::SA1_zxth: |
265 | return true; |
266 | break; |
267 | default: |
268 | return false; |
269 | } |
270 | } |
271 | |
272 | static bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) { |
273 | if (HexagonMCInstrInfo::isFloat(MCII, MCI: ID)) |
274 | return true; |
275 | unsigned Type = HexagonMCInstrInfo::getType(MCII, MCI: ID); |
276 | switch (Type) { |
277 | case HexagonII::TypeALU32_2op: |
278 | case HexagonII::TypeALU32_3op: |
279 | case HexagonII::TypeALU32_ADDI: |
280 | case HexagonII::TypeS_2op: |
281 | case HexagonII::TypeS_3op: |
282 | case HexagonII::TypeEXTENDER: |
283 | case HexagonII::TypeM: |
284 | case HexagonII::TypeALU64: |
285 | return false; |
286 | case HexagonII::TypeSUBINSN: { |
287 | return !isDuplexAGroup(Opcode: ID.getOpcode()); |
288 | } |
289 | case HexagonII::TypeDUPLEX: |
290 | llvm_unreachable("unexpected duplex instruction" ); |
291 | default: |
292 | return true; |
293 | } |
294 | } |
295 | |
296 | bool HexagonMCChecker::checkAXOK() { |
297 | MCInst const *HasSoloAXInst = nullptr; |
298 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) { |
299 | if (HexagonMCInstrInfo::isSoloAX(MCII, MCI: I)) { |
300 | HasSoloAXInst = &I; |
301 | } |
302 | } |
303 | if (!HasSoloAXInst) |
304 | return true; |
305 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) { |
306 | if (&I != HasSoloAXInst && isNeitherAnorX(MCII, ID: I)) { |
307 | reportError( |
308 | Loc: HasSoloAXInst->getLoc(), |
309 | Msg: Twine("Instruction can only be in a packet with ALU or non-FPU XTYPE " |
310 | "instructions" )); |
311 | reportError(Loc: I.getLoc(), |
312 | Msg: Twine("Not an ALU or non-FPU XTYPE instruction" )); |
313 | return false; |
314 | } |
315 | } |
316 | return true; |
317 | } |
318 | |
319 | void HexagonMCChecker::reportBranchErrors() { |
320 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) { |
321 | if (HexagonMCInstrInfo::IsABranchingInst(MCII, STI, I)) |
322 | reportNote(Loc: I.getLoc(), Msg: "Branching instruction" ); |
323 | } |
324 | } |
325 | |
326 | bool HexagonMCChecker::checkHWLoop() { |
327 | if (!HexagonMCInstrInfo::isInnerLoop(MCI: MCB) && |
328 | !HexagonMCInstrInfo::isOuterLoop(MCI: MCB)) |
329 | return true; |
330 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) { |
331 | if (HexagonMCInstrInfo::IsABranchingInst(MCII, STI, I)) { |
332 | reportError(Loc: MCB.getLoc(), |
333 | Msg: "Branches cannot be in a packet with hardware loops" ); |
334 | reportBranchErrors(); |
335 | return false; |
336 | } |
337 | } |
338 | return true; |
339 | } |
340 | |
341 | bool HexagonMCChecker::checkCOFMax1() { |
342 | SmallVector<MCInst const *, 2> BranchLocations; |
343 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) { |
344 | if (HexagonMCInstrInfo::IsABranchingInst(MCII, STI, I)) |
345 | BranchLocations.push_back(Elt: &I); |
346 | } |
347 | for (unsigned J = 0, N = BranchLocations.size(); J < N; ++J) { |
348 | MCInst const &I = *BranchLocations[J]; |
349 | if (HexagonMCInstrInfo::isCofMax1(MCII, MCI: I)) { |
350 | bool Relax1 = HexagonMCInstrInfo::isCofRelax1(MCII, MCI: I); |
351 | bool Relax2 = HexagonMCInstrInfo::isCofRelax2(MCII, MCI: I); |
352 | if (N > 1 && !Relax1 && !Relax2) { |
353 | reportError(Loc: I.getLoc(), |
354 | Msg: "Instruction may not be in a packet with other branches" ); |
355 | reportBranchErrors(); |
356 | return false; |
357 | } |
358 | if (N > 1 && J == 0 && !Relax1) { |
359 | reportError(Loc: I.getLoc(), |
360 | Msg: "Instruction may not be the first branch in packet" ); |
361 | reportBranchErrors(); |
362 | return false; |
363 | } |
364 | if (N > 1 && J == 1 && !Relax2) { |
365 | reportError(Loc: I.getLoc(), |
366 | Msg: "Instruction may not be the second branch in packet" ); |
367 | reportBranchErrors(); |
368 | return false; |
369 | } |
370 | } |
371 | } |
372 | return true; |
373 | } |
374 | |
375 | bool HexagonMCChecker::checkSlots() { |
376 | if (HexagonMCInstrInfo::slotsConsumed(MCII, STI, MCI: MCB) > |
377 | HexagonMCInstrInfo::packetSizeSlots(STI)) { |
378 | reportError(Msg: "invalid instruction packet: out of slots" ); |
379 | return false; |
380 | } |
381 | return true; |
382 | } |
383 | |
384 | // Check legal use of predicate registers. |
385 | bool HexagonMCChecker::checkPredicates() { |
386 | // Check for proper use of new predicate registers. |
387 | for (const auto &I : NewPreds) { |
388 | unsigned P = I; |
389 | |
390 | if (!Defs.count(Val: P) || LatePreds.count(x: P) || Defs.count(Val: Hexagon::P3_0)) { |
391 | // Error out if the new predicate register is not defined, |
392 | // or defined "late" |
393 | // (e.g., "{ if (p3.new)... ; p3 = sp1loop0(#r7:2, Rs) }"). |
394 | reportErrorNewValue(Register: P); |
395 | return false; |
396 | } |
397 | } |
398 | |
399 | // Check for proper use of auto-anded of predicate registers. |
400 | for (const auto &I : LatePreds) { |
401 | unsigned P = I; |
402 | |
403 | if (LatePreds.count(x: P) > 1 || Defs.count(Val: P)) { |
404 | // Error out if predicate register defined "late" multiple times or |
405 | // defined late and regularly defined |
406 | // (e.g., "{ p3 = sp1loop0(...); p3 = cmp.eq(...) }". |
407 | reportErrorRegisters(Register: P); |
408 | return false; |
409 | } |
410 | } |
411 | |
412 | return true; |
413 | } |
414 | |
415 | // Check legal use of new values. |
416 | bool HexagonMCChecker::checkNewValues() { |
417 | for (auto const &ConsumerInst : |
418 | HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) { |
419 | if (!HexagonMCInstrInfo::isNewValue(MCII, MCI: ConsumerInst)) |
420 | continue; |
421 | |
422 | const HexagonMCInstrInfo::PredicateInfo ConsumerPredInfo = |
423 | HexagonMCInstrInfo::predicateInfo(MCII, MCI: ConsumerInst); |
424 | |
425 | bool Branch = HexagonMCInstrInfo::getDesc(MCII, MCI: ConsumerInst).isBranch(); |
426 | MCOperand const &Op = |
427 | HexagonMCInstrInfo::getNewValueOperand(MCII, MCI: ConsumerInst); |
428 | assert(Op.isReg()); |
429 | |
430 | auto Producer = registerProducer(Register: Op.getReg(), Predicated: ConsumerPredInfo); |
431 | const MCInst *const ProducerInst = std::get<0>(t&: Producer); |
432 | const HexagonMCInstrInfo::PredicateInfo ProducerPredInfo = |
433 | std::get<2>(t&: Producer); |
434 | |
435 | if (ProducerInst == nullptr) { |
436 | reportError(Loc: ConsumerInst.getLoc(), |
437 | Msg: "New value register consumer has no producer" ); |
438 | return false; |
439 | } |
440 | if (!RelaxNVChecks) { |
441 | // Checks that statically prove correct new value consumption |
442 | if (ProducerPredInfo.isPredicated() && |
443 | (!ConsumerPredInfo.isPredicated() || |
444 | llvm::HexagonMCInstrInfo::getType(MCII, MCI: ConsumerInst) == |
445 | HexagonII::TypeNCJ)) { |
446 | reportNote( |
447 | Loc: ProducerInst->getLoc(), |
448 | Msg: "Register producer is predicated and consumer is unconditional" ); |
449 | reportError(Loc: ConsumerInst.getLoc(), |
450 | Msg: "Instruction does not have a valid new register producer" ); |
451 | return false; |
452 | } |
453 | if (ProducerPredInfo.Register != Hexagon::NoRegister && |
454 | ProducerPredInfo.Register != ConsumerPredInfo.Register) { |
455 | reportNote(Loc: ProducerInst->getLoc(), |
456 | Msg: "Register producer does not use the same predicate " |
457 | "register as the consumer" ); |
458 | reportError(Loc: ConsumerInst.getLoc(), |
459 | Msg: "Instruction does not have a valid new register producer" ); |
460 | return false; |
461 | } |
462 | } |
463 | if (ProducerPredInfo.Register == ConsumerPredInfo.Register && |
464 | ConsumerPredInfo.PredicatedTrue != ProducerPredInfo.PredicatedTrue) { |
465 | reportNote( |
466 | Loc: ProducerInst->getLoc(), |
467 | Msg: "Register producer has the opposite predicate sense as consumer" ); |
468 | reportError(Loc: ConsumerInst.getLoc(), |
469 | Msg: "Instruction does not have a valid new register producer" ); |
470 | return false; |
471 | } |
472 | |
473 | MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, MCI: *ProducerInst); |
474 | const unsigned ProducerOpIndex = std::get<1>(t&: Producer); |
475 | |
476 | if (Desc.operands()[ProducerOpIndex].RegClass == |
477 | Hexagon::DoubleRegsRegClassID) { |
478 | reportNote(Loc: ProducerInst->getLoc(), |
479 | Msg: "Double registers cannot be new-value producers" ); |
480 | reportError(Loc: ConsumerInst.getLoc(), |
481 | Msg: "Instruction does not have a valid new register producer" ); |
482 | return false; |
483 | } |
484 | |
485 | // The ProducerOpIsMemIndex logic checks for the index of the producer |
486 | // register operand. Z-reg load instructions have an implicit operand |
487 | // that's not encoded, so the producer won't appear as the 1-th def, it |
488 | // will be at the 0-th. |
489 | const unsigned ProducerOpSearchIndex = |
490 | (HexagonMCInstrInfo::getType(MCII, MCI: *ProducerInst) == |
491 | HexagonII::TypeCVI_ZW) |
492 | ? 0 |
493 | : 1; |
494 | |
495 | const bool ProducerOpIsMemIndex = |
496 | ((Desc.mayLoad() && ProducerOpIndex == ProducerOpSearchIndex) || |
497 | (Desc.mayStore() && ProducerOpIndex == 0)); |
498 | |
499 | if (ProducerOpIsMemIndex) { |
500 | unsigned Mode = HexagonMCInstrInfo::getAddrMode(MCII, MCI: *ProducerInst); |
501 | |
502 | StringRef ModeError; |
503 | if (Mode == HexagonII::AbsoluteSet) |
504 | ModeError = "Absolute-set" ; |
505 | if (Mode == HexagonII::PostInc) |
506 | ModeError = "Auto-increment" ; |
507 | if (!ModeError.empty()) { |
508 | reportNote(Loc: ProducerInst->getLoc(), |
509 | Msg: ModeError + " registers cannot be a new-value " |
510 | "producer" ); |
511 | reportError(Loc: ConsumerInst.getLoc(), |
512 | Msg: "Instruction does not have a valid new register producer" ); |
513 | return false; |
514 | } |
515 | } |
516 | if (Branch && HexagonMCInstrInfo::isFloat(MCII, MCI: *ProducerInst)) { |
517 | reportNote(Loc: ProducerInst->getLoc(), |
518 | Msg: "FPU instructions cannot be new-value producers for jumps" ); |
519 | reportError(Loc: ConsumerInst.getLoc(), |
520 | Msg: "Instruction does not have a valid new register producer" ); |
521 | return false; |
522 | } |
523 | } |
524 | return true; |
525 | } |
526 | |
527 | bool HexagonMCChecker::checkRegistersReadOnly() { |
528 | for (auto I : HexagonMCInstrInfo::bundleInstructions(MCI: MCB)) { |
529 | MCInst const &Inst = *I.getInst(); |
530 | unsigned Defs = HexagonMCInstrInfo::getDesc(MCII, MCI: Inst).getNumDefs(); |
531 | for (unsigned j = 0; j < Defs; ++j) { |
532 | MCOperand const &Operand = Inst.getOperand(i: j); |
533 | assert(Operand.isReg() && "Def is not a register" ); |
534 | unsigned Register = Operand.getReg(); |
535 | if (ReadOnly.find(x: Register) != ReadOnly.end()) { |
536 | reportError(Loc: Inst.getLoc(), Msg: "Cannot write to read-only register `" + |
537 | Twine(RI.getName(RegNo: Register)) + "'" ); |
538 | return false; |
539 | } |
540 | } |
541 | } |
542 | return true; |
543 | } |
544 | |
545 | bool HexagonMCChecker::registerUsed(unsigned Register) { |
546 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) |
547 | for (unsigned j = HexagonMCInstrInfo::getDesc(MCII, MCI: I).getNumDefs(), |
548 | n = I.getNumOperands(); |
549 | j < n; ++j) { |
550 | MCOperand const &Operand = I.getOperand(i: j); |
551 | if (Operand.isReg() && Operand.getReg() == Register) |
552 | return true; |
553 | } |
554 | return false; |
555 | } |
556 | |
557 | std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo> |
558 | HexagonMCChecker::registerProducer( |
559 | unsigned Register, HexagonMCInstrInfo::PredicateInfo ConsumerPredicate) { |
560 | std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo> |
561 | WrongSense; |
562 | |
563 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) { |
564 | MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, MCI: I); |
565 | auto ProducerPredicate = HexagonMCInstrInfo::predicateInfo(MCII, MCI: I); |
566 | |
567 | for (unsigned J = 0, N = Desc.getNumDefs(); J < N; ++J) |
568 | for (auto K = MCRegAliasIterator(I.getOperand(i: J).getReg(), &RI, true); |
569 | K.isValid(); ++K) |
570 | if (*K == Register) { |
571 | if (RelaxNVChecks || |
572 | (ProducerPredicate.Register == ConsumerPredicate.Register && |
573 | (ProducerPredicate.Register == Hexagon::NoRegister || |
574 | ProducerPredicate.PredicatedTrue == |
575 | ConsumerPredicate.PredicatedTrue))) |
576 | return std::make_tuple(args: &I, args&: J, args&: ProducerPredicate); |
577 | std::get<0>(t&: WrongSense) = &I; |
578 | std::get<1>(t&: WrongSense) = J; |
579 | std::get<2>(t&: WrongSense) = ProducerPredicate; |
580 | } |
581 | if (Register == Hexagon::VTMP && HexagonMCInstrInfo::hasTmpDst(MCII, MCI: I)) |
582 | return std::make_tuple(args: &I, args: 0, args: HexagonMCInstrInfo::PredicateInfo()); |
583 | } |
584 | return WrongSense; |
585 | } |
586 | |
587 | void HexagonMCChecker::checkRegisterCurDefs() { |
588 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) { |
589 | if (HexagonMCInstrInfo::isCVINew(MCII, MCI: I) && |
590 | HexagonMCInstrInfo::getDesc(MCII, MCI: I).mayLoad()) { |
591 | const unsigned RegDef = I.getOperand(i: 0).getReg(); |
592 | |
593 | bool HasRegDefUse = false; |
594 | for (MCRegAliasIterator Alias(RegDef, &RI, true); Alias.isValid(); |
595 | ++Alias) |
596 | HasRegDefUse = HasRegDefUse || registerUsed(Register: *Alias); |
597 | |
598 | if (!HasRegDefUse) |
599 | reportWarning(Msg: "Register `" + Twine(RI.getName(RegNo: RegDef)) + |
600 | "' used with `.cur' " |
601 | "but not used in the same packet" ); |
602 | } |
603 | } |
604 | } |
605 | |
606 | // Check for legal register uses and definitions. |
607 | bool HexagonMCChecker::checkRegisters() { |
608 | // Check for proper register definitions. |
609 | for (const auto &I : Defs) { |
610 | unsigned R = I.first; |
611 | |
612 | if (isLoopRegister(R) && Defs.count(Val: R) > 1 && |
613 | (HexagonMCInstrInfo::isInnerLoop(MCI: MCB) || |
614 | HexagonMCInstrInfo::isOuterLoop(MCI: MCB))) { |
615 | // Error out for definitions of loop registers at the end of a loop. |
616 | reportError(Msg: "loop-setup and some branch instructions " |
617 | "cannot be in the same packet" ); |
618 | return false; |
619 | } |
620 | if (SoftDefs.count(x: R)) { |
621 | // Error out for explicit changes to registers also weakly defined |
622 | // (e.g., "{ usr = r0; r0 = sfadd(...) }"). |
623 | unsigned UsrR = Hexagon::USR; // Silence warning about mixed types in ?:. |
624 | unsigned BadR = RI.isSubRegister(RegA: Hexagon::USR, RegB: R) ? UsrR : R; |
625 | reportErrorRegisters(Register: BadR); |
626 | return false; |
627 | } |
628 | if (!HexagonMCInstrInfo::isPredReg(MRI: RI, Reg: R) && Defs[R].size() > 1) { |
629 | // Check for multiple register definitions. |
630 | PredSet &PM = Defs[R]; |
631 | |
632 | // Check for multiple unconditional register definitions. |
633 | if (PM.count(x: Unconditional)) { |
634 | // Error out on an unconditional change when there are any other |
635 | // changes, conditional or not. |
636 | unsigned UsrR = Hexagon::USR; |
637 | unsigned BadR = RI.isSubRegister(RegA: Hexagon::USR, RegB: R) ? UsrR : R; |
638 | reportErrorRegisters(Register: BadR); |
639 | return false; |
640 | } |
641 | // Check for multiple conditional register definitions. |
642 | for (const auto &J : PM) { |
643 | PredSense P = J; |
644 | |
645 | // Check for multiple uses of the same condition. |
646 | if (PM.count(x: P) > 1) { |
647 | // Error out on conditional changes based on the same predicate |
648 | // (e.g., "{ if (!p0) r0 =...; if (!p0) r0 =... }"). |
649 | reportErrorRegisters(Register: R); |
650 | return false; |
651 | } |
652 | // Check for the use of the complementary condition. |
653 | P.second = !P.second; |
654 | if (PM.count(x: P) && PM.size() > 2) { |
655 | // Error out on conditional changes based on the same predicate |
656 | // multiple times |
657 | // (e.g., "if (p0) r0 =...; if (!p0) r0 =... }; if (!p0) r0 =..."). |
658 | reportErrorRegisters(Register: R); |
659 | return false; |
660 | } |
661 | } |
662 | } |
663 | } |
664 | |
665 | // Check for use of temporary definitions. |
666 | for (const auto &I : TmpDefs) { |
667 | unsigned R = I; |
668 | |
669 | if (!Uses.count(x: R)) { |
670 | // special case for vhist |
671 | bool vHistFound = false; |
672 | for (auto const &HMI : HexagonMCInstrInfo::bundleInstructions(MCI: MCB)) { |
673 | if (HexagonMCInstrInfo::getType(MCII, MCI: *HMI.getInst()) == |
674 | HexagonII::TypeCVI_HIST) { |
675 | vHistFound = true; // vhist() implicitly uses ALL REGxx.tmp |
676 | break; |
677 | } |
678 | } |
679 | // Warn on an unused temporary definition. |
680 | if (!vHistFound) { |
681 | reportWarning(Msg: "register `" + Twine(RI.getName(RegNo: R)) + |
682 | "' used with `.tmp' but not used in the same packet" ); |
683 | return true; |
684 | } |
685 | } |
686 | } |
687 | |
688 | return true; |
689 | } |
690 | |
691 | // Check for legal use of solo insns. |
692 | bool HexagonMCChecker::checkSolo() { |
693 | if (HexagonMCInstrInfo::bundleSize(MCI: MCB) > 1) |
694 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) { |
695 | if (HexagonMCInstrInfo::isSolo(MCII, MCI: I)) { |
696 | reportError(Loc: I.getLoc(), Msg: "Instruction is marked `isSolo' and " |
697 | "cannot have other instructions in " |
698 | "the same packet" ); |
699 | return false; |
700 | } |
701 | } |
702 | |
703 | return true; |
704 | } |
705 | |
706 | bool HexagonMCChecker::checkShuffle() { |
707 | HexagonMCShuffler MCSDX(Context, ReportErrors, MCII, STI, MCB); |
708 | return MCSDX.check(); |
709 | } |
710 | |
711 | bool HexagonMCChecker::checkValidTmpDst() { |
712 | if (!STI.hasFeature(Feature: Hexagon::ArchV69)) { |
713 | return true; |
714 | } |
715 | auto HasTmp = [&](MCInst const &I) { |
716 | return HexagonMCInstrInfo::hasTmpDst(MCII, MCI: I) || |
717 | HexagonMCInstrInfo::hasHvxTmp(MCII, MCI: I); |
718 | }; |
719 | unsigned HasTmpCount = |
720 | llvm::count_if(Range: HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB), P: HasTmp); |
721 | |
722 | if (HasTmpCount > 1) { |
723 | reportError( |
724 | Loc: MCB.getLoc(), |
725 | Msg: "this packet has more than one HVX vtmp/.tmp destination instruction" ); |
726 | |
727 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) |
728 | if (HasTmp(I)) |
729 | reportNote(Loc: I.getLoc(), |
730 | Msg: "this is an HVX vtmp/.tmp destination instruction" ); |
731 | |
732 | return false; |
733 | } |
734 | return true; |
735 | } |
736 | |
737 | void HexagonMCChecker::compoundRegisterMap(unsigned &Register) { |
738 | switch (Register) { |
739 | default: |
740 | break; |
741 | case Hexagon::R15: |
742 | Register = Hexagon::R23; |
743 | break; |
744 | case Hexagon::R14: |
745 | Register = Hexagon::R22; |
746 | break; |
747 | case Hexagon::R13: |
748 | Register = Hexagon::R21; |
749 | break; |
750 | case Hexagon::R12: |
751 | Register = Hexagon::R20; |
752 | break; |
753 | case Hexagon::R11: |
754 | Register = Hexagon::R19; |
755 | break; |
756 | case Hexagon::R10: |
757 | Register = Hexagon::R18; |
758 | break; |
759 | case Hexagon::R9: |
760 | Register = Hexagon::R17; |
761 | break; |
762 | case Hexagon::R8: |
763 | Register = Hexagon::R16; |
764 | break; |
765 | } |
766 | } |
767 | |
768 | void HexagonMCChecker::reportErrorRegisters(unsigned Register) { |
769 | reportError(Msg: "register `" + Twine(RI.getName(RegNo: Register)) + |
770 | "' modified more than once" ); |
771 | } |
772 | |
773 | void HexagonMCChecker::reportErrorNewValue(unsigned Register) { |
774 | reportError(Msg: "register `" + Twine(RI.getName(RegNo: Register)) + |
775 | "' used with `.new' " |
776 | "but not validly modified in the same packet" ); |
777 | } |
778 | |
779 | void HexagonMCChecker::reportError(Twine const &Msg) { |
780 | reportError(Loc: MCB.getLoc(), Msg); |
781 | } |
782 | |
783 | void HexagonMCChecker::reportError(SMLoc Loc, Twine const &Msg) { |
784 | if (ReportErrors) |
785 | Context.reportError(L: Loc, Msg); |
786 | } |
787 | |
788 | void HexagonMCChecker::reportNote(SMLoc Loc, llvm::Twine const &Msg) { |
789 | if (ReportErrors) { |
790 | auto SM = Context.getSourceManager(); |
791 | if (SM) |
792 | SM->PrintMessage(Loc, Kind: SourceMgr::DK_Note, Msg); |
793 | } |
794 | } |
795 | |
796 | void HexagonMCChecker::reportWarning(Twine const &Msg) { |
797 | if (ReportErrors) |
798 | Context.reportWarning(L: MCB.getLoc(), Msg); |
799 | } |
800 | |
801 | bool HexagonMCChecker::checkLegalVecRegPair() { |
802 | const bool IsPermitted = STI.hasFeature(Feature: Hexagon::ArchV67); |
803 | const bool HasReversePairs = ReversePairs.size() != 0; |
804 | |
805 | if (!IsPermitted && HasReversePairs) { |
806 | for (auto R : ReversePairs) |
807 | reportError(Msg: "register pair `" + Twine(RI.getName(RegNo: R)) + |
808 | "' is not permitted for this architecture" ); |
809 | return false; |
810 | } |
811 | return true; |
812 | } |
813 | |
814 | // Vd.tmp can't be accumulated |
815 | bool HexagonMCChecker::checkHVXAccum() |
816 | { |
817 | for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI: MCB)) { |
818 | bool IsTarget = |
819 | HexagonMCInstrInfo::isAccumulator(MCII, MCI: I) && I.getOperand(i: 0).isReg(); |
820 | if (!IsTarget) |
821 | continue; |
822 | unsigned int R = I.getOperand(i: 0).getReg(); |
823 | TmpDefsIterator It = TmpDefs.find(x: R); |
824 | if (It != TmpDefs.end()) { |
825 | reportError(Msg: "register `" + Twine(RI.getName(RegNo: R)) + ".tmp" + |
826 | "' is accumulated in this packet" ); |
827 | return false; |
828 | } |
829 | } |
830 | return true; |
831 | } |
832 | |