| Florian Hahn | 45e5d5b | 2018-06-08 17:30:45 +0000 | [diff] [blame] | 1 | //===- VPRecipeBuilder.h - Helper class to build recipes --------*- C++ -*-===// |
| 2 | // |
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 |
| Florian Hahn | 45e5d5b | 2018-06-08 17:30:45 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #ifndef LLVM_TRANSFORMS_VECTORIZE_VPRECIPEBUILDER_H |
| 10 | #define LLVM_TRANSFORMS_VECTORIZE_VPRECIPEBUILDER_H |
| 11 | |
| 12 | #include "LoopVectorizationPlanner.h" |
| 13 | #include "VPlan.h" |
| 14 | #include "llvm/ADT/DenseMap.h" |
| 15 | #include "llvm/IR/IRBuilder.h" |
| 16 | |
| 17 | namespace llvm { |
| 18 | |
| 19 | class LoopVectorizationLegality; |
| 20 | class LoopVectorizationCostModel; |
| Florian Hahn | 45e5d5b | 2018-06-08 17:30:45 +0000 | [diff] [blame] | 21 | class TargetLibraryInfo; |
| 22 | |
| 23 | /// Helper class to create VPRecipies from IR instructions. |
| 24 | class VPRecipeBuilder { |
| 25 | /// The loop that we evaluate. |
| 26 | Loop *OrigLoop; |
| 27 | |
| 28 | /// Target Library Info. |
| 29 | const TargetLibraryInfo *TLI; |
| 30 | |
| Florian Hahn | 45e5d5b | 2018-06-08 17:30:45 +0000 | [diff] [blame] | 31 | /// The legality analysis. |
| 32 | LoopVectorizationLegality *Legal; |
| 33 | |
| 34 | /// The profitablity analysis. |
| 35 | LoopVectorizationCostModel &CM; |
| 36 | |
| Florian Hahn | 18138e0 | 2020-04-13 08:28:26 +0100 | [diff] [blame] | 37 | PredicatedScalarEvolution &PSE; |
| 38 | |
| Florian Hahn | 45e5d5b | 2018-06-08 17:30:45 +0000 | [diff] [blame] | 39 | VPBuilder &Builder; |
| 40 | |
| 41 | /// When we if-convert we need to create edge masks. We have to cache values |
| 42 | /// so that we don't end up with exponential recursion/IR. Note that |
| 43 | /// if-conversion currently takes place during VPlan-construction, so these |
| 44 | /// caches are only used at that stage. |
| 45 | using EdgeMaskCacheTy = |
| 46 | DenseMap<std::pair<BasicBlock *, BasicBlock *>, VPValue *>; |
| 47 | using BlockMaskCacheTy = DenseMap<BasicBlock *, VPValue *>; |
| 48 | EdgeMaskCacheTy EdgeMaskCache; |
| 49 | BlockMaskCacheTy BlockMaskCache; |
| 50 | |
| Gil Rapaport | 7f15254 | 2019-10-07 17:24:33 +0300 | [diff] [blame] | 51 | // VPlan-VPlan transformations support: Hold a mapping from ingredients to |
| 52 | // their recipe. To save on memory, only do so for selected ingredients, |
| Florian Hahn | 49d0082 | 2020-03-29 11:35:17 +0100 | [diff] [blame] | 53 | // marked by having a nullptr entry in this map. |
| Gil Rapaport | 7f15254 | 2019-10-07 17:24:33 +0300 | [diff] [blame] | 54 | DenseMap<Instruction *, VPRecipeBase *> Ingredient2Recipe; |
| Gil Rapaport | 7f15254 | 2019-10-07 17:24:33 +0300 | [diff] [blame] | 55 | |
| Florian Hahn | fa284e1 | 2020-04-20 09:42:02 +0100 | [diff] [blame] | 56 | /// Check if \p I can be widened at the start of \p Range and possibly |
| 57 | /// decrease the range such that the returned value holds for the entire \p |
| 58 | /// Range. The function should not be called for memory instructions or calls. |
| 59 | bool shouldWiden(Instruction *I, VFRange &Range) const; |
| 60 | |
| Florian Hahn | 647c9e7 | 2020-04-16 10:43:09 +0100 | [diff] [blame] | 61 | /// Check if the load or store instruction \p I should widened for \p |
| 62 | /// Range.Start and potentially masked. Such instructions are handled by a |
| 63 | /// recipe that takes an additional VPInstruction for the mask. |
| 64 | VPWidenMemoryInstructionRecipe * |
| 65 | tryToWidenMemory(Instruction *I, VFRange &Range, VPlanPtr &Plan); |
| 66 | |
| 67 | /// Check if an induction recipe should be constructed for \I. If so build and |
| 68 | /// return it. If not, return null. |
| 69 | VPWidenIntOrFpInductionRecipe *tryToOptimizeInductionPHI(PHINode *Phi) const; |
| 70 | |
| 71 | /// Optimize the special case where the operand of \p I is a constant integer |
| 72 | /// induction variable. |
| 73 | VPWidenIntOrFpInductionRecipe * |
| 74 | tryToOptimizeInductionTruncate(TruncInst *I, VFRange &Range) const; |
| 75 | |
| 76 | /// Handle non-loop phi nodes. Currently all such phi nodes are turned into |
| 77 | /// a sequence of select instructions as the vectorizer currently performs |
| 78 | /// full if-conversion. |
| 79 | VPBlendRecipe *tryToBlend(PHINode *Phi, VPlanPtr &Plan); |
| 80 | |
| 81 | /// Handle call instructions. If \p CI can be widened for \p Range.Start, |
| 82 | /// return a new VPWidenCallRecipe. Range.End may be decreased to ensure same |
| 83 | /// decision from \p Range.Start to \p Range.End. |
| 84 | VPWidenCallRecipe *tryToWidenCall(CallInst *CI, VFRange &Range, |
| 85 | VPlan &Plan) const; |
| 86 | |
| 87 | /// Check if \p I has an opcode that can be widened and return a VPWidenRecipe |
| 88 | /// if it can. The function should only be called if the cost-model indicates |
| 89 | /// that widening should be performed. |
| 90 | VPWidenRecipe *tryToWiden(Instruction *I, VPlan &Plan) const; |
| 91 | |
| Florian Hahn | fa284e1 | 2020-04-20 09:42:02 +0100 | [diff] [blame] | 92 | public: |
| Florian Hahn | 647c9e7 | 2020-04-16 10:43:09 +0100 | [diff] [blame] | 93 | VPRecipeBuilder(Loop *OrigLoop, const TargetLibraryInfo *TLI, |
| 94 | LoopVectorizationLegality *Legal, |
| 95 | LoopVectorizationCostModel &CM, |
| 96 | PredicatedScalarEvolution &PSE, VPBuilder &Builder) |
| 97 | : OrigLoop(OrigLoop), TLI(TLI), Legal(Legal), CM(CM), PSE(PSE), |
| 98 | Builder(Builder) {} |
| 99 | |
| 100 | /// Check if a recipe can be create for \p I withing the given VF \p Range. |
| 101 | /// If a recipe can be created, return it. Otherwise return nullptr. |
| 102 | VPRecipeBase *tryToCreateWidenRecipe(Instruction *Instr, VFRange &Range, |
| 103 | VPlanPtr &Plan); |
| 104 | |
| Gil Rapaport | 7f15254 | 2019-10-07 17:24:33 +0300 | [diff] [blame] | 105 | /// Set the recipe created for given ingredient. This operation is a no-op for |
| 106 | /// ingredients that were not marked using a nullptr entry in the map. |
| 107 | void setRecipe(Instruction *I, VPRecipeBase *R) { |
| 108 | if (!Ingredient2Recipe.count(I)) |
| 109 | return; |
| 110 | assert(Ingredient2Recipe[I] == nullptr && |
| 111 | "Recipe already set for ingredient"); |
| 112 | Ingredient2Recipe[I] = R; |
| 113 | } |
| 114 | |
| Florian Hahn | 45e5d5b | 2018-06-08 17:30:45 +0000 | [diff] [blame] | 115 | /// A helper function that computes the predicate of the block BB, assuming |
| 116 | /// that the header block of the loop is set to True. It returns the *entry* |
| 117 | /// mask for the block BB. |
| 118 | VPValue *createBlockInMask(BasicBlock *BB, VPlanPtr &Plan); |
| 119 | |
| 120 | /// A helper function that computes the predicate of the edge between SRC |
| 121 | /// and DST. |
| 122 | VPValue *createEdgeMask(BasicBlock *Src, BasicBlock *Dst, VPlanPtr &Plan); |
| 123 | |
| Gil Rapaport | 7f15254 | 2019-10-07 17:24:33 +0300 | [diff] [blame] | 124 | /// Mark given ingredient for recording its recipe once one is created for |
| 125 | /// it. |
| 126 | void recordRecipeOf(Instruction *I) { |
| 127 | assert((!Ingredient2Recipe.count(I) || Ingredient2Recipe[I] == nullptr) && |
| 128 | "Recipe already set for ingredient"); |
| 129 | Ingredient2Recipe[I] = nullptr; |
| 130 | } |
| 131 | |
| 132 | /// Return the recipe created for given ingredient. |
| 133 | VPRecipeBase *getRecipe(Instruction *I) { |
| 134 | assert(Ingredient2Recipe.count(I) && |
| 135 | "Recording this ingredients recipe was not requested"); |
| 136 | assert(Ingredient2Recipe[I] != nullptr && |
| 137 | "Ingredient doesn't have a recipe"); |
| 138 | return Ingredient2Recipe[I]; |
| 139 | } |
| Florian Hahn | 45e5d5b | 2018-06-08 17:30:45 +0000 | [diff] [blame] | 140 | |
| Florian Hahn | 45e5d5b | 2018-06-08 17:30:45 +0000 | [diff] [blame] | 141 | /// Create a replicating region for instruction \p I that requires |
| 142 | /// predication. \p PredRecipe is a VPReplicateRecipe holding \p I. |
| 143 | VPRegionBlock *createReplicateRegion(Instruction *I, VPRecipeBase *PredRecipe, |
| 144 | VPlanPtr &Plan); |
| 145 | |
| Florian Hahn | 45e5d5b | 2018-06-08 17:30:45 +0000 | [diff] [blame] | 146 | /// Build a VPReplicationRecipe for \p I and enclose it within a Region if it |
| 147 | /// is predicated. \return \p VPBB augmented with this new recipe if \p I is |
| 148 | /// not predicated, otherwise \return a new VPBasicBlock that succeeds the new |
| 149 | /// Region. Update the packing decision of predicated instructions if they |
| 150 | /// feed \p I. Range.End may be decreased to ensure same recipe behavior from |
| 151 | /// \p Range.Start to \p Range.End. |
| 152 | VPBasicBlock *handleReplication( |
| 153 | Instruction *I, VFRange &Range, VPBasicBlock *VPBB, |
| 154 | DenseMap<Instruction *, VPReplicateRecipe *> &PredInst2Recipe, |
| 155 | VPlanPtr &Plan); |
| 156 | }; |
| 157 | } // end namespace llvm |
| 158 | |
| 159 | #endif // LLVM_TRANSFORMS_VECTORIZE_VPRECIPEBUILDER_H |