1 //===- Attributor.cpp - Module-wide attribute deduction -------------------===//
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 // This file implements an inter procedural pass that deduces and/or propagating
10 // attributes. This is done in an abstract interpretation style fixpoint
11 // iteration. See the Attributor.h file comment and the class descriptions in
12 // that file for more information.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "llvm/Transforms/IPO/Attributor.h"
17 
18 #include "llvm/ADT/SetVector.h"
19 #include "llvm/ADT/SmallPtrSet.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/Statistic.h"
22 #include "llvm/Analysis/GlobalsModRef.h"
23 #include "llvm/IR/Argument.h"
24 #include "llvm/IR/Attributes.h"
25 #include "llvm/IR/InstIterator.h"
26 #include "llvm/Support/CommandLine.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include <cassert>
30 
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "attributor"
34 
35 STATISTIC(NumFnWithExactDefinition,
36           "Number of function with exact definitions");
37 STATISTIC(NumFnWithoutExactDefinition,
38           "Number of function without exact definitions");
39 STATISTIC(NumAttributesTimedOut,
40           "Number of abstract attributes timed out before fixpoint");
41 STATISTIC(NumAttributesValidFixpoint,
42           "Number of abstract attributes in a valid fixpoint state");
43 STATISTIC(NumAttributesManifested,
44           "Number of abstract attributes manifested in IR");
45 STATISTIC(NumFnNoUnwind, "Number of functions marked nounwind");
46 
47 // TODO: Determine a good default value.
48 //
49 // In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads
50 // (when run with the first 5 abstract attributes). The results also indicate
51 // that we never reach 32 iterations but always find a fixpoint sooner.
52 //
53 // This will become more evolved once we perform two interleaved fixpoint
54 // iterations: bottom-up and top-down.
55 static cl::opt<unsigned>
56     MaxFixpointIterations("attributor-max-iterations", cl::Hidden,
57                           cl::desc("Maximal number of fixpoint iterations."),
58                           cl::init(32));
59 
60 static cl::opt<bool> DisableAttributor(
61     "attributor-disable", cl::Hidden,
62     cl::desc("Disable the attributor inter-procedural deduction pass."),
63     cl::init(true));
64 
65 static cl::opt<bool> VerifyAttributor(
66     "attributor-verify", cl::Hidden,
67     cl::desc("Verify the Attributor deduction and "
68              "manifestation of attributes -- may issue false-positive errors"),
69     cl::init(false));
70 
71 /// Logic operators for the change status enum class.
72 ///
73 ///{
74 ChangeStatus llvm::operator|(ChangeStatus l, ChangeStatus r) {
75   return l == ChangeStatus::CHANGED ? l : r;
76 }
77 ChangeStatus llvm::operator&(ChangeStatus l, ChangeStatus r) {
78   return l == ChangeStatus::UNCHANGED ? l : r;
79 }
80 ///}
81 
82 /// Helper to adjust the statistics.
83 static void bookkeeping(AbstractAttribute::ManifestPosition MP,
84                         const Attribute &Attr) {
85   if (!AreStatisticsEnabled())
86     return;
87 
88   if (!Attr.isEnumAttribute())
89     return;
90   switch (Attr.getKindAsEnum()) {
91   case Attribute::NoUnwind:
92     NumFnNoUnwind++;
93     return;
94   default:
95     return;
96   }
97 }
98 
99 /// Helper to identify the correct offset into an attribute list.
100 static unsigned getAttrIndex(AbstractAttribute::ManifestPosition MP,
101                              unsigned ArgNo = 0) {
102   switch (MP) {
103   case AbstractAttribute::MP_ARGUMENT:
104   case AbstractAttribute::MP_CALL_SITE_ARGUMENT:
105     return ArgNo + AttributeList::FirstArgIndex;
106   case AbstractAttribute::MP_FUNCTION:
107     return AttributeList::FunctionIndex;
108   case AbstractAttribute::MP_RETURNED:
109     return AttributeList::ReturnIndex;
110   }
111   llvm_unreachable("Unknown manifest position!");
112 }
113 
114 /// Return true if \p New is equal or worse than \p Old.
115 static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) {
116   if (!Old.isIntAttribute())
117     return true;
118 
119   return Old.getValueAsInt() >= New.getValueAsInt();
120 }
121 
122 /// Return true if the information provided by \p Attr was added to the
123 /// attribute list \p Attrs. This is only the case if it was not already present
124 /// in \p Attrs at the position describe by \p MP and \p ArgNo.
125 static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
126                              AttributeList &Attrs,
127                              AbstractAttribute::ManifestPosition MP,
128                              unsigned ArgNo = 0) {
129   unsigned AttrIdx = getAttrIndex(MP, ArgNo);
130 
131   if (Attr.isEnumAttribute()) {
132     Attribute::AttrKind Kind = Attr.getKindAsEnum();
133     if (Attrs.hasAttribute(AttrIdx, Kind))
134       if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
135         return false;
136     Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
137     return true;
138   }
139   if (Attr.isStringAttribute()) {
140     StringRef Kind = Attr.getKindAsString();
141     if (Attrs.hasAttribute(AttrIdx, Kind))
142       if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
143         return false;
144     Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
145     return true;
146   }
147 
148   llvm_unreachable("Expected enum or string attribute!");
149 }
150 
151 ChangeStatus AbstractAttribute::update(Attributor &A) {
152   ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
153   if (getState().isAtFixpoint())
154     return HasChanged;
155 
156   LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");
157 
158   HasChanged = updateImpl(A);
159 
160   LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
161                     << "\n");
162 
163   return HasChanged;
164 }
165 
166 ChangeStatus AbstractAttribute::manifest(Attributor &A) {
167   assert(getState().isValidState() &&
168          "Attempted to manifest an invalid state!");
169   assert(getAssociatedValue() &&
170          "Attempted to manifest an attribute without associated value!");
171 
172   ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
173   SmallVector<Attribute, 4> DeducedAttrs;
174   getDeducedAttributes(DeducedAttrs);
175 
176   Function &ScopeFn = getAnchorScope();
177   LLVMContext &Ctx = ScopeFn.getContext();
178   ManifestPosition MP = getManifestPosition();
179 
180   AttributeList Attrs;
181   SmallVector<unsigned, 4> ArgNos;
182 
183   // In the following some generic code that will manifest attributes in
184   // DeducedAttrs if they improve the current IR. Due to the different
185   // annotation positions we use the underlying AttributeList interface.
186   // Note that MP_CALL_SITE_ARGUMENT can annotate multiple locations.
187 
188   switch (MP) {
189   case MP_ARGUMENT:
190     ArgNos.push_back(cast<Argument>(getAssociatedValue())->getArgNo());
191     Attrs = ScopeFn.getAttributes();
192     break;
193   case MP_FUNCTION:
194   case MP_RETURNED:
195     ArgNos.push_back(0);
196     Attrs = ScopeFn.getAttributes();
197     break;
198   case MP_CALL_SITE_ARGUMENT: {
199     CallSite CS(&getAnchoredValue());
200     for (unsigned u = 0, e = CS.getNumArgOperands(); u != e; u++)
201       if (CS.getArgOperand(u) == getAssociatedValue())
202         ArgNos.push_back(u);
203     Attrs = CS.getAttributes();
204   }
205   }
206 
207   for (const Attribute &Attr : DeducedAttrs) {
208     for (unsigned ArgNo : ArgNos) {
209       if (!addIfNotExistent(Ctx, Attr, Attrs, MP, ArgNo))
210         continue;
211 
212       HasChanged = ChangeStatus::CHANGED;
213       bookkeeping(MP, Attr);
214     }
215   }
216 
217   if (HasChanged == ChangeStatus::UNCHANGED)
218     return HasChanged;
219 
220   switch (MP) {
221   case MP_ARGUMENT:
222   case MP_FUNCTION:
223   case MP_RETURNED:
224     ScopeFn.setAttributes(Attrs);
225     break;
226   case MP_CALL_SITE_ARGUMENT:
227     CallSite(&getAnchoredValue()).setAttributes(Attrs);
228   }
229 
230   return HasChanged;
231 }
232 
233 Function &AbstractAttribute::getAnchorScope() {
234   Value &V = getAnchoredValue();
235   if (isa<Function>(V))
236     return cast<Function>(V);
237   if (isa<Argument>(V))
238     return *cast<Argument>(V).getParent();
239   if (isa<Instruction>(V))
240     return *cast<Instruction>(V).getFunction();
241   llvm_unreachable("No scope for anchored value found!");
242 }
243 
244 const Function &AbstractAttribute::getAnchorScope() const {
245   return const_cast<AbstractAttribute *>(this)->getAnchorScope();
246 }
247 
248 /// -----------------------NoUnwind Function Attribute--------------------------
249 
250 struct AANoUnwindFunction : AANoUnwind, BooleanState {
251 
252   AANoUnwindFunction(Function &F, InformationCache &InfoCache)
253       : AANoUnwind(F, InfoCache) {}
254 
255   /// See AbstractAttribute::getState()
256   /// {
257   AbstractState &getState() override { return *this; }
258   const AbstractState &getState() const override { return *this; }
259   /// }
260 
261   /// See AbstractAttribute::getManifestPosition().
262   virtual ManifestPosition getManifestPosition() const override {
263     return MP_FUNCTION;
264   }
265 
266   virtual const std::string getAsStr() const override {
267     return getAssumed() ? "nounwind" : "may-unwind";
268   }
269 
270   /// See AbstractAttribute::updateImpl(...).
271   virtual ChangeStatus updateImpl(Attributor &A) override;
272 
273   /// See AANoUnwind::isAssumedNoUnwind().
274   virtual bool isAssumedNoUnwind() const override { return getAssumed(); }
275 
276   /// See AANoUnwind::isKnownNoUnwind().
277   virtual bool isKnownNoUnwind() const override { return getKnown(); }
278 };
279 
280 ChangeStatus AANoUnwindFunction::updateImpl(Attributor &A) {
281   Function &F = getAnchorScope();
282 
283   // The map from instruction opcodes to those instructions in the function.
284   auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
285   auto Opcodes = {
286       (unsigned)Instruction::Invoke,      (unsigned)Instruction::CallBr,
287       (unsigned)Instruction::Call,        (unsigned)Instruction::CleanupRet,
288       (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
289 
290   for (unsigned Opcode : Opcodes) {
291     for (Instruction *I : OpcodeInstMap[Opcode]) {
292       if (!I->mayThrow())
293         continue;
294 
295       auto *NoUnwindAA = A.getAAFor<AANoUnwind>(*this, *I);
296 
297       if (!NoUnwindAA || !NoUnwindAA->isAssumedNoUnwind()) {
298         indicatePessimisticFixpoint();
299         return ChangeStatus::CHANGED;
300       }
301     }
302   }
303   return ChangeStatus::UNCHANGED;
304 }
305 
306 /// ----------------------------------------------------------------------------
307 ///                               Attributor
308 /// ----------------------------------------------------------------------------
309 
310 ChangeStatus Attributor::run() {
311   // Initialize all abstract attributes.
312   for (AbstractAttribute *AA : AllAbstractAttributes)
313     AA->initialize(*this);
314 
315   LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
316                     << AllAbstractAttributes.size()
317                     << " abstract attributes.\n");
318 
319   // Now that all abstract attributes are collected and initialized we start
320   // the abstract analysis.
321 
322   unsigned IterationCounter = 1;
323 
324   SmallVector<AbstractAttribute *, 64> ChangedAAs;
325   SetVector<AbstractAttribute *> Worklist;
326   Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
327 
328   do {
329     LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
330                       << ", Worklist size: " << Worklist.size() << "\n");
331 
332     // Add all abstract attributes that are potentially dependent on one that
333     // changed to the work list.
334     for (AbstractAttribute *ChangedAA : ChangedAAs) {
335       auto &QuerriedAAs = QueryMap[ChangedAA];
336       Worklist.insert(QuerriedAAs.begin(), QuerriedAAs.end());
337     }
338 
339     // Reset the changed set.
340     ChangedAAs.clear();
341 
342     // Update all abstract attribute in the work list and record the ones that
343     // changed.
344     for (AbstractAttribute *AA : Worklist)
345       if (AA->update(*this) == ChangeStatus::CHANGED)
346         ChangedAAs.push_back(AA);
347 
348     // Reset the work list and repopulate with the changed abstract attributes.
349     // Note that dependent ones are added above.
350     Worklist.clear();
351     Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
352 
353   } while (!Worklist.empty() && ++IterationCounter < MaxFixpointIterations);
354 
355   LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
356                     << IterationCounter << "/" << MaxFixpointIterations
357                     << " iterations\n");
358 
359   bool FinishedAtFixpoint = Worklist.empty();
360 
361   // Reset abstract arguments not settled in a sound fixpoint by now. This
362   // happens when we stopped the fixpoint iteration early. Note that only the
363   // ones marked as "changed" *and* the ones transitively depending on them
364   // need to be reverted to a pessimistic state. Others might not be in a
365   // fixpoint state but we can use the optimistic results for them anyway.
366   SmallPtrSet<AbstractAttribute *, 32> Visited;
367   for (unsigned u = 0; u < ChangedAAs.size(); u++) {
368     AbstractAttribute *ChangedAA = ChangedAAs[u];
369     if (!Visited.insert(ChangedAA).second)
370       continue;
371 
372     AbstractState &State = ChangedAA->getState();
373     if (!State.isAtFixpoint()) {
374       State.indicatePessimisticFixpoint();
375 
376       NumAttributesTimedOut++;
377     }
378 
379     auto &QuerriedAAs = QueryMap[ChangedAA];
380     ChangedAAs.append(QuerriedAAs.begin(), QuerriedAAs.end());
381   }
382 
383   LLVM_DEBUG({
384     if (!Visited.empty())
385       dbgs() << "\n[Attributor] Finalized " << Visited.size()
386              << " abstract attributes.\n";
387   });
388 
389   unsigned NumManifested = 0;
390   unsigned NumAtFixpoint = 0;
391   ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
392   for (AbstractAttribute *AA : AllAbstractAttributes) {
393     AbstractState &State = AA->getState();
394 
395     // If there is not already a fixpoint reached, we can now take the
396     // optimistic state. This is correct because we enforced a pessimistic one
397     // on abstract attributes that were transitively dependent on a changed one
398     // already above.
399     if (!State.isAtFixpoint())
400       State.indicateOptimisticFixpoint();
401 
402     // If the state is invalid, we do not try to manifest it.
403     if (!State.isValidState())
404       continue;
405 
406     // Manifest the state and record if we changed the IR.
407     ChangeStatus LocalChange = AA->manifest(*this);
408     ManifestChange = ManifestChange | LocalChange;
409 
410     NumAtFixpoint++;
411     NumManifested += (LocalChange == ChangeStatus::CHANGED);
412   }
413 
414   (void)NumManifested;
415   (void)NumAtFixpoint;
416   LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
417                     << " arguments while " << NumAtFixpoint
418                     << " were in a valid fixpoint state\n");
419 
420   // If verification is requested, we finished this run at a fixpoint, and the
421   // IR was changed, we re-run the whole fixpoint analysis, starting at
422   // re-initialization of the arguments. This re-run should not result in an IR
423   // change. Though, the (virtual) state of attributes at the end of the re-run
424   // might be more optimistic than the known state or the IR state if the better
425   // state cannot be manifested.
426   if (VerifyAttributor && FinishedAtFixpoint &&
427       ManifestChange == ChangeStatus::CHANGED) {
428     VerifyAttributor = false;
429     ChangeStatus VerifyStatus = run();
430     if (VerifyStatus != ChangeStatus::UNCHANGED)
431       llvm_unreachable(
432           "Attributor verification failed, re-run did result in an IR change "
433           "even after a fixpoint was reached in the original run. (False "
434           "positives possible!)");
435     VerifyAttributor = true;
436   }
437 
438   NumAttributesManifested += NumManifested;
439   NumAttributesValidFixpoint += NumAtFixpoint;
440 
441   return ManifestChange;
442 }
443 
444 void Attributor::identifyDefaultAbstractAttributes(
445     Function &F, InformationCache &InfoCache,
446     DenseSet</* Attribute::AttrKind */ unsigned> *Whitelist) {
447 
448   // Every function can be nounwind.
449   registerAA(*new AANoUnwindFunction(F, InfoCache));
450 
451   // Walk all instructions to find more attribute opportunities and also
452   // interesting instructions that might be queried by abstract attributes
453   // during their initialization or update.
454   auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
455   auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
456 
457   for (Instruction &I : instructions(&F)) {
458     bool IsInterestingOpcode = false;
459 
460     // To allow easy access to all instructions in a function with a given
461     // opcode we store them in the InfoCache. As not all opcodes are interesting
462     // to concrete attributes we only cache the ones that are as identified in
463     // the following switch.
464     // Note: There are no concrete attributes now so this is initially empty.
465     switch (I.getOpcode()) {
466     default:
467       assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) &&
468              "New call site/base instruction type needs to be known int the "
469              "attributor.");
470       break;
471     case Instruction::Call:
472     case Instruction::CallBr:
473     case Instruction::Invoke:
474     case Instruction::CleanupRet:
475     case Instruction::CatchSwitch:
476     case Instruction::Resume:
477       IsInterestingOpcode = true;
478     }
479     if (IsInterestingOpcode)
480       InstOpcodeMap[I.getOpcode()].push_back(&I);
481     if (I.mayReadOrWriteMemory())
482       ReadOrWriteInsts.push_back(&I);
483   }
484 }
485 
486 /// Helpers to ease debugging through output streams and print calls.
487 ///
488 ///{
489 raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
490   return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
491 }
492 
493 raw_ostream &llvm::operator<<(raw_ostream &OS,
494                               AbstractAttribute::ManifestPosition AP) {
495   switch (AP) {
496   case AbstractAttribute::MP_ARGUMENT:
497     return OS << "arg";
498   case AbstractAttribute::MP_CALL_SITE_ARGUMENT:
499     return OS << "cs_arg";
500   case AbstractAttribute::MP_FUNCTION:
501     return OS << "fn";
502   case AbstractAttribute::MP_RETURNED:
503     return OS << "fn_ret";
504   }
505   llvm_unreachable("Unknown attribute position!");
506 }
507 
508 raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
509   return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
510 }
511 
512 raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
513   AA.print(OS);
514   return OS;
515 }
516 
517 void AbstractAttribute::print(raw_ostream &OS) const {
518   OS << "[" << getManifestPosition() << "][" << getAsStr() << "]["
519      << AnchoredVal.getName() << "]";
520 }
521 ///}
522 
523 /// ----------------------------------------------------------------------------
524 ///                       Pass (Manager) Boilerplate
525 /// ----------------------------------------------------------------------------
526 
527 static bool runAttributorOnModule(Module &M) {
528   if (DisableAttributor)
529     return false;
530 
531   LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << M.size()
532                     << " functions.\n");
533 
534   // Create an Attributor and initially empty information cache that is filled
535   // while we identify default attribute opportunities.
536   Attributor A;
537   InformationCache InfoCache;
538 
539   for (Function &F : M) {
540     // TODO: Not all attributes require an exact definition. Find a way to
541     //       enable deduction for some but not all attributes in case the
542     //       definition might be changed at runtime, see also
543     //       http://lists.llvm.org/pipermail/llvm-dev/2018-February/121275.html.
544     // TODO: We could always determine abstract attributes and if sufficient
545     //       information was found we could duplicate the functions that do not
546     //       have an exact definition.
547     if (!F.hasExactDefinition()) {
548       NumFnWithoutExactDefinition++;
549       continue;
550     }
551 
552     // For now we ignore naked and optnone functions.
553     if (F.hasFnAttribute(Attribute::Naked) ||
554         F.hasFnAttribute(Attribute::OptimizeNone))
555       continue;
556 
557     NumFnWithExactDefinition++;
558 
559     // Populate the Attributor with abstract attribute opportunities in the
560     // function and the information cache with IR information.
561     A.identifyDefaultAbstractAttributes(F, InfoCache);
562   }
563 
564   return A.run() == ChangeStatus::CHANGED;
565 }
566 
567 PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
568   if (runAttributorOnModule(M)) {
569     // FIXME: Think about passes we will preserve and add them here.
570     return PreservedAnalyses::none();
571   }
572   return PreservedAnalyses::all();
573 }
574 
575 namespace {
576 
577 struct AttributorLegacyPass : public ModulePass {
578   static char ID;
579 
580   AttributorLegacyPass() : ModulePass(ID) {
581     initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry());
582   }
583 
584   bool runOnModule(Module &M) override {
585     if (skipModule(M))
586       return false;
587     return runAttributorOnModule(M);
588   }
589 
590   void getAnalysisUsage(AnalysisUsage &AU) const override {
591     // FIXME: Think about passes we will preserve and add them here.
592     AU.setPreservesCFG();
593   }
594 };
595 
596 } // end anonymous namespace
597 
598 Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); }
599 
600 char AttributorLegacyPass::ID = 0;
601 INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor",
602                       "Deduce and propagate attributes", false, false)
603 INITIALIZE_PASS_END(AttributorLegacyPass, "attributor",
604                     "Deduce and propagate attributes", false, false)
605