summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Hexagon/MCTargetDesc
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Hexagon/MCTargetDesc')
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp5
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h19
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp322
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h51
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp6
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp114
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h30
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp175
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h6
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp212
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h9
11 files changed, 598 insertions, 351 deletions
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
index 31da9fa06d0..b3ab6763281 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
@@ -655,7 +655,8 @@ public:
assert(HexagonMCInstrInfo::isBundle(Inst) &&
"Hexagon relaxInstruction only works on bundles");
- Res = HexagonMCInstrInfo::createBundle();
+ Res.setOpcode(Hexagon::BUNDLE);
+ Res.addOperand(MCOperand::createImm(Inst.getOperand(0).getImm()));
// Copy the results into the bundle.
bool Update = false;
for (auto &I : HexagonMCInstrInfo::bundleInstructions(Inst)) {
@@ -769,6 +770,6 @@ MCAsmBackend *llvm::createHexagonAsmBackend(Target const &T,
const MCTargetOptions &Options) {
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
- StringRef CPUString = Hexagon_MC::selectHexagonCPU(TT, CPU);
+ StringRef CPUString = Hexagon_MC::selectHexagonCPU(CPU);
return new HexagonAsmBackend(T, TT, OSABI, CPUString);
}
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
index d1a6d38797d..f5a37603375 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
@@ -68,8 +68,8 @@ namespace HexagonII {
SoloAXPos = 7,
SoloAXMask = 0x1,
// Only A-type instruction in first slot or nothing.
- SoloAin1Pos = 8,
- SoloAin1Mask = 0x1,
+ RestrictSlot1AOKPos = 8,
+ RestrictSlot1AOKMask = 0x1,
// Predicated instructions.
PredicatedPos = 9,
@@ -122,6 +122,16 @@ namespace HexagonII {
ExtentAlignPos = 33,
ExtentAlignMask = 0x3,
+ CofMax1Pos = 35,
+ CofMax1Mask = 0x1,
+ CofRelax1Pos = 36,
+ CofRelax1Mask = 0x1,
+ CofRelax2Pos = 37,
+ CofRelax2Mask = 0x1,
+
+ RestrictNoSlot1StorePos = 38,
+ RestrictNoSlot1StoreMask = 0x1,
+
// Addressing mode for load/store instructions.
AddrModePos = 41,
AddrModeMask = 0x7,
@@ -152,8 +162,9 @@ namespace HexagonII {
PrefersSlot3Pos = 56,
PrefersSlot3Mask = 0x1,
- CofMax1Pos = 60,
- CofMax1Mask = 0x1,
+ // v65
+ HasTmpDstPos = 59,
+ HasTmpDstMask = 0x1,
CVINewPos = 61,
CVINewMask = 0x1
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp
index 142070ad73b..53f3cba052b 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp
@@ -179,35 +179,6 @@ void HexagonMCChecker::init(MCInst const &MCI) {
}
}
- // Figure out register definitions that produce new values.
- if (HexagonMCInstrInfo::hasNewValue(MCII, MCI)) {
- unsigned R = HexagonMCInstrInfo::getNewValueOperand(MCII, MCI).getReg();
-
- 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)
- 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)));
-
- // 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();
-
- bool HasSubRegs = MCSubRegIterator(R2, &RI).isValid();
- for (MCRegAliasIterator SRI(R2, &RI, !HasSubRegs); SRI.isValid(); ++SRI)
- if (!MCSubRegIterator(*SRI, &RI).isValid())
- NewDefs[*SRI].push_back(NewSense::Def(
- PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI),
- HexagonMCInstrInfo::isFloat(MCII, MCI)));
- }
- }
-
// Figure out definitions of new predicate registers.
if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI))
for (unsigned i = MCID.getNumDefs(); i < MCID.getNumOperands(); ++i)
@@ -217,21 +188,6 @@ void HexagonMCChecker::init(MCInst const &MCI) {
if (isPredicateRegister(P))
NewPreds.insert(P);
}
-
- // Figure out uses of new values.
- if (HexagonMCInstrInfo::isNewValue(MCII, MCI)) {
- unsigned N = HexagonMCInstrInfo::getNewValueOperand(MCII, MCI).getReg();
-
- if (!MCSubRegIterator(N, &RI).isValid()) {
- // Super-registers cannot use new values.
- if (MCID.isBranch())
- NewUses[N] = NewSense::Jmp(
- HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNCJ);
- else
- NewUses[N] = NewSense::Use(
- PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI));
- }
- }
}
HexagonMCChecker::HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII,
@@ -242,13 +198,17 @@ HexagonMCChecker::HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII,
init();
}
+HexagonMCChecker::HexagonMCChecker(HexagonMCChecker const &Other,
+ MCSubtargetInfo const &STI,
+ bool CopyReportErrors)
+ : Context(Other.Context), MCB(Other.MCB), RI(Other.RI), MCII(Other.MCII),
+ STI(STI), ReportErrors(CopyReportErrors ? Other.ReportErrors : false) {}
+
bool HexagonMCChecker::check(bool FullCheck) {
- bool chkB = checkBranches();
bool chkP = checkPredicates();
bool chkNV = checkNewValues();
bool chkR = checkRegisters();
bool chkRRO = checkRegistersReadOnly();
- bool chkELB = checkEndloopBranches();
checkRegisterCurDefs();
bool chkS = checkSolo();
bool chkSh = true;
@@ -258,30 +218,14 @@ bool HexagonMCChecker::check(bool FullCheck) {
if (FullCheck)
chkSl = checkSlots();
bool chkAXOK = checkAXOK();
- bool chk = chkB && chkP && chkNV && chkR && chkRRO && chkELB && chkS &&
- chkSh && chkSl && chkAXOK;
+ bool chkCofMax1 = checkCOFMax1();
+ bool chkHWLoop = checkHWLoop();
+ bool chk = chkP && chkNV && chkR && chkRRO && chkS && chkSh && chkSl &&
+ chkAXOK && chkCofMax1 && chkHWLoop;
return chk;
}
-bool HexagonMCChecker::checkEndloopBranches() {
- for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
- MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, I);
- if (Desc.isBranch() || Desc.isCall()) {
- auto Inner = HexagonMCInstrInfo::isInnerLoop(MCB);
- if (Inner || HexagonMCInstrInfo::isOuterLoop(MCB)) {
- reportError(I.getLoc(),
- Twine("packet marked with `:endloop") +
- (Inner ? "0" : "1") + "' " +
- "cannot contain instructions that modify register " + "`" +
- Twine(RI.getName(Hexagon::PC)) + "'");
- return false;
- }
- }
- }
- return true;
-}
-
static bool isDuplexAGroup(unsigned Opcode) {
switch (Opcode) {
case Hexagon::SA1_addi:
@@ -355,6 +299,65 @@ bool HexagonMCChecker::checkAXOK() {
return true;
}
+void HexagonMCChecker::reportBranchErrors() {
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
+ MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, I);
+ if (Desc.isBranch() || Desc.isCall() || Desc.isReturn())
+ reportNote(I.getLoc(), "Branching instruction");
+ }
+}
+
+bool HexagonMCChecker::checkHWLoop() {
+ if (!HexagonMCInstrInfo::isInnerLoop(MCB) &&
+ !HexagonMCInstrInfo::isOuterLoop(MCB))
+ return true;
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
+ MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, I);
+ if (Desc.isBranch() || Desc.isCall() || Desc.isReturn()) {
+ reportError(MCB.getLoc(),
+ "Branches cannot be in a packet with hardware loops");
+ reportBranchErrors();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool HexagonMCChecker::checkCOFMax1() {
+ SmallVector<MCInst const *, 2> BranchLocations;
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
+ MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, I);
+ if (Desc.isBranch() || Desc.isCall() || Desc.isReturn())
+ BranchLocations.push_back(&I);
+ }
+ for (unsigned J = 0, N = BranchLocations.size(); J < N; ++J) {
+ MCInst const &I = *BranchLocations[J];
+ if (HexagonMCInstrInfo::isCofMax1(MCII, I)) {
+ bool Relax1 = HexagonMCInstrInfo::isCofRelax1(MCII, I);
+ bool Relax2 = HexagonMCInstrInfo::isCofRelax2(MCII, I);
+ if (N > 1 && !Relax1 && !Relax2) {
+ reportError(I.getLoc(),
+ "Instruction may not be in a packet with other branches");
+ reportBranchErrors();
+ return false;
+ }
+ if (N > 1 && J == 0 && !Relax1) {
+ reportError(I.getLoc(),
+ "Instruction may not be the first branch in packet");
+ reportBranchErrors();
+ return false;
+ }
+ if (N > 1 && J == 1 && !Relax2) {
+ reportError(I.getLoc(),
+ "Instruction may not be the second branch in packet");
+ reportBranchErrors();
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
bool HexagonMCChecker::checkSlots() {
unsigned slotsUsed = 0;
for (auto HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) {
@@ -374,45 +377,6 @@ bool HexagonMCChecker::checkSlots() {
return true;
}
-// Check legal use of branches.
-bool HexagonMCChecker::checkBranches() {
- if (HexagonMCInstrInfo::isBundle(MCB)) {
- bool hasConditional = false;
- unsigned Branches = 0, Conditional = HEXAGON_PRESHUFFLE_PACKET_SIZE,
- Unconditional = HEXAGON_PRESHUFFLE_PACKET_SIZE;
-
- for (unsigned i = HexagonMCInstrInfo::bundleInstructionsOffset;
- i < MCB.size(); ++i) {
- MCInst const &MCI = *MCB.begin()[i].getInst();
-
- if (HexagonMCInstrInfo::isImmext(MCI))
- continue;
- if (HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch() ||
- HexagonMCInstrInfo::getDesc(MCII, MCI).isCall()) {
- ++Branches;
- if (HexagonMCInstrInfo::isPredicated(MCII, MCI) ||
- HexagonMCInstrInfo::isPredicatedNew(MCII, MCI)) {
- hasConditional = true;
- Conditional = i; // Record the position of the conditional branch.
- } else {
- Unconditional = i; // Record the position of the unconditional branch.
- }
- }
- }
-
- if (Branches > 1)
- if (!hasConditional || Conditional > Unconditional) {
- // Error out if more than one unconditional branch or
- // the conditional branch appears after the unconditional one.
- reportError(
- "unconditional branch cannot precede another branch in packet");
- return false;
- }
- }
-
- return true;
-}
-
// Check legal use of predicate registers.
bool HexagonMCChecker::checkPredicates() {
// Check for proper use of new predicate registers.
@@ -446,16 +410,85 @@ bool HexagonMCChecker::checkPredicates() {
// Check legal use of new values.
bool HexagonMCChecker::checkNewValues() {
- for (auto &I : NewUses) {
- unsigned R = I.first;
- NewSense &US = I.second;
-
- if (!hasValidNewValueDef(US, NewDefs[R])) {
- reportErrorNewValue(R);
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
+ if (!HexagonMCInstrInfo::isNewValue(MCII, I))
+ continue;
+ auto Consumer = HexagonMCInstrInfo::predicateInfo(MCII, I);
+ bool Branch = HexagonMCInstrInfo::getDesc(MCII, I).isBranch();
+ MCOperand const &Op = HexagonMCInstrInfo::getNewValueOperand(MCII, I);
+ assert(Op.isReg());
+ auto Producer = registerProducer(Op.getReg(), Consumer);
+ if (std::get<0>(Producer) == nullptr) {
+ reportError(I.getLoc(), "New value register consumer has no producer");
+ return false;
+ }
+ if (!RelaxNVChecks) {
+ // Checks that statically prove correct new value consumption
+ if (std::get<2>(Producer).isPredicated() &&
+ (!Consumer.isPredicated() ||
+ llvm::HexagonMCInstrInfo::getType(MCII, I) == HexagonII::TypeNCJ)) {
+ reportNote(
+ std::get<0>(Producer)->getLoc(),
+ "Register producer is predicated and consumer is unconditional");
+ reportError(I.getLoc(),
+ "Instruction does not have a valid new register producer");
+ return false;
+ }
+ if (std::get<2>(Producer).Register != Hexagon::NoRegister &&
+ std::get<2>(Producer).Register != Consumer.Register) {
+ reportNote(std::get<0>(Producer)->getLoc(),
+ "Register producer does not use the same predicate "
+ "register as the consumer");
+ reportError(I.getLoc(),
+ "Instruction does not have a valid new register producer");
+ return false;
+ }
+ }
+ if (std::get<2>(Producer).Register == Consumer.Register &&
+ Consumer.PredicatedTrue != std::get<2>(Producer).PredicatedTrue) {
+ reportNote(
+ std::get<0>(Producer)->getLoc(),
+ "Register producer has the opposite predicate sense as consumer");
+ reportError(I.getLoc(),
+ "Instruction does not have a valid new register producer");
+ return false;
+ }
+ MCInstrDesc const &Desc =
+ HexagonMCInstrInfo::getDesc(MCII, *std::get<0>(Producer));
+ if (Desc.OpInfo[std::get<1>(Producer)].RegClass ==
+ Hexagon::DoubleRegsRegClassID) {
+ reportNote(std::get<0>(Producer)->getLoc(),
+ "Double registers cannot be new-value producers");
+ reportError(I.getLoc(),
+ "Instruction does not have a valid new register producer");
+ return false;
+ }
+ if ((Desc.mayLoad() && std::get<1>(Producer) == 1) ||
+ (Desc.mayStore() && std::get<1>(Producer) == 0)) {
+ unsigned Mode =
+ HexagonMCInstrInfo::getAddrMode(MCII, *std::get<0>(Producer));
+ StringRef ModeError;
+ if (Mode == HexagonII::AbsoluteSet)
+ ModeError = "Absolute-set";
+ if (Mode == HexagonII::PostInc)
+ ModeError = "Auto-increment";
+ if (!ModeError.empty()) {
+ reportNote(std::get<0>(Producer)->getLoc(),
+ ModeError + " registers cannot be a new-value "
+ "producer");
+ reportError(I.getLoc(),
+ "Instruction does not have a valid new register producer");
+ return false;
+ }
+ }
+ if (Branch && HexagonMCInstrInfo::isFloat(MCII, *std::get<0>(Producer))) {
+ reportNote(std::get<0>(Producer)->getLoc(),
+ "FPU instructions cannot be new-value producers for jumps");
+ reportError(I.getLoc(),
+ "Instruction does not have a valid new register producer");
return false;
}
}
-
return true;
}
@@ -489,6 +522,34 @@ bool HexagonMCChecker::registerUsed(unsigned Register) {
return false;
}
+std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
+HexagonMCChecker::registerProducer(
+ unsigned Register, HexagonMCInstrInfo::PredicateInfo ConsumerPredicate) {
+ std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
+ WrongSense;
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
+ MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, I);
+ auto ProducerPredicate = HexagonMCInstrInfo::predicateInfo(MCII, I);
+ for (unsigned J = 0, N = Desc.getNumDefs(); J < N; ++J)
+ for (auto K = MCRegAliasIterator(I.getOperand(J).getReg(), &RI, true);
+ K.isValid(); ++K)
+ if (*K == Register) {
+ if (RelaxNVChecks ||
+ (ProducerPredicate.Register == ConsumerPredicate.Register &&
+ (ProducerPredicate.Register == Hexagon::NoRegister ||
+ ProducerPredicate.PredicatedTrue ==
+ ConsumerPredicate.PredicatedTrue)))
+ return std::make_tuple(&I, J, ProducerPredicate);
+ std::get<0>(WrongSense) = &I;
+ std::get<1>(WrongSense) = J;
+ std::get<2>(WrongSense) = ProducerPredicate;
+ }
+ if (Register == Hexagon::VTMP && HexagonMCInstrInfo::hasTmpDst(MCII, I))
+ return std::make_tuple(&I, 0, HexagonMCInstrInfo::PredicateInfo());
+ }
+ return WrongSense;
+}
+
void HexagonMCChecker::checkRegisterCurDefs() {
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
if (HexagonMCInstrInfo::isCVINew(MCII, I) &&
@@ -638,35 +699,6 @@ void HexagonMCChecker::compoundRegisterMap(unsigned &Register) {
}
}
-bool HexagonMCChecker::hasValidNewValueDef(const NewSense &Use,
- const NewSenseList &Defs) const {
- bool Strict = !RelaxNVChecks;
-
- for (unsigned i = 0, n = Defs.size(); i < n; ++i) {
- const NewSense &Def = Defs[i];
- // NVJ cannot use a new FP value [7.6.1]
- if (Use.IsNVJ && (Def.IsFloat || Def.PredReg != 0))
- continue;
- // If the definition was not predicated, then it does not matter if
- // the use is.
- if (Def.PredReg == 0)
- return true;
- // With the strict checks, both the definition and the use must be
- // predicated on the same register and condition.
- if (Strict) {
- if (Def.PredReg == Use.PredReg && Def.Cond == Use.Cond)
- return true;
- } else {
- // With the relaxed checks, if the definition was predicated, the only
- // detectable violation is if the use is predicated on the opposing
- // condition, otherwise, it's ok.
- if (Def.PredReg != Use.PredReg || Def.Cond == Use.Cond)
- return true;
- }
- }
- return false;
-}
-
void HexagonMCChecker::reportErrorRegisters(unsigned Register) {
reportError("register `" + Twine(RI.getName(Register)) +
"' modified more than once");
@@ -687,6 +719,14 @@ void HexagonMCChecker::reportError(SMLoc Loc, Twine const &Msg) {
Context.reportError(Loc, Msg);
}
+void HexagonMCChecker::reportNote(SMLoc Loc, llvm::Twine const &Msg) {
+ if (ReportErrors) {
+ auto SM = Context.getSourceManager();
+ if (SM)
+ SM->PrintMessage(Loc, SourceMgr::DK_Note, Msg);
+ }
+}
+
void HexagonMCChecker::reportWarning(Twine const &Msg) {
if (ReportErrors) {
auto SM = Context.getSourceManager();
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h
index 957950156e8..7577baace20 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h
@@ -15,6 +15,7 @@
#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCCHECKER_H
#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCCHECKER_H
+#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
@@ -48,40 +49,6 @@ class HexagonMCChecker {
using DefsIterator = DenseMap<unsigned, PredSet>::iterator;
DenseMap<unsigned, PredSet> Defs;
- /// Information about how a new-value register is defined or used:
- /// PredReg = predicate register, 0 if use/def not predicated,
- /// Cond = true/false for if(PredReg)/if(!PredReg) respectively,
- /// IsFloat = true if definition produces a floating point value
- /// (not valid for uses),
- /// IsNVJ = true if the use is a new-value branch (not valid for
- /// definitions).
- struct NewSense {
- unsigned PredReg;
- bool IsFloat, IsNVJ, Cond;
-
- // The special-case "constructors":
- static NewSense Jmp(bool isNVJ) {
- 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};
- return NS;
- }
- static NewSense Def(unsigned PR, bool True, bool Float) {
- NewSense NS = {/*PredReg=*/PR, /*IsFloat=*/Float, /*IsNVJ=*/false,
- /*Cond=*/True};
- return NS;
- }
- };
-
- /// Set of definitions that produce new register:
- using NewSenseList = SmallVector<NewSense, 2>;
- using NewDefsIterator = DenseMap<unsigned, NewSenseList>::iterator;
- DenseMap<unsigned, NewSenseList> NewDefs;
-
/// Set of weak definitions whose clashes should be enforced selectively.
using SoftDefsIterator = std::set<unsigned>::iterator;
std::set<unsigned> SoftDefs;
@@ -102,10 +69,6 @@ class HexagonMCChecker {
using UsesIterator = std::set<unsigned>::iterator;
std::set<unsigned> Uses;
- /// Set of new values used: new register, if new-value jump.
- using NewUsesIterator = DenseMap<unsigned, NewSense>::iterator;
- DenseMap<unsigned, NewSense> NewUses;
-
/// Pre-defined set of read-only registers.
using ReadOnlyIterator = std::set<unsigned>::iterator;
std::set<unsigned> ReadOnly;
@@ -115,6 +78,9 @@ class HexagonMCChecker {
void initReg(MCInst const &, unsigned, unsigned &PredReg, bool &isTrue);
bool registerUsed(unsigned Register);
+ std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>
+ registerProducer(unsigned Register,
+ HexagonMCInstrInfo::PredicateInfo Predicated);
// Checks performed.
bool checkBranches();
@@ -122,12 +88,13 @@ class HexagonMCChecker {
bool checkNewValues();
bool checkRegisters();
bool checkRegistersReadOnly();
- bool checkEndloopBranches();
void checkRegisterCurDefs();
bool checkSolo();
bool checkShuffle();
bool checkSlots();
bool checkAXOK();
+ bool checkHWLoop();
+ bool checkCOFMax1();
static void compoundRegisterMap(unsigned &);
@@ -141,19 +108,21 @@ class HexagonMCChecker {
Hexagon::LC1 == R);
}
- bool hasValidNewValueDef(const NewSense &Use, const NewSenseList &Defs) const;
-
public:
explicit HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII,
MCSubtargetInfo const &STI, MCInst &mcb,
const MCRegisterInfo &ri, bool ReportErrors = true);
+ explicit HexagonMCChecker(HexagonMCChecker const &Check,
+ MCSubtargetInfo const &STI, bool CopyReportErrors);
bool check(bool FullCheck = true);
void reportErrorRegisters(unsigned Register);
void reportErrorNewValue(unsigned Register);
void reportError(SMLoc Loc, Twine const &Msg);
+ void reportNote(SMLoc Loc, Twine const &Msg);
void reportError(Twine const &Msg);
void reportWarning(Twine const &Msg);
+ void reportBranchErrors();
};
} // end namespace llvm
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp
index c5f3d434759..4c18af60efd 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp
@@ -305,7 +305,7 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
case Hexagon::L4_return_tnew_pt:
case Hexagon::L4_return_fnew_pt:
// [if ([!]p0[.new])] dealloc_return
- SrcReg = MCI.getOperand(0).getReg();
+ SrcReg = MCI.getOperand(1).getReg();
if (Hexagon::P0 == SrcReg) {
return HexagonII::HSIG_L2;
}
@@ -388,7 +388,7 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
}
break;
case Hexagon::S2_allocframe:
- if (inRange<5, 3>(MCI, 0))
+ if (inRange<5, 3>(MCI, 2))
return HexagonII::HSIG_S2;
break;
//
@@ -742,7 +742,7 @@ MCInst HexagonMCInstrInfo::deriveSubInst(MCInst const &Inst) {
break; // 1,2,3 SUBInst $Rx = add($_src_, $Rs)
case Hexagon::S2_allocframe:
Result.setOpcode(Hexagon::SS2_allocframe);
- addOps(Result, Inst, 0);
+ addOps(Result, Inst, 2);
break; // 1 SUBInst allocframe(#$u5_3)
case Hexagon::A2_andir:
if (minConstant(Inst, 2) == 255) {
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
index 94919b1e486..19308cd425e 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
@@ -33,6 +33,10 @@
using namespace llvm;
+bool HexagonMCInstrInfo::PredicateInfo::isPredicated() const {
+ return Register != Hexagon::NoRegister;
+}
+
Hexagon::PacketIterator::PacketIterator(MCInstrInfo const &MCII,
MCInst const &Inst)
: MCII(MCII), BundleCurrent(Inst.begin() +
@@ -50,6 +54,7 @@ Hexagon::PacketIterator &Hexagon::PacketIterator::operator++() {
if (DuplexCurrent == DuplexEnd) {
DuplexCurrent = BundleEnd;
DuplexEnd = BundleEnd;
+ ++BundleCurrent;
}
return *this;
}
@@ -90,6 +95,7 @@ void HexagonMCInstrInfo::addConstExtender(MCContext &Context,
// Create the extender.
MCInst *XMCI =
new (Context) MCInst(HexagonMCInstrInfo::deriveExtender(MCII, MCI, exOp));
+ XMCI->setLoc(MCI.getLoc());
MCB.addOperand(MCOperand::createInst(XMCI));
}
@@ -131,7 +137,7 @@ bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII,
// Examine the packet and convert pairs of instructions to duplex
// instructions when possible.
MCInst InstBundlePreDuplex = MCInst(MCB);
- if (!HexagonDisableDuplex) {
+ if (STI.getFeatureBits() [Hexagon::FeatureDuplex]) {
SmallVector<DuplexCandidate, 8> possibleDuplexes;
possibleDuplexes =
HexagonMCInstrInfo::getDuplexPossibilties(MCII, STI, MCB);
@@ -169,13 +175,6 @@ void HexagonMCInstrInfo::clampExtended(MCInstrInfo const &MCII,
}
}
-MCInst HexagonMCInstrInfo::createBundle() {
- MCInst Result;
- Result.setOpcode(Hexagon::BUNDLE);
- Result.addOperand(MCOperand::createImm(0));
- return Result;
-}
-
MCInst HexagonMCInstrInfo::deriveExtender(MCInstrInfo const &MCII,
MCInst const &Inst,
MCOperand const &MO) {
@@ -233,6 +232,13 @@ unsigned HexagonMCInstrInfo::getMemAccessSize(MCInstrInfo const &MCII,
return HexagonII::getMemAccessSizeInBytes(HexagonII::MemAccessSize(S));
}
+unsigned HexagonMCInstrInfo::getAddrMode(MCInstrInfo const &MCII,
+ MCInst const &MCI) {
+ const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
+ return static_cast<unsigned>((F >> HexagonII::AddrModePos) &
+ HexagonII::AddrModeMask);
+}
+
MCInstrDesc const &HexagonMCInstrInfo::getDesc(MCInstrInfo const &MCII,
MCInst const &MCI) {
return MCII.get(MCI.getOpcode());
@@ -365,13 +371,20 @@ unsigned short HexagonMCInstrInfo::getNewValueOp(MCInstrInfo const &MCII,
MCOperand const &HexagonMCInstrInfo::getNewValueOperand(MCInstrInfo const &MCII,
MCInst const &MCI) {
- unsigned O = HexagonMCInstrInfo::getNewValueOp(MCII, MCI);
- MCOperand const &MCO = MCI.getOperand(O);
-
- assert((HexagonMCInstrInfo::isNewValue(MCII, MCI) ||
- HexagonMCInstrInfo::hasNewValue(MCII, MCI)) &&
- MCO.isReg());
- return (MCO);
+ if (HexagonMCInstrInfo::hasTmpDst(MCII, MCI)) {
+ // VTMP doesn't actually exist in the encodings for these 184
+ // 3 instructions so go ahead and create it here.
+ static MCOperand MCO = MCOperand::createReg(Hexagon::VTMP);
+ return (MCO);
+ } else {
+ unsigned O = HexagonMCInstrInfo::getNewValueOp(MCII, MCI);
+ MCOperand const &MCO = MCI.getOperand(O);
+
+ assert((HexagonMCInstrInfo::isNewValue(MCII, MCI) ||
+ HexagonMCInstrInfo::hasNewValue(MCII, MCI)) &&
+ MCO.isReg());
+ return (MCO);
+ }
}
/// Return the new value or the newly produced value.
@@ -439,8 +452,8 @@ bool HexagonMCInstrInfo::hasDuplex(MCInstrInfo const &MCII, MCInst const &MCI) {
if (!HexagonMCInstrInfo::isBundle(MCI))
return false;
- for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCI)) {
- if (HexagonMCInstrInfo::isDuplex(MCII, I))
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCI)) {
+ if (HexagonMCInstrInfo::isDuplex(MCII, *I.getInst()))
return true;
}
@@ -451,7 +464,7 @@ bool HexagonMCInstrInfo::hasExtenderForIndex(MCInst const &MCB, size_t Index) {
return extenderForIndex(MCB, Index) != nullptr;
}
-bool HexagonMCInstrInfo::hasImmExt( MCInst const &MCI) {
+bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) {
if (!HexagonMCInstrInfo::isBundle(MCI))
return false;
@@ -540,6 +553,18 @@ bool HexagonMCInstrInfo::isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI) {
return ((F >> HexagonII::CofMax1Pos) & HexagonII::CofMax1Mask);
}
+bool HexagonMCInstrInfo::isCofRelax1(MCInstrInfo const &MCII,
+ MCInst const &MCI) {
+ const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
+ return ((F >> HexagonII::CofRelax1Pos) & HexagonII::CofRelax1Mask);
+}
+
+bool HexagonMCInstrInfo::isCofRelax2(MCInstrInfo const &MCII,
+ MCInst const &MCI) {
+ const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
+ return ((F >> HexagonII::CofRelax2Pos) & HexagonII::CofRelax2Mask);
+}
+
bool HexagonMCInstrInfo::isCompound(MCInstrInfo const &MCII,
MCInst const &MCI) {
return (getType(MCII, MCI) == HexagonII::TypeCJ);
@@ -576,6 +601,11 @@ bool HexagonMCInstrInfo::isFloat(MCInstrInfo const &MCII, MCInst const &MCI) {
return ((F >> HexagonII::FPPos) & HexagonII::FPMask);
}
+bool HexagonMCInstrInfo::isHVX(MCInstrInfo const &MCII, MCInst const &MCI) {
+ const uint64_t V = getType(MCII, MCI);
+ return HexagonII::TypeCVI_FIRST <= V && V <= HexagonII::TypeCVI_LAST;
+}
+
bool HexagonMCInstrInfo::isImmext(MCInst const &MCI) {
return MCI.getOpcode() == Hexagon::A4_ext;
}
@@ -655,10 +685,18 @@ bool HexagonMCInstrInfo::isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI) {
}
/// Return whether the insn can be packaged only with an A-type insn in slot #1.
-bool HexagonMCInstrInfo::isSoloAin1(MCInstrInfo const &MCII,
- MCInst const &MCI) {
+bool HexagonMCInstrInfo::isRestrictSlot1AOK(MCInstrInfo const &MCII,
+ MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
- return ((F >> HexagonII::SoloAin1Pos) & HexagonII::SoloAin1Mask);
+ return ((F >> HexagonII::RestrictSlot1AOKPos) &
+ HexagonII::RestrictSlot1AOKMask);
+}
+
+bool HexagonMCInstrInfo::isRestrictNoSlot1Store(MCInstrInfo const &MCII,
+ MCInst const &MCI) {
+ const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
+ return ((F >> HexagonII::RestrictNoSlot1StorePos) &
+ HexagonII::RestrictNoSlot1StoreMask);
}
/// Return whether the insn is solo, i.e., cannot be in a packet.
@@ -673,12 +711,6 @@ bool HexagonMCInstrInfo::isMemReorderDisabled(MCInst const &MCI) {
return (Flags & memReorderDisabledMask) != 0;
}
-bool HexagonMCInstrInfo::isMemStoreReorderEnabled(MCInst const &MCI) {
- assert(isBundle(MCI));
- auto Flags = MCI.getOperand(0).getImm();
- return (Flags & memStoreReorderEnabledMask) != 0;
-}
-
bool HexagonMCInstrInfo::isSubInstruction(MCInst const &MCI) {
switch (MCI.getOpcode()) {
default:
@@ -800,12 +832,29 @@ void HexagonMCInstrInfo::padEndloop(MCInst &MCB, MCContext &Context) {
MCB.addOperand(MCOperand::createInst(new (Context) MCInst(Nop)));
}
+HexagonMCInstrInfo::PredicateInfo
+HexagonMCInstrInfo::predicateInfo(MCInstrInfo const &MCII, MCInst const &MCI) {
+ if (!isPredicated(MCII, MCI))
+ return {0, 0, false};
+ MCInstrDesc const &Desc = getDesc(MCII, MCI);
+ for (auto I = Desc.getNumDefs(), N = Desc.getNumOperands(); I != N; ++I)
+ if (Desc.OpInfo[I].RegClass == Hexagon::PredRegsRegClassID)
+ return {MCI.getOperand(I).getReg(), I, isPredicatedTrue(MCII, MCI)};
+ return {0, 0, false};
+}
+
bool HexagonMCInstrInfo::prefersSlot3(MCInstrInfo const &MCII,
MCInst const &MCI) {
const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
return (F >> HexagonII::PrefersSlot3Pos) & HexagonII::PrefersSlot3Mask;
}
+/// return true if instruction has hasTmpDst attribute.
+bool HexagonMCInstrInfo::hasTmpDst(MCInstrInfo const &MCII, MCInst const &MCI) {
+ const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
+ return (F >> HexagonII::HasTmpDstPos) & HexagonII::HasTmpDstMask;
+}
+
void HexagonMCInstrInfo::replaceDuplex(MCContext &Context, MCInst &MCB,
DuplexCandidate Candidate) {
assert(Candidate.packetIndexI < MCB.size());
@@ -833,13 +882,6 @@ void HexagonMCInstrInfo::setMemReorderDisabled(MCInst &MCI) {
assert(isMemReorderDisabled(MCI));
}
-void HexagonMCInstrInfo::setMemStoreReorderEnabled(MCInst &MCI) {
- assert(isBundle(MCI));
- MCOperand &Operand = MCI.getOperand(0);
- Operand.setImm(Operand.getImm() | memStoreReorderEnabledMask);
- assert(isMemStoreReorderEnabled(MCI));
-}
-
void HexagonMCInstrInfo::setOuterLoop(MCInst &MCI) {
assert(isBundle(MCI));
MCOperand &Operand = MCI.getOperand(0);
@@ -854,7 +896,7 @@ unsigned HexagonMCInstrInfo::SubregisterBit(unsigned Consumer,
if (Producer >= Hexagon::W0 && Producer <= Hexagon::W15)
if (Consumer >= Hexagon::V0 && Consumer <= Hexagon::V31)
return (Consumer - Hexagon::V0) & 0x1;
- if (Consumer == Producer2)
- return 0x1;
+ if (Producer2 != Hexagon::NoRegister)
+ return Consumer == Producer;
return 0;
}
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
index b6b01709a6c..28d89429266 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
@@ -75,10 +75,6 @@ int64_t const outerLoopMask = 1 << outerLoopOffset;
size_t const memReorderDisabledOffset = 2;
int64_t const memReorderDisabledMask = 1 << memReorderDisabledOffset;
-// allow re-ordering of memory stores by default stores cannot be re-ordered
-size_t const memStoreReorderEnabledOffset = 3;
-int64_t const memStoreReorderEnabledMask = 1 << memStoreReorderEnabledOffset;
-
size_t const bundleInstructionsOffset = 1;
void addConstant(MCInst &MI, uint64_t Value, MCContext &Context);
@@ -110,8 +106,6 @@ MCInst deriveSubInst(MCInst const &Inst);
// Clamp off upper 26 bits of extendable operand for emission
void clampExtended(MCInstrInfo const &MCII, MCContext &Context, MCInst &MCI);
-MCInst createBundle();
-
// Return the extender for instruction at Index or nullptr if none
MCInst const *extenderForIndex(MCInst const &MCB, size_t Index);
void extendIfNeeded(MCContext &Context, MCInstrInfo const &MCII, MCInst &MCB,
@@ -120,6 +114,9 @@ void extendIfNeeded(MCContext &Context, MCInstrInfo const &MCII, MCInst &MCB,
// Return memory access size in bytes
unsigned getMemAccessSize(MCInstrInfo const &MCII, MCInst const &MCI);
+// Return memory access size
+unsigned getAddrMode(MCInstrInfo const &MCII, MCInst const &MCI);
+
MCInstrDesc const &getDesc(MCInstrInfo const &MCII, MCInst const &MCI);
// Return which duplex group this instruction belongs to
@@ -184,6 +181,7 @@ bool hasImmExt(MCInst const &MCI);
// Return whether the instruction is a legal new-value producer.
bool hasNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
bool hasNewValue2(MCInstrInfo const &MCII, MCInst const &MCI);
+bool hasTmpDst(MCInstrInfo const &MCII, MCInst const &MCI);
unsigned iClassOfDuplexPair(unsigned Ga, unsigned Gb);
int64_t minConstant(MCInst const &MCI, size_t Index);
@@ -209,6 +207,8 @@ bool isBundle(MCInst const &MCI);
// Return whether the insn is an actual insn.
bool isCanon(MCInstrInfo const &MCII, MCInst const &MCI);
bool isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI);
+bool isCofRelax1(MCInstrInfo const &MCII, MCInst const &MCI);
+bool isCofRelax2(MCInstrInfo const &MCII, MCInst const &MCI);
bool isCompound(MCInstrInfo const &MCII, MCInst const &MCI);
// Return whether the instruction needs to be constant extended.
@@ -236,6 +236,8 @@ bool isExtended(MCInstrInfo const &MCII, MCInst const &MCI);
/// Return whether it is a floating-point insn.
bool isFloat(MCInstrInfo const &MCII, MCInst const &MCI);
+bool isHVX(MCInstrInfo const &MCII, MCInst const &MCI);
+
// Returns whether this instruction is an immediate extender
bool isImmext(MCInst const &MCI);
@@ -248,7 +250,6 @@ bool isIntReg(unsigned Reg);
// Is this register suitable for use in a duplex subinst
bool isIntRegForSubInst(unsigned Reg);
bool isMemReorderDisabled(MCInst const &MCI);
-bool isMemStoreReorderEnabled(MCInst const &MCI);
// Return whether the insn is a new-value consumer.
bool isNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
@@ -283,7 +284,8 @@ bool isSolo(MCInstrInfo const &MCII, MCInst const &MCI);
bool isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI);
/// Return whether the insn can be packaged only with an A-type insn in slot #1.
-bool isSoloAin1(MCInstrInfo const &MCII, MCInst const &MCI);
+bool isRestrictSlot1AOK(MCInstrInfo const &MCII, MCInst const &MCI);
+bool isRestrictNoSlot1Store(MCInstrInfo const &MCII, MCInst const &MCI);
bool isSubInstruction(MCInst const &MCI);
bool isVector(MCInstrInfo const &MCII, MCInst const &MCI);
bool mustExtend(MCExpr const &Expr);
@@ -291,6 +293,17 @@ bool mustNotExtend(MCExpr const &Expr);
// Pad the bundle with nops to satisfy endloop requirements
void padEndloop(MCInst &MCI, MCContext &Context);
+class PredicateInfo {
+public:
+ PredicateInfo() : Register(0), Operand(0), PredicatedTrue(false) {}
+ PredicateInfo(unsigned Register, unsigned Operand, bool PredicatedTrue)
+ : Register(Register), Operand(Operand), PredicatedTrue(PredicatedTrue) {}
+ bool isPredicated() const;
+ unsigned Register;
+ unsigned Operand;
+ bool PredicatedTrue;
+};
+PredicateInfo predicateInfo(MCInstrInfo const &MCII, MCInst const &MCI);
bool prefersSlot3(MCInstrInfo const &MCII, MCInst const &MCI);
// Replace the instructions inside MCB, represented by Candidate
@@ -300,7 +313,6 @@ bool s27_2_reloc(MCExpr const &Expr);
// Marks a bundle as endloop0
void setInnerLoop(MCInst &MCI);
void setMemReorderDisabled(MCInst &MCI);
-void setMemStoreReorderEnabled(MCInst &MCI);
void setMustExtend(MCExpr const &Expr, bool Val = true);
void setMustNotExtend(MCExpr const &Expr, bool Val = true);
void setS27_2_reloc(MCExpr const &Expr, bool Val = true);
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
index 6f48169be8c..c6f67d64b22 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
@@ -13,11 +13,13 @@
#include "MCTargetDesc/HexagonMCTargetDesc.h"
#include "Hexagon.h"
+#include "HexagonDepArch.h"
#include "HexagonTargetStreamer.h"
#include "MCTargetDesc/HexagonInstPrinter.h"
#include "MCTargetDesc/HexagonMCAsmInfo.h"
#include "MCTargetDesc/HexagonMCELFStreamer.h"
#include "MCTargetDesc/HexagonMCInstrInfo.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmBackend.h"
@@ -57,41 +59,55 @@ cl::opt<bool> llvm::HexagonDisableDuplex
("mno-pairing",
cl::desc("Disable looking for duplex instructions for Hexagon"));
-static cl::opt<bool> HexagonV4ArchVariant("mv4", cl::Hidden, cl::init(false),
- cl::desc("Build for Hexagon V4"));
+namespace { // These flags are to be deprecated
+cl::opt<bool> MV4("mv4", cl::Hidden, cl::desc("Build for Hexagon V4"),
+ cl::init(false));
+cl::opt<bool> MV5("mv5", cl::Hidden, cl::desc("Build for Hexagon V5"),
+ cl::init(false));
+cl::opt<bool> MV55("mv55", cl::Hidden, cl::desc("Build for Hexagon V55"),
+ cl::init(false));
+cl::opt<bool> MV60("mv60", cl::Hidden, cl::desc("Build for Hexagon V60"),
+ cl::init(false));
+cl::opt<bool> MV62("mv62", cl::Hidden, cl::desc("Build for Hexagon V62"),
+ cl::init(false));
+cl::opt<bool> MV65("mv65", cl::Hidden, cl::desc("Build for Hexagon V65"),
+ cl::init(false));
+} // namespace
+
+cl::opt<Hexagon::ArchEnum>
+ EnableHVX("mhvx",
+ cl::desc("Enable Hexagon Vector eXtensions"),
+ cl::values(
+ clEnumValN(Hexagon::ArchEnum::V60, "v60", "Build for HVX v60"),
+ clEnumValN(Hexagon::ArchEnum::V62, "v62", "Build for HVX v62"),
+ clEnumValN(Hexagon::ArchEnum::V65, "v65", "Build for HVX v65"),
+ // Sentinal for no value specified
+ clEnumValN(Hexagon::ArchEnum::V5, "", "")),
+ // Sentinal for flag not present
+ cl::init(Hexagon::ArchEnum::V4), cl::ValueOptional);
+static cl::opt<bool>
+ DisableHVX("mno-hvx", cl::Hidden, cl::desc("Disable Hexagon Vector eXtensions"));
-static cl::opt<bool> HexagonV5ArchVariant("mv5", cl::Hidden, cl::init(false),
- cl::desc("Build for Hexagon V5"));
-
-static cl::opt<bool> HexagonV55ArchVariant("mv55", cl::Hidden, cl::init(false),
- cl::desc("Build for Hexagon V55"));
-
-static cl::opt<bool> HexagonV60ArchVariant("mv60", cl::Hidden, cl::init(false),
- cl::desc("Build for Hexagon V60"));
-
-static cl::opt<bool> HexagonV62ArchVariant("mv62", cl::Hidden, cl::init(false),
- cl::desc("Build for Hexagon V62"));
-
-static cl::opt<bool> EnableHVX("mhvx", cl::Hidden, cl::init(false),
- cl::desc("Enable Hexagon Vector Extension (HVX)"));
static StringRef DefaultArch = "hexagonv60";
static StringRef HexagonGetArchVariant() {
- if (HexagonV4ArchVariant)
+ if (MV4)
return "hexagonv4";
- if (HexagonV5ArchVariant)
+ if (MV5)
return "hexagonv5";
- if (HexagonV55ArchVariant)
+ if (MV55)
return "hexagonv55";
- if (HexagonV60ArchVariant)
+ if (MV60)
return "hexagonv60";
- if (HexagonV62ArchVariant)
+ if (MV62)
return "hexagonv62";
+ if (MV65)
+ return "hexagonv65";
return "";
}
-StringRef Hexagon_MC::selectHexagonCPU(const Triple &TT, StringRef CPU) {
+StringRef Hexagon_MC::selectHexagonCPU(StringRef CPU) {
StringRef ArchV = HexagonGetArchVariant();
if (!ArchV.empty() && !CPU.empty()) {
if (ArchV != CPU)
@@ -146,7 +162,11 @@ public:
OS << Indent << InstTxt << Separator;
HeadTail = HeadTail.second.split('\n');
}
- OS << "\t}" << PacketBundle.second;
+
+ if (HexagonMCInstrInfo::isMemReorderDisabled(Inst))
+ OS << "\n\t}:mem_noshuf" << PacketBundle.second;
+ else
+ OS << "\t}" << PacketBundle.second;
}
};
@@ -251,15 +271,37 @@ static bool LLVM_ATTRIBUTE_UNUSED checkFeature(MCSubtargetInfo* STI, uint64_t F)
return (FB & (1ULL << F)) != 0;
}
-StringRef Hexagon_MC::ParseHexagonTriple(const Triple &TT, StringRef CPU) {
- StringRef CPUName = Hexagon_MC::selectHexagonCPU(TT, CPU);
- StringRef FS = "";
- if (EnableHVX) {
- if (CPUName.equals_lower("hexagonv60") ||
- CPUName.equals_lower("hexagonv62"))
- FS = "+hvx";
+namespace {
+std::string selectHexagonFS(StringRef CPU, StringRef FS) {
+ SmallVector<StringRef, 3> Result;
+ if (!FS.empty())
+ Result.push_back(FS);
+
+ switch (EnableHVX) {
+ case Hexagon::ArchEnum::V55:
+ break;
+ case Hexagon::ArchEnum::V60:
+ Result.push_back("+hvxv60");
+ break;
+ case Hexagon::ArchEnum::V62:
+ Result.push_back("+hvxv62");
+ break;
+ case Hexagon::ArchEnum::V65:
+ Result.push_back("+hvxv65");
+ break;
+ case Hexagon::ArchEnum::V5:{
+ Result.push_back(StringSwitch<StringRef>(CPU)
+ .Case("hexagonv60", "+hvxv60")
+ .Case("hexagonv62", "+hvxv62")
+ .Case("hexagonv65", "+hvxv65"));
+ break;
}
- return FS;
+ case Hexagon::ArchEnum::V4:
+ // Sentinal if -mhvx isn't specified
+ break;
+ }
+ return join(Result.begin(), Result.end(), ",");
+}
}
static bool isCPUValid(std::string CPU)
@@ -271,16 +313,76 @@ static bool isCPUValid(std::string CPU)
"hexagonv55",
"hexagonv60",
"hexagonv62",
+ "hexagonv65",
};
return std::find(table.begin(), table.end(), CPU) != table.end();
}
+namespace {
+std::pair<std::string, std::string> selectCPUAndFS(StringRef CPU,
+ StringRef FS) {
+ std::pair<std::string, std::string> Result;
+ Result.first = Hexagon_MC::selectHexagonCPU(CPU);
+ Result.second = selectHexagonFS(Result.first, FS);
+ return Result;
+}
+}
+
+FeatureBitset Hexagon_MC::completeHVXFeatures(const FeatureBitset &S) {
+ using namespace Hexagon;
+ // Make sure that +hvx-length turns hvx on, and that "hvx" alone
+ // turns on hvxvNN, corresponding to the existing ArchVNN.
+ FeatureBitset FB = S;
+ unsigned CpuArch = ArchV4;
+ for (unsigned F : {ArchV65, ArchV62, ArchV60, ArchV55, ArchV5, ArchV4}) {
+ if (!FB.test(F))
+ continue;
+ CpuArch = F;
+ break;
+ }
+ bool UseHvx = false;
+ for (unsigned F : {ExtensionHVX, ExtensionHVX64B, ExtensionHVX128B,
+ ExtensionHVXDbl}) {
+ if (!FB.test(F))
+ continue;
+ UseHvx = true;
+ break;
+ }
+ bool HasHvxVer = false;
+ for (unsigned F : {ExtensionHVXV60, ExtensionHVXV62, ExtensionHVXV65}) {
+ if (!FB.test(F))
+ continue;
+ HasHvxVer = true;
+ UseHvx = true;
+ break;
+ }
+
+ if (!UseHvx || HasHvxVer)
+ return FB;
+
+ // HasHvxVer is false, and UseHvx is true.
+ switch (CpuArch) {
+ case ArchV60:
+ FB.set(ExtensionHVXV60);
+ break;
+ case ArchV62:
+ FB.set(ExtensionHVXV62);
+ break;
+ case ArchV65:
+ FB.set(ExtensionHVXV65);
+ break;
+ }
+ return FB;
+}
+
MCSubtargetInfo *Hexagon_MC::createHexagonMCSubtargetInfo(const Triple &TT,
StringRef CPU,
StringRef FS) {
- StringRef ArchFS = (FS.size()) ? FS : Hexagon_MC::ParseHexagonTriple(TT, CPU);
- StringRef CPUName = Hexagon_MC::selectHexagonCPU(TT, CPU);
+ std::pair<std::string, std::string> Features = selectCPUAndFS(CPU, FS);
+ StringRef CPUName = Features.first;
+ StringRef ArchFS = Features.second;
+
if (!isCPUValid(CPUName.str())) {
errs() << "error: invalid CPU \"" << CPUName.str().c_str()
<< "\" specified\n";
@@ -288,10 +390,12 @@ MCSubtargetInfo *Hexagon_MC::createHexagonMCSubtargetInfo(const Triple &TT,
}
MCSubtargetInfo *X = createHexagonMCSubtargetInfoImpl(TT, CPUName, ArchFS);
- if (X->getFeatureBits()[Hexagon::ExtensionHVX128B]) {
+ if (HexagonDisableDuplex) {
llvm::FeatureBitset Features = X->getFeatureBits();
- X->setFeatureBits(Features.set(Hexagon::ExtensionHVX));
+ X->setFeatureBits(Features.set(Hexagon::FeatureDuplex, false));
}
+
+ X->setFeatureBits(completeHVXFeatures(X->getFeatureBits()));
return X;
}
@@ -302,6 +406,7 @@ unsigned Hexagon_MC::GetELFFlags(const MCSubtargetInfo &STI) {
{"hexagonv55", ELF::EF_HEXAGON_MACH_V55},
{"hexagonv60", ELF::EF_HEXAGON_MACH_V60},
{"hexagonv62", ELF::EF_HEXAGON_MACH_V62},
+ {"hexagonv65", ELF::EF_HEXAGON_MACH_V65},
};
auto F = ElfFlags.find(STI.getCPU());
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h
index 30d75dbc84e..e53208fffee 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h
@@ -16,11 +16,13 @@
#include "llvm/Support/CommandLine.h"
#include <cstdint>
+#include <string>
namespace llvm {
struct InstrItinerary;
struct InstrStage;
+class FeatureBitset;
class MCAsmBackend;
class MCCodeEmitter;
class MCContext;
@@ -44,9 +46,9 @@ MCInstrInfo *createHexagonMCInstrInfo();
MCRegisterInfo *createHexagonMCRegisterInfo(StringRef TT);
namespace Hexagon_MC {
- StringRef ParseHexagonTriple(const Triple &TT, StringRef CPU);
- StringRef selectHexagonCPU(const Triple &TT, StringRef CPU);
+ StringRef selectHexagonCPU(StringRef CPU);
+ FeatureBitset completeHVXFeatures(const FeatureBitset &FB);
/// Create a Hexagon MCSubtargetInfo instance. This is exposed so Asm parser,
/// etc. do not need to go through TargetRegistry.
MCSubtargetInfo *createHexagonMCSubtargetInfo(const Triple &TT, StringRef CPU,
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
index 375a0bde32c..7709a0f6162 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
@@ -27,6 +27,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -115,6 +116,7 @@ void HexagonCVIResource::SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU) {
(*TUL)[HexagonII::TypeCVI_VP] = UnitsAndLanes(CVI_XLANE, 1);
(*TUL)[HexagonII::TypeCVI_VP_VS] = UnitsAndLanes(CVI_XLANE, 2);
(*TUL)[HexagonII::TypeCVI_VS] = UnitsAndLanes(CVI_SHIFT, 1);
+ (*TUL)[HexagonII::TypeCVI_VS_VX] = UnitsAndLanes(CVI_XLANE | CVI_SHIFT, 1);
(*TUL)[HexagonII::TypeCVI_VINLANESAT] =
(CPU == "hexagonv60")
? UnitsAndLanes(CVI_SHIFT, 1)
@@ -128,6 +130,14 @@ void HexagonCVIResource::SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU) {
(*TUL)[HexagonII::TypeCVI_VM_NEW_ST] = UnitsAndLanes(CVI_NONE, 0);
(*TUL)[HexagonII::TypeCVI_VM_STU] = UnitsAndLanes(CVI_XLANE, 1);
(*TUL)[HexagonII::TypeCVI_HIST] = UnitsAndLanes(CVI_XLANE, 4);
+ (*TUL)[HexagonII::TypeCVI_GATHER] =
+ UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
+ (*TUL)[HexagonII::TypeCVI_SCATTER] =
+ UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
+ (*TUL)[HexagonII::TypeCVI_SCATTER_DV] =
+ UnitsAndLanes(CVI_XLANE | CVI_MPY0, 2);
+ (*TUL)[HexagonII::TypeCVI_SCATTER_NEW_ST] =
+ UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
}
HexagonCVIResource::HexagonCVIResource(TypeUnitsAndLanes *TUL,
@@ -211,30 +221,89 @@ static struct {
} jumpSlots[] = {{8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1}};
#define MAX_JUMP_SLOTS (sizeof(jumpSlots) / sizeof(jumpSlots[0]))
+void HexagonShuffler::restrictSlot1AOK() {
+ bool HasRestrictSlot1AOK = false;
+ SMLoc RestrictLoc;
+ for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
+ MCInst const &Inst = ISJ->getDesc();
+ if (HexagonMCInstrInfo::isRestrictSlot1AOK(MCII, Inst)) {
+ HasRestrictSlot1AOK = true;
+ RestrictLoc = Inst.getLoc();
+ }
+ }
+ if (HasRestrictSlot1AOK)
+ for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
+ MCInst const &Inst = ISJ->getDesc();
+ unsigned Type = HexagonMCInstrInfo::getType(MCII, Inst);
+ if (Type != HexagonII::TypeALU32_2op &&
+ Type != HexagonII::TypeALU32_3op &&
+ Type != HexagonII::TypeALU32_ADDI) {
+ unsigned Units = ISJ->Core.getUnits();
+ if (Units & 2U) {
+ AppliedRestrictions.push_back(std::make_pair(
+ Inst.getLoc(),
+ "Instruction was restricted from being in slot 1"));
+ AppliedRestrictions.push_back(
+ std::make_pair(RestrictLoc, "Instruction can only be combine "
+ "with an ALU instruction in slot 1"));
+ ISJ->Core.setUnits(Units & ~2U);
+ }
+ }
+ }
+}
+
+void HexagonShuffler::restrictNoSlot1Store() {
+ bool HasRestrictNoSlot1Store = false;
+ SMLoc RestrictLoc;
+ for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
+ MCInst const &Inst = ISJ->getDesc();
+ if (HexagonMCInstrInfo::isRestrictNoSlot1Store(MCII, Inst)) {
+ HasRestrictNoSlot1Store = true;
+ RestrictLoc = Inst.getLoc();
+ }
+ }
+ if (HasRestrictNoSlot1Store) {
+ bool AppliedRestriction = false;
+ for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
+ MCInst const &Inst = ISJ->getDesc();
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst).mayStore()) {
+ unsigned Units = ISJ->Core.getUnits();
+ if (Units & 2U) {
+ AppliedRestriction = true;
+ AppliedRestrictions.push_back(std::make_pair(
+ Inst.getLoc(),
+ "Instruction was restricted from being in slot 1"));
+ ISJ->Core.setUnits(Units & ~2U);
+ }
+ }
+ }
+ if (AppliedRestriction)
+ AppliedRestrictions.push_back(std::make_pair(
+ RestrictLoc, "Instruction does not allow a store in slot 1"));
+ }
+}
+
+void HexagonShuffler::applySlotRestrictions() {
+ restrictSlot1AOK();
+ restrictNoSlot1Store();
+}
+
/// 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,
+ const unsigned slotSingleLoad = 0x1, slotSingleStore = 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 slotLoadStore = slotFirstLoadStore;
- // Number of branches, solo branches, indirect branches.
- unsigned jumps = 0, jump1 = 0;
// Number of memory operations, loads, solo loads, stores, solo stores, single
// stores.
unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0;
// Number of duplex insns
unsigned duplex = 0;
- // Number of insns restricting other insns in slot #1 to A type.
- unsigned onlyAin1 = 0;
- // Number of insns restricting any insn in slot #1, except A2_nop.
- unsigned onlyNo1 = 0;
unsigned pSlot3Cnt = 0;
- unsigned nvstores = 0;
unsigned memops = 0;
- unsigned deallocs = 0;
iterator slot3ISJ = end();
std::vector<iterator> foundBranches;
unsigned reservedSlots = 0;
@@ -243,15 +312,11 @@ bool HexagonShuffler::check() {
for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
MCInst const &ID = ISJ->getDesc();
- if (HexagonMCInstrInfo::isSoloAin1(MCII, ID))
- ++onlyAin1;
if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) {
++pSlot3Cnt;
slot3ISJ = ISJ;
}
reservedSlots |= HexagonMCInstrInfo::getOtherReservedSlots(MCII, STI, ID);
- if (HexagonMCInstrInfo::isCofMax1(MCII, ID))
- ++jump1;
switch (HexagonMCInstrInfo::getType(MCII, ID)) {
case HexagonII::TypeS_2op:
@@ -259,30 +324,30 @@ bool HexagonShuffler::check() {
case HexagonII::TypeALU64:
break;
case HexagonII::TypeJ:
- ++jumps;
foundBranches.push_back(ISJ);
break;
case HexagonII::TypeCVI_VM_VP_LDU:
- ++onlyNo1;
- LLVM_FALLTHROUGH;
case HexagonII::TypeCVI_VM_LD:
case HexagonII::TypeCVI_VM_TMP_LD:
+ case HexagonII::TypeCVI_GATHER:
+ case HexagonII::TypeCVI_GATHER_RST:
case HexagonII::TypeLD:
++loads;
++memory;
if (ISJ->Core.getUnits() == slotSingleLoad ||
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.
+ if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn())
foundBranches.push_back(ISJ);
- }
break;
case HexagonII::TypeCVI_VM_STU:
- ++onlyNo1;
- LLVM_FALLTHROUGH;
case HexagonII::TypeCVI_VM_ST:
case HexagonII::TypeCVI_VM_NEW_ST:
+ case HexagonII::TypeCVI_SCATTER:
+ case HexagonII::TypeCVI_SCATTER_DV:
+ case HexagonII::TypeCVI_SCATTER_RST:
+ case HexagonII::TypeCVI_SCATTER_NEW_RST:
+ case HexagonII::TypeCVI_SCATTER_NEW_ST:
case HexagonII::TypeST:
++stores;
++memory;
@@ -299,7 +364,6 @@ bool HexagonShuffler::check() {
break;
case HexagonII::TypeNCJ:
++memory; // NV insns are memory-like.
- ++jumps, ++jump1;
foundBranches.push_back(ISJ);
break;
case HexagonII::TypeV2LDST:
@@ -314,65 +378,35 @@ bool HexagonShuffler::check() {
assert(HexagonMCInstrInfo::getDesc(MCII, ID).mayStore());
++memory;
++stores;
- if (HexagonMCInstrInfo::isNewValue(MCII, ID))
- ++nvstores;
}
break;
case HexagonII::TypeCR:
// Legacy conditional branch predicated on a register.
case HexagonII::TypeCJ:
- if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch()) {
- ++jumps;
+ if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch())
foundBranches.push_back(ISJ);
- }
break;
case HexagonII::TypeDUPLEX: {
++duplex;
MCInst const &Inst0 = *ID.getOperand(0).getInst();
MCInst const &Inst1 = *ID.getOperand(1).getInst();
- if (HexagonMCInstrInfo::isCofMax1(MCII, Inst0))
- ++jump1;
- if (HexagonMCInstrInfo::isCofMax1(MCII, Inst1))
- ++jump1;
- if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isBranch()) {
- ++jumps;
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isBranch())
foundBranches.push_back(ISJ);
- }
- if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isBranch()) {
- ++jumps;
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isBranch())
foundBranches.push_back(ISJ);
- }
- if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isReturn()) {
- ++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isReturn())
foundBranches.push_back(ISJ);
- }
- if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isReturn()) {
- ++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isReturn())
foundBranches.push_back(ISJ);
- }
break;
}
}
}
+ applySlotRestrictions();
// Check if the packet is legal.
- if ((load0 > 1 || store0 > 1) ||
- (duplex > 1 || (duplex && memory))) {
- reportError(Twine("invalid instruction packet"));
- return false;
- }
-
- if (jump1 && jumps > 1) {
- // Error if single branch with another branch.
- reportError(Twine("too many branches in packet"));
- return false;
- }
- if ((nvstores || memops) && stores > 1) {
- reportError(Twine("slot 0 instruction does not allow slot 1 store"));
- return false;
- }
- if (deallocs && stores) {
- reportError(Twine("slot 0 instruction does not allow slot 1 store"));
+ if ((load0 > 1 || store0 > 1) || (duplex > 1 || (duplex && memory))) {
+ reportError(llvm::Twine("invalid instruction packet"));
return false;
}
@@ -387,31 +421,46 @@ bool HexagonShuffler::check() {
return false;
}
- // Exclude from slot #1 any insn but A2_nop.
- if (HexagonMCInstrInfo::getDesc(MCII, ID).getOpcode() != Hexagon::A2_nop)
- if (onlyNo1)
- ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
-
- // Exclude from slot #1 any insn but A-type.
- if (HexagonMCInstrInfo::getType(MCII, ID) != HexagonII::TypeALU32_2op &&
- HexagonMCInstrInfo::getType(MCII, ID) != HexagonII::TypeALU32_3op &&
- HexagonMCInstrInfo::getType(MCII, ID) != HexagonII::TypeALU32_ADDI)
- if (onlyAin1)
- ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
-
// A single load must use slot #0.
if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) {
if (loads == 1 && loads == memory && memops == 0)
// Pin the load to slot #0.
- ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
+ switch (ID.getOpcode()) {
+ case Hexagon::V6_vgathermw:
+ case Hexagon::V6_vgathermh:
+ case Hexagon::V6_vgathermhw:
+ case Hexagon::V6_vgathermwq:
+ case Hexagon::V6_vgathermhq:
+ case Hexagon::V6_vgathermhwq:
+ // Slot1 only loads
+ break;
+ default:
+ ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
+ break;
+ }
+ else if (loads >= 1 && isMemReorderDisabled()) { // }:mem_noshuf
+ // Loads must keep the original order ONLY if
+ // isMemReorderDisabled() == true
+ if (slotLoadStore < slotLastLoadStore) {
+ // Error if no more slots available for loads.
+ reportError(
+ llvm::Twine("invalid instruction packet: too many loads"));
+ return false;
+ }
+ // Pin the load to the highest slot available to it.
+ ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
+ // Update the next highest slot available to loads.
+ slotLoadStore >>= 1;
+ }
}
// A single store must use slot #0.
if (HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()) {
if (!store0) {
- if (stores == 1)
+ if (stores == 1 && (loads == 0 || !isMemReorderDisabled()))
+ // Pin the store to slot #0 only if isMemReorderDisabled() == false
ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);
- else if (stores > 1) {
+ else if (stores >= 1) {
if (slotLoadStore < slotLastLoadStore) {
// Error if no more slots available for stores.
reportError(Twine("invalid instruction packet: too many stores"));
@@ -443,7 +492,7 @@ bool HexagonShuffler::check() {
// preserve branch order
bool validateSlots = true;
- if (jumps > 1) {
+ if (foundBranches.size() > 1) {
if (foundBranches.size() > 2) {
reportError(Twine("too many branches in packet"));
return false;
@@ -487,7 +536,8 @@ bool HexagonShuffler::check() {
}
}
- if (jumps <= 1 && !bOnlySlot3 && pSlot3Cnt == 1 && slot3ISJ != end()) {
+ if (foundBranches.size() <= 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
@@ -604,6 +654,12 @@ bool HexagonShuffler::shuffle() {
}
void HexagonShuffler::reportError(Twine const &Msg) {
- if (ReportErrors)
+ if (ReportErrors) {
+ for (auto const &I : AppliedRestrictions) {
+ auto SM = Context.getSourceManager();
+ if (SM)
+ SM->PrintMessage(I.first, SourceMgr::DK_Note, I.second);
+ }
Context.reportError(Loc, Msg);
+ }
}
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h
index df3fb0a1efb..37f90bc46ac 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h
@@ -16,6 +16,7 @@
#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
#include "Hexagon.h"
+#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -152,6 +153,10 @@ protected:
MCSubtargetInfo const &STI;
SMLoc Loc;
bool ReportErrors;
+ std::vector<std::pair<SMLoc, std::string>> AppliedRestrictions;
+ void applySlotRestrictions();
+ void restrictSlot1AOK();
+ void restrictNoSlot1Store();
public:
using iterator = HexagonPacket::iterator;
@@ -168,6 +173,10 @@ public:
unsigned size() const { return (Packet.size()); }
+ bool isMemReorderDisabled() const {
+ return (BundleFlags & HexagonMCInstrInfo::memReorderDisabledMask) != 0;
+ }
+
iterator begin() { return (Packet.begin()); }
iterator end() { return (Packet.end()); }
OpenPOWER on IntegriCloud