mirror of
https://github.com/RPCS3/llvm.git
synced 2025-03-04 00:29:28 +00:00
[Hexagon] Improve shuffle error reporting
Patch by Colin LeMahieu. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301823 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2e6f882a8d
commit
83ab9dc04d
@ -459,94 +459,16 @@ bool HexagonAsmParser::finishBundle(SMLoc IDLoc, MCStreamer &Out) {
|
||||
DEBUG(MCB.dump_pretty(dbgs()));
|
||||
DEBUG(dbgs() << "--\n");
|
||||
|
||||
MCB.setLoc(IDLoc);
|
||||
// Check the bundle for errors.
|
||||
const MCRegisterInfo *RI = getContext().getRegisterInfo();
|
||||
HexagonMCChecker Check(MCII, getSTI(), MCB, MCB, *RI);
|
||||
HexagonMCChecker Check(getContext(), MCII, getSTI(), MCB, *RI);
|
||||
|
||||
bool CheckOk = HexagonMCInstrInfo::canonicalizePacket(MCII, getSTI(),
|
||||
getContext(), MCB,
|
||||
&Check);
|
||||
|
||||
while (Check.getNextErrInfo()) {
|
||||
unsigned Reg = Check.getErrRegister();
|
||||
Twine R(RI->getName(Reg));
|
||||
|
||||
uint64_t Err = Check.getError();
|
||||
if (Err != HexagonMCErrInfo::CHECK_SUCCESS) {
|
||||
if (HexagonMCErrInfo::CHECK_ERROR_BRANCHES & Err)
|
||||
return Error(
|
||||
IDLoc,
|
||||
"unconditional branch cannot precede another branch in packet");
|
||||
|
||||
if (HexagonMCErrInfo::CHECK_ERROR_NEWP & Err ||
|
||||
HexagonMCErrInfo::CHECK_ERROR_NEWV & Err)
|
||||
return Error(IDLoc, "register `" + R +
|
||||
"' used with `.new' "
|
||||
"but not validly modified in the same packet");
|
||||
|
||||
if (HexagonMCErrInfo::CHECK_ERROR_REGISTERS & Err)
|
||||
return Error(IDLoc, "register `" + R + "' modified more than once");
|
||||
|
||||
if (HexagonMCErrInfo::CHECK_ERROR_READONLY & Err)
|
||||
return Error(IDLoc, "cannot write to read-only register `" + R + "'");
|
||||
|
||||
if (HexagonMCErrInfo::CHECK_ERROR_LOOP & Err)
|
||||
return Error(IDLoc, "loop-setup and some branch instructions "
|
||||
"cannot be in the same packet");
|
||||
|
||||
if (HexagonMCErrInfo::CHECK_ERROR_ENDLOOP & Err) {
|
||||
Twine N(HexagonMCInstrInfo::isInnerLoop(MCB) ? '0' : '1');
|
||||
return Error(IDLoc,
|
||||
"packet marked with `:endloop" + N + "' " +
|
||||
"cannot contain instructions that modify register " +
|
||||
"`" + R + "'");
|
||||
}
|
||||
|
||||
if (HexagonMCErrInfo::CHECK_ERROR_SOLO & Err)
|
||||
return Error(
|
||||
IDLoc,
|
||||
"instruction cannot appear in packet with other instructions");
|
||||
|
||||
if (HexagonMCErrInfo::CHECK_ERROR_NOSLOTS & Err)
|
||||
return Error(IDLoc, "too many slots used in packet");
|
||||
|
||||
if (Err & HexagonMCErrInfo::CHECK_ERROR_SHUFFLE) {
|
||||
uint64_t Erm = Check.getShuffleError();
|
||||
|
||||
if (HexagonShuffler::SHUFFLE_ERROR_INVALID == Erm)
|
||||
return Error(IDLoc, "invalid instruction packet");
|
||||
else if (HexagonShuffler::SHUFFLE_ERROR_STORES == Erm)
|
||||
return Error(IDLoc, "invalid instruction packet: too many stores");
|
||||
else if (HexagonShuffler::SHUFFLE_ERROR_LOADS == Erm)
|
||||
return Error(IDLoc, "invalid instruction packet: too many loads");
|
||||
else if (HexagonShuffler::SHUFFLE_ERROR_BRANCHES == Erm)
|
||||
return Error(IDLoc, "too many branches in packet");
|
||||
else if (HexagonShuffler::SHUFFLE_ERROR_NOSLOTS == Erm)
|
||||
return Error(IDLoc, "invalid instruction packet: out of slots");
|
||||
else if (HexagonShuffler::SHUFFLE_ERROR_SLOTS == Erm)
|
||||
return Error(IDLoc, "invalid instruction packet: slot error");
|
||||
else if (HexagonShuffler::SHUFFLE_ERROR_ERRATA2 == Erm)
|
||||
return Error(IDLoc, "v60 packet violation");
|
||||
else if (HexagonShuffler::SHUFFLE_ERROR_STORE_LOAD_CONFLICT == Erm)
|
||||
return Error(IDLoc, "slot 0 instruction does not allow slot 1 store");
|
||||
else
|
||||
return Error(IDLoc, "unknown error in instruction packet");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Warn = Check.getWarning();
|
||||
if (Warn != HexagonMCErrInfo::CHECK_SUCCESS) {
|
||||
if (HexagonMCErrInfo::CHECK_WARN_CURRENT & Warn)
|
||||
Warning(IDLoc, "register `" + R + "' used with `.cur' "
|
||||
"but not used in the same packet");
|
||||
else if (HexagonMCErrInfo::CHECK_WARN_TEMPORARY & Warn)
|
||||
Warning(IDLoc, "register `" + R + "' used with `.tmp' "
|
||||
"but not used in the same packet");
|
||||
}
|
||||
}
|
||||
|
||||
if (CheckOk) {
|
||||
MCB.setLoc(IDLoc);
|
||||
if (HexagonMCInstrInfo::bundleSize(MCB) == 0) {
|
||||
assert(!HexagonMCInstrInfo::isInnerLoop(MCB));
|
||||
assert(!HexagonMCInstrInfo::isOuterLoop(MCB));
|
||||
|
@ -191,7 +191,8 @@ DecodeStatus HexagonDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
|
||||
return Result;
|
||||
if (Size > HEXAGON_MAX_PACKET_SIZE)
|
||||
return MCDisassembler::Fail;
|
||||
HexagonMCChecker Checker(*MCII, STI, MI, MI, *getContext().getRegisterInfo());
|
||||
HexagonMCChecker Checker(getContext(), *MCII, STI, MI,
|
||||
*getContext().getRegisterInfo(), false);
|
||||
if (!Checker.check())
|
||||
return MCDisassembler::Fail;
|
||||
return MCDisassembler::Success;
|
||||
|
@ -58,6 +58,7 @@ class HexagonAsmBackend : public MCAsmBackend {
|
||||
RF.getContents() = Code;
|
||||
RF.getFixups() = Fixups;
|
||||
}
|
||||
|
||||
public:
|
||||
HexagonAsmBackend(const Target &T, const Triple &TT, uint8_t OSABI,
|
||||
StringRef CPU) :
|
||||
@ -711,22 +712,24 @@ public:
|
||||
break;
|
||||
}
|
||||
case MCFragment::FT_Relaxable: {
|
||||
MCContext &Context = Asm.getContext();
|
||||
auto &RF = cast<MCRelaxableFragment>(*K);
|
||||
auto &Inst = const_cast<MCInst &>(RF.getInst());
|
||||
while (Size > 0 && HexagonMCInstrInfo::bundleSize(Inst) < 4) {
|
||||
MCInst *Nop = new (Asm.getContext()) MCInst;
|
||||
MCInst *Nop = new (Context) MCInst;
|
||||
Nop->setOpcode(Hexagon::A2_nop);
|
||||
Inst.addOperand(MCOperand::createInst(Nop));
|
||||
Size -= 4;
|
||||
if (!HexagonMCChecker(
|
||||
*MCII, RF.getSubtargetInfo(), Inst, Inst,
|
||||
*Asm.getContext().getRegisterInfo()).check()) {
|
||||
Context, *MCII, RF.getSubtargetInfo(), Inst,
|
||||
*Context.getRegisterInfo(), false)
|
||||
.check()) {
|
||||
Inst.erase(Inst.end() - 1);
|
||||
Size = 0;
|
||||
}
|
||||
}
|
||||
bool Error = HexagonMCShuffle(true, *MCII, RF.getSubtargetInfo(),
|
||||
Inst);
|
||||
bool Error = HexagonMCShuffle(Context, true, *MCII,
|
||||
RF.getSubtargetInfo(), Inst);
|
||||
//assert(!Error);
|
||||
(void)Error;
|
||||
ReplaceInstruction(Asm.getEmitter(), RF, Inst);
|
||||
|
@ -16,19 +16,22 @@
|
||||
|
||||
#include "HexagonBaseInfo.h"
|
||||
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCInstrDesc.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool> RelaxNVChecks("relax-nv-checks", cl::init(false),
|
||||
cl::ZeroOrMore, cl::Hidden, cl::desc("Relax checks of new-value validity"));
|
||||
static cl::opt<bool>
|
||||
RelaxNVChecks("relax-nv-checks", cl::init(false), cl::ZeroOrMore,
|
||||
cl::Hidden, cl::desc("Relax checks of new-value validity"));
|
||||
|
||||
const HexagonMCChecker::PredSense
|
||||
HexagonMCChecker::Unconditional(Hexagon::NoRegister, false);
|
||||
HexagonMCChecker::Unconditional(Hexagon::NoRegister, false);
|
||||
|
||||
void HexagonMCChecker::init() {
|
||||
// Initialize read-only registers set.
|
||||
@ -46,13 +49,12 @@ void HexagonMCChecker::init() {
|
||||
|
||||
if (HexagonMCInstrInfo::isBundle(MCB))
|
||||
// Unfurl a bundle.
|
||||
for (auto const&I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
MCInst const &Inst = *I.getInst();
|
||||
if (HexagonMCInstrInfo::isDuplex(MCII, Inst)) {
|
||||
init(*Inst.getOperand(0).getInst());
|
||||
init(*Inst.getOperand(1).getInst());
|
||||
}
|
||||
else
|
||||
} else
|
||||
init(Inst);
|
||||
}
|
||||
else
|
||||
@ -69,20 +71,18 @@ void HexagonMCChecker::initReg(MCInst const &MCI, unsigned R, unsigned &PredReg,
|
||||
// Note use of new predicate register.
|
||||
if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI))
|
||||
NewPreds.insert(PredReg);
|
||||
}
|
||||
else
|
||||
} else
|
||||
// Note register use. Super-registers are not tracked directly,
|
||||
// but their components.
|
||||
for(MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
|
||||
SRI.isValid();
|
||||
++SRI)
|
||||
for (MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
|
||||
SRI.isValid(); ++SRI)
|
||||
if (!MCSubRegIterator(*SRI, &RI).isValid())
|
||||
// Skip super-registers used indirectly.
|
||||
Uses.insert(*SRI);
|
||||
}
|
||||
|
||||
void HexagonMCChecker::init(MCInst const& MCI) {
|
||||
const MCInstrDesc& MCID = HexagonMCInstrInfo::getDesc(MCII, MCI);
|
||||
void HexagonMCChecker::init(MCInst const &MCI) {
|
||||
const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MCI);
|
||||
unsigned PredReg = Hexagon::NoRegister;
|
||||
bool isTrue = false;
|
||||
|
||||
@ -109,10 +109,10 @@ void HexagonMCChecker::init(MCInst const& MCI) {
|
||||
|
||||
if (Hexagon::USR_OVF == R)
|
||||
// Many insns change the USR implicitly, but only one or another flag.
|
||||
// The instruction table models the USR.OVF flag, which can be implicitly
|
||||
// modified more than once, but cannot be modified in the same packet
|
||||
// with an instruction that modifies is explicitly. Deal with such situ-
|
||||
// ations individually.
|
||||
// The instruction table models the USR.OVF flag, which can be
|
||||
// implicitly modified more than once, but cannot be modified in the
|
||||
// same packet with an instruction that modifies is explicitly. Deal
|
||||
// with such situ- ations individually.
|
||||
SoftDefs.insert(R);
|
||||
else if (isPredicateRegister(R) &&
|
||||
HexagonMCInstrInfo::isPredicateLate(MCII, MCI))
|
||||
@ -124,8 +124,7 @@ void HexagonMCChecker::init(MCInst const& MCI) {
|
||||
|
||||
// Figure out explicit register definitions.
|
||||
for (unsigned i = 0; i < MCID.getNumDefs(); ++i) {
|
||||
unsigned R = MCI.getOperand(i).getReg(),
|
||||
S = Hexagon::NoRegister;
|
||||
unsigned R = MCI.getOperand(i).getReg(), S = Hexagon::NoRegister;
|
||||
// USR has subregisters (while C8 does not for technical reasons), so
|
||||
// reset R to USR, since we know how to handle multiple defs of USR,
|
||||
// taking into account its subregisters.
|
||||
@ -134,9 +133,8 @@ void HexagonMCChecker::init(MCInst const& MCI) {
|
||||
|
||||
// Note register definitions, direct ones as well as indirect side-effects.
|
||||
// Super-registers are not tracked directly, but their components.
|
||||
for(MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
|
||||
SRI.isValid();
|
||||
++SRI) {
|
||||
for (MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
|
||||
SRI.isValid(); ++SRI) {
|
||||
if (MCSubRegIterator(*SRI, &RI).isValid())
|
||||
// Skip super-registers defined indirectly.
|
||||
continue;
|
||||
@ -156,22 +154,25 @@ void HexagonMCChecker::init(MCInst const& MCI) {
|
||||
// Only an explicit definition of P3:0 is noted as such; if a
|
||||
// side-effect, then note as a soft definition.
|
||||
SoftDefs.insert(*SRI);
|
||||
else if (HexagonMCInstrInfo::isPredicateLate(MCII, MCI) && isPredicateRegister(*SRI))
|
||||
else if (HexagonMCInstrInfo::isPredicateLate(MCII, MCI) &&
|
||||
isPredicateRegister(*SRI))
|
||||
// Some insns produce predicates too late to be used in the same packet.
|
||||
LatePreds.insert(*SRI);
|
||||
else if (i == 0 && llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCVI_VM_CUR_LD)
|
||||
else if (i == 0 && llvm::HexagonMCInstrInfo::getType(MCII, MCI) ==
|
||||
HexagonII::TypeCVI_VM_CUR_LD)
|
||||
// Current loads should be used in the same packet.
|
||||
// TODO: relies on the impossibility of a current and a temporary loads
|
||||
// in the same packet.
|
||||
CurDefs.insert(*SRI), Defs[*SRI].insert(PredSense(PredReg, isTrue));
|
||||
else if (i == 0 && llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCVI_VM_TMP_LD)
|
||||
else if (i == 0 && llvm::HexagonMCInstrInfo::getType(MCII, MCI) ==
|
||||
HexagonII::TypeCVI_VM_TMP_LD)
|
||||
// Temporary loads should be used in the same packet, but don't commit
|
||||
// results, so it should be disregarded if another insn changes the same
|
||||
// register.
|
||||
// TODO: relies on the impossibility of a current and a temporary loads
|
||||
// in the same packet.
|
||||
TmpDefs.insert(*SRI);
|
||||
else if (i <= 1 && llvm::HexagonMCInstrInfo::hasNewValue2(MCII, MCI) )
|
||||
else if (i <= 1 && llvm::HexagonMCInstrInfo::hasNewValue2(MCII, MCI))
|
||||
// vshuff(Vx, Vy, Rx) <- Vx(0) and Vy(1) are both source and
|
||||
// destination registers with this instruction. same for vdeal(Vx,Vy,Rx)
|
||||
Uses.insert(*SRI);
|
||||
@ -187,25 +188,26 @@ void HexagonMCChecker::init(MCInst const& MCI) {
|
||||
if (HexagonMCInstrInfo::isCompound(MCII, MCI))
|
||||
compoundRegisterMap(R); // Compound insns have a limited register range.
|
||||
|
||||
for(MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
|
||||
SRI.isValid();
|
||||
++SRI)
|
||||
for (MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
|
||||
SRI.isValid(); ++SRI)
|
||||
if (!MCSubRegIterator(*SRI, &RI).isValid())
|
||||
// No super-registers defined indirectly.
|
||||
NewDefs[*SRI].push_back(NewSense::Def(PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI),
|
||||
HexagonMCInstrInfo::isFloat(MCII, MCI)));
|
||||
NewDefs[*SRI].push_back(NewSense::Def(
|
||||
PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI),
|
||||
HexagonMCInstrInfo::isFloat(MCII, MCI)));
|
||||
|
||||
// For fairly unique 2-dot-new producers, example:
|
||||
// vdeal(V1, V9, R0) V1.new and V9.new can be used by consumers.
|
||||
if (HexagonMCInstrInfo::hasNewValue2(MCII, MCI)) {
|
||||
unsigned R2 = HexagonMCInstrInfo::getNewValueOperand2(MCII, MCI).getReg();
|
||||
|
||||
for(MCRegAliasIterator SRI(R2, &RI, !MCSubRegIterator(R2, &RI).isValid());
|
||||
SRI.isValid();
|
||||
++SRI)
|
||||
for (MCRegAliasIterator SRI(R2, &RI,
|
||||
!MCSubRegIterator(R2, &RI).isValid());
|
||||
SRI.isValid(); ++SRI)
|
||||
if (!MCSubRegIterator(*SRI, &RI).isValid())
|
||||
NewDefs[*SRI].push_back(NewSense::Def(PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI),
|
||||
HexagonMCInstrInfo::isFloat(MCII, MCI)));
|
||||
NewDefs[*SRI].push_back(NewSense::Def(
|
||||
PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI),
|
||||
HexagonMCInstrInfo::isFloat(MCII, MCI)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,18 +229,19 @@ void HexagonMCChecker::init(MCInst const& MCI) {
|
||||
// Super-registers cannot use new values.
|
||||
if (MCID.isBranch())
|
||||
NewUses[N] = NewSense::Jmp(
|
||||
llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNCJ);
|
||||
llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNCJ);
|
||||
else
|
||||
NewUses[N] = NewSense::Use(
|
||||
PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI));
|
||||
PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HexagonMCChecker::HexagonMCChecker(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst &mcb, MCInst &mcbdx,
|
||||
MCRegisterInfo const &ri)
|
||||
: MCB(mcb), MCBDX(mcbdx), RI(ri), MCII(MCII), STI(STI),
|
||||
bLoadErrInfo(false) {
|
||||
HexagonMCChecker::HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &mcb,
|
||||
MCRegisterInfo const &ri, bool ReportErrors)
|
||||
: Context(Context), MCB(mcb), RI(ri), MCII(MCII), STI(STI),
|
||||
ReportErrors(ReportErrors) {
|
||||
init();
|
||||
}
|
||||
|
||||
@ -250,21 +253,19 @@ bool HexagonMCChecker::check(bool FullCheck) {
|
||||
bool chkS = checkSolo();
|
||||
bool chkSh = true;
|
||||
if (FullCheck)
|
||||
chkSh = checkShuffle();
|
||||
chkSh = checkShuffle();
|
||||
bool chkSl = true;
|
||||
if (FullCheck)
|
||||
chkSl = checkSlots();
|
||||
chkSl = checkSlots();
|
||||
bool chk = chkB && chkP && chkNV && chkR && chkS && chkSh && chkSl;
|
||||
|
||||
return chk;
|
||||
}
|
||||
|
||||
bool HexagonMCChecker::checkSlots()
|
||||
|
||||
{
|
||||
bool HexagonMCChecker::checkSlots() {
|
||||
unsigned slotsUsed = 0;
|
||||
for (auto HMI: HexagonMCInstrInfo::bundleInstructions(MCBDX)) {
|
||||
MCInst const& MCI = *HMI.getInst();
|
||||
for (auto HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
MCInst const &MCI = *HMI.getInst();
|
||||
if (HexagonMCInstrInfo::isImmext(MCI))
|
||||
continue;
|
||||
if (HexagonMCInstrInfo::isDuplex(MCII, MCI))
|
||||
@ -274,9 +275,7 @@ bool HexagonMCChecker::checkSlots()
|
||||
}
|
||||
|
||||
if (slotsUsed > HEXAGON_PACKET_SIZE) {
|
||||
HexagonMCErrInfo errInfo;
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_NOSLOTS);
|
||||
addErrInfo(errInfo);
|
||||
reportError("invalid instruction packet: out of slots");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -284,11 +283,9 @@ bool HexagonMCChecker::checkSlots()
|
||||
|
||||
// Check legal use of branches.
|
||||
bool HexagonMCChecker::checkBranches() {
|
||||
HexagonMCErrInfo errInfo;
|
||||
if (HexagonMCInstrInfo::isBundle(MCB)) {
|
||||
bool hasConditional = false;
|
||||
unsigned Branches = 0,
|
||||
Conditional = HEXAGON_PRESHUFFLE_PACKET_SIZE,
|
||||
unsigned Branches = 0, Conditional = HEXAGON_PRESHUFFLE_PACKET_SIZE,
|
||||
Unconditional = HEXAGON_PRESHUFFLE_PACKET_SIZE;
|
||||
|
||||
for (unsigned i = HexagonMCInstrInfo::bundleInstructionsOffset;
|
||||
@ -314,16 +311,18 @@ bool HexagonMCChecker::checkBranches() {
|
||||
if (HexagonMCInstrInfo::isInnerLoop(MCB) ||
|
||||
HexagonMCInstrInfo::isOuterLoop(MCB)) {
|
||||
// Error out if there's any branch in a loop-end packet.
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_ENDLOOP, Hexagon::PC);
|
||||
addErrInfo(errInfo);
|
||||
Twine N(HexagonMCInstrInfo::isInnerLoop(MCB) ? '0' : '1');
|
||||
reportError("packet marked with `:endloop" + N + "' " +
|
||||
"cannot contain instructions that modify register " + "`" +
|
||||
llvm::Twine(RI.getName(Hexagon::PC)) + "'");
|
||||
return false;
|
||||
}
|
||||
if (Branches > 1)
|
||||
if (!hasConditional || Conditional > Unconditional) {
|
||||
// Error out if more than one unconditional branch or
|
||||
// the conditional branch appears after the unconditional one.
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_BRANCHES);
|
||||
addErrInfo(errInfo);
|
||||
reportError(
|
||||
"unconditional branch cannot precede another branch in packet");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -333,31 +332,28 @@ bool HexagonMCChecker::checkBranches() {
|
||||
|
||||
// Check legal use of predicate registers.
|
||||
bool HexagonMCChecker::checkPredicates() {
|
||||
HexagonMCErrInfo errInfo;
|
||||
// Check for proper use of new predicate registers.
|
||||
for (const auto& I : NewPreds) {
|
||||
for (const auto &I : NewPreds) {
|
||||
unsigned P = I;
|
||||
|
||||
if (!Defs.count(P) || LatePreds.count(P)) {
|
||||
// Error out if the new predicate register is not defined,
|
||||
// or defined "late"
|
||||
// (e.g., "{ if (p3.new)... ; p3 = sp1loop0(#r7:2, Rs) }").
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_NEWP, P);
|
||||
addErrInfo(errInfo);
|
||||
reportErrorNewValue(P);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for proper use of auto-anded of predicate registers.
|
||||
for (const auto& I : LatePreds) {
|
||||
for (const auto &I : LatePreds) {
|
||||
unsigned P = I;
|
||||
|
||||
if (LatePreds.count(P) > 1 || Defs.count(P)) {
|
||||
// Error out if predicate register defined "late" multiple times or
|
||||
// defined late and regularly defined
|
||||
// (e.g., "{ p3 = sp1loop0(...); p3 = cmp.eq(...) }".
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_REGISTERS, P);
|
||||
addErrInfo(errInfo);
|
||||
reportErrorRegisters(P);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -367,15 +363,12 @@ bool HexagonMCChecker::checkPredicates() {
|
||||
|
||||
// Check legal use of new values.
|
||||
bool HexagonMCChecker::checkNewValues() {
|
||||
HexagonMCErrInfo errInfo;
|
||||
memset(&errInfo, 0, sizeof(errInfo));
|
||||
for (auto& I : NewUses) {
|
||||
for (auto &I : NewUses) {
|
||||
unsigned R = I.first;
|
||||
NewSense &US = I.second;
|
||||
|
||||
if (!hasValidNewValueDef(US, NewDefs[R])) {
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_NEWV, R);
|
||||
addErrInfo(errInfo);
|
||||
reportErrorNewValue(R);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -385,23 +378,22 @@ bool HexagonMCChecker::checkNewValues() {
|
||||
|
||||
// Check for legal register uses and definitions.
|
||||
bool HexagonMCChecker::checkRegisters() {
|
||||
HexagonMCErrInfo errInfo;
|
||||
// Check for proper register definitions.
|
||||
for (const auto& I : Defs) {
|
||||
for (const auto &I : Defs) {
|
||||
unsigned R = I.first;
|
||||
|
||||
if (ReadOnly.count(R)) {
|
||||
// Error out for definitions of read-only registers.
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_READONLY, R);
|
||||
addErrInfo(errInfo);
|
||||
reportError("cannot write to read-only register `" +
|
||||
llvm::Twine(RI.getName(R)) + "'");
|
||||
return false;
|
||||
}
|
||||
if (isLoopRegister(R) && Defs.count(R) > 1 &&
|
||||
(HexagonMCInstrInfo::isInnerLoop(MCB) ||
|
||||
HexagonMCInstrInfo::isOuterLoop(MCB))) {
|
||||
// Error out for definitions of loop registers at the end of a loop.
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_LOOP, R);
|
||||
addErrInfo(errInfo);
|
||||
reportError("loop-setup and some branch instructions "
|
||||
"cannot be in the same packet");
|
||||
return false;
|
||||
}
|
||||
if (SoftDefs.count(R)) {
|
||||
@ -409,8 +401,7 @@ bool HexagonMCChecker::checkRegisters() {
|
||||
// (e.g., "{ usr = r0; r0 = sfadd(...) }").
|
||||
unsigned UsrR = Hexagon::USR; // Silence warning about mixed types in ?:.
|
||||
unsigned BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_REGISTERS, BadR);
|
||||
addErrInfo(errInfo);
|
||||
reportErrorRegisters(BadR);
|
||||
return false;
|
||||
}
|
||||
if (!isPredicateRegister(R) && Defs[R].size() > 1) {
|
||||
@ -423,20 +414,18 @@ bool HexagonMCChecker::checkRegisters() {
|
||||
// changes, conditional or not.
|
||||
unsigned UsrR = Hexagon::USR;
|
||||
unsigned BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_REGISTERS, BadR);
|
||||
addErrInfo(errInfo);
|
||||
reportErrorRegisters(BadR);
|
||||
return false;
|
||||
}
|
||||
// Check for multiple conditional register definitions.
|
||||
for (const auto& J : PM) {
|
||||
for (const auto &J : PM) {
|
||||
PredSense P = J;
|
||||
|
||||
// Check for multiple uses of the same condition.
|
||||
if (PM.count(P) > 1) {
|
||||
// Error out on conditional changes based on the same predicate
|
||||
// (e.g., "{ if (!p0) r0 =...; if (!p0) r0 =... }").
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_REGISTERS, R);
|
||||
addErrInfo(errInfo);
|
||||
reportErrorRegisters(R);
|
||||
return false;
|
||||
}
|
||||
// Check for the use of the complementary condition.
|
||||
@ -444,9 +433,9 @@ bool HexagonMCChecker::checkRegisters() {
|
||||
if (PM.count(P) && PM.size() > 2) {
|
||||
// Error out on conditional changes based on the same predicate
|
||||
// multiple times
|
||||
// (e.g., "{ if (p0) r0 =...; if (!p0) r0 =... }; if (!p0) r0 =... }").
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_REGISTERS, R);
|
||||
addErrInfo(errInfo);
|
||||
// (e.g., "{ if (p0) r0 =...; if (!p0) r0 =... }; if (!p0) r0 =...
|
||||
// }").
|
||||
reportErrorRegisters(R);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -454,34 +443,37 @@ bool HexagonMCChecker::checkRegisters() {
|
||||
}
|
||||
|
||||
// Check for use of current definitions.
|
||||
for (const auto& I : CurDefs) {
|
||||
for (const auto &I : CurDefs) {
|
||||
unsigned R = I;
|
||||
|
||||
if (!Uses.count(R)) {
|
||||
// Warn on an unused current definition.
|
||||
errInfo.setWarning(HexagonMCErrInfo::CHECK_WARN_CURRENT, R);
|
||||
addErrInfo(errInfo);
|
||||
reportWarning("register `" + llvm::Twine(RI.getName(R)) +
|
||||
"' used with `.cur' "
|
||||
"but not used in the same packet");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for use of temporary definitions.
|
||||
for (const auto& I : TmpDefs) {
|
||||
for (const auto &I : TmpDefs) {
|
||||
unsigned R = I;
|
||||
|
||||
if (!Uses.count(R)) {
|
||||
// special case for vhist
|
||||
bool vHistFound = false;
|
||||
for (auto const&HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
if(llvm::HexagonMCInstrInfo::getType(MCII, *HMI.getInst()) == HexagonII::TypeCVI_HIST) {
|
||||
vHistFound = true; // vhist() implicitly uses ALL REGxx.tmp
|
||||
for (auto const &HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
if (llvm::HexagonMCInstrInfo::getType(MCII, *HMI.getInst()) ==
|
||||
HexagonII::TypeCVI_HIST) {
|
||||
vHistFound = true; // vhist() implicitly uses ALL REGxx.tmp
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Warn on an unused temporary definition.
|
||||
if (vHistFound == false) {
|
||||
errInfo.setWarning(HexagonMCErrInfo::CHECK_WARN_TEMPORARY, R);
|
||||
addErrInfo(errInfo);
|
||||
reportWarning("register `" + llvm::Twine(RI.getName(R)) +
|
||||
"' used with `.tmp' "
|
||||
"but not used in the same packet");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -492,13 +484,12 @@ bool HexagonMCChecker::checkRegisters() {
|
||||
|
||||
// Check for legal use of solo insns.
|
||||
bool HexagonMCChecker::checkSolo() {
|
||||
HexagonMCErrInfo errInfo;
|
||||
if (HexagonMCInstrInfo::isBundle(MCB) &&
|
||||
HexagonMCInstrInfo::bundleSize(MCB) > 1) {
|
||||
for (auto const&I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
if (llvm::HexagonMCInstrInfo::isSolo(MCII, *I.getInst())) {
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_SOLO);
|
||||
addErrInfo(errInfo);
|
||||
reportError(
|
||||
"instruction cannot appear in packet with other instructions");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -508,29 +499,11 @@ bool HexagonMCChecker::checkSolo() {
|
||||
}
|
||||
|
||||
bool HexagonMCChecker::checkShuffle() {
|
||||
HexagonMCErrInfo errInfo;
|
||||
// Branch info is lost when duplexing. The unduplexed insns must be
|
||||
// checked and only branch errors matter for this case.
|
||||
HexagonMCShuffler MCS(true, MCII, STI, MCB);
|
||||
if (!MCS.check()) {
|
||||
if (MCS.getError() == HexagonShuffler::SHUFFLE_ERROR_BRANCHES) {
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_SHUFFLE);
|
||||
errInfo.setShuffleError(MCS.getError());
|
||||
addErrInfo(errInfo);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
HexagonMCShuffler MCSDX(true, MCII, STI, MCBDX);
|
||||
if (!MCSDX.check()) {
|
||||
errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_SHUFFLE);
|
||||
errInfo.setShuffleError(MCSDX.getError());
|
||||
addErrInfo(errInfo);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
HexagonMCShuffler MCSDX(Context, ReportErrors, MCII, STI, MCB);
|
||||
return MCSDX.check();
|
||||
}
|
||||
|
||||
void HexagonMCChecker::compoundRegisterMap(unsigned& Register) {
|
||||
void HexagonMCChecker::compoundRegisterMap(unsigned &Register) {
|
||||
switch (Register) {
|
||||
default:
|
||||
break;
|
||||
@ -562,7 +535,7 @@ void HexagonMCChecker::compoundRegisterMap(unsigned& Register) {
|
||||
}
|
||||
|
||||
bool HexagonMCChecker::hasValidNewValueDef(const NewSense &Use,
|
||||
const NewSenseList &Defs) const {
|
||||
const NewSenseList &Defs) const {
|
||||
bool Strict = !RelaxNVChecks;
|
||||
|
||||
for (unsigned i = 0, n = Defs.size(); i < n; ++i) {
|
||||
@ -590,3 +563,26 @@ bool HexagonMCChecker::hasValidNewValueDef(const NewSense &Use,
|
||||
return false;
|
||||
}
|
||||
|
||||
void HexagonMCChecker::reportErrorRegisters(unsigned Register) {
|
||||
reportError("register `" + llvm::Twine(RI.getName(Register)) +
|
||||
"' modified more than once");
|
||||
}
|
||||
|
||||
void HexagonMCChecker::reportErrorNewValue(unsigned Register) {
|
||||
reportError("register `" + llvm::Twine(RI.getName(Register)) +
|
||||
"' used with `.new' "
|
||||
"but not validly modified in the same packet");
|
||||
}
|
||||
|
||||
void HexagonMCChecker::reportError(llvm::Twine const &Msg) {
|
||||
if (ReportErrors)
|
||||
Context.reportError(MCB.getLoc(), Msg);
|
||||
}
|
||||
|
||||
void HexagonMCChecker::reportWarning(llvm::Twine const &Msg) {
|
||||
if (ReportErrors) {
|
||||
auto SM = Context.getSourceManager();
|
||||
if (SM)
|
||||
SM->PrintMessage(MCB.getLoc(), SourceMgr::DK_Warning, Msg);
|
||||
}
|
||||
}
|
||||
|
@ -24,59 +24,14 @@ using namespace llvm;
|
||||
namespace llvm {
|
||||
class MCOperandInfo;
|
||||
|
||||
typedef struct {
|
||||
unsigned Error, Warning, ShuffleError;
|
||||
unsigned Register;
|
||||
} ErrInfo_T;
|
||||
|
||||
class HexagonMCErrInfo {
|
||||
public:
|
||||
enum {
|
||||
CHECK_SUCCESS = 0,
|
||||
// Errors.
|
||||
CHECK_ERROR_BRANCHES = 0x00001,
|
||||
CHECK_ERROR_NEWP = 0x00002,
|
||||
CHECK_ERROR_NEWV = 0x00004,
|
||||
CHECK_ERROR_REGISTERS = 0x00008,
|
||||
CHECK_ERROR_READONLY = 0x00010,
|
||||
CHECK_ERROR_LOOP = 0x00020,
|
||||
CHECK_ERROR_ENDLOOP = 0x00040,
|
||||
CHECK_ERROR_SOLO = 0x00080,
|
||||
CHECK_ERROR_SHUFFLE = 0x00100,
|
||||
CHECK_ERROR_NOSLOTS = 0x00200,
|
||||
CHECK_ERROR_UNKNOWN = 0x00400,
|
||||
// Warnings.
|
||||
CHECK_WARN_CURRENT = 0x10000,
|
||||
CHECK_WARN_TEMPORARY = 0x20000
|
||||
};
|
||||
ErrInfo_T s;
|
||||
|
||||
void reset() {
|
||||
s.Error = CHECK_SUCCESS;
|
||||
s.Warning = CHECK_SUCCESS;
|
||||
s.ShuffleError = HexagonShuffler::SHUFFLE_SUCCESS;
|
||||
s.Register = Hexagon::NoRegister;
|
||||
};
|
||||
HexagonMCErrInfo() {
|
||||
reset();
|
||||
};
|
||||
|
||||
void setError(unsigned e, unsigned r = Hexagon::NoRegister)
|
||||
{ s.Error = e; s.Register = r; };
|
||||
void setWarning(unsigned w, unsigned r = Hexagon::NoRegister)
|
||||
{ s.Warning = w; s.Register = r; };
|
||||
void setShuffleError(unsigned e) { s.ShuffleError = e; };
|
||||
};
|
||||
|
||||
/// Check for a valid bundle.
|
||||
class HexagonMCChecker {
|
||||
/// Insn bundle.
|
||||
MCInst& MCB;
|
||||
MCInst& MCBDX;
|
||||
const MCRegisterInfo& RI;
|
||||
MCContext &Context;
|
||||
MCInst &MCB;
|
||||
const MCRegisterInfo &RI;
|
||||
MCInstrInfo const &MCII;
|
||||
MCSubtargetInfo const &STI;
|
||||
bool bLoadErrInfo;
|
||||
bool ReportErrors;
|
||||
|
||||
/// Set of definitions: register #, if predicated, if predicated true.
|
||||
typedef std::pair<unsigned, bool> PredSense;
|
||||
@ -99,23 +54,23 @@ class HexagonMCChecker {
|
||||
bool IsFloat, IsNVJ, Cond;
|
||||
// The special-case "constructors":
|
||||
static NewSense Jmp(bool isNVJ) {
|
||||
NewSense NS = { /*PredReg=*/ 0, /*IsFloat=*/ false, /*IsNVJ=*/ isNVJ,
|
||||
/*Cond=*/ false };
|
||||
NewSense NS = {/*PredReg=*/0, /*IsFloat=*/false, /*IsNVJ=*/isNVJ,
|
||||
/*Cond=*/false};
|
||||
return NS;
|
||||
}
|
||||
static NewSense Use(unsigned PR, bool True) {
|
||||
NewSense NS = { /*PredReg=*/ PR, /*IsFloat=*/ false, /*IsNVJ=*/ false,
|
||||
/*Cond=*/ True };
|
||||
NewSense NS = {/*PredReg=*/PR, /*IsFloat=*/false, /*IsNVJ=*/false,
|
||||
/*Cond=*/True};
|
||||
return NS;
|
||||
}
|
||||
static NewSense Def(unsigned PR, bool True, bool Float) {
|
||||
NewSense NS = { /*PredReg=*/ PR, /*IsFloat=*/ Float, /*IsNVJ=*/ false,
|
||||
/*Cond=*/ True };
|
||||
NewSense NS = {/*PredReg=*/PR, /*IsFloat=*/Float, /*IsNVJ=*/false,
|
||||
/*Cond=*/True};
|
||||
return NS;
|
||||
}
|
||||
};
|
||||
/// Set of definitions that produce new register:
|
||||
typedef llvm::SmallVector<NewSense,2> NewSenseList;
|
||||
typedef llvm::SmallVector<NewSense, 2> NewSenseList;
|
||||
typedef llvm::DenseMap<unsigned, NewSenseList>::iterator NewDefsIterator;
|
||||
llvm::DenseMap<unsigned, NewSenseList> NewDefs;
|
||||
|
||||
@ -151,23 +106,8 @@ class HexagonMCChecker {
|
||||
typedef std::set<unsigned>::iterator ReadOnlyIterator;
|
||||
std::set<unsigned> ReadOnly;
|
||||
|
||||
std::queue<ErrInfo_T> ErrInfoQ;
|
||||
HexagonMCErrInfo CrntErrInfo;
|
||||
|
||||
void getErrInfo() {
|
||||
if (bLoadErrInfo == true) {
|
||||
if (ErrInfoQ.empty()) {
|
||||
CrntErrInfo.reset();
|
||||
} else {
|
||||
CrntErrInfo.s = ErrInfoQ.front();
|
||||
ErrInfoQ.pop();
|
||||
}
|
||||
}
|
||||
bLoadErrInfo = false;
|
||||
}
|
||||
|
||||
void init();
|
||||
void init(MCInst const&);
|
||||
void init(MCInst const &);
|
||||
void initReg(MCInst const &, unsigned, unsigned &PredReg, bool &isTrue);
|
||||
|
||||
// Checks performed.
|
||||
@ -180,40 +120,31 @@ class HexagonMCChecker {
|
||||
bool checkSlots();
|
||||
bool checkSize();
|
||||
|
||||
static void compoundRegisterMap(unsigned&);
|
||||
static void compoundRegisterMap(unsigned &);
|
||||
|
||||
bool isPredicateRegister(unsigned R) const {
|
||||
return (Hexagon::P0 == R || Hexagon::P1 == R ||
|
||||
Hexagon::P2 == R || Hexagon::P3 == R);
|
||||
return (Hexagon::P0 == R || Hexagon::P1 == R || Hexagon::P2 == R ||
|
||||
Hexagon::P3 == R);
|
||||
};
|
||||
bool isLoopRegister(unsigned R) const {
|
||||
return (Hexagon::SA0 == R || Hexagon::LC0 == R ||
|
||||
Hexagon::SA1 == R || Hexagon::LC1 == R);
|
||||
return (Hexagon::SA0 == R || Hexagon::LC0 == R || Hexagon::SA1 == R ||
|
||||
Hexagon::LC1 == R);
|
||||
};
|
||||
|
||||
bool hasValidNewValueDef(const NewSense &Use,
|
||||
const NewSenseList &Defs) const;
|
||||
bool hasValidNewValueDef(const NewSense &Use, const NewSenseList &Defs) const;
|
||||
|
||||
public:
|
||||
explicit HexagonMCChecker(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst& mcb, MCInst &mcbdx,
|
||||
const MCRegisterInfo& ri);
|
||||
public:
|
||||
explicit HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &mcb,
|
||||
const MCRegisterInfo &ri, bool ReportErrors = true);
|
||||
|
||||
bool check(bool FullCheck = true);
|
||||
|
||||
/// add a new error/warning
|
||||
void addErrInfo(HexagonMCErrInfo &err) { ErrInfoQ.push(err.s); };
|
||||
|
||||
/// Return the error code for the last operation in the insn bundle.
|
||||
unsigned getError() { getErrInfo(); return CrntErrInfo.s.Error; };
|
||||
unsigned getWarning() { getErrInfo(); return CrntErrInfo.s.Warning; };
|
||||
unsigned getShuffleError() { getErrInfo(); return CrntErrInfo.s.ShuffleError; };
|
||||
unsigned getErrRegister() { getErrInfo(); return CrntErrInfo.s.Register; };
|
||||
bool getNextErrInfo() {
|
||||
bLoadErrInfo = true;
|
||||
return (ErrInfoQ.empty()) ? false : (getErrInfo(), true);
|
||||
}
|
||||
void reportErrorRegisters(unsigned Register);
|
||||
void reportErrorNewValue(unsigned Register);
|
||||
void reportError(llvm::Twine const &Msg);
|
||||
void reportWarning(llvm::Twine const &Msg);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace llvm
|
||||
|
||||
#endif // HEXAGONMCCHECKER_H
|
||||
|
@ -406,7 +406,7 @@ void HexagonMCInstrInfo::tryCompound(MCInstrInfo const &MCII, MCSubtargetInfo co
|
||||
if (MCI.size() < 2)
|
||||
return;
|
||||
|
||||
bool StartedValid = llvm::HexagonMCShuffle(false, MCII, STI, MCI);
|
||||
bool StartedValid = llvm::HexagonMCShuffle(Context, false, MCII, STI, MCI);
|
||||
|
||||
// Create a vector, needed to keep the order of jump instructions.
|
||||
MCInst CheckList(MCI);
|
||||
@ -420,8 +420,9 @@ void HexagonMCInstrInfo::tryCompound(MCInstrInfo const &MCII, MCSubtargetInfo co
|
||||
// Need to update the bundle.
|
||||
MCI = CheckList;
|
||||
|
||||
if (StartedValid && !llvm::HexagonMCShuffle(false, MCII, STI, MCI)) {
|
||||
DEBUG(dbgs() << "Found ERROR\n");
|
||||
if (StartedValid &&
|
||||
!llvm::HexagonMCShuffle(Context, false, MCII, STI, MCI)) {
|
||||
DEBUG(dbgs() << "Found ERROR\n");
|
||||
MCI = OriginalBundle;
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII,
|
||||
// instructions when possible.
|
||||
if (!HexagonDisableCompound)
|
||||
HexagonMCInstrInfo::tryCompound(MCII, STI, Context, MCB);
|
||||
HexagonMCShuffle(false, MCII, STI, MCB);
|
||||
HexagonMCShuffle(Context, false, MCII, STI, MCB);
|
||||
// Examine the packet and convert pairs of instructions to duplex
|
||||
// instructions when possible.
|
||||
MCInst InstBundlePreDuplex = MCInst(MCB);
|
||||
@ -74,7 +74,7 @@ bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII,
|
||||
SmallVector<DuplexCandidate, 8> possibleDuplexes;
|
||||
possibleDuplexes =
|
||||
HexagonMCInstrInfo::getDuplexPossibilties(MCII, STI, MCB);
|
||||
HexagonMCShuffle(MCII, STI, Context, MCB, possibleDuplexes);
|
||||
HexagonMCShuffle(Context, MCII, STI, MCB, possibleDuplexes);
|
||||
}
|
||||
// Examines packet and pad the packet, if needed, when an
|
||||
// end-loop is in the bundle.
|
||||
@ -87,7 +87,7 @@ bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII,
|
||||
CheckOk = Check ? Check->check(true) : true;
|
||||
if (!CheckOk)
|
||||
return false;
|
||||
HexagonMCShuffle(true, MCII, STI, MCB);
|
||||
HexagonMCShuffle(Context, true, MCII, STI, MCB);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ void HexagonMCShuffler::init(MCInst &MCB) {
|
||||
}
|
||||
}
|
||||
|
||||
Loc = MCB.getLoc();
|
||||
BundleFlags = MCB.getOperand(0).getImm();
|
||||
}
|
||||
|
||||
@ -68,12 +69,14 @@ void HexagonMCShuffler::init(MCInst &MCB, MCInst const &AddMI,
|
||||
append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, AddMI));
|
||||
}
|
||||
|
||||
Loc = MCB.getLoc();
|
||||
BundleFlags = MCB.getOperand(0).getImm();
|
||||
}
|
||||
|
||||
void HexagonMCShuffler::copyTo(MCInst &MCB) {
|
||||
MCB.clear();
|
||||
MCB.addOperand(MCOperand::createImm(BundleFlags));
|
||||
MCB.setLoc(Loc);
|
||||
// Copy the results into the bundle.
|
||||
for (HexagonShuffler::iterator I = begin(); I != end(); ++I) {
|
||||
|
||||
@ -89,15 +92,16 @@ bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) {
|
||||
if (shuffle()) {
|
||||
// Copy the results into the bundle.
|
||||
copyTo(MCB);
|
||||
} else
|
||||
DEBUG(MCB.dump());
|
||||
|
||||
return (!getError());
|
||||
return true;
|
||||
}
|
||||
DEBUG(MCB.dump());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool llvm::HexagonMCShuffle(bool Fatal, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &MCB) {
|
||||
HexagonMCShuffler MCS(true, MCII, STI, MCB);
|
||||
bool llvm::HexagonMCShuffle(MCContext &Context, bool Fatal,
|
||||
MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst &MCB) {
|
||||
HexagonMCShuffler MCS(Context, Fatal, MCII, STI, MCB);
|
||||
|
||||
if (DisableShuffle)
|
||||
// Ignore if user chose so.
|
||||
@ -117,52 +121,16 @@ bool llvm::HexagonMCShuffle(bool Fatal, MCInstrInfo const &MCII,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reorder the bundle and copy the result.
|
||||
if (!MCS.reshuffleTo(MCB)) {
|
||||
// Unless there is any error, which should not happen at this point.
|
||||
unsigned shuffleError = MCS.getError();
|
||||
|
||||
if (!Fatal && (shuffleError != HexagonShuffler::SHUFFLE_SUCCESS))
|
||||
return false;
|
||||
if (shuffleError != HexagonShuffler::SHUFFLE_SUCCESS) {
|
||||
errs() << "\nFailing packet:\n";
|
||||
for (const auto& I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
|
||||
MCInst *MI = const_cast<MCInst *>(I.getInst());
|
||||
errs() << HexagonMCInstrInfo::getName(MCII, *MI) << ' ' << HexagonMCInstrInfo::getDesc(MCII, *MI).getOpcode() << '\n';
|
||||
}
|
||||
errs() << '\n';
|
||||
}
|
||||
|
||||
switch (shuffleError) {
|
||||
default:
|
||||
llvm_unreachable("unknown error");
|
||||
case HexagonShuffler::SHUFFLE_ERROR_INVALID:
|
||||
llvm_unreachable("invalid packet");
|
||||
case HexagonShuffler::SHUFFLE_ERROR_STORES:
|
||||
llvm_unreachable("too many stores");
|
||||
case HexagonShuffler::SHUFFLE_ERROR_LOADS:
|
||||
llvm_unreachable("too many loads");
|
||||
case HexagonShuffler::SHUFFLE_ERROR_BRANCHES:
|
||||
llvm_unreachable("too many branches");
|
||||
case HexagonShuffler::SHUFFLE_ERROR_NOSLOTS:
|
||||
llvm_unreachable("no suitable slot");
|
||||
case HexagonShuffler::SHUFFLE_ERROR_SLOTS:
|
||||
llvm_unreachable("over-subscribed slots");
|
||||
case HexagonShuffler::SHUFFLE_SUCCESS: // Single instruction case.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return MCS.reshuffleTo(MCB);
|
||||
}
|
||||
|
||||
unsigned
|
||||
llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCContext &Context, MCInst &MCB,
|
||||
bool
|
||||
llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &MCB,
|
||||
SmallVector<DuplexCandidate, 8> possibleDuplexes) {
|
||||
|
||||
if (DisableShuffle)
|
||||
return HexagonShuffler::SHUFFLE_SUCCESS;
|
||||
return false;
|
||||
|
||||
if (!HexagonMCInstrInfo::bundleSize(MCB)) {
|
||||
// There once was a bundle:
|
||||
@ -172,46 +140,44 @@ llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
// After the IMPLICIT_DEFs were removed by the asm printer, the bundle
|
||||
// became empty.
|
||||
DEBUG(dbgs() << "Skipping empty bundle");
|
||||
return HexagonShuffler::SHUFFLE_SUCCESS;
|
||||
return false;
|
||||
} else if (!HexagonMCInstrInfo::isBundle(MCB)) {
|
||||
DEBUG(dbgs() << "Skipping stand-alone insn");
|
||||
return HexagonShuffler::SHUFFLE_SUCCESS;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool doneShuffling = false;
|
||||
unsigned shuffleError;
|
||||
while (possibleDuplexes.size() > 0 && (!doneShuffling)) {
|
||||
// case of Duplex Found
|
||||
DuplexCandidate duplexToTry = possibleDuplexes.pop_back_val();
|
||||
MCInst Attempt(MCB);
|
||||
HexagonMCInstrInfo::replaceDuplex(Context, Attempt, duplexToTry);
|
||||
HexagonMCShuffler MCS(true, MCII, STI, Attempt); // copy packet to the shuffler
|
||||
HexagonMCShuffler MCS(Context, false, MCII, STI, Attempt); // copy packet to the shuffler
|
||||
if (MCS.size() == 1) { // case of one duplex
|
||||
// copy the created duplex in the shuffler to the bundle
|
||||
MCS.copyTo(MCB);
|
||||
return HexagonShuffler::SHUFFLE_SUCCESS;
|
||||
return false;
|
||||
}
|
||||
// try shuffle with this duplex
|
||||
doneShuffling = MCS.reshuffleTo(MCB);
|
||||
shuffleError = MCS.getError();
|
||||
|
||||
if (doneShuffling)
|
||||
break;
|
||||
}
|
||||
|
||||
if (doneShuffling == false) {
|
||||
HexagonMCShuffler MCS(true, MCII, STI, MCB);
|
||||
HexagonMCShuffler MCS(Context, false, MCII, STI, MCB);
|
||||
doneShuffling = MCS.reshuffleTo(MCB); // shuffle
|
||||
shuffleError = MCS.getError();
|
||||
}
|
||||
if (!doneShuffling)
|
||||
return shuffleError;
|
||||
return true;
|
||||
|
||||
return HexagonShuffler::SHUFFLE_SUCCESS;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst &MCB, MCInst const &AddMI, int fixupCount) {
|
||||
bool llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &MCB,
|
||||
MCInst const &AddMI, int fixupCount) {
|
||||
if (!HexagonMCInstrInfo::isBundle(MCB))
|
||||
return false;
|
||||
|
||||
@ -246,16 +212,6 @@ bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
if (bhasDuplex && bundleSize >= maxBundleSize)
|
||||
return false;
|
||||
|
||||
HexagonMCShuffler MCS(MCII, STI, MCB, AddMI, false);
|
||||
if (!MCS.reshuffleTo(MCB)) {
|
||||
unsigned shuffleError = MCS.getError();
|
||||
switch (shuffleError) {
|
||||
default:
|
||||
return false;
|
||||
case HexagonShuffler::SHUFFLE_SUCCESS: // single instruction case
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
HexagonMCShuffler MCS(Context, false, MCII, STI, MCB, AddMI, false);
|
||||
return MCS.reshuffleTo(MCB);
|
||||
}
|
||||
|
@ -18,24 +18,19 @@
|
||||
#include "MCTargetDesc/HexagonShuffler.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCInst;
|
||||
|
||||
// Insn bundle shuffler.
|
||||
class HexagonMCShuffler : public HexagonShuffler {
|
||||
bool immext_present;
|
||||
bool duplex_present;
|
||||
|
||||
public:
|
||||
HexagonMCShuffler(bool Fatal, MCInstrInfo const &MCII,
|
||||
HexagonMCShuffler(MCContext &Context, bool Fatal, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &MCB)
|
||||
: HexagonShuffler(MCII, STI) {
|
||||
: HexagonShuffler(Context, Fatal, MCII, STI) {
|
||||
init(MCB);
|
||||
};
|
||||
HexagonMCShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst &MCB, MCInst const &AddMI,
|
||||
bool InsertAtFront)
|
||||
: HexagonShuffler(MCII, STI) {
|
||||
HexagonMCShuffler(MCContext &Context, bool Fatal, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &MCB,
|
||||
MCInst const &AddMI, bool InsertAtFront)
|
||||
: HexagonShuffler(Context, Fatal, MCII, STI) {
|
||||
init(MCB, AddMI, InsertAtFront);
|
||||
};
|
||||
|
||||
@ -44,22 +39,20 @@ public:
|
||||
// Reorder and copy result to another.
|
||||
bool reshuffleTo(MCInst &MCB);
|
||||
|
||||
bool immextPresent() const { return immext_present; };
|
||||
bool duplexPresent() const { return duplex_present; };
|
||||
|
||||
private:
|
||||
void init(MCInst &MCB);
|
||||
void init(MCInst &MCB, MCInst const &AddMI, bool InsertAtFront);
|
||||
};
|
||||
|
||||
// Invocation of the shuffler.
|
||||
bool HexagonMCShuffle(bool Fatal, MCInstrInfo const &MCII,
|
||||
bool HexagonMCShuffle(MCContext &Context, bool Fatal, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &);
|
||||
bool HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCInst &, MCInst const &, int);
|
||||
unsigned HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
|
||||
MCContext &Context, MCInst &,
|
||||
SmallVector<DuplexCandidate, 8>);
|
||||
}
|
||||
bool HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &, MCInst const &,
|
||||
int);
|
||||
bool HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI, MCInst &,
|
||||
SmallVector<DuplexCandidate, 8>);
|
||||
} // namespace llvm
|
||||
|
||||
#endif // HEXAGONMCSHUFFLER_H
|
||||
|
@ -14,17 +14,18 @@
|
||||
|
||||
#define DEBUG_TYPE "hexagon-shuffle"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include "HexagonShuffler.h"
|
||||
#include "Hexagon.h"
|
||||
#include "MCTargetDesc/HexagonBaseInfo.h"
|
||||
#include "MCTargetDesc/HexagonMCTargetDesc.h"
|
||||
#include "MCTargetDesc/HexagonMCInstrInfo.h"
|
||||
#include "HexagonShuffler.h"
|
||||
#include "MCTargetDesc/HexagonMCTargetDesc.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -38,7 +39,7 @@ class HexagonBid {
|
||||
unsigned Bid;
|
||||
|
||||
public:
|
||||
HexagonBid() : Bid(0){}
|
||||
HexagonBid() : Bid(0) {}
|
||||
HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; }
|
||||
|
||||
// Check if the insn priority is overflowed.
|
||||
@ -87,7 +88,7 @@ unsigned HexagonResource::setWeight(unsigned s) {
|
||||
// Calculate relative weight of the insn for the given slot, weighing it the
|
||||
// heavier the more restrictive the insn is and the lowest the slots that the
|
||||
// insn may be executed in.
|
||||
if (Key == 0 || Units == 0 || (SlotWeight*s >= 32))
|
||||
if (Key == 0 || Units == 0 || (SlotWeight * s >= 32))
|
||||
return Weight = 0;
|
||||
|
||||
unsigned Ctpop = countPopulation(Units);
|
||||
@ -106,9 +107,9 @@ void HexagonCVIResource::SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU) {
|
||||
(*TUL)[HexagonII::TypeCVI_VP_VS] = UnitsAndLanes(CVI_XLANE, 2);
|
||||
(*TUL)[HexagonII::TypeCVI_VS] = UnitsAndLanes(CVI_SHIFT, 1);
|
||||
(*TUL)[HexagonII::TypeCVI_VINLANESAT] =
|
||||
(CPU == "hexagonv60" || CPU == "hexagonv61" || CPU == "hexagonv61v1") ?
|
||||
UnitsAndLanes(CVI_SHIFT, 1) :
|
||||
UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
|
||||
(CPU == "hexagonv60" || CPU == "hexagonv61" || CPU == "hexagonv61v1")
|
||||
? UnitsAndLanes(CVI_SHIFT, 1)
|
||||
: UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
|
||||
(*TUL)[HexagonII::TypeCVI_VM_LD] =
|
||||
UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
|
||||
(*TUL)[HexagonII::TypeCVI_VM_TMP_LD] = UnitsAndLanes(CVI_NONE, 0);
|
||||
@ -154,18 +155,19 @@ typedef SmallVector<struct CVIUnits, 8> HVXInstsT;
|
||||
static unsigned makeAllBits(unsigned startBit, unsigned Lanes)
|
||||
|
||||
{
|
||||
for (unsigned i = 1 ; i < Lanes ; ++i)
|
||||
for (unsigned i = 1; i < Lanes; ++i)
|
||||
startBit = (startBit << 1) | startBit;
|
||||
return startBit;
|
||||
}
|
||||
|
||||
static bool checkHVXPipes(const HVXInstsT& hvxInsts, unsigned startIdx, unsigned usedUnits)
|
||||
static bool checkHVXPipes(const HVXInstsT &hvxInsts, unsigned startIdx,
|
||||
unsigned usedUnits)
|
||||
|
||||
{
|
||||
if (startIdx < hvxInsts.size()) {
|
||||
if (!hvxInsts[startIdx].Units)
|
||||
return checkHVXPipes(hvxInsts, startIdx + 1, usedUnits);
|
||||
for (unsigned b = 0x1 ; b <= 0x8 ; b <<= 1) {
|
||||
for (unsigned b = 0x1; b <= 0x8; b <<= 1) {
|
||||
if ((hvxInsts[startIdx].Units & b) == 0)
|
||||
continue;
|
||||
unsigned allBits = makeAllBits(b, hvxInsts[startIdx].Lanes);
|
||||
@ -179,9 +181,10 @@ static bool checkHVXPipes(const HVXInstsT& hvxInsts, unsigned startIdx, unsigned
|
||||
return true;
|
||||
}
|
||||
|
||||
HexagonShuffler::HexagonShuffler(MCInstrInfo const &MCII,
|
||||
HexagonShuffler::HexagonShuffler(MCContext &Context, bool ReportErrors,
|
||||
MCInstrInfo const &MCII,
|
||||
MCSubtargetInfo const &STI)
|
||||
: MCII(MCII), STI(STI) {
|
||||
: Context(Context), MCII(MCII), STI(STI), ReportErrors(ReportErrors) {
|
||||
reset();
|
||||
HexagonCVIResource::SetupTUL(&TUL, STI.getCPU());
|
||||
}
|
||||
@ -189,7 +192,6 @@ HexagonShuffler::HexagonShuffler(MCInstrInfo const &MCII,
|
||||
void HexagonShuffler::reset() {
|
||||
Packet.clear();
|
||||
BundleFlags = 0;
|
||||
Error = SHUFFLE_SUCCESS;
|
||||
}
|
||||
|
||||
void HexagonShuffler::append(MCInst const &ID, MCInst const *Extender,
|
||||
@ -202,8 +204,8 @@ void HexagonShuffler::append(MCInst const &ID, MCInst const *Extender,
|
||||
static struct {
|
||||
unsigned first;
|
||||
unsigned second;
|
||||
} jumpSlots[] = { {8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1} };
|
||||
#define MAX_JUMP_SLOTS (sizeof(jumpSlots)/sizeof(jumpSlots[0]))
|
||||
} jumpSlots[] = {{8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1}};
|
||||
#define MAX_JUMP_SLOTS (sizeof(jumpSlots) / sizeof(jumpSlots[0]))
|
||||
|
||||
namespace {
|
||||
bool isDuplexAGroup(unsigned Opcode) {
|
||||
@ -248,26 +250,23 @@ unsigned countNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) {
|
||||
Result += !isDuplexAGroup(subInst0Opcode);
|
||||
Result += !isDuplexAGroup(subInst1Opcode);
|
||||
} else
|
||||
Result += Type != HexagonII::TypeALU32_2op &&
|
||||
Type != HexagonII::TypeALU32_3op &&
|
||||
Type != HexagonII::TypeALU32_ADDI &&
|
||||
Type != HexagonII::TypeS_2op &&
|
||||
Type != HexagonII::TypeS_3op &&
|
||||
Type != HexagonII::TypeALU64 &&
|
||||
(Type != HexagonII::TypeM ||
|
||||
HexagonMCInstrInfo::isFloat(MCII, ID));
|
||||
Result +=
|
||||
Type != HexagonII::TypeALU32_2op && Type != HexagonII::TypeALU32_3op &&
|
||||
Type != HexagonII::TypeALU32_ADDI && Type != HexagonII::TypeS_2op &&
|
||||
Type != HexagonII::TypeS_3op && Type != HexagonII::TypeALU64 &&
|
||||
(Type != HexagonII::TypeM || HexagonMCInstrInfo::isFloat(MCII, ID));
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/// Check that the packet is legal and enforce relative insn order.
|
||||
bool HexagonShuffler::check() {
|
||||
// Descriptive slot masks.
|
||||
const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2,
|
||||
slotThree = 0x8, //slotFirstJump = 0x8,
|
||||
slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
|
||||
slotThree = 0x8, // slotFirstJump = 0x8,
|
||||
slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
|
||||
// Highest slots for branches and stores used to keep their original order.
|
||||
//unsigned slotJump = slotFirstJump;
|
||||
// unsigned slotJump = slotFirstJump;
|
||||
unsigned slotLoadStore = slotFirstLoadStore;
|
||||
// Number of branches, solo branches, indirect branches.
|
||||
unsigned jumps = 0, jump1 = 0;
|
||||
@ -287,6 +286,7 @@ bool HexagonShuffler::check() {
|
||||
unsigned onlyNo1 = 0;
|
||||
unsigned xtypeFloat = 0;
|
||||
unsigned pSlot3Cnt = 0;
|
||||
unsigned nvstores = 0;
|
||||
unsigned memops = 0;
|
||||
unsigned deallocs = 0;
|
||||
iterator slot3ISJ = end();
|
||||
@ -333,8 +333,7 @@ bool HexagonShuffler::check() {
|
||||
++loads;
|
||||
++memory;
|
||||
if (ISJ->Core.getUnits() == slotSingleLoad ||
|
||||
HexagonMCInstrInfo::getType(MCII, ID) ==
|
||||
HexagonII::TypeCVI_VM_VP_LDU)
|
||||
HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_VP_LDU)
|
||||
++load0;
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn()) {
|
||||
++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
|
||||
@ -368,18 +367,19 @@ bool HexagonShuffler::check() {
|
||||
}
|
||||
break;
|
||||
case HexagonII::TypeV2LDST:
|
||||
if(HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) {
|
||||
if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) {
|
||||
++loads;
|
||||
++memory;
|
||||
if (ISJ->Core.getUnits() == slotSingleLoad ||
|
||||
HexagonMCInstrInfo::getType(MCII,ID) ==
|
||||
HexagonMCInstrInfo::getType(MCII, ID) ==
|
||||
HexagonII::TypeCVI_VM_VP_LDU)
|
||||
++load0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
assert(HexagonMCInstrInfo::getDesc(MCII, ID).mayStore());
|
||||
++memory;
|
||||
++stores;
|
||||
if (HexagonMCInstrInfo::isNewValue(MCII, ID))
|
||||
++nvstores;
|
||||
}
|
||||
break;
|
||||
case HexagonII::TypeCR:
|
||||
@ -415,21 +415,21 @@ bool HexagonShuffler::check() {
|
||||
if ((load0 > 1 || store0 > 1 || CVIloads > 1 || CVIstores > 1) ||
|
||||
(duplex > 1 || (duplex && memory)) || (solo && size() > 1) ||
|
||||
(onlyAX && neitherAnorX > 1) || (onlyAX && xtypeFloat)) {
|
||||
Error = SHUFFLE_ERROR_INVALID;
|
||||
reportError(llvm::Twine("invalid instruction packet"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (jump1 && jumps > 1) {
|
||||
// Error if single branch with another branch.
|
||||
Error = SHUFFLE_ERROR_BRANCHES;
|
||||
reportError(llvm::Twine("too many branches in packet"));
|
||||
return false;
|
||||
}
|
||||
if (memops && stores > 1) {
|
||||
Error = SHUFFLE_ERROR_STORE_LOAD_CONFLICT;
|
||||
if ((nvstores || memops) && stores > 1) {
|
||||
reportError(llvm::Twine("slot 0 instruction does not allow slot 1 store"));
|
||||
return false;
|
||||
}
|
||||
if (deallocs && stores) {
|
||||
Error = SHUFFLE_ERROR_STORE_LOAD_CONFLICT;
|
||||
reportError(llvm::Twine("slot 0 instruction does not allow slot 1 store"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -441,7 +441,6 @@ bool HexagonShuffler::check() {
|
||||
|
||||
if (!ISJ->Core.getUnits()) {
|
||||
// Error if insn may not be executed in any slot.
|
||||
Error = SHUFFLE_ERROR_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -472,7 +471,8 @@ bool HexagonShuffler::check() {
|
||||
else if (stores > 1) {
|
||||
if (slotLoadStore < slotLastLoadStore) {
|
||||
// Error if no more slots available for stores.
|
||||
Error = SHUFFLE_ERROR_STORES;
|
||||
reportError(
|
||||
llvm::Twine("invalid instruction packet: too many stores"));
|
||||
return false;
|
||||
}
|
||||
// Pin the store to the highest slot available to it.
|
||||
@ -483,7 +483,7 @@ bool HexagonShuffler::check() {
|
||||
}
|
||||
if (store1 && stores > 1) {
|
||||
// Error if a single store with another store.
|
||||
Error = SHUFFLE_ERROR_STORES;
|
||||
reportError(llvm::Twine("invalid instruction packet: too many stores"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -494,7 +494,7 @@ bool HexagonShuffler::check() {
|
||||
|
||||
if (!ISJ->Core.getUnits()) {
|
||||
// Error if insn may not be executed in any slot.
|
||||
Error = SHUFFLE_ERROR_NOSLOTS;
|
||||
reportError(llvm::Twine("invalid instruction packet: out of slots"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -503,12 +503,12 @@ bool HexagonShuffler::check() {
|
||||
bool validateSlots = true;
|
||||
if (jumps > 1) {
|
||||
if (foundBranches.size() > 2) {
|
||||
Error = SHUFFLE_ERROR_BRANCHES;
|
||||
reportError(llvm::Twine("too many branches in packet"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// try all possible choices
|
||||
for (unsigned int i = 0 ; i < MAX_JUMP_SLOTS ; ++i) {
|
||||
for (unsigned int i = 0; i < MAX_JUMP_SLOTS; ++i) {
|
||||
// validate first jump with this slot rule
|
||||
if (!(jumpSlots[i].first & foundBranches[0]->Core.getUnits()))
|
||||
continue;
|
||||
@ -535,18 +535,18 @@ bool HexagonShuffler::check() {
|
||||
if (!bFail) {
|
||||
validateSlots = false; // all good, no need to re-do auction
|
||||
break;
|
||||
}
|
||||
else
|
||||
} else
|
||||
// restore original values
|
||||
Packet = PacketSave;
|
||||
}
|
||||
if (validateSlots == true) {
|
||||
Error = SHUFFLE_ERROR_NOSLOTS;
|
||||
reportError(llvm::Twine("invalid instruction packet: out of slots"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (jumps <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) {
|
||||
if (jumps <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 &&
|
||||
slot3ISJ != end()) {
|
||||
validateSlots = true;
|
||||
// save off slot mask of instruction marked with A_PREFER_SLOT3
|
||||
// and then pin it to slot #3
|
||||
@ -582,7 +582,7 @@ bool HexagonShuffler::check() {
|
||||
|
||||
for (iterator I = begin(); I != end(); ++I)
|
||||
if (!AuctionCore.bid(I->Core.getUnits())) {
|
||||
Error = SHUFFLE_ERROR_SLOTS;
|
||||
reportError(llvm::Twine("invalid instruction packet: slot error"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -605,12 +605,11 @@ bool HexagonShuffler::check() {
|
||||
startIdx = usedUnits = 0x0;
|
||||
if (checkHVXPipes(hvxInsts, startIdx, usedUnits) == false) {
|
||||
// too many pipes used to be valid
|
||||
Error = SHUFFLE_ERROR_SLOTS;
|
||||
reportError(llvm::Twine("invalid instruction packet: slot error"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Error = SHUFFLE_SUCCESS;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -618,12 +617,13 @@ bool HexagonShuffler::shuffle() {
|
||||
if (size() > HEXAGON_PACKET_SIZE) {
|
||||
// Ignore a packet with with more than what a packet can hold
|
||||
// or with compound or duplex insns for now.
|
||||
Error = SHUFFLE_ERROR_INVALID;
|
||||
reportError(llvm::Twine("invalid instruction packet"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check and prepare packet.
|
||||
if (size() > 1 && check())
|
||||
bool Ok = true;
|
||||
if (size() > 1 && (Ok = check()))
|
||||
// Reorder the handles for each slot.
|
||||
for (unsigned nSlot = 0, emptySlots = 0; nSlot < HEXAGON_PACKET_SIZE;
|
||||
++nSlot) {
|
||||
@ -659,5 +659,10 @@ bool HexagonShuffler::shuffle() {
|
||||
dbgs() << '\n');
|
||||
DEBUG(dbgs() << '\n');
|
||||
|
||||
return (!getError());
|
||||
return Ok;
|
||||
}
|
||||
|
||||
void HexagonShuffler::reportError(llvm::Twine const &Msg) {
|
||||
if (ReportErrors)
|
||||
Context.reportError(Loc, Msg);
|
||||
}
|
||||
|
@ -45,8 +45,7 @@ public:
|
||||
|
||||
// Check if the resources are in ascending slot order.
|
||||
static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {
|
||||
return (countPopulation(A.getUnits()) <
|
||||
countPopulation(B.getUnits()));
|
||||
return (countPopulation(A.getUnits()) < countPopulation(B.getUnits()));
|
||||
};
|
||||
// Check if the resources are in ascending weight order.
|
||||
static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
|
||||
@ -106,7 +105,7 @@ class HexagonInstr {
|
||||
public:
|
||||
HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes *T,
|
||||
MCInstrInfo const &MCII, MCInst const *id,
|
||||
MCInst const *Extender, unsigned s)
|
||||
MCInst const *Extender, unsigned s, bool x = false)
|
||||
: ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id) {}
|
||||
|
||||
MCInst const &getDesc() const { return *ID; };
|
||||
@ -136,33 +135,21 @@ class HexagonShuffler {
|
||||
HexagonPacket Packet;
|
||||
HexagonPacket PacketSave;
|
||||
|
||||
// Shuffling error code.
|
||||
unsigned Error;
|
||||
|
||||
HexagonCVIResource::TypeUnitsAndLanes TUL;
|
||||
|
||||
protected:
|
||||
MCContext &Context;
|
||||
int64_t BundleFlags;
|
||||
MCInstrInfo const &MCII;
|
||||
MCSubtargetInfo const &STI;
|
||||
SMLoc Loc;
|
||||
bool ReportErrors;
|
||||
|
||||
public:
|
||||
typedef HexagonPacket::iterator iterator;
|
||||
|
||||
enum {
|
||||
SHUFFLE_SUCCESS = 0, ///< Successful operation.
|
||||
SHUFFLE_ERROR_INVALID, ///< Invalid bundle.
|
||||
SHUFFLE_ERROR_STORES, ///< No free slots for store insns.
|
||||
SHUFFLE_ERROR_LOADS, ///< No free slots for load insns.
|
||||
SHUFFLE_ERROR_BRANCHES, ///< No free slots for branch insns.
|
||||
SHUFFLE_ERROR_NOSLOTS, ///< No free slots for other insns.
|
||||
SHUFFLE_ERROR_SLOTS, ///< Over-subscribed slots.
|
||||
SHUFFLE_ERROR_ERRATA2, ///< Errata violation (v60).
|
||||
SHUFFLE_ERROR_STORE_LOAD_CONFLICT, ///< store/load conflict
|
||||
SHUFFLE_ERROR_UNKNOWN ///< Unknown error.
|
||||
};
|
||||
|
||||
explicit HexagonShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI);
|
||||
HexagonShuffler(MCContext &Context, bool ReportErrors,
|
||||
MCInstrInfo const &MCII, MCSubtargetInfo const &STI);
|
||||
|
||||
// Reset to initial state.
|
||||
void reset();
|
||||
@ -180,9 +167,8 @@ public:
|
||||
void append(MCInst const &ID, MCInst const *Extender, unsigned S);
|
||||
|
||||
// Return the error code for the last check or shuffling of the bundle.
|
||||
void setError(unsigned Err) { Error = Err; };
|
||||
unsigned getError() const { return (Error); };
|
||||
void reportError(llvm::Twine const &Msg);
|
||||
};
|
||||
}
|
||||
} // namespace llvm
|
||||
|
||||
#endif // HEXAGONSHUFFLER_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user