[llvm] r238692 - [Hexagon] Adding MC packet shuffler.
Justin Bogner
mail at justinbogner.com
Wed Jun 24 00:12:30 PDT 2015
Chandler Carruth <chandlerc at google.com> writes:
> Justin, I'd just revert until the UBSan issues can be fixed. It's important
> that we not let UBSan bots get stale and less useful because of this. (Our
> bots were red for other reasons which is why we didn't see this quickly, I'm
> glad you caught it!)
Reverting was difficult, as quite a few follow up changes made it in
after this one.
Colin, I'm told you're away, so I committed a change that avoids the
undefined behaviour in r240526. It's kind of scary that that change
works. We *really* need tests for this code.
> On Sat, Jun 20, 2015 at 12:26 AM Justin Bogner <mail at justinbogner.com> wrote:
>
> Colin LeMahieu <colinl at codeaurora.org> writes:
> > Author: colinl
> > Date: Sun May 31 16:57:09 2015
> > New Revision: 238692
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=238692&view=rev
> > Log:
> > [Hexagon] Adding MC packet shuffler.
>
> This commit hits undefined behaviour in the tests (I was running with
> ubsan locally). Combined with the fact that Rafael asked about test
> cases over two weeks ago and you seem not to have responded to that at
> all, I'm a bit concerned about this change.
>
> > Added:
> > llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp
> > llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h
> > llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
> > llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h
> > Modified:
> > llvm/trunk/lib/Target/Hexagon/Hexagon.h
> > llvm/trunk/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt
> > llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
> > llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
> > llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h
> >
> > Modified: llvm/trunk/lib/Target/Hexagon/Hexagon.h
> > URL:
> > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/
> Hexagon.h?rev=238692&r1=238691&r2=238692&view=diff
> > ========================================================================
> ======
> > --- llvm/trunk/lib/Target/Hexagon/Hexagon.h (original)
> > +++ llvm/trunk/lib/Target/Hexagon/Hexagon.h Sun May 31 16:57:09 2015
> > @@ -79,5 +79,8 @@ namespace llvm {
> > // Minimum number of instructions in an end-loop packet.
> > #define HEXAGON_PACKET_INNER_SIZE 2
> > #define HEXAGON_PACKET_OUTER_SIZE 3
> > +// Maximum number of instructions in a packet before shuffling,
> > +// including a compound one or a duplex or an extender.
> > +#define HEXAGON_PRESHUFFLE_PACKET_SIZE (HEXAGON_PACKET_SIZE + 3)
> >
> > #endif
> >
> > Modified: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/
> MCTargetDesc/CMakeLists.txt?rev=238692&r1=238691&r2=238692&view=diff
> > ========================================================================
> ======
> > --- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt (original)
> > +++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt Sun May 31
> 16:57:09 2015
> > @@ -5,7 +5,9 @@ add_llvm_library(LLVMHexagonDesc
> > HexagonMCAsmInfo.cpp
> > HexagonMCCodeEmitter.cpp
> > HexagonMCInstrInfo.cpp
> > + HexagonMCShuffler.cpp
> > HexagonMCTargetDesc.cpp
> > + HexagonShuffler.cpp
> > )
> >
> > add_dependencies(LLVMHexagonDesc HexagonCommonTableGen)
> >
> > Modified: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/
> HexagonMCInstrInfo.cpp
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/
> MCTargetDesc/HexagonMCInstrInfo.cpp?rev=238692&r1=238691&r2=238692&view=
> diff
> > ========================================================================
> ======
> > --- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
> (original)
> > +++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
> Sun May 31 16:57:09 2015
> > @@ -11,9 +11,12 @@
> > //
> > //===
> ----------------------------------------------------------------------===/
> /
> >
> > +#include "HexagonMCInstrInfo.h"
> > +
> > #include "Hexagon.h"
> > #include "HexagonBaseInfo.h"
> > -#include "HexagonMCInstrInfo.h"
> > +
> > +#include "llvm/MC/MCSubtargetInfo.h"
> >
> > namespace llvm {
> > iterator_range<MCInst::const_iterator>
> > @@ -140,6 +143,21 @@ MCOperand const &HexagonMCInstrInfo::get
> > return (MCO);
> > }
> >
> > +int HexagonMCInstrInfo::getSubTarget(MCInstrInfo const &MCII,
> > + MCInst const &MCI) {
> > + const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
> > +
> > + HexagonII::SubTarget Target = static_cast<HexagonII::SubTarget>(
> > + (F >> HexagonII::validSubTargetPos) &
> HexagonII::validSubTargetMask);
> > +
> > + switch (Target) {
> > + default:
> > + return Hexagon::ArchV4;
> > + case HexagonII::HasV5SubT:
> > + return Hexagon::ArchV5;
> > + }
> > +}
> > +
> > // Return the Hexagon ISA class for the insn.
> > unsigned HexagonMCInstrInfo::getType(MCInstrInfo const &MCII,
> > MCInst const &MCI) {
> > @@ -148,6 +166,28 @@ unsigned HexagonMCInstrInfo::getType(MCI
> > return ((F >> HexagonII::TypePos) & HexagonII::TypeMask);
> > }
> >
> > +unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII,
> > + MCSubtargetInfo const &STI,
> > + MCInst const &MCI) {
> > +
> > + const InstrItinerary *II = STI.getSchedModel().InstrItineraries;
> > + int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass
> ();
> > + return ((II[SchedClass].FirstStage + HexagonStages)->getUnits());
> > +}
> > +
> > +bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) {
> > + if (!HexagonMCInstrInfo::isBundle(MCI))
> > + return false;
> > +
> > + for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCI)) {
> > + auto MI = I.getInst();
> > + if (isImmext(*MI))
> > + return true;
> > + }
> > +
> > + return false;
> > +}
> > +
> > // Return whether the instruction is a legal new-value producer.
> > bool HexagonMCInstrInfo::hasNewValue(MCInstrInfo const &MCII,
> > MCInst const &MCI) {
> > @@ -212,20 +252,23 @@ bool HexagonMCInstrInfo::isConstExtended
> > return (ImmValue < MinValue || ImmValue > MaxValue);
> > }
> >
> > -// Return true if the instruction may be extended based on the operand
> value.
> > bool HexagonMCInstrInfo::isExtendable(MCInstrInfo const &MCII,
> > MCInst const &MCI) {
> > uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
> > return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask;
> > }
> >
> > -// Return whether the instruction must be always extended.
> > bool HexagonMCInstrInfo::isExtended(MCInstrInfo const &MCII,
> > MCInst const &MCI) {
> > uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
> > return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
> > }
> >
> > +bool HexagonMCInstrInfo::isFloat(MCInstrInfo const &MCII, MCInst const
> &MCI) {
> > + const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
> > + return ((F >> HexagonII::FPPos) & HexagonII::FPMask);
> > +}
> > +
> > bool HexagonMCInstrInfo::isImmext(MCInst const &MCI) {
> > auto Op = MCI.getOpcode();
> > return (Op == Hexagon::A4_ext_b || Op == Hexagon::A4_ext_c ||
> > @@ -273,17 +316,26 @@ bool HexagonMCInstrInfo::isPredicatedTru
> > !((F >> HexagonII::PredicatedFalsePos) &
> HexagonII::PredicatedFalseMask));
> > }
> >
> > -// Return whether the insn is a prefix.
> > bool HexagonMCInstrInfo::isPrefix(MCInstrInfo const &MCII, MCInst const
> &MCI) {
> > return (HexagonMCInstrInfo::getType(MCII, MCI) ==
> HexagonII::TypePREFIX);
> > }
> >
> > -// Return whether the insn is solo, i.e., cannot be in a packet.
> > bool HexagonMCInstrInfo::isSolo(MCInstrInfo const &MCII, MCInst const &
> MCI) {
> > const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
> > return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask);
> > }
> >
> > +bool HexagonMCInstrInfo::isSoloAX(MCInstrInfo const &MCII, MCInst const
> &MCI) {
> > + const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
> > + return ((F >> HexagonII::SoloAXPos) & HexagonII::SoloAXMask);
> > +}
> > +
> > +bool HexagonMCInstrInfo::isSoloAin1(MCInstrInfo const &MCII,
> > + MCInst const &MCI) {
> > + const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;
> > + return ((F >> HexagonII::SoloAin1Pos) & HexagonII::SoloAin1Mask);
> > +}
> > +
> > void HexagonMCInstrInfo::padEndloop(MCInst &MCB) {
> > MCInst Nop;
> > Nop.setOpcode(Hexagon::A2_nop);
> > @@ -295,6 +347,26 @@ void HexagonMCInstrInfo::padEndloop(MCIn
> > MCB.addOperand(MCOperand::createInst(new MCInst(Nop)));
> > }
> >
> > +bool HexagonMCInstrInfo::prefersSlot3(MCInstrInfo const &MCII,
> > + MCInst const &MCI) {
> > + if (HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCR)
> > + return false;
> > +
> > + unsigned SchedClass = HexagonMCInstrInfo::getDesc(MCII,
> MCI).getSchedClass();
> > + switch (SchedClass) {
> > + case Hexagon::Sched::ALU32_3op_tc_2_SLOT0123:
> > + case Hexagon::Sched::ALU64_tc_2_SLOT23:
> > + case Hexagon::Sched::ALU64_tc_3x_SLOT23:
> > + case Hexagon::Sched::M_tc_2_SLOT23:
> > + case Hexagon::Sched::M_tc_3x_SLOT23:
> > + case Hexagon::Sched::S_2op_tc_2_SLOT23:
> > + case Hexagon::Sched::S_3op_tc_2_SLOT23:
> > + case Hexagon::Sched::S_3op_tc_3x_SLOT23:
> > + return true;
> > + }
> > + return false;
> > +}
> > +
> > void HexagonMCInstrInfo::setInnerLoop(MCInst &MCI) {
> > assert(isBundle(MCI));
> > MCOperand &Operand = MCI.getOperand(0);
> >
> > Modified: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/
> HexagonMCInstrInfo.h
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/
> MCTargetDesc/HexagonMCInstrInfo.h?rev=238692&r1=238691&r2=238692&view=diff
> > ========================================================================
> ======
> > --- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
> (original)
> > +++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h Sun
> May 31 16:57:09 2015
> > @@ -1,4 +1,4 @@
> > -//===- HexagonMCInstrInfo.cpp - Hexagon sub-class of MCInst
> ---------------===//
> > +//===- HexagonMCInstrInfo.cpp - Utility functions on Hexagon MCInsts
> ------===//
> > //
> > // The LLVM Compiler Infrastructure
> > //
> > @@ -27,6 +27,12 @@ class MCOperand;
> > 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 HexagonMCInstrInfo {
> > size_t const innerLoopOffset = 0;
> > int64_t const innerLoopMask = 1 << innerLoopOffset;
> > @@ -84,9 +90,17 @@ unsigned short getNewValueOp(MCInstrInfo
> > // Return the operand that consumes or produces a new value.
> > MCOperand const &getNewValueOperand(MCInstrInfo const &MCII, MCInst
> const &MCI);
> >
> > +int getSubTarget(MCInstrInfo const &MCII, MCInst const &MCI);
> > +
> > // Return the Hexagon ISA class for the insn.
> > unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI);
> >
> > +/// Return the slots used by the insn.
> > +unsigned getUnits(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
> > + MCInst const &MCI);
> > +
> > +bool hasImmExt(MCInst const &MCI);
> > +
> > // Return whether the instruction is a legal new-value producer.
> > bool hasNewValue(MCInstrInfo const &MCII, MCInst const &MCI);
> >
> > @@ -108,6 +122,9 @@ bool isExtendable(MCInstrInfo const &MCI
> > // Return whether the instruction must be always extended.
> > bool isExtended(MCInstrInfo const &MCII, MCInst const &MCI);
> >
> > +/// Return whether it is a floating-point insn.
> > +bool isFloat(MCInstrInfo const &MCII, MCInst const &MCI);
> > +
> > // Returns whether this instruction is an immediate extender
> > bool isImmext(MCInst const &MCI);
> >
> > @@ -136,9 +153,17 @@ bool isPrefix(MCInstrInfo const &MCII, M
> > // Return whether the insn is solo, i.e., cannot be in a packet.
> > bool isSolo(MCInstrInfo const &MCII, MCInst const &MCI);
> >
> > +/// Return whether the insn can be packaged only with A and X-type
> insns.
> > +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);
> > +
> > // Pad the bundle with nops to satisfy endloop requirements
> > void padEndloop(MCInst &MCI);
> >
> > +bool prefersSlot3(MCInstrInfo const &MCII, MCInst const &MCI);
> > +
> > // Marks a bundle as endloop0
> > void setInnerLoop(MCInst &MCI);
> >
> >
> > Added: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/
> MCTargetDesc/HexagonMCShuffler.cpp?rev=238692&view=auto
> > ========================================================================
> ======
> > --- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp
> (added)
> > +++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp Sun
> May 31 16:57:09 2015
> > @@ -0,0 +1,181 @@
> > +//===----- HexagonMCShuffler.cpp - MC bundle shuffling
> --------------------===//
> > +//
> > +// The LLVM Compiler Infrastructure
> > +//
> > +// This file is distributed under the University of Illinois Open
> Source
> > +// License. See LICENSE.TXT for details.
> > +//
> > +//===
> ----------------------------------------------------------------------===/
> /
> > +//
> > +// This implements the shuffling of insns inside a bundle according to
> the
> > +// packet formation rules of the Hexagon ISA.
> > +//
> > +//===
> ----------------------------------------------------------------------===/
> /
> > +
> > +#define DEBUG_TYPE "hexagon-shuffle"
> > +
> > +#include "Hexagon.h"
> > +#include "MCTargetDesc/HexagonMCInstrInfo.h"
> > +#include "MCTargetDesc/HexagonMCShuffler.h"
> > +#include "MCTargetDesc/HexagonMCTargetDesc.h"
> > +#include "llvm/Support/CommandLine.h"
> > +#include "llvm/Support/Debug.h"
> > +
> > +using namespace llvm;
> > +
> > +static cl::opt<bool>
> > + DisableShuffle("disable-hexagon-shuffle", cl::Hidden, cl::init
> (false),
> > + cl::desc("Disable Hexagon instruction shuffling"));
> > +
> > +void HexagonMCShuffler::init(MCInst &MCB) {
> > + if (HexagonMCInstrInfo::isBundle(MCB)) {
> > + MCInst const *Extender = nullptr;
> > + // Copy the bundle for the shuffling.
> > + for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
> > + assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo
> ());
> > + MCInst *MI = const_cast<MCInst *>(I.getInst());
> > +
> > + if (!HexagonMCInstrInfo::isImmext(*MI)) {
> > + append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI,
> *MI),
> > + false);
> > + Extender = nullptr;
> > + } else
> > + Extender = MI;
> > + }
> > + }
> > +
> > + BundleFlags = MCB.getOperand(0).getImm();
> > +}
> > +
> > +void HexagonMCShuffler::init(MCInst &MCB, MCInst const *AddMI,
> > + bool bInsertAtFront) {
> > + if (HexagonMCInstrInfo::isBundle(MCB)) {
> > + if (bInsertAtFront && AddMI)
> > + append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI,
> *AddMI),
> > + false);
> > + MCInst const *Extender = nullptr;
> > + // Copy the bundle for the shuffling.
> > + for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
> > + assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo
> ());
> > + MCInst *MI = const_cast<MCInst *>(I.getInst());
> > + if (!HexagonMCInstrInfo::isImmext(*MI)) {
> > + append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI,
> *MI),
> > + false);
> > + Extender = nullptr;
> > + } else
> > + Extender = MI;
> > + }
> > + if (!bInsertAtFront && AddMI)
> > + append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI,
> *AddMI),
> > + false);
> > + }
> > +
> > + BundleFlags = MCB.getOperand(0).getImm();
> > +}
> > +
> > +void HexagonMCShuffler::copyTo(MCInst &MCB) {
> > + MCB.clear();
> > + MCB.addOperand(MCOperand::createImm(BundleFlags));
> > + // Copy the results into the bundle.
> > + for (HexagonShuffler::iterator I = begin(); I != end(); ++I) {
> > +
> > + MCInst const *MI = I->getDesc();
> > + MCInst const *Extender = I->getExtender();
> > + if (Extender)
> > + MCB.addOperand(MCOperand::createInst(Extender));
> > + MCB.addOperand(MCOperand::createInst(MI));
> > + }
> > +}
> > +
> > +bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) {
> > + if (shuffle()) {
> > + // Copy the results into the bundle.
> > + copyTo(MCB);
> > + } else
> > + DEBUG(MCB.dump());
> > +
> > + return (!getError());
> > +}
> > +
> > +bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo
> const &STI,
> > + MCInst &MCB) {
> > + HexagonMCShuffler MCS(MCII, STI, MCB);
> > +
> > + if (DisableShuffle)
> > + // Ignore if user chose so.
> > + 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:
> > + // After the IMPLICIT_DEFs were removed by the asm printer, the
> bundle
> > + // became empty.
> > + DEBUG(dbgs() << "Skipping empty bundle");
> > + return false;
> > + } else if (!HexagonMCInstrInfo::isBundle(MCB)) {
> > + DEBUG(dbgs() << "Skipping stand-alone insn");
> > + return false;
> > + }
> > +
> > + // Reorder the bundle and copy the result.
> > + if (!MCS.reshuffleTo(MCB)) {
> > + // Unless there is any error, which should not happen at this
> point.
> > + unsigned shuffleError = MCS.getError();
> > + switch (shuffleError) {
> > + default:
> > + llvm_unreachable("unknown error");
> > + case HexagonShuffler::SHUFFLE_ERROR_INVALID:
> > + llvm_unreachable("invalid packet");
> > + case HexagonShuffler::SHUFFLE_ERROR_STORES:
> > + llvm_unreachable("too many stores");
> > + case HexagonShuffler::SHUFFLE_ERROR_LOADS:
> > + llvm_unreachable("too many loads");
> > + case HexagonShuffler::SHUFFLE_ERROR_BRANCHES:
> > + llvm_unreachable("too many branches");
> > + case HexagonShuffler::SHUFFLE_ERROR_NOSLOTS:
> > + llvm_unreachable("no suitable slot");
> > + case HexagonShuffler::SHUFFLE_ERROR_SLOTS:
> > + llvm_unreachable("over-subscribed slots");
> > + case HexagonShuffler::SHUFFLE_SUCCESS: // Single instruction case.
> > + return true;
> > + }
> > + }
> > +
> > + return true;
> > +}
> > +
> > +bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo
> const &STI,
> > + MCInst &MCB, MCInst const *AddMI, int
> fixupCount) {
> > + if (!HexagonMCInstrInfo::isBundle(MCB) || !AddMI)
> > + return false;
> > +
> > + // if fixups present, make sure we don't insert too many nops that
> would
> > + // later prevent an extender from being inserted.
> > + unsigned int bundleSize = HexagonMCInstrInfo::bundleSize(MCB);
> > + if (bundleSize >= HEXAGON_PACKET_SIZE)
> > + return false;
> > + if (fixupCount >= 2) {
> > + return false;
> > + } else {
> > + if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount)
> > + return false;
> > + }
> > +
> > + if (DisableShuffle)
> > + return false;
> > +
> > + HexagonMCShuffler MCS(MCII, STI, MCB, AddMI);
> > + if (!MCS.reshuffleTo(MCB)) {
> > + unsigned shuffleError = MCS.getError();
> > + switch (shuffleError) {
> > + default:
> > + return false;
> > + case HexagonShuffler::SHUFFLE_SUCCESS: // single instruction case
> > + return true;
> > + }
> > + }
> > +
> > + return true;
> > +}
> >
> > Added: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/
> MCTargetDesc/HexagonMCShuffler.h?rev=238692&view=auto
> > ========================================================================
> ======
> > --- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h
> (added)
> > +++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h Sun
> May 31 16:57:09 2015
> > @@ -0,0 +1,65 @@
> > +//=-- HexagonMCShuffler.h
> ---------------------------------------------------=//
> > +//
> > +// The LLVM Compiler Infrastructure
> > +//
> > +// This file is distributed under the University of Illinois Open
> Source
> > +// License. See LICENSE.TXT for details.
> > +//
> > +//===
> ----------------------------------------------------------------------===/
> /
> > +//
> > +// This declares the shuffling of insns inside a bundle according to
> the
> > +// packet formation rules of the Hexagon ISA.
> > +//
> > +//===
> ----------------------------------------------------------------------===/
> /
> > +
> > +#ifndef HEXAGONMCSHUFFLER_H
> > +#define HEXAGONMCSHUFFLER_H
> > +
> > +#include "MCTargetDesc/HexagonShuffler.h"
> > +
> > +namespace llvm {
> > +
> > +class MCInst;
> > +
> > +// Insn bundle shuffler.
> > +class HexagonMCShuffler : public HexagonShuffler {
> > + bool immext_present;
> > + bool duplex_present;
> > +
> > +public:
> > + HexagonMCShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &
> STI,
> > + MCInst &MCB)
> > + : HexagonShuffler(MCII, STI) {
> > + init(MCB);
> > + };
> > + HexagonMCShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &
> STI,
> > + MCInst &MCB, const MCInst *AddMI,
> > + bool bInsertAtFront = false)
> > + : HexagonShuffler(MCII, STI) {
> > + init(MCB, AddMI, bInsertAtFront);
> > + };
> > +
> > + // Copy reordered bundle to another.
> > + void copyTo(MCInst &MCB);
> > + // Reorder and copy result to another.
> > + bool reshuffleTo(MCInst &MCB);
> > +
> > + bool immextPresent() const { return immext_present; };
> > + bool duplexPresent() const { return duplex_present; };
> > +
> > +private:
> > + void init(MCInst &MCB);
> > + void init(MCInst &MCB, const MCInst *AddMI, bool bInsertAtFront =
> false);
> > +};
> > +
> > +// Invocation of the shuffler.
> > +bool HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &
> STI,
> > + MCInst &);
> > +bool HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &
> STI,
> > + MCInst &, const MCInst *, int);
> > +unsigned HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo
> const &STI,
> > + MCContext &Context, MCInst &,
> > + SmallVector<DuplexCandidate, 8>);
> > +}
> > +
> > +#endif // HEXAGONMCSHUFFLER_H
> >
> > Modified: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/
> HexagonMCTargetDesc.h
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/
> MCTargetDesc/HexagonMCTargetDesc.h?rev=238692&r1=238691&r2=238692&view=
> diff
> > ========================================================================
> ======
> > --- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h
> (original)
> > +++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h Sun
> May 31 16:57:09 2015
> > @@ -17,6 +17,8 @@
> > #include <cstdint>
> >
> > namespace llvm {
> > +class InstrItinerary;
> > +class InstrStage;
> > class MCAsmBackend;
> > class MCCodeEmitter;
> > class MCContext;
> > @@ -31,6 +33,8 @@ class raw_pwrite_stream;
> >
> > extern Target TheHexagonTarget;
> >
> > +extern const InstrStage HexagonStages[];
> > +
> > MCInstrInfo *createHexagonMCInstrInfo();
> >
> > MCCodeEmitter *createHexagonMCCodeEmitter(MCInstrInfo const &MCII,
> >
> > Added: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/
> MCTargetDesc/HexagonShuffler.cpp?rev=238692&view=auto
> > ========================================================================
> ======
> > --- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
> (added)
> > +++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp Sun
> May 31 16:57:09 2015
> > @@ -0,0 +1,385 @@
> > +//===----- HexagonShuffler.cpp - Instruction bundle shuffling
> -------------===//
> > +//
> > +// The LLVM Compiler Infrastructure
> > +//
> > +// This file is distributed under the University of Illinois Open
> Source
> > +// License. See LICENSE.TXT for details.
> > +//
> > +//===
> ----------------------------------------------------------------------===/
> /
> > +//
> > +// This implements the shuffling of insns inside a bundle according to
> the
> > +// packet formation rules of the Hexagon ISA.
> > +//
> > +//===
> ----------------------------------------------------------------------===/
> /
> > +
> > +#define DEBUG_TYPE "hexagon-shuffle"
> > +
> > +#include <algorithm>
> > +#include <utility>
> > +#include "Hexagon.h"
> > +#include "MCTargetDesc/HexagonBaseInfo.h"
> > +#include "MCTargetDesc/HexagonMCTargetDesc.h"
> > +#include "MCTargetDesc/HexagonMCInstrInfo.h"
> > +#include "HexagonShuffler.h"
> > +#include "llvm/Support/Debug.h"
> > +#include "llvm/Support/MathExtras.h"
> > +#include "llvm/Support/raw_ostream.h"
> > +
> > +using namespace llvm;
> > +
> > +// 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;
> > +
> > +public:
> > + HexagonBid() : Bid(0){};
> > + HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; };
> > +
> > + // Check if the insn priority is overflowed.
> > + bool isSold() const { return (Bid >= MAX); };
> > +
> > + HexagonBid &operator+=(const HexagonBid &B) {
> > + Bid += B.Bid;
> > + return *this;
> > + };
> > +};
> > +
> > +// Slot shuffling allocation.
> > +class HexagonUnitAuction {
> > + HexagonBid Scores[HEXAGON_PACKET_SIZE];
> > + // Mask indicating which slot is unavailable.
> > + unsigned isSold : HEXAGON_PACKET_SIZE;
> > +
> > +public:
> > + HexagonUnitAuction() : isSold(0){};
> > +
> > + // Allocate slots.
> > + bool bid(unsigned B) {
> > + // Exclude already auctioned slots from the bid.
> > + unsigned b = B & ~isSold;
> > + if (b) {
> > + for (unsigned i = 0; i < HEXAGON_PACKET_SIZE; ++i)
> > + if (b & (1 << i)) {
> > + // Request candidate slots.
> > + Scores[i] += HexagonBid(b);
> > + isSold |= Scores[i].isSold() << i;
> > + }
> > + return true;
> > + ;
> > + } else
> > + // Error if the desired slots are already full.
> > + return false;
> > + };
> > +};
> > +
> > +unsigned HexagonResource::setWeight(unsigned s) {
> > + const unsigned SlotWeight = 8;
> > + const unsigned MaskWeight = SlotWeight - 1;
> > + bool Key = (1 << s) & getUnits();
> > +
> > + // Calculate relative weight of the insn for the given slot, weighing
> it the
> > + // heavier the more restrictive the insn is and the lowest the slots
> that the
> > + // insn may be executed in.
> > + Weight =
> > + (Key << (SlotWeight * s)) * ((MaskWeight - countPopulation
> (getUnits()))
> > + << countTrailingZeros(getUnits()));
>
> If `s` is 4 or more here we hit undefined behaviour since we end up with
> a shift value that's greater than 32 (since Key is implicitly converted
> to int here). We should probably change this interface so it's harder to
> mess up, or at least assert(s < 4) in here.
>
> Worse still, `s` seems to regularly take values such as 12 and 15 in the
> existing lit tests, according to ubsan:
>
> ********************
> FAIL: LLVM :: MC/Hexagon/inst_or.ll (9070 of 13946)
> ******************** TEST 'LLVM :: MC/Hexagon/inst_or.ll' FAILED
> ********************
> Script:
> --
> /Users/bogner/build/llvm-san/./bin/llc -mtriple=hexagon-unknown-elf
> -filetype=obj /Volumes/Data/bogner/code/llvm/test/MC/Hexagon/inst_or.ll -o
> - | /Users/bogne
> r/build/llvm-san/./bin/llvm-objdump -s - | /Users/bogner/build/llvm-san
> /./bin/FileCheck /Volumes/Data/bogner/code/llvm/test/MC/Hexagon/inst_or.ll
> --
> Exit Code: 2
>
> Command Output (stderr):
> --
> /Users/bogner/code/llvm/lib/Target/Hexagon/MCTargetDesc/
> HexagonShuffler.cpp:88:12: runtime error: shift exponent 120 is too large
> for 32-bit type 'int'
> SUMMARY: AddressSanitizer: undefined-behavior /Users/bogner/code/llvm/
> lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp:88:12 in
> /Users/bogner/build/llvm-san/./bin/llvm-objdump: '-': The file was not
> recognized as a valid object file.
> FileCheck error: '-' is empty.
>
> --
>
> ********************
> FAIL: LLVM :: MC/Hexagon/inst_or64.ll (9071 of 13946)
> ******************** TEST 'LLVM :: MC/Hexagon/inst_or64.ll' FAILED
> ********************
> Script:
> --
> /Users/bogner/build/llvm-san/./bin/llc -mtriple=hexagon-unknown-elf
> -filetype=obj /Volumes/Data/bogner/code/llvm/test/MC/Hexagon/inst_or64.ll
> -o - | /Users/bog
> ner/build/llvm-san/./bin/llvm-objdump -s - | /Users/bogner/build/
> llvm-san/./bin/FileCheck /Volumes/Data/bogner/code/llvm/test/MC/Hexagon/
> inst_or64.ll
> --
> Exit Code: 2
>
> Command Output (stderr):
> --
> /Users/bogner/code/llvm/lib/Target/Hexagon/MCTargetDesc/
> HexagonShuffler.cpp:88:12: runtime error: shift exponent 96 is too large
> for 32-bit type 'int'
> SUMMARY: AddressSanitizer: undefined-behavior /Users/bogner/code/llvm/
> lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp:88:12 in
> /Users/bogner/build/llvm-san/./bin/llvm-objdump: '-': The file was not
> recognized as a valid object file.
> FileCheck error: '-' is empty.
>
> --
>
> > + return (Weight);
> > +}
> > +
> > +HexagonShuffler::HexagonShuffler(MCInstrInfo const &MCII,
> > + MCSubtargetInfo const &STI)
> > + : MCII(MCII), STI(STI) {
> > + reset();
> > +}
> > +
> > +void HexagonShuffler::reset() {
> > + Packet.clear();
> > + BundleFlags = 0;
> > + Error = SHUFFLE_SUCCESS;
> > +}
> > +
> > +void HexagonShuffler::append(MCInst const *ID, MCInst const *Extender,
> > + unsigned S, bool X) {
> > + HexagonInstr PI(ID, Extender, S, X);
> > +
> > + Packet.push_back(PI);
> > +}
> > +
> > +/// Check that the packet is legal and enforce relative insn order.
> > +bool HexagonShuffler::check() {
> > + // Descriptive slot masks.
> > + const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne =
> 0x2,
> > + slotThree = 0x8, slotFirstJump = 0x8, slotLastJump =
> 0x4,
> > + 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, jumpr = 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, solo insns.
> > + unsigned duplex = 0, solo = 0;
> > + // Number of insns restricting other insns in the packet to A and X
> types,
> > + // which is neither A or X types.
> > + unsigned onlyAX = 0, neitherAnorX = 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 xtypeFloat = 0;
> > + unsigned pSlot3Cnt = 0;
> > + iterator slot3ISJ = end();
> > +
> > + // Collect information from the insns in the packet.
> > + for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
> > + MCInst const *ID = ISJ->getDesc();
> > +
> > + if (HexagonMCInstrInfo::isSolo(MCII, *ID))
> > + solo += !ISJ->isSoloException();
> > + else if (HexagonMCInstrInfo::isSoloAX(MCII, *ID))
> > + onlyAX += !ISJ->isSoloException();
> > + else if (HexagonMCInstrInfo::isSoloAin1(MCII, *ID))
> > + onlyAin1 += !ISJ->isSoloException();
> > + if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32
> &&
> > + HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeXTYPE)
> > + ++neitherAnorX;
> > + if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID)) {
> > + ++pSlot3Cnt;
> > + slot3ISJ = ISJ;
> > + }
> > +
> > + switch (HexagonMCInstrInfo::getType(MCII, *ID)) {
> > + case HexagonII::TypeXTYPE:
> > + if (HexagonMCInstrInfo::isFloat(MCII, *ID))
> > + ++xtypeFloat;
> > + break;
> > + case HexagonII::TypeJR:
> > + ++jumpr;
> > + // Fall-through.
> > + case HexagonII::TypeJ:
> > + ++jumps;
> > + break;
> > + case HexagonII::TypeLD:
> > + ++loads;
> > + ++memory;
> > + if (ISJ->Core.getUnits() == slotSingleLoad)
> > + ++load0;
> > + if (HexagonMCInstrInfo::getDesc(MCII, *ID).isReturn())
> > + ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
> > + break;
> > + case HexagonII::TypeST:
> > + ++stores;
> > + ++memory;
> > + if (ISJ->Core.getUnits() == slotSingleStore)
> > + ++store0;
> > + break;
> > + case HexagonII::TypeMEMOP:
> > + ++loads;
> > + ++stores;
> > + ++store1;
> > + ++memory;
> > + break;
> > + case HexagonII::TypeNV:
> > + ++memory; // NV insns are memory-like.
> > + if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch())
> > + ++jumps, ++jump1;
> > + break;
> > + case HexagonII::TypeCR:
> > + // Legacy conditional branch predicated on a register.
> > + case HexagonII::TypeSYSTEM:
> > + if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad())
> > + ++loads;
> > + break;
> > + }
> > + }
> > +
> > + // Check if the packet is legal.
> > + if ((load0 > 1 || store0 > 1) || (duplex > 1 || (duplex && memory)) |
> |
> > + (solo && size() > 1) || (onlyAX && neitherAnorX > 1) ||
> > + (onlyAX && xtypeFloat)) {
> > + Error = SHUFFLE_ERROR_INVALID;
> > + return false;
> > + }
> > +
> > + if (jump1 && jumps > 1) {
> > + // Error if single branch with another branch.
> > + Error = SHUFFLE_ERROR_BRANCHES;
> > + return false;
> > + }
> > +
> > + // Modify packet accordingly.
> > + // TODO: need to reserve slots #0 and #1 for duplex insns.
> > + bool bOnlySlot3 = false;
> > + for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
> > + MCInst const *ID = ISJ->getDesc();
> > +
> > + if (!ISJ->Core.getUnits()) {
> > + // Error if insn may not be executed in any slot.
> > + Error = SHUFFLE_ERROR_UNKNOWN;
> > + 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)
> > + if (onlyAin1)
> > + ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
> > +
> > + // Branches must keep the original order.
> > + if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch() ||
> > + HexagonMCInstrInfo::getDesc(MCII, *ID).isCall())
> > + if (jumps > 1) {
> > + if (jumpr || slotJump < slotLastJump) {
> > + // Error if indirect branch with another branch or
> > + // no more slots available for branches.
> > + Error = SHUFFLE_ERROR_BRANCHES;
> > + return false;
> > + }
> > + // Pin the branch to the highest slot available to it.
> > + ISJ->Core.setUnits(ISJ->Core.getUnits() & slotJump);
> > + // Update next highest slot available to branches.
> > + slotJump >>= 1;
> > + }
> > +
> > + // A single load must use slot #0.
> > + if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad()) {
> > + if (loads == 1 && loads == memory)
> > + // Pin the load to slot #0.
> > + ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
> > + }
> > +
> > + // A single store must use slot #0.
> > + if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayStore()) {
> > + if (!store0) {
> > + if (stores == 1)
> > + ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);
> > + else if (stores > 1) {
> > + if (slotLoadStore < slotLastLoadStore) {
> > + // Error if no more slots available for stores.
> > + Error = SHUFFLE_ERROR_STORES;
> > + return false;
> > + }
> > + // Pin the store to the highest slot available to it.
> > + ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
> > + // Update the next highest slot available to stores.
> > + slotLoadStore >>= 1;
> > + }
> > + }
> > + if (store1 && stores > 1) {
> > + // Error if a single store with another store.
> > + Error = SHUFFLE_ERROR_STORES;
> > + return false;
> > + }
> > + }
> > +
> > + // flag if an instruction can only be executed in slot 3
> > + if (ISJ->Core.getUnits() == slotThree)
> > + bOnlySlot3 = true;
> > +
> > + if (!ISJ->Core.getUnits()) {
> > + // Error if insn may not be executed in any slot.
> > + Error = SHUFFLE_ERROR_NOSLOTS;
> > + return false;
> > + }
> > + }
> > +
> > + bool validateSlots = true;
> > + if (bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) {
> > + // save off slot mask of instruction marked with A_PREFER_SLOT3
> > + // and then pin it to slot #3
> > + unsigned saveUnits = slot3ISJ->Core.getUnits();
> > + slot3ISJ->Core.setUnits(saveUnits & slotThree);
> > +
> > + HexagonUnitAuction AuctionCore;
> > + std::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)
> > + if (!AuctionCore.bid(I->Core.getUnits()))
> > + bFail = true;
> > +
> > + // if yes, great, if not then restore original slot mask
> > + if (!bFail)
> > + validateSlots = false; // all good, no need to re-do auction
> > + else
> > + for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
> > + MCInst const *ID = ISJ->getDesc();
> > + if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID))
> > + ISJ->Core.setUnits(saveUnits);
> > + }
> > + }
> > +
> > + // Check if any slot, core, is over-subscribed.
> > + // Verify the core slot subscriptions.
> > + if (validateSlots) {
> > + HexagonUnitAuction AuctionCore;
> > +
> > + std::sort(begin(), end(), HexagonInstr::lessCore);
> > +
> > + for (iterator I = begin(); I != end(); ++I)
> > + if (!AuctionCore.bid(I->Core.getUnits())) {
> > + Error = SHUFFLE_ERROR_SLOTS;
> > + return false;
> > + }
> > + }
> > +
> > + Error = SHUFFLE_SUCCESS;
> > + return true;
> > +}
> > +
> > +bool HexagonShuffler::shuffle() {
> > + if (size() > HEXAGON_PACKET_SIZE) {
> > + // Ignore a packet with with more than what a packet can hold
> > + // or with compound or duplex insns for now.
> > + Error = SHUFFLE_ERROR_INVALID;
> > + return false;
> > + }
> > +
> > + // Check and prepare packet.
> > + if (size() > 1 && check())
> > + // Reorder the handles for each slot.
> > + for (unsigned nSlot = 0, emptySlots = 0; nSlot <
> HEXAGON_PACKET_SIZE;
> > + ++nSlot) {
> > + iterator ISJ, ISK;
> > + unsigned slotSkip, slotWeight;
> > +
> > + // Prioritize the handles considering their restrictions.
> > + for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0;
> > + ISK != Packet.end(); ++ISK, ++slotSkip)
> > + if (slotSkip < nSlot - emptySlots)
> > + // Note which handle to begin at.
> > + ++ISJ;
> > + else
> > + // Calculate the weight of the slot.
> > + slotWeight += ISK->Core.setWeight(HEXAGON_PACKET_SIZE - nSlot
> - 1);
> > +
> > + if (slotWeight)
> > + // Sort the packet, favoring source order,
> > + // beginning after the previous slot.
> > + std::sort(ISJ, Packet.end());
> > + else
> > + // Skip unused slot.
> > + ++emptySlots;
> > + }
> > +
> > + for (iterator ISJ = begin(); ISJ != end(); ++ISJ)
> > + DEBUG(dbgs().write_hex(ISJ->Core.getUnits());
> > + dbgs() << ':'
> > + << HexagonMCInstrInfo::getDesc(MCII, *ISJ->getDesc())
> > + .getOpcode();
> > + dbgs() << '\n');
> > + DEBUG(dbgs() << '\n');
> > +
> > + return (!getError());
> > +}
> >
> > Added: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h
> > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/
> MCTargetDesc/HexagonShuffler.h?rev=238692&view=auto
> > ========================================================================
> ======
> > --- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h (added)
> > +++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h Sun May
> 31 16:57:09 2015
> > @@ -0,0 +1,139 @@
> > +//===----- HexagonShuffler.h - Instruction bundle shuffling
> ---------------===//
> > +//
> > +// The LLVM Compiler Infrastructure
> > +//
> > +// This file is distributed under the University of Illinois Open
> Source
> > +// License. See LICENSE.TXT for details.
> > +//
> > +//===
> ----------------------------------------------------------------------===/
> /
> > +//
> > +// This implements the shuffling of insns inside a bundle according to
> the
> > +// packet formation rules of the Hexagon ISA.
> > +//
> > +//===
> ----------------------------------------------------------------------===/
> /
> > +
> > +#ifndef HEXAGONSHUFFLER_H
> > +#define HEXAGONSHUFFLER_H
> > +
> > +#include "Hexagon.h"
> > +#include "MCTargetDesc/HexagonMCInstrInfo.h"
> > +
> > +#include "llvm/ADT/SmallVector.h"
> > +#include "llvm/MC/MCInstrInfo.h"
> > +
> > +using namespace llvm;
> > +
> > +namespace llvm {
> > +// Insn resources.
> > +class HexagonResource {
> > + // Mask of the slots or units that may execute the insn and
> > + // the weight or priority that the insn requires to be assigned a
> slot.
> > + unsigned Slots, Weight;
> > +
> > +public:
> > + HexagonResource(unsigned s) { setUnits(s); };
> > +
> > + void setUnits(unsigned s) {
> > + Slots = s & ~(-1 << HEXAGON_PACKET_SIZE);
> > + setWeight(s);
> > + };
> > + unsigned setWeight(unsigned s);
> > +
> > + 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());
> > + };
> > +};
> > +
> > +// Handle to an insn used by the shuffling algorithm.
> > +class HexagonInstr {
> > + friend class HexagonShuffler;
> > +
> > + MCInst const *ID;
> > + MCInst const *Extender;
> > + HexagonResource Core;
> > + bool SoloException;
> > +
> > +public:
> > + HexagonInstr(MCInst const *id, MCInst const *Extender, unsigned s,
> > + bool x = false)
> > + : ID(id), Extender(Extender), Core(s), SoloException(x){};
> > +
> > + MCInst const *getDesc() const { return (ID); };
> > +
> > + MCInst const *getExtender() const { return Extender; }
> > +
> > + unsigned isSoloException() const { return (SoloException); };
> > +
> > + // 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));
> > + };
> > +};
> > +
> > +// Bundle shuffler.
> > +class HexagonShuffler {
> > + typedef SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>
> > + HexagonPacket;
> > +
> > + // Insn handles in a bundle.
> > + HexagonPacket Packet;
> > +
> > + // Shuffling error code.
> > + unsigned Error;
> > +
> > +protected:
> > + int64_t BundleFlags;
> > + MCInstrInfo const &MCII;
> > + MCSubtargetInfo const &STI;
> > +
> > +public:
> > + typedef HexagonPacket::iterator iterator;
> > +
> > + enum {
> > + SHUFFLE_SUCCESS = 0, ///< Successful operation.
> > + SHUFFLE_ERROR_INVALID, ///< Invalid bundle.
> > + SHUFFLE_ERROR_STORES, ///< No free slots for store insns.
> > + SHUFFLE_ERROR_LOADS, ///< No free slots for load insns.
> > + SHUFFLE_ERROR_BRANCHES, ///< No free slots for branch insns.
> > + SHUFFLE_ERROR_NOSLOTS, ///< No free slots for other insns.
> > + SHUFFLE_ERROR_SLOTS, ///< Over-subscribed slots.
> > + SHUFFLE_ERROR_UNKNOWN ///< Unknown error.
> > + };
> > +
> > + explicit HexagonShuffler(MCInstrInfo const &MCII, MCSubtargetInfo
> const &STI);
> > +
> > + // Reset to initial state.
> > + void reset();
> > + // Check if the bundle may be validly shuffled.
> > + bool check();
> > + // Reorder the insn handles in the bundle.
> > + bool shuffle();
> > +
> > + unsigned size() const { return (Packet.size()); };
> > +
> > + 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,
> > + bool X = false);
> > +
> > + // Return the error code for the last check or shuffling of the
> bundle.
> > + void setError(unsigned Err) { Error = Err; };
> > + unsigned getError() const { return (Error); };
> > +};
> > +}
> > +
> > +#endif // HEXAGONSHUFFLER_H
> >
> >
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list