Skip to content

Commit 00de79a

Browse files
Rajveer100tomtor
authored andcommitted
[AArch64] Extend usage of XAR instruction for fixed-length operations (llvm#139460)
1 parent 7c18a1e commit 00de79a

File tree

2 files changed

+324
-28
lines changed

2 files changed

+324
-28
lines changed

llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp

Lines changed: 86 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4606,7 +4606,33 @@ bool AArch64DAGToDAGISel::trySelectXAR(SDNode *N) {
46064606
return false;
46074607
}
46084608

4609-
if (!Subtarget->hasSHA3())
4609+
// We have Neon SHA3 XAR operation for v2i64 but for types
4610+
// v4i32, v8i16, v16i8 we can use SVE operations when SVE2-SHA3
4611+
// is available.
4612+
EVT SVT;
4613+
switch (VT.getSimpleVT().SimpleTy) {
4614+
case MVT::v4i32:
4615+
case MVT::v2i32:
4616+
SVT = MVT::nxv4i32;
4617+
break;
4618+
case MVT::v8i16:
4619+
case MVT::v4i16:
4620+
SVT = MVT::nxv8i16;
4621+
break;
4622+
case MVT::v16i8:
4623+
case MVT::v8i8:
4624+
SVT = MVT::nxv16i8;
4625+
break;
4626+
case MVT::v2i64:
4627+
case MVT::v1i64:
4628+
SVT = Subtarget->hasSHA3() ? MVT::v2i64 : MVT::nxv2i64;
4629+
break;
4630+
default:
4631+
return false;
4632+
}
4633+
4634+
if ((!SVT.isScalableVector() && !Subtarget->hasSHA3()) ||
4635+
(SVT.isScalableVector() && !Subtarget->hasSVE2()))
46104636
return false;
46114637

46124638
if (N0->getOpcode() != AArch64ISD::VSHL ||
@@ -4632,41 +4658,85 @@ bool AArch64DAGToDAGISel::trySelectXAR(SDNode *N) {
46324658
SDValue Imm = CurDAG->getTargetConstant(
46334659
ShAmt, DL, N0.getOperand(1).getValueType(), false);
46344660

4635-
if (ShAmt + HsAmt != 64)
4661+
unsigned VTSizeInBits = VT.getScalarSizeInBits();
4662+
if (ShAmt + HsAmt != VTSizeInBits)
46364663
return false;
46374664

46384665
if (!IsXOROperand) {
46394666
SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i64);
46404667
SDNode *MOV =
46414668
CurDAG->getMachineNode(AArch64::MOVIv2d_ns, DL, MVT::v2i64, Zero);
46424669
SDValue MOVIV = SDValue(MOV, 0);
4670+
46434671
R1 = N1->getOperand(0);
46444672
R2 = MOVIV;
46454673
}
46464674

4647-
// If the input is a v1i64, widen to a v2i64 to use XAR.
4648-
assert((VT == MVT::v1i64 || VT == MVT::v2i64) && "Unexpected XAR type!");
4649-
if (VT == MVT::v1i64) {
4650-
EVT SVT = MVT::v2i64;
4675+
if (SVT != VT) {
46514676
SDValue Undef =
4652-
SDValue(CurDAG->getMachineNode(AArch64::IMPLICIT_DEF, DL, SVT), 0);
4653-
SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub, DL, MVT::i32);
4677+
SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, SVT), 0);
4678+
4679+
if (SVT.isScalableVector() && VT.is64BitVector()) {
4680+
EVT QVT = VT.getDoubleNumVectorElementsVT(*CurDAG->getContext());
4681+
4682+
SDValue UndefQ = SDValue(
4683+
CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, QVT), 0);
4684+
SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub, DL, MVT::i32);
4685+
4686+
R1 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG, DL, QVT,
4687+
UndefQ, R1, DSub),
4688+
0);
4689+
if (R2.getValueType() == VT)
4690+
R2 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG, DL, QVT,
4691+
UndefQ, R2, DSub),
4692+
0);
4693+
}
4694+
4695+
SDValue SubReg = CurDAG->getTargetConstant(
4696+
(SVT.isScalableVector() ? AArch64::zsub : AArch64::dsub), DL, MVT::i32);
4697+
46544698
R1 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG, DL, SVT, Undef,
4655-
R1, DSub),
4699+
R1, SubReg),
46564700
0);
4657-
if (R2.getValueType() == MVT::v1i64)
4701+
4702+
if (SVT.isScalableVector() || R2.getValueType() != SVT)
46584703
R2 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG, DL, SVT,
4659-
Undef, R2, DSub),
4704+
Undef, R2, SubReg),
46604705
0);
46614706
}
46624707

46634708
SDValue Ops[] = {R1, R2, Imm};
4664-
SDNode *XAR = CurDAG->getMachineNode(AArch64::XAR, DL, MVT::v2i64, Ops);
4709+
SDNode *XAR = nullptr;
4710+
4711+
if (SVT.isScalableVector()) {
4712+
if (auto Opc = SelectOpcodeFromVT<SelectTypeKind::Int>(
4713+
SVT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
4714+
AArch64::XAR_ZZZI_D}))
4715+
XAR = CurDAG->getMachineNode(Opc, DL, SVT, Ops);
4716+
} else {
4717+
XAR = CurDAG->getMachineNode(AArch64::XAR, DL, SVT, Ops);
4718+
}
46654719

4666-
if (VT == MVT::v1i64) {
4667-
SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub, DL, MVT::i32);
4668-
XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG, DL, VT,
4669-
SDValue(XAR, 0), DSub);
4720+
assert(XAR && "Unexpected NULL value for XAR instruction in DAG");
4721+
4722+
if (SVT != VT) {
4723+
if (VT.is64BitVector() && SVT.isScalableVector()) {
4724+
EVT QVT = VT.getDoubleNumVectorElementsVT(*CurDAG->getContext());
4725+
4726+
SDValue ZSub = CurDAG->getTargetConstant(AArch64::zsub, DL, MVT::i32);
4727+
SDNode *Q = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG, DL, QVT,
4728+
SDValue(XAR, 0), ZSub);
4729+
4730+
SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub, DL, MVT::i32);
4731+
XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG, DL, VT,
4732+
SDValue(Q, 0), DSub);
4733+
} else {
4734+
SDValue SubReg = CurDAG->getTargetConstant(
4735+
(SVT.isScalableVector() ? AArch64::zsub : AArch64::dsub), DL,
4736+
MVT::i32);
4737+
XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG, DL, VT,
4738+
SDValue(XAR, 0), SubReg);
4739+
}
46704740
}
46714741
ReplaceNode(N, XAR);
46724742
return true;

0 commit comments

Comments
 (0)