summaryrefslogtreecommitdiff
path: root/lib/Target/Hexagon/MCTargetDesc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Hexagon/MCTargetDesc')
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp8
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h63
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp11
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp380
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h110
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp102
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h28
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp25
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp24
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h24
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp149
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h63
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp23
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h34
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp187
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h12
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp275
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h98
18 files changed, 983 insertions, 633 deletions
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
index 2a0edda8dcee..b3ab6763281c 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
@@ -65,7 +65,8 @@ public:
OSABI(OSABI), CPU(CPU), MCII(T.createMCInstrInfo()),
RelaxTarget(new MCInst *), Extender(nullptr) {}
- MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override {
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const override {
return createHexagonELFObjectWriter(OS, OSABI, CPU);
}
@@ -654,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)) {
@@ -768,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/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
index 7f90e83fc8e9..f5a376033757 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
@@ -1,4 +1,4 @@
-//===-- HexagonBaseInfo.h - Top level definitions for Hexagon --*- C++ -*--===//
+//===- HexagonBaseInfo.h - Top level definitions for Hexagon ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,15 +18,12 @@
#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONBASEINFO_H
#include "HexagonDepITypes.h"
-#include "HexagonMCTargetDesc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <stdint.h>
+#include "MCTargetDesc/HexagonMCTargetDesc.h"
namespace llvm {
/// HexagonII - This namespace holds all of the target specific flags that
/// instruction info tracks.
-///
namespace HexagonII {
unsigned const TypeCVI_FIRST = TypeCVI_HIST;
unsigned const TypeCVI_LAST = TypeCVI_VX_LATE;
@@ -48,16 +45,13 @@ namespace HexagonII {
PostInc = 6 // Post increment addressing mode
};
- // MemAccessSize is represented as 1+log2(N) where N is size in bits.
- enum class MemAccessSize {
- NoMemAccess = 0, // Not a memory access instruction.
- ByteAccess = 1, // Byte access instruction (memb).
- HalfWordAccess = 2, // Half word access instruction (memh).
- WordAccess = 3, // Word access instruction (memw).
- DoubleWordAccess = 4, // Double word access instruction (memd)
- // 5, // We do not have a 16 byte vector access.
- Vector64Access = 7, // 64 Byte vector access instruction (vmem).
- Vector128Access = 8 // 128 Byte vector access instruction (vmem).
+ enum MemAccessSize {
+ NoMemAccess = 0,
+ ByteAccess,
+ HalfWordAccess,
+ WordAccess,
+ DoubleWordAccess,
+ HVXVectorAccess
};
// MCInstrDesc TSFlags
@@ -74,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,
@@ -128,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,
@@ -158,8 +162,9 @@ namespace HexagonII {
PrefersSlot3Pos = 56,
PrefersSlot3Mask = 0x1,
- CofMax1Pos = 60,
- CofMax1Mask = 0x1,
+ // v65
+ HasTmpDstPos = 59,
+ HasTmpDstMask = 0x1,
CVINewPos = 61,
CVINewMask = 0x1
@@ -266,8 +271,18 @@ namespace HexagonII {
INST_ICLASS_ALU32_3 = 0xf0000000
};
-} // End namespace HexagonII.
-
-} // End namespace llvm.
-
-#endif
+ LLVM_ATTRIBUTE_UNUSED
+ static unsigned getMemAccessSizeInBytes(MemAccessSize S) {
+ switch (S) {
+ case ByteAccess: return 1;
+ case HalfWordAccess: return 2;
+ case WordAccess: return 4;
+ case DoubleWordAccess: return 8;
+ default: return 0;
+ }
+ }
+} // end namespace HexagonII
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONBASEINFO_H
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp
index b975e3131094..12aa1bd9b2a0 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp
@@ -11,6 +11,7 @@
#include "MCTargetDesc/HexagonFixupKinds.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -297,9 +298,9 @@ unsigned HexagonELFObjectWriter::getRelocType(MCContext &Ctx,
}
}
-MCObjectWriter *llvm::createHexagonELFObjectWriter(raw_pwrite_stream &OS,
- uint8_t OSABI,
- StringRef CPU) {
- MCELFObjectTargetWriter *MOTW = new HexagonELFObjectWriter(OSABI, CPU);
- return createELFObjectWriter(MOTW, OS, /*IsLittleEndian*/ true);
+std::unique_ptr<MCObjectWriter>
+llvm::createHexagonELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI,
+ StringRef CPU) {
+ auto MOTW = llvm::make_unique<HexagonELFObjectWriter>(OSABI, CPU);
+ return createELFObjectWriter(std::move(MOTW), OS, /*IsLittleEndian*/ true);
}
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp
index 3bb658b84451..53f3cba052bc 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp
@@ -12,17 +12,20 @@
//
//===----------------------------------------------------------------------===//
-#include "HexagonMCChecker.h"
-
-#include "HexagonBaseInfo.h"
-
+#include "MCTargetDesc/HexagonMCChecker.h"
+#include "Hexagon.h"
+#include "MCTargetDesc/HexagonBaseInfo.h"
+#include "MCTargetDesc/HexagonMCInstrInfo.h"
+#include "MCTargetDesc/HexagonMCShuffler.h"
+#include "MCTargetDesc/HexagonMCTargetDesc.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrDesc.h"
-#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/raw_ostream.h"
+#include <cassert>
using namespace llvm;
@@ -159,7 +162,7 @@ void HexagonMCChecker::init(MCInst const &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) ==
+ else if (i == 0 && 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
@@ -167,7 +170,7 @@ void HexagonMCChecker::init(MCInst const &MCI) {
// 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 && 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);
@@ -176,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)
@@ -214,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(
- llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNCJ);
- else
- NewUses[N] = NewSense::Use(
- PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI));
- }
- }
}
HexagonMCChecker::HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII,
@@ -239,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;
@@ -255,32 +218,15 @@ 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(),
- llvm::Twine("packet marked with `:endloop") +
- (Inner ? "0" : "1") + "' " +
- "cannot contain instructions that modify register " +
- "`" + llvm::Twine(RI.getName(Hexagon::PC)) + "'");
- return false;
- }
- }
- }
- return true;
-}
-
-namespace {
-bool isDuplexAGroup(unsigned Opcode) {
+static bool isDuplexAGroup(unsigned Opcode) {
switch (Opcode) {
case Hexagon::SA1_addi:
case Hexagon::SA1_addrx:
@@ -313,7 +259,7 @@ bool isDuplexAGroup(unsigned Opcode) {
}
}
-bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) {
+static bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) {
unsigned Result = 0;
unsigned Type = HexagonMCInstrInfo::getType(MCII, ID);
if (Type == HexagonII::TypeDUPLEX) {
@@ -329,7 +275,6 @@ bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) {
(Type != HexagonII::TypeALU64 || HexagonMCInstrInfo::isFloat(MCII, ID));
return Result != 0;
}
-} // namespace
bool HexagonMCChecker::checkAXOK() {
MCInst const *HasSoloAXInst = nullptr;
@@ -344,16 +289,75 @@ bool HexagonMCChecker::checkAXOK() {
if (&I != HasSoloAXInst && isNeitherAnorX(MCII, I)) {
reportError(
HasSoloAXInst->getLoc(),
- llvm::Twine("Instruction can only be in a packet with ALU or "
- "non-FPU XTYPE instructions"));
+ Twine("Instruction can only be in a packet with ALU or non-FPU XTYPE "
+ "instructions"));
reportError(I.getLoc(),
- llvm::Twine("Not an ALU or non-FPU XTYPE instruction"));
+ Twine("Not an ALU or non-FPU XTYPE instruction"));
return false;
}
}
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)) {
@@ -373,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.
@@ -445,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;
}
@@ -468,7 +502,7 @@ bool HexagonMCChecker::checkRegistersReadOnly() {
unsigned Register = Operand.getReg();
if (ReadOnly.find(Register) != ReadOnly.end()) {
reportError(Inst.getLoc(), "Cannot write to read-only register `" +
- llvm::Twine(RI.getName(Register)) + "'");
+ Twine(RI.getName(Register)) + "'");
return false;
}
}
@@ -488,13 +522,41 @@ 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) &&
HexagonMCInstrInfo::getDesc(MCII, I).mayLoad()) {
unsigned Register = I.getOperand(0).getReg();
if (!registerUsed(Register))
- reportWarning("Register `" + llvm::Twine(RI.getName(Register)) +
+ reportWarning("Register `" + Twine(RI.getName(Register)) +
"' used with `.cur' "
"but not used in the same packet");
}
@@ -568,17 +630,16 @@ bool HexagonMCChecker::checkRegisters() {
// special case for vhist
bool vHistFound = false;
for (auto const &HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) {
- if (llvm::HexagonMCInstrInfo::getType(MCII, *HMI.getInst()) ==
+ if (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) {
- reportWarning("register `" + llvm::Twine(RI.getName(R)) +
- "' used with `.tmp' "
- "but not used in the same packet");
+ if (!vHistFound) {
+ reportWarning("register `" + Twine(RI.getName(R)) +
+ "' used with `.tmp' but not used in the same packet");
return true;
}
}
@@ -591,7 +652,7 @@ bool HexagonMCChecker::checkRegisters() {
bool HexagonMCChecker::checkSolo() {
if (HexagonMCInstrInfo::bundleSize(MCB) > 1)
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
- if (llvm::HexagonMCInstrInfo::isSolo(MCII, I)) {
+ if (HexagonMCInstrInfo::isSolo(MCII, I)) {
reportError(I.getLoc(), "Instruction is marked `isSolo' and "
"cannot have other instructions in "
"the same packet");
@@ -638,56 +699,35 @@ 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 `" + llvm::Twine(RI.getName(Register)) +
+ reportError("register `" + Twine(RI.getName(Register)) +
"' modified more than once");
}
void HexagonMCChecker::reportErrorNewValue(unsigned Register) {
- reportError("register `" + llvm::Twine(RI.getName(Register)) +
+ reportError("register `" + Twine(RI.getName(Register)) +
"' used with `.new' "
"but not validly modified in the same packet");
}
-void HexagonMCChecker::reportError(llvm::Twine const &Msg) {
+void HexagonMCChecker::reportError(Twine const &Msg) {
reportError(MCB.getLoc(), Msg);
}
-void HexagonMCChecker::reportError(SMLoc Loc, llvm::Twine const &Msg) {
+void HexagonMCChecker::reportError(SMLoc Loc, Twine const &Msg) {
if (ReportErrors)
Context.reportError(Loc, Msg);
}
-void HexagonMCChecker::reportWarning(llvm::Twine const &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();
if (SM)
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h
index 027f78b4899c..7577baace20c 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h
@@ -1,4 +1,4 @@
-//===----- HexagonMCChecker.h - Instruction bundle checking ---------------===//
+//===- HexagonMCChecker.h - Instruction bundle checking ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,17 +12,24 @@
//
//===----------------------------------------------------------------------===//
-#ifndef HEXAGONMCCHECKER_H
-#define HEXAGONMCCHECKER_H
+#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCCHECKER_H
+#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCCHECKER_H
-#include "MCTargetDesc/HexagonMCShuffler.h"
-#include <queue>
+#include "MCTargetDesc/HexagonMCInstrInfo.h"
+#include "MCTargetDesc/HexagonMCTargetDesc.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/SMLoc.h"
#include <set>
-
-using namespace llvm;
+#include <utility>
namespace llvm {
-class MCOperandInfo;
+
+class MCContext;
+class MCInst;
+class MCInstrInfo;
+class MCRegisterInfo;
+class MCSubtargetInfo;
/// Check for a valid bundle.
class HexagonMCChecker {
@@ -34,72 +41,36 @@ class HexagonMCChecker {
bool ReportErrors;
/// Set of definitions: register #, if predicated, if predicated true.
- typedef std::pair<unsigned, bool> PredSense;
+ using PredSense = std::pair<unsigned, bool>;
static const PredSense Unconditional;
- typedef std::multiset<PredSense> PredSet;
- typedef std::multiset<PredSense>::iterator PredSetIterator;
-
- typedef llvm::DenseMap<unsigned, PredSet>::iterator DefsIterator;
- llvm::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:
- typedef llvm::SmallVector<NewSense, 2> NewSenseList;
- typedef llvm::DenseMap<unsigned, NewSenseList>::iterator NewDefsIterator;
- llvm::DenseMap<unsigned, NewSenseList> NewDefs;
+ using PredSet = std::multiset<PredSense>;
+ using PredSetIterator = std::multiset<PredSense>::iterator;
+
+ using DefsIterator = DenseMap<unsigned, PredSet>::iterator;
+ DenseMap<unsigned, PredSet> Defs;
/// Set of weak definitions whose clashes should be enforced selectively.
- typedef std::set<unsigned>::iterator SoftDefsIterator;
+ using SoftDefsIterator = std::set<unsigned>::iterator;
std::set<unsigned> SoftDefs;
/// Set of temporary definitions not committed to the register file.
- typedef std::set<unsigned>::iterator TmpDefsIterator;
+ using TmpDefsIterator = std::set<unsigned>::iterator;
std::set<unsigned> TmpDefs;
/// Set of new predicates used.
- typedef std::set<unsigned>::iterator NewPredsIterator;
+ using NewPredsIterator = std::set<unsigned>::iterator;
std::set<unsigned> NewPreds;
/// Set of predicates defined late.
- typedef std::multiset<unsigned>::iterator LatePredsIterator;
+ using LatePredsIterator = std::multiset<unsigned>::iterator;
std::multiset<unsigned> LatePreds;
/// Set of uses.
- typedef std::set<unsigned>::iterator UsesIterator;
+ using UsesIterator = std::set<unsigned>::iterator;
std::set<unsigned> Uses;
- /// Set of new values used: new register, if new-value jump.
- typedef llvm::DenseMap<unsigned, NewSense>::iterator NewUsesIterator;
- llvm::DenseMap<unsigned, NewSense> NewUses;
-
/// Pre-defined set of read-only registers.
- typedef std::set<unsigned>::iterator ReadOnlyIterator;
+ using ReadOnlyIterator = std::set<unsigned>::iterator;
std::set<unsigned> ReadOnly;
void init();
@@ -107,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();
@@ -114,39 +88,43 @@ 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 &);
bool isPredicateRegister(unsigned R) const {
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);
- };
-
- 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, llvm::Twine const &Msg);
- void reportError(llvm::Twine const &Msg);
- void reportWarning(llvm::Twine const &Msg);
+ 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();
};
-} // namespace llvm
+} // end namespace llvm
-#endif // HEXAGONMCCHECKER_H
+#endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCCHECKER_H
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp
index 50f00d1aaeac..631c38c2734f 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp
@@ -1,4 +1,4 @@
-//===-- HexagonMCCodeEmitter.cpp - Hexagon Target Descriptions ------------===//
+//===- HexagonMCCodeEmitter.cpp - Hexagon Target Descriptions -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,19 +11,29 @@
#include "Hexagon.h"
#include "MCTargetDesc/HexagonBaseInfo.h"
#include "MCTargetDesc/HexagonFixupKinds.h"
+#include "MCTargetDesc/HexagonMCExpr.h"
#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <string>
#define DEBUG_TYPE "mccodeemitter"
@@ -89,7 +99,6 @@ void HexagonMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
*Addend += HEXAGON_INSTR_SIZE;
++*CurrentIndex;
}
- return;
}
static bool RegisterMatches(unsigned Consumer, unsigned Producer,
@@ -158,17 +167,16 @@ void HexagonMCCodeEmitter::EncodeSingleInstruction(
++MCNumEmitted;
}
-namespace {
-void raise_relocation_error(unsigned bits, unsigned kind) {
+LLVM_ATTRIBUTE_NORETURN
+static void raise_relocation_error(unsigned bits, unsigned kind) {
std::string Text;
{
- llvm::raw_string_ostream Stream(Text);
+ raw_string_ostream Stream(Text);
Stream << "Unrecognized relocation combination bits: " << bits
<< " kind: " << kind;
}
report_fatal_error(Text);
}
-}
/// getFixupNoBits - Some insns are not extended and thus have no
/// bits. These cases require a more brute force method for determining
@@ -177,7 +185,7 @@ Hexagon::Fixups HexagonMCCodeEmitter::getFixupNoBits(
MCInstrInfo const &MCII, const MCInst &MI, const MCOperand &MO,
const MCSymbolRefExpr::VariantKind kind) const {
const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(MCII, MI);
- unsigned insnType = llvm::HexagonMCInstrInfo::getType(MCII, MI);
+ unsigned insnType = HexagonMCInstrInfo::getType(MCII, MI);
if (insnType == HexagonII::TypeEXTENDER) {
switch (kind) {
@@ -282,14 +290,14 @@ Hexagon::Fixups HexagonMCCodeEmitter::getFixupNoBits(
++ImpUses) {
if (*ImpUses != Hexagon::GP)
continue;
- switch (HexagonMCInstrInfo::getAccessSize(MCII, MI)) {
- case HexagonII::MemAccessSize::ByteAccess:
+ switch (HexagonMCInstrInfo::getMemAccessSize(MCII, MI)) {
+ case 1:
return fixup_Hexagon_GPREL16_0;
- case HexagonII::MemAccessSize::HalfWordAccess:
+ case 2:
return fixup_Hexagon_GPREL16_1;
- case HexagonII::MemAccessSize::WordAccess:
+ case 4:
return fixup_Hexagon_GPREL16_2;
- case HexagonII::MemAccessSize::DoubleWordAccess:
+ case 8:
return fixup_Hexagon_GPREL16_3;
default:
raise_relocation_error(0, kind);
@@ -302,34 +310,34 @@ Hexagon::Fixups HexagonMCCodeEmitter::getFixupNoBits(
}
namespace llvm {
+
extern const MCInstrDesc HexagonInsts[];
-}
-namespace {
- bool isPCRel (unsigned Kind) {
- switch(Kind){
- case fixup_Hexagon_B22_PCREL:
- case fixup_Hexagon_B15_PCREL:
- case fixup_Hexagon_B7_PCREL:
- case fixup_Hexagon_B13_PCREL:
- case fixup_Hexagon_B9_PCREL:
- case fixup_Hexagon_B32_PCREL_X:
- case fixup_Hexagon_B22_PCREL_X:
- case fixup_Hexagon_B15_PCREL_X:
- case fixup_Hexagon_B13_PCREL_X:
- case fixup_Hexagon_B9_PCREL_X:
- case fixup_Hexagon_B7_PCREL_X:
- case fixup_Hexagon_32_PCREL:
- case fixup_Hexagon_PLT_B22_PCREL:
- case fixup_Hexagon_GD_PLT_B22_PCREL:
- case fixup_Hexagon_LD_PLT_B22_PCREL:
- case fixup_Hexagon_GD_PLT_B22_PCREL_X:
- case fixup_Hexagon_LD_PLT_B22_PCREL_X:
- case fixup_Hexagon_6_PCREL_X:
- return true;
- default:
- return false;
- }
+} // end namespace llvm
+
+static bool isPCRel (unsigned Kind) {
+ switch(Kind){
+ case fixup_Hexagon_B22_PCREL:
+ case fixup_Hexagon_B15_PCREL:
+ case fixup_Hexagon_B7_PCREL:
+ case fixup_Hexagon_B13_PCREL:
+ case fixup_Hexagon_B9_PCREL:
+ case fixup_Hexagon_B32_PCREL_X:
+ case fixup_Hexagon_B22_PCREL_X:
+ case fixup_Hexagon_B15_PCREL_X:
+ case fixup_Hexagon_B13_PCREL_X:
+ case fixup_Hexagon_B9_PCREL_X:
+ case fixup_Hexagon_B7_PCREL_X:
+ case fixup_Hexagon_32_PCREL:
+ case fixup_Hexagon_PLT_B22_PCREL:
+ case fixup_Hexagon_GD_PLT_B22_PCREL:
+ case fixup_Hexagon_LD_PLT_B22_PCREL:
+ case fixup_Hexagon_GD_PLT_B22_PCREL_X:
+ case fixup_Hexagon_LD_PLT_B22_PCREL_X:
+ case fixup_Hexagon_6_PCREL_X:
+ return true;
+ default:
+ return false;
}
}
@@ -338,7 +346,6 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
const MCExpr *ME,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const
-
{
if (isa<HexagonMCExpr>(ME))
ME = &HexagonMCInstrInfo::getExpr(*ME);
@@ -475,7 +482,7 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
}
} else
switch (kind) {
- case MCSymbolRefExpr::VK_None: {
+ case MCSymbolRefExpr::VK_None:
if (HexagonMCInstrInfo::s27_2_reloc(*MO.getExpr()))
FixupKind = Hexagon::fixup_Hexagon_27_REG;
else
@@ -484,17 +491,17 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
++ImpUses) {
if (*ImpUses != Hexagon::GP)
continue;
- switch (HexagonMCInstrInfo::getAccessSize(MCII, MI)) {
- case HexagonII::MemAccessSize::ByteAccess:
+ switch (HexagonMCInstrInfo::getMemAccessSize(MCII, MI)) {
+ case 1:
FixupKind = fixup_Hexagon_GPREL16_0;
break;
- case HexagonII::MemAccessSize::HalfWordAccess:
+ case 2:
FixupKind = fixup_Hexagon_GPREL16_1;
break;
- case HexagonII::MemAccessSize::WordAccess:
+ case 4:
FixupKind = fixup_Hexagon_GPREL16_2;
break;
- case HexagonII::MemAccessSize::DoubleWordAccess:
+ case 8:
FixupKind = fixup_Hexagon_GPREL16_3;
break;
default:
@@ -504,7 +511,6 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
} else
raise_relocation_error(bits, kind);
break;
- }
case MCSymbolRefExpr::VK_DTPREL:
FixupKind = Hexagon::fixup_Hexagon_DTPREL_16;
break;
@@ -786,7 +792,7 @@ HexagonMCCodeEmitter::getMachineOpValue(MCInst const &MI, MCOperand const &MO,
if (MO.isReg()) {
unsigned Reg = MO.getReg();
if (HexagonMCInstrInfo::isSubInstruction(MI) ||
- llvm::HexagonMCInstrInfo::getType(MCII, MI) == HexagonII::TypeCJ)
+ HexagonMCInstrInfo::getType(MCII, MI) == HexagonII::TypeCJ)
return HexagonMCInstrInfo::getDuplexRegisterNumbering(Reg);
return MCT.getRegisterInfo()->getEncodingValue(Reg);
}
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h
index c3a4beec313f..14cabf1534a5 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h
@@ -1,4 +1,4 @@
-//===-- HexagonMCCodeEmitter.h - Hexagon Target Descriptions ----*- C++ -*-===//
+//===- HexagonMCCodeEmitter.h - Hexagon Target Descriptions -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,20 +12,26 @@
///
//===----------------------------------------------------------------------===//
-#ifndef HEXAGONMCCODEEMITTER_H
-#define HEXAGONMCCODEEMITTER_H
+#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCCODEEMITTER_H
+#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCCODEEMITTER_H
#include "MCTargetDesc/HexagonFixupKinds.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/MC/SubtargetFeature.h"
+#include <cstddef>
+#include <cstdint>
+#include <memory>
namespace llvm {
+class MCContext;
+class MCInst;
+class MCInstrInfo;
+class MCOperand;
+class MCSubtargetInfo;
+class raw_ostream;
+
class HexagonMCCodeEmitter : public MCCodeEmitter {
MCContext &MCT;
MCInstrInfo const &MCII;
@@ -73,8 +79,8 @@ private:
uint64_t computeAvailableFeatures(const FeatureBitset &FB) const;
void verifyInstructionPredicates(const MCInst &MI,
uint64_t AvailableFeatures) const;
-}; // class HexagonMCCodeEmitter
+};
-} // namespace llvm
+} // end namespace llvm
-#endif /* HEXAGONMCCODEEMITTER_H */
+#endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCCODEEMITTER_H
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp
index c7114c7f18a0..4c18af60efd1 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCDuplexInfo.cpp
@@ -1,4 +1,4 @@
-//===----- HexagonMCDuplexInfo.cpp - Instruction bundle checking ----------===//
+//===- HexagonMCDuplexInfo.cpp - Instruction bundle checking --------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,15 +11,22 @@
//
//===----------------------------------------------------------------------===//
-#include "HexagonBaseInfo.h"
+#include "MCTargetDesc/HexagonBaseInfo.h"
#include "MCTargetDesc/HexagonMCInstrInfo.h"
-
+#include "MCTargetDesc/HexagonMCTargetDesc.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-
+#include <cassert>
+#include <cstdint>
+#include <iterator>
#include <map>
+#include <utility>
using namespace llvm;
using namespace Hexagon;
@@ -265,7 +272,7 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
case Hexagon::J2_jumpr:
case Hexagon::PS_jmpret:
// jumpr r31
- // Actual form JMPR %PC<imp-def>, %R31<imp-use>, %R0<imp-use,internal>.
+ // Actual form JMPR implicit-def %pc, implicit %r31, implicit internal %r0.
DstReg = MCI.getOperand(0).getReg();
if (Hexagon::R31 == DstReg)
return HexagonII::HSIG_L2;
@@ -298,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;
}
@@ -381,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;
//
@@ -464,7 +471,7 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
case Hexagon::C2_cmovenewif:
// if ([!]P0[.new]) Rd = #0
// Actual form:
- // %R16<def> = C2_cmovenewit %P0<internal>, 0, %R16<imp-use,undef>;
+ // %r16 = C2_cmovenewit internal %p0, 0, implicit undef %r16;
DstReg = MCI.getOperand(0).getReg(); // Rd
PredReg = MCI.getOperand(1).getReg(); // P0
if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
@@ -735,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/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp
index 47007e08a2ff..691e269cb91f 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp
@@ -18,7 +18,9 @@
#include "MCTargetDesc/HexagonMCShuffler.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
@@ -43,6 +45,19 @@ static cl::opt<unsigned> GPSize
cl::Prefix,
cl::init(8));
+HexagonMCELFStreamer::HexagonMCELFStreamer(
+ MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
+ raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter)
+ : MCELFStreamer(Context, std::move(TAB), OS, std::move(Emitter)),
+ MCII(createHexagonMCInstrInfo()) {}
+
+HexagonMCELFStreamer::HexagonMCELFStreamer(
+ MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
+ raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter,
+ MCAssembler *Assembler)
+ : MCELFStreamer(Context, std::move(TAB), OS, std::move(Emitter)),
+ MCII(createHexagonMCInstrInfo()) {}
+
void HexagonMCELFStreamer::EmitInstruction(const MCInst &MCB,
const MCSubtargetInfo &STI, bool) {
assert(MCB.getOpcode() == Hexagon::BUNDLE);
@@ -149,10 +164,11 @@ void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol,
namespace llvm {
- MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context,
- MCAsmBackend &MAB,
- raw_pwrite_stream &OS, MCCodeEmitter *CE) {
- return new HexagonMCELFStreamer(Context, MAB, OS, CE);
+MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context,
+ std::unique_ptr<MCAsmBackend> MAB,
+ raw_pwrite_stream &OS,
+ std::unique_ptr<MCCodeEmitter> CE) {
+ return new HexagonMCELFStreamer(Context, std::move(MAB), OS, std::move(CE));
}
} // end namespace llvm
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h
index 024dff1a2f97..c6fa0021d86b 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.h
@@ -22,17 +22,14 @@ class HexagonMCELFStreamer : public MCELFStreamer {
std::unique_ptr<MCInstrInfo> MCII;
public:
- HexagonMCELFStreamer(MCContext &Context, MCAsmBackend &TAB,
- raw_pwrite_stream &OS, MCCodeEmitter *Emitter)
- : MCELFStreamer(Context, TAB, OS, Emitter),
- MCII(createHexagonMCInstrInfo()) {}
-
- HexagonMCELFStreamer(MCContext &Context,
- MCAsmBackend &TAB,
- raw_pwrite_stream &OS, MCCodeEmitter *Emitter,
- MCAssembler *Assembler) :
- MCELFStreamer(Context, TAB, OS, Emitter),
- MCII (createHexagonMCInstrInfo()) {}
+ HexagonMCELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
+ raw_pwrite_stream &OS,
+ std::unique_ptr<MCCodeEmitter> Emitter);
+
+ HexagonMCELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
+ raw_pwrite_stream &OS,
+ std::unique_ptr<MCCodeEmitter> Emitter,
+ MCAssembler *Assembler);
void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
bool) override;
@@ -45,8 +42,9 @@ public:
};
MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context,
- MCAsmBackend &MAB, raw_pwrite_stream &OS,
- MCCodeEmitter *CE);
+ std::unique_ptr<MCAsmBackend> MAB,
+ raw_pwrite_stream &OS,
+ std::unique_ptr<MCCodeEmitter> CE);
} // end namespace llvm
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
index 5fe638a9996b..19308cd425e8 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
@@ -11,17 +11,31 @@
//
//===----------------------------------------------------------------------===//
-#include "HexagonMCInstrInfo.h"
-
+#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "Hexagon.h"
-#include "HexagonBaseInfo.h"
-#include "HexagonMCChecker.h"
+#include "MCTargetDesc/HexagonBaseInfo.h"
+#include "MCTargetDesc/HexagonMCChecker.h"
+#include "MCTargetDesc/HexagonMCExpr.h"
+#include "MCTargetDesc/HexagonMCShuffler.h"
+#include "MCTargetDesc/HexagonMCTargetDesc.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <cstdint>
+#include <limits>
+
+using namespace llvm;
-namespace llvm {
+bool HexagonMCInstrInfo::PredicateInfo::isPredicated() const {
+ return Register != Hexagon::NoRegister;
+}
Hexagon::PacketIterator::PacketIterator(MCInstrInfo const &MCII,
MCInst const &Inst)
@@ -40,6 +54,7 @@ Hexagon::PacketIterator &Hexagon::PacketIterator::operator++() {
if (DuplexCurrent == DuplexEnd) {
DuplexCurrent = BundleEnd;
DuplexEnd = BundleEnd;
+ ++BundleCurrent;
}
return *this;
}
@@ -80,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));
}
@@ -121,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);
@@ -159,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) {
@@ -216,12 +225,18 @@ void HexagonMCInstrInfo::extendIfNeeded(MCContext &Context,
addConstExtender(Context, MCII, MCB, MCI);
}
-HexagonII::MemAccessSize
-HexagonMCInstrInfo::getAccessSize(MCInstrInfo const &MCII, MCInst const &MCI) {
- const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
+unsigned HexagonMCInstrInfo::getMemAccessSize(MCInstrInfo const &MCII,
+ MCInst const &MCI) {
+ uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
+ unsigned S = (F >> HexagonII::MemAccessSizePos) & HexagonII::MemAccesSizeMask;
+ return HexagonII::getMemAccessSizeInBytes(HexagonII::MemAccessSize(S));
+}
- return (HexagonII::MemAccessSize((F >> HexagonII::MemAccessSizePos) &
- HexagonII::MemAccesSizeMask));
+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,
@@ -231,6 +246,7 @@ MCInstrDesc const &HexagonMCInstrInfo::getDesc(MCInstrInfo const &MCII,
unsigned HexagonMCInstrInfo::getDuplexRegisterNumbering(unsigned Reg) {
using namespace Hexagon;
+
switch (Reg) {
default:
llvm_unreachable("unknown duplex register");
@@ -355,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.
@@ -429,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;
}
@@ -441,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;
@@ -530,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);
@@ -566,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;
}
@@ -645,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.
@@ -663,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:
@@ -769,11 +811,11 @@ bool HexagonMCInstrInfo::mustNotExtend(MCExpr const &Expr) {
}
void HexagonMCInstrInfo::setS27_2_reloc(MCExpr const &Expr, bool Val) {
HexagonMCExpr &HExpr =
- const_cast<HexagonMCExpr &>(*llvm::cast<HexagonMCExpr>(&Expr));
+ const_cast<HexagonMCExpr &>(*cast<HexagonMCExpr>(&Expr));
HExpr.setS27_2_reloc(Val);
}
bool HexagonMCInstrInfo::s27_2_reloc(MCExpr const &Expr) {
- HexagonMCExpr const *HExpr = llvm::dyn_cast<HexagonMCExpr>(&Expr);
+ HexagonMCExpr const *HExpr = dyn_cast<HexagonMCExpr>(&Expr);
if (!HExpr)
return false;
return HExpr->s27_2_reloc();
@@ -790,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());
@@ -823,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);
@@ -844,8 +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;
}
-} // namespace llvm
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
index ca44c3a11ba7..28d89429266b 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
@@ -14,24 +14,33 @@
#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINSTRINFO_H
#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINSTRINFO_H
-#include "HexagonMCExpr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/Support/MathExtras.h"
+#include <cstddef>
+#include <cstdint>
namespace llvm {
+
class HexagonMCChecker;
+class MCContext;
+class MCExpr;
class MCInstrDesc;
class MCInstrInfo;
class MCSubtargetInfo;
-namespace HexagonII {
-enum class MemAccessSize;
-}
+
class DuplexCandidate {
public:
unsigned packetIndexI, packetIndexJ, iClass;
+
DuplexCandidate(unsigned i, unsigned j, unsigned iClass)
: packetIndexI(i), packetIndexJ(j), iClass(iClass) {}
};
+
namespace Hexagon {
+
class PacketIterator {
MCInstrInfo const &MCII;
MCInst::const_iterator BundleCurrent;
@@ -42,6 +51,7 @@ class PacketIterator {
public:
PacketIterator(MCInstrInfo const &MCII, MCInst const &Inst);
PacketIterator(MCInstrInfo const &MCII, MCInst const &Inst, std::nullptr_t);
+
PacketIterator &operator++();
MCInst const &operator*() const;
bool operator==(PacketIterator const &Other) const;
@@ -49,8 +59,11 @@ public:
return !(*this == Other);
}
};
-} // namespace Hexagon
+
+} // end namespace Hexagon
+
namespace HexagonMCInstrInfo {
+
size_t const innerLoopOffset = 0;
int64_t const innerLoopMask = 1 << innerLoopOffset;
@@ -62,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);
@@ -97,16 +106,17 @@ 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,
MCInst const &MCI);
+// Return memory access size in bytes
+unsigned getMemAccessSize(MCInstrInfo const &MCII, MCInst const &MCI);
+
// Return memory access size
-HexagonII::MemAccessSize getAccessSize(MCInstrInfo const &MCII,
- MCInst const &MCI);
+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
@@ -171,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);
@@ -196,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.
@@ -223,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);
@@ -235,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);
@@ -270,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);
@@ -278,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
@@ -287,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);
@@ -303,7 +328,9 @@ unsigned SubregisterBit(unsigned Consumer, unsigned Producer,
// Attempt to find and replace compound pairs
void tryCompound(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
MCContext &Context, MCInst &MCI);
-} // namespace HexagonMCInstrInfo
-} // namespace llvm
+
+} // end namespace HexagonMCInstrInfo
+
+} // end namespace llvm
#endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCINSTRINFO_H
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp
index b2c7f1569380..7bd54fdfa3d5 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp
@@ -17,10 +17,14 @@
#include "MCTargetDesc/HexagonMCShuffler.h"
#include "Hexagon.h"
#include "MCTargetDesc/HexagonMCInstrInfo.h"
-#include "MCTargetDesc/HexagonMCTargetDesc.h"
+#include "MCTargetDesc/HexagonShuffler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCInstrInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
using namespace llvm;
@@ -109,9 +113,10 @@ bool llvm::HexagonMCShuffle(MCContext &Context, bool Fatal,
if (!HexagonMCInstrInfo::bundleSize(MCB)) {
// There once was a bundle:
- // BUNDLE %D2<imp-def>, %R4<imp-def>, %R5<imp-def>, %D7<imp-def>, ...
- // * %D2<def> = IMPLICIT_DEF; flags:
- // * %D7<def> = IMPLICIT_DEF; flags:
+ // BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5,
+ // implicit-def %d7, ...
+ // * %d2 = IMPLICIT_DEF; flags:
+ // * %d7 = IMPLICIT_DEF; flags:
// After the IMPLICIT_DEFs were removed by the asm printer, the bundle
// became empty.
DEBUG(dbgs() << "Skipping empty bundle");
@@ -128,15 +133,15 @@ bool
llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
MCSubtargetInfo const &STI, MCInst &MCB,
SmallVector<DuplexCandidate, 8> possibleDuplexes) {
-
if (DisableShuffle)
return false;
if (!HexagonMCInstrInfo::bundleSize(MCB)) {
// There once was a bundle:
- // BUNDLE %D2<imp-def>, %R4<imp-def>, %R5<imp-def>, %D7<imp-def>, ...
- // * %D2<def> = IMPLICIT_DEF; flags:
- // * %D7<def> = IMPLICIT_DEF; flags:
+ // BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5,
+ // implicit-def %d7, ...
+ // * %d2 = IMPLICIT_DEF; flags:
+ // * %d7 = IMPLICIT_DEF; flags:
// After the IMPLICIT_DEFs were removed by the asm printer, the bundle
// became empty.
DEBUG(dbgs() << "Skipping empty bundle");
@@ -165,7 +170,7 @@ llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
break;
}
- if (doneShuffling == false) {
+ if (!doneShuffling) {
HexagonMCShuffler MCS(Context, false, MCII, STI, MCB);
doneShuffling = MCS.reshuffleTo(MCB); // shuffle
}
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h
index dbe85b434dc4..59658999d24d 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h
@@ -1,4 +1,4 @@
-//=-- HexagonMCShuffler.h ---------------------------------------------------=//
+//===- HexagonMCShuffler.h --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,13 +12,20 @@
//
//===----------------------------------------------------------------------===//
-#ifndef HEXAGONMCSHUFFLER_H
-#define HEXAGONMCSHUFFLER_H
+#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCSHUFFLER_H
+#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCSHUFFLER_H
+#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "MCTargetDesc/HexagonShuffler.h"
+#include "llvm/ADT/SmallVector.h"
namespace llvm {
+
+class MCContext;
class MCInst;
+class MCInstrInfo;
+class MCSubtargetInfo;
+
// Insn bundle shuffler.
class HexagonMCShuffler : public HexagonShuffler {
public:
@@ -26,16 +33,18 @@ public:
MCSubtargetInfo const &STI, MCInst &MCB)
: HexagonShuffler(Context, Fatal, MCII, STI) {
init(MCB);
- };
+ }
+
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);
- };
+ }
// Copy reordered bundle to another.
void copyTo(MCInst &MCB);
+
// Reorder and copy result to another.
bool reshuffleTo(MCInst &MCB);
@@ -46,13 +55,14 @@ private:
// Invocation of the shuffler.
bool HexagonMCShuffle(MCContext &Context, bool Fatal, MCInstrInfo const &MCII,
- MCSubtargetInfo const &STI, MCInst &);
+ MCSubtargetInfo const &STI, MCInst &MCB);
bool HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
- MCSubtargetInfo const &STI, MCInst &, MCInst const &,
- int);
+ MCSubtargetInfo const &STI, MCInst &MCB,
+ MCInst const &AddMI, int fixupCount);
bool HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
- MCSubtargetInfo const &STI, MCInst &,
- SmallVector<DuplexCandidate, 8>);
-} // namespace llvm
+ MCSubtargetInfo const &STI, MCInst &MCB,
+ SmallVector<DuplexCandidate, 8> possibleDuplexes);
+
+} // end namespace llvm
-#endif // HEXAGONMCSHUFFLER_H
+#endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONMCSHUFFLER_H
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
index 1a361548f938..3fbe2197f937 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
@@ -13,13 +13,17 @@
#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"
+#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCELFStreamer.h"
@@ -55,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)
@@ -144,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;
}
};
@@ -224,13 +246,13 @@ createMCAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS,
return new HexagonTargetAsmStreamer(S, OS, IsVerboseAsm, *IP);
}
-static MCStreamer *createMCStreamer(Triple const &T,
- MCContext &Context,
- MCAsmBackend &MAB,
+static MCStreamer *createMCStreamer(Triple const &T, MCContext &Context,
+ std::unique_ptr<MCAsmBackend> &&MAB,
raw_pwrite_stream &OS,
- MCCodeEmitter *Emitter,
+ std::unique_ptr<MCCodeEmitter> &&Emitter,
bool RelaxAll) {
- return createHexagonELFStreamer(T, Context, MAB, OS, Emitter);
+ return createHexagonELFStreamer(T, Context, std::move(MAB), OS,
+ std::move(Emitter));
}
static MCTargetStreamer *
@@ -249,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)
@@ -269,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 ArchV65:
+ FB.set(ExtensionHVXV65);
+ LLVM_FALLTHROUGH;
+ case ArchV62:
+ FB.set(ExtensionHVXV62);
+ LLVM_FALLTHROUGH;
+ case ArchV60:
+ FB.set(ExtensionHVXV60);
+ 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";
@@ -286,10 +390,12 @@ MCSubtargetInfo *Hexagon_MC::createHexagonMCSubtargetInfo(const Triple &TT,
}
MCSubtargetInfo *X = createHexagonMCSubtargetInfoImpl(TT, CPUName, ArchFS);
- if (X->getFeatureBits()[Hexagon::ExtensionHVXDbl]) {
+ 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;
}
@@ -300,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/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h
index 6bb69be6142e..05d17c368dcc 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h
+++ b/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,
@@ -63,8 +65,9 @@ MCAsmBackend *createHexagonAsmBackend(const Target &T,
const Triple &TT, StringRef CPU,
const MCTargetOptions &Options);
-MCObjectWriter *createHexagonELFObjectWriter(raw_pwrite_stream &OS,
- uint8_t OSABI, StringRef CPU);
+std::unique_ptr<MCObjectWriter>
+createHexagonELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI,
+ StringRef CPU);
unsigned HexagonGetLastSlot();
@@ -79,6 +82,7 @@ unsigned HexagonGetLastSlot();
// Defines symbolic names for the Hexagon instructions.
//
#define GET_INSTRINFO_ENUM
+#define GET_INSTRINFO_SCHED_ENUM
#include "HexagonGenInstrInfo.inc"
#define GET_SUBTARGETINFO_ENUM
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
index 1604e7c8dc54..7709a0f61624 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
@@ -1,4 +1,4 @@
-//===----- HexagonShuffler.cpp - Instruction bundle shuffling -------------===//
+//===- HexagonShuffler.cpp - Instruction bundle shuffling -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,32 +14,40 @@
#define DEBUG_TYPE "hexagon-shuffle"
-#include "HexagonShuffler.h"
+#include "MCTargetDesc/HexagonShuffler.h"
#include "Hexagon.h"
#include "MCTargetDesc/HexagonBaseInfo.h"
#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
#include <utility>
+#include <vector>
using namespace llvm;
namespace {
+
// Insn shuffling priority.
class HexagonBid {
// The priority is directly proportional to how restricted the insn is based
// on its flexibility to run on the available slots. So, the fewer slots it
// may run on, the higher its priority.
enum { MAX = 360360 }; // LCD of 1/2, 1/3, 1/4,... 1/15.
- unsigned Bid;
+ unsigned Bid = 0;
public:
- HexagonBid() : Bid(0) {}
+ HexagonBid() = default;
HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; }
// Check if the insn priority is overflowed.
@@ -58,7 +66,7 @@ class HexagonUnitAuction {
unsigned isSold : HEXAGON_PACKET_SIZE;
public:
- HexagonUnitAuction(unsigned cs = 0) : isSold(cs){};
+ HexagonUnitAuction(unsigned cs = 0) : isSold(cs) {}
// Allocate slots.
bool bid(unsigned B) {
@@ -77,6 +85,7 @@ public:
return false;
}
};
+
} // end anonymous namespace
unsigned HexagonResource::setWeight(unsigned s) {
@@ -107,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)
@@ -120,12 +130,20 @@ 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,
MCInstrInfo const &MCII, unsigned s,
MCInst const *id)
- : HexagonResource(s), TUL(TUL) {
+ : HexagonResource(s) {
unsigned T = HexagonMCInstrInfo::getType(MCII, *id);
if (TUL->count(T)) {
@@ -149,10 +167,9 @@ struct CVIUnits {
unsigned Units;
unsigned Lanes;
};
-typedef SmallVector<struct CVIUnits, 8> HVXInstsT;
+using HVXInstsT = SmallVector<struct CVIUnits, 8>;
static unsigned makeAllBits(unsigned startBit, unsigned Lanes)
-
{
for (unsigned i = 1; i < Lanes; ++i)
startBit = (startBit << 1) | startBit;
@@ -160,9 +177,7 @@ static unsigned makeAllBits(unsigned startBit, unsigned Lanes)
}
static bool checkHVXPipes(const HVXInstsT &hvxInsts, unsigned startIdx,
- unsigned usedUnits)
-
-{
+ unsigned usedUnits) {
if (startIdx < hvxInsts.size()) {
if (!hvxInsts[startIdx].Units)
return checkHVXPipes(hvxInsts, startIdx + 1, usedUnits);
@@ -206,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;
@@ -238,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:
@@ -254,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;
@@ -294,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:
@@ -309,68 +378,38 @@ 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))) {
+ if ((load0 > 1 || store0 > 1) || (duplex > 1 || (duplex && memory))) {
reportError(llvm::Twine("invalid instruction packet"));
return false;
}
- if (jump1 && jumps > 1) {
- // Error if single branch with another branch.
- reportError(llvm::Twine("too many branches in packet"));
- return false;
- }
- if ((nvstores || memops) && stores > 1) {
- reportError(llvm::Twine("slot 0 instruction does not allow slot 1 store"));
- return false;
- }
- if (deallocs && stores) {
- reportError(llvm::Twine("slot 0 instruction does not allow slot 1 store"));
- return false;
- }
-
// Modify packet accordingly.
// TODO: need to reserve slots #0 and #1 for duplex insns.
bool bOnlySlot3 = false;
@@ -382,35 +421,49 @@ 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(
- llvm::Twine("invalid instruction packet: too many stores"));
+ reportError(Twine("invalid instruction packet: too many stores"));
return false;
}
// Pin the store to the highest slot available to it.
@@ -421,7 +474,7 @@ bool HexagonShuffler::check() {
}
if (store1 && stores > 1) {
// Error if a single store with another store.
- reportError(llvm::Twine("invalid instruction packet: too many stores"));
+ reportError(Twine("invalid instruction packet: too many stores"));
return false;
}
}
@@ -432,16 +485,16 @@ bool HexagonShuffler::check() {
if (!ISJ->Core.getUnits()) {
// Error if insn may not be executed in any slot.
- reportError(llvm::Twine("invalid instruction packet: out of slots"));
+ reportError(Twine("invalid instruction packet: out of slots"));
return false;
}
}
// preserve branch order
bool validateSlots = true;
- if (jumps > 1) {
+ if (foundBranches.size() > 1) {
if (foundBranches.size() > 2) {
- reportError(llvm::Twine("too many branches in packet"));
+ reportError(Twine("too many branches in packet"));
return false;
}
@@ -461,11 +514,11 @@ bool HexagonShuffler::check() {
foundBranches[1]->Core.setUnits(jumpSlots[i].second);
HexagonUnitAuction AuctionCore(reservedSlots);
- std::sort(begin(), end(), HexagonInstr::lessCore);
+ std::stable_sort(begin(), end(), HexagonInstr::lessCore);
// see if things ok with that instruction being pinned to slot "slotJump"
bool bFail = false;
- for (iterator I = begin(); I != end() && bFail != true; ++I)
+ for (iterator I = begin(); I != end() && !bFail; ++I)
if (!AuctionCore.bid(I->Core.getUnits()))
bFail = true;
@@ -477,13 +530,13 @@ bool HexagonShuffler::check() {
// restore original values
Packet = PacketSave;
}
- if (validateSlots == true) {
- reportError(llvm::Twine("invalid instruction packet: out of slots"));
+ if (validateSlots) {
+ reportError(Twine("invalid instruction packet: out of slots"));
return false;
}
}
- if (jumps <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 &&
+ if (foundBranches.size() <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 &&
slot3ISJ != end()) {
validateSlots = true;
// save off slot mask of instruction marked with A_PREFER_SLOT3
@@ -492,11 +545,11 @@ bool HexagonShuffler::check() {
slot3ISJ->Core.setUnits(saveUnits & slotThree);
HexagonUnitAuction AuctionCore(reservedSlots);
- std::sort(begin(), end(), HexagonInstr::lessCore);
+ std::stable_sort(begin(), end(), HexagonInstr::lessCore);
// see if things ok with that instruction being pinned to slot #3
bool bFail = false;
- for (iterator I = begin(); I != end() && bFail != true; ++I)
+ for (iterator I = begin(); I != end() && !bFail; ++I)
if (!AuctionCore.bid(I->Core.getUnits()))
bFail = true;
@@ -516,16 +569,16 @@ bool HexagonShuffler::check() {
if (validateSlots) {
HexagonUnitAuction AuctionCore(reservedSlots);
- std::sort(begin(), end(), HexagonInstr::lessCore);
+ std::stable_sort(begin(), end(), HexagonInstr::lessCore);
for (iterator I = begin(); I != end(); ++I)
if (!AuctionCore.bid(I->Core.getUnits())) {
- reportError(llvm::Twine("invalid instruction packet: slot error"));
+ reportError(Twine("invalid instruction packet: slot error"));
return false;
}
}
// Verify the CVI slot subscriptions.
- std::sort(begin(), end(), HexagonInstr::lessCVI);
+ std::stable_sort(begin(), end(), HexagonInstr::lessCVI);
// create vector of hvx instructions to check
HVXInstsT hvxInsts;
hvxInsts.clear();
@@ -541,9 +594,9 @@ bool HexagonShuffler::check() {
if (hvxInsts.size() > 0) {
unsigned startIdx, usedUnits;
startIdx = usedUnits = 0x0;
- if (checkHVXPipes(hvxInsts, startIdx, usedUnits) == false) {
+ if (!checkHVXPipes(hvxInsts, startIdx, usedUnits)) {
// too many pipes used to be valid
- reportError(llvm::Twine("invalid instruction packet: slot error"));
+ reportError(Twine("invalid instruction packet: slot error"));
return false;
}
}
@@ -555,7 +608,7 @@ 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.
- reportError(llvm::Twine("invalid instruction packet"));
+ reportError(Twine("invalid instruction packet"));
return false;
}
@@ -581,7 +634,7 @@ bool HexagonShuffler::shuffle() {
if (slotWeight)
// Sort the packet, favoring source order,
// beginning after the previous slot.
- std::sort(ISJ, Packet.end());
+ std::stable_sort(ISJ, Packet.end());
else
// Skip unused slot.
++emptySlots;
@@ -600,7 +653,13 @@ bool HexagonShuffler::shuffle() {
return Ok;
}
-void HexagonShuffler::reportError(llvm::Twine const &Msg) {
- if (ReportErrors)
+void HexagonShuffler::reportError(Twine const &Msg) {
+ 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/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h
index 10a959008f44..37f90bc46ac7 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h
@@ -1,4 +1,4 @@
-//===----- HexagonShuffler.h - Instruction bundle shuffling ---------------===//
+//===- HexagonShuffler.h - Instruction bundle shuffling ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,19 +12,26 @@
//
//===----------------------------------------------------------------------===//
-#ifndef HEXAGONSHUFFLER_H
-#define HEXAGONSHUFFLER_H
+#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
+#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/MC/MCInstrInfo.h"
-#include "llvm/MC/MCSubtargetInfo.h"
-
-using namespace llvm;
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/SMLoc.h"
+#include <cstdint>
+#include <utility>
namespace llvm {
+
+class MCContext;
+class MCInst;
+class MCInstrInfo;
+class MCSubtargetInfo;
+
// Insn resources.
class HexagonResource {
// Mask of the slots or units that may execute the insn and
@@ -32,32 +39,34 @@ class HexagonResource {
unsigned Slots, Weight;
public:
- HexagonResource(unsigned s) { setUnits(s); };
+ HexagonResource(unsigned s) { setUnits(s); }
void setUnits(unsigned s) {
Slots = s & ((1u << HEXAGON_PACKET_SIZE) - 1);
setWeight(s);
- };
+ }
+
unsigned setWeight(unsigned s);
- unsigned getUnits() const { return (Slots); };
- unsigned getWeight() const { return (Weight); };
+ unsigned getUnits() const { return (Slots); }
+ unsigned getWeight() const { return (Weight); }
// 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()));
- };
+ }
+
// Check if the resources are in ascending weight order.
static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
return (A.getWeight() < B.getWeight());
- };
+ }
};
// HVX insn resources.
class HexagonCVIResource : public HexagonResource {
public:
- typedef std::pair<unsigned, unsigned> UnitsAndLanes;
- typedef llvm::DenseMap<unsigned, UnitsAndLanes> TypeUnitsAndLanes;
+ using UnitsAndLanes = std::pair<unsigned, unsigned>;
+ using TypeUnitsAndLanes = DenseMap<unsigned, UnitsAndLanes>;
private:
// Available HVX slots.
@@ -69,8 +78,6 @@ private:
CVI_MPY1 = 1 << 3
};
- TypeUnitsAndLanes *TUL;
-
// Count of adjacent slots that the insn requires to be executed.
unsigned Lanes;
// Flag whether the insn is a load or a store.
@@ -78,19 +85,20 @@ private:
// Flag whether the HVX resources are valid.
bool Valid;
- void setLanes(unsigned l) { Lanes = l; };
- void setLoad(bool f = true) { Load = f; };
- void setStore(bool f = true) { Store = f; };
+ void setLanes(unsigned l) { Lanes = l; }
+ void setLoad(bool f = true) { Load = f; }
+ void setStore(bool f = true) { Store = f; }
public:
HexagonCVIResource(TypeUnitsAndLanes *TUL, MCInstrInfo const &MCII,
unsigned s, MCInst const *id);
+
static void SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU);
- bool isValid() const { return Valid; };
- unsigned getLanes() const { return Lanes; };
- bool mayLoad() const { return Load; };
- bool mayStore() const { return Store; };
+ bool isValid() const { return Valid; }
+ unsigned getLanes() const { return Lanes; }
+ bool mayLoad() const { return Load; }
+ bool mayStore() const { return Store; }
};
// Handle to an insn used by the shuffling algorithm.
@@ -106,30 +114,31 @@ public:
HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes *T,
MCInstrInfo const &MCII, MCInst const *id,
MCInst const *Extender, unsigned s)
- : ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id) {};
-
- MCInst const &getDesc() const { return *ID; };
+ : ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id) {}
+ MCInst const &getDesc() const { return *ID; }
MCInst const *getExtender() const { return Extender; }
// Check if the handles are in ascending order for shuffling purposes.
bool operator<(const HexagonInstr &B) const {
return (HexagonResource::lessWeight(B.Core, Core));
- };
+ }
+
// Check if the handles are in ascending order by core slots.
static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) {
return (HexagonResource::lessUnits(A.Core, B.Core));
- };
+ }
+
// Check if the handles are in ascending order by HVX slots.
static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B) {
return (HexagonResource::lessUnits(A.CVI, B.CVI));
- };
+ }
};
// Bundle shuffler.
class HexagonShuffler {
- typedef SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>
- HexagonPacket;
+ using HexagonPacket =
+ SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>;
// Insn handles in a bundle.
HexagonPacket Packet;
@@ -144,9 +153,13 @@ protected:
MCSubtargetInfo const &STI;
SMLoc Loc;
bool ReportErrors;
+ std::vector<std::pair<SMLoc, std::string>> AppliedRestrictions;
+ void applySlotRestrictions();
+ void restrictSlot1AOK();
+ void restrictNoSlot1Store();
public:
- typedef HexagonPacket::iterator iterator;
+ using iterator = HexagonPacket::iterator;
HexagonShuffler(MCContext &Context, bool ReportErrors,
MCInstrInfo const &MCII, MCSubtargetInfo const &STI);
@@ -158,17 +171,22 @@ public:
// Reorder the insn handles in the bundle.
bool shuffle();
- unsigned size() const { return (Packet.size()); };
+ unsigned size() const { return (Packet.size()); }
- iterator begin() { return (Packet.begin()); };
- iterator end() { return (Packet.end()); };
+ bool isMemReorderDisabled() const {
+ return (BundleFlags & HexagonMCInstrInfo::memReorderDisabledMask) != 0;
+ }
+
+ iterator begin() { return (Packet.begin()); }
+ iterator end() { return (Packet.end()); }
// Add insn handle to the bundle .
void append(MCInst const &ID, MCInst const *Extender, unsigned S);
// Return the error code for the last check or shuffling of the bundle.
- void reportError(llvm::Twine const &Msg);
+ void reportError(Twine const &Msg);
};
-} // namespace llvm
-#endif // HEXAGONSHUFFLER_H
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H