summaryrefslogtreecommitdiff
path: root/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp')
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp275
1 files changed, 167 insertions, 108 deletions
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
index 1604e7c8dc54..7709a0f61624 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
@@ -1,4 +1,4 @@
-//===----- HexagonShuffler.cpp - Instruction bundle shuffling -------------===//
+//===- HexagonShuffler.cpp - Instruction bundle shuffling -----------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,32 +14,40 @@
#define DEBUG_TYPE "hexagon-shuffle"
-#include "HexagonShuffler.h"
+#include "MCTargetDesc/HexagonShuffler.h"
#include "Hexagon.h"
#include "MCTargetDesc/HexagonBaseInfo.h"
#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
#include <utility>
+#include <vector>
using namespace llvm;
namespace {
+
// Insn shuffling priority.
class HexagonBid {
// The priority is directly proportional to how restricted the insn is based
// on its flexibility to run on the available slots. So, the fewer slots it
// may run on, the higher its priority.
enum { MAX = 360360 }; // LCD of 1/2, 1/3, 1/4,... 1/15.
- unsigned Bid;
+ unsigned Bid = 0;
public:
- HexagonBid() : Bid(0) {}
+ HexagonBid() = default;
HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; }
// Check if the insn priority is overflowed.
@@ -58,7 +66,7 @@ class HexagonUnitAuction {
unsigned isSold : HEXAGON_PACKET_SIZE;
public:
- HexagonUnitAuction(unsigned cs = 0) : isSold(cs){};
+ HexagonUnitAuction(unsigned cs = 0) : isSold(cs) {}
// Allocate slots.
bool bid(unsigned B) {
@@ -77,6 +85,7 @@ public:
return false;
}
};
+
} // end anonymous namespace
unsigned HexagonResource::setWeight(unsigned s) {
@@ -107,6 +116,7 @@ void HexagonCVIResource::SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU) {
(*TUL)[HexagonII::TypeCVI_VP] = UnitsAndLanes(CVI_XLANE, 1);
(*TUL)[HexagonII::TypeCVI_VP_VS] = UnitsAndLanes(CVI_XLANE, 2);
(*TUL)[HexagonII::TypeCVI_VS] = UnitsAndLanes(CVI_SHIFT, 1);
+ (*TUL)[HexagonII::TypeCVI_VS_VX] = UnitsAndLanes(CVI_XLANE | CVI_SHIFT, 1);
(*TUL)[HexagonII::TypeCVI_VINLANESAT] =
(CPU == "hexagonv60")
? UnitsAndLanes(CVI_SHIFT, 1)
@@ -120,12 +130,20 @@ void HexagonCVIResource::SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU) {
(*TUL)[HexagonII::TypeCVI_VM_NEW_ST] = UnitsAndLanes(CVI_NONE, 0);
(*TUL)[HexagonII::TypeCVI_VM_STU] = UnitsAndLanes(CVI_XLANE, 1);
(*TUL)[HexagonII::TypeCVI_HIST] = UnitsAndLanes(CVI_XLANE, 4);
+ (*TUL)[HexagonII::TypeCVI_GATHER] =
+ UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
+ (*TUL)[HexagonII::TypeCVI_SCATTER] =
+ UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
+ (*TUL)[HexagonII::TypeCVI_SCATTER_DV] =
+ UnitsAndLanes(CVI_XLANE | CVI_MPY0, 2);
+ (*TUL)[HexagonII::TypeCVI_SCATTER_NEW_ST] =
+ UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
}
HexagonCVIResource::HexagonCVIResource(TypeUnitsAndLanes *TUL,
MCInstrInfo const &MCII, unsigned s,
MCInst const *id)
- : HexagonResource(s), TUL(TUL) {
+ : HexagonResource(s) {
unsigned T = HexagonMCInstrInfo::getType(MCII, *id);
if (TUL->count(T)) {
@@ -149,10 +167,9 @@ struct CVIUnits {
unsigned Units;
unsigned Lanes;
};
-typedef SmallVector<struct CVIUnits, 8> HVXInstsT;
+using HVXInstsT = SmallVector<struct CVIUnits, 8>;
static unsigned makeAllBits(unsigned startBit, unsigned Lanes)
-
{
for (unsigned i = 1; i < Lanes; ++i)
startBit = (startBit << 1) | startBit;
@@ -160,9 +177,7 @@ static unsigned makeAllBits(unsigned startBit, unsigned Lanes)
}
static bool checkHVXPipes(const HVXInstsT &hvxInsts, unsigned startIdx,
- unsigned usedUnits)
-
-{
+ unsigned usedUnits) {
if (startIdx < hvxInsts.size()) {
if (!hvxInsts[startIdx].Units)
return checkHVXPipes(hvxInsts, startIdx + 1, usedUnits);
@@ -206,30 +221,89 @@ static struct {
} jumpSlots[] = {{8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1}};
#define MAX_JUMP_SLOTS (sizeof(jumpSlots) / sizeof(jumpSlots[0]))
+void HexagonShuffler::restrictSlot1AOK() {
+ bool HasRestrictSlot1AOK = false;
+ SMLoc RestrictLoc;
+ for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
+ MCInst const &Inst = ISJ->getDesc();
+ if (HexagonMCInstrInfo::isRestrictSlot1AOK(MCII, Inst)) {
+ HasRestrictSlot1AOK = true;
+ RestrictLoc = Inst.getLoc();
+ }
+ }
+ if (HasRestrictSlot1AOK)
+ for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
+ MCInst const &Inst = ISJ->getDesc();
+ unsigned Type = HexagonMCInstrInfo::getType(MCII, Inst);
+ if (Type != HexagonII::TypeALU32_2op &&
+ Type != HexagonII::TypeALU32_3op &&
+ Type != HexagonII::TypeALU32_ADDI) {
+ unsigned Units = ISJ->Core.getUnits();
+ if (Units & 2U) {
+ AppliedRestrictions.push_back(std::make_pair(
+ Inst.getLoc(),
+ "Instruction was restricted from being in slot 1"));
+ AppliedRestrictions.push_back(
+ std::make_pair(RestrictLoc, "Instruction can only be combine "
+ "with an ALU instruction in slot 1"));
+ ISJ->Core.setUnits(Units & ~2U);
+ }
+ }
+ }
+}
+
+void HexagonShuffler::restrictNoSlot1Store() {
+ bool HasRestrictNoSlot1Store = false;
+ SMLoc RestrictLoc;
+ for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
+ MCInst const &Inst = ISJ->getDesc();
+ if (HexagonMCInstrInfo::isRestrictNoSlot1Store(MCII, Inst)) {
+ HasRestrictNoSlot1Store = true;
+ RestrictLoc = Inst.getLoc();
+ }
+ }
+ if (HasRestrictNoSlot1Store) {
+ bool AppliedRestriction = false;
+ for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
+ MCInst const &Inst = ISJ->getDesc();
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst).mayStore()) {
+ unsigned Units = ISJ->Core.getUnits();
+ if (Units & 2U) {
+ AppliedRestriction = true;
+ AppliedRestrictions.push_back(std::make_pair(
+ Inst.getLoc(),
+ "Instruction was restricted from being in slot 1"));
+ ISJ->Core.setUnits(Units & ~2U);
+ }
+ }
+ }
+ if (AppliedRestriction)
+ AppliedRestrictions.push_back(std::make_pair(
+ RestrictLoc, "Instruction does not allow a store in slot 1"));
+ }
+}
+
+void HexagonShuffler::applySlotRestrictions() {
+ restrictSlot1AOK();
+ restrictNoSlot1Store();
+}
+
/// Check that the packet is legal and enforce relative insn order.
bool HexagonShuffler::check() {
// Descriptive slot masks.
- const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2,
+ const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1,
slotThree = 0x8, // slotFirstJump = 0x8,
slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
// Highest slots for branches and stores used to keep their original order.
// unsigned slotJump = slotFirstJump;
unsigned slotLoadStore = slotFirstLoadStore;
- // Number of branches, solo branches, indirect branches.
- unsigned jumps = 0, jump1 = 0;
// Number of memory operations, loads, solo loads, stores, solo stores, single
// stores.
unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0;
// Number of duplex insns
unsigned duplex = 0;
- // Number of insns restricting other insns in slot #1 to A type.
- unsigned onlyAin1 = 0;
- // Number of insns restricting any insn in slot #1, except A2_nop.
- unsigned onlyNo1 = 0;
unsigned pSlot3Cnt = 0;
- unsigned nvstores = 0;
unsigned memops = 0;
- unsigned deallocs = 0;
iterator slot3ISJ = end();
std::vector<iterator> foundBranches;
unsigned reservedSlots = 0;
@@ -238,15 +312,11 @@ bool HexagonShuffler::check() {
for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
MCInst const &ID = ISJ->getDesc();
- if (HexagonMCInstrInfo::isSoloAin1(MCII, ID))
- ++onlyAin1;
if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) {
++pSlot3Cnt;
slot3ISJ = ISJ;
}
reservedSlots |= HexagonMCInstrInfo::getOtherReservedSlots(MCII, STI, ID);
- if (HexagonMCInstrInfo::isCofMax1(MCII, ID))
- ++jump1;
switch (HexagonMCInstrInfo::getType(MCII, ID)) {
case HexagonII::TypeS_2op:
@@ -254,30 +324,30 @@ bool HexagonShuffler::check() {
case HexagonII::TypeALU64:
break;
case HexagonII::TypeJ:
- ++jumps;
foundBranches.push_back(ISJ);
break;
case HexagonII::TypeCVI_VM_VP_LDU:
- ++onlyNo1;
- LLVM_FALLTHROUGH;
case HexagonII::TypeCVI_VM_LD:
case HexagonII::TypeCVI_VM_TMP_LD:
+ case HexagonII::TypeCVI_GATHER:
+ case HexagonII::TypeCVI_GATHER_RST:
case HexagonII::TypeLD:
++loads;
++memory;
if (ISJ->Core.getUnits() == slotSingleLoad ||
HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_VP_LDU)
++load0;
- if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn()) {
- ++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
+ if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn())
foundBranches.push_back(ISJ);
- }
break;
case HexagonII::TypeCVI_VM_STU:
- ++onlyNo1;
- LLVM_FALLTHROUGH;
case HexagonII::TypeCVI_VM_ST:
case HexagonII::TypeCVI_VM_NEW_ST:
+ case HexagonII::TypeCVI_SCATTER:
+ case HexagonII::TypeCVI_SCATTER_DV:
+ case HexagonII::TypeCVI_SCATTER_RST:
+ case HexagonII::TypeCVI_SCATTER_NEW_RST:
+ case HexagonII::TypeCVI_SCATTER_NEW_ST:
case HexagonII::TypeST:
++stores;
++memory;
@@ -294,7 +364,6 @@ bool HexagonShuffler::check() {
break;
case HexagonII::TypeNCJ:
++memory; // NV insns are memory-like.
- ++jumps, ++jump1;
foundBranches.push_back(ISJ);
break;
case HexagonII::TypeV2LDST:
@@ -309,68 +378,38 @@ bool HexagonShuffler::check() {
assert(HexagonMCInstrInfo::getDesc(MCII, ID).mayStore());
++memory;
++stores;
- if (HexagonMCInstrInfo::isNewValue(MCII, ID))
- ++nvstores;
}
break;
case HexagonII::TypeCR:
// Legacy conditional branch predicated on a register.
case HexagonII::TypeCJ:
- if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch()) {
- ++jumps;
+ if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch())
foundBranches.push_back(ISJ);
- }
break;
case HexagonII::TypeDUPLEX: {
++duplex;
MCInst const &Inst0 = *ID.getOperand(0).getInst();
MCInst const &Inst1 = *ID.getOperand(1).getInst();
- if (HexagonMCInstrInfo::isCofMax1(MCII, Inst0))
- ++jump1;
- if (HexagonMCInstrInfo::isCofMax1(MCII, Inst1))
- ++jump1;
- if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isBranch()) {
- ++jumps;
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isBranch())
foundBranches.push_back(ISJ);
- }
- if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isBranch()) {
- ++jumps;
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isBranch())
foundBranches.push_back(ISJ);
- }
- if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isReturn()) {
- ++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isReturn())
foundBranches.push_back(ISJ);
- }
- if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isReturn()) {
- ++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
+ if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isReturn())
foundBranches.push_back(ISJ);
- }
break;
}
}
}
+ applySlotRestrictions();
// Check if the packet is legal.
- if ((load0 > 1 || store0 > 1) ||
- (duplex > 1 || (duplex && memory))) {
+ if ((load0 > 1 || store0 > 1) || (duplex > 1 || (duplex && memory))) {
reportError(llvm::Twine("invalid instruction packet"));
return false;
}
- if (jump1 && jumps > 1) {
- // Error if single branch with another branch.
- reportError(llvm::Twine("too many branches in packet"));
- return false;
- }
- if ((nvstores || memops) && stores > 1) {
- reportError(llvm::Twine("slot 0 instruction does not allow slot 1 store"));
- return false;
- }
- if (deallocs && stores) {
- reportError(llvm::Twine("slot 0 instruction does not allow slot 1 store"));
- return false;
- }
-
// Modify packet accordingly.
// TODO: need to reserve slots #0 and #1 for duplex insns.
bool bOnlySlot3 = false;
@@ -382,35 +421,49 @@ bool HexagonShuffler::check() {
return false;
}
- // Exclude from slot #1 any insn but A2_nop.
- if (HexagonMCInstrInfo::getDesc(MCII, ID).getOpcode() != Hexagon::A2_nop)
- if (onlyNo1)
- ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
-
- // Exclude from slot #1 any insn but A-type.
- if (HexagonMCInstrInfo::getType(MCII, ID) != HexagonII::TypeALU32_2op &&
- HexagonMCInstrInfo::getType(MCII, ID) != HexagonII::TypeALU32_3op &&
- HexagonMCInstrInfo::getType(MCII, ID) != HexagonII::TypeALU32_ADDI)
- if (onlyAin1)
- ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
-
// A single load must use slot #0.
if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) {
if (loads == 1 && loads == memory && memops == 0)
// Pin the load to slot #0.
- ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
+ switch (ID.getOpcode()) {
+ case Hexagon::V6_vgathermw:
+ case Hexagon::V6_vgathermh:
+ case Hexagon::V6_vgathermhw:
+ case Hexagon::V6_vgathermwq:
+ case Hexagon::V6_vgathermhq:
+ case Hexagon::V6_vgathermhwq:
+ // Slot1 only loads
+ break;
+ default:
+ ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
+ break;
+ }
+ else if (loads >= 1 && isMemReorderDisabled()) { // }:mem_noshuf
+ // Loads must keep the original order ONLY if
+ // isMemReorderDisabled() == true
+ if (slotLoadStore < slotLastLoadStore) {
+ // Error if no more slots available for loads.
+ reportError(
+ llvm::Twine("invalid instruction packet: too many loads"));
+ return false;
+ }
+ // Pin the load to the highest slot available to it.
+ ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
+ // Update the next highest slot available to loads.
+ slotLoadStore >>= 1;
+ }
}
// A single store must use slot #0.
if (HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()) {
if (!store0) {
- if (stores == 1)
+ if (stores == 1 && (loads == 0 || !isMemReorderDisabled()))
+ // Pin the store to slot #0 only if isMemReorderDisabled() == false
ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);
- else if (stores > 1) {
+ else if (stores >= 1) {
if (slotLoadStore < slotLastLoadStore) {
// Error if no more slots available for stores.
- reportError(
- llvm::Twine("invalid instruction packet: too many stores"));
+ reportError(Twine("invalid instruction packet: too many stores"));
return false;
}
// Pin the store to the highest slot available to it.
@@ -421,7 +474,7 @@ bool HexagonShuffler::check() {
}
if (store1 && stores > 1) {
// Error if a single store with another store.
- reportError(llvm::Twine("invalid instruction packet: too many stores"));
+ reportError(Twine("invalid instruction packet: too many stores"));
return false;
}
}
@@ -432,16 +485,16 @@ bool HexagonShuffler::check() {
if (!ISJ->Core.getUnits()) {
// Error if insn may not be executed in any slot.
- reportError(llvm::Twine("invalid instruction packet: out of slots"));
+ reportError(Twine("invalid instruction packet: out of slots"));
return false;
}
}
// preserve branch order
bool validateSlots = true;
- if (jumps > 1) {
+ if (foundBranches.size() > 1) {
if (foundBranches.size() > 2) {
- reportError(llvm::Twine("too many branches in packet"));
+ reportError(Twine("too many branches in packet"));
return false;
}
@@ -461,11 +514,11 @@ bool HexagonShuffler::check() {
foundBranches[1]->Core.setUnits(jumpSlots[i].second);
HexagonUnitAuction AuctionCore(reservedSlots);
- std::sort(begin(), end(), HexagonInstr::lessCore);
+ std::stable_sort(begin(), end(), HexagonInstr::lessCore);
// see if things ok with that instruction being pinned to slot "slotJump"
bool bFail = false;
- for (iterator I = begin(); I != end() && bFail != true; ++I)
+ for (iterator I = begin(); I != end() && !bFail; ++I)
if (!AuctionCore.bid(I->Core.getUnits()))
bFail = true;
@@ -477,13 +530,13 @@ bool HexagonShuffler::check() {
// restore original values
Packet = PacketSave;
}
- if (validateSlots == true) {
- reportError(llvm::Twine("invalid instruction packet: out of slots"));
+ if (validateSlots) {
+ reportError(Twine("invalid instruction packet: out of slots"));
return false;
}
}
- if (jumps <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 &&
+ if (foundBranches.size() <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 &&
slot3ISJ != end()) {
validateSlots = true;
// save off slot mask of instruction marked with A_PREFER_SLOT3
@@ -492,11 +545,11 @@ bool HexagonShuffler::check() {
slot3ISJ->Core.setUnits(saveUnits & slotThree);
HexagonUnitAuction AuctionCore(reservedSlots);
- std::sort(begin(), end(), HexagonInstr::lessCore);
+ std::stable_sort(begin(), end(), HexagonInstr::lessCore);
// see if things ok with that instruction being pinned to slot #3
bool bFail = false;
- for (iterator I = begin(); I != end() && bFail != true; ++I)
+ for (iterator I = begin(); I != end() && !bFail; ++I)
if (!AuctionCore.bid(I->Core.getUnits()))
bFail = true;
@@ -516,16 +569,16 @@ bool HexagonShuffler::check() {
if (validateSlots) {
HexagonUnitAuction AuctionCore(reservedSlots);
- std::sort(begin(), end(), HexagonInstr::lessCore);
+ std::stable_sort(begin(), end(), HexagonInstr::lessCore);
for (iterator I = begin(); I != end(); ++I)
if (!AuctionCore.bid(I->Core.getUnits())) {
- reportError(llvm::Twine("invalid instruction packet: slot error"));
+ reportError(Twine("invalid instruction packet: slot error"));
return false;
}
}
// Verify the CVI slot subscriptions.
- std::sort(begin(), end(), HexagonInstr::lessCVI);
+ std::stable_sort(begin(), end(), HexagonInstr::lessCVI);
// create vector of hvx instructions to check
HVXInstsT hvxInsts;
hvxInsts.clear();
@@ -541,9 +594,9 @@ bool HexagonShuffler::check() {
if (hvxInsts.size() > 0) {
unsigned startIdx, usedUnits;
startIdx = usedUnits = 0x0;
- if (checkHVXPipes(hvxInsts, startIdx, usedUnits) == false) {
+ if (!checkHVXPipes(hvxInsts, startIdx, usedUnits)) {
// too many pipes used to be valid
- reportError(llvm::Twine("invalid instruction packet: slot error"));
+ reportError(Twine("invalid instruction packet: slot error"));
return false;
}
}
@@ -555,7 +608,7 @@ bool HexagonShuffler::shuffle() {
if (size() > HEXAGON_PACKET_SIZE) {
// Ignore a packet with with more than what a packet can hold
// or with compound or duplex insns for now.
- reportError(llvm::Twine("invalid instruction packet"));
+ reportError(Twine("invalid instruction packet"));
return false;
}
@@ -581,7 +634,7 @@ bool HexagonShuffler::shuffle() {
if (slotWeight)
// Sort the packet, favoring source order,
// beginning after the previous slot.
- std::sort(ISJ, Packet.end());
+ std::stable_sort(ISJ, Packet.end());
else
// Skip unused slot.
++emptySlots;
@@ -600,7 +653,13 @@ bool HexagonShuffler::shuffle() {
return Ok;
}
-void HexagonShuffler::reportError(llvm::Twine const &Msg) {
- if (ReportErrors)
+void HexagonShuffler::reportError(Twine const &Msg) {
+ if (ReportErrors) {
+ for (auto const &I : AppliedRestrictions) {
+ auto SM = Context.getSourceManager();
+ if (SM)
+ SM->PrintMessage(I.first, SourceMgr::DK_Note, I.second);
+ }
Context.reportError(Loc, Msg);
+ }
}