diff options
| author | Simon Pilgrim <llvm-dev@redking.me.uk> | 2016-03-28 21:33:52 +0000 |
|---|---|---|
| committer | Simon Pilgrim <llvm-dev@redking.me.uk> | 2016-03-28 21:33:52 +0000 |
| commit | d3df400fa9d20ea11c1c0b1296ce4299d5b82b86 (patch) | |
| tree | ccd598b5a80d0a7a89d1a2299719f3025c50ad47 /llvm/lib | |
| parent | c2feac75fd3f3ef3f64465e498848699ff43286f (diff) | |
| download | bcm5719-llvm-d3df400fa9d20ea11c1c0b1296ce4299d5b82b86.tar.gz bcm5719-llvm-d3df400fa9d20ea11c1c0b1296ce4299d5b82b86.zip | |
[X86][SSE] Vectorize a bit (AND/XOR/OR) op if a BUILD_VECTOR has the same op for all their scalar elements.
If all a BUILD_VECTOR's source elements are the same bit (AND/XOR/OR) operation type and each has one constant operand, lower to a pair of BUILD_VECTOR and just apply the bit operation to the vectors.
The constant operands will form a constant vector meaning that we still only have a single BUILD_VECTOR to lower and we will have replaced all the scalarized operations with a single SSE equivalent.
Its not in our interest to start make a general purpose vectorizer from this, but I'm seeing enough of these scalar bit operations from the later legalization/scalarization stages to support them at least.
Differential Revision: http://reviews.llvm.org/D18492
llvm-svn: 264666
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 98c020c655f..4f8719d1213 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -6625,6 +6625,54 @@ static SDValue LowerToHorizontalOp(const BuildVectorSDNode *BV, return SDValue(); } +/// If a BUILD_VECTOR's source elements all apply the same bit operation and +/// one of their operands is constant, lower to a pair of BUILD_VECTOR and +/// just apply the bit to the vectors. +/// NOTE: Its not in our interest to start make a general purpose vectorizer +/// from this, but enough scalar bit operations are created from the later +/// legalization + scalarization stages to need basic support. +static SDValue lowerBuildVectorToBitOp(SDValue Op, SelectionDAG &DAG) { + SDLoc DL(Op); + MVT VT = Op.getSimpleValueType(); + unsigned NumElems = VT.getVectorNumElements(); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + // Check that all elements have the same opcode. + // TODO: Should we allow UNDEFS and if so how many? + unsigned Opcode = Op.getOperand(0).getOpcode(); + for (unsigned i = 1; i < NumElems; ++i) + if (Opcode != Op.getOperand(i).getOpcode()) + return SDValue(); + + // TODO: We may be able to add support for other Ops (ADD/SUB + shifts). + switch (Opcode) { + default: + return SDValue(); + case ISD::AND: + case ISD::XOR: + case ISD::OR: + if (!TLI.isOperationLegalOrPromote(Opcode, VT)) + return SDValue(); + break; + } + + SmallVector<SDValue, 4> LHSElts, RHSElts; + for (SDValue Elt : Op->ops()) { + SDValue LHS = Elt.getOperand(0); + SDValue RHS = Elt.getOperand(1); + + // We expect the canonicalized RHS operand to be the constant. + if (!isa<ConstantSDNode>(RHS)) + return SDValue(); + LHSElts.push_back(LHS); + RHSElts.push_back(RHS); + } + + SDValue LHS = DAG.getNode(ISD::BUILD_VECTOR, DL, VT, LHSElts); + SDValue RHS = DAG.getNode(ISD::BUILD_VECTOR, DL, VT, RHSElts); + return DAG.getNode(Opcode, DL, VT, LHS, RHS); +} + /// Create a vector constant without a load. SSE/AVX provide the bare minimum /// functionality to do this, so it's all zeros, all ones, or some derivation /// that is cheap to calculate. @@ -6679,6 +6727,8 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const { return HorizontalOp; if (SDValue Broadcast = LowerVectorBroadcast(Op, Subtarget, DAG)) return Broadcast; + if (SDValue BitOp = lowerBuildVectorToBitOp(Op, DAG)) + return BitOp; unsigned EVTBits = ExtVT.getSizeInBits(); |

