llvm.org GIT mirror llvm / f64487e
[Attributor] Pass infrastructure and fixpoint framework NOTE: Note that no attributes are derived yet. This patch will not go in alone but only with others that derive attributes. The framework is split for review purposes. This commit introduces the Attributor pass infrastructure and fixpoint iteration framework. Further patches will introduce abstract attributes into this framework. In a nutshell, the Attributor will update instances of abstract arguments until a fixpoint, or a "timeout", is reached. Communication between the Attributor and the abstract attributes that are derived is restricted to the AbstractState and AbstractAttribute interfaces. Please see the file comment in Attributor.h for detailed information including design decisions and typical use case. Also consider the class documentation for Attributor, AbstractState, and AbstractAttribute. Reviewers: chandlerc, homerdin, hfinkel, fedor.sergeev, sanjoy, spatel, nlopes, nicholas, reames Subscribers: mehdi_amini, mgorny, hiraditya, bollu, steven_wu, dexonsmith, dang, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D59918 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362578 91177308-0d34-0410-b5e6-96231b3b80d8 Johannes Doerfert 2 months ago
17 changed file(s) with 1123 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
7373 void initializeArgPromotionPass(PassRegistry&);
7474 void initializeAssumptionCacheTrackerPass(PassRegistry&);
7575 void initializeAtomicExpandPass(PassRegistry&);
76 void initializeAttributorLegacyPassPass(PassRegistry&);
7677 void initializeBDCELegacyPassPass(PassRegistry&);
7778 void initializeBarrierNoopPass(PassRegistry&);
7879 void initializeBasicAAWrapperPassPass(PassRegistry&);
4040 #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h"
4141 #include "llvm/Transforms/IPO.h"
4242 #include "llvm/Transforms/IPO/AlwaysInliner.h"
43 #include "llvm/Transforms/IPO/Attributor.h"
4344 #include "llvm/Transforms/IPO/FunctionAttrs.h"
4445 #include "llvm/Transforms/InstCombine/InstCombine.h"
4546 #include "llvm/Transforms/Instrumentation.h"
187188 (void) llvm::createPostDomTree();
188189 (void) llvm::createInstructionNamerPass();
189190 (void) llvm::createMetaRenamerPass();
191 (void) llvm::createAttributorLegacyPass();
190192 (void) llvm::createPostOrderFunctionAttrsLegacyPass();
191193 (void) llvm::createReversePostOrderFunctionAttrsPass();
192194 (void) llvm::createMergeFunctionsPass();
0 //===- Attributor.h --- Module-wide attribute deduction ---------*- C++ -*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Attributor: An inter procedural (abstract) "attribute" deduction framework.
9 //
10 // The Attributor framework is an inter procedural abstract analysis (fixpoint
11 // iteration analysis). The goal is to allow easy deduction of new attributes as
12 // well as information exchange between abstract attributes in-flight.
13 //
14 // The Attributor class is the driver and the link between the various abstract
15 // attributes. The Attributor will iterate until a fixpoint state is reached by
16 // all abstract attributes in-flight, or until it will enforce a pessimistic fix
17 // point because an iteration limit is reached.
18 //
19 // Abstract attributes, derived from the AbstractAttribute class, actually
20 // describe properties of the code. They can correspond to actual LLVM-IR
21 // attributes, or they can be more general, ultimately unrelated to LLVM-IR
22 // attributes. The latter is useful when an abstract attributes provides
23 // information to other abstract attributes in-flight but we might not want to
24 // manifest the information. The Attributor allows to query in-flight abstract
25 // attributes through the `Attributor::getAAFor` method (see the method
26 // description for an example). If the method is used by an abstract attribute
27 // P, and it results in an abstract attribute Q, the Attributor will
28 // automatically capture a potential dependence from Q to P. This dependence
29 // will cause P to be reevaluated whenever Q changes in the future.
30 //
31 // The Attributor will only reevaluated abstract attributes that might have
32 // changed since the last iteration. That means that the Attribute will not
33 // revisit all instructions/blocks/functions in the module but only query
34 // an update from a subset of the abstract attributes.
35 //
36 // The update method `AbstractAttribute::updateImpl` is implemented by the
37 // specific "abstract attribute" subclasses. The method is invoked whenever the
38 // currently assumed state (see the AbstractState class) might not be valid
39 // anymore. This can, for example, happen if the state was dependent on another
40 // abstract attribute that changed. In every invocation, the update method has
41 // to adjust the internal state of an abstract attribute to a point that is
42 // justifiable by the underlying IR and the current state of abstract attributes
43 // in-flight. Since the IR is given and assumed to be valid, the information
44 // derived from it can be assumed to hold. However, information derived from
45 // other abstract attributes is conditional on various things. If the justifying
46 // state changed, the `updateImpl` has to revisit the situation and potentially
47 // find another justification or limit the optimistic assumes made.
48 //
49 // Change is the key in this framework. Until a state of no-change, thus a
50 // fixpoint, is reached, the Attributor will query the abstract attributes
51 // in-flight to re-evaluate their state. If the (current) state is too
52 // optimistic, hence it cannot be justified anymore through other abstract
53 // attributes or the state of the IR, the state of the abstract attribute will
54 // have to change. Generally, we assume abstract attribute state to be a finite
55 // height lattice and the update function to be monotone. However, these
56 // conditions are not enforced because the iteration limit will guarantee
57 // termination. If an optimistic fixpoint is reached, or a pessimistic fix
58 // point is enforced after a timeout, the abstract attributes are tasked to
59 // manifest their result in the IR for passes to come.
60 //
61 // Attribute manifestation is not mandatory. If desired, there is support to
62 // generate a single LLVM-IR attribute already in the AbstractAttribute base
63 // class. In the simplest case, a subclass overloads
64 // `AbstractAttribute::getManifestPosition()` and
65 // `AbstractAttribute::getAttrKind()` to return the appropriate values. The
66 // Attributor manifestation framework will then create and place a new attribute
67 // if it is allowed to do so (based on the abstract state). Other use cases can
68 // be achieved by overloading other abstract attribute methods.
69 //
70 //
71 // The "mechanics" of adding a new "abstract attribute":
72 // - Define a class (transitively) inheriting from AbstractAttribute and one
73 // (which could be the same) that (transitively) inherits from AbstractState.
74 // For the latter, consider the already available BooleanState and
75 // IntegerState if they fit your needs, e.g., you require only a bit-encoding.
76 // - Implement all pure methods. Also use overloading if the attribute is not
77 // conforming with the "default" behavior: A (set of) LLVM-IR attribute(s) for
78 // an argument, call site argument, function return value, or function. See
79 // the class and method descriptions for more information on the two
80 // "Abstract" classes and their respective methods.
81 // - Register opportunities for the new abstract attribute in the
82 // `Attributor::identifyDefaultAbstractAttributes` method if it should be
83 // counted as a 'default' attribute.
84 // - Add sufficient tests.
85 // - Add a Statistics object for bookkeeping. If it is a simple (set of)
86 // attribute(s) manifested through the Attributor manifestation framework, see
87 // the bookkeeping function in Attributor.cpp.
88 // - If instructions with a certain opcode are interesting to the attribute, add
89 // that opcode to the switch in `Attributor::identifyAbstractAttributes`. This
90 // will make it possible to query all those instructions through the
91 // `InformationCache::getOpcodeInstMapForFunction` interface and eliminate the
92 // need to traverse the IR repeatedly.
93 //
94 //===----------------------------------------------------------------------===//
95
96 #ifndef LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H
97 #define LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H
98
99 #include "llvm/Analysis/CGSCCPassManager.h"
100 #include "llvm/Analysis/LazyCallGraph.h"
101 #include "llvm/IR/CallSite.h"
102 #include "llvm/IR/PassManager.h"
103
104 namespace llvm {
105
106 struct AbstractAttribute;
107 struct InformationCache;
108
109 class Function;
110
111 /// Simple enum class that forces the status to be spelled out explicitly.
112 ///
113 ///{
114 enum class ChangeStatus {
115 CHANGED,
116 UNCHANGED,
117 };
118
119 ChangeStatus operator|(ChangeStatus l, ChangeStatus r);
120 ChangeStatus operator&(ChangeStatus l, ChangeStatus r);
121 ///}
122
123 /// The fixpoint analysis framework that orchestrates the attribute deduction.
124 ///
125 /// The Attributor provides a general abstract analysis framework (guided
126 /// fixpoint iteration) as well as helper functions for the deduction of
127 /// (LLVM-IR) attributes. However, also other code properties can be deduced,
128 /// propagated, and ultimately manifested through the Attributor framework. This
129 /// is particularly useful if these properties interact with attributes and a
130 /// co-scheduled deduction allows to improve the solution. Even if not, thus if
131 /// attributes/properties are completely isolated, they should use the
132 /// Attributor framework to reduce the number of fixpoint iteration frameworks
133 /// in the code base. Note that the Attributor design makes sure that isolated
134 /// attributes are not impacted, in any way, by others derived at the same time
135 /// if there is no cross-reasoning performed.
136 ///
137 /// The public facing interface of the Attributor is kept simple and basically
138 /// allows abstract attributes to one thing, query abstract attributes
139 /// in-flight. There are two reasons to do this:
140 /// a) The optimistic state of one abstract attribute can justify an
141 /// optimistic state of another, allowing to framework to end up with an
142 /// optimistic (=best possible) fixpoint instead of one based solely on
143 /// information in the IR.
144 /// b) This avoids reimplementing various kinds of lookups, e.g., to check
145 /// for existing IR attributes, in favor of a single lookups interface
146 /// provided by an abstract attribute subclass.
147 ///
148 /// NOTE: The mechanics of adding a new "concrete" abstract attribute are
149 /// described in the file comment.
150 struct Attributor {
151 ~Attributor() { DeleteContainerPointers(AllAbstractAttributes); }
152
153 /// Run the analyses until a fixpoint is reached or enforced (timeout).
154 ///
155 /// The attributes registered with this Attributor can be used after as long
156 /// as the Attributor is not destroyed (it owns the attributes now).
157 ///
158 /// \Returns CHANGED if the IR was changed, otherwise UNCHANGED.
159 ChangeStatus run();
160
161 /// Lookup an abstract attribute of type \p AAType anchored at value \p V and
162 /// argument number \p ArgNo. If no attribute is found and \p V is a call base
163 /// instruction, the called function is tried as a value next. Thus, the
164 /// returned abstract attribute might be anchored at the callee of \p V.
165 ///
166 /// This method is the only (supported) way an abstract attribute can retrieve
167 /// information from another abstract attribute. As an example, take an
168 /// abstract attribute that determines the memory access behavior for a
169 /// argument (readnone, readonly, ...). It should use `getAAFor` to get the
170 /// most optimistic information for other abstract attributes in-flight, e.g.
171 /// the one reasoning about the "captured" state for the argument or the one
172 /// reasoning on the memory access behavior of the function as a whole.
173 template
174 const AAType *getAAFor(AbstractAttribute &QueryingAA, const Value &V,
175 int ArgNo = -1) {
176 static_assert(std::is_base_of::value,
177 "Cannot query an attribute with a type not derived from "
178 "'AbstractAttribute'!");
179 assert(AAType::ID != Attribute::None &&
180 "Cannot lookup generic abstract attributes!");
181
182 // Determine the argument number automatically for llvm::Arguments.
183 if (auto *Arg = dyn_cast(&V))
184 ArgNo = Arg->getArgNo();
185
186 // If a function was given together with an argument number, perform the
187 // lookup for the actual argument instead. Don't do it for variadic
188 // arguments.
189 if (ArgNo >= 0 && isa(&V) &&
190 cast(&V)->arg_size() > (size_t)ArgNo)
191 return getAAFor(
192 QueryingAA, *(cast(&V)->arg_begin() + ArgNo), ArgNo);
193
194 // Lookup the abstract attribute of type AAType. If found, return it after
195 // registering a dependence of QueryingAA on the one returned attribute.
196 const auto &KindToAbstractAttributeMap = AAMap.lookup({&V, ArgNo});
197 if (AAType *AA = static_cast(
198 KindToAbstractAttributeMap.lookup(AAType::ID))) {
199 QueryMap[AA].insert(&QueryingAA);
200 return AA;
201 }
202
203 // If no abstract attribute was found and we look for a call site argument,
204 // defer to the actual argument instead.
205 ImmutableCallSite ICS(&V);
206 if (ICS && ICS.getCalledValue())
207 return getAAFor(QueryingAA, *ICS.getCalledValue(), ArgNo);
208
209 // No matching attribute found
210 return nullptr;
211 }
212
213 /// Introduce a new abstract attribute into the fixpoint analysis.
214 ///
215 /// Note that ownership of the attribute is given to the Attributor. It will
216 /// invoke delete for the Attributor on destruction of the Attributor.
217 ///
218 /// Attributes are identified by
219 /// (1) their anchored value (see AA.getAnchoredValue()),
220 /// (2) their argument number (\p ArgNo, or Argument::getArgNo()), and
221 /// (3) their default attribute kind (see AAType::ID).
222 template AAType ®isterAA(AAType &AA, int ArgNo = -1) {
223 static_assert(std::is_base_of::value,
224 "Cannot register an attribute with a type not derived from "
225 "'AbstractAttribute'!");
226
227 // Determine the anchor value and the argument number which are used to
228 // lookup the attribute together with AAType::ID.
229 Value &AnchoredVal = AA.getAnchoredValue();
230 if (auto *Arg = dyn_cast(&AnchoredVal))
231 ArgNo = Arg->getArgNo();
232
233 // Put the attribute in the lookup map structure and the container we use to
234 // keep track of all attributes.
235 AAMap[{&AnchoredVal, ArgNo}][AAType::ID] = &AA;
236 AllAbstractAttributes.push_back(&AA);
237 return AA;
238 }
239
240 /// Determine opportunities to derive 'default' attributes in \p F and create
241 /// abstract attribute objects for them.
242 ///
243 /// \param F The function that is checked for attribute opportunities.
244 /// \param InfoCache A cache for information queryable by the new attributes.
245 /// \param Whitelist If not null, a set limiting the attribute opportunities.
246 ///
247 /// Note that abstract attribute instances are generally created even if the
248 /// IR already contains the information they would deduce. The most important
249 /// reason for this is the single interface, the one of the abstract attribute
250 /// instance, which can be queried without the need to look at the IR in
251 /// various places.
252 void identifyDefaultAbstractAttributes(
253 Function &F, InformationCache &InfoCache,
254 DenseSet *Whitelist = nullptr);
255
256 private:
257 /// The set of all abstract attributes.
258 ///{
259 using AAVector = SmallVector;
260 AAVector AllAbstractAttributes;
261 ///}
262
263 /// A nested map to lookup abstract attributes based on the anchored value and
264 /// an argument positions (or -1) on the outer level, and attribute kinds
265 /// (Attribute::AttrKind) on the inner level.
266 ///{
267 using KindToAbstractAttributeMap = DenseMap;
268 DenseMap, KindToAbstractAttributeMap> AAMap;
269 ///}
270
271 /// A map from abstract attributes to the ones that queried them through calls
272 /// to the getAAFor<...>(...) method.
273 ///{
274 using QueryMapTy =
275 DenseMap>;
276 QueryMapTy QueryMap;
277 ///}
278 };
279
280 /// Data structure to hold cached (LLVM-IR) information.
281 ///
282 /// All attributes are given an InformationCache object at creation time to
283 /// avoid inspection of the IR by all of them individually. This default
284 /// InformationCache will hold information required by 'default' attributes,
285 /// thus the ones deduced when Attributor::identifyDefaultAbstractAttributes(..)
286 /// is called.
287 ///
288 /// If custom abstract attributes, registered manually through
289 /// Attributor::registerAA(...), need more information, especially if it is not
290 /// reusable, it is advised to inherit from the InformationCache and cast the
291 /// instance down in the abstract attributes.
292 struct InformationCache {
293 /// A map type from opcodes to instructions with this opcode.
294 using OpcodeInstMapTy = DenseMap>;
295
296 /// Return the map that relates "interesting" opcodes with all instructions
297 /// with that opcode in \p F.
298 OpcodeInstMapTy &getOpcodeInstMapForFunction(Function &F) {
299 return FuncInstOpcodeMap[&F];
300 }
301
302 /// A vector type to hold instructions.
303 using InstructionVectorTy = std::vector;
304
305 /// Return the instructions in \p F that may read or write memory.
306 InstructionVectorTy &getReadOrWriteInstsForFunction(Function &F) {
307 return FuncRWInstsMap[&F];
308 }
309
310 private:
311 /// A map type from functions to opcode to instruction maps.
312 using FuncInstOpcodeMapTy = DenseMap;
313
314 /// A map type from functions to their read or write instructions.
315 using FuncRWInstsMapTy = DenseMap;
316
317 /// A nested map that remembers all instructions in a function with a certain
318 /// instruction opcode (Instruction::getOpcode()).
319 FuncInstOpcodeMapTy FuncInstOpcodeMap;
320
321 /// A map from functions to their instructions that may read or write memory.
322 FuncRWInstsMapTy FuncRWInstsMap;
323
324 /// Give the Attributor access to the members so
325 /// Attributor::identifyDefaultAbstractAttributes(...) can initialize them.
326 friend struct Attributor;
327 };
328
329 /// An interface to query the internal state of an abstract attribute.
330 ///
331 /// The abstract state is a minimal interface that allows the Attributor to
332 /// communicate with the abstract attributes about their internal state without
333 /// enforcing or exposing implementation details, e.g., the (existence of an)
334 /// underlying lattice.
335 ///
336 /// It is sufficient to be able to query if a state is (1) valid or invalid, (2)
337 /// at a fixpoint, and to indicate to the state that (3) an optimistic fixpoint
338 /// was reached or (4) a pessimistic fixpoint was enforced.
339 ///
340 /// All methods need to be implemented by the subclass. For the common use case,
341 /// a single boolean state or a bit-encoded state, the BooleanState and
342 /// IntegerState classes are already provided. An abstract attribute can inherit
343 /// from them to get the abstract state interface and additional methods to
344 /// directly modify the state based if needed. See the class comments for help.
345 struct AbstractState {
346 virtual ~AbstractState() {}
347
348 /// Return if this abstract state is in a valid state. If false, no
349 /// information provided should be used.
350 virtual bool isValidState() const = 0;
351
352 /// Return if this abstract state is fixed, thus does not need to be updated
353 /// if information changes as it cannot change itself.
354 virtual bool isAtFixpoint() const = 0;
355
356 /// Indicate that the abstract state should converge to the optimistic state.
357 ///
358 /// This will usually make the optimistically assumed state the known to be
359 /// true state.
360 virtual void indicateOptimisticFixpoint() = 0;
361
362 /// Indicate that the abstract state should converge to the pessimistic state.
363 ///
364 /// This will usually revert the optimistically assumed state to the known to
365 /// be true state.
366 virtual void indicatePessimisticFixpoint() = 0;
367 };
368
369 /// Base struct for all "concrete attribute" deductions.
370 ///
371 /// The abstract attribute is a minimal interface that allows the Attributor to
372 /// orchestrate the abstract/fixpoint analysis. The design allows to hide away
373 /// implementation choices made for the subclasses but also to structure their
374 /// implementation and simplify the use of other abstract attributes in-flight.
375 ///
376 /// To allow easy creation of new attributes, most methods have default
377 /// implementations. The ones that do not are generally straight forward, except
378 /// `AbstractAttribute::updateImpl` which is the location of most reasoning
379 /// associated with the abstract attribute. The update is invoked by the
380 /// Attributor in case the situation used to justify the current optimistic
381 /// state might have changed. The Attributor determines this automatically
382 /// by monitoring the `Attributor::getAAFor` calls made by abstract attributes.
383 ///
384 /// The `updateImpl` method should inspect the IR and other abstract attributes
385 /// in-flight to justify the best possible (=optimistic) state. The actual
386 /// implementation is, similar to the underlying abstract state encoding, not
387 /// exposed. In the most common case, the `updateImpl` will go through a list of
388 /// reasons why its optimistic state is valid given the current information. If
389 /// any combination of them holds and is sufficient to justify the current
390 /// optimistic state, the method shall return UNCHAGED. If not, the optimistic
391 /// state is adjusted to the situation and the method shall return CHANGED.
392 ///
393 /// If the manifestation of the "concrete attribute" deduced by the subclass
394 /// differs from the "default" behavior, which is a (set of) LLVM-IR
395 /// attribute(s) for an argument, call site argument, function return value, or
396 /// function, the `AbstractAttribute::manifest` method should be overloaded.
397 ///
398 /// NOTE: If the state obtained via getState() is INVALID, thus if
399 /// AbstractAttribute::getState().isValidState() returns false, no
400 /// information provided by the methods of this class should be used.
401 /// NOTE: The Attributor currently runs as a call graph SCC pass. Partially to
402 /// this *current* choice there are certain limitations to what we can do.
403 /// As a general rule of thumb, "concrete" abstract attributes should *for
404 /// now* only perform "backward" information propagation. That means
405 /// optimistic information obtained through abstract attributes should
406 /// only be used at positions that precede the origin of the information
407 /// with regards to the program flow. More practically, information can
408 /// *now* be propagated from instructions to their enclosing function, but
409 /// *not* from call sites to the called function. The mechanisms to allow
410 /// both directions will be added in the future.
411 /// NOTE: The mechanics of adding a new "concrete" abstract attribute are
412 /// described in the file comment.
413 struct AbstractAttribute {
414
415 /// The positions attributes can be manifested in.
416 enum ManifestPosition {
417 MP_ARGUMENT, ///< An attribute for a function argument.
418 MP_CALL_SITE_ARGUMENT, ///< An attribute for a call site argument.
419 MP_FUNCTION, ///< An attribute for a function as a whole.
420 MP_RETURNED, ///< An attribute for the function return value.
421 };
422
423 /// An abstract attribute associated with \p AssociatedVal and anchored at
424 /// \p AnchoredVal.
425 ///
426 /// \param AssociatedVal The value this abstract attribute is associated with.
427 /// \param AnchoredVal The value this abstract attributes is anchored at.
428 /// \param InfoCache Cached information accessible to the abstract attribute.
429 AbstractAttribute(Value *AssociatedVal, Value &AnchoredVal,
430 InformationCache &InfoCache)
431 : AssociatedVal(AssociatedVal), AnchoredVal(AnchoredVal),
432 InfoCache(InfoCache) {}
433
434 /// An abstract attribute associated with and anchored at \p V.
435 AbstractAttribute(Value &V, InformationCache &InfoCache)
436 : AbstractAttribute(&V, V, InfoCache) {}
437
438 /// Virtual destructor.
439 virtual ~AbstractAttribute() {}
440
441 /// Initialize the state with the information in the Attributor \p A.
442 ///
443 /// This function is called by the Attributor once all abstract attributes
444 /// have been identified. It can and shall be used for task like:
445 /// - identify existing knowledge in the IR and use it for the "known state"
446 /// - perform any work that is not going to change over time, e.g., determine
447 /// a subset of the IR, or attributes in-flight, that have to be looked at
448 /// in the `updateImpl` method.
449 virtual void initialize(Attributor &A) {}
450
451 /// Return the internal abstract state for inspection.
452 virtual const AbstractState &getState() const = 0;
453
454 /// Return the value this abstract attribute is anchored with.
455 ///
456 /// The anchored value might not be the associated value if the latter is not
457 /// sufficient to determine where arguments will be manifested. This is mostly
458 /// the case for call site arguments as the value is not sufficient to
459 /// pinpoint them. Instead, we can use the call site as an anchor.
460 ///
461 ///{
462 Value &getAnchoredValue() { return AnchoredVal; }
463 const Value &getAnchoredValue() const { return AnchoredVal; }
464 ///}
465
466 /// Return the llvm::Function surrounding the anchored value.
467 ///
468 ///{
469 Function &getAnchorScope();
470 const Function &getAnchorScope() const;
471 ///}
472
473 /// Return the value this abstract attribute is associated with.
474 ///
475 /// The abstract state usually represents this value.
476 ///
477 ///{
478 virtual Value *getAssociatedValue() { return AssociatedVal; }
479 virtual const Value *getAssociatedValue() const { return AssociatedVal; }
480 ///}
481
482 /// Return the position this abstract state is manifested in.
483 virtual ManifestPosition getManifestPosition() const = 0;
484
485 /// Return the kind that identifies the abstract attribute implementation.
486 virtual Attribute::AttrKind getAttrKind() const = 0;
487
488 /// Return the deduced attributes in \p Attrs.
489 virtual void getDeducedAttributes(SmallVectorImpl &Attrs) const {
490 LLVMContext &Ctx = AnchoredVal.getContext();
491 Attrs.emplace_back(Attribute::get(Ctx, getAttrKind()));
492 }
493
494 /// Helper functions, for debug purposes only.
495 ///{
496 virtual void print(raw_ostream &OS) const;
497 void dump() const { print(dbgs()); }
498
499 /// This function should return the "summarized" assumed state as string.
500 virtual const std::string getAsStr() const = 0;
501 ///}
502
503 /// Allow the Attributor access to the protected methods.
504 friend struct Attributor;
505
506 protected:
507 /// Hook for the Attributor to trigger an update of the internal state.
508 ///
509 /// If this attribute is already fixed, this method will return UNCHANGED,
510 /// otherwise it delegates to `AbstractAttribute::updateImpl`.
511 ///
512 /// \Return CHANGED if the internal state changed, otherwise UNCHANGED.
513 ChangeStatus update(Attributor &A);
514
515 /// Hook for the Attributor to trigger the manifestation of the information
516 /// represented by the abstract attribute in the LLVM-IR.
517 ///
518 /// \Return CHANGED if the IR was altered, otherwise UNCHANGED.
519 virtual ChangeStatus manifest(Attributor &A);
520
521 /// Return the internal abstract state for careful modification.
522 virtual AbstractState &getState() = 0;
523
524 /// The actual update/transfer function which has to be implemented by the
525 /// derived classes.
526 ///
527 /// If it is called, the environment has changed and we have to determine if
528 /// the current information is still valid or adjust it otherwise.
529 ///
530 /// \Return CHANGED if the internal state changed, otherwise UNCHANGED.
531 virtual ChangeStatus updateImpl(Attributor &A) = 0;
532
533 /// The value this abstract attribute is associated with.
534 Value *AssociatedVal;
535
536 /// The value this abstract attribute is anchored at.
537 Value &AnchoredVal;
538
539 /// The information cache accessible to this abstract attribute.
540 InformationCache &InfoCache;
541 };
542
543 /// Forward declarations of output streams for debug purposes.
544 ///
545 ///{
546 raw_ostream &operator<<(raw_ostream &OS, const AbstractAttribute &AA);
547 raw_ostream &operator<<(raw_ostream &OS, ChangeStatus S);
548 raw_ostream &operator<<(raw_ostream &OS, AbstractAttribute::ManifestPosition);
549 raw_ostream &operator<<(raw_ostream &OS, const AbstractState &State);
550 ///}
551
552 struct AttributorPass : public PassInfoMixin {
553 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
554 };
555
556 Pass *createAttributorLegacyPass();
557
558 /// ----------------------------------------------------------------------------
559 /// Abstract Attribute Classes
560 /// ----------------------------------------------------------------------------
561
562 } // end namespace llvm
563
564 #endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
129129 initializeArgPromotionPass(R);
130130 initializeJumpThreadingPass(R);
131131 initializeSROALegacyPassPass(R);
132 initializeAttributorLegacyPassPass(R);
132133 initializePostOrderFunctionAttrsLegacyPassPass(R);
133134 initializeReversePostOrderFunctionAttrsLegacyPassPass(R);
134135 initializeGlobalsAAWrapperPassPass(R);
6464 #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h"
6565 #include "llvm/Transforms/IPO/AlwaysInliner.h"
6666 #include "llvm/Transforms/IPO/ArgumentPromotion.h"
67 #include "llvm/Transforms/IPO/Attributor.h"
6768 #include "llvm/Transforms/IPO/CalledValuePropagation.h"
6869 #include "llvm/Transforms/IPO/ConstantMerge.h"
6970 #include "llvm/Transforms/IPO/CrossDSOCFI.h"
4040 #define MODULE_PASS(NAME, CREATE_PASS)
4141 #endif
4242 MODULE_PASS("always-inline", AlwaysInlinerPass())
43 MODULE_PASS("attributor", AttributorPass())
4344 MODULE_PASS("called-value-propagation", CalledValuePropagationPass())
4445 MODULE_PASS("canonicalize-aliases", CanonicalizeAliasesPass())
4546 MODULE_PASS("cg-profile", CGProfilePass())
0 //===- Attributor.cpp - Module-wide attribute deduction -------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file implements an inter procedural pass that deduces and/or propagating
9 // attributes. This is done in an abstract interpretation style fixpoint
10 // iteration. See the Attributor.h file comment and the class descriptions in
11 // that file for more information.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/Transforms/IPO/Attributor.h"
16
17 #include "llvm/ADT/SetVector.h"
18 #include "llvm/ADT/SmallPtrSet.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/Statistic.h"
21 #include "llvm/Analysis/GlobalsModRef.h"
22 #include "llvm/IR/Argument.h"
23 #include "llvm/IR/Attributes.h"
24 #include "llvm/IR/InstIterator.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include
29
30 using namespace llvm;
31
32 #define DEBUG_TYPE "attributor"
33
34 STATISTIC(NumFnWithExactDefinition,
35 "Number of function with exact definitions");
36 STATISTIC(NumFnWithoutExactDefinition,
37 "Number of function without exact definitions");
38 STATISTIC(NumAttributesTimedOut,
39 "Number of abstract attributes timed out before fixpoint");
40 STATISTIC(NumAttributesValidFixpoint,
41 "Number of abstract attributes in a valid fixpoint state");
42 STATISTIC(NumAttributesManifested,
43 "Number of abstract attributes manifested in IR");
44
45 // TODO: Determine a good default value.
46 //
47 // In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads
48 // (when run with the first 5 abstract attributes). The results also indicate
49 // that we never reach 32 iterations but always find a fixpoint sooner.
50 //
51 // This will become more evolved once we perform two interleaved fixpoint
52 // iterations: bottom-up and top-down.
53 static cl::opt
54 MaxFixpointIterations("attributor-max-iterations", cl::Hidden,
55 cl::desc("Maximal number of fixpoint iterations."),
56 cl::init(32));
57
58 static cl::opt DisableAttributor(
59 "attributor-disable", cl::Hidden,
60 cl::desc("Disable the attributor inter-procedural deduction pass."),
61 cl::init(false));
62
63 static cl::opt VerifyAttributor(
64 "attributor-verify", cl::Hidden,
65 cl::desc("Verify the Attributor deduction and "
66 "manifestation of attributes -- may issue false-positive errors"),
67 cl::init(false));
68
69 /// Logic operators for the change status enum class.
70 ///
71 ///{
72 ChangeStatus llvm::operator|(ChangeStatus l, ChangeStatus r) {
73 return l == ChangeStatus::CHANGED ? l : r;
74 }
75 ChangeStatus llvm::operator&(ChangeStatus l, ChangeStatus r) {
76 return l == ChangeStatus::UNCHANGED ? l : r;
77 }
78 ///}
79
80 /// Helper to adjust the statistics.
81 static void bookkeeping(AbstractAttribute::ManifestPosition MP,
82 const Attribute &Attr) {
83 if (!AreStatisticsEnabled())
84 return;
85
86 if (!Attr.isEnumAttribute())
87 return;
88 switch (Attr.getKindAsEnum()) {
89 default:
90 return;
91 }
92 }
93
94 /// Helper to identify the correct offset into an attribute list.
95 static unsigned getAttrIndex(AbstractAttribute::ManifestPosition MP,
96 unsigned ArgNo = 0) {
97 switch (MP) {
98 case AbstractAttribute::MP_ARGUMENT:
99 case AbstractAttribute::MP_CALL_SITE_ARGUMENT:
100 return ArgNo + AttributeList::FirstArgIndex;
101 case AbstractAttribute::MP_FUNCTION:
102 return AttributeList::FunctionIndex;
103 case AbstractAttribute::MP_RETURNED:
104 return AttributeList::ReturnIndex;
105 }
106 }
107
108 /// Return true if \p New is equal or worse than \p Old.
109 static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) {
110 if (!Old.isIntAttribute())
111 return true;
112
113 return Old.getValueAsInt() >= New.getValueAsInt();
114 }
115
116 /// Return true if the information provided by \p Attr was added to the
117 /// attribute list \p Attrs. This is only the case if it was not already present
118 /// in \p Attrs at the position describe by \p MP and \p ArgNo.
119 static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
120 AttributeList &Attrs,
121 AbstractAttribute::ManifestPosition MP,
122 unsigned ArgNo = 0) {
123 unsigned AttrIdx = getAttrIndex(MP, ArgNo);
124
125 if (Attr.isEnumAttribute()) {
126 Attribute::AttrKind Kind = Attr.getKindAsEnum();
127 if (Attrs.hasAttribute(AttrIdx, Kind))
128 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
129 return false;
130 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
131 return true;
132 }
133 if (Attr.isStringAttribute()) {
134 StringRef Kind = Attr.getKindAsString();
135 if (Attrs.hasAttribute(AttrIdx, Kind))
136 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
137 return false;
138 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
139 return true;
140 }
141
142 llvm_unreachable("Expected enum or string attribute!");
143 }
144
145 ChangeStatus AbstractAttribute::update(Attributor &A) {
146 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
147 if (getState().isAtFixpoint())
148 return HasChanged;
149
150 LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");
151
152 HasChanged = updateImpl(A);
153
154 LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
155 << "\n");
156
157 return HasChanged;
158 }
159
160 ChangeStatus AbstractAttribute::manifest(Attributor &A) {
161 assert(getState().isValidState() &&
162 "Attempted to manifest an invalid state!");
163 assert(getAssociatedValue() &&
164 "Attempted to manifest an attribute without associated value!");
165
166 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
167 SmallVector DeducedAttrs;
168 getDeducedAttributes(DeducedAttrs);
169
170 Function &ScopeFn = getAnchorScope();
171 LLVMContext &Ctx = ScopeFn.getContext();
172 ManifestPosition MP = getManifestPosition();
173
174 AttributeList Attrs;
175 SmallVector ArgNos;
176
177 // In the following some generic code that will manifest attributes in
178 // DeducedAttrs if they improve the current IR. Due to the different
179 // annotation positions we use the underlying AttributeList interface.
180 // Note that MP_CALL_SITE_ARGUMENT can annotate multiple locations.
181
182 switch (MP) {
183 case MP_ARGUMENT:
184 ArgNos.push_back(cast(getAssociatedValue())->getArgNo());
185 Attrs = ScopeFn.getAttributes();
186 break;
187 case MP_FUNCTION:
188 case MP_RETURNED:
189 ArgNos.push_back(0);
190 Attrs = ScopeFn.getAttributes();
191 break;
192 case MP_CALL_SITE_ARGUMENT: {
193 CallSite CS(&getAnchoredValue());
194 for (unsigned u = 0, e = CS.getNumArgOperands(); u != e; u++)
195 if (CS.getArgOperand(u) == getAssociatedValue())
196 ArgNos.push_back(u);
197 Attrs = CS.getAttributes();
198 }
199 }
200
201 for (const Attribute &Attr : DeducedAttrs) {
202 for (unsigned ArgNo : ArgNos) {
203 if (!addIfNotExistent(Ctx, Attr, Attrs, MP, ArgNo))
204 continue;
205
206 HasChanged = ChangeStatus::CHANGED;
207 bookkeeping(MP, Attr);
208 }
209 }
210
211 if (HasChanged == ChangeStatus::UNCHANGED)
212 return HasChanged;
213
214 switch (MP) {
215 case MP_ARGUMENT:
216 case MP_FUNCTION:
217 case MP_RETURNED:
218 ScopeFn.setAttributes(Attrs);
219 break;
220 case MP_CALL_SITE_ARGUMENT:
221 CallSite(&getAnchoredValue()).setAttributes(Attrs);
222 }
223
224 return HasChanged;
225 }
226
227 Function &AbstractAttribute::getAnchorScope() {
228 Value &V = getAnchoredValue();
229 if (isa(V))
230 return cast(V);
231 if (isa(V))
232 return *cast(V).getParent();
233 if (isa(V))
234 return *cast(V).getFunction();
235 llvm_unreachable("No scope for anchored value found!");
236 }
237
238 const Function &AbstractAttribute::getAnchorScope() const {
239 return const_cast(this)->getAnchorScope();
240 }
241
242 /// ----------------------------------------------------------------------------
243 /// Attributor
244 /// ----------------------------------------------------------------------------
245
246 ChangeStatus Attributor::run() {
247 // Initialize all abstract attributes.
248 for (AbstractAttribute *AA : AllAbstractAttributes)
249 AA->initialize(*this);
250
251 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
252 << AllAbstractAttributes.size()
253 << " abstract attributes.\n");
254
255 // Now that all abstract attributes are collected and initialized we start the
256 // abstract analysis.
257
258 unsigned IterationCounter = 1;
259
260 SmallVector ChangedAAs;
261 SetVector Worklist;
262 Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
263
264 do {
265 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
266 << ", Worklist size: " << Worklist.size() << "\n");
267
268 // Add all abstract attributes that are potentially dependent on one that
269 // changed to the work list.
270 for (AbstractAttribute *ChangedAA : ChangedAAs) {
271 auto &QuerriedAAs = QueryMap[ChangedAA];
272 Worklist.insert(QuerriedAAs.begin(), QuerriedAAs.end());
273 }
274
275 // Reset the changed set.
276 ChangedAAs.clear();
277
278 // Update all abstract attribute in the work list and record the ones that
279 // changed.
280 for (AbstractAttribute *AA : Worklist)
281 if (AA->update(*this) == ChangeStatus::CHANGED)
282 ChangedAAs.push_back(AA);
283
284 // Reset the work list and repopulate with the changed abstract attributes.
285 // Note that dependent ones are added above.
286 Worklist.clear();
287 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
288
289 } while (!Worklist.empty() && ++IterationCounter < MaxFixpointIterations);
290
291 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
292 << IterationCounter << "/" << MaxFixpointIterations
293 << " iterations\n");
294
295 bool FinishedAtFixpoint = Worklist.empty();
296
297 // Reset abstract arguments not settled in a sound fixpoint by now. This
298 // happens when we stopped the fixpoint iteration early. Note that only the
299 // ones marked as "changed" *and* the ones transitively depending on them
300 // need to be reverted to a pessimistic state. Others might not be in a
301 // fixpoint state but we can use the optimistic results for them anyway.
302 SmallPtrSet Visited;
303 for (unsigned u = 0; u < ChangedAAs.size(); u++) {
304 AbstractAttribute *ChangedAA = ChangedAAs[u];
305 if (!Visited.insert(ChangedAA).second)
306 continue;
307
308 AbstractState &State = ChangedAA->getState();
309 if (!State.isAtFixpoint()) {
310 State.indicatePessimisticFixpoint();
311
312 NumAttributesTimedOut++;
313 }
314
315 auto &QuerriedAAs = QueryMap[ChangedAA];
316 ChangedAAs.append(QuerriedAAs.begin(), QuerriedAAs.end());
317 }
318
319 LLVM_DEBUG({
320 if (!Visited.empty())
321 dbgs() << "\n[Attributor] Finalized " << Visited.size()
322 << " abstract attributes.\n";
323 });
324
325 unsigned NumManifested = 0;
326 unsigned NumAtFixpoint = 0;
327 ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
328 for (AbstractAttribute *AA : AllAbstractAttributes) {
329 AbstractState &State = AA->getState();
330
331 // If there is not already a fixpoint reached, we can now take the
332 // optimistic state. This is correct because we enforced a pessimistic one
333 // on abstract attributes that were transitively dependent on a changed one
334 // already above.
335 if (!State.isAtFixpoint())
336 State.indicateOptimisticFixpoint();
337
338 // If the state is invalid, we do not try to manifest it.
339 if (!State.isValidState())
340 continue;
341
342 // Manifest the state and record if we changed the IR.
343 ChangeStatus LocalChange = AA->manifest(*this);
344 ManifestChange = ManifestChange | LocalChange;
345
346 NumAtFixpoint++;
347 NumManifested += (LocalChange == ChangeStatus::CHANGED);
348 }
349
350 (void)NumManifested;
351 (void)NumAtFixpoint;
352 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
353 << " arguments while " << NumAtFixpoint
354 << " were in a valid fixpoint state\n");
355
356 // If verification is requested, we finished this run at a fixpoint, and the
357 // IR was changed, we re-run the whole fixpoint analysis, starting at
358 // re-initialization of the arguments. This re-run should not result in an IR
359 // change. Though, the (virtual) state of attributes at the end of the re-run
360 // might be more optimistic than the known state or the IR state if the better
361 // state cannot be manifested.
362 if (VerifyAttributor && FinishedAtFixpoint &&
363 ManifestChange == ChangeStatus::CHANGED) {
364 VerifyAttributor = false;
365 ChangeStatus VerifyStatus = run();
366 if (VerifyStatus != ChangeStatus::UNCHANGED)
367 llvm_unreachable(
368 "Attributor verification failed, re-run did result in an IR change "
369 "even after a fixpoint was reached in the original run. (False "
370 "positives possible!)");
371 VerifyAttributor = true;
372 }
373
374 NumAttributesManifested += NumManifested;
375 NumAttributesValidFixpoint += NumAtFixpoint;
376
377 return ManifestChange;
378 }
379
380 void Attributor::identifyDefaultAbstractAttributes(
381 Function &F, InformationCache &InfoCache,
382 DenseSet *Whitelist) {
383
384 // Walk all instructions to find more attribute opportunities and also
385 // interesting instructions that might be queried by abstract attributes
386 // during their initialization or update.
387 auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
388 auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
389
390 for (Instruction &I : instructions(&F)) {
391 bool IsInterestingOpcode = false;
392
393 // To allow easy access to all instructions in a function with a given
394 // opcode we store them in the InfoCache. As not all opcodes are interesting
395 // to concrete attributes we only cache the ones that are as identified in
396 // the following switch.
397 // Note: There are no concrete attributes now so this is initially empty.
398 switch (I.getOpcode()) {
399 default:
400 break;
401 }
402 if (IsInterestingOpcode)
403 InstOpcodeMap[I.getOpcode()].push_back(&I);
404 if (I.mayReadOrWriteMemory())
405 ReadOrWriteInsts.push_back(&I);
406 }
407 }
408
409 /// Helpers to ease debugging through output streams and print calls.
410 ///
411 ///{
412 raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
413 return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
414 }
415
416 raw_ostream &llvm::operator<<(raw_ostream &OS,
417 AbstractAttribute::ManifestPosition AP) {
418 switch (AP) {
419 case AbstractAttribute::MP_ARGUMENT:
420 return OS << "arg";
421 case AbstractAttribute::MP_CALL_SITE_ARGUMENT:
422 return OS << "cs_arg";
423 case AbstractAttribute::MP_FUNCTION:
424 return OS << "fn";
425 case AbstractAttribute::MP_RETURNED:
426 return OS << "fn_ret";
427 }
428 llvm_unreachable("Unknown attribute position!");
429 }
430
431 raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
432 return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
433 }
434
435 raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
436 AA.print(OS);
437 return OS;
438 }
439
440 void AbstractAttribute::print(raw_ostream &OS) const {
441 OS << "[" << getManifestPosition() << "][" << getAsStr() << "]["
442 << AnchoredVal.getName() << "]";
443 }
444 ///}
445
446 /// ----------------------------------------------------------------------------
447 /// Pass (Manager) Boilerplate
448 /// ----------------------------------------------------------------------------
449
450 static bool runAttributorOnModule(Module &M) {
451 if (DisableAttributor)
452 return false;
453
454 LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << M.size()
455 << " functions.\n");
456
457 // Create an Attributor and initially empty information cache that is filled
458 // while we identify default attribute opportunities.
459 Attributor A;
460 InformationCache InfoCache;
461
462 for (Function &F : M) {
463 // TODO: Not all attributes require an exact definition. Find a way to
464 // enable deduction for some but not all attributes in case the
465 // definition might be changed at runtime, see also
466 // http://lists.llvm.org/pipermail/llvm-dev/2018-February/121275.html.
467 // TODO: We could always determine abstract attributes and if sufficient
468 // information was found we could duplicate the functions that do not
469 // have an exact definition.
470 if (!F.hasExactDefinition()) {
471 NumFnWithoutExactDefinition++;
472 continue;
473 }
474
475 // For now we ignore naked and optnone functions.
476 if (F.hasFnAttribute(Attribute::Naked) ||
477 F.hasFnAttribute(Attribute::OptimizeNone))
478 continue;
479
480 NumFnWithExactDefinition++;
481
482 // Populate the Attributor with abstract attribute opportunities in the
483 // function and the information cache with IR information.
484 A.identifyDefaultAbstractAttributes(F, InfoCache);
485 }
486
487 return A.run() == ChangeStatus::CHANGED;
488 }
489
490 PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
491 if (runAttributorOnModule(M)) {
492 // FIXME: Think about passes we will preserve and add them here.
493 return PreservedAnalyses::none();
494 }
495 return PreservedAnalyses::all();
496 }
497
498 namespace {
499
500 struct AttributorLegacyPass : public ModulePass {
501 static char ID;
502
503 AttributorLegacyPass() : ModulePass(ID) {
504 initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry());
505 }
506
507 bool runOnModule(Module &M) override {
508 if (skipModule(M))
509 return false;
510 return runAttributorOnModule(M);
511 }
512
513 void getAnalysisUsage(AnalysisUsage &AU) const override {
514 // FIXME: Think about passes we will preserve and add them here.
515 AU.setPreservesCFG();
516 }
517 };
518
519 } // end anonymous namespace
520
521 Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); }
522
523 char AttributorLegacyPass::ID = 0;
524 INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor",
525 "Deduce and propagate attributes", false, false)
526 INITIALIZE_PASS_END(AttributorLegacyPass, "attributor",
527 "Deduce and propagate attributes", false, false)
528
0 add_llvm_library(LLVMipo
11 AlwaysInliner.cpp
22 ArgumentPromotion.cpp
3 Attributor.cpp
34 BarrierNoopPass.cpp
45 BlockExtractor.cpp
56 CalledValuePropagation.cpp
4444 initializeLowerTypeTestsPass(Registry);
4545 initializeMergeFunctionsPass(Registry);
4646 initializePartialInlinerLegacyPassPass(Registry);
47 initializeAttributorLegacyPassPass(Registry);
4748 initializePostOrderFunctionAttrsLegacyPassPass(Registry);
4849 initializeReversePostOrderFunctionAttrsLegacyPassPass(Registry);
4950 initializePruneEHPass(Registry);
2929 #include "llvm/Support/ManagedStatic.h"
3030 #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h"
3131 #include "llvm/Transforms/IPO.h"
32 #include "llvm/Transforms/IPO/Attributor.h"
3233 #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
3334 #include "llvm/Transforms/IPO/FunctionAttrs.h"
3435 #include "llvm/Transforms/IPO/InferFunctionAttrs.h"
514515
515516 MPM.add(createIPSCCPPass()); // IP SCCP
516517 MPM.add(createCalledValuePropagationPass());
518
519 // Infer attributes on declarations, call sites, arguments, etc.
520 MPM.add(createAttributorLegacyPass());
521
517522 MPM.add(createGlobalOptimizerPass()); // Optimize out global vars
518523 // Promote any localized global vars.
519524 MPM.add(createPromoteMemoryToRegisterPass());
818823 // Attach metadata to indirect call sites indicating the set of functions
819824 // they may target at run-time. This should follow IPSCCP.
820825 PM.add(createCalledValuePropagationPass());
826
827 // Infer attributes on declarations, call sites, arguments, etc.
828 PM.add(createAttributorLegacyPass());
821829 }
822830
823831 // Infer attributes about definitions. The readnone attribute in particular is
891899 // link-time inlining, and visibility of nocapture attribute.
892900 PM.add(createTailCallEliminationPass());
893901
902 // Infer attributes on declarations, call sites, arguments, etc.
903 PM.add(createPostOrderFunctionAttrsLegacyPass()); // Add nocapture.
894904 // Run a few AA driven optimizations here and now, to cleanup the code.
895 PM.add(createPostOrderFunctionAttrsLegacyPass()); // Add nocapture.
896905 PM.add(createGlobalsAAWrapperPass()); // IP alias analysis.
897906
898907 PM.add(createLICMPass(LicmMssaOptCap, LicmMssaNoAccForPromotionCap));
2929 ; CHECK-NEXT: Interprocedural Sparse Conditional Constant Propagation
3030 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
3131 ; CHECK-NEXT: Called Value Propagation
32 ; CHECK-NEXT: Deduce and propagate attributes
3233 ; CHECK-NEXT: Global Variable Optimizer
3334 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
3435 ; CHECK-NEXT: FunctionPass Manager
3232 ; CHECK-NEXT: Interprocedural Sparse Conditional Constant Propagation
3333 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
3434 ; CHECK-NEXT: Called Value Propagation
35 ; CHECK-NEXT: Deduce and propagate attributes
3536 ; CHECK-NEXT: Global Variable Optimizer
3637 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
3738 ; CHECK-NEXT: FunctionPass Manager
2929 ; CHECK-NEXT: Interprocedural Sparse Conditional Constant Propagation
3030 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
3131 ; CHECK-NEXT: Called Value Propagation
32 ; CHECK-NEXT: Deduce and propagate attributes
3233 ; CHECK-NEXT: Global Variable Optimizer
3334 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
3435 ; CHECK-NEXT: FunctionPass Manager
None ; RUN: opt -functionattrs -S < %s | FileCheck %s
0 ; RUN: opt -functionattrs -attributor -attributor-disable=false -S < %s | FileCheck %s
1 ; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-verify=true -S < %s | FileCheck %s
12 ;
23 ; Test cases specifically designed for the "no-capture" argument attribute.
34 ; We use FIXME's to indicate problems and missing attributes.
None ; RUN: opt -functionattrs -S < %s | FileCheck %s
0 ; RUN: opt -functionattrs -attributor -attributor-disable=false -S < %s | FileCheck %s
1 ; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-verify=true -S < %s | FileCheck %s
12 ;
23 ; Test cases specifically designed for the "returned" argument attribute.
34 ; We use FIXME's to indicate problems and missing attributes.
None ; RUN: opt -functionattrs -S < %s | FileCheck %s
0 ; RUN: opt -functionattrs -attributor -attributor-disable=false -S < %s | FileCheck %s
1 ; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-verify=true -S < %s | FileCheck %s
12 ;
23 ; Test cases specifically designed for the "no-return" function attribute.
34 ; We use FIXME's to indicate problems and missing attributes.
None ; RUN: opt -S -functionattrs -enable-nonnull-arg-prop %s | FileCheck %s
0 ; RUN: opt -functionattrs -enable-nonnull-arg-prop -attributor -attributor-disable=false -S < %s | FileCheck %s
1 ; RUN: opt -functionattrs -enable-nonnull-arg-prop -attributor -attributor-disable=false -attributor-verify=true -S < %s | FileCheck %s
12 ;
23 ; This is an evolved example to stress test SCC parameter attribute propagation.
34 ; The SCC in this test is made up of the following six function, three of which