PowerPC: Optimize SPE double parameter calling setup
authorJustin Hibbits <jrh29@alumni.cwru.edu>
Sat, 15 Aug 2020 20:34:33 +0000 (21:34 +0100)
committerGianfranco Costamagna <locutusofborg@debian.org>
Sat, 15 Aug 2020 20:34:33 +0000 (21:34 +0100)
Origin: https://reviews.llvm.org/D54583
Last-Update: 2018-12-04

Gbp-Pq: Topic powerpcspe
Gbp-Pq: Name D54584-powerpcspe-double-parameter.diff

lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/PowerPC/PPCISelLowering.h
lib/Target/PowerPC/PPCInstrInfo.td
lib/Target/PowerPC/PPCInstrSPE.td
test/CodeGen/PowerPC/spe.ll

index 39608cb74bee8286294255e4338e6c1e5b72c9ee..4bb62b0816c42716726b47192bd6c224b154c4d8 100644 (file)
@@ -385,8 +385,16 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
   } else {
     setOperationAction(ISD::BITCAST, MVT::f32, Expand);
     setOperationAction(ISD::BITCAST, MVT::i32, Expand);
-    setOperationAction(ISD::BITCAST, MVT::i64, Expand);
     setOperationAction(ISD::BITCAST, MVT::f64, Expand);
+    if (Subtarget.hasSPE()) {
+      setOperationAction(ISD::BITCAST, MVT::i64, Custom);
+    } else {
+      setOperationAction(ISD::BITCAST, MVT::i64, Expand);
+    }
+  }
+
+  if (Subtarget.hasSPE()) {
+    setOperationAction(ISD::EXTRACT_ELEMENT, MVT::i64, Custom);
   }
 
   // We cannot sextinreg(i1).  Expand to shifts.
@@ -1366,6 +1374,9 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case PPCISD::QVLFSb:          return "PPCISD::QVLFSb";
   case PPCISD::BUILD_FP128:     return "PPCISD::BUILD_FP128";
   case PPCISD::EXTSWSLI:        return "PPCISD::EXTSWSLI";
+  case PPCISD::BUILD_SPE64:     return "PPCISD::BUILD_SPE64";
+  case PPCISD::EXTRACT_SPE_LO:  return "PPCISD::EXTRACT_SPE_LO";
+  case PPCISD::EXTRACT_SPE_HI:  return "PPCISD::EXTRACT_SPE_HI";
   }
   return nullptr;
 }
@@ -7886,6 +7897,15 @@ SDValue PPCTargetLowering::LowerBITCAST(SDValue Op, SelectionDAG &DAG) const {
   SDLoc dl(Op);
   SDValue Op0 = Op->getOperand(0);
 
+  if (Subtarget.hasSPE()) {
+    if (Op.getValueType() == MVT::f64 &&
+        Op0.getOpcode() == ISD::BUILD_PAIR &&
+        (Op0.getOperand(1).getValueType() == MVT::i32) &&
+        (Op0.getOperand(0).getValueType() == MVT::i32))
+      return DAG.getNode(PPCISD::BUILD_SPE64, dl, MVT::f64, Op0.getOperand(0),
+          Op0.getOperand(1));
+  }
+
   if (!EnableQuadPrecision ||
       (Op.getValueType() != MVT::f128 ) ||
       (Op0.getOpcode() != ISD::BUILD_PAIR) ||
@@ -7897,6 +7917,26 @@ SDValue PPCTargetLowering::LowerBITCAST(SDValue Op, SelectionDAG &DAG) const {
                      Op0.getOperand(1));
 }
 
+// Lower EXTRACT_ELEMENT (i64 BITCAST f64), 0/1 to evmerge*
+SDValue PPCTargetLowering::LowerEXTRACT_ELEMENT(SDValue Op, SelectionDAG &DAG) const {
+
+  SDLoc dl(Op);
+  SDValue Op0 = Op->getOperand(0);
+
+  if (!Subtarget.hasSPE())
+    return SDValue();
+
+  if (!(Op.getValueType() == MVT::i32 &&
+      Op0.getOpcode() == ISD::BITCAST))
+    return SDValue();
+
+  assert(Op0.getNumOperands() > 0 && "WTF?");
+  if (Op->getConstantOperandVal(1) == 0)
+    return DAG.getNode(PPCISD::EXTRACT_SPE_LO,  dl, MVT::i32, Op0.getOperand(0));
+
+  return DAG.getNode(PPCISD::EXTRACT_SPE_HI, dl, MVT::i32, Op0.getOperand(0));
+}
+
 // If this is a case we can't handle, return null and let the default
 // expansion code take care of it.  If we CAN select this case, and if it
 // selects to a single instruction, return Op.  Otherwise, if we can codegen
@@ -9680,6 +9720,8 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
     return LowerBSWAP(Op, DAG);
   case ISD::ATOMIC_CMP_SWAP:
     return LowerATOMIC_CMP_SWAP(Op, DAG);
+  case ISD::EXTRACT_ELEMENT:
+    return LowerEXTRACT_ELEMENT(Op, DAG);
   }
 }
 
index 30acd60eba6f4c6c245cf0d1c2e6000a4c8a9314..280261a13603e6c4fe08682c3eb550bb76c15f91 100644 (file)
@@ -196,6 +196,15 @@ namespace llvm {
       /// Direct move of 2 consective GPR to a VSX register.
       BUILD_FP128,
 
+      /// Merge 2 GPRs to a single SPE register
+      BUILD_SPE64,
+
+      /// Extract high SPE register component
+      EXTRACT_SPE_HI,
+
+      /// Extract low SPE register component
+      EXTRACT_SPE_LO,
+
       /// Extract a subvector from signed integer vector and convert to FP.
       /// It is primarily used to convert a (widened) illegal integer vector
       /// type to a legal floating point vector type.
@@ -1110,6 +1119,7 @@ namespace llvm {
     SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const;
     SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const;
     SDValue LowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
+    SDValue LowerEXTRACT_ELEMENT(SDValue Op, SelectionDAG &DAG) const;
 
     SDValue DAGCombineExtBoolTrunc(SDNode *N, DAGCombinerInfo &DCI) const;
     SDValue DAGCombineBuildVector(SDNode *N, DAGCombinerInfo &DCI) const;
index 77aa4fe3d415866e93e87ee658ba5c31d7c78129..6df07e5ac3e1b0993e43b7b4577813e309a38484 100644 (file)
@@ -231,6 +231,22 @@ def PPCbuild_fp128: SDNode<"PPCISD::BUILD_FP128",
                               SDTCisSameAs<1,2>]>,
                            []>;
 
+def PPCbuild_spe64: SDNode<"PPCISD::BUILD_SPE64",
+                           SDTypeProfile<1, 2,
+                             [SDTCisFP<0>, SDTCisSameSizeAs<1,2>,
+                              SDTCisSameAs<1,2>]>,
+                           []>;
+
+def PPCextract_spe_hi : SDNode<"PPCISD::EXTRACT_SPE_HI",
+                               SDTypeProfile<1, 1,
+                                 [SDTCisInt<0>, SDTCisFP<1>]>,
+                                 []>;
+
+def PPCextract_spe_lo : SDNode<"PPCISD::EXTRACT_SPE_LO",
+                               SDTypeProfile<1, 1,
+                               [SDTCisInt<0>, SDTCisFP<1>]>,
+                               []>;
+
 // These are target-independent nodes, but have target-specific formats.
 def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PPCCallSeqStart,
                            [SDNPHasChain, SDNPOutGlue]>;
index 9f5891a45f22346e6b4e63e8d91538c131bd4cc8..2da7c449d37d37c64e07743937404e39bcc92152 100644 (file)
@@ -512,7 +512,7 @@ def EVLWWSPLATX    : EVXForm_1<792, (outs sperc:$RT), (ins memrr:$src),
 
 def EVMERGEHI      : EVXForm_1<556, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB),
                                "evmergehi $RT, $RA, $RB", IIC_VecGeneral, []>;
-def EVMERGELO      : EVXForm_1<557, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB),
+def EVMERGELO      : EVXForm_1<557, (outs sperc:$RT), (ins gprc:$RA, gprc:$RB),
                                "evmergelo $RT, $RA, $RB", IIC_VecGeneral, []>;
 def EVMERGEHILO    : EVXForm_1<558, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB),
                                "evmergehilo $RT, $RA, $RB", IIC_VecGeneral, []>;
@@ -887,4 +887,15 @@ def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETUGT)),
           (SELECT_SPE (CRANDC $lhs, $rhs), $tval, $fval)>;
 def : Pat<(f64 (selectcc i1:$lhs, i1:$rhs, f64:$tval, f64:$fval, SETNE)),
           (SELECT_SPE (CRXOR $lhs, $rhs), $tval, $fval)>;
+
+
+def : Pat<(f64 (PPCbuild_spe64 i32:$rB, i32:$rA)),
+          (f64 (COPY_TO_REGCLASS (EVMERGELO $rA, $rB), SPERC))>;
+
+def : Pat<(i32 (PPCextract_spe_hi f64:$rA)),
+          (i32 (EXTRACT_SUBREG (EVMERGEHI $rA, $rA), sub_32))>;
+
+def : Pat<(i32 (PPCextract_spe_lo f64:$rA)),
+          (i32 (EXTRACT_SUBREG $rA, sub_32))>;
+
 }
index eeb39d4c7126325db73675f4860a00f1ff0ddb54..20d0e6e54de3d4b71bc6f49383edccdc676c1846 100644 (file)
@@ -472,10 +472,8 @@ entry:
 ; CHECK-LABEL: test_dselect
 ; CHECK: andi.
 ; CHECK: bc
-; CHECK: evldd
-; CHECK: b
-; CHECK: evldd
-; CHECK: evstdd
+; CHECK: evor
+; CHECK: evmergehi
 ; CHECK: blr
 }
 
@@ -519,7 +517,7 @@ entry:
   %1 = call i32 asm sideeffect "efdctsi $0, $1", "=d,d"(double %0)
   ret i32 %1
 ; CHECK-LABEL: test_dasmconst
-; CHECK: evldd
+; CHECK: evmergelo
 ; CHECK: #APP
 ; CHECK: efdctsi
 ; CHECK: #NO_APP
@@ -541,7 +539,7 @@ entry:
   %a4.addr = alloca i32*, align 4
   %a5.addr = alloca i32*, align 4
   %ptr = alloca i32*, align 4
-  %v1 = alloca [8 x i32], align 4
+  %v1 = alloca [9 x i32], align 4
   %v2 = alloca [7 x i32], align 4
   %v3 = alloca [5 x i32], align 4
   store i32 %a1, i32* %a1.addr, align 4
@@ -554,7 +552,7 @@ entry:
   call void asm sideeffect "","~{s0},~{s3},~{s4},~{s5},~{s6},~{s7},~{s8},~{s9},~{s10},~{s11},~{s12},~{s13},~{s14},~{s15},~{s16},~{s17},~{s18},~{s19},~{s20},~{s21},~{s22},~{s23},~{s24},~{s25},~{s26},~{s27},~{s28},~{s29},~{s30},~{s31}"() nounwind
   %1 = fadd double %0, 3.14159
   %2 = load i32*, i32** %ptr, align 4
-  %3 = bitcast [8 x i32]* %v1 to i8*
+  %3 = bitcast [9 x i32]* %v1 to i8*
   call void @llvm.memset.p0i8.i32(i8* align 4 %3, i8 0, i32 24, i1 true)
   %4 = load i32*, i32** %a5.addr, align 4
   store i32 0, i32* %4, align 4