Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- SROA.h - Scalar Replacement Of Aggregates ----------------*- C++ -*-===// |
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 | /// \file |
||
9 | /// This file provides the interface for LLVM's Scalar Replacement of |
||
10 | /// Aggregates pass. This pass provides both aggregate splitting and the |
||
11 | /// primary SSA formation used in the compiler. |
||
12 | /// |
||
13 | //===----------------------------------------------------------------------===// |
||
14 | |||
15 | #ifndef LLVM_TRANSFORMS_SCALAR_SROA_H |
||
16 | #define LLVM_TRANSFORMS_SCALAR_SROA_H |
||
17 | |||
18 | #include "llvm/ADT/MapVector.h" |
||
19 | #include "llvm/ADT/PointerIntPair.h" |
||
20 | #include "llvm/ADT/SetVector.h" |
||
21 | #include "llvm/ADT/SmallVector.h" |
||
22 | #include "llvm/IR/PassManager.h" |
||
23 | #include "llvm/IR/ValueHandle.h" |
||
24 | #include <vector> |
||
25 | |||
26 | namespace llvm { |
||
27 | |||
28 | class AllocaInst; |
||
29 | class LoadInst; |
||
30 | class StoreInst; |
||
31 | class AssumptionCache; |
||
32 | class DominatorTree; |
||
33 | class DomTreeUpdater; |
||
34 | class Function; |
||
35 | class LLVMContext; |
||
36 | class PHINode; |
||
37 | class SelectInst; |
||
38 | class Use; |
||
39 | |||
40 | /// A private "module" namespace for types and utilities used by SROA. These |
||
41 | /// are implementation details and should not be used by clients. |
||
42 | namespace sroa LLVM_LIBRARY_VISIBILITY { |
||
43 | |||
44 | class AllocaSliceRewriter; |
||
45 | class AllocaSlices; |
||
46 | class Partition; |
||
47 | class SROALegacyPass; |
||
48 | |||
49 | class SelectHandSpeculativity { |
||
50 | unsigned char Storage = 0; // None are speculatable by default. |
||
51 | using TrueVal = Bitfield::Element<bool, 0, 1>; // Low 0'th bit. |
||
52 | using FalseVal = Bitfield::Element<bool, 1, 1>; // Low 1'th bit. |
||
53 | public: |
||
54 | SelectHandSpeculativity() = default; |
||
55 | SelectHandSpeculativity &setAsSpeculatable(bool isTrueVal); |
||
56 | bool isSpeculatable(bool isTrueVal) const; |
||
57 | bool areAllSpeculatable() const; |
||
58 | bool areAnySpeculatable() const; |
||
59 | bool areNoneSpeculatable() const; |
||
60 | // For interop as int half of PointerIntPair. |
||
61 | explicit operator intptr_t() const { return static_cast<intptr_t>(Storage); } |
||
62 | explicit SelectHandSpeculativity(intptr_t Storage_) : Storage(Storage_) {} |
||
63 | }; |
||
64 | static_assert(sizeof(SelectHandSpeculativity) == sizeof(unsigned char)); |
||
65 | |||
66 | using PossiblySpeculatableLoad = |
||
67 | PointerIntPair<LoadInst *, 2, sroa::SelectHandSpeculativity>; |
||
68 | using UnspeculatableStore = StoreInst *; |
||
69 | using RewriteableMemOp = |
||
70 | std::variant<PossiblySpeculatableLoad, UnspeculatableStore>; |
||
71 | using RewriteableMemOps = SmallVector<RewriteableMemOp, 2>; |
||
72 | |||
73 | } // end namespace sroa |
||
74 | |||
75 | enum class SROAOptions : bool { ModifyCFG, PreserveCFG }; |
||
76 | |||
77 | /// An optimization pass providing Scalar Replacement of Aggregates. |
||
78 | /// |
||
79 | /// This pass takes allocations which can be completely analyzed (that is, they |
||
80 | /// don't escape) and tries to turn them into scalar SSA values. There are |
||
81 | /// a few steps to this process. |
||
82 | /// |
||
83 | /// 1) It takes allocations of aggregates and analyzes the ways in which they |
||
84 | /// are used to try to split them into smaller allocations, ideally of |
||
85 | /// a single scalar data type. It will split up memcpy and memset accesses |
||
86 | /// as necessary and try to isolate individual scalar accesses. |
||
87 | /// 2) It will transform accesses into forms which are suitable for SSA value |
||
88 | /// promotion. This can be replacing a memset with a scalar store of an |
||
89 | /// integer value, or it can involve speculating operations on a PHI or |
||
90 | /// select to be a PHI or select of the results. |
||
91 | /// 3) Finally, this will try to detect a pattern of accesses which map cleanly |
||
92 | /// onto insert and extract operations on a vector value, and convert them to |
||
93 | /// this form. By doing so, it will enable promotion of vector aggregates to |
||
94 | /// SSA vector values. |
||
95 | class SROAPass : public PassInfoMixin<SROAPass> { |
||
96 | LLVMContext *C = nullptr; |
||
97 | DomTreeUpdater *DTU = nullptr; |
||
98 | AssumptionCache *AC = nullptr; |
||
99 | const bool PreserveCFG; |
||
100 | |||
101 | /// Worklist of alloca instructions to simplify. |
||
102 | /// |
||
103 | /// Each alloca in the function is added to this. Each new alloca formed gets |
||
104 | /// added to it as well to recursively simplify unless that alloca can be |
||
105 | /// directly promoted. Finally, each time we rewrite a use of an alloca other |
||
106 | /// the one being actively rewritten, we add it back onto the list if not |
||
107 | /// already present to ensure it is re-visited. |
||
108 | SetVector<AllocaInst *, SmallVector<AllocaInst *, 16>> Worklist; |
||
109 | |||
110 | /// A collection of instructions to delete. |
||
111 | /// We try to batch deletions to simplify code and make things a bit more |
||
112 | /// efficient. We also make sure there is no dangling pointers. |
||
113 | SmallVector<WeakVH, 8> DeadInsts; |
||
114 | |||
115 | /// Post-promotion worklist. |
||
116 | /// |
||
117 | /// Sometimes we discover an alloca which has a high probability of becoming |
||
118 | /// viable for SROA after a round of promotion takes place. In those cases, |
||
119 | /// the alloca is enqueued here for re-processing. |
||
120 | /// |
||
121 | /// Note that we have to be very careful to clear allocas out of this list in |
||
122 | /// the event they are deleted. |
||
123 | SetVector<AllocaInst *, SmallVector<AllocaInst *, 16>> PostPromotionWorklist; |
||
124 | |||
125 | /// A collection of alloca instructions we can directly promote. |
||
126 | std::vector<AllocaInst *> PromotableAllocas; |
||
127 | |||
128 | /// A worklist of PHIs to speculate prior to promoting allocas. |
||
129 | /// |
||
130 | /// All of these PHIs have been checked for the safety of speculation and by |
||
131 | /// being speculated will allow promoting allocas currently in the promotable |
||
132 | /// queue. |
||
133 | SetVector<PHINode *, SmallVector<PHINode *, 8>> SpeculatablePHIs; |
||
134 | |||
135 | /// A worklist of select instructions to rewrite prior to promoting |
||
136 | /// allocas. |
||
137 | SmallMapVector<SelectInst *, sroa::RewriteableMemOps, 8> SelectsToRewrite; |
||
138 | |||
139 | /// Select instructions that use an alloca and are subsequently loaded can be |
||
140 | /// rewritten to load both input pointers and then select between the result, |
||
141 | /// allowing the load of the alloca to be promoted. |
||
142 | /// From this: |
||
143 | /// %P2 = select i1 %cond, ptr %Alloca, ptr %Other |
||
144 | /// %V = load <type>, ptr %P2 |
||
145 | /// to: |
||
146 | /// %V1 = load <type>, ptr %Alloca -> will be mem2reg'd |
||
147 | /// %V2 = load <type>, ptr %Other |
||
148 | /// %V = select i1 %cond, <type> %V1, <type> %V2 |
||
149 | /// |
||
150 | /// We can do this to a select if its only uses are loads |
||
151 | /// and if either the operand to the select can be loaded unconditionally, |
||
152 | /// or if we are allowed to perform CFG modifications. |
||
153 | /// If found an intervening bitcast with a single use of the load, |
||
154 | /// allow the promotion. |
||
155 | static std::optional<sroa::RewriteableMemOps> |
||
156 | isSafeSelectToSpeculate(SelectInst &SI, bool PreserveCFG); |
||
157 | |||
158 | public: |
||
159 | /// If \p PreserveCFG is set, then the pass is not allowed to modify CFG |
||
160 | /// in any way, even if it would update CFG analyses. |
||
161 | SROAPass(SROAOptions PreserveCFG); |
||
162 | |||
163 | /// Run the pass over the function. |
||
164 | PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); |
||
165 | |||
166 | void printPipeline(raw_ostream &OS, |
||
167 | function_ref<StringRef(StringRef)> MapClassName2PassName); |
||
168 | |||
169 | private: |
||
170 | friend class sroa::AllocaSliceRewriter; |
||
171 | friend class sroa::SROALegacyPass; |
||
172 | |||
173 | /// Helper used by both the public run method and by the legacy pass. |
||
174 | PreservedAnalyses runImpl(Function &F, DomTreeUpdater &RunDTU, |
||
175 | AssumptionCache &RunAC); |
||
176 | PreservedAnalyses runImpl(Function &F, DominatorTree &RunDT, |
||
177 | AssumptionCache &RunAC); |
||
178 | |||
179 | bool presplitLoadsAndStores(AllocaInst &AI, sroa::AllocaSlices &AS); |
||
180 | AllocaInst *rewritePartition(AllocaInst &AI, sroa::AllocaSlices &AS, |
||
181 | sroa::Partition &P); |
||
182 | bool splitAlloca(AllocaInst &AI, sroa::AllocaSlices &AS); |
||
183 | std::pair<bool /*Changed*/, bool /*CFGChanged*/> runOnAlloca(AllocaInst &AI); |
||
184 | void clobberUse(Use &U); |
||
185 | bool deleteDeadInstructions(SmallPtrSetImpl<AllocaInst *> &DeletedAllocas); |
||
186 | bool promoteAllocas(Function &F); |
||
187 | }; |
||
188 | |||
189 | } // end namespace llvm |
||
190 | |||
191 | #endif // LLVM_TRANSFORMS_SCALAR_SROA_H |