<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>