15#include "llvm/IR/IntrinsicsHexagon.h"
28#define DEBUG_TYPE "hexagon-isel"
98enum class ColorKind {
None, Red, Black };
104 using MapType = std::map<Node, ColorKind>;
113 const MapType &colors()
const {
117 ColorKind other(ColorKind Color) {
118 if (Color == ColorKind::None)
119 return ColorKind::Red;
120 return Color == ColorKind::Red ? ColorKind::Black : ColorKind::Red;
128 std::set<Node> Needed;
130 using NodeSet = std::set<Node>;
131 std::map<Node,NodeSet> Edges;
135 return (Pos < Num/2) ? Pos + Num/2 : Pos - Num/2;
138 ColorKind getColor(
Node N) {
139 auto F = Colors.find(
N);
140 return F != Colors.end() ?
F->second : ColorKind::None;
143 std::pair<bool, ColorKind> getUniqueColor(
const NodeSet &Nodes);
150std::pair<bool, ColorKind> Coloring::getUniqueColor(
const NodeSet &Nodes) {
151 auto Color = ColorKind::None;
152 for (Node
N : Nodes) {
153 ColorKind ColorN = getColor(
N);
154 if (ColorN == ColorKind::None)
156 if (Color == ColorKind::None)
158 else if (Color != ColorKind::None && Color != ColorN)
159 return {
false, ColorKind::None };
161 return {
true, Color };
164void Coloring::build() {
166 for (
unsigned P = 0;
P != Order.size(); ++
P) {
170 Node PC = Order[conj(
P)];
176 for (
unsigned I = 0;
I != Order.size(); ++
I) {
177 if (!Needed.count(
I))
183 NodeSet &Is = Edges[
I];
189bool Coloring::color() {
190 SetVector<Node> FirstQ;
191 auto Enqueue = [
this,&FirstQ] (Node
N) {
194 for (
unsigned I = 0;
I != Q.
size(); ++
I) {
195 NodeSet &Ns = Edges[Q[
I]];
200 for (Node
N : Needed)
203 for (Node
N : FirstQ) {
206 NodeSet &Ns = Edges[
N];
207 auto P = getUniqueColor(Ns);
210 Colors[
N] = other(
P.second);
214 for (
auto E : Edges) {
216 if (!Needed.count(conj(
N)) || Colors.count(
N))
218 auto P = getUniqueColor(
E.second);
221 Colors[
N] = other(
P.second);
226 std::vector<Node> WorkQ;
227 for (
auto E : Edges) {
229 if (!Colors.count(
N))
233 for (Node
N : WorkQ) {
234 NodeSet &Ns = Edges[
N];
235 auto P = getUniqueColor(Ns);
237 Colors[
N] = other(
P.second);
243 ColorKind ColorN = other(ColorKind::None);
244 ColorKind ColorC = other(ColorN);
245 NodeSet &Cs = Edges[
C];
247 for (Node M : CopyNs) {
248 ColorKind ColorM = getColor(M);
249 if (ColorM == ColorC) {
262 for (
unsigned I = 0;
I != Order.size(); ++
I)
263 Colors.try_emplace(
I, ColorKind::None);
268#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
269void Coloring::dump()
const {
270 dbgs() <<
"{ Order: {";
271 for (Node
P : Order) {
278 dbgs() <<
" Needed: {";
279 for (Node
N : Needed)
283 dbgs() <<
" Edges: {\n";
284 for (
auto E : Edges) {
285 dbgs() <<
" " <<
E.first <<
" -> {";
286 for (
auto N :
E.second)
292 auto ColorKindToName = [](ColorKind
C) {
294 case ColorKind::None:
298 case ColorKind::Black:
304 dbgs() <<
" Colors: {\n";
305 for (
auto C : Colors)
306 dbgs() <<
" " <<
C.first <<
" -> " << ColorKindToName(
C.second) <<
"\n";
316 using Controls = std::vector<uint8_t>;
317 using ElemType = int;
318 static constexpr ElemType
Ignore = ElemType(-1);
334 unsigned S = Order.size();
338 Table.resize(Order.size());
339 for (RowType &Row :
Table)
340 Row.resize(Mult*Log,
None);
343 void getControls(Controls &V,
unsigned StartAt, uint8_t Dir)
const {
344 unsigned Size = Order.size();
346 for (
unsigned I = 0;
I !=
Size; ++
I) {
348 for (
unsigned L = 0;
L != Log; ++
L) {
349 unsigned C = ctl(
I, StartAt+L) == Switch;
360 uint8_t ctl(ElemType Pos,
unsigned Step)
const {
361 return Table[Pos][Step];
363 unsigned size()
const {
366 unsigned steps()
const {
372 std::vector<ElemType> Order;
373 using RowType = std::vector<uint8_t>;
374 std::vector<RowType>
Table;
377struct ForwardDeltaNetwork :
public PermNetwork {
380 bool run(Controls &V) {
381 if (!route(Order.data(),
Table.data(),
size(), 0))
383 getControls(V, 0, Forward);
388 bool route(ElemType *
P, RowType *
T,
unsigned Size,
unsigned Step);
391struct ReverseDeltaNetwork :
public PermNetwork {
394 bool run(Controls &V) {
395 if (!route(Order.data(),
Table.data(),
size(), 0))
402 bool route(ElemType *
P, RowType *
T,
unsigned Size,
unsigned Step);
405struct BenesNetwork :
public PermNetwork {
408 bool run(Controls &
F, Controls &R) {
409 if (!route(Order.data(),
Table.data(),
size(), 0))
412 getControls(
F, 0, Forward);
418 bool route(ElemType *
P, RowType *
T,
unsigned Size,
unsigned Step);
422bool ForwardDeltaNetwork::route(ElemType *
P, RowType *
T,
unsigned Size,
424 bool UseUp =
false, UseDown =
false;
431 for (ElemType J = 0; J != Num; ++J) {
441 S = (J < Num/2) ? Switch :
Pass;
444 ElemType
U = (S ==
Pass) ?
I : (
I < Num/2 ?
I+Num/2 :
I-Num/2);
449 if (
T[U][Step] != S &&
T[U][Step] !=
None)
454 for (ElemType J = 0; J != Num; ++J)
455 if (
P[J] !=
Ignore &&
P[J] >= Num/2)
459 if (UseUp && !route(
P,
T,
Size/2, Step+1))
467bool ReverseDeltaNetwork::route(ElemType *
P, RowType *
T,
unsigned Size,
469 unsigned Pets =
Log-1 - Step;
470 bool UseUp =
false, UseDown =
false;
475 const Coloring::MapType &
M =
G.colors();
479 ColorKind ColorUp = ColorKind::None;
480 for (ElemType J = 0; J != Num; ++J) {
486 ColorKind
C =
M.at(
I);
487 if (
C == ColorKind::None)
492 bool InpUp =
I < Num/2;
493 if (ColorUp == ColorKind::None)
494 ColorUp = InpUp ?
C :
G.other(
C);
495 if ((
C == ColorUp) != InpUp) {
505 S = (J < Num/2) ? Switch :
Pass;
513 for (ElemType J = 0,
E =
Size / 2; J !=
E; ++J) {
515 ElemType PC =
P[J+
Size/2];
518 if (
T[J][Pets] == Switch)
520 if (
T[J+
Size/2][Pets] == Switch)
526 for (ElemType J = 0; J != Num; ++J)
527 if (
P[J] !=
Ignore &&
P[J] >= Num/2)
531 if (UseUp && !route(
P,
T,
Size/2, Step+1))
539bool BenesNetwork::route(ElemType *
P, RowType *
T,
unsigned Size,
542 const Coloring::MapType &
M =
G.colors();
547 unsigned Pets = 2*
Log-1 - Step;
548 bool UseUp =
false, UseDown =
false;
553 ColorKind ColorUp = ColorKind::None;
554 for (ElemType J = 0; J != Num; ++J) {
558 ColorKind
C =
M.at(
I);
559 if (
C == ColorKind::None)
561 if (ColorUp == ColorKind::None) {
562 ColorUp = (
I < Num / 2) ? ColorKind::Red : ColorKind::Black;
564 unsigned CI = (
I < Num/2) ?
I+Num/2 :
I-Num/2;
577 T[J][Pets] = (J < Num/2) ? Switch :
Pass;
584 for (ElemType J = 0; J != Num/2; ++J) {
586 ElemType PC =
P[J+Num/2];
589 if (
T[J][Pets] == Switch)
591 if (
T[J+Num/2][Pets] == Switch)
597 for (ElemType J = 0; J != Num; ++J)
598 if (
P[J] !=
Ignore &&
P[J] >= Num/2)
602 if (UseUp && !route(
P,
T,
Size/2, Step+1))
616 OpRef(SDValue V) : OpV(
V) {}
617 bool isValue()
const {
return OpV.
getNode() !=
nullptr; }
620 static OpRef res(
int N) {
return OpRef(Whole | (
N & Index)); }
623 static OpRef
lo(
const OpRef &R) {
625 return OpRef(
R.OpN & (
Undef | Index | LoHalf));
627 static OpRef
hi(
const OpRef &R) {
629 return OpRef(
R.OpN & (
Undef | Index | HiHalf));
631 static OpRef undef(MVT Ty) {
return OpRef(
Undef | Ty.
SimpleTy); }
634 SDValue OpV = SDValue();
647 Whole = LoHalf | HiHalf,
654 void print(raw_ostream &OS,
const SelectionDAG &
G)
const;
657 OpRef(
unsigned N) : OpN(
N) {}
661 NodeTemplate() =
default;
664 std::vector<OpRef>
Ops;
670 ResultStack(SDNode *Inp)
674 unsigned push(
const NodeTemplate &Res) {
676 return List.size()-1;
678 unsigned push(
unsigned Opc, MVT Ty, std::vector<OpRef> &&
Ops) {
685 bool empty()
const {
return List.empty(); }
686 unsigned size()
const {
return List.size(); }
687 unsigned top()
const {
return size()-1; }
688 const NodeTemplate &operator[](
unsigned I)
const {
return List[
I]; }
689 unsigned reset(
unsigned NewTop) {
690 List.resize(NewTop+1);
694 using BaseType = std::vector<NodeTemplate>;
695 BaseType::iterator
begin() {
return List.begin(); }
696 BaseType::iterator
end() {
return List.end(); }
697 BaseType::const_iterator
begin()
const {
return List.begin(); }
698 BaseType::const_iterator
end()
const {
return List.end(); }
703 void print(raw_ostream &OS,
const SelectionDAG &
G)
const;
707#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
708void OpRef::print(raw_ostream &OS,
const SelectionDAG &
G)
const {
721 if ((OpN & Whole) != Whole) {
722 assert((OpN & Whole) == LoHalf || (OpN & Whole) == HiHalf);
731void NodeTemplate::print(raw_ostream &OS,
const SelectionDAG &
G)
const {
732 const TargetInstrInfo &
TII = *
G.getSubtarget().getInstrInfo();
733 OS <<
format(
"%8s", EVT(Ty).getEVTString().
c_str()) <<
" "
736 for (
const auto &R :
Ops) {
745void ResultStack::print(raw_ostream &OS,
const SelectionDAG &
G)
const {
746 OS <<
"Input node:\n";
750 OS <<
"Result templates:\n";
751 for (
unsigned I = 0,
E =
List.size();
I !=
E; ++
I) {
752 OS <<
'[' <<
I <<
"] ";
761 ShuffleMask(ArrayRef<int> M) : Mask(
M) {
765 MinSrc = (MinSrc == -1) ? M : std::
min(MinSrc,
M);
766 MaxSrc = (MaxSrc == -1) ?
M : std::max(MaxSrc, M);
771 int MinSrc = -1, MaxSrc = -1;
773 ShuffleMask
lo()
const {
774 size_t H =
Mask.size()/2;
775 return ShuffleMask(
Mask.take_front(
H));
777 ShuffleMask
hi()
const {
778 size_t H =
Mask.size()/2;
779 return ShuffleMask(
Mask.take_back(
H));
782 void print(raw_ostream &OS)
const {
783 OS <<
"MinSrc:" << MinSrc <<
", MaxSrc:" << MaxSrc <<
" {";
791raw_ostream &
operator<<(raw_ostream &OS,
const ShuffleMask &SM) {
821 for (
int i = 0; i != Len; ++i) {
841 for (
int i = 0; i != Len; ++i) {
852 auto Odd =
static_cast<int>(TakeOdd);
853 for (
int i = 0, e = Len / (2 *
Size); i != e; ++i) {
854 for (
int b = 0; b !=
static_cast<int>(
Size); ++b) {
856 Vd[i *
Size + b] = Vv[(2 * i + Odd) *
Size + b];
857 Vd[i *
Size + b + Len / 2] = Vu[(2 * i + Odd) *
Size + b];
867 auto Odd =
static_cast<int>(TakeOdd);
868 for (
int i = 0, e = Len / (2 *
Size); i != e; ++i) {
869 for (
int b = 0; b !=
static_cast<int>(
Size); ++b) {
870 Vd[(2 * i + 0) *
Size + b] = Vv[(2 * i + Odd) *
Size + b];
871 Vd[(2 * i + 1) *
Size + b] = Vu[(2 * i + Odd) *
Size + b];
886 for (
int i = 0, e = Len / 4; i != e; ++i) {
887 Vd[0 * (Len / 4) + i] = Vv[4 * i + 0];
888 Vd[1 * (Len / 4) + i] = Vv[4 * i + 2];
889 Vd[2 * (Len / 4) + i] = Vu[4 * i + 0];
890 Vd[3 * (Len / 4) + i] = Vu[4 * i + 2];
895template <
typename ShuffFunc,
typename... OptArgs>
898 std::iota(Vu.begin(), Vu.end(),
Length);
900 return S(Vu, Vv,
args...);
928 assert(
ElemTy != MVT::i1 &&
"Use getBoolVT for predicates");
929 unsigned NumElems =
HwLen / (
ElemTy.getSizeInBits() / 8);
935 unsigned NumElems = (2 *
HwLen) / (
ElemTy.getSizeInBits() / 8);
944 void selectExtractSubvector(
SDNode *
N);
953 static std::optional<int> rotationDistance(ShuffleMask SM,
unsigned WrapAt);
956 void select(
SDNode *ISelN);
957 void materialize(
const ResultStack &
Results);
967 OpRef concats(OpRef Va, OpRef Vb, ResultStack &
Results);
968 OpRef funnels(OpRef Va, OpRef Vb,
int Amount, ResultStack &
Results);
970 OpRef packs(ShuffleMask SM, OpRef Va, OpRef Vb, ResultStack &
Results,
972 OpRef packp(ShuffleMask SM, OpRef Va, OpRef Vb, ResultStack &
Results,
979 OpRef shuffs1(ShuffleMask SM, OpRef Va, ResultStack &
Results);
980 OpRef shuffs2(ShuffleMask SM, OpRef Va, OpRef Vb, ResultStack &
Results);
981 OpRef shuffp1(ShuffleMask SM, OpRef Va, ResultStack &
Results);
982 OpRef shuffp2(ShuffleMask SM, OpRef Va, OpRef Vb, ResultStack &
Results);
984 OpRef butterfly(ShuffleMask SM, OpRef Va, ResultStack &
Results);
985 OpRef contracting(ShuffleMask SM, OpRef Va, OpRef Vb, ResultStack &
Results);
986 OpRef expanding(ShuffleMask SM, OpRef Va, ResultStack &
Results);
987 OpRef perfect(ShuffleMask SM, OpRef Va, ResultStack &
Results);
989 bool selectVectorConstants(
SDNode *
N);
997 unsigned VecLen = Mask.size();
999 for (
unsigned I = 0;
I != VecLen; ++
I) {
1002 MaskL[
I] = MaskR[
I] = -1;
1003 }
else if (
unsigned(M) < VecLen) {
1008 MaskR[
I] = M-VecLen;
1015 assert(
A.size() > 0 &&
A.size() >= MaxLen);
1018 for (
unsigned I = 1;
I != MaxLen; ++
I) {
1019 if (
A[
I] -
E != Inc)
1023 return {
F, MaxLen };
1027 for (
int Idx : Mask)
1034 for (
int I = 0,
E = Mask.size();
I !=
E; ++
I) {
1036 if (M >= 0 && M !=
I)
1043 int L = Mask.size();
1046 return llvm::all_of(Mask.drop_front(L / 2), [](
int M) { return M < 0; });
1053 if (SM.MaxSrc == -1)
1056 unsigned Shift =
Log2_32(SegLen);
1059 for (
int M : SM.Mask) {
1061 Segs.
set(M >> Shift);
1079 unsigned MaskLen = SM.Mask.
size();
1080 assert(MaskLen % SegLen == 0);
1083 for (
int S = 0,
E = Map.size(); S !=
E; ++S) {
1085 for (
int I = 0;
I !=
static_cast<int>(SegLen); ++
I) {
1086 int M = SM.Mask[S*SegLen +
I];
1089 unsigned G = M / SegLen;
1092 }
else if (Idx !=
G) {
1106 for (
int I = OutSegMap.
size() - 1;
I >= 0; --
I) {
1107 unsigned S = OutSegMap[
I];
1108 assert(S != ~0u &&
"Unexpected undef");
1109 assert(S != ~1u &&
"Unexpected multi");
1110 if (InvMap.
size() <= S)
1115 unsigned Shift =
Log2_32(SegLen);
1116 for (
int I = 0,
E = Mask.size();
I !=
E; ++
I) {
1119 int OutIdx = InvMap[M >> Shift];
1120 M = (M & (SegLen-1)) + SegLen*OutIdx;
1126bool HvxSelector::selectVectorConstants(SDNode *
N) {
1132 SetVector<SDNode*> WorkQ;
1137 for (
unsigned i = 0; i != WorkQ.
size(); ++i) {
1138 SDNode *
W = WorkQ[i];
1141 for (
unsigned j = 0, f =
W->getNumOperands(); j != f; ++j)
1142 WorkQ.
insert(
W->getOperand(j).getNode());
1145 for (SDNode *L : Nodes)
1148 return !Nodes.empty();
1151void HvxSelector::materialize(
const ResultStack &
Results) {
1153 dbgs() <<
"Materializing\n";
1158 const SDLoc &dl(
Results.InpNode);
1159 std::vector<SDValue>
Output;
1163 std::vector<SDValue>
Ops;
1164 for (
const OpRef &R :
Node.Ops) {
1167 Ops.push_back(
R.OpV);
1170 if (
R.OpN & OpRef::Undef) {
1172 Ops.push_back(ISel.selectUndef(dl, MVT(SVT)));
1176 unsigned Part =
R.OpN & OpRef::Whole;
1182 MVT OpTy =
Op.getValueType().getSimpleVT();
1183 if (Part != OpRef::Whole) {
1184 assert(Part == OpRef::LoHalf || Part == OpRef::HiHalf);
1187 unsigned Sub = (Part == OpRef::LoHalf) ? Hexagon::vsub_lo
1189 Op = DAG.getTargetExtractSubreg(
Sub, dl, HalfTy,
Op);
1195 SDNode *ResN = (
Node.Opc == TargetOpcode::COPY)
1196 ?
Ops.front().getNode()
1198 Output.push_back(SDValue(ResN, 0));
1201 SDNode *OutN =
Output.back().getNode();
1202 SDNode *InpN =
Results.InpNode;
1204 dbgs() <<
"Generated node:\n";
1208 ISel.ReplaceNode(InpN, OutN);
1209 selectVectorConstants(OutN);
1210 DAG.RemoveDeadNodes();
1213OpRef HvxSelector::concats(OpRef
Lo, OpRef
Hi, ResultStack &
Results) {
1215 const SDLoc &dl(
Results.InpNode);
1216 Results.push(TargetOpcode::REG_SEQUENCE, getPairVT(MVT::i8), {
1217 getConst32(Hexagon::HvxWRRegClassID, dl),
1218 Lo, getConst32(Hexagon::vsub_lo, dl),
1219 Hi, getConst32(Hexagon::vsub_hi, dl),
1221 return OpRef::res(
Results.top());
1224OpRef HvxSelector::funnels(OpRef Va, OpRef Vb,
int Amount,
1229 auto VecLen =
static_cast<int>(HwLen);
1233 if (Amount == VecLen)
1236 MVT Ty = getSingleVT(MVT::i8);
1237 const SDLoc &dl(
Results.InpNode);
1241 if (Amount > VecLen) {
1247 SDValue
A = getConst32(Amount, dl);
1248 Results.push(Hexagon::V6_valignbi, Ty, {Vb, Va,
A});
1249 }
else if (
isUInt<3>(VecLen - Amount)) {
1250 SDValue
A = getConst32(VecLen - Amount, dl);
1251 Results.push(Hexagon::V6_vlalignbi, Ty, {Vb, Va,
A});
1253 SDValue
A = getConst32(Amount, dl);
1254 Results.push(Hexagon::A2_tfrsi, Ty, {
A});
1255 Results.push(Hexagon::V6_valignb, Ty, {Vb, Va, OpRef::res(-1)});
1257 return OpRef::res(
Results.top());
1263OpRef HvxSelector::packs(ShuffleMask SM, OpRef Va, OpRef Vb,
1267 if (!Va.isValid() || !Vb.isValid())
1268 return OpRef::fail();
1280 MVT Ty = getSingleVT(MVT::i8);
1281 MVT
PairTy = getPairVT(MVT::i8);
1282 OpRef Inp[2] = {Va, Vb};
1283 unsigned VecLen = SM.Mask.
size();
1285 auto valign = [
this](OpRef
Lo, OpRef
Hi,
unsigned Amt, MVT Ty,
1289 const SDLoc &dl(
Results.InpNode);
1292 SDValue S = getConst32(IsRight ? Amt : HwLen - Amt, dl);
1293 unsigned Opc = IsRight ? Hexagon::V6_valignbi : Hexagon::V6_vlalignbi;
1295 return OpRef::res(
Results.top());
1297 Results.push(Hexagon::A2_tfrsi, MVT::i32, {getConst32(Amt, dl)});
1298 OpRef
A = OpRef::res(
Results.top());
1300 return OpRef::res(
Results.top());
1304 unsigned SegLen = HwLen / 2;
1310 unsigned SegCount = SegList.
size();
1313 if (SegList.
empty())
1314 return OpRef::undef(Ty);
1332 unsigned Seg0 = ~0
u, Seg1 = ~0
u;
1333 for (
unsigned X : SegMap) {
1338 else if (Seg1 != ~0u)
1340 if (
X == ~1u ||
X != Seg0)
1344 if (SegCount == 1) {
1345 unsigned SrcOp = SegList[0] / 2;
1346 for (
int I = 0;
I !=
static_cast<int>(VecLen); ++
I) {
1357 if (SegCount == 2) {
1364 if (Seg0 == ~1u || Seg1 == ~1u) {
1368 }
else if (Seg0 == ~1u) {
1369 Seg0 = SegList[0] != Seg1 ? SegList[0] : SegList[1];
1372 Seg1 = SegList[0] != Seg0 ? SegList[0] : SegList[1];
1375 assert(Seg0 != ~1u && Seg1 != ~1u);
1377 assert(Seg0 != Seg1 &&
"Expecting different segments");
1378 const SDLoc &dl(
Results.InpNode);
1379 Results.push(Hexagon::A2_tfrsi, MVT::i32, {getConst32(SegLen, dl)});
1380 OpRef HL = OpRef::res(
Results.top());
1384 if (Seg0 / 2 == Seg1 / 2) {
1389 Results.push(Hexagon::V6_vror, Ty, {Inp[Seg0 / 2], HL});
1390 Va = OpRef::res(
Results.top());
1393 }
else if (Seg0 % 2 == Seg1 % 2) {
1397 auto Vs = (Seg0 == 0 || Seg0 == 1) ? std::make_pair(Vb, Va)
1398 : std::make_pair(Va, Vb);
1399 Results.push(Hexagon::V6_vshuffvdd,
PairTy, {Vs.first, Vs.second, HL});
1400 OpRef
P = OpRef::res(
Results.top());
1401 Va = (Seg0 == 0 || Seg0 == 2) ? OpRef::lo(
P) : OpRef::hi(
P);
1405 if ((Seg0 == 0 && Seg1 == 3) || (Seg0 == 2 && Seg1 == 1)) {
1409 Results.push(Hexagon::V6_pred_scalar2, getBoolVT(), {HL});
1410 OpRef Qt = OpRef::res(
Results.top());
1411 auto Vs = (Seg0 == 0) ? std::make_pair(Va, Vb)
1412 : std::make_pair(Vb, Va);
1413 Results.push(Hexagon::V6_vmux, Ty, {Qt, Vs.first, Vs.second});
1414 Va = OpRef::res(
Results.top());
1420 assert(Seg0 == 1 || Seg0 == 3);
1427 ShuffleMask SMH(MaskH);
1428 assert(SMH.Mask.size() == VecLen);
1431 if (SMH.MaxSrc - SMH.MinSrc >=
static_cast<int>(HwLen)) {
1435 ShuffleMask SW(Swapped);
1436 if (SW.MaxSrc - SW.MinSrc <
static_cast<int>(HwLen)) {
1437 MaskA.assign(SW.Mask.begin(), SW.Mask.end());
1441 ShuffleMask SMA(MaskA);
1442 assert(SMA.Mask.size() == VecLen);
1444 if (SMA.MaxSrc - SMA.MinSrc <
static_cast<int>(HwLen)) {
1445 int ShiftR = SMA.MinSrc;
1446 if (ShiftR >=
static_cast<int>(HwLen)) {
1448 Vb = OpRef::undef(Ty);
1451 OpRef RetVal = valign(Va, Vb, ShiftR, Ty,
Results);
1453 for (
int I = 0;
I !=
static_cast<int>(VecLen); ++
I) {
1454 int M = SMA.Mask[
I];
1470 BitVector Picked(HwLen);
1471 SmallVector<uint8_t,128> MuxBytes(HwLen);
1473 for (
int I = 0;
I !=
static_cast<int>(VecLen); ++
I) {
1477 if (M >=
static_cast<int>(HwLen))
1488 return vmuxs(MuxBytes, Va, Vb,
Results);
1490 return OpRef::fail();
1496OpRef HvxSelector::packp(ShuffleMask SM, OpRef Va, OpRef Vb,
1500 if (SegList.empty())
1501 return OpRef::undef(getPairVT(MVT::i8));
1505 unsigned SegCount = SegList.size();
1507 return OpRef::fail();
1509 MVT HalfTy = getSingleVT(MVT::i8);
1511 OpRef Inp[2] = { Va, Vb };
1512 OpRef
Out[2] = { OpRef::undef(HalfTy), OpRef::undef(HalfTy) };
1517 for (
int I = 0,
E = SegList.size();
I !=
E; ++
I) {
1518 unsigned S = SegList[
I];
1519 OpRef
Op = Inp[S / 2];
1520 Out[
I] = (S & 1) ? OpRef::hi(
Op) : OpRef::lo(
Op);
1530 return concats(Out[0], Out[1],
Results);
1533OpRef HvxSelector::vmuxs(ArrayRef<uint8_t> Bytes, OpRef Va, OpRef Vb,
1536 MVT ByteTy = getSingleVT(MVT::i8);
1538 const SDLoc &dl(
Results.InpNode);
1539 SDValue
B = getVectorConstant(Bytes, dl);
1540 Results.push(Hexagon::V6_vd0, ByteTy, {});
1541 Results.push(Hexagon::V6_veqb, BoolTy, {OpRef(
B), OpRef::res(-1)});
1542 Results.push(Hexagon::V6_vmux, ByteTy, {OpRef::res(-1), Vb, Va});
1543 return OpRef::res(
Results.top());
1546OpRef HvxSelector::vmuxp(ArrayRef<uint8_t> Bytes, OpRef Va, OpRef Vb,
1549 size_t S = Bytes.
size() / 2;
1555OpRef HvxSelector::shuffs1(ShuffleMask SM, OpRef Va, ResultStack &
Results) {
1557 unsigned VecLen = SM.Mask.
size();
1560 assert(
all_of(SM.Mask, [
this](
int M) { return M == -1 || M < int(HwLen); }));
1565 return OpRef::undef(getSingleVT(MVT::i8));
1568 if (
auto Dist = rotationDistance(SM, VecLen)) {
1569 OpRef Rotate = funnels(Va, Va, *Dist,
Results);
1570 if (Rotate.isValid())
1573 unsigned HalfLen = HwLen / 2;
1578 std::pair<int, unsigned> Strip1 =
findStrip(SM.Mask, 1, HalfLen);
1579 if ((Strip1.first & ~HalfLen) == 0 && Strip1.second == HalfLen) {
1580 std::pair<int, unsigned> Strip2 =
1582 if (Strip1 == Strip2) {
1583 const SDLoc &dl(
Results.InpNode);
1584 Results.push(Hexagon::A2_tfrsi, MVT::i32, {getConst32(HalfLen, dl)});
1585 Results.push(Hexagon::V6_vshuffvdd, getPairVT(MVT::i8),
1586 {Va, Va, OpRef::res(
Results.top())});
1587 OpRef S = OpRef::res(
Results.top());
1588 return (Strip1.first == 0) ? OpRef::lo(S) : OpRef::
hi(S);
1592 OpRef
P = perfect(SM, Va,
Results);
1595 return butterfly(SM, Va,
Results);
1598OpRef HvxSelector::shuffs2(ShuffleMask SM, OpRef Va, OpRef Vb,
1602 return OpRef::undef(getSingleVT(MVT::i8));
1604 OpRef
C = contracting(SM, Va, Vb,
Results);
1608 int VecLen = SM.Mask.
size();
1610 OpRef
P = packs(SM, Va, Vb,
Results, PackedMask);
1612 return shuffs1(ShuffleMask(PackedMask),
P,
Results);
1620 OpRef
L = shuffs1(ShuffleMask(MaskL), Va,
Results);
1621 OpRef
R = shuffs1(ShuffleMask(MaskR), Vb,
Results);
1622 if (!
L.isValid() || !
R.isValid())
1623 return OpRef::fail();
1625 SmallVector<uint8_t, 128> Bytes(VecLen);
1626 for (
int I = 0;
I != VecLen; ++
I) {
1630 return vmuxs(Bytes, L, R,
Results);
1633OpRef HvxSelector::shuffp1(ShuffleMask SM, OpRef Va, ResultStack &
Results) {
1635 int VecLen = SM.Mask.
size();
1640 return OpRef::undef(getPairVT(MVT::i8));
1643 OpRef
P = packs(SM, OpRef::lo(Va), OpRef::hi(Va),
Results, PackedMask);
1645 ShuffleMask PM(PackedMask);
1652 if (
L.isValid() &&
H.isValid())
1662 OpRef
R = perfect(SM, Va,
Results);
1668 OpRef
L = shuffs2(SM.lo(), OpRef::lo(Va), OpRef::hi(Va),
Results);
1669 OpRef
H = shuffs2(SM.hi(), OpRef::lo(Va), OpRef::hi(Va),
Results);
1670 if (
L.isValid() &&
H.isValid())
1673 return OpRef::fail();
1676OpRef HvxSelector::shuffp2(ShuffleMask SM, OpRef Va, OpRef Vb,
1680 return OpRef::undef(getPairVT(MVT::i8));
1682 int VecLen = SM.Mask.
size();
1684 OpRef
P = packp(SM, Va, Vb,
Results, PackedMask);
1686 return shuffp1(ShuffleMask(PackedMask),
P,
Results);
1691 OpRef
L = shuffp1(ShuffleMask(MaskL), Va,
Results);
1692 OpRef
R = shuffp1(ShuffleMask(MaskR), Vb,
Results);
1693 if (!
L.isValid() || !
R.isValid())
1694 return OpRef::fail();
1698 for (
int I = 0;
I != VecLen; ++
I) {
1702 return vmuxp(Bytes, L, R,
Results);
1706 struct Deleter :
public SelectionDAG::DAGNodeDeletedListener {
1707 template <
typename T>
1708 Deleter(SelectionDAG &
D,
T &
C)
1709 : SelectionDAG::DAGNodeDeletedListener(
D, [&
C] (SDNode *
N, SDNode *
E) {
1714 template <
typename T>
1715 struct NullifyingVector :
public T {
1716 DenseMap<SDNode*, SDNode**> Refs;
1717 NullifyingVector(
T &&V) :
T(
V) {
1718 for (
unsigned i = 0, e = T::size(); i !=
e; ++i) {
1719 SDNode *&
N = T::operator[](i);
1725 if (
F != Refs.
end())
1726 *
F->second =
nullptr;
1731void HvxSelector::select(SDNode *ISelN) {
1748 DAG.RemoveDeadNodes();
1750 SetVector<SDNode *> SubNodes;
1759 if (SubNodes.
empty()) {
1760 ISel.ReplaceNode(ISelN, N0);
1767 SetVector<SDNode*> Dom, NonDom;
1770 auto IsDomRec = [&Dom, &NonDom] (SDNode *
T,
auto Rec) ->
bool {
1773 if (
T->use_empty() || NonDom.
count(
T))
1775 for (SDNode *U :
T->users()) {
1787 auto IsDom = [&IsDomRec] (SDNode *
T) {
return IsDomRec(
T, IsDomRec); };
1790 for (
unsigned I = 0;
I != SubNodes.
size(); ++
I) {
1791 for (SDValue
Op : SubNodes[
I]->
ops()) {
1792 SDNode *
O =
Op.getNode();
1799 SetVector<SDNode*> TmpQ;
1801 std::map<SDNode *, unsigned> OpCount;
1802 for (SDNode *
T : Dom) {
1803 unsigned NumDomOps =
llvm::count_if(
T->ops(), [&Dom](
const SDUse &U) {
1804 return Dom.count(U.getNode());
1807 OpCount.insert({
T, NumDomOps});
1812 for (
unsigned I = 0;
I != TmpQ.
size(); ++
I) {
1813 SDNode *S = TmpQ[
I];
1814 for (SDNode *U : S->
users()) {
1817 auto F = OpCount.find(U);
1819 if (
F->second > 0 && !--
F->second)
1825 ISel.ReplaceNode(ISelN, N0);
1828 NullifyingVector<
decltype(TmpQ)::vector_type>
Queue(TmpQ.
takeVector());
1830 Deleter DUQ(DAG, Queue);
1831 for (SDNode *S :
reverse(Queue)) {
1839bool HvxSelector::scalarizeShuffle(ArrayRef<int> Mask,
const SDLoc &dl,
1840 MVT ResTy, SDValue Va, SDValue Vb,
1844 assert(ElemTy == MVT::i8);
1845 unsigned VecLen =
Mask.size();
1846 bool HavePairs = (2*HwLen == VecLen);
1847 MVT SingleTy = getSingleVT(MVT::i8);
1863 LLVMContext &Ctx = *DAG.getContext();
1864 MVT LegalTy =
Lower.getTypeToTransformTo(Ctx, ElemTy).getSimpleVT();
1865 for (
int I : Mask) {
1867 Ops.push_back(ISel.selectUndef(dl, LegalTy));
1880 Vec = DAG.getTargetExtractSubreg(Hexagon::vsub_lo, dl, SingleTy, Vec);
1882 Vec = DAG.getTargetExtractSubreg(Hexagon::vsub_hi, dl, SingleTy, Vec);
1886 SDValue
Idx = DAG.getConstant(M, dl, MVT::i32);
1888 SDValue
L =
Lower.LowerOperation(Ex, DAG);
1894 if (2*HwLen == VecLen) {
1895 SDValue
B0 = DAG.getBuildVector(SingleTy, dl, {
Ops.data(), HwLen});
1896 SDValue L0 =
Lower.LowerOperation(B0, DAG);
1897 SDValue
B1 = DAG.getBuildVector(SingleTy, dl, {
Ops.data()+HwLen, HwLen});
1898 SDValue L1 =
Lower.LowerOperation(B1, DAG);
1905 SDValue BV = DAG.getBuildVector(ResTy, dl,
Ops);
1906 LV =
Lower.LowerOperation(BV, DAG);
1911 ISel.ReplaceNode(
N,
IS.getNode());
1912 select(
IS.getNode());
1913 DAG.RemoveDeadNodes();
1920 unsigned Impossible = ~(1u << Width) + 1;
1921 for (
unsigned I = 0, E = Bs.
size();
I != E; ++
I) {
1925 if (~Impossible == 0)
1927 for (
unsigned Log = 0; Log != Width; ++Log) {
1928 if (Impossible & (1u << Log))
1932 Impossible |= (1u << Log);
1940 for (
unsigned BitIdx = 0; BitIdx != Width; ++BitIdx) {
1942 for (
int i = 0, e = SM.Mask.
size(); i != e; ++i) {
1945 BitValues[i] = 0xff;
1947 BitValues[i] = (M & (1u << BitIdx)) != 0;
1949 Worklist[BitIdx] = possibilities(BitValues, Width);
1991 for (
unsigned I = 0, E = Sorted.
size();
I != E;) {
1992 unsigned P = Sorted[
I],
Count = 1;
1993 while (++
I != E &&
P == Sorted[
I])
2011 for (
unsigned I = 0;
I != Width; ++
I) {
2019 for (
unsigned J =
I + 1; J != Width; ++J) {
2033 assert(OrAll == (1u << Width) -1);
2041 std::optional<int> Dist;
2042 for (
int I = 0, E = SM.Mask.
size();
I != E; ++
I) {
2047 if ((
I + *Dist) %
static_cast<int>(WrapAt) != M)
2048 return std::nullopt;
2055 Dist = *Dist + WrapAt;
2061OpRef HvxSelector::contracting(ShuffleMask SM, OpRef Va, OpRef Vb,
2064 if (!Va.isValid() || !Vb.isValid())
2065 return OpRef::fail();
2076 int VecLen = SM.Mask.
size();
2079 if (
auto Dist = rotationDistance(SM, 2 * VecLen)) {
2080 OpRef Funnel = funnels(Va, Vb, *Dist,
Results);
2081 if (Funnel.isValid())
2085 MVT SingleTy = getSingleVT(MVT::i8);
2086 MVT
PairTy = getPairVT(MVT::i8);
2088 auto same = [](ArrayRef<int> Mask1, ArrayRef<int> Mask2) ->
bool {
2089 return Mask1 == Mask2;
2092 using PackConfig = std::pair<unsigned, bool>;
2093 PackConfig Packs[] = {
2101 unsigned Opcodes[] = {
2102 Hexagon::V6_vpackeb,
2103 Hexagon::V6_vpackob,
2104 Hexagon::V6_vpackeh,
2105 Hexagon::V6_vpackoh,
2107 for (
int i = 0, e = std::size(Opcodes); i !=
e; ++i) {
2108 auto [
Size, Odd] = Packs[i];
2110 Results.push(Opcodes[i], SingleTy, {Vb, Va});
2111 return OpRef::res(
Results.top());
2117 unsigned Opcodes[] = {
2118 Hexagon::V6_vshuffeb,
2119 Hexagon::V6_vshuffob,
2120 Hexagon::V6_vshufeh,
2121 Hexagon::V6_vshufoh,
2123 for (
int i = 0, e = std::size(Opcodes); i !=
e; ++i) {
2124 auto [
Size, Odd] = Packs[i];
2126 Results.push(Opcodes[i], SingleTy, {Vb, Va});
2127 return OpRef::res(
Results.top());
2136 unsigned Opcodes[] = {
2137 Hexagon::V6_vpackeb,
2138 Hexagon::V6_vpackob,
2139 Hexagon::V6_vpackeh,
2140 Hexagon::V6_vpackoh,
2142 const SDLoc &dl(
Results.InpNode);
2144 for (
int i = 0, e = std::size(Opcodes); i !=
e; ++i) {
2145 auto [
Size, Odd] = Packs[i];
2147 Results.push(Hexagon::A2_tfrsi, MVT::i32,
2148 {getSignedConst32(-2 *
Size, dl)});
2149 Results.push(Hexagon::V6_vdealvdd,
PairTy, {Vb, Va, OpRef::res(-1)});
2151 Results.push(Opcodes[i], SingleTy,
2152 {OpRef::hi(vdeal), OpRef::lo(vdeal)});
2153 return OpRef::res(
Results.top());
2159 Results.push(Hexagon::V6_vdealb4w, SingleTy, {Vb, Va});
2160 return OpRef::res(
Results.top());
2163 return OpRef::fail();
2166OpRef HvxSelector::expanding(ShuffleMask SM, OpRef Va, ResultStack &
Results) {
2179 int VecLen = SM.Mask.
size();
2180 assert(2*HwLen ==
unsigned(VecLen) &&
"Expecting vector-pair type");
2182 std::pair<int,unsigned> Strip =
findStrip(SM.Mask, 1, VecLen);
2189 if (Strip.first != 0)
2190 return OpRef::fail();
2193 if (Strip.second != 1 && Strip.second != 2)
2194 return OpRef::fail();
2197 int L = Strip.second;
2200 for (
int I = 2*L;
I <
N;
I += 2*
L) {
2202 if (S.second !=
unsigned(L))
2203 return OpRef::fail();
2205 return OpRef::fail();
2208 for (
int I = L;
I <
N;
I += 2*
L) {
2210 if (S.first != -1 || S.second !=
unsigned(L))
2211 return OpRef::fail();
2214 unsigned Opc = Strip.second == 1 ? Hexagon::V6_vunpackub
2215 : Hexagon::V6_vunpackuh;
2217 return OpRef::res(
Results.top());
2220OpRef HvxSelector::perfect(ShuffleMask SM, OpRef Va, ResultStack &
Results) {
2229 int VecLen = SM.Mask.
size();
2231 unsigned LogLen =
Log2_32(VecLen);
2232 unsigned HwLog =
Log2_32(HwLen);
2235 assert(LogLen == HwLog || LogLen == HwLog + 1);
2236 bool HavePairs = LogLen == HwLog + 1;
2238 SmallVector<unsigned, 8> Perm(LogLen);
2322 bool InvertedPair =
false;
2323 if (HavePairs && SM.Mask[0] >=
int(HwLen)) {
2324 for (
int i = 0, e = SM.Mask.
size(); i != e; ++i) {
2326 MaskStorage[i] =
M >= int(HwLen) ?
M - HwLen :
M + HwLen;
2328 InvertedPair =
true;
2329 SM = ShuffleMask(MaskStorage);
2332 auto Comps = getPerfectCompletions(SM, LogLen);
2334 return OpRef::fail();
2336 auto Pick = completeToPerfect(Comps, LogLen);
2337 for (
unsigned I = 0;
I != LogLen; ++
I)
2365 using CycleType = SmallVector<unsigned, 8>;
2366 std::set<CycleType> Cycles;
2367 std::set<unsigned>
All;
2369 for (
unsigned I : Perm)
2374 auto canonicalize = [LogLen](
const CycleType &
C) -> CycleType {
2375 unsigned LogPos,
N =
C.size();
2376 for (LogPos = 0; LogPos !=
N; ++LogPos)
2377 if (
C[LogPos] == LogLen - 1)
2382 CycleType NewC(
C.begin() + LogPos,
C.end());
2383 NewC.append(
C.begin(),
C.begin() + LogPos);
2387 auto pfs = [](
const std::set<CycleType> &Cs,
unsigned Len) {
2392 const CycleType &
C = *Cs.begin();
2393 if (
C[0] != Len - 1)
2395 int D =
Len -
C.size();
2396 if (
D != 0 &&
D != 1)
2399 bool IsDeal =
true, IsShuff =
true;
2400 for (
unsigned I = 1;
I !=
Len -
D; ++
I) {
2401 if (
C[
I] != Len - 1 -
I)
2403 if (
C[
I] !=
I - (1 -
D))
2407 assert(!(IsDeal || IsShuff) || IsDeal != IsShuff);
2408 static unsigned Deals[] = {Hexagon::V6_vdealb, Hexagon::V6_vdealh};
2409 static unsigned Shufs[] = {Hexagon::V6_vshuffb, Hexagon::V6_vshuffh};
2410 return IsDeal ? Deals[
D] : (IsShuff ? Shufs[
D] : 0);
2413 while (!
All.empty()) {
2414 unsigned A = *
All.begin();
2418 for (
unsigned B = Perm[
A];
B !=
A;
B = Perm[
B]) {
2424 Cycles.insert(canonicalize(
C));
2427 MVT SingleTy = getSingleVT(MVT::i8);
2428 MVT
PairTy = getPairVT(MVT::i8);
2431 if (
unsigned(VecLen) == HwLen) {
2432 if (
unsigned SingleOpc = pfs(Cycles, LogLen)) {
2433 Results.push(SingleOpc, SingleTy, {Va});
2434 return OpRef::res(
Results.top());
2444 SmallVector<unsigned, 8> SwapElems;
2457 for (
const CycleType &
C : Cycles) {
2459 unsigned First = (
C[0] == LogLen - 1) ? 1 : 0;
2467 const SDLoc &dl(
Results.InpNode);
2468 OpRef Arg = HavePairs ? Va : concats(Va, OpRef::undef(SingleTy),
Results);
2470 Arg = concats(OpRef::hi(Arg), OpRef::lo(Arg),
Results);
2472 for (
unsigned I = 0,
E = SwapElems.
size();
I !=
E;) {
2473 bool IsInc =
I ==
E - 1 || SwapElems[
I] < SwapElems[
I + 1];
2474 unsigned S = (1u << SwapElems[
I]);
2476 while (++
I <
E - 1 && IsInc == (SwapElems[
I] < SwapElems[
I + 1]))
2477 S |= 1u << SwapElems[
I];
2480 S |= 1u << SwapElems[
I];
2492 Results.push(Hexagon::A2_tfrsi, MVT::i32, {getSignedConst32(SS, dl)});
2493 Res.Opc = IsInc ? Hexagon::V6_vshuffvdd : Hexagon::V6_vdealvdd;
2495 Res.Ops = {OpRef::hi(Arg), OpRef::lo(Arg), OpRef::res(-1)};
2497 Arg = OpRef::res(
Results.top());
2500 return HavePairs ? Arg : OpRef::lo(Arg);
2503OpRef HvxSelector::butterfly(ShuffleMask SM, OpRef Va, ResultStack &
Results) {
2515 MVT ResTy = getSingleVT(MVT::i8);
2516 PermNetwork::Controls
FC, RC;
2517 const SDLoc &dl(
Results.InpNode);
2518 int VecLen = SM.Mask.
size();
2520 for (
int M : SM.Mask) {
2521 if (M != -1 && M >= VecLen)
2522 return OpRef::fail();
2526 ForwardDeltaNetwork FN(SM.Mask);
2528 SDValue Ctl = getVectorConstant(FC, dl);
2529 Results.push(Hexagon::V6_vdelta, ResTy, {Va, OpRef(Ctl)});
2530 return OpRef::res(
Results.top());
2534 ReverseDeltaNetwork
RN(SM.Mask);
2536 SDValue Ctl = getVectorConstant(RC, dl);
2537 Results.push(Hexagon::V6_vrdelta, ResTy, {Va, OpRef(Ctl)});
2538 return OpRef::res(
Results.top());
2542 BenesNetwork BN(SM.Mask);
2543 if (BN.run(FC, RC)) {
2544 SDValue CtlF = getVectorConstant(FC, dl);
2545 SDValue CtlR = getVectorConstant(RC, dl);
2546 Results.push(Hexagon::V6_vdelta, ResTy, {Va, OpRef(CtlF)});
2547 Results.push(Hexagon::V6_vrdelta, ResTy,
2548 {OpRef::res(-1), OpRef(CtlR)});
2549 return OpRef::res(
Results.top());
2552 return OpRef::fail();
2555SDValue HvxSelector::getConst32(
unsigned Val,
const SDLoc &dl) {
2556 return DAG.getTargetConstant(Val, dl, MVT::i32);
2559SDValue HvxSelector::getSignedConst32(
int Val,
const SDLoc &dl) {
2560 return DAG.getSignedTargetConstant(Val, dl, MVT::i32);
2563SDValue HvxSelector::getVectorConstant(ArrayRef<uint8_t>
Data,
2566 for (uint8_t
C :
Data)
2567 Elems.
push_back(DAG.getConstant(
C, dl, MVT::i8));
2569 SDValue BV = DAG.getBuildVector(VecTy, dl, Elems);
2570 SDValue LV =
Lower.LowerOperation(BV, DAG);
2571 DAG.RemoveDeadNode(BV.
getNode());
2577 MVT ResTy =
N->getValueType(0).getSimpleVT();
2578 unsigned Idx =
N->getConstantOperandVal(1);
2584 assert(Idx == 0 || Idx == ResLen);
2586 unsigned SubReg = Idx == 0 ? Hexagon::vsub_lo : Hexagon::vsub_hi;
2594 dbgs() <<
"Starting " << __func__ <<
" on node:\n";
2597 MVT ResTy =
N->getValueType(0).getSimpleVT();
2599 assert(ResTy.isVectorOf(MVT::i8));
2602 std::vector<int> Mask(SN->getMask().begin(), SN->getMask().end());
2604 for (
int &Idx : Mask)
2605 if (Idx != -1 && Idx < 0)
2608 unsigned VecLen = Mask.size();
2609 bool HavePairs = (2*
HwLen == VecLen);
2610 assert(ResTy.getSizeInBits() / 8 == VecLen);
2615 bool UseLeft =
false, UseRight =
false;
2616 for (
unsigned I = 0;
I != VecLen; ++
I) {
2619 unsigned Idx = Mask[
I];
2628 dbgs() <<
"VecLen=" << VecLen <<
" HwLen=" <<
HwLen <<
" UseLeft="
2629 << UseLeft <<
" UseRight=" << UseRight <<
" HavePairs="
2630 << HavePairs <<
'\n';
2633 if (!UseLeft && !UseRight) {
2643 OpRef Va = OpRef::undef(ResTy);
2644 OpRef Vb = OpRef::undef(ResTy);
2647 Results.push(TargetOpcode::COPY, ResTy, {Vec0});
2648 Va = OpRef::OpRef::res(
Results.top());
2651 Results.push(TargetOpcode::COPY, ResTy, {Vec1});
2652 Vb = OpRef::res(
Results.top());
2655 OpRef Res = !HavePairs ? shuffs2(ShuffleMask(Mask), Va, Vb,
Results)
2656 : shuffp2(ShuffleMask(Mask), Va, Vb,
Results);
2658 bool Done = Res.isValid();
2661 Results.push(TargetOpcode::COPY, ResTy, {Res});
2664 Done = scalarizeShuffle(Mask,
SDLoc(
N), ResTy, Vec0, Vec1,
N);
2669 dbgs() <<
"Unhandled shuffle:\n";
2678 MVT Ty =
N->getValueType(0).getSimpleVT();
2685 unsigned S = CN->getZExtValue() %
HST.getVectorLength();
2689 NewN =
DAG.getMachineNode(Hexagon::V6_valignbi, dl, Ty,
2690 {VecV, VecV, getConst32(S, dl)});
2695 NewN =
DAG.getMachineNode(Hexagon::V6_vror, dl, Ty, {VecV, RotV});
2697 ISel.ReplaceNode(
N, NewN);
2705 N->getValueType(0), {Vv, Vu, Rt});
2706 ISel.ReplaceNode(
N, NewN);
2707 DAG.RemoveDeadNode(
N);
2710void HexagonDAGToDAGISel::PreprocessHvxISelDAG() {
2711 auto getNodes = [
this]() -> std::vector<SDNode *> {
2712 std::vector<SDNode *>
T;
2713 T.reserve(CurDAG->allnodes_size());
2714 for (
SDNode &
N : CurDAG->allnodes())
2719 ppHvxShuffleOfShuffle(getNodes());
2724 return std::hash<const void *>()(V.getNode()) +
2725 std::hash<unsigned>()(V.getResNo());
2729void HexagonDAGToDAGISel::ppHvxShuffleOfShuffle(std::vector<SDNode *> &&Nodes) {
2740 unsigned HwLen = HST->getVectorLength();
2742 struct SubVectorInfo {
2743 SubVectorInfo(
SDValue S,
unsigned H) : Src(S), HalfIdx(
H) {}
2748 using MapType = DenseMap<SDValue, unsigned>;
2750 auto getMaskElt = [&](
unsigned Idx, ShuffleVectorSDNode *Shuff0,
2751 ShuffleVectorSDNode *Shuff1,
2752 const MapType &OpMap) ->
int {
2759 ShuffleVectorSDNode *OpShuff =
Idx < HwLen ? Shuff0 : Shuff1;
2768 auto N =
static_cast<unsigned>(MaybeN);
2769 unsigned SrcBase =
N < HwLen ? OpMap.at(OpShuff->
getOperand(0))
2777 auto fold3 = [&](SDValue TopShuff, SDValue Inp,
MapType &&OpMap) -> SDValue {
2782 ArrayRef<int> TopMask =
This->getMask();
2785 assert(TopMask.
size() == S0->getMask().size() &&
2786 TopMask.
size() ==
S1->getMask().size());
2790 for (
unsigned I = 0;
I != HwLen; ++
I) {
2791 int MaybeM = TopMask[
I];
2794 getMaskElt(
static_cast<unsigned>(MaybeM), S0,
S1, OpMap);
2800 std::fill(FoldedMask.begin() + HwLen, FoldedMask.end(), -1);
2805 const SDLoc &dl(TopShuff);
2808 SDValue FoldedShuff =
2815 auto getSourceInfo = [](SDValue
V) -> std::optional<SubVectorInfo> {
2817 V =
V.getOperand(0);
2819 return std::nullopt;
2820 return SubVectorInfo(
V.getOperand(0),
2824 for (SDNode *
N : Nodes) {
2827 EVT ResTy =
N->getValueType(0);
2833 SDValue
V0 =
N->getOperand(0);
2834 SDValue
V1 =
N->getOperand(1);
2839 if (
V0.getValueType() != ResTy ||
V1.getValueType() != ResTy)
2844 auto V0A = getSourceInfo(
V0.getOperand(0));
2845 if (!V0A.has_value())
2847 auto V0B = getSourceInfo(
V0.getOperand(1));
2848 if (!V0B.has_value() || V0B->Src != V0A->Src)
2850 auto V1A = getSourceInfo(
V1.getOperand(0));
2851 if (!V1A.has_value() || V1A->Src != V0A->Src)
2853 auto V1B = getSourceInfo(
V1.getOperand(1));
2854 if (!V1B.has_value() || V1B->Src != V0A->Src)
2859 assert(V0A->Src.getValueType().getSizeInBits() == 16 * HwLen);
2862 {
V0.getOperand(0), V0A->HalfIdx * HwLen},
2863 {
V0.getOperand(1), V0B->HalfIdx * HwLen},
2864 {
V1.getOperand(0), V1A->HalfIdx * HwLen},
2865 {
V1.getOperand(1), V1B->HalfIdx * HwLen},
2867 SDValue NewS = fold3(SDValue(
N, 0), V0A->Src, std::move(OpMap));
2872void HexagonDAGToDAGISel::SelectHvxExtractSubvector(SDNode *
N) {
2873 HvxSelector(*
this, *CurDAG).selectExtractSubvector(
N);
2876void HexagonDAGToDAGISel::SelectHvxShuffle(SDNode *
N) {
2877 HvxSelector(*
this, *CurDAG).selectShuffle(
N);
2880void HexagonDAGToDAGISel::SelectHvxRor(SDNode *
N) {
2881 HvxSelector(*
this, *CurDAG).selectRor(
N);
2884void HexagonDAGToDAGISel::SelectHvxVAlign(SDNode *
N) {
2885 HvxSelector(*
this, *CurDAG).selectVAlign(
N);
2892 SDValue Predicate =
N->getOperand(3);
2894 SDValue Modifier =
N->getOperand(5);
2896 SDValue ImmOperand =
CurDAG->getTargetConstant(0, dl, MVT::i32);
2899 unsigned IntNo =
N->getConstantOperandVal(1);
2903 case Intrinsic::hexagon_V6_vgathermhq:
2904 case Intrinsic::hexagon_V6_vgathermhq_128B:
2905 Opcode = Hexagon::V6_vgathermhq_pseudo;
2907 case Intrinsic::hexagon_V6_vgathermwq:
2908 case Intrinsic::hexagon_V6_vgathermwq_128B:
2909 Opcode = Hexagon::V6_vgathermwq_pseudo;
2911 case Intrinsic::hexagon_V6_vgathermhwq:
2912 case Intrinsic::hexagon_V6_vgathermhwq_128B:
2913 Opcode = Hexagon::V6_vgathermhwq_pseudo;
2933 SDValue Modifier =
N->getOperand(4);
2935 SDValue ImmOperand =
CurDAG->getTargetConstant(0, dl, MVT::i32);
2938 unsigned IntNo =
N->getConstantOperandVal(1);
2942 case Intrinsic::hexagon_V6_vgathermh:
2943 case Intrinsic::hexagon_V6_vgathermh_128B:
2944 Opcode = Hexagon::V6_vgathermh_pseudo;
2946 case Intrinsic::hexagon_V6_vgathermw:
2947 case Intrinsic::hexagon_V6_vgathermw_128B:
2948 Opcode = Hexagon::V6_vgathermw_pseudo;
2950 case Intrinsic::hexagon_V6_vgathermhw:
2951 case Intrinsic::hexagon_V6_vgathermhw_128B:
2952 Opcode = Hexagon::V6_vgathermhw_pseudo;
2954 case Intrinsic::hexagon_V6_vgather_vscattermh:
2955 case Intrinsic::hexagon_V6_vgather_vscattermh_128B:
2956 Opcode = Hexagon::V6_vgather_vscatter_mh_pseudo;
2971 unsigned IID =
N->getConstantOperandVal(0);
2974 case Intrinsic::hexagon_V6_vaddcarry: {
2975 std::array<SDValue, 3>
Ops = {
2976 {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3)}};
2978 Result =
CurDAG->getMachineNode(Hexagon::V6_vaddcarry,
SDLoc(
N), VTs,
Ops);
2981 case Intrinsic::hexagon_V6_vaddcarry_128B: {
2982 std::array<SDValue, 3>
Ops = {
2983 {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3)}};
2985 Result =
CurDAG->getMachineNode(Hexagon::V6_vaddcarry,
SDLoc(
N), VTs,
Ops);
2988 case Intrinsic::hexagon_V6_vsubcarry: {
2989 std::array<SDValue, 3>
Ops = {
2990 {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3)}};
2992 Result =
CurDAG->getMachineNode(Hexagon::V6_vsubcarry,
SDLoc(
N), VTs,
Ops);
2995 case Intrinsic::hexagon_V6_vsubcarry_128B: {
2996 std::array<SDValue, 3>
Ops = {
2997 {
N->getOperand(1),
N->getOperand(2),
N->getOperand(3)}};
2999 Result =
CurDAG->getMachineNode(Hexagon::V6_vsubcarry,
SDLoc(
N), VTs,
Ops);
3013 return Opcode == Intrinsic::hexagon_V6_vabs_hf_128B ||
3014 Opcode == Intrinsic::hexagon_V6_vabs_sf_128B ||
3015 Opcode == Intrinsic::hexagon_V6_vsub_hf_hf_128B ||
3016 Opcode == Intrinsic::hexagon_V6_vadd_hf_hf_128B ||
3017 Opcode == Intrinsic::hexagon_V6_vadd_sf_hf_128B ||
3018 Opcode == Intrinsic::hexagon_V6_vsub_sf_hf_128B ||
3019 Opcode == Intrinsic::hexagon_V6_vadd_sf_sf_128B ||
3020 Opcode == Intrinsic::hexagon_V6_vsub_sf_sf_128B ||
3021 Opcode == Intrinsic::hexagon_V6_vassign_fp_128B ||
3022 Opcode == Intrinsic::hexagon_V6_vfmin_hf_128B ||
3023 Opcode == Intrinsic::hexagon_V6_vfmin_sf_128B ||
3024 Opcode == Intrinsic::hexagon_V6_vfmax_hf_128B ||
3025 Opcode == Intrinsic::hexagon_V6_vfmax_sf_128B ||
3026 Opcode == Intrinsic::hexagon_V6_vfneg_hf_128B ||
3027 Opcode == Intrinsic::hexagon_V6_vfneg_sf_128B ||
3028 Opcode == Intrinsic::hexagon_V6_vmpy_sf_hf_acc_128B ||
3029 Opcode == Intrinsic::hexagon_V6_vmpy_hf_hf_acc_128B ||
3030 Opcode == Intrinsic::hexagon_V6_vmpy_sf_hf_128B ||
3031 Opcode == Intrinsic::hexagon_V6_vmpy_hf_hf_128B ||
3032 Opcode == Intrinsic::hexagon_V6_vmpy_sf_sf_128B ||
3033 Opcode == Intrinsic::hexagon_V6_vcvt_sf_hf_128B ||
3034 Opcode == Intrinsic::hexagon_V6_vcvt_hf_h_128B ||
3035 Opcode == Intrinsic::hexagon_V6_vcvt_hf_sf_128B ||
3036 Opcode == Intrinsic::hexagon_V6_vcvt_hf_uh_128B ||
3037 Opcode == Intrinsic::hexagon_V6_vcvt_hf_b_128B ||
3038 Opcode == Intrinsic::hexagon_V6_vcvt_hf_ub_128B ||
3039 Opcode == Intrinsic::hexagon_V6_vcvt_h_hf_128B ||
3040 Opcode == Intrinsic::hexagon_V6_vcvt_b_hf_128B ||
3041 Opcode == Intrinsic::hexagon_V6_vcvt_ub_hf_128B ||
3042 Opcode == Intrinsic::hexagon_V6_vcvt_uh_hf_128B ||
3043 Opcode == Intrinsic::hexagon_V6_vdmpy_sf_hf_128B ||
3044 Opcode == Intrinsic::hexagon_V6_vdmpy_sf_hf_acc_128B;
3054 MVT ResTy =
N->getValueType(0).getSimpleVT();
3059 case Intrinsic::hexagon_V6_vadd_sf_sf_128B: {
3061 Hexagon::V6_vadd_sf,
DL, ResTy,
N->getOperand(1),
N->getOperand(2));
3062 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32,
DL,
3070 case Intrinsic::hexagon_V6_vsub_sf_sf_128B: {
3072 Hexagon::V6_vsub_sf,
DL, ResTy,
N->getOperand(1),
N->getOperand(2));
3073 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32,
DL,
3081 case Intrinsic::hexagon_V6_vadd_hf_hf_128B: {
3083 Hexagon::V6_vadd_hf,
DL, ResTy,
N->getOperand(1),
N->getOperand(2));
3084 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf16,
DL,
3092 case Intrinsic::hexagon_V6_vsub_hf_hf_128B: {
3094 Hexagon::V6_vsub_hf,
DL, ResTy,
N->getOperand(1),
N->getOperand(2));
3095 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf16,
DL,
3109 case Intrinsic::hexagon_V6_vadd_sf_hf_128B: {
3111 SDNode *SplatPseudoNode =
3112 CurDAG->getMachineNode(Hexagon::PS_vsplatih,
DL, ResTy, Const);
3114 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, ResTy,
3115 N->getOperand(1),
SDValue(SplatPseudoNode, 0));
3117 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, ResTy,
3118 N->getOperand(2),
SDValue(SplatPseudoNode, 0));
3121 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(MpyNodeOp1, 0));
3123 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(MpyNodeOp1, 0));
3125 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(MpyNodeOp2, 0));
3127 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(MpyNodeOp2, 0));
3129 SDNode *LoAddNode =
CurDAG->getMachineNode(Hexagon::V6_vadd_qf32,
DL,
3130 MVT::v32i32, LoRegOp1, LoRegOp2);
3131 SDNode *HiAddNode =
CurDAG->getMachineNode(Hexagon::V6_vadd_qf32,
DL,
3132 MVT::v32i32, HiRegOp1, HiRegOp2);
3135 Hexagon::V6_vconv_sf_qf32,
DL, MVT::v32i32,
SDValue(LoAddNode, 0));
3137 Hexagon::V6_vconv_sf_qf32,
DL, MVT::v32i32,
SDValue(HiAddNode, 0));
3140 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3141 SDValue SubRegL =
CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3142 SDValue SubRegH =
CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3144 SDValue(ConvLoNode, 0), SubRegL};
3145 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
3159 case Intrinsic::hexagon_V6_vsub_sf_hf_128B: {
3161 SDNode *SplatPseudoNode =
3162 CurDAG->getMachineNode(Hexagon::PS_vsplatih,
DL, ResTy, Const);
3164 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, ResTy,
3165 N->getOperand(1),
SDValue(SplatPseudoNode, 0));
3167 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, ResTy,
3168 N->getOperand(2),
SDValue(SplatPseudoNode, 0));
3171 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(MpyNodeOp1, 0));
3173 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(MpyNodeOp1, 0));
3175 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(MpyNodeOp2, 0));
3177 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(MpyNodeOp2, 0));
3179 SDNode *LoSubNode =
CurDAG->getMachineNode(Hexagon::V6_vsub_qf32,
DL,
3180 MVT::v32i32, LoRegOp1, LoRegOp2);
3181 SDNode *HiSubNode =
CurDAG->getMachineNode(Hexagon::V6_vsub_qf32,
DL,
3182 MVT::v32i32, HiRegOp1, HiRegOp2);
3185 Hexagon::V6_vconv_sf_qf32,
DL, MVT::v32i32,
SDValue(LoSubNode, 0));
3187 Hexagon::V6_vconv_sf_qf32,
DL, MVT::v32i32,
SDValue(HiSubNode, 0));
3190 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3191 SDValue SubRegL =
CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3192 SDValue SubRegH =
CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3194 SDValue(ConvLoNode, 0), SubRegL};
3195 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
3203 case Intrinsic::hexagon_V6_vassign_fp_128B: {
3204 SDNode *AssignNode =
CurDAG->getMachineNode(Hexagon::V6_vassign,
DL, ResTy,
3212 case Intrinsic::hexagon_V6_vmpy_hf_hf_128B: {
3214 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, MVT::v64i32,
3215 N->getOperand(1),
N->getOperand(2));
3216 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf32,
DL,
3224 case Intrinsic::hexagon_V6_vmpy_sf_sf_128B: {
3226 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_sf,
DL, ResTy,
3227 N->getOperand(1),
N->getOperand(2));
3228 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32,
DL,
3236 case Intrinsic::hexagon_V6_vmpy_sf_hf_128B: {
3238 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, ResTy,
3239 N->getOperand(1),
N->getOperand(2));
3241 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3243 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3244 SDNode *ConvLoNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32,
DL,
3245 MVT::v32i32, LoReg);
3246 SDNode *ConvHiNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32,
DL,
3247 MVT::v32i32, HiReg);
3250 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3251 SDValue SubRegL =
CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3252 SDValue SubRegH =
CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3254 SDValue(ConvLoNode, 0), SubRegL};
3255 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
3268 case Intrinsic::hexagon_V6_vmpy_hf_hf_acc_128B: {
3270 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, MVT::v64i32,
3271 N->getOperand(2),
N->getOperand(3));
3275 CurDAG->getMachineNode(Hexagon::PS_vsplatih,
DL, MVT::v64i32, Const);
3277 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, MVT::v64i32,
3278 N->getOperand(1),
SDValue(SplatConstNode, 0));
3281 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3283 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3285 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(WidenAcc, 0));
3287 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(WidenAcc, 0));
3290 Hexagon::V6_vadd_qf32,
DL, MVT::v32i32, LoWidenAcc, LoMpyNode);
3292 Hexagon::V6_vadd_qf32,
DL, MVT::v32i32, HiWidenAcc, HiMpyNode);
3295 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3296 SDValue SubRegL =
CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3297 SDValue SubRegH =
CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3299 SDValue(LoAddNode, 0), SubRegL};
3300 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
3303 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf32,
DL,
3313 case Intrinsic::hexagon_V6_vmpy_sf_hf_acc_128B: {
3315 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, ResTy,
3316 N->getOperand(2),
N->getOperand(3));
3319 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3321 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3324 Hexagon::vsub_lo,
DL, MVT::v32i32,
N->getOperand(1));
3326 Hexagon::vsub_hi,
DL, MVT::v32i32,
N->getOperand(1));
3329 Hexagon::V6_vadd_qf32_mix,
DL, MVT::v32i32, LoRegMpy, LoRegDest);
3331 Hexagon::V6_vadd_qf32_mix,
DL, MVT::v32i32, HiRegMpy, HiRegDest);
3334 Hexagon::V6_vconv_sf_qf32,
DL, MVT::v32i32,
SDValue(LoAddNode, 0));
3336 Hexagon::V6_vconv_sf_qf32,
DL, MVT::v32i32,
SDValue(HiAddNode, 0));
3339 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3340 SDValue SubRegL =
CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3341 SDValue SubRegH =
CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3343 SDValue(ConvLoNode, 0), SubRegL};
3344 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
3352 case Intrinsic::hexagon_V6_vfmin_hf_128B: {
3354 Hexagon::V6_vmin_hf,
DL, ResTy,
N->getOperand(1),
N->getOperand(2));
3360 case Intrinsic::hexagon_V6_vfmin_sf_128B: {
3362 Hexagon::V6_vmin_sf,
DL, ResTy,
N->getOperand(1),
N->getOperand(2));
3368 case Intrinsic::hexagon_V6_vfmax_hf_128B: {
3370 Hexagon::V6_vmax_hf,
DL, ResTy,
N->getOperand(1),
N->getOperand(2));
3376 case Intrinsic::hexagon_V6_vfmax_sf_128B: {
3378 Hexagon::V6_vmax_sf,
DL, ResTy,
N->getOperand(1),
N->getOperand(2));
3390 case Intrinsic::hexagon_V6_vabs_hf_128B: {
3391 if (HST.useHVXV79OpsOnly()) {
3393 SDNode *SplatPseudoNode =
3394 CurDAG->getMachineNode(Hexagon::PS_vsplatih,
DL, ResTy, Const);
3396 CurDAG->getMachineNode(Hexagon::V6_vand,
DL, ResTy,
N->getOperand(1),
3400 SDNode *AbsNode =
CurDAG->getMachineNode(Hexagon::V6_vabs_qf16_hf,
DL,
3401 ResTy,
N->getOperand(1));
3402 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf16,
DL,
3416 case Intrinsic::hexagon_V6_vabs_sf_128B: {
3417 if (HST.useHVXV79OpsOnly()) {
3419 SDNode *SplatPseudoNode =
3420 CurDAG->getMachineNode(Hexagon::PS_vsplatiw,
DL, ResTy, Const);
3422 CurDAG->getMachineNode(Hexagon::V6_vand,
DL, ResTy,
N->getOperand(1),
3426 SDNode *AbsNode =
CurDAG->getMachineNode(Hexagon::V6_vabs_qf32_sf,
DL,
3427 ResTy,
N->getOperand(1));
3428 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32,
DL,
3442 case Intrinsic::hexagon_V6_vfneg_hf_128B: {
3443 if (HST.useHVXV79OpsOnly()) {
3445 SDNode *SplatPseudoNode =
3446 CurDAG->getMachineNode(Hexagon::PS_vsplatih,
DL, ResTy, Const);
3448 CurDAG->getMachineNode(Hexagon::V6_vxor,
DL, ResTy,
N->getOperand(1),
3452 SDNode *NegNode =
CurDAG->getMachineNode(Hexagon::V6_vneg_qf16_hf,
DL,
3453 ResTy,
N->getOperand(1));
3454 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf16,
DL,
3468 case Intrinsic::hexagon_V6_vfneg_sf_128B: {
3469 if (HST.useHVXV79OpsOnly()) {
3471 SDNode *SplatPseudoNode =
3472 CurDAG->getMachineNode(Hexagon::PS_vsplatiw,
DL, ResTy, Const);
3474 CurDAG->getMachineNode(Hexagon::V6_vxor,
DL, ResTy,
N->getOperand(1),
3478 SDNode *NegNode =
CurDAG->getMachineNode(Hexagon::V6_vneg_qf32_sf,
DL,
3479 ResTy,
N->getOperand(1));
3480 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32,
DL,
3488 case Intrinsic::hexagon_V6_vcvt_hf_h_128B: {
3489 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_h,
DL, ResTy,
3497 case Intrinsic::hexagon_V6_vcvt_h_hf_128B: {
3498 if (HST.useHVXV79OpsOnly())
3501 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_h_hf_rnd,
DL,
3502 ResTy,
N->getOperand(1));
3512 case Intrinsic::hexagon_V6_vcvt_sf_hf_128B: {
3514 SDNode *SplatPseudoNode =
3515 CurDAG->getMachineNode(Hexagon::PS_vsplatih,
DL, ResTy, Const);
3517 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, ResTy,
3518 N->getOperand(1),
SDValue(SplatPseudoNode, 0));
3521 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3523 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3524 SDNode *ConvLoNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32,
DL,
3525 MVT::v32i32, LoReg);
3526 SDNode *ConvHiNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32,
DL,
3527 MVT::v32i32, HiReg);
3530 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3531 SDValue SubRegL =
CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3532 SDValue SubRegH =
CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3534 SDValue(ConvLoNode, 0), SubRegL};
3535 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
3545 case Intrinsic::hexagon_V6_vdmpy_sf_hf_128B: {
3547 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, ResTy,
3548 N->getOperand(1),
N->getOperand(2));
3550 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3552 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3554 CurDAG->getMachineNode(Hexagon::V6_vadd_qf32,
DL, ResTy, LoReg, HiReg);
3556 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32,
DL,
3567 case Intrinsic::hexagon_V6_vdmpy_sf_hf_acc_128B: {
3569 CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf,
DL, ResTy,
3570 N->getOperand(2),
N->getOperand(3));
3572 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3574 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(MpyNode, 0));
3576 CurDAG->getMachineNode(Hexagon::V6_vadd_qf32,
DL, ResTy, LoReg, HiReg);
3578 CurDAG->getMachineNode(Hexagon::V6_vadd_qf32_mix,
DL, ResTy,
3579 SDValue(AddNode, 0),
N->getOperand(1));
3580 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32,
DL,
3590 case Intrinsic::hexagon_V6_vcvt_b_hf_128B: {
3591 if (HST.useHVXV79OpsOnly())
3594 SDNode *ConvOp1Node =
CurDAG->getMachineNode(Hexagon::V6_vconv_h_hf_rnd,
3595 DL, ResTy,
N->getOperand(1));
3596 SDNode *ConvOp2Node =
CurDAG->getMachineNode(Hexagon::V6_vconv_h_hf_rnd,
3597 DL, ResTy,
N->getOperand(2));
3598 SDNode *PackNode =
CurDAG->getMachineNode(Hexagon::V6_vpackhb_sat,
DL,
3599 ResTy,
SDValue(ConvOp2Node, 0),
3601 SDNode *ShuffNode =
CurDAG->getMachineNode(Hexagon::V6_vshuffh,
DL, ResTy,
3612 case Intrinsic::hexagon_V6_vcvt_ub_hf_128B: {
3613 if (HST.useHVXV79OpsOnly())
3616 SDNode *ConvOp1Node =
CurDAG->getMachineNode(Hexagon::V6_vconv_h_hf_rnd,
3617 DL, ResTy,
N->getOperand(1));
3618 SDNode *ConvOp2Node =
CurDAG->getMachineNode(Hexagon::V6_vconv_h_hf_rnd,
3619 DL, ResTy,
N->getOperand(2));
3620 SDNode *PackNode =
CurDAG->getMachineNode(Hexagon::V6_vpackhub_sat,
DL,
3621 ResTy,
SDValue(ConvOp2Node, 0),
3623 SDNode *ShuffNode =
CurDAG->getMachineNode(Hexagon::V6_vshuffh,
DL, ResTy,
3635 case Intrinsic::hexagon_V6_vcvt_hf_sf_128B: {
3636 if (HST.useHVXV79OpsOnly()) {
3637 SDNode *ZeroNode =
CurDAG->getMachineNode(Hexagon::V6_vd0,
DL, ResTy);
3639 CurDAG->getMachineNode(Hexagon::V6_vadd_sf,
DL, ResTy,
3640 N->getOperand(1),
SDValue(ZeroNode, 0));
3642 CurDAG->getMachineNode(Hexagon::V6_vadd_sf,
DL, ResTy,
3643 N->getOperand(2),
SDValue(ZeroNode, 0));
3646 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3648 CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3650 CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3652 SDValue(AddOp1Node, 0), SubRegL};
3653 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
3655 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf32,
DL,
3659 SDNode *ConvOp1Node =
CurDAG->getMachineNode(Hexagon::V6_vconv_qf32_sf,
3660 DL, ResTy,
N->getOperand(1));
3661 SDNode *ConvOp2Node =
CurDAG->getMachineNode(Hexagon::V6_vconv_qf32_sf,
3662 DL, ResTy,
N->getOperand(2));
3664 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3666 CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3668 CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3670 SDValue(ConvOp1Node, 0), SubRegL};
3671 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
3673 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf32,
DL,
3688 case Intrinsic::hexagon_V6_vcvt_hf_uh_128B: {
3689 if (HST.useHVXV79OpsOnly()) {
3690 SDNode *ZeroNode =
CurDAG->getMachineNode(Hexagon::V6_vd0,
DL, ResTy);
3693 MVT::v64i32,
N->getOperand(1));
3696 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(ZExtNode, 0));
3698 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(ZExtNode, 0));
3701 CurDAG->getMachineNode(Hexagon::V6_vconv_sf_w,
DL, ResTy, LoReg);
3703 CurDAG->getMachineNode(Hexagon::V6_vconv_sf_w,
DL, ResTy, HiReg);
3706 CurDAG->getMachineNode(Hexagon::V6_vadd_sf,
DL, ResTy,
3709 CurDAG->getMachineNode(Hexagon::V6_vadd_sf,
DL, ResTy,
3713 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3715 CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3717 CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3719 SDValue(WidenAddLoNode, 0), SubRegL};
3720 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
3722 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf32,
DL,
3728 MVT::v64i32,
N->getOperand(1));
3731 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(ZExtNode, 0));
3733 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(ZExtNode, 0));
3736 CurDAG->getMachineNode(Hexagon::V6_vconv_sf_w,
DL, ResTy, LoReg);
3738 CurDAG->getMachineNode(Hexagon::V6_vconv_sf_w,
DL, ResTy, HiReg);
3741 Hexagon::V6_vconv_qf32_sf,
DL, ResTy,
SDValue(ConvLoNode, 0));
3743 Hexagon::V6_vconv_qf32_sf,
DL, ResTy,
SDValue(ConvHiNode, 0));
3746 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3748 CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3750 CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3752 SDValue(ConvLoQFNode, 0), SubRegL};
3753 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
3755 SDNode *ConvNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf32,
DL,
3772 case Intrinsic::hexagon_V6_vcvt_uh_hf_128B: {
3773 if (HST.useHVXV79OpsOnly())
3777 SDValue HalfConst =
CurDAG->getTargetConstant(0x38003800U,
DL, MVT::i32);
3779 CurDAG->getMachineNode(Hexagon::A2_tfrsi,
DL, MVT::i32, HalfConst);
3782 CurDAG->getTargetConstant(0x77FFU,
DL, MVT::i32);
3785 CurDAG->getMachineNode(Hexagon::A2_tfrsi,
DL, MVT::i32, ShiftConst);
3787 SDValue UnderInfConst =
CurDAG->getTargetConstant(0x7BFFU,
DL, MVT::i32);
3789 SDNode *ZeroNode =
CurDAG->getMachineNode(Hexagon::V6_vd0,
DL, ResTy);
3792 CurDAG->getMachineNode(Hexagon::V6_vmpy_rt_hf,
DL, ResTy,
3793 N->getOperand(1),
SDValue(HalfConstNode, 0));
3796 Hexagon::V6_vconv_h_hf_rnd,
DL, ResTy,
N->getOperand(1));
3799 SDNode *ConvHFNode =
CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf16,
DL,
3803 Hexagon::V6_vmax_hf,
DL, ResTy,
SDValue(ZeroNode, 0),
3808 Hexagon::PS_vsplatih,
DL, ResTy, Before2Power15Const);
3811 Hexagon::V6_vconv_h_hf_rnd,
DL, ResTy,
SDValue(ConvHFNode, 0));
3816 CurDAG->getMachineNode(Hexagon::V6_vgthf,
DL, ResTy,
3817 SDValue(SplatPseudoNode, 0),
N->getOperand(1));
3820 Hexagon::V6_vaslh,
DL, ResTy,
SDValue(ConvMpyNode, 0),
3823 SDNode *SplatInfNode =
CurDAG->getMachineNode(Hexagon::PS_vsplatih,
DL,
3824 ResTy, UnderInfConst);
3828 Hexagon::V6_vgthf_or,
DL, ResTy,
SDValue(CmpNode, 0),
3829 N->getOperand(1),
SDValue(SplatInfNode, 0));
3834 Hexagon::V6_vmux,
DL, ResTy,
SDValue(OrCmpNode, 0),
3845 case Intrinsic::hexagon_V6_vcvt_hf_b_128B: {
3848 CurDAG->getMachineNode(Hexagon::V6_vdealh,
DL, ResTy,
N->getOperand(1));
3850 SDNode *UnpackNode =
CurDAG->getMachineNode(Hexagon::V6_vunpackb,
DL, ResTy,
3854 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(UnpackNode, 0));
3856 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(UnpackNode, 0));
3859 CurDAG->getMachineNode(Hexagon::V6_vconv_hf_h,
DL, MVT::v32i32, LoReg);
3861 CurDAG->getMachineNode(Hexagon::V6_vconv_hf_h,
DL, MVT::v32i32, HiReg);
3864 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3865 SDValue SubRegL =
CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3866 SDValue SubRegH =
CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3868 SDValue(ConvLoNode, 0), SubRegL};
3869 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
3880 case Intrinsic::hexagon_V6_vcvt_hf_ub_128B: {
3883 CurDAG->getMachineNode(Hexagon::V6_vdealh,
DL, ResTy,
N->getOperand(1));
3885 SDNode *UnpackNode =
CurDAG->getMachineNode(Hexagon::V6_vunpackub,
DL,
3889 Hexagon::vsub_lo,
DL, MVT::v32i32,
SDValue(UnpackNode, 0));
3891 Hexagon::vsub_hi,
DL, MVT::v32i32,
SDValue(UnpackNode, 0));
3894 CurDAG->getMachineNode(Hexagon::V6_vconv_hf_h,
DL, MVT::v32i32, LoReg);
3896 CurDAG->getMachineNode(Hexagon::V6_vconv_hf_h,
DL, MVT::v32i32, HiReg);
3899 CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID,
DL, MVT::i32);
3900 SDValue SubRegL =
CurDAG->getTargetConstant(Hexagon::vsub_lo,
DL, MVT::i32);
3901 SDValue SubRegH =
CurDAG->getTargetConstant(Hexagon::vsub_hi,
DL, MVT::i32);
3903 SDValue(ConvLoNode, 0), SubRegL};
3904 SDNode *RS =
CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
DL,
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
ReachingDefInfo InstSet InstSet & Ignore
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static void fail(const SDLoc &DL, SelectionDAG &DAG, const Twine &Msg, SDValue Val={})
This file implements the BitVector class.
static constexpr unsigned long long mask(BlockVerifier::State S)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
const HexagonInstrInfo * TII
static bool isIdentity(ArrayRef< int > Mask)
static std::pair< int, unsigned > findStrip(ArrayRef< int > A, int Inc, unsigned MaxLen)
static const HexagonSubtarget & getHexagonSubtarget(SelectionDAG &G)
static void splitMask(ArrayRef< int > Mask, MutableArrayRef< int > MaskL, MutableArrayRef< int > MaskR)
static void packSegmentMask(ArrayRef< int > Mask, ArrayRef< unsigned > OutSegMap, unsigned SegLen, MutableArrayRef< int > PackedMask)
static SmallVector< unsigned, 4 > getInputSegmentList(ShuffleMask SM, unsigned SegLen)
static const HexagonTargetLowering & getHexagonLowering(SelectionDAG &G)
static SmallVector< unsigned, 4 > getOutputSegmentMap(ShuffleMask SM, unsigned SegLen)
static bool isLowHalfOnly(ArrayRef< int > Mask)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
print mir2vec MIR2Vec Vocabulary Printer Pass
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
static bool isUndef(const MachineInstr &MI)
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
static LLVM_ATTRIBUTE_ALWAYS_INLINE MVT::SimpleValueType getSimpleVT(const uint8_t *MatcherTable, size_t &MatcherIndex)
getSimpleVT - Decode a value in MatcherTable, if it's a VBR encoded value, use GetVBR to decode it.
This file implements a set that has insertion order iteration characteristics.
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
Get the array size.
ArrayRef< T > take_back(size_t N=1) const
Return a copy of *this with only the last N elements.
BitVector & set()
Set all bits in the bitvector.
iterator_range< const_set_bits_iterator > set_bits() const
iterator find(const_arg_type_t< KeyT > Val)
Tagged union holding either a T or a Error.
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW=nullptr, bool ShouldPreserveUseListOrder=false, bool IsForDebug=false) const
Print the function to an output stream with an optional AssemblyAnnotationWriter.
bool isIEEEHVXIntrinsic(unsigned)
void translateIEEEIntrinsicToQFloat(SDNode *N, unsigned &Opcode)
void SelectV65GatherPred(SDNode *N)
void SelectV65Gather(SDNode *N)
void SelectHVXDualOutput(SDNode *N)
unsigned getVectorNumElements() const
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
A description of a memory reference used in the backend.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
A NodeSet contains a set of SUnit DAG nodes with additional information that assigns a priority to th...
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
LLVM_ABI void dump() const
Dump this node, for debugging.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
LLVM_ABI void dumpr() const
Dump (recursively) this node and its use-def subgraph.
const SDValue & getOperand(unsigned Num) const
LLVM_ABI void print(raw_ostream &OS, const SelectionDAG *G=nullptr) const
iterator_range< user_iterator > users()
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
size_type count(const_arg_type key) const
Count the number of elements of a given key in the SetVector.
Vector takeVector()
Clear the SetVector and return the underlying vector.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
int getMaskElt(unsigned Idx) const
static void commuteMask(MutableArrayRef< int > Mask)
Change values in a shuffle permute mask assuming the two vector operands have swapped position.
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
NodeAddr< NodeBase * > Node
LLVM_ABI iterator begin() const
Type * getValueType(Value *V, bool ReVec, bool LookThroughCmp)
Returns the "element type" of the given value/instruction V.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
constexpr NextUseDistance min(NextUseDistance A, NextUseDistance B)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
@ Sub
Subtraction of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr int32_t SignExtend32(uint32_t X)
Sign-extend the number in the bottom B bits of X to a 32-bit integer.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
MaskT vshuffvdd(ArrayRef< int > Vu, ArrayRef< int > Vv, unsigned Rt)
MaskT vpack(ArrayRef< int > Vu, ArrayRef< int > Vv, unsigned Size, bool TakeOdd)
ArrayRef< int > hi(ArrayRef< int > Vuu)
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT
MaskT vshuff(ArrayRef< int > Vu, ArrayRef< int > Vv, unsigned Size, bool TakeOdd)
MaskT vdealb4w(ArrayRef< int > Vu, ArrayRef< int > Vv)
SmallVector< int, 128 > MaskT
MaskT vdeal(ArrayRef< int > Vu, ArrayRef< int > Vv, unsigned Size, bool TakeOdd)
ArrayRef< int > lo(ArrayRef< int > Vuu)
MaskT vdealvdd(ArrayRef< int > Vu, ArrayRef< int > Vv, unsigned Rt)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
HvxSelector(HexagonDAGToDAGISel &HS, SelectionDAG &G)
MVT getSingleVT(MVT ElemTy) const
static SmallVector< uint32_t, 8 > completeToPerfect(ArrayRef< uint32_t > Completions, unsigned Width)
HexagonDAGToDAGISel & ISel
const HexagonTargetLowering & Lower
void selectVAlign(SDNode *N)
void selectExtractSubvector(SDNode *N)
void selectRor(SDNode *N)
void selectShuffle(SDNode *N)
static SmallVector< uint32_t, 8 > getPerfectCompletions(ShuffleMask SM, unsigned Width)
MVT getPairVT(MVT ElemTy) const
const HexagonSubtarget & HST
static std::optional< int > rotationDistance(ShuffleMask SM, unsigned WrapAt)
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
std::size_t operator()(SDValue V) const