<p dir="ltr">Testcase?</p>
<div class="gmail_quote">On May 31, 2015 6:03 PM, "Colin LeMahieu" <<a href="mailto:colinl@codeaurora.org">colinl@codeaurora.org</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: colinl<br>
Date: Sun May 31 16:57:09 2015<br>
New Revision: 238692<br>
<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D238692-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=acFBsnXvZIN6nnihBxoZZQnhFWH1vMw1sPAw5CPvwVY&s=5g6PHWxR-93Mc0bHMW8Ch6aSDSvie64aqoqV5UuBUSk&e=" target="_blank">http://llvm.org/viewvc/llvm-project?rev=238692&view=rev</a><br>
Log:<br>
[Hexagon] Adding MC packet shuffler.<br>
<br>
Added:<br>
    llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp<br>
    llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h<br>
    llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp<br>
    llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h<br>
Modified:<br>
    llvm/trunk/lib/Target/Hexagon/Hexagon.h<br>
    llvm/trunk/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt<br>
    llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp<br>
    llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h<br>
    llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h<br>
<br>
Modified: llvm/trunk/lib/Target/Hexagon/Hexagon.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Target_Hexagon_Hexagon.h-3Frev-3D238692-26r1-3D238691-26r2-3D238692-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=acFBsnXvZIN6nnihBxoZZQnhFWH1vMw1sPAw5CPvwVY&s=eMehFZ0sR8HmyfHzl1F9LnkZt2IVUmQDl2tDrT8Z128&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/Hexagon.h?rev=238692&r1=238691&r2=238692&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/Hexagon/Hexagon.h (original)<br>
+++ llvm/trunk/lib/Target/Hexagon/Hexagon.h Sun May 31 16:57:09 2015<br>
@@ -79,5 +79,8 @@ namespace llvm {<br>
 // Minimum number of instructions in an end-loop packet.<br>
 #define HEXAGON_PACKET_INNER_SIZE 2<br>
 #define HEXAGON_PACKET_OUTER_SIZE 3<br>
+// Maximum number of instructions in a packet before shuffling,<br>
+// including a compound one or a duplex or an extender.<br>
+#define HEXAGON_PRESHUFFLE_PACKET_SIZE (HEXAGON_PACKET_SIZE + 3)<br>
<br>
 #endif<br>
<br>
Modified: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Target_Hexagon_MCTargetDesc_CMakeLists.txt-3Frev-3D238692-26r1-3D238691-26r2-3D238692-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=acFBsnXvZIN6nnihBxoZZQnhFWH1vMw1sPAw5CPvwVY&s=FDhiMuMTcJKekBYdNN9txIJGn488_ms4DeSFJ7Ko0uQ&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt?rev=238692&r1=238691&r2=238692&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt Sun May 31 16:57:09 2015<br>
@@ -5,7 +5,9 @@ add_llvm_library(LLVMHexagonDesc<br>
   HexagonMCAsmInfo.cpp<br>
   HexagonMCCodeEmitter.cpp<br>
   HexagonMCInstrInfo.cpp<br>
+  HexagonMCShuffler.cpp<br>
   HexagonMCTargetDesc.cpp<br>
+  HexagonShuffler.cpp<br>
   )<br>
<br>
 add_dependencies(LLVMHexagonDesc HexagonCommonTableGen)<br>
<br>
Modified: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Target_Hexagon_MCTargetDesc_HexagonMCInstrInfo.cpp-3Frev-3D238692-26r1-3D238691-26r2-3D238692-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=acFBsnXvZIN6nnihBxoZZQnhFWH1vMw1sPAw5CPvwVY&s=ymUdpVmMUD_shCzi4AJ1uo8gFCAyehZ69tUC1R7cwJE&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp?rev=238692&r1=238691&r2=238692&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp (original)<br>
+++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp Sun May 31 16:57:09 2015<br>
@@ -11,9 +11,12 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
<br>
+#include "HexagonMCInstrInfo.h"<br>
+<br>
 #include "Hexagon.h"<br>
 #include "HexagonBaseInfo.h"<br>
-#include "HexagonMCInstrInfo.h"<br>
+<br>
+#include "llvm/MC/MCSubtargetInfo.h"<br>
<br>
 namespace llvm {<br>
 iterator_range<MCInst::const_iterator><br>
@@ -140,6 +143,21 @@ MCOperand const &HexagonMCInstrInfo::get<br>
   return (MCO);<br>
 }<br>
<br>
+int HexagonMCInstrInfo::getSubTarget(MCInstrInfo const &MCII,<br>
+                                     MCInst const &MCI) {<br>
+  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;<br>
+<br>
+  HexagonII::SubTarget Target = static_cast<HexagonII::SubTarget>(<br>
+      (F >> HexagonII::validSubTargetPos) & HexagonII::validSubTargetMask);<br>
+<br>
+  switch (Target) {<br>
+  default:<br>
+    return Hexagon::ArchV4;<br>
+  case HexagonII::HasV5SubT:<br>
+    return Hexagon::ArchV5;<br>
+  }<br>
+}<br>
+<br>
 // Return the Hexagon ISA class for the insn.<br>
 unsigned HexagonMCInstrInfo::getType(MCInstrInfo const &MCII,<br>
                                      MCInst const &MCI) {<br>
@@ -148,6 +166,28 @@ unsigned HexagonMCInstrInfo::getType(MCI<br>
   return ((F >> HexagonII::TypePos) & HexagonII::TypeMask);<br>
 }<br>
<br>
+unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII,<br>
+                                      MCSubtargetInfo const &STI,<br>
+                                      MCInst const &MCI) {<br>
+<br>
+  const InstrItinerary *II = STI.getSchedModel().InstrItineraries;<br>
+  int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass();<br>
+  return ((II[SchedClass].FirstStage + HexagonStages)->getUnits());<br>
+}<br>
+<br>
+bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) {<br>
+  if (!HexagonMCInstrInfo::isBundle(MCI))<br>
+    return false;<br>
+<br>
+  for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCI)) {<br>
+    auto MI = I.getInst();<br>
+    if (isImmext(*MI))<br>
+      return true;<br>
+  }<br>
+<br>
+  return false;<br>
+}<br>
+<br>
 // Return whether the instruction is a legal new-value producer.<br>
 bool HexagonMCInstrInfo::hasNewValue(MCInstrInfo const &MCII,<br>
                                      MCInst const &MCI) {<br>
@@ -212,20 +252,23 @@ bool HexagonMCInstrInfo::isConstExtended<br>
   return (ImmValue < MinValue || ImmValue > MaxValue);<br>
 }<br>
<br>
-// Return true if the instruction may be extended based on the operand value.<br>
 bool HexagonMCInstrInfo::isExtendable(MCInstrInfo const &MCII,<br>
                                       MCInst const &MCI) {<br>
   uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;<br>
   return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask;<br>
 }<br>
<br>
-// Return whether the instruction must be always extended.<br>
 bool HexagonMCInstrInfo::isExtended(MCInstrInfo const &MCII,<br>
                                     MCInst const &MCI) {<br>
   uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;<br>
   return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;<br>
 }<br>
<br>
+bool HexagonMCInstrInfo::isFloat(MCInstrInfo const &MCII, MCInst const &MCI) {<br>
+  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;<br>
+  return ((F >> HexagonII::FPPos) & HexagonII::FPMask);<br>
+}<br>
+<br>
 bool HexagonMCInstrInfo::isImmext(MCInst const &MCI) {<br>
   auto Op = MCI.getOpcode();<br>
   return (Op == Hexagon::A4_ext_b || Op == Hexagon::A4_ext_c ||<br>
@@ -273,17 +316,26 @@ bool HexagonMCInstrInfo::isPredicatedTru<br>
       !((F >> HexagonII::PredicatedFalsePos) & HexagonII::PredicatedFalseMask));<br>
 }<br>
<br>
-// Return whether the insn is a prefix.<br>
 bool HexagonMCInstrInfo::isPrefix(MCInstrInfo const &MCII, MCInst const &MCI) {<br>
   return (HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypePREFIX);<br>
 }<br>
<br>
-// Return whether the insn is solo, i.e., cannot be in a packet.<br>
 bool HexagonMCInstrInfo::isSolo(MCInstrInfo const &MCII, MCInst const &MCI) {<br>
   const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;<br>
   return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask);<br>
 }<br>
<br>
+bool HexagonMCInstrInfo::isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI) {<br>
+  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;<br>
+  return ((F >> HexagonII::SoloAXPos) & HexagonII::SoloAXMask);<br>
+}<br>
+<br>
+bool HexagonMCInstrInfo::isSoloAin1(MCInstrInfo const &MCII,<br>
+                                    MCInst const &MCI) {<br>
+  const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags;<br>
+  return ((F >> HexagonII::SoloAin1Pos) & HexagonII::SoloAin1Mask);<br>
+}<br>
+<br>
 void HexagonMCInstrInfo::padEndloop(MCInst &MCB) {<br>
   MCInst Nop;<br>
   Nop.setOpcode(Hexagon::A2_nop);<br>
@@ -295,6 +347,26 @@ void HexagonMCInstrInfo::padEndloop(MCIn<br>
     MCB.addOperand(MCOperand::createInst(new MCInst(Nop)));<br>
 }<br>
<br>
+bool HexagonMCInstrInfo::prefersSlot3(MCInstrInfo const &MCII,<br>
+                                      MCInst const &MCI) {<br>
+  if (HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCR)<br>
+    return false;<br>
+<br>
+  unsigned SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass();<br>
+  switch (SchedClass) {<br>
+  case Hexagon::Sched::ALU32_3op_tc_2_SLOT0123:<br>
+  case Hexagon::Sched::ALU64_tc_2_SLOT23:<br>
+  case Hexagon::Sched::ALU64_tc_3x_SLOT23:<br>
+  case Hexagon::Sched::M_tc_2_SLOT23:<br>
+  case Hexagon::Sched::M_tc_3x_SLOT23:<br>
+  case Hexagon::Sched::S_2op_tc_2_SLOT23:<br>
+  case Hexagon::Sched::S_3op_tc_2_SLOT23:<br>
+  case Hexagon::Sched::S_3op_tc_3x_SLOT23:<br>
+    return true;<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
 void HexagonMCInstrInfo::setInnerLoop(MCInst &MCI) {<br>
   assert(isBundle(MCI));<br>
   MCOperand &Operand = MCI.getOperand(0);<br>
<br>
Modified: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Target_Hexagon_MCTargetDesc_HexagonMCInstrInfo.h-3Frev-3D238692-26r1-3D238691-26r2-3D238692-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=acFBsnXvZIN6nnihBxoZZQnhFWH1vMw1sPAw5CPvwVY&s=7uAlN8qdEJbEbngsvlN9kVEhV5ceHBxT3yrBwpsFVqo&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h?rev=238692&r1=238691&r2=238692&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h (original)<br>
+++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h Sun May 31 16:57:09 2015<br>
@@ -1,4 +1,4 @@<br>
-//===- HexagonMCInstrInfo.cpp - Hexagon sub-class of MCInst ---------------===//<br>
+//===- HexagonMCInstrInfo.cpp - Utility functions on Hexagon MCInsts ------===//<br>
 //<br>
 //                     The LLVM Compiler Infrastructure<br>
 //<br>
@@ -27,6 +27,12 @@ class MCOperand;<br>
 namespace HexagonII {<br>
 enum class MemAccessSize;<br>
 }<br>
+class DuplexCandidate {<br>
+public:<br>
+  unsigned packetIndexI, packetIndexJ, iClass;<br>
+  DuplexCandidate(unsigned i, unsigned j, unsigned iClass)<br>
+      : packetIndexI(i), packetIndexJ(j), iClass(iClass) {}<br>
+};<br>
 namespace HexagonMCInstrInfo {<br>
 size_t const innerLoopOffset = 0;<br>
 int64_t const innerLoopMask = 1 << innerLoopOffset;<br>
@@ -84,9 +90,17 @@ unsigned short getNewValueOp(MCInstrInfo<br>
 // Return the operand that consumes or produces a new value.<br>
 MCOperand const &getNewValueOperand(MCInstrInfo const &MCII, MCInst const &MCI);<br>
<br>
+int getSubTarget(MCInstrInfo const &MCII, MCInst const &MCI);<br>
+<br>
 // Return the Hexagon ISA class for the insn.<br>
 unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI);<br>
<br>
+/// Return the slots used by the insn.<br>
+unsigned getUnits(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,<br>
+                  MCInst const &MCI);<br>
+<br>
+bool hasImmExt(MCInst const &MCI);<br>
+<br>
 // Return whether the instruction is a legal new-value producer.<br>
 bool hasNewValue(MCInstrInfo const &MCII, MCInst const &MCI);<br>
<br>
@@ -108,6 +122,9 @@ bool isExtendable(MCInstrInfo const &MCI<br>
 // Return whether the instruction must be always extended.<br>
 bool isExtended(MCInstrInfo const &MCII, MCInst const &MCI);<br>
<br>
+/// Return whether it is a floating-point insn.<br>
+bool isFloat(MCInstrInfo const &MCII, MCInst const &MCI);<br>
+<br>
 // Returns whether this instruction is an immediate extender<br>
 bool isImmext(MCInst const &MCI);<br>
<br>
@@ -136,9 +153,17 @@ bool isPrefix(MCInstrInfo const &MCII, M<br>
 // Return whether the insn is solo, i.e., cannot be in a packet.<br>
 bool isSolo(MCInstrInfo const &MCII, MCInst const &MCI);<br>
<br>
+/// Return whether the insn can be packaged only with A and X-type insns.<br>
+bool isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI);<br>
+<br>
+/// Return whether the insn can be packaged only with an A-type insn in slot #1.<br>
+bool isSoloAin1(MCInstrInfo const &MCII, MCInst const &MCI);<br>
+<br>
 // Pad the bundle with nops to satisfy endloop requirements<br>
 void padEndloop(MCInst &MCI);<br>
<br>
+bool prefersSlot3(MCInstrInfo const &MCII, MCInst const &MCI);<br>
+<br>
 // Marks a bundle as endloop0<br>
 void setInnerLoop(MCInst &MCI);<br>
<br>
<br>
Added: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Target_Hexagon_MCTargetDesc_HexagonMCShuffler.cpp-3Frev-3D238692-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=acFBsnXvZIN6nnihBxoZZQnhFWH1vMw1sPAw5CPvwVY&s=YFjkZ1P7oGXtJwniGEb-zAzVvQdPvOcwkL98kHYk2vs&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp?rev=238692&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp (added)<br>
+++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp Sun May 31 16:57:09 2015<br>
@@ -0,0 +1,181 @@<br>
+//===----- HexagonMCShuffler.cpp - MC bundle shuffling --------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This implements the shuffling of insns inside a bundle according to the<br>
+// packet formation rules of the Hexagon ISA.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#define DEBUG_TYPE "hexagon-shuffle"<br>
+<br>
+#include "Hexagon.h"<br>
+#include "MCTargetDesc/HexagonMCInstrInfo.h"<br>
+#include "MCTargetDesc/HexagonMCShuffler.h"<br>
+#include "MCTargetDesc/HexagonMCTargetDesc.h"<br>
+#include "llvm/Support/CommandLine.h"<br>
+#include "llvm/Support/Debug.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+static cl::opt<bool><br>
+    DisableShuffle("disable-hexagon-shuffle", cl::Hidden, cl::init(false),<br>
+                   cl::desc("Disable Hexagon instruction shuffling"));<br>
+<br>
+void HexagonMCShuffler::init(MCInst &MCB) {<br>
+  if (HexagonMCInstrInfo::isBundle(MCB)) {<br>
+    MCInst const *Extender = nullptr;<br>
+    // Copy the bundle for the shuffling.<br>
+    for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {<br>
+      assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());<br>
+      MCInst *MI = const_cast<MCInst *>(I.getInst());<br>
+<br>
+      if (!HexagonMCInstrInfo::isImmext(*MI)) {<br>
+        append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, *MI),<br>
+               false);<br>
+        Extender = nullptr;<br>
+      } else<br>
+        Extender = MI;<br>
+    }<br>
+  }<br>
+<br>
+  BundleFlags = MCB.getOperand(0).getImm();<br>
+}<br>
+<br>
+void HexagonMCShuffler::init(MCInst &MCB, MCInst const *AddMI,<br>
+                             bool bInsertAtFront) {<br>
+  if (HexagonMCInstrInfo::isBundle(MCB)) {<br>
+    if (bInsertAtFront && AddMI)<br>
+      append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, *AddMI),<br>
+             false);<br>
+    MCInst const *Extender = nullptr;<br>
+    // Copy the bundle for the shuffling.<br>
+    for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {<br>
+      assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());<br>
+      MCInst *MI = const_cast<MCInst *>(I.getInst());<br>
+      if (!HexagonMCInstrInfo::isImmext(*MI)) {<br>
+        append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, *MI),<br>
+               false);<br>
+        Extender = nullptr;<br>
+      } else<br>
+        Extender = MI;<br>
+    }<br>
+    if (!bInsertAtFront && AddMI)<br>
+      append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, *AddMI),<br>
+             false);<br>
+  }<br>
+<br>
+  BundleFlags = MCB.getOperand(0).getImm();<br>
+}<br>
+<br>
+void HexagonMCShuffler::copyTo(MCInst &MCB) {<br>
+  MCB.clear();<br>
+  MCB.addOperand(MCOperand::createImm(BundleFlags));<br>
+  // Copy the results into the bundle.<br>
+  for (HexagonShuffler::iterator I = begin(); I != end(); ++I) {<br>
+<br>
+    MCInst const *MI = I->getDesc();<br>
+    MCInst const *Extender = I->getExtender();<br>
+    if (Extender)<br>
+      MCB.addOperand(MCOperand::createInst(Extender));<br>
+    MCB.addOperand(MCOperand::createInst(MI));<br>
+  }<br>
+}<br>
+<br>
+bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) {<br>
+  if (shuffle()) {<br>
+    // Copy the results into the bundle.<br>
+    copyTo(MCB);<br>
+  } else<br>
+    DEBUG(MCB.dump());<br>
+<br>
+  return (!getError());<br>
+}<br>
+<br>
+bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,<br>
+                            MCInst &MCB) {<br>
+  HexagonMCShuffler MCS(MCII, STI, MCB);<br>
+<br>
+  if (DisableShuffle)<br>
+    // Ignore if user chose so.<br>
+    return false;<br>
+<br>
+  if (!HexagonMCInstrInfo::bundleSize(MCB)) {<br>
+    // There once was a bundle:<br>
+    //    BUNDLE %D2<imp-def>, %R4<imp-def>, %R5<imp-def>, %D7<imp-def>, ...<br>
+    //      * %D2<def> = IMPLICIT_DEF; flags:<br>
+    //      * %D7<def> = IMPLICIT_DEF; flags:<br>
+    // After the IMPLICIT_DEFs were removed by the asm printer, the bundle<br>
+    // became empty.<br>
+    DEBUG(dbgs() << "Skipping empty bundle");<br>
+    return false;<br>
+  } else if (!HexagonMCInstrInfo::isBundle(MCB)) {<br>
+    DEBUG(dbgs() << "Skipping stand-alone insn");<br>
+    return false;<br>
+  }<br>
+<br>
+  // Reorder the bundle and copy the result.<br>
+  if (!MCS.reshuffleTo(MCB)) {<br>
+    // Unless there is any error, which should not happen at this point.<br>
+    unsigned shuffleError = MCS.getError();<br>
+    switch (shuffleError) {<br>
+    default:<br>
+      llvm_unreachable("unknown error");<br>
+    case HexagonShuffler::SHUFFLE_ERROR_INVALID:<br>
+      llvm_unreachable("invalid packet");<br>
+    case HexagonShuffler::SHUFFLE_ERROR_STORES:<br>
+      llvm_unreachable("too many stores");<br>
+    case HexagonShuffler::SHUFFLE_ERROR_LOADS:<br>
+      llvm_unreachable("too many loads");<br>
+    case HexagonShuffler::SHUFFLE_ERROR_BRANCHES:<br>
+      llvm_unreachable("too many branches");<br>
+    case HexagonShuffler::SHUFFLE_ERROR_NOSLOTS:<br>
+      llvm_unreachable("no suitable slot");<br>
+    case HexagonShuffler::SHUFFLE_ERROR_SLOTS:<br>
+      llvm_unreachable("over-subscribed slots");<br>
+    case HexagonShuffler::SHUFFLE_SUCCESS: // Single instruction case.<br>
+      return true;<br>
+    }<br>
+  }<br>
+<br>
+  return true;<br>
+}<br>
+<br>
+bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,<br>
+                            MCInst &MCB, MCInst const *AddMI, int fixupCount) {<br>
+  if (!HexagonMCInstrInfo::isBundle(MCB) || !AddMI)<br>
+    return false;<br>
+<br>
+  // if fixups present, make sure we don't insert too many nops that would<br>
+  // later prevent an extender from being inserted.<br>
+  unsigned int bundleSize = HexagonMCInstrInfo::bundleSize(MCB);<br>
+  if (bundleSize >= HEXAGON_PACKET_SIZE)<br>
+    return false;<br>
+  if (fixupCount >= 2) {<br>
+    return false;<br>
+  } else {<br>
+    if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount)<br>
+      return false;<br>
+  }<br>
+<br>
+  if (DisableShuffle)<br>
+    return false;<br>
+<br>
+  HexagonMCShuffler MCS(MCII, STI, MCB, AddMI);<br>
+  if (!MCS.reshuffleTo(MCB)) {<br>
+    unsigned shuffleError = MCS.getError();<br>
+    switch (shuffleError) {<br>
+    default:<br>
+      return false;<br>
+    case HexagonShuffler::SHUFFLE_SUCCESS: // single instruction case<br>
+      return true;<br>
+    }<br>
+  }<br>
+<br>
+  return true;<br>
+}<br>
<br>
Added: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Target_Hexagon_MCTargetDesc_HexagonMCShuffler.h-3Frev-3D238692-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=acFBsnXvZIN6nnihBxoZZQnhFWH1vMw1sPAw5CPvwVY&s=mbe7lMS9AZgs5zeZxDmMp8W42-BIXv3y9lR55etGKQU&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h?rev=238692&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h (added)<br>
+++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.h Sun May 31 16:57:09 2015<br>
@@ -0,0 +1,65 @@<br>
+//=-- HexagonMCShuffler.h ---------------------------------------------------=//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This declares the shuffling of insns inside a bundle according to the<br>
+// packet formation rules of the Hexagon ISA.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef HEXAGONMCSHUFFLER_H<br>
+#define HEXAGONMCSHUFFLER_H<br>
+<br>
+#include "MCTargetDesc/HexagonShuffler.h"<br>
+<br>
+namespace llvm {<br>
+<br>
+class MCInst;<br>
+<br>
+// Insn bundle shuffler.<br>
+class HexagonMCShuffler : public HexagonShuffler {<br>
+  bool immext_present;<br>
+  bool duplex_present;<br>
+<br>
+public:<br>
+  HexagonMCShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,<br>
+                    MCInst &MCB)<br>
+      : HexagonShuffler(MCII, STI) {<br>
+    init(MCB);<br>
+  };<br>
+  HexagonMCShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,<br>
+                    MCInst &MCB, const MCInst *AddMI,<br>
+                    bool bInsertAtFront = false)<br>
+      : HexagonShuffler(MCII, STI) {<br>
+    init(MCB, AddMI, bInsertAtFront);<br>
+  };<br>
+<br>
+  // Copy reordered bundle to another.<br>
+  void copyTo(MCInst &MCB);<br>
+  // Reorder and copy result to another.<br>
+  bool reshuffleTo(MCInst &MCB);<br>
+<br>
+  bool immextPresent() const { return immext_present; };<br>
+  bool duplexPresent() const { return duplex_present; };<br>
+<br>
+private:<br>
+  void init(MCInst &MCB);<br>
+  void init(MCInst &MCB, const MCInst *AddMI, bool bInsertAtFront = false);<br>
+};<br>
+<br>
+// Invocation of the shuffler.<br>
+bool HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,<br>
+                      MCInst &);<br>
+bool HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,<br>
+                      MCInst &, const MCInst *, int);<br>
+unsigned HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,<br>
+                          MCContext &Context, MCInst &,<br>
+                          SmallVector<DuplexCandidate, 8>);<br>
+}<br>
+<br>
+#endif // HEXAGONMCSHUFFLER_H<br>
<br>
Modified: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Target_Hexagon_MCTargetDesc_HexagonMCTargetDesc.h-3Frev-3D238692-26r1-3D238691-26r2-3D238692-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=acFBsnXvZIN6nnihBxoZZQnhFWH1vMw1sPAw5CPvwVY&s=gY8VRVHravO8BeenwqSUmWEI7drBt-X8tcjIAYES0bs&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h?rev=238692&r1=238691&r2=238692&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h (original)<br>
+++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h Sun May 31 16:57:09 2015<br>
@@ -17,6 +17,8 @@<br>
 #include <cstdint><br>
<br>
 namespace llvm {<br>
+class InstrItinerary;<br>
+class InstrStage;<br>
 class MCAsmBackend;<br>
 class MCCodeEmitter;<br>
 class MCContext;<br>
@@ -31,6 +33,8 @@ class raw_pwrite_stream;<br>
<br>
 extern Target TheHexagonTarget;<br>
<br>
+extern const InstrStage HexagonStages[];<br>
+<br>
 MCInstrInfo *createHexagonMCInstrInfo();<br>
<br>
 MCCodeEmitter *createHexagonMCCodeEmitter(MCInstrInfo const &MCII,<br>
<br>
Added: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Target_Hexagon_MCTargetDesc_HexagonShuffler.cpp-3Frev-3D238692-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=acFBsnXvZIN6nnihBxoZZQnhFWH1vMw1sPAw5CPvwVY&s=0-mQqBmedSX7pAB6RMXA3a398mauUd5Mb4S846dqflw&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp?rev=238692&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp (added)<br>
+++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp Sun May 31 16:57:09 2015<br>
@@ -0,0 +1,385 @@<br>
+//===----- HexagonShuffler.cpp - Instruction bundle shuffling -------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This implements the shuffling of insns inside a bundle according to the<br>
+// packet formation rules of the Hexagon ISA.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#define DEBUG_TYPE "hexagon-shuffle"<br>
+<br>
+#include <algorithm><br>
+#include <utility><br>
+#include "Hexagon.h"<br>
+#include "MCTargetDesc/HexagonBaseInfo.h"<br>
+#include "MCTargetDesc/HexagonMCTargetDesc.h"<br>
+#include "MCTargetDesc/HexagonMCInstrInfo.h"<br>
+#include "HexagonShuffler.h"<br>
+#include "llvm/Support/Debug.h"<br>
+#include "llvm/Support/MathExtras.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+// Insn shuffling priority.<br>
+class HexagonBid {<br>
+  // The priority is directly proportional to how restricted the insn is based<br>
+  // on its flexibility to run on the available slots.  So, the fewer slots it<br>
+  // may run on, the higher its priority.<br>
+  enum { MAX = 360360 }; // LCD of 1/2, 1/3, 1/4,... 1/15.<br>
+  unsigned Bid;<br>
+<br>
+public:<br>
+  HexagonBid() : Bid(0){};<br>
+  HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; };<br>
+<br>
+  // Check if the insn priority is overflowed.<br>
+  bool isSold() const { return (Bid >= MAX); };<br>
+<br>
+  HexagonBid &operator+=(const HexagonBid &B) {<br>
+    Bid += B.Bid;<br>
+    return *this;<br>
+  };<br>
+};<br>
+<br>
+// Slot shuffling allocation.<br>
+class HexagonUnitAuction {<br>
+  HexagonBid Scores[HEXAGON_PACKET_SIZE];<br>
+  // Mask indicating which slot is unavailable.<br>
+  unsigned isSold : HEXAGON_PACKET_SIZE;<br>
+<br>
+public:<br>
+  HexagonUnitAuction() : isSold(0){};<br>
+<br>
+  // Allocate slots.<br>
+  bool bid(unsigned B) {<br>
+    // Exclude already auctioned slots from the bid.<br>
+    unsigned b = B & ~isSold;<br>
+    if (b) {<br>
+      for (unsigned i = 0; i < HEXAGON_PACKET_SIZE; ++i)<br>
+        if (b & (1 << i)) {<br>
+          // Request candidate slots.<br>
+          Scores[i] += HexagonBid(b);<br>
+          isSold |= Scores[i].isSold() << i;<br>
+        }<br>
+      return true;<br>
+      ;<br>
+    } else<br>
+      // Error if the desired slots are already full.<br>
+      return false;<br>
+  };<br>
+};<br>
+<br>
+unsigned HexagonResource::setWeight(unsigned s) {<br>
+  const unsigned SlotWeight = 8;<br>
+  const unsigned MaskWeight = SlotWeight - 1;<br>
+  bool Key = (1 << s) & getUnits();<br>
+<br>
+  // Calculate relative weight of the insn for the given slot, weighing it the<br>
+  // heavier the more restrictive the insn is and the lowest the slots that the<br>
+  // insn may be executed in.<br>
+  Weight =<br>
+      (Key << (SlotWeight * s)) * ((MaskWeight - countPopulation(getUnits()))<br>
+                                   << countTrailingZeros(getUnits()));<br>
+  return (Weight);<br>
+}<br>
+<br>
+HexagonShuffler::HexagonShuffler(MCInstrInfo const &MCII,<br>
+                                 MCSubtargetInfo const &STI)<br>
+    : MCII(MCII), STI(STI) {<br>
+  reset();<br>
+}<br>
+<br>
+void HexagonShuffler::reset() {<br>
+  Packet.clear();<br>
+  BundleFlags = 0;<br>
+  Error = SHUFFLE_SUCCESS;<br>
+}<br>
+<br>
+void HexagonShuffler::append(MCInst const *ID, MCInst const *Extender,<br>
+                             unsigned S, bool X) {<br>
+  HexagonInstr PI(ID, Extender, S, X);<br>
+<br>
+  Packet.push_back(PI);<br>
+}<br>
+<br>
+/// Check that the packet is legal and enforce relative insn order.<br>
+bool HexagonShuffler::check() {<br>
+  // Descriptive slot masks.<br>
+  const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2,<br>
+                 slotThree = 0x8, slotFirstJump = 0x8, slotLastJump = 0x4,<br>
+                 slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;<br>
+  // Highest slots for branches and stores used to keep their original order.<br>
+  unsigned slotJump = slotFirstJump;<br>
+  unsigned slotLoadStore = slotFirstLoadStore;<br>
+  // Number of branches, solo branches, indirect branches.<br>
+  unsigned jumps = 0, jump1 = 0, jumpr = 0;<br>
+  // Number of memory operations, loads, solo loads, stores, solo stores, single<br>
+  // stores.<br>
+  unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0;<br>
+  // Number of duplex insns, solo insns.<br>
+  unsigned duplex = 0, solo = 0;<br>
+  // Number of insns restricting other insns in the packet to A and X types,<br>
+  // which is neither A or X types.<br>
+  unsigned onlyAX = 0, neitherAnorX = 0;<br>
+  // Number of insns restricting other insns in slot #1 to A type.<br>
+  unsigned onlyAin1 = 0;<br>
+  // Number of insns restricting any insn in slot #1, except A2_nop.<br>
+  unsigned onlyNo1 = 0;<br>
+  unsigned xtypeFloat = 0;<br>
+  unsigned pSlot3Cnt = 0;<br>
+  iterator slot3ISJ = end();<br>
+<br>
+  // Collect information from the insns in the packet.<br>
+  for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {<br>
+    MCInst const *ID = ISJ->getDesc();<br>
+<br>
+    if (HexagonMCInstrInfo::isSolo(MCII, *ID))<br>
+      solo += !ISJ->isSoloException();<br>
+    else if (HexagonMCInstrInfo::isSoloAX(MCII, *ID))<br>
+      onlyAX += !ISJ->isSoloException();<br>
+    else if (HexagonMCInstrInfo::isSoloAin1(MCII, *ID))<br>
+      onlyAin1 += !ISJ->isSoloException();<br>
+    if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32 &&<br>
+        HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeXTYPE)<br>
+      ++neitherAnorX;<br>
+    if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID)) {<br>
+      ++pSlot3Cnt;<br>
+      slot3ISJ = ISJ;<br>
+    }<br>
+<br>
+    switch (HexagonMCInstrInfo::getType(MCII, *ID)) {<br>
+    case HexagonII::TypeXTYPE:<br>
+      if (HexagonMCInstrInfo::isFloat(MCII, *ID))<br>
+        ++xtypeFloat;<br>
+      break;<br>
+    case HexagonII::TypeJR:<br>
+      ++jumpr;<br>
+    // Fall-through.<br>
+    case HexagonII::TypeJ:<br>
+      ++jumps;<br>
+      break;<br>
+    case HexagonII::TypeLD:<br>
+      ++loads;<br>
+      ++memory;<br>
+      if (ISJ->Core.getUnits() == slotSingleLoad)<br>
+        ++load0;<br>
+      if (HexagonMCInstrInfo::getDesc(MCII, *ID).isReturn())<br>
+        ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.<br>
+      break;<br>
+    case HexagonII::TypeST:<br>
+      ++stores;<br>
+      ++memory;<br>
+      if (ISJ->Core.getUnits() == slotSingleStore)<br>
+        ++store0;<br>
+      break;<br>
+    case HexagonII::TypeMEMOP:<br>
+      ++loads;<br>
+      ++stores;<br>
+      ++store1;<br>
+      ++memory;<br>
+      break;<br>
+    case HexagonII::TypeNV:<br>
+      ++memory; // NV insns are memory-like.<br>
+      if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch())<br>
+        ++jumps, ++jump1;<br>
+      break;<br>
+    case HexagonII::TypeCR:<br>
+    // Legacy conditional branch predicated on a register.<br>
+    case HexagonII::TypeSYSTEM:<br>
+      if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad())<br>
+        ++loads;<br>
+      break;<br>
+    }<br>
+  }<br>
+<br>
+  // Check if the packet is legal.<br>
+  if ((load0 > 1 || store0 > 1) || (duplex > 1 || (duplex && memory)) ||<br>
+      (solo && size() > 1) || (onlyAX && neitherAnorX > 1) ||<br>
+      (onlyAX && xtypeFloat)) {<br>
+    Error = SHUFFLE_ERROR_INVALID;<br>
+    return false;<br>
+  }<br>
+<br>
+  if (jump1 && jumps > 1) {<br>
+    // Error if single branch with another branch.<br>
+    Error = SHUFFLE_ERROR_BRANCHES;<br>
+    return false;<br>
+  }<br>
+<br>
+  // Modify packet accordingly.<br>
+  // TODO: need to reserve slots #0 and #1 for duplex insns.<br>
+  bool bOnlySlot3 = false;<br>
+  for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {<br>
+    MCInst const *ID = ISJ->getDesc();<br>
+<br>
+    if (!ISJ->Core.getUnits()) {<br>
+      // Error if insn may not be executed in any slot.<br>
+      Error = SHUFFLE_ERROR_UNKNOWN;<br>
+      return false;<br>
+    }<br>
+<br>
+    // Exclude from slot #1 any insn but A2_nop.<br>
+    if (HexagonMCInstrInfo::getDesc(MCII, *ID).getOpcode() != Hexagon::A2_nop)<br>
+      if (onlyNo1)<br>
+        ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);<br>
+<br>
+    // Exclude from slot #1 any insn but A-type.<br>
+    if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32)<br>
+      if (onlyAin1)<br>
+        ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);<br>
+<br>
+    // Branches must keep the original order.<br>
+    if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch() ||<br>
+        HexagonMCInstrInfo::getDesc(MCII, *ID).isCall())<br>
+      if (jumps > 1) {<br>
+        if (jumpr || slotJump < slotLastJump) {<br>
+          // Error if indirect branch with another branch or<br>
+          // no more slots available for branches.<br>
+          Error = SHUFFLE_ERROR_BRANCHES;<br>
+          return false;<br>
+        }<br>
+        // Pin the branch to the highest slot available to it.<br>
+        ISJ->Core.setUnits(ISJ->Core.getUnits() & slotJump);<br>
+        // Update next highest slot available to branches.<br>
+        slotJump >>= 1;<br>
+      }<br>
+<br>
+    // A single load must use slot #0.<br>
+    if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad()) {<br>
+      if (loads == 1 && loads == memory)<br>
+        // Pin the load to slot #0.<br>
+        ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);<br>
+    }<br>
+<br>
+    // A single store must use slot #0.<br>
+    if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayStore()) {<br>
+      if (!store0) {<br>
+        if (stores == 1)<br>
+          ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);<br>
+        else if (stores > 1) {<br>
+          if (slotLoadStore < slotLastLoadStore) {<br>
+            // Error if no more slots available for stores.<br>
+            Error = SHUFFLE_ERROR_STORES;<br>
+            return false;<br>
+          }<br>
+          // Pin the store to the highest slot available to it.<br>
+          ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);<br>
+          // Update the next highest slot available to stores.<br>
+          slotLoadStore >>= 1;<br>
+        }<br>
+      }<br>
+      if (store1 && stores > 1) {<br>
+        // Error if a single store with another store.<br>
+        Error = SHUFFLE_ERROR_STORES;<br>
+        return false;<br>
+      }<br>
+    }<br>
+<br>
+    // flag if an instruction can only be executed in slot 3<br>
+    if (ISJ->Core.getUnits() == slotThree)<br>
+      bOnlySlot3 = true;<br>
+<br>
+    if (!ISJ->Core.getUnits()) {<br>
+      // Error if insn may not be executed in any slot.<br>
+      Error = SHUFFLE_ERROR_NOSLOTS;<br>
+      return false;<br>
+    }<br>
+  }<br>
+<br>
+  bool validateSlots = true;<br>
+  if (bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) {<br>
+    // save off slot mask of instruction marked with A_PREFER_SLOT3<br>
+    // and then pin it to slot #3<br>
+    unsigned saveUnits = slot3ISJ->Core.getUnits();<br>
+    slot3ISJ->Core.setUnits(saveUnits & slotThree);<br>
+<br>
+    HexagonUnitAuction AuctionCore;<br>
+    std::sort(begin(), end(), HexagonInstr::lessCore);<br>
+<br>
+    // see if things ok with that instruction being pinned to slot #3<br>
+    bool bFail = false;<br>
+    for (iterator I = begin(); I != end() && bFail != true; ++I)<br>
+      if (!AuctionCore.bid(I->Core.getUnits()))<br>
+        bFail = true;<br>
+<br>
+    // if yes, great, if not then restore original slot mask<br>
+    if (!bFail)<br>
+      validateSlots = false; // all good, no need to re-do auction<br>
+    else<br>
+      for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {<br>
+        MCInst const *ID = ISJ->getDesc();<br>
+        if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID))<br>
+          ISJ->Core.setUnits(saveUnits);<br>
+      }<br>
+  }<br>
+<br>
+  // Check if any slot, core, is over-subscribed.<br>
+  // Verify the core slot subscriptions.<br>
+  if (validateSlots) {<br>
+    HexagonUnitAuction AuctionCore;<br>
+<br>
+    std::sort(begin(), end(), HexagonInstr::lessCore);<br>
+<br>
+    for (iterator I = begin(); I != end(); ++I)<br>
+      if (!AuctionCore.bid(I->Core.getUnits())) {<br>
+        Error = SHUFFLE_ERROR_SLOTS;<br>
+        return false;<br>
+      }<br>
+  }<br>
+<br>
+  Error = SHUFFLE_SUCCESS;<br>
+  return true;<br>
+}<br>
+<br>
+bool HexagonShuffler::shuffle() {<br>
+  if (size() > HEXAGON_PACKET_SIZE) {<br>
+    // Ignore a packet with with more than what a packet can hold<br>
+    // or with compound or duplex insns for now.<br>
+    Error = SHUFFLE_ERROR_INVALID;<br>
+    return false;<br>
+  }<br>
+<br>
+  // Check and prepare packet.<br>
+  if (size() > 1 && check())<br>
+    // Reorder the handles for each slot.<br>
+    for (unsigned nSlot = 0, emptySlots = 0; nSlot < HEXAGON_PACKET_SIZE;<br>
+         ++nSlot) {<br>
+      iterator ISJ, ISK;<br>
+      unsigned slotSkip, slotWeight;<br>
+<br>
+      // Prioritize the handles considering their restrictions.<br>
+      for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0;<br>
+           ISK != Packet.end(); ++ISK, ++slotSkip)<br>
+        if (slotSkip < nSlot - emptySlots)<br>
+          // Note which handle to begin at.<br>
+          ++ISJ;<br>
+        else<br>
+          // Calculate the weight of the slot.<br>
+          slotWeight += ISK->Core.setWeight(HEXAGON_PACKET_SIZE - nSlot - 1);<br>
+<br>
+      if (slotWeight)<br>
+        // Sort the packet, favoring source order,<br>
+        // beginning after the previous slot.<br>
+        std::sort(ISJ, Packet.end());<br>
+      else<br>
+        // Skip unused slot.<br>
+        ++emptySlots;<br>
+    }<br>
+<br>
+  for (iterator ISJ = begin(); ISJ != end(); ++ISJ)<br>
+    DEBUG(dbgs().write_hex(ISJ->Core.getUnits());<br>
+          dbgs() << ':'<br>
+                 << HexagonMCInstrInfo::getDesc(MCII, *ISJ->getDesc())<br>
+                        .getOpcode();<br>
+          dbgs() << '\n');<br>
+  DEBUG(dbgs() << '\n');<br>
+<br>
+  return (!getError());<br>
+}<br>
<br>
Added: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Target_Hexagon_MCTargetDesc_HexagonShuffler.h-3Frev-3D238692-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=acFBsnXvZIN6nnihBxoZZQnhFWH1vMw1sPAw5CPvwVY&s=QyrM5UEaXhkmxy_a8OAJ3TByp4xNYqT3Pzw5ZKJDVbs&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h?rev=238692&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h (added)<br>
+++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h Sun May 31 16:57:09 2015<br>
@@ -0,0 +1,139 @@<br>
+//===----- HexagonShuffler.h - Instruction bundle shuffling ---------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+//<br>
+// This implements the shuffling of insns inside a bundle according to the<br>
+// packet formation rules of the Hexagon ISA.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef HEXAGONSHUFFLER_H<br>
+#define HEXAGONSHUFFLER_H<br>
+<br>
+#include "Hexagon.h"<br>
+#include "MCTargetDesc/HexagonMCInstrInfo.h"<br>
+<br>
+#include "llvm/ADT/SmallVector.h"<br>
+#include "llvm/MC/MCInstrInfo.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+namespace llvm {<br>
+// Insn resources.<br>
+class HexagonResource {<br>
+  // Mask of the slots or units that may execute the insn and<br>
+  // the weight or priority that the insn requires to be assigned a slot.<br>
+  unsigned Slots, Weight;<br>
+<br>
+public:<br>
+  HexagonResource(unsigned s) { setUnits(s); };<br>
+<br>
+  void setUnits(unsigned s) {<br>
+    Slots = s & ~(-1 << HEXAGON_PACKET_SIZE);<br>
+    setWeight(s);<br>
+  };<br>
+  unsigned setWeight(unsigned s);<br>
+<br>
+  unsigned getUnits() const { return (Slots); };<br>
+  unsigned getWeight() const { return (Weight); };<br>
+<br>
+  // Check if the resources are in ascending slot order.<br>
+  static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {<br>
+    return (countPopulation(A.getUnits()) < countPopulation(B.getUnits()));<br>
+  };<br>
+  // Check if the resources are in ascending weight order.<br>
+  static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {<br>
+    return (A.getWeight() < B.getWeight());<br>
+  };<br>
+};<br>
+<br>
+// Handle to an insn used by the shuffling algorithm.<br>
+class HexagonInstr {<br>
+  friend class HexagonShuffler;<br>
+<br>
+  MCInst const *ID;<br>
+  MCInst const *Extender;<br>
+  HexagonResource Core;<br>
+  bool SoloException;<br>
+<br>
+public:<br>
+  HexagonInstr(MCInst const *id, MCInst const *Extender, unsigned s,<br>
+               bool x = false)<br>
+      : ID(id), Extender(Extender), Core(s), SoloException(x){};<br>
+<br>
+  MCInst const *getDesc() const { return (ID); };<br>
+<br>
+  MCInst const *getExtender() const { return Extender; }<br>
+<br>
+  unsigned isSoloException() const { return (SoloException); };<br>
+<br>
+  // Check if the handles are in ascending order for shuffling purposes.<br>
+  bool operator<(const HexagonInstr &B) const {<br>
+    return (HexagonResource::lessWeight(B.Core, Core));<br>
+  };<br>
+  // Check if the handles are in ascending order by core slots.<br>
+  static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) {<br>
+    return (HexagonResource::lessUnits(A.Core, B.Core));<br>
+  };<br>
+};<br>
+<br>
+// Bundle shuffler.<br>
+class HexagonShuffler {<br>
+  typedef SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE><br>
+      HexagonPacket;<br>
+<br>
+  // Insn handles in a bundle.<br>
+  HexagonPacket Packet;<br>
+<br>
+  // Shuffling error code.<br>
+  unsigned Error;<br>
+<br>
+protected:<br>
+  int64_t BundleFlags;<br>
+  MCInstrInfo const &MCII;<br>
+  MCSubtargetInfo const &STI;<br>
+<br>
+public:<br>
+  typedef HexagonPacket::iterator iterator;<br>
+<br>
+  enum {<br>
+    SHUFFLE_SUCCESS = 0,    ///< Successful operation.<br>
+    SHUFFLE_ERROR_INVALID,  ///< Invalid bundle.<br>
+    SHUFFLE_ERROR_STORES,   ///< No free slots for store insns.<br>
+    SHUFFLE_ERROR_LOADS,    ///< No free slots for load insns.<br>
+    SHUFFLE_ERROR_BRANCHES, ///< No free slots for branch insns.<br>
+    SHUFFLE_ERROR_NOSLOTS,  ///< No free slots for other insns.<br>
+    SHUFFLE_ERROR_SLOTS,    ///< Over-subscribed slots.<br>
+    SHUFFLE_ERROR_UNKNOWN   ///< Unknown error.<br>
+  };<br>
+<br>
+  explicit HexagonShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI);<br>
+<br>
+  // Reset to initial state.<br>
+  void reset();<br>
+  // Check if the bundle may be validly shuffled.<br>
+  bool check();<br>
+  // Reorder the insn handles in the bundle.<br>
+  bool shuffle();<br>
+<br>
+  unsigned size() const { return (Packet.size()); };<br>
+<br>
+  iterator begin() { return (Packet.begin()); };<br>
+  iterator end() { return (Packet.end()); };<br>
+<br>
+  // Add insn handle to the bundle .<br>
+  void append(MCInst const *ID, MCInst const *Extender, unsigned S,<br>
+              bool X = false);<br>
+<br>
+  // Return the error code for the last check or shuffling of the bundle.<br>
+  void setError(unsigned Err) { Error = Err; };<br>
+  unsigned getError() const { return (Error); };<br>
+};<br>
+}<br>
+<br>
+#endif // HEXAGONSHUFFLER_H<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>