diff options
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
| -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; |

