Changes in directory llvm/lib/Target/PowerPC:
PPCISelLowering.cpp updated: 1.157 -> 1.158 --- Log message: Make some code more general, adding support for constant formation of several new patterns. --- Diffs of the changes: (+78 -22) PPCISelLowering.cpp | 100 ++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 78 insertions(+), 22 deletions(-) Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp diff -u llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.157 llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.158 --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp:1.157 Mon Apr 17 01:07:44 2006 +++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp Mon Apr 17 01:58:41 2006 @@ -1046,6 +1046,10 @@ static SDOperand BuildSplatI(int Val, unsigned SplatSize, MVT::ValueType VT, SelectionDAG &DAG) { assert(Val >= -16 && Val <= 15 && "vsplti is out of range!"); + + // Force vspltis[hw] -1 to vspltisb -1. + if (Val == -1) SplatSize = 1; + static const MVT::ValueType VTys[] = { // canonical VT to use for each size. MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32 }; @@ -1058,6 +1062,14 @@ return DAG.getNode(ISD::BIT_CONVERT, VT, Res); } +/// BuildIntrinsicBinOp - Return a binary operator intrinsic node with the +/// specified intrinsic ID. +static SDOperand BuildIntrinsicBinOp(unsigned IID, SDOperand LHS, SDOperand RHS, + SelectionDAG &DAG) { + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, LHS.getValueType(), + DAG.getConstant(IID, MVT::i32), LHS, RHS); +} + // 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 @@ -1105,37 +1117,81 @@ Op = BuildSplatI(SextVal >> 1, SplatSize, Op.getValueType(), DAG); return DAG.getNode(ISD::ADD, Op.getValueType(), Op, Op); } - // Otherwise, in range [17,29]: (vsplti 15) + (vsplti C). - if (SextVal >= 0 && SextVal <= 29) { - SDOperand LHS = BuildSplatI(15, SplatSize, Op.getValueType(), DAG); - SDOperand RHS = BuildSplatI(SextVal-15, SplatSize, Op.getValueType(),DAG); - return DAG.getNode(ISD::ADD, Op.getValueType(), LHS, RHS); - - } - // If this is 0x8000_0000 x 4, turn into vspltisw + vslw. If it is - // 0x7FFF_FFFF x 4, turn it into not(0x8000_0000). These are important + // 0x7FFF_FFFF x 4, turn it into not(0x8000_0000). This is important // for fneg/fabs. - if (SplatSize == 4 && - SplatBits == 0x80000000 || SplatBits == (0x7FFFFFFF&~SplatUndef)) { + if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) { // Make -1 and vspltisw -1: - SDOperand OnesI = DAG.getConstant(~0U, MVT::i32); - SDOperand OnesV = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, - OnesI, OnesI, OnesI, OnesI); + SDOperand OnesV = BuildSplatI(-1, 4, MVT::v4i32, DAG); // Make the VSLW intrinsic, computing 0x8000_0000. - SDOperand Res - = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, MVT::v4i32, - DAG.getConstant(Intrinsic::ppc_altivec_vslw, MVT::i32), - OnesV, OnesV); - - // If this is 0x7FFF_FFFF, xor by OnesV to invert it. - if (SplatBits == 0x80000000) - Res = DAG.getNode(ISD::XOR, MVT::v4i32, Res, OnesV); + SDOperand Res = BuildIntrinsicBinOp(Intrinsic::ppc_altivec_vslw, OnesV, + OnesV, DAG); + // xor by OnesV to invert it. + Res = DAG.getNode(ISD::XOR, MVT::v4i32, Res, OnesV); return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res); } + + // Check to see if this is a wide variety of vsplti*, binop self cases. + unsigned SplatBitSize = SplatSize*8; + static const char SplatCsts[] = { + -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, + -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 14, -15 + }; + for (unsigned idx = 0; idx < sizeof(SplatCsts)/sizeof(SplatCsts[0]); ++idx){ + // Indirect through the SplatCsts array so that we favor 'vsplti -1' for + // cases which are ambiguous (e.g. formation of 0x8000_0000). 'vsplti -1' + int i = SplatCsts[idx]; + + // Figure out what shift amount will be used by altivec if shifted by i in + // this splat size. + unsigned TypeShiftAmt = i & (SplatBitSize-1); + + // vsplti + shl self. + if (SextVal == (i << (int)TypeShiftAmt)) { + Op = BuildSplatI(i, SplatSize, Op.getValueType(), DAG); + static const unsigned IIDs[] = { // Intrinsic to use for each size. + Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0, + Intrinsic::ppc_altivec_vslw + }; + return BuildIntrinsicBinOp(IIDs[SplatSize-1], Op, Op, DAG); + } + + // vsplti + srl self. + if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) { + Op = BuildSplatI(i, SplatSize, Op.getValueType(), DAG); + static const unsigned IIDs[] = { // Intrinsic to use for each size. + Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0, + Intrinsic::ppc_altivec_vsrw + }; + return BuildIntrinsicBinOp(IIDs[SplatSize-1], Op, Op, DAG); + } + + // vsplti + sra self. + if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) { + Op = BuildSplatI(i, SplatSize, Op.getValueType(), DAG); + static const unsigned IIDs[] = { // Intrinsic to use for each size. + Intrinsic::ppc_altivec_vsrab, Intrinsic::ppc_altivec_vsrah, 0, + Intrinsic::ppc_altivec_vsraw + }; + return BuildIntrinsicBinOp(IIDs[SplatSize-1], Op, Op, DAG); + } + + // TODO: ROL. + } + + + + // Three instruction sequences. + + // Otherwise, in range [17,29]: (vsplti 15) + (vsplti C). + if (SextVal >= 0 && SextVal <= 29) { + SDOperand LHS = BuildSplatI(15, SplatSize, Op.getValueType(), DAG); + SDOperand RHS = BuildSplatI(SextVal-15, SplatSize, Op.getValueType(),DAG); + return DAG.getNode(ISD::ADD, Op.getValueType(), LHS, RHS); + } } return SDOperand(); _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits