| 1 | //===- VPlan.h - VPlan-based SLP ------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | /// \file |
| 10 | /// This file contains the declarations for VPlan-based SLP. |
| 11 | /// |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANSLP_H |
| 15 | #define LLVM_TRANSFORMS_VECTORIZE_VPLANSLP_H |
| 16 | |
| 17 | #include "llvm/ADT/DenseMap.h" |
| 18 | #include "llvm/ADT/SmallPtrSet.h" |
| 19 | #include "llvm/ADT/SmallVector.h" |
| 20 | #include "llvm/Analysis/VectorUtils.h" |
| 21 | |
| 22 | namespace llvm { |
| 23 | |
| 24 | class VPBasicBlock; |
| 25 | class VPBlockBase; |
| 26 | class VPRegionBlock; |
| 27 | class VPlan; |
| 28 | class VPValue; |
| 29 | class VPInstruction; |
| 30 | |
| 31 | class VPInterleavedAccessInfo { |
| 32 | DenseMap<VPInstruction *, InterleaveGroup<VPInstruction> *> |
| 33 | InterleaveGroupMap; |
| 34 | |
| 35 | /// Type for mapping of instruction based interleave groups to VPInstruction |
| 36 | /// interleave groups |
| 37 | using Old2NewTy = DenseMap<InterleaveGroup<Instruction> *, |
| 38 | InterleaveGroup<VPInstruction> *>; |
| 39 | |
| 40 | /// Recursively \p Region and populate VPlan based interleave groups based on |
| 41 | /// \p IAI. |
| 42 | void visitRegion(VPRegionBlock *Region, Old2NewTy &Old2New, |
| 43 | InterleavedAccessInfo &IAI); |
| 44 | /// Recursively traverse \p Block and populate VPlan based interleave groups |
| 45 | /// based on \p IAI. |
| 46 | void visitBlock(VPBlockBase *Block, Old2NewTy &Old2New, |
| 47 | InterleavedAccessInfo &IAI); |
| 48 | |
| 49 | public: |
| 50 | VPInterleavedAccessInfo(VPlan &Plan, InterleavedAccessInfo &IAI); |
| 51 | VPInterleavedAccessInfo(const VPInterleavedAccessInfo &) = delete; |
| 52 | VPInterleavedAccessInfo &operator=(const VPInterleavedAccessInfo &) = delete; |
| 53 | |
| 54 | ~VPInterleavedAccessInfo() { |
| 55 | // Avoid releasing a pointer twice. |
| 56 | SmallPtrSet<InterleaveGroup<VPInstruction> *, 4> DelSet( |
| 57 | llvm::from_range, llvm::make_second_range(c&: InterleaveGroupMap)); |
| 58 | for (auto *Ptr : DelSet) |
| 59 | delete Ptr; |
| 60 | } |
| 61 | |
| 62 | /// Get the interleave group that \p Instr belongs to. |
| 63 | /// |
| 64 | /// \returns nullptr if doesn't have such group. |
| 65 | InterleaveGroup<VPInstruction> * |
| 66 | getInterleaveGroup(VPInstruction *Instr) const { |
| 67 | return InterleaveGroupMap.lookup(Val: Instr); |
| 68 | } |
| 69 | }; |
| 70 | |
| 71 | /// Class that maps (parts of) an existing VPlan to trees of combined |
| 72 | /// VPInstructions. |
| 73 | class VPlanSlp { |
| 74 | enum class OpMode { Failed, Load, Opcode }; |
| 75 | |
| 76 | /// Mapping of values in the original VPlan to a combined VPInstruction. |
| 77 | DenseMap<SmallVector<VPValue *, 4>, VPInstruction *> BundleToCombined; |
| 78 | |
| 79 | VPInterleavedAccessInfo &IAI; |
| 80 | |
| 81 | /// Basic block to operate on. For now, only instructions in a single BB are |
| 82 | /// considered. |
| 83 | const VPBasicBlock &BB; |
| 84 | |
| 85 | /// Indicates whether we managed to combine all visited instructions or not. |
| 86 | bool CompletelySLP = true; |
| 87 | |
| 88 | /// Width of the widest combined bundle in bits. |
| 89 | unsigned WidestBundleBits = 0; |
| 90 | |
| 91 | using MultiNodeOpTy = |
| 92 | typename std::pair<VPInstruction *, SmallVector<VPValue *, 4>>; |
| 93 | |
| 94 | // Input operand bundles for the current multi node. Each multi node operand |
| 95 | // bundle contains values not matching the multi node's opcode. They will |
| 96 | // be reordered in reorderMultiNodeOps, once we completed building a |
| 97 | // multi node. |
| 98 | SmallVector<MultiNodeOpTy, 4> MultiNodeOps; |
| 99 | |
| 100 | /// Indicates whether we are building a multi node currently. |
| 101 | bool MultiNodeActive = false; |
| 102 | |
| 103 | /// Check if we can vectorize Operands together. |
| 104 | bool areVectorizable(ArrayRef<VPValue *> Operands) const; |
| 105 | |
| 106 | /// Add combined instruction \p New for the bundle \p Operands. |
| 107 | void addCombined(ArrayRef<VPValue *> Operands, VPInstruction *New); |
| 108 | |
| 109 | /// Indicate we hit a bundle we failed to combine. Returns nullptr for now. |
| 110 | VPInstruction *markFailed(); |
| 111 | |
| 112 | /// Reorder operands in the multi node to maximize sequential memory access |
| 113 | /// and commutative operations. |
| 114 | SmallVector<MultiNodeOpTy, 4> reorderMultiNodeOps(); |
| 115 | |
| 116 | /// Choose the best candidate to use for the lane after \p Last. The set of |
| 117 | /// candidates to choose from are values with an opcode matching \p Last's |
| 118 | /// or loads consecutive to \p Last. |
| 119 | std::pair<OpMode, VPValue *> getBest(OpMode Mode, VPValue *Last, |
| 120 | SmallPtrSetImpl<VPValue *> &Candidates, |
| 121 | VPInterleavedAccessInfo &IAI); |
| 122 | |
| 123 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
| 124 | /// Print bundle \p Values to dbgs(). |
| 125 | void dumpBundle(ArrayRef<VPValue *> Values); |
| 126 | #endif |
| 127 | |
| 128 | public: |
| 129 | VPlanSlp(VPInterleavedAccessInfo &IAI, VPBasicBlock &BB) : IAI(IAI), BB(BB) {} |
| 130 | |
| 131 | ~VPlanSlp() = default; |
| 132 | |
| 133 | /// Tries to build an SLP tree rooted at \p Operands and returns a |
| 134 | /// VPInstruction combining \p Operands, if they can be combined. |
| 135 | VPInstruction *buildGraph(ArrayRef<VPValue *> Operands); |
| 136 | |
| 137 | /// Return the width of the widest combined bundle in bits. |
| 138 | unsigned getWidestBundleBits() const { return WidestBundleBits; } |
| 139 | |
| 140 | /// Return true if all visited instruction can be combined. |
| 141 | bool isCompletelySLP() const { return CompletelySLP; } |
| 142 | }; |
| 143 | } // end namespace llvm |
| 144 | |
| 145 | #endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_H |
| 146 | |