LLVM: lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
19
28#include
29
30using namespace llvm;
31
34 cl::desc("Relax checks of new-value validity"));
35
36const HexagonMCChecker::PredSense
37 HexagonMCChecker::Unconditional(Hexagon::NoRegister, false);
38
39void HexagonMCChecker::init() {
40
41 ReadOnly.insert(Hexagon::PC);
42 ReadOnly.insert(Hexagon::C9_8);
43
44
46 Defs[Hexagon::SA0].insert(Unconditional);
47 Defs[Hexagon::LC0].insert(Unconditional);
48 }
50 Defs[Hexagon::SA1].insert(Unconditional);
51 Defs[Hexagon::LC1].insert(Unconditional);
52 }
53
55
57 MCInst const &Inst = *I.getInst();
61 } else
62 init(Inst);
63 }
64 else
65 init(MCB);
66}
67
68void HexagonMCChecker::initReg(MCInst const &MCI, MCRegister R,
72
73 PredReg = R;
75
76
78 NewPreds.insert(PredReg);
79 } else
80
81
82 for (MCRegAliasIterator SRI(R, &RI, RI.subregs(R).empty()); SRI.isValid();
83 ++SRI)
84 if (RI.subregs(*SRI).empty())
85
86 Uses.insert(*SRI);
87
89 ReversePairs.insert(R);
90}
91
92void HexagonMCChecker::init(MCInst const &MCI) {
94 MCRegister PredReg;
95 bool isTrue = false;
96
97
102 initReg(MCI, ImpUse, PredReg, isTrue);
103
106 STI.hasFeature(Hexagon::ArchV69);
107
108
110 if (Hexagon::R31 != R && MCID.isCall())
111
112
113 continue;
114 if (Hexagon::PC == R)
115
116
117 continue;
118
119 if (Hexagon::USR_OVF == R)
120
121
122
123
124
125 SoftDefs.insert(R);
128
129 LatePreds.insert(R);
130 else if (!IgnoreTmpDst)
131 Defs[R].insert(PredSense(PredReg, isTrue));
132 }
133
134
135 for (unsigned i = 0; i < MCID.getNumDefs(); ++i) {
137
138
139
140 if (R == Hexagon::C8)
141 R = Hexagon::USR;
142
144 ReversePairs.insert(R);
145
146
147
148 for (MCRegAliasIterator SRI(R, &RI, RI.subregs(R).empty()); SRI.isValid();
149 ++SRI) {
150 if (!RI.subregs(*SRI).empty())
151
152 continue;
153
154 if (R == *SRI) {
155 if (S == R)
156
157 continue;
158 else
159
160 S = R;
161 }
162
163 if (Hexagon::P3_0 != R && Hexagon::P3_0 == *SRI)
164
165
166
167
168 SoftDefs.insert(*SRI);
171
172 LatePreds.insert(*SRI);
175
176
177
178
179
180 TmpDefs.insert(*SRI);
181 else if (!IgnoreTmpDst)
182 Defs[*SRI].insert(PredSense(PredReg, isTrue));
183 }
184 }
185
186
191
193 NewPreds.insert(P);
194 }
195}
196
200 : Context(Context), MCB(mcb), RI(ri), MCII(MCII), STI(STI),
201 ReportErrors(ReportErrors) {
202 init();
203}
204
207 bool CopyReportErrors)
209 STI(STI), ReportErrors(CopyReportErrors ? Other.ReportErrors : false) {
210 init();
211}
212
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
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
274 return true;
276 switch (Type) {
285 return false;
288 }
291 default:
292 return true;
293 }
294}
295
296bool HexagonMCChecker::checkAXOK() {
297 MCInst const *HasSoloAXInst = nullptr;
300 HasSoloAXInst = &I;
301 }
302 }
303 if (!HasSoloAXInst)
304 return true;
308 HasSoloAXInst->getLoc(),
309 Twine("Instruction can only be in a packet with ALU or non-FPU XTYPE "
310 "instructions"));
312 Twine("Not an ALU or non-FPU XTYPE instruction"));
313 return false;
314 }
315 }
316 return true;
317}
318
322 reportNote(I.getLoc(), "Branching instruction");
323 }
324}
325
326bool HexagonMCChecker::checkHWLoop() {
329 return true;
333 "Branches cannot be in a packet with hardware loops");
335 return false;
336 }
337 }
338 return true;
339}
340
341bool HexagonMCChecker::checkCOFMax1() {
346 }
347 for (unsigned J = 0, N = BranchLocations.size(); J < N; ++J) {
348 MCInst const &I = *BranchLocations[J];
352 if (N > 1 && !Relax1 && !Relax2) {
354 "Instruction may not be in a packet with other branches");
356 return false;
357 }
358 if (N > 1 && J == 0 && !Relax1) {
360 "Instruction may not be the first branch in packet");
362 return false;
363 }
364 if (N > 1 && J == 1 && !Relax2) {
366 "Instruction may not be the second branch in packet");
368 return false;
369 }
370 }
371 }
372 return true;
373}
374
375bool HexagonMCChecker::checkSlots() {
378 reportError("invalid instruction packet: out of slots");
379 return false;
380 }
381 return true;
382}
383
384
385bool HexagonMCChecker::checkPredicates() {
386
387 for (const auto &I : NewPreds) {
389
390 if (!Defs.count(P) || LatePreds.count(P) || Defs.count(Hexagon::P3_0)) {
391
392
393
395 return false;
396 }
397 }
398
399
400 for (const auto &I : LatePreds) {
402
403 if (LatePreds.count(P) > 1 || Defs.count(P)) {
404
405
406
408 return false;
409 }
410 }
411
412 return true;
413}
414
415
416bool HexagonMCChecker::checkNewValues() {
417 for (auto const &ConsumerInst :
420 continue;
421
422 const HexagonMCInstrInfo::PredicateInfo ConsumerPredInfo =
424
426 MCOperand const &Op =
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) {
437 "New value register consumer has no producer");
438 return false;
439 }
441
447 ProducerInst->getLoc(),
448 "Register producer is predicated and consumer is unconditional");
450 "Instruction does not have a valid new register producer");
451 return false;
452 }
453 if (ProducerPredInfo.Register != Hexagon::NoRegister &&
456 "Register producer does not use the same predicate "
457 "register as the consumer");
459 "Instruction does not have a valid new register producer");
460 return false;
461 }
462 }
463 if (ProducerPredInfo.Register == ConsumerPredInfo.Register &&
466 ProducerInst->getLoc(),
467 "Register producer has the opposite predicate sense as consumer");
469 "Instruction does not have a valid new register producer");
470 return false;
471 }
472
474 const unsigned ProducerOpIndex = std::get<1>(Producer);
475
476 if (Desc.operands()[ProducerOpIndex].RegClass ==
477 Hexagon::DoubleRegsRegClassID) {
479 "Double registers cannot be new-value producers");
481 "Instruction does not have a valid new register producer");
482 return false;
483 }
484
485
486
487
488
489 const unsigned ProducerOpSearchIndex =
492 ? 0
493 : 1;
494
495 const bool ProducerOpIsMemIndex =
496 ((Desc.mayLoad() && ProducerOpIndex == ProducerOpSearchIndex) ||
497 (Desc.mayStore() && ProducerOpIndex == 0));
498
499 if (ProducerOpIsMemIndex) {
501
502 StringRef ModeError;
504 ModeError = "Absolute-set";
506 ModeError = "Auto-increment";
507 if (!ModeError.empty()) {
509 ModeError + " registers cannot be a new-value "
510 "producer");
512 "Instruction does not have a valid new register producer");
513 return false;
514 }
515 }
518 "FPU instructions cannot be new-value producers for jumps");
520 "Instruction does not have a valid new register producer");
521 return false;
522 }
523 }
524 return true;
525}
526
527bool HexagonMCChecker::checkRegistersReadOnly() {
529 MCInst const &Inst = *I.getInst();
531 for (unsigned j = 0; j < Defs; ++j) {
532 MCOperand const &Operand = Inst.getOperand(j);
533 assert(Operand.isReg() && "Def is not a register");
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
549 j < n; ++j) {
550 MCOperand const &Operand = I.getOperand(j);
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
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)
572 (ProducerPredicate.Register == ConsumerPredicate.Register &&
573 (ProducerPredicate.Register == Hexagon::NoRegister ||
574 ProducerPredicate.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 }
582 return std::make_tuple(&I, 0, HexagonMCInstrInfo::PredicateInfo());
583 }
584 return WrongSense;
585}
586
587void HexagonMCChecker::checkRegisterCurDefs() {
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
607bool HexagonMCChecker::checkRegisters() {
608
609 for (const auto &I : Defs) {
611
612 if (isLoopRegister(R) && Defs.count(R) > 1 &&
615
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
622
623 MCRegister UsrR = Hexagon::USR;
624 MCRegister BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;
626 return false;
627 }
629
630 PredSet &PM = Defs[R];
631
632
633 if (PM.count(Unconditional)) {
634
635
636 MCRegister UsrR = Hexagon::USR;
637 MCRegister BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;
639 return false;
640 }
641
642 for (const auto &J : PM) {
643 PredSense P = J;
644
645
646 if (PM.count(P) > 1) {
647
648
650 return false;
651 }
652
653 P.second = .second;
654 if (PM.count(P) && PM.size() > 2) {
655
656
657
659 return false;
660 }
661 }
662 }
663 }
664
665
666 for (const auto &I : TmpDefs) {
668
669 if (!Uses.count(R)) {
670
671 bool vHistFound = false;
675 vHistFound = true;
676 break;
677 }
678 }
679
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
692bool HexagonMCChecker::checkSolo() {
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) {
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
728 if (HasTmp(I))
730 "this is an HVX vtmp/.tmp destination instruction");
731
732 return false;
733 }
734 return true;
735}
736
737void HexagonMCChecker::compoundRegisterMap(unsigned &Register) {
739 default:
740 break;
741 case Hexagon::R15:
743 break;
744 case Hexagon::R14:
746 break;
747 case Hexagon::R13:
749 break;
750 case Hexagon::R12:
752 break;
753 case Hexagon::R11:
755 break;
756 case Hexagon::R10:
758 break;
759 case Hexagon::R9:
761 break;
762 case Hexagon::R8:
764 break;
765 }
766}
767
770 "' modified more than once");
771}
772
775 "' used with `.new' "
776 "but not validly modified in the same packet");
777}
778
782
784 if (ReportErrors)
785 Context.reportError(Loc, Msg);
786}
787
789 if (ReportErrors) {
790 auto SM = Context.getSourceManager();
791 if (SM)
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)
808 "' is not permitted for this architecture");
809 return false;
810 }
811 return true;
812}
813
814
815bool HexagonMCChecker::checkHVXAccum()
816{
818 bool IsTarget =
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)
Definition HexagonMCChecker.cpp:239
static bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID)
Definition HexagonMCChecker.cpp:272
Promote Memory to Register
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")))
void reportErrorNewValue(MCRegister Register)
Definition HexagonMCChecker.cpp:773
HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst &mcb, const MCRegisterInfo &ri, bool ReportErrors=true)
Definition HexagonMCChecker.cpp:197
bool check(bool FullCheck=true)
Definition HexagonMCChecker.cpp:213
void reportWarning(Twine const &Msg)
Definition HexagonMCChecker.cpp:796
void reportNote(SMLoc Loc, Twine const &Msg)
Definition HexagonMCChecker.cpp:788
void reportErrorRegisters(MCRegister Register)
Definition HexagonMCChecker.cpp:768
void reportBranchErrors()
Definition HexagonMCChecker.cpp:319
void reportError(SMLoc Loc, Twine const &Msg)
Definition HexagonMCChecker.cpp:783
bool isPredicated() const
Context object for machine code objects.
Instances of this class represent a single low-level machine instruction.
const MCOperand & getOperand(unsigned i) const
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.
MCRegister getReg() const
Returns the register number.
const MCInst * getInst() const
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.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
Wrapper class representing virtual and physical registers.
Represents a location in source code.
void push_back(const T &Elt)
constexpr bool empty() const
empty - Check if the string is empty.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
#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.
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
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...