// V6_vmpybv.)
return getInstr(Hexagon::V6_vmpyih, dl, ResTy, {Vs, Vt}, DAG);
case MVT::i32: {
- // Use the following sequence for signed word multiply:
- // T0 = V6_vmpyiowh Vs, Vt
- // T1 = V6_vaslw T0, 16
- // T2 = V6_vmpyiewuh_acc T1, Vs, Vt
- SDValue S16 = DAG.getConstant(16, dl, MVT::i32);
- SDValue T0 = getInstr(Hexagon::V6_vmpyiowh, dl, ResTy, {Vs, Vt}, DAG);
- SDValue T1 = getInstr(Hexagon::V6_vaslw, dl, ResTy, {T0, S16}, DAG);
- SDValue T2 = getInstr(Hexagon::V6_vmpyiewuh_acc, dl, ResTy,
- {T1, Vs, Vt}, DAG);
- return T2;
+ auto MulL_V60 = [&](SDValue Vs, SDValue Vt) {
+ // Use the following sequence for signed word multiply:
+ // T0 = V6_vmpyiowh Vs, Vt
+ // T1 = V6_vaslw T0, 16
+ // T2 = V6_vmpyiewuh_acc T1, Vs, Vt
+ SDValue S16 = DAG.getConstant(16, dl, MVT::i32);
+ SDValue T0 = getInstr(Hexagon::V6_vmpyiowh, dl, ResTy, {Vs, Vt}, DAG);
+ SDValue T1 = getInstr(Hexagon::V6_vaslw, dl, ResTy, {T0, S16}, DAG);
+ SDValue T2 = getInstr(Hexagon::V6_vmpyiewuh_acc, dl, ResTy,
+ {T1, Vs, Vt}, DAG);
+ return T2;
+ };
+ auto MulL_V62 = [&](SDValue Vs, SDValue Vt) {
+ MVT PairTy = typeJoin({ResTy, ResTy});
+ SDValue T0 = getInstr(Hexagon::V6_vmpyewuh_64, dl, PairTy,
+ {Vs, Vt}, DAG);
+ SDValue T1 = getInstr(Hexagon::V6_vmpyowh_64_acc, dl, PairTy,
+ {T0, Vs, Vt}, DAG);
+ return opSplit(T1, dl, DAG).first;
+ };
+ if (Subtarget.useHVXV62Ops())
+ return MulL_V62(Vs, Vt);
+ return MulL_V60(Vs, Vt);
}
default:
break;
assert(ElemTy == MVT::i32);
SDValue S16 = DAG.getConstant(16, dl, MVT::i32);
- if (IsSigned) {
+ auto MulHS_V60 = [&](SDValue Vs, SDValue Vt) {
// mulhs(Vs,Vt) =
// = [(Hi(Vs)*2^16 + Lo(Vs)) *s (Hi(Vt)*2^16 + Lo(Vt))] >> 32
// = [Hi(Vs)*2^16 *s Hi(Vt)*2^16 + Hi(Vs) *su Lo(Vt)*2^16
// Add:
SDValue T3 = DAG.getNode(ISD::ADD, dl, ResTy, {S2, T2});
return T3;
+ };
+
+ auto MulHS_V62 = [&](SDValue Vs, SDValue Vt) {
+ MVT PairTy = typeJoin({ResTy, ResTy});
+ SDValue T0 = getInstr(Hexagon::V6_vmpyewuh_64, dl, PairTy, {Vs, Vt}, DAG);
+ SDValue T1 = getInstr(Hexagon::V6_vmpyowh_64_acc, dl, PairTy,
+ {T0, Vs, Vt}, DAG);
+ return opSplit(T1, dl, DAG).second;
+ };
+
+ if (IsSigned) {
+ if (Subtarget.useHVXV62Ops())
+ return MulHS_V62(Vs, Vt);
+ return MulHS_V60(Vs, Vt);
}
// Unsigned mulhw. (Would expansion using signed mulhw be better?)
ret <64 x i16> %p
}
-; CHECK-LABEL: mpyw_64:
+; CHECK-LABEL: mpyw_64_v60:
; CHECK-DAG: r[[T00:[0-9]+]] = #16
; CHECK-DAG: v[[T01:[0-9]+]].w = vmpyio(v0.w,v1.h)
; CHECK: v[[T02:[0-9]+]].w = vasl(v[[T01]].w,r[[T00]])
; CHECK: v[[T02]].w += vmpyie(v0.w,v1.uh)
-define <16 x i32> @mpyw_64(<16 x i32> %v0, <16 x i32> %v1) #0 {
+define <16 x i32> @mpyw_64_v60(<16 x i32> %v0, <16 x i32> %v1) #0 {
%p = mul <16 x i32> %v0, %v1
ret <16 x i32> %p
}
-; CHECK-LABEL: mpyw_128:
+; CHECK-LABEL: mpyw_128_v60:
; CHECK-DAG: r[[T10:[0-9]+]] = #16
; CHECK-DAG: v[[T11:[0-9]+]].w = vmpyio(v0.w,v1.h)
; CHECK: v[[T12:[0-9]+]].w = vasl(v[[T11]].w,r[[T10]])
; CHECK: v[[T12]].w += vmpyie(v0.w,v1.uh)
-define <32 x i32> @mpyw_128(<32 x i32> %v0, <32 x i32> %v1) #1 {
+define <32 x i32> @mpyw_128_v60(<32 x i32> %v0, <32 x i32> %v1) #1 {
+ %p = mul <32 x i32> %v0, %v1
+ ret <32 x i32> %p
+}
+
+; CHECK-LABEL: mpyw_64_v62:
+; CHECK: v[[T00:[0-9]+]]:[[T01:[0-9]+]] = vmpye(v0.w,v1.uh)
+; CHECK: v[[T00]]:[[T01]] += vmpyo(v0.w,v1.h)
+define <16 x i32> @mpyw_64_v62(<16 x i32> %v0, <16 x i32> %v1) #3 {
+ %p = mul <16 x i32> %v0, %v1
+ ret <16 x i32> %p
+}
+
+; CHECK-LABEL: mpyw_128_v62:
+; CHECK: v[[T00:[0-9]+]]:[[T01:[0-9]+]] = vmpye(v0.w,v1.uh)
+; CHECK: v[[T00]]:[[T01]] += vmpyo(v0.w,v1.h)
+define <32 x i32> @mpyw_128_v62(<32 x i32> %v0, <32 x i32> %v1) #4 {
%p = mul <32 x i32> %v0, %v1
ret <32 x i32> %p
}
attributes #0 = { nounwind "target-cpu"="hexagonv60" "target-features"="+hvx,+hvx-length64b" }
attributes #1 = { nounwind "target-cpu"="hexagonv60" "target-features"="+hvx,+hvx-length128b" }
+attributes #3 = { nounwind "target-cpu"="hexagonv62" "target-features"="+hvxv62,+hvx-length64b" }
+attributes #4 = { nounwind "target-cpu"="hexagonv62" "target-features"="+hvxv62,+hvx-length128b" }