diff options
Diffstat (limited to 'lib/Target/Hexagon/MCTargetDesc')
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 |
