[llvm] r238692 - [Hexagon] Adding MC packet shuffler.

Colin LeMahieu colinl at codeaurora.org
Wed Jul 1 15:26:52 PDT 2015


Thanks for taking a look at this, the changes that were made look appropriate.

I looked at the setWeight method and it seems like it's incorrectly named, the function has no side effects and is actually returning the calculated weight.  The call to setWeight inside setUnits seems vestigious; perhaps at some time this did, in fact, set something.  I'll rename this function.  setUnits was passing a bitmask to setWeight though setWeight is expecting an integer which is why the shift numbers were completely incorrect.  Since the result was being discarded, this is also why removing the call to this function didn't change any test results

I did a quick check to make sure this area of code is being covered in lit tests.  I placed llvm_unreachable in the setUnits function and 2/3 of the hexagon CodeGen/MC tests failed so at a minimum we have positive test coverage of the area.

The checker is most heavily used when checking hand assembly since the integrated assembler is always given valid packets from the compiler.  We do, however, use the checker when applying duplexing which is a machine code size compression optimization that's also applied in the integrated assembler path.  This means that while all validity rules are being checked through the integrated assembler path, only a subset of them could fail in practice due to compiler guarantees.  

We're working on getting functionality for the assembler organized and upstreamed at which point we'd be able to submit the appropriate negative test cases on the checker that require an asm parser.

Let me know if there's anything else specific to do in this area besides address the TODO, I'll try to get ubsan running on a machine here to filter these issues before submission.

-----Original Message-----
From: Justin Bogner [mailto:justin at justinbogner.com] On Behalf Of Justin Bogner
Sent: Wednesday, June 24, 2015 2:13 AM
To: Chandler Carruth; Colin LeMahieu
Cc: llvm-commits at cs.uiuc.edu
Subject: Re: [llvm] r238692 - [Hexagon] Adding MC packet shuffler.

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