diff options
Diffstat (limited to 'llvm/lib/CodeGen')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 31 | 
1 files changed, 31 insertions, 0 deletions
| diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 75fb6559b9b..b8af674a1e2 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -19537,6 +19537,37 @@ SDValue DAGCombiner::SimplifyVBinOp(SDNode *N) {      }    } +  // Make sure all but the first op are undef. +  auto ConcatWithUndef = [](SDValue Concat) { +    return Concat.getOpcode() == ISD::CONCAT_VECTORS && +           std::all_of(std::next(Concat->op_begin()), Concat->op_end(), +                       [](const SDValue &Op) { +                         return Op.isUndef(); +                       }); +  }; + +  // The following pattern is likely to emerge with vector reduction ops. Moving +  // the binary operation ahead of the concat may allow using a narrower vector +  // instruction that has better performance than the wide version of the op: +  // VBinOp (concat X, undef), (concat Y, undef) --> concat (VBinOp X, Y), VecC +  if (ConcatWithUndef(LHS) && ConcatWithUndef(RHS) && +      (LHS.hasOneUse() || RHS.hasOneUse())) { +    SDValue X = LHS.getOperand(0); +    SDValue Y = RHS.getOperand(0); +    EVT NarrowVT = X.getValueType(); +    if (NarrowVT == Y.getValueType() && +        TLI.isOperationLegalOrCustomOrPromote(Opcode, NarrowVT)) { +      // (binop undef, undef) may not return undef, so compute that result. +      SDLoc DL(N); +      SDValue VecC = +          DAG.getNode(Opcode, DL, NarrowVT, DAG.getUNDEF(NarrowVT), +                      DAG.getUNDEF(NarrowVT)); +      SmallVector<SDValue, 4> Ops(LHS.getNumOperands(), VecC); +      Ops[0] = DAG.getNode(Opcode, DL, NarrowVT, X, Y); +      return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Ops); +    } +  } +    if (SDValue V = scalarizeBinOpOfSplats(N, DAG))      return V; | 

