[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sun Apr 16 23:58:53 PDT 2006
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();
More information about the llvm-commits
mailing list