10b57cec5SDimitry Andric //===----- HexagonMCChecker.cpp - Instruction bundle checking -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This implements the checking of insns inside a bundle according to the
100b57cec5SDimitry Andric // packet constraint rules of the Hexagon ISA.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCChecker.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/HexagonBaseInfo.h"
160b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCInstrInfo.h"
170b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCShuffler.h"
180b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCTargetDesc.h"
1904eeddc0SDimitry Andric
200b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
2581ad6265SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
260b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
270b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
280b57cec5SDimitry Andric #include <cassert>
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric static cl::opt<bool>
3381ad6265SDimitry Andric RelaxNVChecks("relax-nv-checks", cl::Hidden,
3481ad6265SDimitry Andric cl::desc("Relax checks of new-value validity"));
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric const HexagonMCChecker::PredSense
370b57cec5SDimitry Andric HexagonMCChecker::Unconditional(Hexagon::NoRegister, false);
380b57cec5SDimitry Andric
init()390b57cec5SDimitry Andric void HexagonMCChecker::init() {
400b57cec5SDimitry Andric // Initialize read-only registers set.
410b57cec5SDimitry Andric ReadOnly.insert(Hexagon::PC);
420b57cec5SDimitry Andric ReadOnly.insert(Hexagon::C9_8);
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric // Figure out the loop-registers definitions.
450b57cec5SDimitry Andric if (HexagonMCInstrInfo::isInnerLoop(MCB)) {
460b57cec5SDimitry Andric Defs[Hexagon::SA0].insert(Unconditional); // FIXME: define or change SA0?
470b57cec5SDimitry Andric Defs[Hexagon::LC0].insert(Unconditional);
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric if (HexagonMCInstrInfo::isOuterLoop(MCB)) {
500b57cec5SDimitry Andric Defs[Hexagon::SA1].insert(Unconditional); // FIXME: define or change SA0?
510b57cec5SDimitry Andric Defs[Hexagon::LC1].insert(Unconditional);
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric if (HexagonMCInstrInfo::isBundle(MCB))
550b57cec5SDimitry Andric // Unfurl a bundle.
560b57cec5SDimitry Andric for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
570b57cec5SDimitry Andric MCInst const &Inst = *I.getInst();
580b57cec5SDimitry Andric if (HexagonMCInstrInfo::isDuplex(MCII, Inst)) {
590b57cec5SDimitry Andric init(*Inst.getOperand(0).getInst());
600b57cec5SDimitry Andric init(*Inst.getOperand(1).getInst());
610b57cec5SDimitry Andric } else
620b57cec5SDimitry Andric init(Inst);
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric else
650b57cec5SDimitry Andric init(MCB);
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric
initReg(MCInst const & MCI,unsigned R,unsigned & PredReg,bool & isTrue)680b57cec5SDimitry Andric void HexagonMCChecker::initReg(MCInst const &MCI, unsigned R, unsigned &PredReg,
690b57cec5SDimitry Andric bool &isTrue) {
7004eeddc0SDimitry Andric if (HexagonMCInstrInfo::isPredicated(MCII, MCI) &&
7104eeddc0SDimitry Andric HexagonMCInstrInfo::isPredReg(RI, R)) {
720b57cec5SDimitry Andric // Note an used predicate register.
730b57cec5SDimitry Andric PredReg = R;
740b57cec5SDimitry Andric isTrue = HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI);
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric // Note use of new predicate register.
770b57cec5SDimitry Andric if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI))
780b57cec5SDimitry Andric NewPreds.insert(PredReg);
790b57cec5SDimitry Andric } else
800b57cec5SDimitry Andric // Note register use. Super-registers are not tracked directly,
810b57cec5SDimitry Andric // but their components.
82*06c3fb27SDimitry Andric for (MCRegAliasIterator SRI(R, &RI, RI.subregs(R).empty()); SRI.isValid();
83*06c3fb27SDimitry Andric ++SRI)
84*06c3fb27SDimitry Andric if (RI.subregs(*SRI).empty())
850b57cec5SDimitry Andric // Skip super-registers used indirectly.
860b57cec5SDimitry Andric Uses.insert(*SRI);
875ffd83dbSDimitry Andric
885ffd83dbSDimitry Andric if (HexagonMCInstrInfo::IsReverseVecRegPair(R))
895ffd83dbSDimitry Andric ReversePairs.insert(R);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric
init(MCInst const & MCI)920b57cec5SDimitry Andric void HexagonMCChecker::init(MCInst const &MCI) {
930b57cec5SDimitry Andric const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MCI);
940b57cec5SDimitry Andric unsigned PredReg = Hexagon::NoRegister;
950b57cec5SDimitry Andric bool isTrue = false;
960b57cec5SDimitry Andric
970b57cec5SDimitry Andric // Get used registers.
980b57cec5SDimitry Andric for (unsigned i = MCID.getNumDefs(); i < MCID.getNumOperands(); ++i)
990b57cec5SDimitry Andric if (MCI.getOperand(i).isReg())
1000b57cec5SDimitry Andric initReg(MCI, MCI.getOperand(i).getReg(), PredReg, isTrue);
101bdd1243dSDimitry Andric for (MCPhysReg ImpUse : MCID.implicit_uses())
102bdd1243dSDimitry Andric initReg(MCI, ImpUse, PredReg, isTrue);
1030b57cec5SDimitry Andric
1040eae32dcSDimitry Andric const bool IgnoreTmpDst = (HexagonMCInstrInfo::hasTmpDst(MCII, MCI) ||
1050eae32dcSDimitry Andric HexagonMCInstrInfo::hasHvxTmp(MCII, MCI)) &&
106*06c3fb27SDimitry Andric STI.hasFeature(Hexagon::ArchV69);
1070eae32dcSDimitry Andric
1080b57cec5SDimitry Andric // Get implicit register definitions.
109bdd1243dSDimitry Andric for (MCPhysReg R : MCID.implicit_defs()) {
1100b57cec5SDimitry Andric if (Hexagon::R31 != R && MCID.isCall())
1110b57cec5SDimitry Andric // Any register other than the LR and the PC are actually volatile ones
1120b57cec5SDimitry Andric // as defined by the ABI, not modified implicitly by the call insn.
1130b57cec5SDimitry Andric continue;
1140b57cec5SDimitry Andric if (Hexagon::PC == R)
1150b57cec5SDimitry Andric // Branches are the only insns that can change the PC,
1160b57cec5SDimitry Andric // otherwise a read-only register.
1170b57cec5SDimitry Andric continue;
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric if (Hexagon::USR_OVF == R)
1200b57cec5SDimitry Andric // Many insns change the USR implicitly, but only one or another flag.
1210b57cec5SDimitry Andric // The instruction table models the USR.OVF flag, which can be
1220b57cec5SDimitry Andric // implicitly modified more than once, but cannot be modified in the
1230b57cec5SDimitry Andric // same packet with an instruction that modifies is explicitly. Deal
1240b57cec5SDimitry Andric // with such situations individually.
1250b57cec5SDimitry Andric SoftDefs.insert(R);
12604eeddc0SDimitry Andric else if (HexagonMCInstrInfo::isPredReg(RI, R) &&
1270b57cec5SDimitry Andric HexagonMCInstrInfo::isPredicateLate(MCII, MCI))
1280b57cec5SDimitry Andric // Include implicit late predicates.
1290b57cec5SDimitry Andric LatePreds.insert(R);
1300eae32dcSDimitry Andric else if (!IgnoreTmpDst)
1310b57cec5SDimitry Andric Defs[R].insert(PredSense(PredReg, isTrue));
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric // Figure out explicit register definitions.
1350b57cec5SDimitry Andric for (unsigned i = 0; i < MCID.getNumDefs(); ++i) {
1360b57cec5SDimitry Andric unsigned R = MCI.getOperand(i).getReg(), S = Hexagon::NoRegister;
1370b57cec5SDimitry Andric // USR has subregisters (while C8 does not for technical reasons), so
1380b57cec5SDimitry Andric // reset R to USR, since we know how to handle multiple defs of USR,
1390b57cec5SDimitry Andric // taking into account its subregisters.
1400b57cec5SDimitry Andric if (R == Hexagon::C8)
1410b57cec5SDimitry Andric R = Hexagon::USR;
1420b57cec5SDimitry Andric
1435ffd83dbSDimitry Andric if (HexagonMCInstrInfo::IsReverseVecRegPair(R))
1445ffd83dbSDimitry Andric ReversePairs.insert(R);
1455ffd83dbSDimitry Andric
1460b57cec5SDimitry Andric // Note register definitions, direct ones as well as indirect side-effects.
1470b57cec5SDimitry Andric // Super-registers are not tracked directly, but their components.
148*06c3fb27SDimitry Andric for (MCRegAliasIterator SRI(R, &RI, RI.subregs(R).empty()); SRI.isValid();
149*06c3fb27SDimitry Andric ++SRI) {
150*06c3fb27SDimitry Andric if (!RI.subregs(*SRI).empty())
1510b57cec5SDimitry Andric // Skip super-registers defined indirectly.
1520b57cec5SDimitry Andric continue;
1530b57cec5SDimitry Andric
1540b57cec5SDimitry Andric if (R == *SRI) {
1550b57cec5SDimitry Andric if (S == R)
1560b57cec5SDimitry Andric // Avoid scoring the defined register multiple times.
1570b57cec5SDimitry Andric continue;
1580b57cec5SDimitry Andric else
1590b57cec5SDimitry Andric // Note that the defined register has already been scored.
1600b57cec5SDimitry Andric S = R;
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric if (Hexagon::P3_0 != R && Hexagon::P3_0 == *SRI)
1640b57cec5SDimitry Andric // P3:0 is a special case, since multiple predicate register definitions
1650b57cec5SDimitry Andric // in a packet is allowed as the equivalent of their logical "and".
1660b57cec5SDimitry Andric // Only an explicit definition of P3:0 is noted as such; if a
1670b57cec5SDimitry Andric // side-effect, then note as a soft definition.
1680b57cec5SDimitry Andric SoftDefs.insert(*SRI);
1690b57cec5SDimitry Andric else if (HexagonMCInstrInfo::isPredicateLate(MCII, MCI) &&
17004eeddc0SDimitry Andric HexagonMCInstrInfo::isPredReg(RI, *SRI))
1710b57cec5SDimitry Andric // Some insns produce predicates too late to be used in the same packet.
1720b57cec5SDimitry Andric LatePreds.insert(*SRI);
1730b57cec5SDimitry Andric else if (i == 0 && HexagonMCInstrInfo::getType(MCII, MCI) ==
1740b57cec5SDimitry Andric HexagonII::TypeCVI_VM_TMP_LD)
1750b57cec5SDimitry Andric // Temporary loads should be used in the same packet, but don't commit
1760b57cec5SDimitry Andric // results, so it should be disregarded if another insn changes the same
1770b57cec5SDimitry Andric // register.
1780b57cec5SDimitry Andric // TODO: relies on the impossibility of a current and a temporary loads
1790b57cec5SDimitry Andric // in the same packet.
1800b57cec5SDimitry Andric TmpDefs.insert(*SRI);
1810eae32dcSDimitry Andric else if (!IgnoreTmpDst)
1820b57cec5SDimitry Andric Defs[*SRI].insert(PredSense(PredReg, isTrue));
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric // Figure out definitions of new predicate registers.
1870b57cec5SDimitry Andric if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI))
1880b57cec5SDimitry Andric for (unsigned i = MCID.getNumDefs(); i < MCID.getNumOperands(); ++i)
1890b57cec5SDimitry Andric if (MCI.getOperand(i).isReg()) {
1900b57cec5SDimitry Andric unsigned P = MCI.getOperand(i).getReg();
1910b57cec5SDimitry Andric
19204eeddc0SDimitry Andric if (HexagonMCInstrInfo::isPredReg(RI, P))
1930b57cec5SDimitry Andric NewPreds.insert(P);
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric
HexagonMCChecker(MCContext & Context,MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst & mcb,MCRegisterInfo const & ri,bool ReportErrors)1970b57cec5SDimitry Andric HexagonMCChecker::HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII,
1980b57cec5SDimitry Andric MCSubtargetInfo const &STI, MCInst &mcb,
1990b57cec5SDimitry Andric MCRegisterInfo const &ri, bool ReportErrors)
2000b57cec5SDimitry Andric : Context(Context), MCB(mcb), RI(ri), MCII(MCII), STI(STI),
20104eeddc0SDimitry Andric ReportErrors(ReportErrors) {
2020b57cec5SDimitry Andric init();
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
HexagonMCChecker(HexagonMCChecker const & Other,MCSubtargetInfo const & STI,bool CopyReportErrors)2050b57cec5SDimitry Andric HexagonMCChecker::HexagonMCChecker(HexagonMCChecker const &Other,
2060b57cec5SDimitry Andric MCSubtargetInfo const &STI,
2070b57cec5SDimitry Andric bool CopyReportErrors)
2080b57cec5SDimitry Andric : Context(Other.Context), MCB(Other.MCB), RI(Other.RI), MCII(Other.MCII),
20904eeddc0SDimitry Andric STI(STI), ReportErrors(CopyReportErrors ? Other.ReportErrors : false) {
2105ffd83dbSDimitry Andric init();
2115ffd83dbSDimitry Andric }
2120b57cec5SDimitry Andric
check(bool FullCheck)2130b57cec5SDimitry Andric bool HexagonMCChecker::check(bool FullCheck) {
2140b57cec5SDimitry Andric bool chkP = checkPredicates();
2150b57cec5SDimitry Andric bool chkNV = checkNewValues();
2160b57cec5SDimitry Andric bool chkR = checkRegisters();
2170b57cec5SDimitry Andric bool chkRRO = checkRegistersReadOnly();
2180b57cec5SDimitry Andric checkRegisterCurDefs();
2190b57cec5SDimitry Andric bool chkS = checkSolo();
2200b57cec5SDimitry Andric bool chkSh = true;
2210b57cec5SDimitry Andric if (FullCheck)
2220b57cec5SDimitry Andric chkSh = checkShuffle();
2230b57cec5SDimitry Andric bool chkSl = true;
2240b57cec5SDimitry Andric if (FullCheck)
2250b57cec5SDimitry Andric chkSl = checkSlots();
2260b57cec5SDimitry Andric bool chkAXOK = checkAXOK();
2270b57cec5SDimitry Andric bool chkCofMax1 = checkCOFMax1();
2280b57cec5SDimitry Andric bool chkHWLoop = checkHWLoop();
2290eae32dcSDimitry Andric bool chkValidTmpDst = FullCheck ? checkValidTmpDst() : true;
2305ffd83dbSDimitry Andric bool chkLegalVecRegPair = checkLegalVecRegPair();
23104eeddc0SDimitry Andric bool ChkHVXAccum = checkHVXAccum();
2320b57cec5SDimitry Andric bool chk = chkP && chkNV && chkR && chkRRO && chkS && chkSh && chkSl &&
2330eae32dcSDimitry Andric chkAXOK && chkCofMax1 && chkHWLoop && chkValidTmpDst &&
23404eeddc0SDimitry Andric chkLegalVecRegPair && ChkHVXAccum;
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric return chk;
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric
isDuplexAGroup(unsigned Opcode)2390b57cec5SDimitry Andric static bool isDuplexAGroup(unsigned Opcode) {
2400b57cec5SDimitry Andric switch (Opcode) {
2410b57cec5SDimitry Andric case Hexagon::SA1_addi:
2420b57cec5SDimitry Andric case Hexagon::SA1_addrx:
2430b57cec5SDimitry Andric case Hexagon::SA1_addsp:
2440b57cec5SDimitry Andric case Hexagon::SA1_and1:
2450b57cec5SDimitry Andric case Hexagon::SA1_clrf:
2460b57cec5SDimitry Andric case Hexagon::SA1_clrfnew:
2470b57cec5SDimitry Andric case Hexagon::SA1_clrt:
2480b57cec5SDimitry Andric case Hexagon::SA1_clrtnew:
2490b57cec5SDimitry Andric case Hexagon::SA1_cmpeqi:
2500b57cec5SDimitry Andric case Hexagon::SA1_combine0i:
2510b57cec5SDimitry Andric case Hexagon::SA1_combine1i:
2520b57cec5SDimitry Andric case Hexagon::SA1_combine2i:
2530b57cec5SDimitry Andric case Hexagon::SA1_combine3i:
2540b57cec5SDimitry Andric case Hexagon::SA1_combinerz:
2550b57cec5SDimitry Andric case Hexagon::SA1_combinezr:
2560b57cec5SDimitry Andric case Hexagon::SA1_dec:
2570b57cec5SDimitry Andric case Hexagon::SA1_inc:
2580b57cec5SDimitry Andric case Hexagon::SA1_seti:
2590b57cec5SDimitry Andric case Hexagon::SA1_setin1:
2600b57cec5SDimitry Andric case Hexagon::SA1_sxtb:
2610b57cec5SDimitry Andric case Hexagon::SA1_sxth:
2620b57cec5SDimitry Andric case Hexagon::SA1_tfr:
2630b57cec5SDimitry Andric case Hexagon::SA1_zxtb:
2640b57cec5SDimitry Andric case Hexagon::SA1_zxth:
2650b57cec5SDimitry Andric return true;
2660b57cec5SDimitry Andric break;
2670b57cec5SDimitry Andric default:
2680b57cec5SDimitry Andric return false;
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric
isNeitherAnorX(MCInstrInfo const & MCII,MCInst const & ID)2720b57cec5SDimitry Andric static bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) {
27304eeddc0SDimitry Andric if (HexagonMCInstrInfo::isFloat(MCII, ID))
27404eeddc0SDimitry Andric return true;
2750b57cec5SDimitry Andric unsigned Type = HexagonMCInstrInfo::getType(MCII, ID);
27604eeddc0SDimitry Andric switch (Type) {
27704eeddc0SDimitry Andric case HexagonII::TypeALU32_2op:
27804eeddc0SDimitry Andric case HexagonII::TypeALU32_3op:
27904eeddc0SDimitry Andric case HexagonII::TypeALU32_ADDI:
28004eeddc0SDimitry Andric case HexagonII::TypeS_2op:
28104eeddc0SDimitry Andric case HexagonII::TypeS_3op:
28204eeddc0SDimitry Andric case HexagonII::TypeEXTENDER:
28304eeddc0SDimitry Andric case HexagonII::TypeM:
28404eeddc0SDimitry Andric case HexagonII::TypeALU64:
28504eeddc0SDimitry Andric return false;
28604eeddc0SDimitry Andric case HexagonII::TypeSUBINSN: {
28704eeddc0SDimitry Andric return !isDuplexAGroup(ID.getOpcode());
28804eeddc0SDimitry Andric }
28904eeddc0SDimitry Andric case HexagonII::TypeDUPLEX:
29004eeddc0SDimitry Andric llvm_unreachable("unexpected duplex instruction");
29104eeddc0SDimitry Andric default:
29204eeddc0SDimitry Andric return true;
29304eeddc0SDimitry Andric }
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
checkAXOK()2960b57cec5SDimitry Andric bool HexagonMCChecker::checkAXOK() {
2970b57cec5SDimitry Andric MCInst const *HasSoloAXInst = nullptr;
2980b57cec5SDimitry Andric for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
2990b57cec5SDimitry Andric if (HexagonMCInstrInfo::isSoloAX(MCII, I)) {
3000b57cec5SDimitry Andric HasSoloAXInst = &I;
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric if (!HasSoloAXInst)
3040b57cec5SDimitry Andric return true;
3050b57cec5SDimitry Andric for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
3060b57cec5SDimitry Andric if (&I != HasSoloAXInst && isNeitherAnorX(MCII, I)) {
3070b57cec5SDimitry Andric reportError(
3080b57cec5SDimitry Andric HasSoloAXInst->getLoc(),
3090b57cec5SDimitry Andric Twine("Instruction can only be in a packet with ALU or non-FPU XTYPE "
3100b57cec5SDimitry Andric "instructions"));
3110b57cec5SDimitry Andric reportError(I.getLoc(),
3120b57cec5SDimitry Andric Twine("Not an ALU or non-FPU XTYPE instruction"));
3130b57cec5SDimitry Andric return false;
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric }
3160b57cec5SDimitry Andric return true;
3170b57cec5SDimitry Andric }
3180b57cec5SDimitry Andric
reportBranchErrors()3190b57cec5SDimitry Andric void HexagonMCChecker::reportBranchErrors() {
3200b57cec5SDimitry Andric for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
32104eeddc0SDimitry Andric if (HexagonMCInstrInfo::IsABranchingInst(MCII, STI, I))
3220b57cec5SDimitry Andric reportNote(I.getLoc(), "Branching instruction");
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric
checkHWLoop()3260b57cec5SDimitry Andric bool HexagonMCChecker::checkHWLoop() {
3270b57cec5SDimitry Andric if (!HexagonMCInstrInfo::isInnerLoop(MCB) &&
3280b57cec5SDimitry Andric !HexagonMCInstrInfo::isOuterLoop(MCB))
3290b57cec5SDimitry Andric return true;
3300b57cec5SDimitry Andric for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
33104eeddc0SDimitry Andric if (HexagonMCInstrInfo::IsABranchingInst(MCII, STI, I)) {
3320b57cec5SDimitry Andric reportError(MCB.getLoc(),
3330b57cec5SDimitry Andric "Branches cannot be in a packet with hardware loops");
3340b57cec5SDimitry Andric reportBranchErrors();
3350b57cec5SDimitry Andric return false;
3360b57cec5SDimitry Andric }
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric return true;
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric
checkCOFMax1()3410b57cec5SDimitry Andric bool HexagonMCChecker::checkCOFMax1() {
3420b57cec5SDimitry Andric SmallVector<MCInst const *, 2> BranchLocations;
3430b57cec5SDimitry Andric for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
34404eeddc0SDimitry Andric if (HexagonMCInstrInfo::IsABranchingInst(MCII, STI, I))
3450b57cec5SDimitry Andric BranchLocations.push_back(&I);
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric for (unsigned J = 0, N = BranchLocations.size(); J < N; ++J) {
3480b57cec5SDimitry Andric MCInst const &I = *BranchLocations[J];
3490b57cec5SDimitry Andric if (HexagonMCInstrInfo::isCofMax1(MCII, I)) {
3500b57cec5SDimitry Andric bool Relax1 = HexagonMCInstrInfo::isCofRelax1(MCII, I);
3510b57cec5SDimitry Andric bool Relax2 = HexagonMCInstrInfo::isCofRelax2(MCII, I);
3520b57cec5SDimitry Andric if (N > 1 && !Relax1 && !Relax2) {
3530b57cec5SDimitry Andric reportError(I.getLoc(),
3540b57cec5SDimitry Andric "Instruction may not be in a packet with other branches");
3550b57cec5SDimitry Andric reportBranchErrors();
3560b57cec5SDimitry Andric return false;
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric if (N > 1 && J == 0 && !Relax1) {
3590b57cec5SDimitry Andric reportError(I.getLoc(),
3600b57cec5SDimitry Andric "Instruction may not be the first branch in packet");
3610b57cec5SDimitry Andric reportBranchErrors();
3620b57cec5SDimitry Andric return false;
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric if (N > 1 && J == 1 && !Relax2) {
3650b57cec5SDimitry Andric reportError(I.getLoc(),
3660b57cec5SDimitry Andric "Instruction may not be the second branch in packet");
3670b57cec5SDimitry Andric reportBranchErrors();
3680b57cec5SDimitry Andric return false;
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric }
3720b57cec5SDimitry Andric return true;
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric
checkSlots()3750b57cec5SDimitry Andric bool HexagonMCChecker::checkSlots() {
37604eeddc0SDimitry Andric if (HexagonMCInstrInfo::slotsConsumed(MCII, STI, MCB) >
37704eeddc0SDimitry Andric HexagonMCInstrInfo::packetSizeSlots(STI)) {
3780b57cec5SDimitry Andric reportError("invalid instruction packet: out of slots");
3790b57cec5SDimitry Andric return false;
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric return true;
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric
3840b57cec5SDimitry Andric // Check legal use of predicate registers.
checkPredicates()3850b57cec5SDimitry Andric bool HexagonMCChecker::checkPredicates() {
3860b57cec5SDimitry Andric // Check for proper use of new predicate registers.
3870b57cec5SDimitry Andric for (const auto &I : NewPreds) {
3880b57cec5SDimitry Andric unsigned P = I;
3890b57cec5SDimitry Andric
3905ffd83dbSDimitry Andric if (!Defs.count(P) || LatePreds.count(P) || Defs.count(Hexagon::P3_0)) {
3910b57cec5SDimitry Andric // Error out if the new predicate register is not defined,
3920b57cec5SDimitry Andric // or defined "late"
3930b57cec5SDimitry Andric // (e.g., "{ if (p3.new)... ; p3 = sp1loop0(#r7:2, Rs) }").
3940b57cec5SDimitry Andric reportErrorNewValue(P);
3950b57cec5SDimitry Andric return false;
3960b57cec5SDimitry Andric }
3970b57cec5SDimitry Andric }
3980b57cec5SDimitry Andric
3990b57cec5SDimitry Andric // Check for proper use of auto-anded of predicate registers.
4000b57cec5SDimitry Andric for (const auto &I : LatePreds) {
4010b57cec5SDimitry Andric unsigned P = I;
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric if (LatePreds.count(P) > 1 || Defs.count(P)) {
4040b57cec5SDimitry Andric // Error out if predicate register defined "late" multiple times or
4050b57cec5SDimitry Andric // defined late and regularly defined
4060b57cec5SDimitry Andric // (e.g., "{ p3 = sp1loop0(...); p3 = cmp.eq(...) }".
4070b57cec5SDimitry Andric reportErrorRegisters(P);
4080b57cec5SDimitry Andric return false;
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric
4120b57cec5SDimitry Andric return true;
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric
4150b57cec5SDimitry Andric // Check legal use of new values.
checkNewValues()4160b57cec5SDimitry Andric bool HexagonMCChecker::checkNewValues() {
41704eeddc0SDimitry Andric for (auto const &ConsumerInst :
41804eeddc0SDimitry Andric HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
41904eeddc0SDimitry Andric if (!HexagonMCInstrInfo::isNewValue(MCII, ConsumerInst))
4200b57cec5SDimitry Andric continue;
42104eeddc0SDimitry Andric
42204eeddc0SDimitry Andric const HexagonMCInstrInfo::PredicateInfo ConsumerPredInfo =
42304eeddc0SDimitry Andric HexagonMCInstrInfo::predicateInfo(MCII, ConsumerInst);
42404eeddc0SDimitry Andric
42504eeddc0SDimitry Andric bool Branch = HexagonMCInstrInfo::getDesc(MCII, ConsumerInst).isBranch();
42604eeddc0SDimitry Andric MCOperand const &Op =
42704eeddc0SDimitry Andric HexagonMCInstrInfo::getNewValueOperand(MCII, ConsumerInst);
4280b57cec5SDimitry Andric assert(Op.isReg());
42904eeddc0SDimitry Andric
43004eeddc0SDimitry Andric auto Producer = registerProducer(Op.getReg(), ConsumerPredInfo);
43104eeddc0SDimitry Andric const MCInst *const ProducerInst = std::get<0>(Producer);
43204eeddc0SDimitry Andric const HexagonMCInstrInfo::PredicateInfo ProducerPredInfo =
43304eeddc0SDimitry Andric std::get<2>(Producer);
43404eeddc0SDimitry Andric
43504eeddc0SDimitry Andric if (ProducerInst == nullptr) {
43604eeddc0SDimitry Andric reportError(ConsumerInst.getLoc(),
43704eeddc0SDimitry Andric "New value register consumer has no producer");
4380b57cec5SDimitry Andric return false;
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric if (!RelaxNVChecks) {
4410b57cec5SDimitry Andric // Checks that statically prove correct new value consumption
44204eeddc0SDimitry Andric if (ProducerPredInfo.isPredicated() &&
44304eeddc0SDimitry Andric (!ConsumerPredInfo.isPredicated() ||
44404eeddc0SDimitry Andric llvm::HexagonMCInstrInfo::getType(MCII, ConsumerInst) ==
44504eeddc0SDimitry Andric HexagonII::TypeNCJ)) {
4460b57cec5SDimitry Andric reportNote(
44704eeddc0SDimitry Andric ProducerInst->getLoc(),
4480b57cec5SDimitry Andric "Register producer is predicated and consumer is unconditional");
44904eeddc0SDimitry Andric reportError(ConsumerInst.getLoc(),
4500b57cec5SDimitry Andric "Instruction does not have a valid new register producer");
4510b57cec5SDimitry Andric return false;
4520b57cec5SDimitry Andric }
45304eeddc0SDimitry Andric if (ProducerPredInfo.Register != Hexagon::NoRegister &&
45404eeddc0SDimitry Andric ProducerPredInfo.Register != ConsumerPredInfo.Register) {
45504eeddc0SDimitry Andric reportNote(ProducerInst->getLoc(),
4560b57cec5SDimitry Andric "Register producer does not use the same predicate "
4570b57cec5SDimitry Andric "register as the consumer");
45804eeddc0SDimitry Andric reportError(ConsumerInst.getLoc(),
4590b57cec5SDimitry Andric "Instruction does not have a valid new register producer");
4600b57cec5SDimitry Andric return false;
4610b57cec5SDimitry Andric }
4620b57cec5SDimitry Andric }
46304eeddc0SDimitry Andric if (ProducerPredInfo.Register == ConsumerPredInfo.Register &&
46404eeddc0SDimitry Andric ConsumerPredInfo.PredicatedTrue != ProducerPredInfo.PredicatedTrue) {
4650b57cec5SDimitry Andric reportNote(
46604eeddc0SDimitry Andric ProducerInst->getLoc(),
4670b57cec5SDimitry Andric "Register producer has the opposite predicate sense as consumer");
46804eeddc0SDimitry Andric reportError(ConsumerInst.getLoc(),
4690b57cec5SDimitry Andric "Instruction does not have a valid new register producer");
4700b57cec5SDimitry Andric return false;
4710b57cec5SDimitry Andric }
47204eeddc0SDimitry Andric
47304eeddc0SDimitry Andric MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, *ProducerInst);
47404eeddc0SDimitry Andric const unsigned ProducerOpIndex = std::get<1>(Producer);
47504eeddc0SDimitry Andric
476bdd1243dSDimitry Andric if (Desc.operands()[ProducerOpIndex].RegClass ==
4770b57cec5SDimitry Andric Hexagon::DoubleRegsRegClassID) {
47804eeddc0SDimitry Andric reportNote(ProducerInst->getLoc(),
4790b57cec5SDimitry Andric "Double registers cannot be new-value producers");
48004eeddc0SDimitry Andric reportError(ConsumerInst.getLoc(),
4810b57cec5SDimitry Andric "Instruction does not have a valid new register producer");
4820b57cec5SDimitry Andric return false;
4830b57cec5SDimitry Andric }
48404eeddc0SDimitry Andric
48504eeddc0SDimitry Andric // The ProducerOpIsMemIndex logic checks for the index of the producer
48604eeddc0SDimitry Andric // register operand. Z-reg load instructions have an implicit operand
48704eeddc0SDimitry Andric // that's not encoded, so the producer won't appear as the 1-th def, it
48804eeddc0SDimitry Andric // will be at the 0-th.
48904eeddc0SDimitry Andric const unsigned ProducerOpSearchIndex =
49004eeddc0SDimitry Andric (HexagonMCInstrInfo::getType(MCII, *ProducerInst) ==
49104eeddc0SDimitry Andric HexagonII::TypeCVI_ZW)
49204eeddc0SDimitry Andric ? 0
49304eeddc0SDimitry Andric : 1;
49404eeddc0SDimitry Andric
49504eeddc0SDimitry Andric const bool ProducerOpIsMemIndex =
49604eeddc0SDimitry Andric ((Desc.mayLoad() && ProducerOpIndex == ProducerOpSearchIndex) ||
49704eeddc0SDimitry Andric (Desc.mayStore() && ProducerOpIndex == 0));
49804eeddc0SDimitry Andric
49904eeddc0SDimitry Andric if (ProducerOpIsMemIndex) {
50004eeddc0SDimitry Andric unsigned Mode = HexagonMCInstrInfo::getAddrMode(MCII, *ProducerInst);
50104eeddc0SDimitry Andric
5020b57cec5SDimitry Andric StringRef ModeError;
5030b57cec5SDimitry Andric if (Mode == HexagonII::AbsoluteSet)
5040b57cec5SDimitry Andric ModeError = "Absolute-set";
5050b57cec5SDimitry Andric if (Mode == HexagonII::PostInc)
5060b57cec5SDimitry Andric ModeError = "Auto-increment";
5070b57cec5SDimitry Andric if (!ModeError.empty()) {
50804eeddc0SDimitry Andric reportNote(ProducerInst->getLoc(),
5090b57cec5SDimitry Andric ModeError + " registers cannot be a new-value "
5100b57cec5SDimitry Andric "producer");
51104eeddc0SDimitry Andric reportError(ConsumerInst.getLoc(),
5120b57cec5SDimitry Andric "Instruction does not have a valid new register producer");
5130b57cec5SDimitry Andric return false;
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric }
51604eeddc0SDimitry Andric if (Branch && HexagonMCInstrInfo::isFloat(MCII, *ProducerInst)) {
51704eeddc0SDimitry Andric reportNote(ProducerInst->getLoc(),
5180b57cec5SDimitry Andric "FPU instructions cannot be new-value producers for jumps");
51904eeddc0SDimitry Andric reportError(ConsumerInst.getLoc(),
5200b57cec5SDimitry Andric "Instruction does not have a valid new register producer");
5210b57cec5SDimitry Andric return false;
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric return true;
5250b57cec5SDimitry Andric }
5260b57cec5SDimitry Andric
checkRegistersReadOnly()5270b57cec5SDimitry Andric bool HexagonMCChecker::checkRegistersReadOnly() {
5280b57cec5SDimitry Andric for (auto I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
5290b57cec5SDimitry Andric MCInst const &Inst = *I.getInst();
5300b57cec5SDimitry Andric unsigned Defs = HexagonMCInstrInfo::getDesc(MCII, Inst).getNumDefs();
5310b57cec5SDimitry Andric for (unsigned j = 0; j < Defs; ++j) {
5320b57cec5SDimitry Andric MCOperand const &Operand = Inst.getOperand(j);
5330b57cec5SDimitry Andric assert(Operand.isReg() && "Def is not a register");
5340b57cec5SDimitry Andric unsigned Register = Operand.getReg();
5350b57cec5SDimitry Andric if (ReadOnly.find(Register) != ReadOnly.end()) {
5360b57cec5SDimitry Andric reportError(Inst.getLoc(), "Cannot write to read-only register `" +
5370b57cec5SDimitry Andric Twine(RI.getName(Register)) + "'");
5380b57cec5SDimitry Andric return false;
5390b57cec5SDimitry Andric }
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric }
5420b57cec5SDimitry Andric return true;
5430b57cec5SDimitry Andric }
5440b57cec5SDimitry Andric
registerUsed(unsigned Register)5450b57cec5SDimitry Andric bool HexagonMCChecker::registerUsed(unsigned Register) {
5460b57cec5SDimitry Andric for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB))
5470b57cec5SDimitry Andric for (unsigned j = HexagonMCInstrInfo::getDesc(MCII, I).getNumDefs(),
5480b57cec5SDimitry Andric n = I.getNumOperands();
5490b57cec5SDimitry Andric j < n; ++j) {
5500b57cec5SDimitry Andric MCOperand const &Operand = I.getOperand(j);
5510b57cec5SDimitry Andric if (Operand.isReg() && Operand.getReg() == Register)
5520b57cec5SDimitry Andric return true;
5530b57cec5SDimitry Andric }
5540b57cec5SDimitry Andric return false;
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric
5570b57cec5SDimitry Andric std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
registerProducer(unsigned Register,HexagonMCInstrInfo::PredicateInfo ConsumerPredicate)5580b57cec5SDimitry Andric HexagonMCChecker::registerProducer(
5590b57cec5SDimitry Andric unsigned Register, HexagonMCInstrInfo::PredicateInfo ConsumerPredicate) {
5600b57cec5SDimitry Andric std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
5610b57cec5SDimitry Andric WrongSense;
56204eeddc0SDimitry Andric
5630b57cec5SDimitry Andric for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
5640b57cec5SDimitry Andric MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, I);
5650b57cec5SDimitry Andric auto ProducerPredicate = HexagonMCInstrInfo::predicateInfo(MCII, I);
56604eeddc0SDimitry Andric
5670b57cec5SDimitry Andric for (unsigned J = 0, N = Desc.getNumDefs(); J < N; ++J)
5680b57cec5SDimitry Andric for (auto K = MCRegAliasIterator(I.getOperand(J).getReg(), &RI, true);
5690b57cec5SDimitry Andric K.isValid(); ++K)
5700b57cec5SDimitry Andric if (*K == Register) {
5710b57cec5SDimitry Andric if (RelaxNVChecks ||
5720b57cec5SDimitry Andric (ProducerPredicate.Register == ConsumerPredicate.Register &&
5730b57cec5SDimitry Andric (ProducerPredicate.Register == Hexagon::NoRegister ||
5740b57cec5SDimitry Andric ProducerPredicate.PredicatedTrue ==
5750b57cec5SDimitry Andric ConsumerPredicate.PredicatedTrue)))
5760b57cec5SDimitry Andric return std::make_tuple(&I, J, ProducerPredicate);
5770b57cec5SDimitry Andric std::get<0>(WrongSense) = &I;
5780b57cec5SDimitry Andric std::get<1>(WrongSense) = J;
5790b57cec5SDimitry Andric std::get<2>(WrongSense) = ProducerPredicate;
5800b57cec5SDimitry Andric }
5810b57cec5SDimitry Andric if (Register == Hexagon::VTMP && HexagonMCInstrInfo::hasTmpDst(MCII, I))
5820b57cec5SDimitry Andric return std::make_tuple(&I, 0, HexagonMCInstrInfo::PredicateInfo());
5830b57cec5SDimitry Andric }
5840b57cec5SDimitry Andric return WrongSense;
5850b57cec5SDimitry Andric }
5860b57cec5SDimitry Andric
checkRegisterCurDefs()5870b57cec5SDimitry Andric void HexagonMCChecker::checkRegisterCurDefs() {
5880b57cec5SDimitry Andric for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
5890b57cec5SDimitry Andric if (HexagonMCInstrInfo::isCVINew(MCII, I) &&
5900b57cec5SDimitry Andric HexagonMCInstrInfo::getDesc(MCII, I).mayLoad()) {
59104eeddc0SDimitry Andric const unsigned RegDef = I.getOperand(0).getReg();
59204eeddc0SDimitry Andric
59304eeddc0SDimitry Andric bool HasRegDefUse = false;
59404eeddc0SDimitry Andric for (MCRegAliasIterator Alias(RegDef, &RI, true); Alias.isValid();
59504eeddc0SDimitry Andric ++Alias)
59604eeddc0SDimitry Andric HasRegDefUse = HasRegDefUse || registerUsed(*Alias);
59704eeddc0SDimitry Andric
59804eeddc0SDimitry Andric if (!HasRegDefUse)
59904eeddc0SDimitry Andric reportWarning("Register `" + Twine(RI.getName(RegDef)) +
6000b57cec5SDimitry Andric "' used with `.cur' "
6010b57cec5SDimitry Andric "but not used in the same packet");
6020b57cec5SDimitry Andric }
6030b57cec5SDimitry Andric }
6040b57cec5SDimitry Andric }
6050b57cec5SDimitry Andric
6060b57cec5SDimitry Andric // Check for legal register uses and definitions.
checkRegisters()6070b57cec5SDimitry Andric bool HexagonMCChecker::checkRegisters() {
6080b57cec5SDimitry Andric // Check for proper register definitions.
6090b57cec5SDimitry Andric for (const auto &I : Defs) {
6100b57cec5SDimitry Andric unsigned R = I.first;
6110b57cec5SDimitry Andric
6120b57cec5SDimitry Andric if (isLoopRegister(R) && Defs.count(R) > 1 &&
6130b57cec5SDimitry Andric (HexagonMCInstrInfo::isInnerLoop(MCB) ||
6140b57cec5SDimitry Andric HexagonMCInstrInfo::isOuterLoop(MCB))) {
6150b57cec5SDimitry Andric // Error out for definitions of loop registers at the end of a loop.
6160b57cec5SDimitry Andric reportError("loop-setup and some branch instructions "
6170b57cec5SDimitry Andric "cannot be in the same packet");
6180b57cec5SDimitry Andric return false;
6190b57cec5SDimitry Andric }
6200b57cec5SDimitry Andric if (SoftDefs.count(R)) {
6210b57cec5SDimitry Andric // Error out for explicit changes to registers also weakly defined
6220b57cec5SDimitry Andric // (e.g., "{ usr = r0; r0 = sfadd(...) }").
6230b57cec5SDimitry Andric unsigned UsrR = Hexagon::USR; // Silence warning about mixed types in ?:.
6240b57cec5SDimitry Andric unsigned BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;
6250b57cec5SDimitry Andric reportErrorRegisters(BadR);
6260b57cec5SDimitry Andric return false;
6270b57cec5SDimitry Andric }
62804eeddc0SDimitry Andric if (!HexagonMCInstrInfo::isPredReg(RI, R) && Defs[R].size() > 1) {
6290b57cec5SDimitry Andric // Check for multiple register definitions.
6300b57cec5SDimitry Andric PredSet &PM = Defs[R];
6310b57cec5SDimitry Andric
6320b57cec5SDimitry Andric // Check for multiple unconditional register definitions.
6330b57cec5SDimitry Andric if (PM.count(Unconditional)) {
6340b57cec5SDimitry Andric // Error out on an unconditional change when there are any other
6350b57cec5SDimitry Andric // changes, conditional or not.
6360b57cec5SDimitry Andric unsigned UsrR = Hexagon::USR;
6370b57cec5SDimitry Andric unsigned BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;
6380b57cec5SDimitry Andric reportErrorRegisters(BadR);
6390b57cec5SDimitry Andric return false;
6400b57cec5SDimitry Andric }
6410b57cec5SDimitry Andric // Check for multiple conditional register definitions.
6420b57cec5SDimitry Andric for (const auto &J : PM) {
6430b57cec5SDimitry Andric PredSense P = J;
6440b57cec5SDimitry Andric
6450b57cec5SDimitry Andric // Check for multiple uses of the same condition.
6460b57cec5SDimitry Andric if (PM.count(P) > 1) {
6470b57cec5SDimitry Andric // Error out on conditional changes based on the same predicate
6480b57cec5SDimitry Andric // (e.g., "{ if (!p0) r0 =...; if (!p0) r0 =... }").
6490b57cec5SDimitry Andric reportErrorRegisters(R);
6500b57cec5SDimitry Andric return false;
6510b57cec5SDimitry Andric }
6520b57cec5SDimitry Andric // Check for the use of the complementary condition.
6530b57cec5SDimitry Andric P.second = !P.second;
6540b57cec5SDimitry Andric if (PM.count(P) && PM.size() > 2) {
6550b57cec5SDimitry Andric // Error out on conditional changes based on the same predicate
6560b57cec5SDimitry Andric // multiple times
6570b57cec5SDimitry Andric // (e.g., "if (p0) r0 =...; if (!p0) r0 =... }; if (!p0) r0 =...").
6580b57cec5SDimitry Andric reportErrorRegisters(R);
6590b57cec5SDimitry Andric return false;
6600b57cec5SDimitry Andric }
6610b57cec5SDimitry Andric }
6620b57cec5SDimitry Andric }
6630b57cec5SDimitry Andric }
6640b57cec5SDimitry Andric
6650b57cec5SDimitry Andric // Check for use of temporary definitions.
6660b57cec5SDimitry Andric for (const auto &I : TmpDefs) {
6670b57cec5SDimitry Andric unsigned R = I;
6680b57cec5SDimitry Andric
6690b57cec5SDimitry Andric if (!Uses.count(R)) {
6700b57cec5SDimitry Andric // special case for vhist
6710b57cec5SDimitry Andric bool vHistFound = false;
6720b57cec5SDimitry Andric for (auto const &HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) {
6730b57cec5SDimitry Andric if (HexagonMCInstrInfo::getType(MCII, *HMI.getInst()) ==
6740b57cec5SDimitry Andric HexagonII::TypeCVI_HIST) {
6750b57cec5SDimitry Andric vHistFound = true; // vhist() implicitly uses ALL REGxx.tmp
6760b57cec5SDimitry Andric break;
6770b57cec5SDimitry Andric }
6780b57cec5SDimitry Andric }
6790b57cec5SDimitry Andric // Warn on an unused temporary definition.
6800b57cec5SDimitry Andric if (!vHistFound) {
6810b57cec5SDimitry Andric reportWarning("register `" + Twine(RI.getName(R)) +
6820b57cec5SDimitry Andric "' used with `.tmp' but not used in the same packet");
6830b57cec5SDimitry Andric return true;
6840b57cec5SDimitry Andric }
6850b57cec5SDimitry Andric }
6860b57cec5SDimitry Andric }
6870b57cec5SDimitry Andric
6880b57cec5SDimitry Andric return true;
6890b57cec5SDimitry Andric }
6900b57cec5SDimitry Andric
6910b57cec5SDimitry Andric // Check for legal use of solo insns.
checkSolo()6920b57cec5SDimitry Andric bool HexagonMCChecker::checkSolo() {
6930b57cec5SDimitry Andric if (HexagonMCInstrInfo::bundleSize(MCB) > 1)
6940b57cec5SDimitry Andric for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
6950b57cec5SDimitry Andric if (HexagonMCInstrInfo::isSolo(MCII, I)) {
6960b57cec5SDimitry Andric reportError(I.getLoc(), "Instruction is marked `isSolo' and "
6970b57cec5SDimitry Andric "cannot have other instructions in "
6980b57cec5SDimitry Andric "the same packet");
6990b57cec5SDimitry Andric return false;
7000b57cec5SDimitry Andric }
7010b57cec5SDimitry Andric }
7020b57cec5SDimitry Andric
7030b57cec5SDimitry Andric return true;
7040b57cec5SDimitry Andric }
7050b57cec5SDimitry Andric
checkShuffle()7060b57cec5SDimitry Andric bool HexagonMCChecker::checkShuffle() {
7070b57cec5SDimitry Andric HexagonMCShuffler MCSDX(Context, ReportErrors, MCII, STI, MCB);
7080b57cec5SDimitry Andric return MCSDX.check();
7090b57cec5SDimitry Andric }
7100b57cec5SDimitry Andric
checkValidTmpDst()7110eae32dcSDimitry Andric bool HexagonMCChecker::checkValidTmpDst() {
712*06c3fb27SDimitry Andric if (!STI.hasFeature(Hexagon::ArchV69)) {
7130eae32dcSDimitry Andric return true;
7140eae32dcSDimitry Andric }
7150eae32dcSDimitry Andric auto HasTmp = [&](MCInst const &I) {
7160eae32dcSDimitry Andric return HexagonMCInstrInfo::hasTmpDst(MCII, I) ||
7170eae32dcSDimitry Andric HexagonMCInstrInfo::hasHvxTmp(MCII, I);
7180eae32dcSDimitry Andric };
7190eae32dcSDimitry Andric unsigned HasTmpCount =
7200eae32dcSDimitry Andric llvm::count_if(HexagonMCInstrInfo::bundleInstructions(MCII, MCB), HasTmp);
7210eae32dcSDimitry Andric
7220eae32dcSDimitry Andric if (HasTmpCount > 1) {
7230eae32dcSDimitry Andric reportError(
7240eae32dcSDimitry Andric MCB.getLoc(),
7250eae32dcSDimitry Andric "this packet has more than one HVX vtmp/.tmp destination instruction");
7260eae32dcSDimitry Andric
7270eae32dcSDimitry Andric for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB))
7280eae32dcSDimitry Andric if (HasTmp(I))
7290eae32dcSDimitry Andric reportNote(I.getLoc(),
7300eae32dcSDimitry Andric "this is an HVX vtmp/.tmp destination instruction");
7310eae32dcSDimitry Andric
7320eae32dcSDimitry Andric return false;
7330eae32dcSDimitry Andric }
7340eae32dcSDimitry Andric return true;
7350eae32dcSDimitry Andric }
7360eae32dcSDimitry Andric
compoundRegisterMap(unsigned & Register)7370b57cec5SDimitry Andric void HexagonMCChecker::compoundRegisterMap(unsigned &Register) {
7380b57cec5SDimitry Andric switch (Register) {
7390b57cec5SDimitry Andric default:
7400b57cec5SDimitry Andric break;
7410b57cec5SDimitry Andric case Hexagon::R15:
7420b57cec5SDimitry Andric Register = Hexagon::R23;
7430b57cec5SDimitry Andric break;
7440b57cec5SDimitry Andric case Hexagon::R14:
7450b57cec5SDimitry Andric Register = Hexagon::R22;
7460b57cec5SDimitry Andric break;
7470b57cec5SDimitry Andric case Hexagon::R13:
7480b57cec5SDimitry Andric Register = Hexagon::R21;
7490b57cec5SDimitry Andric break;
7500b57cec5SDimitry Andric case Hexagon::R12:
7510b57cec5SDimitry Andric Register = Hexagon::R20;
7520b57cec5SDimitry Andric break;
7530b57cec5SDimitry Andric case Hexagon::R11:
7540b57cec5SDimitry Andric Register = Hexagon::R19;
7550b57cec5SDimitry Andric break;
7560b57cec5SDimitry Andric case Hexagon::R10:
7570b57cec5SDimitry Andric Register = Hexagon::R18;
7580b57cec5SDimitry Andric break;
7590b57cec5SDimitry Andric case Hexagon::R9:
7600b57cec5SDimitry Andric Register = Hexagon::R17;
7610b57cec5SDimitry Andric break;
7620b57cec5SDimitry Andric case Hexagon::R8:
7630b57cec5SDimitry Andric Register = Hexagon::R16;
7640b57cec5SDimitry Andric break;
7650b57cec5SDimitry Andric }
7660b57cec5SDimitry Andric }
7670b57cec5SDimitry Andric
reportErrorRegisters(unsigned Register)7680b57cec5SDimitry Andric void HexagonMCChecker::reportErrorRegisters(unsigned Register) {
7690b57cec5SDimitry Andric reportError("register `" + Twine(RI.getName(Register)) +
7700b57cec5SDimitry Andric "' modified more than once");
7710b57cec5SDimitry Andric }
7720b57cec5SDimitry Andric
reportErrorNewValue(unsigned Register)7730b57cec5SDimitry Andric void HexagonMCChecker::reportErrorNewValue(unsigned Register) {
7740b57cec5SDimitry Andric reportError("register `" + Twine(RI.getName(Register)) +
7750b57cec5SDimitry Andric "' used with `.new' "
7760b57cec5SDimitry Andric "but not validly modified in the same packet");
7770b57cec5SDimitry Andric }
7780b57cec5SDimitry Andric
reportError(Twine const & Msg)7790b57cec5SDimitry Andric void HexagonMCChecker::reportError(Twine const &Msg) {
7800b57cec5SDimitry Andric reportError(MCB.getLoc(), Msg);
7810b57cec5SDimitry Andric }
7820b57cec5SDimitry Andric
reportError(SMLoc Loc,Twine const & Msg)7830b57cec5SDimitry Andric void HexagonMCChecker::reportError(SMLoc Loc, Twine const &Msg) {
7840b57cec5SDimitry Andric if (ReportErrors)
7850b57cec5SDimitry Andric Context.reportError(Loc, Msg);
7860b57cec5SDimitry Andric }
7870b57cec5SDimitry Andric
reportNote(SMLoc Loc,llvm::Twine const & Msg)7880b57cec5SDimitry Andric void HexagonMCChecker::reportNote(SMLoc Loc, llvm::Twine const &Msg) {
7890b57cec5SDimitry Andric if (ReportErrors) {
7900b57cec5SDimitry Andric auto SM = Context.getSourceManager();
7910b57cec5SDimitry Andric if (SM)
7920b57cec5SDimitry Andric SM->PrintMessage(Loc, SourceMgr::DK_Note, Msg);
7930b57cec5SDimitry Andric }
7940b57cec5SDimitry Andric }
7950b57cec5SDimitry Andric
reportWarning(Twine const & Msg)7960b57cec5SDimitry Andric void HexagonMCChecker::reportWarning(Twine const &Msg) {
7978bcb0991SDimitry Andric if (ReportErrors)
7988bcb0991SDimitry Andric Context.reportWarning(MCB.getLoc(), Msg);
7990b57cec5SDimitry Andric }
8005ffd83dbSDimitry Andric
checkLegalVecRegPair()8015ffd83dbSDimitry Andric bool HexagonMCChecker::checkLegalVecRegPair() {
802*06c3fb27SDimitry Andric const bool IsPermitted = STI.hasFeature(Hexagon::ArchV67);
8035ffd83dbSDimitry Andric const bool HasReversePairs = ReversePairs.size() != 0;
8045ffd83dbSDimitry Andric
8055ffd83dbSDimitry Andric if (!IsPermitted && HasReversePairs) {
8065ffd83dbSDimitry Andric for (auto R : ReversePairs)
8075ffd83dbSDimitry Andric reportError("register pair `" + Twine(RI.getName(R)) +
8085ffd83dbSDimitry Andric "' is not permitted for this architecture");
8095ffd83dbSDimitry Andric return false;
8105ffd83dbSDimitry Andric }
8115ffd83dbSDimitry Andric return true;
8125ffd83dbSDimitry Andric }
81304eeddc0SDimitry Andric
81404eeddc0SDimitry Andric // Vd.tmp can't be accumulated
checkHVXAccum()81504eeddc0SDimitry Andric bool HexagonMCChecker::checkHVXAccum()
81604eeddc0SDimitry Andric {
81704eeddc0SDimitry Andric for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
81804eeddc0SDimitry Andric bool IsTarget =
81904eeddc0SDimitry Andric HexagonMCInstrInfo::isAccumulator(MCII, I) && I.getOperand(0).isReg();
82004eeddc0SDimitry Andric if (!IsTarget)
82104eeddc0SDimitry Andric continue;
82204eeddc0SDimitry Andric unsigned int R = I.getOperand(0).getReg();
82304eeddc0SDimitry Andric TmpDefsIterator It = TmpDefs.find(R);
82404eeddc0SDimitry Andric if (It != TmpDefs.end()) {
82504eeddc0SDimitry Andric reportError("register `" + Twine(RI.getName(R)) + ".tmp" +
82604eeddc0SDimitry Andric "' is accumulated in this packet");
82704eeddc0SDimitry Andric return false;
82804eeddc0SDimitry Andric }
82904eeddc0SDimitry Andric }
83004eeddc0SDimitry Andric return true;
83104eeddc0SDimitry Andric }
832