34 cl::desc(
"Relax checks of new-value validity"));
36const HexagonMCChecker::PredSense
37 HexagonMCChecker::Unconditional(Hexagon::NoRegister,
false);
39void HexagonMCChecker::init() {
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();
78 NewPreds.insert(PredReg);
82 for (MCRegAliasIterator SRI(R, &RI, RI.subregs(R).empty()); SRI.isValid();
84 if (RI.subregs(*SRI).empty())
89 ReversePairs.insert(R);
92void HexagonMCChecker::init(
MCInst const &MCI) {
102 initReg(MCI, ImpUse, PredReg, isTrue);
106 STI.hasFeature(Hexagon::ArchV69);
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);
148 for (MCRegAliasIterator SRI(R, &RI, RI.subregs(R).empty()); SRI.isValid();
150 if (!RI.subregs(*SRI).empty())
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 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;
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:
298bool HexagonMCChecker::checkAXOK() {
299 MCInst
const *HasSoloAXInst =
nullptr;
311 Twine(
"Instruction can only be in a packet with ALU or non-FPU XTYPE "
314 Twine(
"Not an ALU or non-FPU XTYPE instruction"));
328bool HexagonMCChecker::checkHWLoop() {
335 "Branches cannot be in a packet with hardware loops");
343bool HexagonMCChecker::checkCOFMax1() {
349 for (
unsigned J = 0,
N = BranchLocations.
size(); J <
N; ++J) {
350 MCInst
const &
I = *BranchLocations[J];
354 if (
N > 1 && !Relax1 && !Relax2) {
356 "Instruction may not be in a packet with other branches");
360 if (
N > 1 && J == 0 && !Relax1) {
362 "Instruction may not be the first branch in packet");
366 if (
N > 1 && J == 1 && !Relax2) {
368 "Instruction may not be the second branch in packet");
377bool HexagonMCChecker::checkSlots() {
380 reportError(
"invalid instruction packet: out of slots");
387bool HexagonMCChecker::checkPredicates() {
389 for (
const auto &
I : NewPreds) {
392 if (!Defs.count(
P) || LatePreds.count(
P) || Defs.count(Hexagon::P3_0)) {
402 for (
const auto &
I : LatePreds) {
405 if (LatePreds.count(
P) > 1 || Defs.count(
P)) {
418bool HexagonMCChecker::checkNewValues() {
419 for (
auto const &ConsumerInst :
424 const HexagonMCInstrInfo::PredicateInfo ConsumerPredInfo =
428 MCOperand
const &
Op =
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);
437 if (ProducerInst ==
nullptr) {
439 "New value register consumer has no producer");
450 "Register producer is predicated and consumer is unconditional");
452 "Instruction does not have a valid new register producer");
455 if (ProducerPredInfo.
Register != Hexagon::NoRegister &&
458 "Register producer does not use the same predicate "
459 "register as the consumer");
461 "Instruction does not have a valid new register producer");
469 "Register producer has the opposite predicate sense as consumer");
471 "Instruction does not have a valid new register producer");
476 const unsigned ProducerOpIndex = std::get<1>(Producer);
478 if (
Desc.operands()[ProducerOpIndex].RegClass ==
479 Hexagon::DoubleRegsRegClassID) {
481 "Double registers cannot be new-value producers");
483 "Instruction does not have a valid new register producer");
491 const unsigned ProducerOpSearchIndex =
497 const bool ProducerOpIsMemIndex =
498 ((
Desc.mayLoad() && ProducerOpIndex == ProducerOpSearchIndex) ||
499 (
Desc.mayStore() && ProducerOpIndex == 0));
501 if (ProducerOpIsMemIndex) {
506 ModeError =
"Absolute-set";
508 ModeError =
"Auto-increment";
509 if (!ModeError.
empty()) {
511 ModeError +
" registers cannot be a new-value "
514 "Instruction does not have a valid new register producer");
520 "FPU instructions cannot be new-value producers for jumps");
522 "Instruction does not have a valid new register producer");
529bool HexagonMCChecker::checkRegistersReadOnly() {
531 MCInst
const &Inst = *
I.getInst();
533 for (
unsigned j = 0;
j < Defs; ++
j) {
534 MCOperand
const &Operand = Inst.
getOperand(j);
535 assert(Operand.
isReg() &&
"Def is not a register");
537 if (ReadOnly.find(
Register) != ReadOnly.end()) {
552 MCOperand
const &Operand =
I.getOperand(j);
559std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
560HexagonMCChecker::registerProducer(
562 std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
569 for (
unsigned J = 0,
N =
Desc.getNumDefs(); J <
N; ++J)
570 for (
auto K = MCRegAliasIterator(
I.getOperand(J).getReg(), &RI,
true);
574 (ProducerPredicate.Register == ConsumerPredicate.
Register &&
575 (ProducerPredicate.Register == Hexagon::NoRegister ||
576 ProducerPredicate.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;
584 return std::make_tuple(&
I, 0, HexagonMCInstrInfo::PredicateInfo());
589void HexagonMCChecker::checkRegisterCurDefs() {
593 const MCRegister RegDef =
I.getOperand(0).getReg();
595 bool HasRegDefUse =
false;
596 for (MCRegAliasIterator Alias(RegDef, &RI,
true); Alias.isValid();
598 HasRegDefUse = HasRegDefUse || registerUsed(*Alias);
602 "' used with `.cur' "
603 "but not used in the same packet");
609bool HexagonMCChecker::checkRegisters() {
611 for (
const auto &
I : Defs) {
612 MCRegister
R =
I.first;
614 if (isLoopRegister(R) && Defs.count(R) > 1 &&
618 reportError(
"loop-setup and some branch instructions "
619 "cannot be in the same packet");
622 if (SoftDefs.count(R)) {
625 MCRegister UsrR = Hexagon::USR;
626 MCRegister BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR :
R;
632 PredSet &PM = Defs[
R];
635 if (PM.count(Unconditional)) {
638 MCRegister UsrR = Hexagon::USR;
639 MCRegister BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR :
R;
644 for (
const auto &J : PM) {
648 if (PM.count(
P) > 1) {
655 P.second = !
P.second;
656 if (PM.count(
P) && PM.size() > 2) {
668 for (
const auto &
I : TmpDefs) {
671 if (!Uses.count(R)) {
673 bool vHistFound =
false;
684 "' used with `.tmp' but not used in the same packet");
693bool HexagonMCChecker::checkValidHMX() {
694 bool hasWeight =
false;
695 bool hasActivation =
false;
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);
712 reportNote(
I.getLoc(),
"this is an HMX weight instruction");
714 reportNote(
I.getLoc(),
"this is an HMX activation instruction");
717 "this is neither an HMX weight nor activation");
720 return ValidWeightActPairing;
724bool HexagonMCChecker::checkSolo() {
728 reportError(
I.getLoc(),
"Instruction is marked `isSolo' and "
729 "cannot have other instructions in "
738bool HexagonMCChecker::checkShuffle() {
739 HexagonMCShuffler MCSDX(Context, ReportErrors, MCII, STI, MCB);
740 return MCSDX.check();
743bool HexagonMCChecker::checkValidTmpDst() {
744 if (!STI.hasFeature(Hexagon::ArchV69)) {
747 auto HasTmp = [&](MCInst
const &
I) {
752 unsigned HasTmpCount =
755 if (HasTmpCount > 1) {
758 "this packet has more than one HVX vtmp/.tmp destination instruction");
763 "this is an HVX vtmp/.tmp destination instruction");
770void HexagonMCChecker::compoundRegisterMap(
unsigned &
Register) {
803 "' modified more than once");
808 "' used with `.new' "
809 "but not validly modified in the same packet");
818 Context.reportError(
Loc,
Msg);
823 auto SM = Context.getSourceManager();
831 Context.reportWarning(MCB.getLoc(),
Msg);
834bool HexagonMCChecker::checkLegalVecRegPair() {
835 const bool IsPermitted = STI.
hasFeature(Hexagon::ArchV67);
836 const bool HasReversePairs = ReversePairs.size() != 0;
838 if (!IsPermitted && HasReversePairs) {
839 for (
auto R : ReversePairs)
841 "' is not permitted for this architecture");
848bool HexagonMCChecker::checkHVXAccum()
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");
866bool HexagonMCChecker::checkHLX64BitRegUse() {
868 RI.getRegClass(Hexagon::DoubleRegsRegClassID);
869 const MCRegisterClass &
IntRegs = RI.getRegClass(Hexagon::IntRegsRegClassID);
870 const MCInst *DoubleInst =
nullptr;
871 unsigned NumScalarArg = 0;
876 if (
Desc.mayLoad() ||
Desc.mayStore())
878 bool UsesScalarArg =
false;
879 for (
const auto &
Op :
I) {
880 if (!DoubleInst &&
Op.isReg() &&
DoubleRegs.contains(
Op.getReg()))
882 if (
Op.isImm() ||
Op.isExpr() ||
885 UsesScalarArg =
true;
891 if (DoubleInst && NumScalarArg > 1) {
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");
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)
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")))
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 reportBranchErrors()
void reportError(SMLoc Loc, Twine const &Msg)
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
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 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.
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...