Thanks to visit codestin.com
Credit goes to llvm.org

LLVM 22.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::hasHvxTmp(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 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
239static 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
272static bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) {
274 return true;
275 unsigned Type = HexagonMCInstrInfo::getType(MCII, ID);
276 switch (Type) {
283 case HexagonII::TypeM:
285 return false;
287 return !isDuplexAGroup(ID.getOpcode());
288 }
290 llvm_unreachable("unexpected duplex instruction");
291 default:
292 return true;
293 }
294}
295
296bool HexagonMCChecker::checkAXOK() {
297 MCInst const *HasSoloAXInst = nullptr;
298 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
299 if (HexagonMCInstrInfo::isSoloAX(MCII, I)) {
300 HasSoloAXInst = &I;
301 }
302 }
303 if (!HasSoloAXInst)
304 return true;
305 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
306 if (&I != HasSoloAXInst && isNeitherAnorX(MCII, I)) {
308 HasSoloAXInst->getLoc(),
309 Twine("Instruction can only be in a packet with ALU or non-FPU XTYPE "
310 "instructions"));
311 reportError(I.getLoc(),
312 Twine("Not an ALU or non-FPU XTYPE instruction"));
313 return false;
314 }
315 }
316 return true;
317}
318
320 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
322 reportNote(I.getLoc(), "Branching instruction");
323 }
324}
325
326bool HexagonMCChecker::checkHWLoop() {
329 return true;
330 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
331 if (HexagonMCInstrInfo::IsABranchingInst(MCII, STI, I)) {
332 reportError(MCB.getLoc(),
333 "Branches cannot be in a packet with hardware loops");
335 return false;
336 }
337 }
338 return true;
339}
340
341bool HexagonMCChecker::checkCOFMax1() {
342 SmallVector<MCInst const *, 2> BranchLocations;
343 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
345 BranchLocations.push_back(&I);
346 }
347 for (unsigned J = 0, N = BranchLocations.size(); J < N; ++J) {
348 MCInst const &I = *BranchLocations[J];
349 if (HexagonMCInstrInfo::isCofMax1(MCII, I)) {
350 bool Relax1 = HexagonMCInstrInfo::isCofRelax1(MCII, I);
351 bool Relax2 = HexagonMCInstrInfo::isCofRelax2(MCII, I);
352 if (N > 1 && !Relax1 && !Relax2) {
353 reportError(I.getLoc(),
354 "Instruction may not be in a packet with other branches");
356 return false;
357 }
358 if (N > 1 && J == 0 && !Relax1) {
359 reportError(I.getLoc(),
360 "Instruction may not be the first branch in packet");
362 return false;
363 }
364 if (N > 1 && J == 1 && !Relax2) {
365 reportError(I.getLoc(),
366 "Instruction may not be the second branch in packet");
368 return false;
369 }
370 }
371 }
372 return true;
373}
374
375bool HexagonMCChecker::checkSlots() {
376 if (HexagonMCInstrInfo::slotsConsumed(MCII, STI, MCB) >
378 reportError("invalid instruction packet: out of slots");
379 return false;
380 }
381 return true;
382}
383
384// Check legal use of predicate registers.
385bool 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(P) || LatePreds.count(P) || Defs.count(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) }").
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(P) > 1 || Defs.count(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(...) }".
408 return false;
409 }
410 }
411
412 return true;
413}
414
415// Check legal use of new values.
416bool HexagonMCChecker::checkNewValues() {
417 for (auto const &ConsumerInst :
419 if (!HexagonMCInstrInfo::isNewValue(MCII, ConsumerInst))
420 continue;
421
422 const HexagonMCInstrInfo::PredicateInfo ConsumerPredInfo =
423 HexagonMCInstrInfo::predicateInfo(MCII, ConsumerInst);
424
425 bool Branch = HexagonMCInstrInfo::getDesc(MCII, ConsumerInst).isBranch();
426 MCOperand const &Op =
427 HexagonMCInstrInfo::getNewValueOperand(MCII, ConsumerInst);
428 assert(Op.isReg());
429
430 auto Producer = registerProducer(Op.getReg(), ConsumerPredInfo);
431 const MCInst *const ProducerInst = std::get<0>(Producer);
432 const HexagonMCInstrInfo::PredicateInfo ProducerPredInfo =
433 std::get<2>(Producer);
434
435 if (ProducerInst == nullptr) {
436 reportError(ConsumerInst.getLoc(),
437 "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, ConsumerInst) ==
447 ProducerInst->getLoc(),
448 "Register producer is predicated and consumer is unconditional");
449 reportError(ConsumerInst.getLoc(),
450 "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(ProducerInst->getLoc(),
456 "Register producer does not use the same predicate "
457 "register as the consumer");
458 reportError(ConsumerInst.getLoc(),
459 "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) {
466 ProducerInst->getLoc(),
467 "Register producer has the opposite predicate sense as consumer");
468 reportError(ConsumerInst.getLoc(),
469 "Instruction does not have a valid new register producer");
470 return false;
471 }
472
473 MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, *ProducerInst);
474 const unsigned ProducerOpIndex = std::get<1>(Producer);
475
476 if (Desc.operands()[ProducerOpIndex].RegClass ==
477 Hexagon::DoubleRegsRegClassID) {
478 reportNote(ProducerInst->getLoc(),
479 "Double registers cannot be new-value producers");
480 reportError(ConsumerInst.getLoc(),
481 "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, *ProducerInst) ==
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, *ProducerInst);
501
502 StringRef ModeError;
504 ModeError = "Absolute-set";
506 ModeError = "Auto-increment";
507 if (!ModeError.empty()) {
508 reportNote(ProducerInst->getLoc(),
509 ModeError + " registers cannot be a new-value "
510 "producer");
511 reportError(ConsumerInst.getLoc(),
512 "Instruction does not have a valid new register producer");
513 return false;
514 }
515 }
516 if (Branch && HexagonMCInstrInfo::isFloat(MCII, *ProducerInst)) {
517 reportNote(ProducerInst->getLoc(),
518 "FPU instructions cannot be new-value producers for jumps");
519 reportError(ConsumerInst.getLoc(),
520 "Instruction does not have a valid new register producer");
521 return false;
522 }
523 }
524 return true;
525}
526
527bool HexagonMCChecker::checkRegistersReadOnly() {
528 for (auto I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
529 MCInst const &Inst = *I.getInst();
530 unsigned Defs = HexagonMCInstrInfo::getDesc(MCII, Inst).getNumDefs();
531 for (unsigned j = 0; j < Defs; ++j) {
532 MCOperand const &Operand = Inst.getOperand(j);
533 assert(Operand.isReg() && "Def is not a register");
534 MCRegister Register = Operand.getReg();
535 if (ReadOnly.find(Register) != ReadOnly.end()) {
536 reportError(Inst.getLoc(), "Cannot write to read-only register `" +
537 Twine(RI.getName(Register)) + "'");
538 return false;
539 }
540 }
541 }
542 return true;
543}
544
545bool HexagonMCChecker::registerUsed(MCRegister Register) {
546 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB))
547 for (unsigned j = HexagonMCInstrInfo::getDesc(MCII, I).getNumDefs(),
548 n = I.getNumOperands();
549 j < n; ++j) {
550 MCOperand const &Operand = I.getOperand(j);
551 if (Operand.isReg() && Operand.getReg() == Register)
552 return true;
553 }
554 return false;
555}
556
557std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
558HexagonMCChecker::registerProducer(
560 std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
561 WrongSense;
562
563 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
564 MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, I);
565 auto ProducerPredicate = HexagonMCInstrInfo::predicateInfo(MCII, I);
566
567 for (unsigned J = 0, N = Desc.getNumDefs(); J < N; ++J)
568 for (auto K = MCRegAliasIterator(I.getOperand(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(&I, J, ProducerPredicate);
577 std::get<0>(WrongSense) = &I;
578 std::get<1>(WrongSense) = J;
579 std::get<2>(WrongSense) = ProducerPredicate;
580 }
581 if (Register == Hexagon::VTMP && HexagonMCInstrInfo::hasTmpDst(MCII, I))
582 return std::make_tuple(&I, 0, HexagonMCInstrInfo::PredicateInfo());
583 }
584 return WrongSense;
585}
586
587void HexagonMCChecker::checkRegisterCurDefs() {
588 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
589 if (HexagonMCInstrInfo::isCVINew(MCII, I) &&
590 HexagonMCInstrInfo::getDesc(MCII, I).mayLoad()) {
591 const MCRegister RegDef = I.getOperand(0).getReg();
592
593 bool HasRegDefUse = false;
594 for (MCRegAliasIterator Alias(RegDef, &RI, true); Alias.isValid();
595 ++Alias)
596 HasRegDefUse = HasRegDefUse || registerUsed(*Alias);
597
598 if (!HasRegDefUse)
599 reportWarning("Register `" + Twine(RI.getName(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.
607bool 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(R) > 1 &&
615 // Error out for definitions of loop registers at the end of a loop.
616 reportError("loop-setup and some branch instructions "
617 "cannot be in the same packet");
618 return false;
619 }
620 if (SoftDefs.count(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(Hexagon::USR, R) ? UsrR : R;
626 return false;
627 }
628 if (!HexagonMCInstrInfo::isPredReg(RI, 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(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(Hexagon::USR, R) ? UsrR : R;
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(P) > 1) {
647 // Error out on conditional changes based on the same predicate
648 // (e.g., "{ if (!p0) r0 =...; if (!p0) r0 =... }").
650 return false;
651 }
652 // Check for the use of the complementary condition.
653 P.second = !P.second;
654 if (PM.count(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 =...").
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(R)) {
670 // special case for vhist
671 bool vHistFound = false;
672 for (auto const &HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) {
673 if (HexagonMCInstrInfo::getType(MCII, *HMI.getInst()) ==
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("register `" + Twine(RI.getName(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.
692bool HexagonMCChecker::checkSolo() {
694 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
695 if (HexagonMCInstrInfo::isSolo(MCII, I)) {
696 reportError(I.getLoc(), "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
706bool HexagonMCChecker::checkShuffle() {
707 HexagonMCShuffler MCSDX(Context, ReportErrors, MCII, STI, MCB);
708 return MCSDX.check();
709}
710
711bool HexagonMCChecker::checkValidTmpDst() {
712 if (!STI.hasFeature(Hexagon::ArchV69)) {
713 return true;
714 }
715 auto HasTmp = [&](MCInst const &I) {
716 return HexagonMCInstrInfo::hasTmpDst(MCII, I) ||
718 };
719 unsigned HasTmpCount =
721
722 if (HasTmpCount > 1) {
724 MCB.getLoc(),
725 "this packet has more than one HVX vtmp/.tmp destination instruction");
726
727 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB))
728 if (HasTmp(I))
729 reportNote(I.getLoc(),
730 "this is an HVX vtmp/.tmp destination instruction");
731
732 return false;
733 }
734 return true;
735}
736
737void 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
769 reportError("register `" + Twine(RI.getName(Register)) +
770 "' modified more than once");
771}
772
774 reportError("register `" + Twine(RI.getName(Register)) +
775 "' used with `.new' "
776 "but not validly modified in the same packet");
777}
778
780 reportError(MCB.getLoc(), Msg);
781}
782
784 if (ReportErrors)
785 Context.reportError(Loc, Msg);
786}
787
789 if (ReportErrors) {
790 auto SM = Context.getSourceManager();
791 if (SM)
792 SM->PrintMessage(Loc, SourceMgr::DK_Note, Msg);
793 }
794}
795
797 if (ReportErrors)
798 Context.reportWarning(MCB.getLoc(), Msg);
799}
800
801bool HexagonMCChecker::checkLegalVecRegPair() {
802 const bool IsPermitted = STI.hasFeature(Hexagon::ArchV67);
803 const bool HasReversePairs = ReversePairs.size() != 0;
804
805 if (!IsPermitted && HasReversePairs) {
806 for (auto R : ReversePairs)
807 reportError("register pair `" + Twine(RI.getName(R)) +
808 "' is not permitted for this architecture");
809 return false;
810 }
811 return true;
812}
813
814// Vd.tmp can't be accumulated
815bool HexagonMCChecker::checkHVXAccum()
816{
817 for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
818 bool IsTarget =
819 HexagonMCInstrInfo::isAccumulator(MCII, I) && I.getOperand(0).isReg();
820 if (!IsTarget)
821 continue;
822 MCRegister R = I.getOperand(0).getReg();
823 TmpDefsIterator It = TmpDefs.find(R);
824 if (It != TmpDefs.end()) {
825 reportError("register `" + Twine(RI.getName(R)) + ".tmp" +
826 "' is accumulated in this packet");
827 return false;
828 }
829 }
830 return true;
831}
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:58
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")))
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:214
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(unsigned Register)
void reportErrorNewValue(unsigned 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:33
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
Wrapper class representing virtual and physical registers.
Definition Register.h:19
Represents a location in source code.
Definition SMLoc.h:23
void push_back(const T &Elt)
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:143
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:45
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
bool hasHvxTmp(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.
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 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:1657
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:1941
#define N