summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-04-18 03:43:48 +0000
committerChris Lattner <sabre@nondot.org>2006-04-18 03:43:48 +0000
commit7e439874cbc28da824378fbc0c5f0c12d90978e9 (patch)
tree7fc4d8f93a5dbb9b2dbda98b22706db21c0ae7ec /llvm/lib/Target/PowerPC/PPCISelLowering.cpp
parenta2cae1bb10535845829a611d88516d22ed4b88dd (diff)
downloadbcm5719-llvm-7e439874cbc28da824378fbc0c5f0c12d90978e9.tar.gz
bcm5719-llvm-7e439874cbc28da824378fbc0c5f0c12d90978e9.zip
Lower v8i16 multiply into this code:
li r5, lo16(LCPI1_0) lis r6, ha16(LCPI1_0) lvx v4, r6, r5 vmulouh v5, v3, v2 vmuleuh v2, v3, v2 vperm v2, v2, v5, v4 where v4 is: LCPI1_0: ; <16 x ubyte> .byte 2 .byte 3 .byte 18 .byte 19 .byte 6 .byte 7 .byte 22 .byte 23 .byte 10 .byte 11 .byte 26 .byte 27 .byte 14 .byte 15 .byte 30 .byte 31 This is 5.07x faster on the G5 (measured) than lowering to scalar code + loads/stores. llvm-svn: 27789
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCISelLowering.cpp')
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelLowering.cpp76
1 files changed, 51 insertions, 25 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 3bc1c90e310..c8a0cc91403 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -228,6 +228,7 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
setOperationAction(ISD::MUL, MVT::v4f32, Legal);
setOperationAction(ISD::MUL, MVT::v4i32, Custom);
+ setOperationAction(ISD::MUL, MVT::v8i16, Custom);
setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4i32, Custom);
@@ -1573,31 +1574,56 @@ static SDOperand LowerSCALAR_TO_VECTOR(SDOperand Op, SelectionDAG &DAG) {
}
static SDOperand LowerMUL(SDOperand Op, SelectionDAG &DAG) {
- assert(Op.getValueType() == MVT::v4i32 && "Unknown mul to lower!");
- SDOperand LHS = Op.getOperand(0);
- SDOperand RHS = Op.getOperand(1);
-
- SDOperand Zero = BuildSplatI( 0, 1, MVT::v4i32, DAG);
- SDOperand Neg16 = BuildSplatI(-16, 4, MVT::v4i32, DAG); // +16 as shift amt.
-
- SDOperand RHSSwap = // = vrlw RHS, 16
- BuildIntrinsicOp(Intrinsic::ppc_altivec_vrlw, RHS, Neg16, DAG);
-
- // Shrinkify inputs to v8i16.
- LHS = DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, LHS);
- RHS = DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, RHS);
- RHSSwap = DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, RHSSwap);
-
- // Low parts multiplied together, generating 32-bit results (we ignore the top
- // parts).
- SDOperand LoProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmulouh,
- LHS, RHS, DAG, MVT::v4i32);
-
- SDOperand HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmsumuhm,
- LHS, RHSSwap, Zero, DAG, MVT::v4i32);
- // Shift the high parts up 16 bits.
- HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, HiProd, Neg16, DAG);
- return DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd);
+ if (Op.getValueType() == MVT::v4i32) {
+ SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1);
+
+ SDOperand Zero = BuildSplatI( 0, 1, MVT::v4i32, DAG);
+ SDOperand Neg16 = BuildSplatI(-16, 4, MVT::v4i32, DAG); // +16 as shift amt.
+
+ SDOperand RHSSwap = // = vrlw RHS, 16
+ BuildIntrinsicOp(Intrinsic::ppc_altivec_vrlw, RHS, Neg16, DAG);
+
+ // Shrinkify inputs to v8i16.
+ LHS = DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, LHS);
+ RHS = DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, RHS);
+ RHSSwap = DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, RHSSwap);
+
+ // Low parts multiplied together, generating 32-bit results (we ignore the
+ // top parts).
+ SDOperand LoProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmulouh,
+ LHS, RHS, DAG, MVT::v4i32);
+
+ SDOperand HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmsumuhm,
+ LHS, RHSSwap, Zero, DAG, MVT::v4i32);
+ // Shift the high parts up 16 bits.
+ HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, HiProd, Neg16, DAG);
+ return DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd);
+ } else if (Op.getValueType() == MVT::v8i16) {
+ SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1);
+
+ // Multiply the even 16-parts, producing 32-bit sums.
+ SDOperand EvenParts = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmuleuh,
+ LHS, RHS, DAG, MVT::v4i32);
+ EvenParts = DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, EvenParts);
+
+ // Multiply the odd 16-parts, producing 32-bit sums.
+ SDOperand OddParts = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmulouh,
+ LHS, RHS, DAG, MVT::v4i32);
+ OddParts = DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, OddParts);
+
+ // Merge the results together.
+ std::vector<SDOperand> Ops;
+ for (unsigned i = 0; i != 4; ++i) {
+ Ops.push_back(DAG.getConstant(2*i+1, MVT::i16));
+ Ops.push_back(DAG.getConstant(2*i+1+8, MVT::i16));
+ }
+
+ return DAG.getNode(ISD::VECTOR_SHUFFLE, MVT::v8i16, EvenParts, OddParts,
+ DAG.getNode(ISD::BUILD_VECTOR, MVT::v8i16, Ops));
+ } else {
+ assert(0 && "Unknown mul to lower!");
+ abort();
+ }
}
/// LowerOperation - Provide custom lowering hooks for some operations.
OpenPOWER on IntegriCloud