OSDN Git Service

[Hexagon] Emit better 32-bit multiplication sequence for HVXv62+
authorKrzysztof Parzyszek <kparzysz@quicinc.com>
Thu, 27 Aug 2020 20:16:39 +0000 (15:16 -0500)
committerKrzysztof Parzyszek <kparzysz@quicinc.com>
Thu, 27 Aug 2020 20:24:32 +0000 (15:24 -0500)
llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
llvm/test/CodeGen/Hexagon/autohvx/arith.ll

index 254e5a8..ed70172 100644 (file)
@@ -1464,16 +1464,29 @@ HexagonTargetLowering::LowerHvxMul(SDValue Op, SelectionDAG &DAG) const {
       // 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;
@@ -1520,7 +1533,7 @@ HexagonTargetLowering::LowerHvxMulh(SDValue Op, SelectionDAG &DAG) const {
   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
@@ -1547,6 +1560,20 @@ HexagonTargetLowering::LowerHvxMulh(SDValue Op, SelectionDAG &DAG) const {
     // 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?)
index f7b4033..99e287d 100644 (file)
@@ -252,25 +252,43 @@ define <64 x i16> @mpyh_128(<64 x i16> %v0, <64 x i16> %v1) #1 {
   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" }