LoopVectorizationPlanner.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. //===- LoopVectorizationPlanner.h - Planner for LoopVectorization ---------===//
  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 provides a LoopVectorizationPlanner class.
  11. /// InnerLoopVectorizer vectorizes loops which contain only one basic
  12. /// LoopVectorizationPlanner - drives the vectorization process after having
  13. /// passed Legality checks.
  14. /// The planner builds and optimizes the Vectorization Plans which record the
  15. /// decisions how to vectorize the given loop. In particular, represent the
  16. /// control-flow of the vectorized version, the replication of instructions that
  17. /// are to be scalarized, and interleave access groups.
  18. ///
  19. /// Also provides a VPlan-based builder utility analogous to IRBuilder.
  20. /// It provides an instruction-level API for generating VPInstructions while
  21. /// abstracting away the Recipe manipulation details.
  22. //===----------------------------------------------------------------------===//
  23. #ifndef LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
  24. #define LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
  25. #include "VPlan.h"
  26. namespace llvm {
  27. class LoopInfo;
  28. class LoopVectorizationLegality;
  29. class LoopVectorizationCostModel;
  30. class PredicatedScalarEvolution;
  31. class LoopVectorizationRequirements;
  32. class LoopVectorizeHints;
  33. class OptimizationRemarkEmitter;
  34. class TargetTransformInfo;
  35. class TargetLibraryInfo;
  36. class VPRecipeBuilder;
  37. /// VPlan-based builder utility analogous to IRBuilder.
  38. class VPBuilder {
  39. VPBasicBlock *BB = nullptr;
  40. VPBasicBlock::iterator InsertPt = VPBasicBlock::iterator();
  41. VPInstruction *createInstruction(unsigned Opcode,
  42. ArrayRef<VPValue *> Operands, DebugLoc DL) {
  43. VPInstruction *Instr = new VPInstruction(Opcode, Operands, DL);
  44. if (BB)
  45. BB->insert(Instr, InsertPt);
  46. return Instr;
  47. }
  48. VPInstruction *createInstruction(unsigned Opcode,
  49. std::initializer_list<VPValue *> Operands,
  50. DebugLoc DL) {
  51. return createInstruction(Opcode, ArrayRef<VPValue *>(Operands), DL);
  52. }
  53. public:
  54. VPBuilder() {}
  55. /// Clear the insertion point: created instructions will not be inserted into
  56. /// a block.
  57. void clearInsertionPoint() {
  58. BB = nullptr;
  59. InsertPt = VPBasicBlock::iterator();
  60. }
  61. VPBasicBlock *getInsertBlock() const { return BB; }
  62. VPBasicBlock::iterator getInsertPoint() const { return InsertPt; }
  63. /// InsertPoint - A saved insertion point.
  64. class VPInsertPoint {
  65. VPBasicBlock *Block = nullptr;
  66. VPBasicBlock::iterator Point;
  67. public:
  68. /// Creates a new insertion point which doesn't point to anything.
  69. VPInsertPoint() = default;
  70. /// Creates a new insertion point at the given location.
  71. VPInsertPoint(VPBasicBlock *InsertBlock, VPBasicBlock::iterator InsertPoint)
  72. : Block(InsertBlock), Point(InsertPoint) {}
  73. /// Returns true if this insert point is set.
  74. bool isSet() const { return Block != nullptr; }
  75. VPBasicBlock *getBlock() const { return Block; }
  76. VPBasicBlock::iterator getPoint() const { return Point; }
  77. };
  78. /// Sets the current insert point to a previously-saved location.
  79. void restoreIP(VPInsertPoint IP) {
  80. if (IP.isSet())
  81. setInsertPoint(IP.getBlock(), IP.getPoint());
  82. else
  83. clearInsertionPoint();
  84. }
  85. /// This specifies that created VPInstructions should be appended to the end
  86. /// of the specified block.
  87. void setInsertPoint(VPBasicBlock *TheBB) {
  88. assert(TheBB && "Attempting to set a null insert point");
  89. BB = TheBB;
  90. InsertPt = BB->end();
  91. }
  92. /// This specifies that created instructions should be inserted at the
  93. /// specified point.
  94. void setInsertPoint(VPBasicBlock *TheBB, VPBasicBlock::iterator IP) {
  95. BB = TheBB;
  96. InsertPt = IP;
  97. }
  98. /// Insert and return the specified instruction.
  99. VPInstruction *insert(VPInstruction *I) const {
  100. BB->insert(I, InsertPt);
  101. return I;
  102. }
  103. /// Create an N-ary operation with \p Opcode, \p Operands and set \p Inst as
  104. /// its underlying Instruction.
  105. VPValue *createNaryOp(unsigned Opcode, ArrayRef<VPValue *> Operands,
  106. Instruction *Inst = nullptr) {
  107. DebugLoc DL;
  108. if (Inst)
  109. DL = Inst->getDebugLoc();
  110. VPInstruction *NewVPInst = createInstruction(Opcode, Operands, DL);
  111. NewVPInst->setUnderlyingValue(Inst);
  112. return NewVPInst;
  113. }
  114. VPValue *createNaryOp(unsigned Opcode, ArrayRef<VPValue *> Operands,
  115. DebugLoc DL) {
  116. return createInstruction(Opcode, Operands, DL);
  117. }
  118. VPValue *createNot(VPValue *Operand, DebugLoc DL) {
  119. return createInstruction(VPInstruction::Not, {Operand}, DL);
  120. }
  121. VPValue *createAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL) {
  122. return createInstruction(Instruction::BinaryOps::And, {LHS, RHS}, DL);
  123. }
  124. VPValue *createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL) {
  125. return createInstruction(Instruction::BinaryOps::Or, {LHS, RHS}, DL);
  126. }
  127. VPValue *createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal,
  128. DebugLoc DL) {
  129. return createNaryOp(Instruction::Select, {Cond, TrueVal, FalseVal}, DL);
  130. }
  131. //===--------------------------------------------------------------------===//
  132. // RAII helpers.
  133. //===--------------------------------------------------------------------===//
  134. /// RAII object that stores the current insertion point and restores it when
  135. /// the object is destroyed.
  136. class InsertPointGuard {
  137. VPBuilder &Builder;
  138. VPBasicBlock *Block;
  139. VPBasicBlock::iterator Point;
  140. public:
  141. InsertPointGuard(VPBuilder &B)
  142. : Builder(B), Block(B.getInsertBlock()), Point(B.getInsertPoint()) {}
  143. InsertPointGuard(const InsertPointGuard &) = delete;
  144. InsertPointGuard &operator=(const InsertPointGuard &) = delete;
  145. ~InsertPointGuard() { Builder.restoreIP(VPInsertPoint(Block, Point)); }
  146. };
  147. };
  148. /// TODO: The following VectorizationFactor was pulled out of
  149. /// LoopVectorizationCostModel class. LV also deals with
  150. /// VectorizerParams::VectorizationFactor and VectorizationCostTy.
  151. /// We need to streamline them.
  152. /// Information about vectorization costs.
  153. struct VectorizationFactor {
  154. /// Vector width with best cost.
  155. ElementCount Width;
  156. /// Cost of the loop with that width.
  157. InstructionCost Cost;
  158. VectorizationFactor(ElementCount Width, InstructionCost Cost)
  159. : Width(Width), Cost(Cost) {}
  160. /// Width 1 means no vectorization, cost 0 means uncomputed cost.
  161. static VectorizationFactor Disabled() {
  162. return {ElementCount::getFixed(1), 0};
  163. }
  164. bool operator==(const VectorizationFactor &rhs) const {
  165. return Width == rhs.Width && Cost == rhs.Cost;
  166. }
  167. bool operator!=(const VectorizationFactor &rhs) const {
  168. return !(*this == rhs);
  169. }
  170. };
  171. /// A class that represents two vectorization factors (initialized with 0 by
  172. /// default). One for fixed-width vectorization and one for scalable
  173. /// vectorization. This can be used by the vectorizer to choose from a range of
  174. /// fixed and/or scalable VFs in order to find the most cost-effective VF to
  175. /// vectorize with.
  176. struct FixedScalableVFPair {
  177. ElementCount FixedVF;
  178. ElementCount ScalableVF;
  179. FixedScalableVFPair()
  180. : FixedVF(ElementCount::getFixed(0)),
  181. ScalableVF(ElementCount::getScalable(0)) {}
  182. FixedScalableVFPair(const ElementCount &Max) : FixedScalableVFPair() {
  183. *(Max.isScalable() ? &ScalableVF : &FixedVF) = Max;
  184. }
  185. FixedScalableVFPair(const ElementCount &FixedVF,
  186. const ElementCount &ScalableVF)
  187. : FixedVF(FixedVF), ScalableVF(ScalableVF) {
  188. assert(!FixedVF.isScalable() && ScalableVF.isScalable() &&
  189. "Invalid scalable properties");
  190. }
  191. static FixedScalableVFPair getNone() { return FixedScalableVFPair(); }
  192. /// \return true if either fixed- or scalable VF is non-zero.
  193. explicit operator bool() const { return FixedVF || ScalableVF; }
  194. /// \return true if either fixed- or scalable VF is a valid vector VF.
  195. bool hasVector() const { return FixedVF.isVector() || ScalableVF.isVector(); }
  196. };
  197. /// Planner drives the vectorization process after having passed
  198. /// Legality checks.
  199. class LoopVectorizationPlanner {
  200. /// The loop that we evaluate.
  201. Loop *OrigLoop;
  202. /// Loop Info analysis.
  203. LoopInfo *LI;
  204. /// Target Library Info.
  205. const TargetLibraryInfo *TLI;
  206. /// Target Transform Info.
  207. const TargetTransformInfo *TTI;
  208. /// The legality analysis.
  209. LoopVectorizationLegality *Legal;
  210. /// The profitability analysis.
  211. LoopVectorizationCostModel &CM;
  212. /// The interleaved access analysis.
  213. InterleavedAccessInfo &IAI;
  214. PredicatedScalarEvolution &PSE;
  215. const LoopVectorizeHints &Hints;
  216. LoopVectorizationRequirements &Requirements;
  217. OptimizationRemarkEmitter *ORE;
  218. SmallVector<VPlanPtr, 4> VPlans;
  219. /// A builder used to construct the current plan.
  220. VPBuilder Builder;
  221. public:
  222. LoopVectorizationPlanner(Loop *L, LoopInfo *LI, const TargetLibraryInfo *TLI,
  223. const TargetTransformInfo *TTI,
  224. LoopVectorizationLegality *Legal,
  225. LoopVectorizationCostModel &CM,
  226. InterleavedAccessInfo &IAI,
  227. PredicatedScalarEvolution &PSE,
  228. const LoopVectorizeHints &Hints,
  229. LoopVectorizationRequirements &Requirements,
  230. OptimizationRemarkEmitter *ORE)
  231. : OrigLoop(L), LI(LI), TLI(TLI), TTI(TTI), Legal(Legal), CM(CM), IAI(IAI),
  232. PSE(PSE), Hints(Hints), Requirements(Requirements), ORE(ORE) {}
  233. /// Plan how to best vectorize, return the best VF and its cost, or None if
  234. /// vectorization and interleaving should be avoided up front.
  235. Optional<VectorizationFactor> plan(ElementCount UserVF, unsigned UserIC);
  236. /// Use the VPlan-native path to plan how to best vectorize, return the best
  237. /// VF and its cost.
  238. VectorizationFactor planInVPlanNativePath(ElementCount UserVF);
  239. /// Return the best VPlan for \p VF.
  240. VPlan &getBestPlanFor(ElementCount VF) const;
  241. /// Generate the IR code for the body of the vectorized loop according to the
  242. /// best selected \p VF, \p UF and VPlan \p BestPlan.
  243. void executePlan(ElementCount VF, unsigned UF, VPlan &BestPlan,
  244. InnerLoopVectorizer &LB, DominatorTree *DT);
  245. #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  246. void printPlans(raw_ostream &O);
  247. #endif
  248. /// Look through the existing plans and return true if we have one with all
  249. /// the vectorization factors in question.
  250. bool hasPlanWithVF(ElementCount VF) const {
  251. return any_of(VPlans,
  252. [&](const VPlanPtr &Plan) { return Plan->hasVF(VF); });
  253. }
  254. /// Test a \p Predicate on a \p Range of VF's. Return the value of applying
  255. /// \p Predicate on Range.Start, possibly decreasing Range.End such that the
  256. /// returned value holds for the entire \p Range.
  257. static bool
  258. getDecisionAndClampRange(const std::function<bool(ElementCount)> &Predicate,
  259. VFRange &Range);
  260. protected:
  261. /// Collect the instructions from the original loop that would be trivially
  262. /// dead in the vectorized loop if generated.
  263. void collectTriviallyDeadInstructions(
  264. SmallPtrSetImpl<Instruction *> &DeadInstructions);
  265. /// Build VPlans for power-of-2 VF's between \p MinVF and \p MaxVF inclusive,
  266. /// according to the information gathered by Legal when it checked if it is
  267. /// legal to vectorize the loop.
  268. void buildVPlans(ElementCount MinVF, ElementCount MaxVF);
  269. private:
  270. /// Build a VPlan according to the information gathered by Legal. \return a
  271. /// VPlan for vectorization factors \p Range.Start and up to \p Range.End
  272. /// exclusive, possibly decreasing \p Range.End.
  273. VPlanPtr buildVPlan(VFRange &Range);
  274. /// Build a VPlan using VPRecipes according to the information gather by
  275. /// Legal. This method is only used for the legacy inner loop vectorizer.
  276. VPlanPtr buildVPlanWithVPRecipes(
  277. VFRange &Range, SmallPtrSetImpl<Instruction *> &DeadInstructions,
  278. const MapVector<Instruction *, Instruction *> &SinkAfter);
  279. /// Build VPlans for power-of-2 VF's between \p MinVF and \p MaxVF inclusive,
  280. /// according to the information gathered by Legal when it checked if it is
  281. /// legal to vectorize the loop. This method creates VPlans using VPRecipes.
  282. void buildVPlansWithVPRecipes(ElementCount MinVF, ElementCount MaxVF);
  283. // Adjust the recipes for reductions. For in-loop reductions the chain of
  284. // instructions leading from the loop exit instr to the phi need to be
  285. // converted to reductions, with one operand being vector and the other being
  286. // the scalar reduction chain. For other reductions, a select is introduced
  287. // between the phi and live-out recipes when folding the tail.
  288. void adjustRecipesForReductions(VPBasicBlock *LatchVPBB, VPlanPtr &Plan,
  289. VPRecipeBuilder &RecipeBuilder,
  290. ElementCount MinVF);
  291. };
  292. } // namespace llvm
  293. #endif // LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H