LLVM 24.0.0git
HexagonMCChecker.cpp
Go to the documentation of this file.
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
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"
28#include <cassert>
29
30using namespace llvm;
31
32static cl::opt<bool>
33 RelaxNVChecks("relax-nv-checks", cl::Hidden,
34 cl::desc("Relax checks of new-value validity"));
35
36const HexagonMCChecker::PredSense
37 HexagonMCChecker::Unconditional(Hexagon::NoRegister, false);
38
39void HexagonMCChecker::init() {
40 // Initialize read-only registers set.
41 ReadOnly.insert(Hexagon::PC);
42 ReadOnly.insert(Hexagon::C9_8);
43
44 // Figure out the loop-registers definitions.
46 Defs[Hexagon::SA0].insert(Unconditional); // FIXME: define or change SA0?
47 Defs[Hexagon::LC0].insert(Unconditional);
48 }
50 Defs[Hexagon::SA1].insert(Unconditional); // FIXME: define or change SA0?
51 Defs[Hexagon::LC1].insert(Unconditional);
52 }
53
55 // Unfurl a bundle.
56 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
57 MCInst const &Inst = *I.getInst();
58 if (HexagonMCInstrInfo::isDuplex(MCII, Inst)) {
59 init(*Inst.getOperand(0).getInst());
60 init(*Inst.getOperand(1).getInst());
61 } else
62 init(Inst);
63 }
64 else
65 init(MCB);
66}
67
68void HexagonMCChecker::initReg(MCInst const &MCI, MCRegister R,
69 MCRegister &PredReg, bool &isTrue) {
70 if (HexagonMCInstrInfo::isPredicated(MCII, MCI) &&
72 // Note an used predicate register.
73 PredReg = R;
74 isTrue = HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI);
75
76 // Note use of new predicate register.
78 NewPreds.insert(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(R).empty()); SRI.isValid();
83 ++SRI)
84 if (RI.subregs(*SRI).empty())
85 // Skip super-registers used indirectly.
86 Uses.insert(*SRI);
87
89 ReversePairs.insert(R);
90}
91
92void HexagonMCChecker::init(MCInst const &MCI) {
93 const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MCI);
94 MCRegister PredReg;
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, MCI.getOperand(i).getReg(), PredReg, isTrue);
101 for (MCPhysReg ImpUse : MCID.implicit_uses())
102 initReg(MCI, ImpUse, PredReg, isTrue);
103
104 const bool IgnoreTmpDst = (HexagonMCInstrInfo::hasTmpDst(MCII, MCI) ||
105 HexagonMCInstrInfo::isTmpWrite(MCII, MCI)) &&
106 STI.hasFeature(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(R);
126 else if (HexagonMCInstrInfo::isPredReg(RI, R) &&
128 // Include implicit late predicates.
129 LatePreds.insert(R);
130 else if (!IgnoreTmpDst)
131 Defs[R].insert(PredSense(PredReg, isTrue));
132 }
133
134 // Figure out explicit register definitions.
135 for (unsigned i = 0; i < MCID.getNumDefs(); ++i) {
136 MCRegister R = MCI.getOperand(i).getReg(), S = MCRegister();
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
144 ReversePairs.insert(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(R).empty()); SRI.isValid();
149 ++SRI) {
150 if (!RI.subregs(*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(*SRI);
169 else if (HexagonMCInstrInfo::isPredicateLate(MCII, MCI) &&
171 // Some insns produce predicates too late to be used in the same packet.
172 LatePreds.insert(*SRI);
173 else if (i == 0 && HexagonMCInstrInfo::getType(MCII, MCI) ==
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(*SRI);
181 else if (!IgnoreTmpDst)
182 Defs[*SRI].insert(PredSense(PredReg, isTrue));
183 }
184 }
185
186 // Figure out definitions of new predicate registers.
188 for (unsigned i = MCID.getNumDefs(); i < MCID.getNumOperands(); ++i)
189 if (MCI.getOperand(i).isReg()) {
190 MCRegister P = MCI.getOperand(i).getReg();
191
193 NewPreds.insert(P);
194 }
195}
196
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
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
213bool 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 chkHMX = checkValidHMX();
230 bool chkValidTmpDst = FullCheck ? checkValidTmpDst() : true;
231 bool chkLegalVecRegPair = checkLegalVecRegPair();
232 bool ChkHVXAccum = checkHVXAccum();
233 bool ChkHLX64BitRegUse = checkHLX64BitRegUse();
234 bool chk = chkP && chkNV && chkR && chkRRO && chkS && chkSh && chkSl &&
235 chkAXOK && chkCofMax1 && chkHWLoop && chkHMX && chkValidTmpDst &&
236 chkLegalVecRegPair && ChkHVXAccum && ChkHLX64BitRegUse;
237
238 return chk;
239}
240
241static bool isDuplexAGroup(unsigned Opcode) {
242 switch (Opcode) {
243 case Hexagon::SA1_addi:
244 case Hexagon::SA1_addrx:
245 case Hexagon::SA1_addsp:
246 case Hexagon::SA1_and1:
247 case Hexagon::SA1_clrf:
248 case Hexagon::SA1_clrfnew:
249 case Hexagon::SA1_clrt:
250 case Hexagon::SA1_clrtnew:
251 case Hexagon::SA1_cmpeqi:
252 case Hexagon::SA1_combine0i:
253 case Hexagon::SA1_combine1i:
254 case Hexagon::SA1_combine2i:
255 case Hexagon::SA1_combine3i:
256 case Hexagon::SA1_combinerz:
257 case Hexagon::SA1_combinezr:
258 case Hexagon::SA1_dec:
259 case Hexagon::SA1_inc:
260 case Hexagon::SA1_seti:
261 case Hexagon::SA1_setin1:
262 case Hexagon::SA1_sxtb:
263 case Hexagon::SA1_sxth:
264 case Hexagon::SA1_tfr:
265 case Hexagon::SA1_zxtb:
266 case Hexagon::SA1_zxth:
267 return true;
268 break;
269 default:
270 return false;
271 }
272}
273
274static bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) {
275 if (HexagonMCInstrInfo::isFloat(MCII, ID))
276 return true;
277 unsigned Type = HexagonMCInstrInfo::getType(MCII, ID);
278 switch (Type) {
285 case HexagonII::TypeM:
287 return false;
289 return !isDuplexAGroup(ID.getOpcode());
290 }
292 llvm_unreachable("unexpected duplex instruction");
293 default:
294 return true;
295 }
296}
297
298bool HexagonMCChecker::checkAXOK() {
299 MCInst const *HasSoloAXInst = nullptr;
300 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
301 if (HexagonMCInstrInfo::isSoloAX(MCII, I)) {
302 HasSoloAXInst = &I;
303 }
304 }
305 if (!HasSoloAXInst)
306 return true;
307 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
308 if (&I != HasSoloAXInst && isNeitherAnorX(MCII, I)) {
310 HasSoloAXInst->getLoc(),
311 Twine("Instruction can only be in a packet with ALU or non-FPU XTYPE "
312 "instructions"));
313 reportError(I.getLoc(),
314 Twine("Not an ALU or non-FPU XTYPE instruction"));
315 return false;
316 }
317 }
318 return true;
319}
320
322 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
324 reportNote(I.getLoc(), "Branching instruction");
325 }
326}
327
328bool HexagonMCChecker::checkHWLoop() {
331 return true;
332 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
333 if (HexagonMCInstrInfo::IsABranchingInst(MCII, STI, I)) {
334 reportError(MCB.getLoc(),
335 "Branches cannot be in a packet with hardware loops");
337 return false;
338 }
339 }
340 return true;
341}
342
343bool HexagonMCChecker::checkCOFMax1() {
344 SmallVector<MCInst const *, 2> BranchLocations;
345 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
347 BranchLocations.push_back(&I);
348 }
349 for (unsigned J = 0, N = BranchLocations.size(); J < N; ++J) {
350 MCInst const &I = *BranchLocations[J];
351 if (HexagonMCInstrInfo::isCofMax1(MCII, I)) {
352 bool Relax1 = HexagonMCInstrInfo::isCofRelax1(MCII, I);
353 bool Relax2 = HexagonMCInstrInfo::isCofRelax2(MCII, I);
354 if (N > 1 && !Relax1 && !Relax2) {
355 reportError(I.getLoc(),
356 "Instruction may not be in a packet with other branches");
358 return false;
359 }
360 if (N > 1 && J == 0 && !Relax1) {
361 reportError(I.getLoc(),
362 "Instruction may not be the first branch in packet");
364 return false;
365 }
366 if (N > 1 && J == 1 && !Relax2) {
367 reportError(I.getLoc(),
368 "Instruction may not be the second branch in packet");
370 return false;
371 }
372 }
373 }
374 return true;
375}
376
377bool HexagonMCChecker::checkSlots() {
378 if (HexagonMCInstrInfo::slotsConsumed(MCII, STI, MCB) >
380 reportError("invalid instruction packet: out of slots");
381 return false;
382 }
383 return true;
384}
385
386// Check legal use of predicate registers.
387bool HexagonMCChecker::checkPredicates() {
388 // Check for proper use of new predicate registers.
389 for (const auto &I : NewPreds) {
390 MCRegister P = I;
391
392 if (!Defs.count(P) || LatePreds.count(P) || Defs.count(Hexagon::P3_0)) {
393 // Error out if the new predicate register is not defined,
394 // or defined "late"
395 // (e.g., "{ if (p3.new)... ; p3 = sp1loop0(#r7:2, Rs) }").
397 return false;
398 }
399 }
400
401 // Check for proper use of auto-anded of predicate registers.
402 for (const auto &I : LatePreds) {
403 MCRegister P = I;
404
405 if (LatePreds.count(P) > 1 || Defs.count(P)) {
406 // Error out if predicate register defined "late" multiple times or
407 // defined late and regularly defined
408 // (e.g., "{ p3 = sp1loop0(...); p3 = cmp.eq(...) }".
410 return false;
411 }
412 }
413
414 return true;
415}
416
417// Check legal use of new values.
418bool HexagonMCChecker::checkNewValues() {
419 for (auto const &ConsumerInst :
421 if (!HexagonMCInstrInfo::isNewValue(MCII, ConsumerInst))
422 continue;
423
424 const HexagonMCInstrInfo::PredicateInfo ConsumerPredInfo =
425 HexagonMCInstrInfo::predicateInfo(MCII, ConsumerInst);
426
427 bool Branch = HexagonMCInstrInfo::getDesc(MCII, ConsumerInst).isBranch();
428 MCOperand const &Op =
429 HexagonMCInstrInfo::getNewValueOperand(MCII, ConsumerInst);
430 assert(Op.isReg());
431
432 auto Producer = registerProducer(Op.getReg(), ConsumerPredInfo);
433 const MCInst *const ProducerInst = std::get<0>(Producer);
434 const HexagonMCInstrInfo::PredicateInfo ProducerPredInfo =
435 std::get<2>(Producer);
436
437 if (ProducerInst == nullptr) {
438 reportError(ConsumerInst.getLoc(),
439 "New value register consumer has no producer");
440 return false;
441 }
442 if (!RelaxNVChecks) {
443 // Checks that statically prove correct new value consumption
444 if (ProducerPredInfo.isPredicated() &&
445 (!ConsumerPredInfo.isPredicated() ||
446 llvm::HexagonMCInstrInfo::getType(MCII, ConsumerInst) ==
449 ProducerInst->getLoc(),
450 "Register producer is predicated and consumer is unconditional");
451 reportError(ConsumerInst.getLoc(),
452 "Instruction does not have a valid new register producer");
453 return false;
454 }
455 if (ProducerPredInfo.Register != Hexagon::NoRegister &&
456 ProducerPredInfo.Register != ConsumerPredInfo.Register) {
457 reportNote(ProducerInst->getLoc(),
458 "Register producer does not use the same predicate "
459 "register as the consumer");
460 reportError(ConsumerInst.getLoc(),
461 "Instruction does not have a valid new register producer");
462 return false;
463 }
464 }
465 if (ProducerPredInfo.Register == ConsumerPredInfo.Register &&
466 ConsumerPredInfo.PredicatedTrue != ProducerPredInfo.PredicatedTrue) {
468 ProducerInst->getLoc(),
469 "Register producer has the opposite predicate sense as consumer");
470 reportError(ConsumerInst.getLoc(),
471 "Instruction does not have a valid new register producer");
472 return false;
473 }
474
475 MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, *ProducerInst);
476 const unsigned ProducerOpIndex = std::get<1>(Producer);
477
478 if (Desc.operands()[ProducerOpIndex].RegClass ==
479 Hexagon::DoubleRegsRegClassID) {
480 reportNote(ProducerInst->getLoc(),
481 "Double registers cannot be new-value producers");
482 reportError(ConsumerInst.getLoc(),
483 "Instruction does not have a valid new register producer");
484 return false;
485 }
486
487 // The ProducerOpIsMemIndex logic checks for the index of the producer
488 // register operand. Z-reg load instructions have an implicit operand
489 // that's not encoded, so the producer won't appear as the 1-th def, it
490 // will be at the 0-th.
491 const unsigned ProducerOpSearchIndex =
492 (HexagonMCInstrInfo::getType(MCII, *ProducerInst) ==
494 ? 0
495 : 1;
496
497 const bool ProducerOpIsMemIndex =
498 ((Desc.mayLoad() && ProducerOpIndex == ProducerOpSearchIndex) ||
499 (Desc.mayStore() && ProducerOpIndex == 0));
500
501 if (ProducerOpIsMemIndex) {
502 unsigned Mode = HexagonMCInstrInfo::getAddrMode(MCII, *ProducerInst);
503
504 StringRef ModeError;
506 ModeError = "Absolute-set";
508 ModeError = "Auto-increment";
509 if (!ModeError.empty()) {
510 reportNote(ProducerInst->getLoc(),
511 ModeError + " registers cannot be a new-value "
512 "producer");
513 reportError(ConsumerInst.getLoc(),
514 "Instruction does not have a valid new register producer");
515 return false;
516 }
517 }
518 if (Branch && HexagonMCInstrInfo::isFloat(MCII, *ProducerInst)) {
519 reportNote(ProducerInst->getLoc(),
520 "FPU instructions cannot be new-value producers for jumps");
521 reportError(ConsumerInst.getLoc(),
522 "Instruction does not have a valid new register producer");
523 return false;
524 }
525 }
526 return true;
527}
528
529bool HexagonMCChecker::checkRegistersReadOnly() {
530 for (auto I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
531 MCInst const &Inst = *I.getInst();
532 unsigned Defs = HexagonMCInstrInfo::getDesc(MCII, Inst).getNumDefs();
533 for (unsigned j = 0; j < Defs; ++j) {
534 MCOperand const &Operand = Inst.getOperand(j);
535 assert(Operand.isReg() && "Def is not a register");
536 MCRegister Register = Operand.getReg();
537 if (ReadOnly.find(Register) != ReadOnly.end()) {
538 reportError(Inst.getLoc(), "Cannot write to read-only register `" +
539 Twine(RI.getName(Register)) + "'");
540 return false;
541 }
542 }
543 }
544 return true;
545}
546
547bool HexagonMCChecker::registerUsed(MCRegister Register) {
548 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB))
549 for (unsigned j = HexagonMCInstrInfo::getDesc(MCII, I).getNumDefs(),
550 n = I.getNumOperands();
551 j < n; ++j) {
552 MCOperand const &Operand = I.getOperand(j);
553 if (Operand.isReg() && Operand.getReg() == Register)
554 return true;
555 }
556 return false;
557}
558
559std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
560HexagonMCChecker::registerProducer(
562 std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
563 WrongSense;
564
565 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
566 MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, I);
567 auto ProducerPredicate = HexagonMCInstrInfo::predicateInfo(MCII, I);
568
569 for (unsigned J = 0, N = Desc.getNumDefs(); J < N; ++J)
570 for (auto K = MCRegAliasIterator(I.getOperand(J).getReg(), &RI, true);
571 K.isValid(); ++K)
572 if (*K == Register) {
573 if (RelaxNVChecks ||
574 (ProducerPredicate.Register == ConsumerPredicate.Register &&
575 (ProducerPredicate.Register == Hexagon::NoRegister ||
576 ProducerPredicate.PredicatedTrue ==
577 ConsumerPredicate.PredicatedTrue)))
578 return std::make_tuple(&I, J, ProducerPredicate);
579 std::get<0>(WrongSense) = &I;
580 std::get<1>(WrongSense) = J;
581 std::get<2>(WrongSense) = ProducerPredicate;
582 }
583 if (Register == Hexagon::VTMP && HexagonMCInstrInfo::hasTmpDst(MCII, I))
584 return std::make_tuple(&I, 0, HexagonMCInstrInfo::PredicateInfo());
585 }
586 return WrongSense;
587}
588
589void HexagonMCChecker::checkRegisterCurDefs() {
590 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
591 if (HexagonMCInstrInfo::isCVINew(MCII, I) &&
592 HexagonMCInstrInfo::getDesc(MCII, I).mayLoad()) {
593 const MCRegister RegDef = I.getOperand(0).getReg();
594
595 bool HasRegDefUse = false;
596 for (MCRegAliasIterator Alias(RegDef, &RI, true); Alias.isValid();
597 ++Alias)
598 HasRegDefUse = HasRegDefUse || registerUsed(*Alias);
599
600 if (!HasRegDefUse)
601 reportWarning("Register `" + Twine(RI.getName(RegDef)) +
602 "' used with `.cur' "
603 "but not used in the same packet");
604 }
605 }
606}
607
608// Check for legal register uses and definitions.
609bool HexagonMCChecker::checkRegisters() {
610 // Check for proper register definitions.
611 for (const auto &I : Defs) {
612 MCRegister R = I.first;
613
614 if (isLoopRegister(R) && Defs.count(R) > 1 &&
617 // Error out for definitions of loop registers at the end of a loop.
618 reportError("loop-setup and some branch instructions "
619 "cannot be in the same packet");
620 return false;
621 }
622 if (SoftDefs.count(R)) {
623 // Error out for explicit changes to registers also weakly defined
624 // (e.g., "{ usr = r0; r0 = sfadd(...) }").
625 MCRegister UsrR = Hexagon::USR;
626 MCRegister BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;
628 return false;
629 }
630 if (!HexagonMCInstrInfo::isPredReg(RI, R) && Defs[R].size() > 1) {
631 // Check for multiple register definitions.
632 PredSet &PM = Defs[R];
633
634 // Check for multiple unconditional register definitions.
635 if (PM.count(Unconditional)) {
636 // Error out on an unconditional change when there are any other
637 // changes, conditional or not.
638 MCRegister UsrR = Hexagon::USR;
639 MCRegister BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;
641 return false;
642 }
643 // Check for multiple conditional register definitions.
644 for (const auto &J : PM) {
645 PredSense P = J;
646
647 // Check for multiple uses of the same condition.
648 if (PM.count(P) > 1) {
649 // Error out on conditional changes based on the same predicate
650 // (e.g., "{ if (!p0) r0 =...; if (!p0) r0 =... }").
652 return false;
653 }
654 // Check for the use of the complementary condition.
655 P.second = !P.second;
656 if (PM.count(P) && PM.size() > 2) {
657 // Error out on conditional changes based on the same predicate
658 // multiple times
659 // (e.g., "if (p0) r0 =...; if (!p0) r0 =... }; if (!p0) r0 =...").
661 return false;
662 }
663 }
664 }
665 }
666
667 // Check for use of temporary definitions.
668 for (const auto &I : TmpDefs) {
669 MCRegister R = I;
670
671 if (!Uses.count(R)) {
672 // special case for vhist
673 bool vHistFound = false;
674 for (auto const &HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) {
675 if (HexagonMCInstrInfo::getType(MCII, *HMI.getInst()) ==
677 vHistFound = true; // vhist() implicitly uses ALL REGxx.tmp
678 break;
679 }
680 }
681 // Warn on an unused temporary definition.
682 if (!vHistFound) {
683 reportWarning("register `" + Twine(RI.getName(R)) +
684 "' used with `.tmp' but not used in the same packet");
685 return true;
686 }
687 }
688 }
689
690 return true;
691}
692
693bool HexagonMCChecker::checkValidHMX() {
694 bool hasWeight = false;
695 bool hasActivation = false;
696 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
697 hasWeight = hasWeight || (HexagonMCInstrInfo::isHMXWeight(MCII, I));
698 hasActivation =
699 hasActivation || (HexagonMCInstrInfo::isHMXActivation(MCII, I));
700 }
701
702 // To be valid they must both be present or neither:
703 const bool ValidWeightActPairing = hasWeight == hasActivation;
704 if (!ValidWeightActPairing) {
705 const std::string ErrMsg = hasWeight ? "weight without an activation"
706 : "activation without a weight";
707 reportError(MCB.getLoc(), Twine("packet has HMX ") + ErrMsg);
708
710 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
712 reportNote(I.getLoc(), "this is an HMX weight instruction");
714 reportNote(I.getLoc(), "this is an HMX activation instruction");
715 else
716 reportNote(I.getLoc(),
717 "this is neither an HMX weight nor activation");
718 }
719 }
720 return ValidWeightActPairing;
721}
722
723// Check for legal use of solo insns.
724bool HexagonMCChecker::checkSolo() {
726 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
727 if (HexagonMCInstrInfo::isSolo(MCII, I)) {
728 reportError(I.getLoc(), "Instruction is marked `isSolo' and "
729 "cannot have other instructions in "
730 "the same packet");
731 return false;
732 }
733 }
734
735 return true;
736}
737
738bool HexagonMCChecker::checkShuffle() {
739 HexagonMCShuffler MCSDX(Context, ReportErrors, MCII, STI, MCB);
740 return MCSDX.check();
741}
742
743bool HexagonMCChecker::checkValidTmpDst() {
744 if (!STI.hasFeature(Hexagon::ArchV69)) {
745 return true;
746 }
747 auto HasTmp = [&](MCInst const &I) {
748 return HexagonMCInstrInfo::hasTmpDst(MCII, I) ||
751 };
752 unsigned HasTmpCount =
754
755 if (HasTmpCount > 1) {
757 MCB.getLoc(),
758 "this packet has more than one HVX vtmp/.tmp destination instruction");
759
760 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB))
761 if (HasTmp(I))
762 reportNote(I.getLoc(),
763 "this is an HVX vtmp/.tmp destination instruction");
764
765 return false;
766 }
767 return true;
768}
769
770void HexagonMCChecker::compoundRegisterMap(unsigned &Register) {
771 switch (Register) {
772 default:
773 break;
774 case Hexagon::R15:
775 Register = Hexagon::R23;
776 break;
777 case Hexagon::R14:
778 Register = Hexagon::R22;
779 break;
780 case Hexagon::R13:
781 Register = Hexagon::R21;
782 break;
783 case Hexagon::R12:
784 Register = Hexagon::R20;
785 break;
786 case Hexagon::R11:
787 Register = Hexagon::R19;
788 break;
789 case Hexagon::R10:
790 Register = Hexagon::R18;
791 break;
792 case Hexagon::R9:
793 Register = Hexagon::R17;
794 break;
795 case Hexagon::R8:
796 Register = Hexagon::R16;
797 break;
798 }
799}
800
802 reportError("register `" + Twine(RI.getName(Register)) +
803 "' modified more than once");
804}
805
807 reportError("register `" + Twine(RI.getName(Register)) +
808 "' used with `.new' "
809 "but not validly modified in the same packet");
810}
811
813 reportError(MCB.getLoc(), Msg);
814}
815
817 if (ReportErrors)
818 Context.reportError(Loc, Msg);
819}
820
822 if (ReportErrors) {
823 auto SM = Context.getSourceManager();
824 if (SM)
825 SM->PrintMessage(Loc, SourceMgr::DK_Note, Msg);
826 }
827}
828
830 if (ReportErrors)
831 Context.reportWarning(MCB.getLoc(), Msg);
832}
833
834bool HexagonMCChecker::checkLegalVecRegPair() {
835 const bool IsPermitted = STI.hasFeature(Hexagon::ArchV67);
836 const bool HasReversePairs = ReversePairs.size() != 0;
837
838 if (!IsPermitted && HasReversePairs) {
839 for (auto R : ReversePairs)
840 reportError("register pair `" + Twine(RI.getName(R)) +
841 "' is not permitted for this architecture");
842 return false;
843 }
844 return true;
845}
846
847// Vd.tmp can't be accumulated
848bool HexagonMCChecker::checkHVXAccum()
849{
850 for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
851 bool IsTarget =
852 HexagonMCInstrInfo::isAccumulator(MCII, I) && I.getOperand(0).isReg();
853 if (!IsTarget)
854 continue;
855 MCRegister R = I.getOperand(0).getReg();
856 TmpDefsIterator It = TmpDefs.find(R);
857 if (It != TmpDefs.end()) {
858 reportError("register `" + Twine(RI.getName(R)) + ".tmp" +
859 "' is accumulated in this packet");
860 return false;
861 }
862 }
863 return true;
864}
865
866bool HexagonMCChecker::checkHLX64BitRegUse() {
867 const MCRegisterClass &DoubleRegs =
868 RI.getRegClass(Hexagon::DoubleRegsRegClassID);
869 const MCRegisterClass &IntRegs = RI.getRegClass(Hexagon::IntRegsRegClassID);
870 const MCInst *DoubleInst = nullptr;
871 unsigned NumScalarArg = 0;
872 for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
873 if (!HexagonMCInstrInfo::isHLX(MCII, I))
874 continue;
875 const MCInstrDesc &Desc = HexagonMCInstrInfo::getDesc(MCII, I);
876 if (Desc.mayLoad() || Desc.mayStore())
877 continue;
878 bool UsesScalarArg = false;
879 for (const auto &Op : I) {
880 if (!DoubleInst && Op.isReg() && DoubleRegs.contains(Op.getReg()))
881 DoubleInst = &I;
882 if (Op.isImm() || Op.isExpr() ||
883 (Op.isReg() &&
884 (IntRegs.contains(Op.getReg()) || DoubleRegs.contains(Op.getReg()))))
885 UsesScalarArg = true;
886 }
887 if (UsesScalarArg)
888 ++NumScalarArg;
889 }
890
891 if (DoubleInst && NumScalarArg > 1) {
892 reportError(DoubleInst->getLoc(),
893 "HLX instruction using a 64-bit scalar register cannot be "
894 "in the same packet with another HLX instruction using a "
895 "scalar register or immediate");
896 return false;
897 }
898 return true;
899}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > RelaxNVChecks("relax-nv-checks", cl::Hidden, cl::desc("Relax checks of new-value validity"))
static bool isDuplexAGroup(unsigned Opcode)
static bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID)
#define I(x, y, z)
Definition MD5.cpp:57
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
const char * Msg
static const MCPhysReg DoubleRegs[32]
static const MCPhysReg IntRegs[32]
void reportErrorNewValue(MCRegister Register)
HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst &mcb, const MCRegisterInfo &ri, bool ReportErrors=true)
bool check(bool FullCheck=true)
void reportWarning(Twine const &Msg)
void reportNote(SMLoc Loc, Twine const &Msg)
void reportErrorRegisters(MCRegister Register)
void reportError(SMLoc Loc, Twine const &Msg)
Context object for machine code objects.
Definition MCContext.h:83
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
SMLoc getLoc() const
Definition MCInst.h:208
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
bool isBranch() const
Returns true if this is a conditional, unconditional, or indirect branch.
ArrayRef< MCPhysReg > implicit_defs() const
Return a list of registers that are potentially written by any instance of this machine instruction.
bool isCall() const
Return true if the instruction is a call.
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCInst * getInst() const
Definition MCInst.h:128
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
const char * getName(MCRegister RegNo) const
Return the human-readable symbolic target-specific name for the specified physical register.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Represents a location in source code.
Definition SMLoc.h:22
void push_back(const T &Elt)
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isTmpWrite(MCInstrInfo const &MCII, MCInst const &MCI)
bool isHMXWeight(MCInstrInfo const &MCII, MCInst const &MCI)
bool isSolo(MCInstrInfo const &MCII, MCInst const &MCI)
Return whether the insn is solo, i.e., cannot be in a packet.
bool isPredicatedNew(MCInstrInfo const &MCII, MCInst const &MCI)
Return whether the insn is newly predicated.
bool IsReverseVecRegPair(MCRegister VecReg)
bool isOuterLoop(MCInst const &MCI)
unsigned getAddrMode(MCInstrInfo const &MCII, MCInst const &MCI)
size_t bundleSize(MCInst const &MCI)
bool IsABranchingInst(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst const &I)
bool isDuplex(MCInstrInfo const &MCII, MCInst const &MCI)
bool isPredicateLate(MCInstrInfo const &MCII, MCInst const &MCI)
bool isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI)
Return whether the insn can be packaged only with A and X-type insns.
bool isNewValue(MCInstrInfo const &MCII, MCInst const &MCI)
Return whether the insn expects newly produced value.
bool isHVX(MCInstrInfo const &MCII, MCInst const &MCI)
bool isHLX(MCInstrInfo const &MCII, MCInst const &MCI)
MCInstrDesc const & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)
iterator_range< Hexagon::PacketIterator > bundleInstructions(MCInstrInfo const &MCII, MCInst const &MCI)
bool isBundle(MCInst const &MCI)
bool isCofRelax1(MCInstrInfo const &MCII, MCInst const &MCI)
unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI)
Return the Hexagon ISA class for the insn.
MCOperand const & getNewValueOperand(MCInstrInfo const &MCII, MCInst const &MCI)
bool isPredicated(MCInstrInfo const &MCII, MCInst const &MCI)
bool isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI)
bool isInnerLoop(MCInst const &MCI)
PredicateInfo predicateInfo(MCInstrInfo const &MCII, MCInst const &MCI)
unsigned slotsConsumed(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst const &MCI)
bool hasTmpDst(MCInstrInfo const &MCII, MCInst const &MCI)
unsigned packetSizeSlots(MCSubtargetInfo const &STI)
bool isPredReg(MCRegisterInfo const &MRI, MCRegister Reg)
bool isPredicatedTrue(MCInstrInfo const &MCII, MCInst const &MCI)
bool isAccumulator(MCInstrInfo const &MCII, MCInst const &MCI)
Return where the instruction is an accumulator.
bool isHMXActivation(MCInstrInfo const &MCII, MCInst const &MCI)
bool isCVINew(MCInstrInfo const &MCII, MCInst const &MCI)
bool isFloat(MCInstrInfo const &MCII, MCInst const &MCI)
Return whether it is a floating-point insn.
bool isCofRelax2(MCInstrInfo const &MCII, MCInst const &MCI)
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
Op::Description Desc
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Other
Any other memory.
Definition ModRef.h:68
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
DWARFExpression::Operation Op
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
Definition STLExtras.h:2035
#define N