[llvm-commits] [llvm] r162926 - in /llvm/trunk: lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp test/CodeGen/ARM/2012-08-30-select.ll

Duncan Sands baldrick at free.fr
Sat Sep 1 23:49:33 PDT 2012


Hi Nadav,

On 30/08/12 21:17, Nadav Rotem wrote:
> Author: nadav
> Date: Thu Aug 30 14:17:29 2012
> New Revision: 162926
>
> URL: http://llvm.org/viewvc/llvm-project?rev=162926&view=rev
> Log:
>
> Currently targets that do not support selects with scalar conditions and vector operands - scalarize the code. ARM is such a target
> because it does not support CMOV of vectors. To implement this efficientlyi, we broadcast the condition bit and use a sequence of NAND-OR
> to select between the two operands. This is the same sequence we use for targets that don't have vector BLENDs (like SSE2).
>
> rdar://12201387
>
>
> Added:
>      llvm/trunk/test/CodeGen/ARM/2012-08-30-select.ll
> Modified:
>      llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp?rev=162926&r1=162925&r2=162926&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp Thu Aug 30 14:17:29 2012
> @@ -64,6 +64,7 @@
>     // Implement vselect in terms of XOR, AND, OR when blend is not supported
>     // by the target.
>     SDValue ExpandVSELECT(SDValue Op);
> +  SDValue ExpandSELECT(SDValue Op);
>     SDValue ExpandLoad(SDValue Op);
>     SDValue ExpandStore(SDValue Op);
>     SDValue ExpandFNEG(SDValue Op);
> @@ -261,6 +262,8 @@
>     case TargetLowering::Expand:
>       if (Node->getOpcode() == ISD::VSELECT)
>         Result = ExpandVSELECT(Op);
> +    else if (Node->getOpcode() == ISD::SELECT)
> +      Result = ExpandSELECT(Op);
>       else if (Node->getOpcode() == ISD::UINT_TO_FP)
>         Result = ExpandUINT_TO_FLOAT(Op);
>       else if (Node->getOpcode() == ISD::FNEG)
> @@ -436,6 +439,67 @@
>     return TF;
>   }
>
> +SDValue VectorLegalizer::ExpandSELECT(SDValue Op) {
> +  // Lower a select instruction where the condition is a scalar and the
> +  // operands are vectors. Lower this select to VSELECT and implement it
> +  // using XOR AND OR. The selector bit is broadcasted.
> +  EVT VT = Op.getValueType();
> +  DebugLoc DL = Op.getDebugLoc();
> +
> +  SDValue Mask = Op.getOperand(0);
> +  SDValue Op1 = Op.getOperand(1);
> +  SDValue Op2 = Op.getOperand(2);
> +
> +  assert(VT.isVector() && !Mask.getValueType().isVector()
> +         && Op1.getValueType() == Op2.getValueType() && "Invalid type");
> +
> +  unsigned NumElem = VT.getVectorNumElements();
> +
> +  // If we can't even use the basic vector operations of
> +  // AND,OR,XOR, we will have to scalarize the op.
> +  // Notice that the operation may be 'promoted' which means that it is
> +  // 'bitcasted' to another type which is handled.
> +  // Also, we need to be able to construct a splat vector using BUILD_VECTOR.
> +  if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
> +      TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
> +      TLI.getOperationAction(ISD::OR,  VT) == TargetLowering::Expand ||
> +      TLI.getOperationAction(ISD::BUILD_VECTOR,  VT) == TargetLowering::Expand)
> +    return DAG.UnrollVectorOp(Op.getNode());
> +
> +  // Generate a mask operand.
> +  EVT MaskTy = TLI.getSetCCResultType(VT);
> +  assert(MaskTy.isVector() && "Invalid CC type");
> +  assert(MaskTy.getSizeInBits() == Op1.getValueType().getSizeInBits()
> +         && "Invalid mask size");
> +
> +  // What is the size of each element in the vector mask.
> +  EVT BitTy = MaskTy.getScalarType();
> +
> +  // Turn the mask into an all-one or all-zero word.

this seems to be assuming that booleans are 0 or all 1.  You should check
getBooleanContents.

Ciao, Duncan.

> +  Mask = DAG.getAnyExtOrTrunc(Mask, DL, BitTy);
> +  Mask = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, BitTy, Mask,
> +                     DAG.getValueType(MVT::i1));
> +
> +  // Broadcast the mask so that the entire vector is all-one or all zero.
> +  SmallVector<SDValue, 8> Ops(NumElem, Mask);
> +  Mask = DAG.getNode(ISD::BUILD_VECTOR, DL, MaskTy, &Ops[0], Ops.size());
> +
> +  // Bitcast the operands to be the same type as the mask.
> +  // This is needed when we select between FP types because
> +  // the mask is a vector of integers.
> +  Op1 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op1);
> +  Op2 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op2);
> +
> +  SDValue AllOnes = DAG.getConstant(
> +            APInt::getAllOnesValue(BitTy.getSizeInBits()), MaskTy);
> +  SDValue NotMask = DAG.getNode(ISD::XOR, DL, MaskTy, Mask, AllOnes);
> +
> +  Op1 = DAG.getNode(ISD::AND, DL, MaskTy, Op1, Mask);
> +  Op2 = DAG.getNode(ISD::AND, DL, MaskTy, Op2, NotMask);
> +  SDValue Val = DAG.getNode(ISD::OR, DL, MaskTy, Op1, Op2);
> +  return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Val);
> +}
> +
>   SDValue VectorLegalizer::ExpandVSELECT(SDValue Op) {
>     // Implement VSELECT in terms of XOR, AND, OR
>     // on platforms which do not support blend natively.
> @@ -455,7 +519,7 @@
>         TLI.getOperationAction(ISD::OR,  VT) == TargetLowering::Expand)
>       return DAG.UnrollVectorOp(Op.getNode());
>
> -  assert(VT.getSizeInBits() == Op.getOperand(1).getValueType().getSizeInBits()
> +  assert(VT.getSizeInBits() == Op1.getValueType().getSizeInBits()
>            && "Invalid mask size");
>     // Bitcast the operands to be the same type as the mask.
>     // This is needed when we select between FP types because
>
> Added: llvm/trunk/test/CodeGen/ARM/2012-08-30-select.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2012-08-30-select.ll?rev=162926&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/ARM/2012-08-30-select.ll (added)
> +++ llvm/trunk/test/CodeGen/ARM/2012-08-30-select.ll Thu Aug 30 14:17:29 2012
> @@ -0,0 +1,17 @@
> +; RUN: llc < %s -mtriple=thumbv7-apple-ios | FileCheck %s
> +; rdar://12201387
> +
> +;CHECK: select_s_v_v
> +;CHECK: vbsl
> +;CHECK: bx
> +define <16 x i8> @select_s_v_v(i32 %avail, i8* %bar) {
> +entry:
> +  %vld1 = call <16 x i8> @llvm.arm.neon.vld1.v16i8(i8* %bar, i32 1)
> +  %and = and i32 %avail, 1
> +  %tobool = icmp eq i32 %and, 0
> +  %vld1. = select i1 %tobool, <16 x i8> %vld1, <16 x i8> zeroinitializer
> +  ret <16 x i8> %vld1.
> +}
> +
> +declare <16 x i8> @llvm.arm.neon.vld1.v16i8(i8* , i32 )
> +
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>




More information about the llvm-commits mailing list