[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