34 cl::desc(
"Relax checks of new-value validity"));
36const HexagonMCChecker::PredSense
37 HexagonMCChecker::Unconditional(Hexagon::NoRegister,
false);
39void HexagonMCChecker::init() {
41 ReadOnly.insert(Hexagon::PC);
42 ReadOnly.insert(Hexagon::C9_8);
46 Defs[Hexagon::SA0].
insert(Unconditional);
47 Defs[Hexagon::LC0].
insert(Unconditional);
50 Defs[Hexagon::SA1].
insert(Unconditional);
51 Defs[Hexagon::LC1].
insert(Unconditional);
57 MCInst const &Inst = *
I.getInst();
68void HexagonMCChecker::initReg(
MCInst const &MCI,
unsigned R,
unsigned &PredReg,
78 NewPreds.insert(PredReg);
89 ReversePairs.insert(R);
92void HexagonMCChecker::init(
MCInst const &MCI) {
94 unsigned PredReg = Hexagon::NoRegister;
102 initReg(MCI, ImpUse, PredReg, isTrue);
110 if (Hexagon::R31 != R && MCID.
isCall())
114 if (Hexagon::PC == R)
119 if (Hexagon::USR_OVF == R)
130 else if (!IgnoreTmpDst)
131 Defs[
R].
insert(PredSense(PredReg, isTrue));
135 for (
unsigned i = 0; i < MCID.
getNumDefs(); ++i) {
140 if (R == Hexagon::C8)
144 ReversePairs.insert(R);
163 if (Hexagon::P3_0 != R && Hexagon::P3_0 == *SRI)
168 SoftDefs.insert(*SRI);
172 LatePreds.insert(*SRI);
180 TmpDefs.insert(*SRI);
181 else if (!IgnoreTmpDst)
182 Defs[*SRI].
insert(PredSense(PredReg, isTrue));
200 : Context(Context), MCB(mcb), RI(ri), MCII(MCII), STI(STI),
201 ReportErrors(ReportErrors) {
207 bool CopyReportErrors)
209 STI(STI), ReportErrors(CopyReportErrors ?
Other.ReportErrors :
false) {
214 bool chkP = checkPredicates();
215 bool chkNV = checkNewValues();
216 bool chkR = checkRegisters();
217 bool chkRRO = checkRegistersReadOnly();
218 checkRegisterCurDefs();
219 bool chkS = checkSolo();
222 chkSh = checkShuffle();
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;
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:
296bool HexagonMCChecker::checkAXOK() {
297 MCInst const *HasSoloAXInst =
nullptr;
309 Twine(
"Instruction can only be in a packet with ALU or non-FPU XTYPE "
312 Twine(
"Not an ALU or non-FPU XTYPE instruction"));
326bool HexagonMCChecker::checkHWLoop() {
333 "Branches cannot be in a packet with hardware loops");
341bool HexagonMCChecker::checkCOFMax1() {
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");
358 if (
N > 1 && J == 0 && !Relax1) {
360 "Instruction may not be the first branch in packet");
364 if (
N > 1 && J == 1 && !Relax2) {
366 "Instruction may not be the second branch in packet");
375bool HexagonMCChecker::checkSlots() {
378 reportError(
"invalid instruction packet: out of slots");
385bool HexagonMCChecker::checkPredicates() {
387 for (
const auto &
I : NewPreds) {
390 if (!Defs.
count(
P) || LatePreds.count(
P) || Defs.
count(Hexagon::P3_0)) {
400 for (
const auto &
I : LatePreds) {
403 if (LatePreds.count(
P) > 1 || Defs.
count(
P)) {
416bool HexagonMCChecker::checkNewValues() {
417 for (
auto const &ConsumerInst :
430 auto Producer = registerProducer(
Op.getReg(), ConsumerPredInfo);
431 const MCInst *
const ProducerInst = std::get<0>(Producer);
433 std::get<2>(Producer);
435 if (ProducerInst ==
nullptr) {
437 "New value register consumer has no producer");
448 "Register producer is predicated and consumer is unconditional");
450 "Instruction does not have a valid new register producer");
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");
467 "Register producer has the opposite predicate sense as consumer");
469 "Instruction does not have a valid new register producer");
474 const unsigned ProducerOpIndex = std::get<1>(Producer);
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");
489 const unsigned ProducerOpSearchIndex =
495 const bool ProducerOpIsMemIndex =
496 ((
Desc.mayLoad() && ProducerOpIndex == ProducerOpSearchIndex) ||
497 (
Desc.mayStore() && ProducerOpIndex == 0));
499 if (ProducerOpIsMemIndex) {
504 ModeError =
"Absolute-set";
506 ModeError =
"Auto-increment";
507 if (!ModeError.
empty()) {
509 ModeError +
" registers cannot be a new-value "
512 "Instruction does not have a valid new register producer");
518 "FPU instructions cannot be new-value producers for jumps");
520 "Instruction does not have a valid new register producer");
527bool HexagonMCChecker::checkRegistersReadOnly() {
529 MCInst const &Inst = *
I.getInst();
531 for (
unsigned j = 0;
j < Defs; ++
j) {
533 assert(Operand.
isReg() &&
"Def is not a register");
535 if (ReadOnly.find(
Register) != ReadOnly.end()) {
545bool HexagonMCChecker::registerUsed(
unsigned Register) {
548 n =
I.getNumOperands();
557std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
558HexagonMCChecker::registerProducer(
560 std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
567 for (
unsigned J = 0,
N =
Desc.getNumDefs(); J <
N; ++J)
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;
587void HexagonMCChecker::checkRegisterCurDefs() {
591 const unsigned RegDef =
I.getOperand(0).getReg();
593 bool HasRegDefUse =
false;
596 HasRegDefUse = HasRegDefUse || registerUsed(*Alias);
600 "' used with `.cur' "
601 "but not used in the same packet");
607bool HexagonMCChecker::checkRegisters() {
609 for (
const auto &
I : Defs) {
610 unsigned R =
I.first;
612 if (isLoopRegister(R) && Defs.count(R) > 1 &&
616 reportError(
"loop-setup and some branch instructions "
617 "cannot be in the same packet");
620 if (SoftDefs.count(R)) {
623 unsigned UsrR = Hexagon::USR;
630 PredSet &PM = Defs[
R];
633 if (PM.count(Unconditional)) {
636 unsigned UsrR = Hexagon::USR;
642 for (
const auto &J : PM) {
646 if (PM.count(
P) > 1) {
653 P.second = !
P.second;
654 if (PM.count(
P) && PM.size() > 2) {
666 for (
const auto &
I : TmpDefs) {
669 if (!Uses.count(R)) {
671 bool vHistFound =
false;
682 "' used with `.tmp' but not used in the same packet");
692bool HexagonMCChecker::checkSolo() {
696 reportError(
I.getLoc(),
"Instruction is marked `isSolo' and "
697 "cannot have other instructions in "
706bool HexagonMCChecker::checkShuffle() {
708 return MCSDX.check();
711bool HexagonMCChecker::checkValidTmpDst() {
715 auto HasTmp = [&](
MCInst const &
I) {
719 unsigned HasTmpCount =
722 if (HasTmpCount > 1) {
725 "this packet has more than one HVX vtmp/.tmp destination instruction");
730 "this is an HVX vtmp/.tmp destination instruction");
737void HexagonMCChecker::compoundRegisterMap(
unsigned &
Register) {
770 "' modified more than once");
775 "' used with `.new' "
776 "but not validly modified in the same packet");
801bool HexagonMCChecker::checkLegalVecRegPair() {
802 const bool IsPermitted = STI.
hasFeature(Hexagon::ArchV67);
803 const bool HasReversePairs = ReversePairs.size() != 0;
805 if (!IsPermitted && HasReversePairs) {
806 for (
auto R : ReversePairs)
808 "' is not permitted for this architecture");
815bool HexagonMCChecker::checkHVXAccum()
822 unsigned int R =
I.getOperand(0).getReg();
823 TmpDefsIterator It = TmpDefs.find(R);
824 if (It != TmpDefs.end()) {
826 "' is accumulated in this packet");
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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class represents an Operation in the Expression.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Check for a valid bundle.
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 reportBranchErrors()
void reportErrorRegisters(unsigned Register)
void reportErrorNewValue(unsigned Register)
void reportError(SMLoc Loc, Twine const &Msg)
bool isPredicated() const
Context object for machine code objects.
void reportWarning(SMLoc L, const Twine &Msg)
const SourceMgr * getSourceManager() const
void reportError(SMLoc L, const Twine &Msg)
Instances of this class represent a single low-level machine instruction.
const MCOperand & getOperand(unsigned i) const
Describe properties that are true of each instruction in the target description file.
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.
Instances of this class represent operands of the MCInst class.
unsigned getReg() const
Returns the register number.
const MCInst * getInst() const
MCRegAliasIterator enumerates all registers aliasing Reg.
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.
bool isSubRegister(MCRegister RegA, MCRegister RegB) const
Returns true if RegB is a sub-register of RegA.
iterator_range< MCSubRegIterator > subregs(MCRegister Reg) const
Return an iterator range over all sub-registers of Reg, excluding Reg.
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)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
StringRef - Represent a constant reference to a string, i.e.
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.
bool IsReverseVecRegPair(unsigned VecReg)
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 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 isPredReg(MCRegisterInfo const &MRI, unsigned Reg)
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 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.
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...
Description of the encoding of one expression Op.