diff options
author | Andrea Di Biagio <Andrea_DiBiagio@sn.scee.net> | 2013-12-28 11:11:52 +0000 |
---|---|---|
committer | Andrea Di Biagio <Andrea_DiBiagio@sn.scee.net> | 2013-12-28 11:11:52 +0000 |
commit | 6ec3395335addb3d352881d84a93cae8a235af95 (patch) | |
tree | 2247fdacb179150567ab6f25a3d6360ba9f377ea /lib/Target/X86/X86ISelLowering.cpp | |
parent | 14b42a1c92b47bced8e6b94a0213a8970d1c0edd (diff) | |
download | llvm-6ec3395335addb3d352881d84a93cae8a235af95.tar.gz llvm-6ec3395335addb3d352881d84a93cae8a235af95.tar.bz2 llvm-6ec3395335addb3d352881d84a93cae8a235af95.tar.xz |
[X86] Teach the backend how to fold target specific dag node for packed
vector shift by immedate count (VSHLI/VSRLI/VSRAI) into a build_vector when
the vector in input to the shift is a build_vector of all constants or UNDEFs.
Target specific nodes for packed shifts by immediate count are in
general introduced by function 'getTargetVShiftByConstNode' (in
X86ISelLowering.cpp) when lowering shift operations, SSE/AVX immediate
shift intrinsics and (only in very few cases) SIGN_EXTEND_INREG dag
nodes.
This patch adds extra rules for simplifying vector shifts inside
function 'getTargetVShiftByConstNode'.
Added file test/CodeGen/X86/vec_shift5.ll to verify that packed
shifts by immediate are correctly folded into a build_vector when the
input vector to the shift dag node is a vector of constants or undefs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198113 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/X86/X86ISelLowering.cpp')
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 3011407eb3..4fd7461659 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -11103,11 +11103,12 @@ static SDValue LowerVACOPY(SDValue Op, const X86Subtarget *Subtarget, static SDValue getTargetVShiftByConstNode(unsigned Opc, SDLoc dl, EVT VT, SDValue SrcOp, uint64_t ShiftAmt, SelectionDAG &DAG) { + EVT ElementType = VT.getVectorElementType(); // Check for ShiftAmt >= element width - if (ShiftAmt >= VT.getVectorElementType().getSizeInBits()) { + if (ShiftAmt >= ElementType.getSizeInBits()) { if (Opc == X86ISD::VSRAI) - ShiftAmt = VT.getVectorElementType().getSizeInBits() - 1; + ShiftAmt = ElementType.getSizeInBits() - 1; else return DAG.getConstant(0, VT); } @@ -11115,6 +11116,56 @@ static SDValue getTargetVShiftByConstNode(unsigned Opc, SDLoc dl, EVT VT, assert((Opc == X86ISD::VSHLI || Opc == X86ISD::VSRLI || Opc == X86ISD::VSRAI) && "Unknown target vector shift-by-constant node"); + // Fold this packed vector shift into a build vector if SrcOp is a + // vector of ConstantSDNodes or UNDEFs. + if (ISD::isBuildVectorOfConstantSDNodes(SrcOp.getNode())) { + SmallVector<SDValue, 8> Elts; + unsigned NumElts = SrcOp->getNumOperands(); + ConstantSDNode *ND; + + switch(Opc) { + default: llvm_unreachable(0); + case X86ISD::VSHLI: + for (unsigned i=0; i!=NumElts; ++i) { + SDValue CurrentOp = SrcOp->getOperand(i); + if (CurrentOp->getOpcode() == ISD::UNDEF) { + Elts.push_back(CurrentOp); + continue; + } + ND = cast<ConstantSDNode>(CurrentOp); + const APInt &C = ND->getAPIntValue(); + Elts.push_back(DAG.getConstant(C.shl(ShiftAmt), ElementType)); + } + break; + case X86ISD::VSRLI: + for (unsigned i=0; i!=NumElts; ++i) { + SDValue CurrentOp = SrcOp->getOperand(i); + if (CurrentOp->getOpcode() == ISD::UNDEF) { + Elts.push_back(CurrentOp); + continue; + } + ND = cast<ConstantSDNode>(CurrentOp); + const APInt &C = ND->getAPIntValue(); + Elts.push_back(DAG.getConstant(C.lshr(ShiftAmt), ElementType)); + } + break; + case X86ISD::VSRAI: + for (unsigned i=0; i!=NumElts; ++i) { + SDValue CurrentOp = SrcOp->getOperand(i); + if (CurrentOp->getOpcode() == ISD::UNDEF) { + Elts.push_back(CurrentOp); + continue; + } + ND = cast<ConstantSDNode>(CurrentOp); + const APInt &C = ND->getAPIntValue(); + Elts.push_back(DAG.getConstant(C.ashr(ShiftAmt), ElementType)); + } + break; + } + + return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Elts[0], NumElts); + } + return DAG.getNode(Opc, dl, VT, SrcOp, DAG.getConstant(ShiftAmt, MVT::i8)); } |