#include "Hexagon.h"
#include "HexagonISelDAGToDAG.h"
#include "HexagonISelLowering.h"
#include "HexagonTargetMachine.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsHexagon.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cmath>
#include <deque>
#include <functional>
#include <map>
#include <optional>
#include <set>
#include <unordered_map>
#include <utility>
#include <vector>
#define DEBUG_TYPE …
usingnamespacellvm;
namespace {
enum class ColorKind { … };
struct Coloring { … };
}
std::pair<bool, ColorKind> Coloring::getUniqueColor(const NodeSet &Nodes) { … }
void Coloring::build() { … }
bool Coloring::color() { … }
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void Coloring::dump() const {
dbgs() << "{ Order: {";
for (Node P : Order) {
if (P != Ignore)
dbgs() << ' ' << P;
else
dbgs() << " -";
}
dbgs() << " }\n";
dbgs() << " Needed: {";
for (Node N : Needed)
dbgs() << ' ' << N;
dbgs() << " }\n";
dbgs() << " Edges: {\n";
for (auto E : Edges) {
dbgs() << " " << E.first << " -> {";
for (auto N : E.second)
dbgs() << ' ' << N;
dbgs() << " }\n";
}
dbgs() << " }\n";
auto ColorKindToName = [](ColorKind C) {
switch (C) {
case ColorKind::None:
return "None";
case ColorKind::Red:
return "Red";
case ColorKind::Black:
return "Black";
}
llvm_unreachable("all ColorKinds should be handled by the switch above");
};
dbgs() << " Colors: {\n";
for (auto C : Colors)
dbgs() << " " << C.first << " -> " << ColorKindToName(C.second) << "\n";
dbgs() << " }\n}\n";
}
#endif
namespace {
struct PermNetwork { … };
struct ForwardDeltaNetwork : public PermNetwork { … };
struct ReverseDeltaNetwork : public PermNetwork { … };
struct BenesNetwork : public PermNetwork { … };
}
bool ForwardDeltaNetwork::route(ElemType *P, RowType *T, unsigned Size,
unsigned Step) { … }
bool ReverseDeltaNetwork::route(ElemType *P, RowType *T, unsigned Size,
unsigned Step) { … }
bool BenesNetwork::route(ElemType *P, RowType *T, unsigned Size,
unsigned Step) { … }
namespace {
struct OpRef { … };
struct NodeTemplate { … };
struct ResultStack { … };
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void OpRef::print(raw_ostream &OS, const SelectionDAG &G) const {
if (isValue()) {
OpV.getNode()->print(OS, &G);
return;
}
if (OpN & Invalid) {
OS << "invalid";
return;
}
if (OpN & Undef) {
OS << "undef";
return;
}
if ((OpN & Whole) != Whole) {
assert((OpN & Whole) == LoHalf || (OpN & Whole) == HiHalf);
if (OpN & LoHalf)
OS << "lo ";
else
OS << "hi ";
}
OS << '#' << SignExtend32(OpN & Index, IndexBits);
}
void NodeTemplate::print(raw_ostream &OS, const SelectionDAG &G) const {
const TargetInstrInfo &TII = *G.getSubtarget().getInstrInfo();
OS << format("%8s", EVT(Ty).getEVTString().c_str()) << " "
<< TII.getName(Opc);
bool Comma = false;
for (const auto &R : Ops) {
if (Comma)
OS << ',';
Comma = true;
OS << ' ';
R.print(OS, G);
}
}
void ResultStack::print(raw_ostream &OS, const SelectionDAG &G) const {
OS << "Input node:\n";
#ifndef NDEBUG
InpNode->dumpr(&G);
#endif
OS << "Result templates:\n";
for (unsigned I = 0, E = List.size(); I != E; ++I) {
OS << '[' << I << "] ";
List[I].print(OS, G);
OS << '\n';
}
}
#endif
namespace {
struct ShuffleMask { … };
LLVM_ATTRIBUTE_UNUSED
raw_ostream &operator<<(raw_ostream &OS, const ShuffleMask &SM) { … }
}
namespace shuffles {
MaskT;
ArrayRef<int> lo(ArrayRef<int> Vuu) { … }
ArrayRef<int> hi(ArrayRef<int> Vuu) { … }
MaskT vshuffvdd(ArrayRef<int> Vu, ArrayRef<int> Vv, unsigned Rt) { … }
MaskT vdealvdd(ArrayRef<int> Vu, ArrayRef<int> Vv, unsigned Rt) { … }
MaskT vpack(ArrayRef<int> Vu, ArrayRef<int> Vv, unsigned Size, bool TakeOdd) { … }
MaskT vshuff(ArrayRef<int> Vu, ArrayRef<int> Vv, unsigned Size, bool TakeOdd) { … }
MaskT vdeal(ArrayRef<int> Vu, ArrayRef<int> Vv, unsigned Size, bool TakeOdd) { … }
MaskT vdealb4w(ArrayRef<int> Vu, ArrayRef<int> Vv) { … }
template <typename ShuffFunc, typename... OptArgs>
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT { … }
}
static const HexagonTargetLowering &getHexagonLowering(SelectionDAG &G) { … }
static const HexagonSubtarget &getHexagonSubtarget(SelectionDAG &G) { … }
namespace llvm {
struct HvxSelector { … };
}
static void splitMask(ArrayRef<int> Mask, MutableArrayRef<int> MaskL,
MutableArrayRef<int> MaskR) { … }
static std::pair<int,unsigned> findStrip(ArrayRef<int> A, int Inc,
unsigned MaxLen) { … }
static bool isUndef(ArrayRef<int> Mask) { … }
static bool isIdentity(ArrayRef<int> Mask) { … }
static bool isLowHalfOnly(ArrayRef<int> Mask) { … }
static SmallVector<unsigned, 4> getInputSegmentList(ShuffleMask SM,
unsigned SegLen) { … }
static SmallVector<unsigned, 4> getOutputSegmentMap(ShuffleMask SM,
unsigned SegLen) { … }
static void packSegmentMask(ArrayRef<int> Mask, ArrayRef<unsigned> OutSegMap,
unsigned SegLen, MutableArrayRef<int> PackedMask) { … }
bool HvxSelector::selectVectorConstants(SDNode *N) { … }
void HvxSelector::materialize(const ResultStack &Results) { … }
OpRef HvxSelector::concats(OpRef Lo, OpRef Hi, ResultStack &Results) { … }
OpRef HvxSelector::funnels(OpRef Va, OpRef Vb, int Amount,
ResultStack &Results) { … }
OpRef HvxSelector::packs(ShuffleMask SM, OpRef Va, OpRef Vb,
ResultStack &Results, MutableArrayRef<int> NewMask,
unsigned Options) { … }
OpRef HvxSelector::packp(ShuffleMask SM, OpRef Va, OpRef Vb,
ResultStack &Results, MutableArrayRef<int> NewMask) { … }
OpRef HvxSelector::vmuxs(ArrayRef<uint8_t> Bytes, OpRef Va, OpRef Vb,
ResultStack &Results) { … }
OpRef HvxSelector::vmuxp(ArrayRef<uint8_t> Bytes, OpRef Va, OpRef Vb,
ResultStack &Results) { … }
OpRef HvxSelector::shuffs1(ShuffleMask SM, OpRef Va, ResultStack &Results) { … }
OpRef HvxSelector::shuffs2(ShuffleMask SM, OpRef Va, OpRef Vb,
ResultStack &Results) { … }
OpRef HvxSelector::shuffp1(ShuffleMask SM, OpRef Va, ResultStack &Results) { … }
OpRef HvxSelector::shuffp2(ShuffleMask SM, OpRef Va, OpRef Vb,
ResultStack &Results) { … }
namespace {
struct Deleter : public SelectionDAG::DAGNodeDeletedListener { … };
template <typename T>
struct NullifyingVector : public T { … };
}
void HvxSelector::select(SDNode *ISelN) { … }
bool HvxSelector::scalarizeShuffle(ArrayRef<int> Mask, const SDLoc &dl,
MVT ResTy, SDValue Va, SDValue Vb,
SDNode *N) { … }
SmallVector<uint32_t, 8> HvxSelector::getPerfectCompletions(ShuffleMask SM,
unsigned Width) { … }
SmallVector<uint32_t, 8>
HvxSelector::completeToPerfect(ArrayRef<uint32_t> Completions, unsigned Width) { … }
std::optional<int> HvxSelector::rotationDistance(ShuffleMask SM,
unsigned WrapAt) { … }
OpRef HvxSelector::contracting(ShuffleMask SM, OpRef Va, OpRef Vb,
ResultStack &Results) { … }
OpRef HvxSelector::expanding(ShuffleMask SM, OpRef Va, ResultStack &Results) { … }
OpRef HvxSelector::perfect(ShuffleMask SM, OpRef Va, ResultStack &Results) { … }
OpRef HvxSelector::butterfly(ShuffleMask SM, OpRef Va, ResultStack &Results) { … }
SDValue HvxSelector::getConst32(int Val, const SDLoc &dl) { … }
SDValue HvxSelector::getVectorConstant(ArrayRef<uint8_t> Data,
const SDLoc &dl) { … }
void HvxSelector::selectExtractSubvector(SDNode *N) { … }
void HvxSelector::selectShuffle(SDNode *N) { … }
void HvxSelector::selectRor(SDNode *N) { … }
void HvxSelector::selectVAlign(SDNode *N) { … }
void HexagonDAGToDAGISel::PreprocessHvxISelDAG() { … }
template <> struct std::hash<SDValue> { … };
void HexagonDAGToDAGISel::ppHvxShuffleOfShuffle(std::vector<SDNode *> &&Nodes) { … }
void HexagonDAGToDAGISel::SelectHvxExtractSubvector(SDNode *N) { … }
void HexagonDAGToDAGISel::SelectHvxShuffle(SDNode *N) { … }
void HexagonDAGToDAGISel::SelectHvxRor(SDNode *N) { … }
void HexagonDAGToDAGISel::SelectHvxVAlign(SDNode *N) { … }
void HexagonDAGToDAGISel::SelectV65GatherPred(SDNode *N) { … }
void HexagonDAGToDAGISel::SelectV65Gather(SDNode *N) { … }
void HexagonDAGToDAGISel::SelectHVXDualOutput(SDNode *N) { … }