blob: aac00d5b994ae4236f55151f8a90cd80689cb116 [file] [log] [blame]
Johannes Doerfertaade7822019-06-05 03:02:24 +00001//===- 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
Hideto Ueno11d37102019-07-17 15:15:43 +000018#include "llvm/ADT/DepthFirstIterator.h"
Stefan Stipanovic6058b862019-07-22 23:58:23 +000019#include "llvm/ADT/STLExtras.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000020#include "llvm/ADT/SetVector.h"
21#include "llvm/ADT/SmallPtrSet.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/Statistic.h"
Stefan Stipanovic69ebb022019-07-22 19:36:27 +000024#include "llvm/Analysis/CaptureTracking.h"
Johannes Doerfert924d2132019-08-05 21:34:45 +000025#include "llvm/Analysis/EHPersonalities.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000026#include "llvm/Analysis/GlobalsModRef.h"
Hideto Ueno19c07af2019-07-23 08:16:17 +000027#include "llvm/Analysis/Loads.h"
Hideto Ueno54869ec2019-07-15 06:49:04 +000028#include "llvm/Analysis/ValueTracking.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000029#include "llvm/IR/Argument.h"
30#include "llvm/IR/Attributes.h"
Hideto Ueno11d37102019-07-17 15:15:43 +000031#include "llvm/IR/CFG.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000032#include "llvm/IR/InstIterator.h"
Stefan Stipanovic06263672019-07-11 21:37:40 +000033#include "llvm/IR/IntrinsicInst.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000034#include "llvm/Support/CommandLine.h"
35#include "llvm/Support/Debug.h"
36#include "llvm/Support/raw_ostream.h"
Stefan Stipanovic6058b862019-07-22 23:58:23 +000037#include "llvm/Transforms/Utils/BasicBlockUtils.h"
38#include "llvm/Transforms/Utils/Local.h"
39
Johannes Doerfertaade7822019-06-05 03:02:24 +000040#include <cassert>
41
42using namespace llvm;
43
44#define DEBUG_TYPE "attributor"
45
46STATISTIC(NumFnWithExactDefinition,
47 "Number of function with exact definitions");
48STATISTIC(NumFnWithoutExactDefinition,
49 "Number of function without exact definitions");
50STATISTIC(NumAttributesTimedOut,
51 "Number of abstract attributes timed out before fixpoint");
52STATISTIC(NumAttributesValidFixpoint,
53 "Number of abstract attributes in a valid fixpoint state");
54STATISTIC(NumAttributesManifested,
55 "Number of abstract attributes manifested in IR");
56
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000057// Some helper macros to deal with statistics tracking.
58//
59// Usage:
60// For simple IR attribute tracking overload trackStatistics in the abstract
Johannes Doerfert17b578b2019-08-14 21:46:25 +000061// attribute and choose the right STATS_DECLTRACK_********* macro,
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000062// e.g.,:
63// void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +000064// STATS_DECLTRACK_ARG_ATTR(returned)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000065// }
66// If there is a single "increment" side one can use the macro
Johannes Doerfert17b578b2019-08-14 21:46:25 +000067// STATS_DECLTRACK with a custom message. If there are multiple increment
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000068// sides, STATS_DECL and STATS_TRACK can also be used separatly.
69//
70#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
71 ("Number of " #TYPE " marked '" #NAME "'")
72#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
73#define STATS_DECL(NAME, TYPE, MSG) STATISTIC(BUILD_STAT_NAME(NAME, TYPE), MSG);
74#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
Johannes Doerfert17b578b2019-08-14 21:46:25 +000075#define STATS_DECLTRACK(NAME, TYPE, MSG) \
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000076 STATS_DECL(NAME, TYPE, MSG) \
77 STATS_TRACK(NAME, TYPE)
Johannes Doerfert17b578b2019-08-14 21:46:25 +000078#define STATS_DECLTRACK_ARG_ATTR(NAME) \
79 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
80#define STATS_DECLTRACK_CSARG_ATTR(NAME) \
81 STATS_DECLTRACK(NAME, CSArguments, \
82 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
83#define STATS_DECLTRACK_FN_ATTR(NAME) \
84 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
85#define STATS_DECLTRACK_CS_ATTR(NAME) \
86 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
87#define STATS_DECLTRACK_FNRET_ATTR(NAME) \
88 STATS_DECLTRACK(NAME, FunctionReturn, \
89 BUILD_STAT_MSG_IR_ATTR(function returns, NAME));
90#define STATS_DECLTRACK_CSRET_ATTR(NAME) \
91 STATS_DECLTRACK(NAME, CSReturn, \
92 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
93#define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
94 STATS_DECLTRACK(NAME, Floating, \
95 ("Number of floating values known to be '" #NAME "'"))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +000096
Johannes Doerfertaade7822019-06-05 03:02:24 +000097// TODO: Determine a good default value.
98//
99// In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads
100// (when run with the first 5 abstract attributes). The results also indicate
101// that we never reach 32 iterations but always find a fixpoint sooner.
102//
103// This will become more evolved once we perform two interleaved fixpoint
104// iterations: bottom-up and top-down.
105static cl::opt<unsigned>
106 MaxFixpointIterations("attributor-max-iterations", cl::Hidden,
107 cl::desc("Maximal number of fixpoint iterations."),
108 cl::init(32));
109
110static cl::opt<bool> DisableAttributor(
111 "attributor-disable", cl::Hidden,
112 cl::desc("Disable the attributor inter-procedural deduction pass."),
Johannes Doerfert282d34e2019-06-14 14:53:41 +0000113 cl::init(true));
Johannes Doerfertaade7822019-06-05 03:02:24 +0000114
115static cl::opt<bool> VerifyAttributor(
116 "attributor-verify", cl::Hidden,
117 cl::desc("Verify the Attributor deduction and "
118 "manifestation of attributes -- may issue false-positive errors"),
119 cl::init(false));
120
121/// Logic operators for the change status enum class.
122///
123///{
124ChangeStatus llvm::operator|(ChangeStatus l, ChangeStatus r) {
125 return l == ChangeStatus::CHANGED ? l : r;
126}
127ChangeStatus llvm::operator&(ChangeStatus l, ChangeStatus r) {
128 return l == ChangeStatus::UNCHANGED ? l : r;
129}
130///}
131
Johannes Doerfertdef99282019-08-14 21:29:37 +0000132/// Recursively visit all values that might become \p IRP at some point. This
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000133/// will be done by looking through cast instructions, selects, phis, and calls
Johannes Doerfertdef99282019-08-14 21:29:37 +0000134/// with the "returned" attribute. Once we cannot look through the value any
135/// further, the callback \p VisitValueCB is invoked and passed the current
136/// value, the \p State, and a flag to indicate if we stripped anything. To
137/// limit how much effort is invested, we will never visit more values than
138/// specified by \p MaxValues.
139template <typename AAType, typename StateTy>
140bool genericValueTraversal(
141 Attributor &A, IRPosition IRP, const AAType &QueryingAA, StateTy &State,
142 const function_ref<void(Value &, StateTy &, bool)> &VisitValueCB,
143 int MaxValues = 8) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000144
Johannes Doerfertdef99282019-08-14 21:29:37 +0000145 const AAIsDead *LivenessAA = nullptr;
146 if (IRP.getAnchorScope())
147 LivenessAA = A.getAAFor<AAIsDead>(
148 QueryingAA, IRPosition::function(*IRP.getAnchorScope()));
149
150 // TODO: Use Positions here to allow context sensitivity in VisitValueCB
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000151 SmallPtrSet<Value *, 16> Visited;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000152 SmallVector<Value *, 16> Worklist;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000153 Worklist.push_back(&IRP.getAssociatedValue());
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000154
155 int Iteration = 0;
156 do {
157 Value *V = Worklist.pop_back_val();
158
159 // Check if we should process the current value. To prevent endless
160 // recursion keep a record of the values we followed!
Johannes Doerfertdef99282019-08-14 21:29:37 +0000161 if (!Visited.insert(V).second)
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000162 continue;
163
164 // Make sure we limit the compile time for complex expressions.
165 if (Iteration++ >= MaxValues)
166 return false;
167
168 // Explicitly look through calls with a "returned" attribute if we do
169 // not have a pointer as stripPointerCasts only works on them.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000170 Value *NewV = nullptr;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000171 if (V->getType()->isPointerTy()) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000172 NewV = V->stripPointerCasts();
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000173 } else {
174 CallSite CS(V);
175 if (CS && CS.getCalledFunction()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000176 for (Argument &Arg : CS.getCalledFunction()->args())
177 if (Arg.hasReturnedAttr()) {
178 NewV = CS.getArgOperand(Arg.getArgNo());
179 break;
180 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000181 }
182 }
Johannes Doerfertdef99282019-08-14 21:29:37 +0000183 if (NewV && NewV != V) {
184 Worklist.push_back(NewV);
185 continue;
186 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000187
188 // Look through select instructions, visit both potential values.
189 if (auto *SI = dyn_cast<SelectInst>(V)) {
190 Worklist.push_back(SI->getTrueValue());
191 Worklist.push_back(SI->getFalseValue());
192 continue;
193 }
194
Johannes Doerfertdef99282019-08-14 21:29:37 +0000195 // Look through phi nodes, visit all live operands.
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000196 if (auto *PHI = dyn_cast<PHINode>(V)) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000197 for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
198 const BasicBlock *IncomingBB = PHI->getIncomingBlock(u);
199 if (!LivenessAA ||
200 !LivenessAA->isAssumedDead(IncomingBB->getTerminator()))
201 Worklist.push_back(PHI->getIncomingValue(u));
202 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000203 continue;
204 }
205
206 // Once a leaf is reached we inform the user through the callback.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000207 VisitValueCB(*V, State, Iteration > 1);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000208 } while (!Worklist.empty());
209
210 // All values have been visited.
211 return true;
212}
213
Johannes Doerfertaade7822019-06-05 03:02:24 +0000214/// Return true if \p New is equal or worse than \p Old.
215static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) {
216 if (!Old.isIntAttribute())
217 return true;
218
219 return Old.getValueAsInt() >= New.getValueAsInt();
220}
221
222/// Return true if the information provided by \p Attr was added to the
223/// attribute list \p Attrs. This is only the case if it was not already present
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000224/// in \p Attrs at the position describe by \p PK and \p AttrIdx.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000225static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000226 AttributeList &Attrs, int AttrIdx) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000227
228 if (Attr.isEnumAttribute()) {
229 Attribute::AttrKind Kind = Attr.getKindAsEnum();
230 if (Attrs.hasAttribute(AttrIdx, Kind))
231 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
232 return false;
233 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
234 return true;
235 }
236 if (Attr.isStringAttribute()) {
237 StringRef Kind = Attr.getKindAsString();
238 if (Attrs.hasAttribute(AttrIdx, Kind))
239 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
240 return false;
241 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
242 return true;
243 }
Hideto Ueno19c07af2019-07-23 08:16:17 +0000244 if (Attr.isIntAttribute()) {
245 Attribute::AttrKind Kind = Attr.getKindAsEnum();
246 if (Attrs.hasAttribute(AttrIdx, Kind))
247 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
248 return false;
249 Attrs = Attrs.removeAttribute(Ctx, AttrIdx, Kind);
250 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
251 return true;
252 }
Johannes Doerfertaade7822019-06-05 03:02:24 +0000253
254 llvm_unreachable("Expected enum or string attribute!");
255}
256
Johannes Doerfertece81902019-08-12 22:05:53 +0000257ChangeStatus AbstractAttribute::update(Attributor &A) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000258 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
259 if (getState().isAtFixpoint())
260 return HasChanged;
261
262 LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");
263
Johannes Doerfertece81902019-08-12 22:05:53 +0000264 HasChanged = updateImpl(A);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000265
266 LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
267 << "\n");
268
269 return HasChanged;
270}
271
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000272ChangeStatus
273IRAttributeManifest::manifestAttrs(Attributor &A, IRPosition &IRP,
274 const ArrayRef<Attribute> &DeducedAttrs) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000275 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000276
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000277 Function *ScopeFn = IRP.getAssociatedFunction();
Kristina Brooks26e60f02019-08-06 19:53:19 +0000278 IRPosition::Kind PK = IRP.getPositionKind();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000279
Johannes Doerfertaade7822019-06-05 03:02:24 +0000280 // In the following some generic code that will manifest attributes in
281 // DeducedAttrs if they improve the current IR. Due to the different
282 // annotation positions we use the underlying AttributeList interface.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000283
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000284 AttributeList Attrs;
285 switch (PK) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000286 case IRPosition::IRP_INVALID:
287 case IRPosition::IRP_FLOAT:
288 llvm_unreachable("Cannot manifest at a floating or invalid position!");
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000289 case IRPosition::IRP_ARGUMENT:
290 case IRPosition::IRP_FUNCTION:
291 case IRPosition::IRP_RETURNED:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000292 Attrs = ScopeFn->getAttributes();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000293 break;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000294 case IRPosition::IRP_CALL_SITE:
295 case IRPosition::IRP_CALL_SITE_RETURNED:
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000296 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000297 Attrs = ImmutableCallSite(&IRP.getAnchorValue()).getAttributes();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000298 break;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000299 }
300
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000301 LLVMContext &Ctx = IRP.getAnchorValue().getContext();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000302 for (const Attribute &Attr : DeducedAttrs) {
Kristina Brooks26e60f02019-08-06 19:53:19 +0000303 if (!addIfNotExistent(Ctx, Attr, Attrs, IRP.getAttrIdx()))
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000304 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000305
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000306 HasChanged = ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000307 }
308
309 if (HasChanged == ChangeStatus::UNCHANGED)
310 return HasChanged;
311
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000312 switch (PK) {
313 case IRPosition::IRP_ARGUMENT:
314 case IRPosition::IRP_FUNCTION:
315 case IRPosition::IRP_RETURNED:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000316 ScopeFn->setAttributes(Attrs);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000317 break;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000318 case IRPosition::IRP_CALL_SITE:
319 case IRPosition::IRP_CALL_SITE_RETURNED:
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000320 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000321 CallSite(&IRP.getAnchorValue()).setAttributes(Attrs);
Johannes Doerfert4395b312019-08-14 21:46:28 +0000322 break;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000323 case IRPosition::IRP_INVALID:
Johannes Doerfert4395b312019-08-14 21:46:28 +0000324 case IRPosition::IRP_FLOAT:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000325 break;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000326 }
327
328 return HasChanged;
329}
330
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000331const IRPosition IRPosition::EmptyKey(255);
332const IRPosition IRPosition::TombstoneKey(256);
333
334SubsumingPositionIterator::SubsumingPositionIterator(const IRPosition &IRP) {
335 IRPositions.emplace_back(IRP);
336
337 ImmutableCallSite ICS(&IRP.getAnchorValue());
338 switch (IRP.getPositionKind()) {
339 case IRPosition::IRP_INVALID:
340 case IRPosition::IRP_FLOAT:
341 case IRPosition::IRP_FUNCTION:
342 return;
343 case IRPosition::IRP_ARGUMENT:
344 case IRPosition::IRP_RETURNED:
345 IRPositions.emplace_back(
346 IRPosition::function(*IRP.getAssociatedFunction()));
347 return;
348 case IRPosition::IRP_CALL_SITE:
349 assert(ICS && "Expected call site!");
350 // TODO: We need to look at the operand bundles similar to the redirection
351 // in CallBase.
352 if (!ICS.hasOperandBundles())
353 if (const Function *Callee = ICS.getCalledFunction())
354 IRPositions.emplace_back(IRPosition::function(*Callee));
355 return;
356 case IRPosition::IRP_CALL_SITE_RETURNED:
357 assert(ICS && "Expected call site!");
358 // TODO: We need to look at the operand bundles similar to the redirection
359 // in CallBase.
360 if (!ICS.hasOperandBundles()) {
361 if (const Function *Callee = ICS.getCalledFunction()) {
362 IRPositions.emplace_back(IRPosition::returned(*Callee));
363 IRPositions.emplace_back(IRPosition::function(*Callee));
364 }
365 }
366 IRPositions.emplace_back(
367 IRPosition::callsite_function(cast<CallBase>(*ICS.getInstruction())));
368 return;
369 case IRPosition::IRP_CALL_SITE_ARGUMENT: {
370 int ArgNo = IRP.getArgNo();
371 assert(ICS && ArgNo >= 0 && "Expected call site!");
372 // TODO: We need to look at the operand bundles similar to the redirection
373 // in CallBase.
374 if (!ICS.hasOperandBundles()) {
375 const Function *Callee = ICS.getCalledFunction();
376 if (Callee && Callee->arg_size() > unsigned(ArgNo))
377 IRPositions.emplace_back(IRPosition::argument(*Callee->getArg(ArgNo)));
378 if (Callee)
379 IRPositions.emplace_back(IRPosition::function(*Callee));
380 }
381 IRPositions.emplace_back(IRPosition::value(IRP.getAssociatedValue()));
382 return;
383 }
384 }
385}
386
387bool IRPosition::hasAttr(ArrayRef<Attribute::AttrKind> AKs) const {
388 for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this))
389 for (Attribute::AttrKind AK : AKs)
390 if (EquivIRP.getAttr(AK).getKindAsEnum() == AK)
391 return true;
392 return false;
393}
394
395void IRPosition::getAttrs(ArrayRef<Attribute::AttrKind> AKs,
396 SmallVectorImpl<Attribute> &Attrs) const {
397 for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this))
398 for (Attribute::AttrKind AK : AKs) {
399 const Attribute &Attr = EquivIRP.getAttr(AK);
400 if (Attr.getKindAsEnum() == AK)
401 Attrs.push_back(Attr);
402 }
403}
404
405void IRPosition::verify() {
406 switch (KindOrArgNo) {
407 default:
408 assert(KindOrArgNo >= 0 && "Expected argument or call site argument!");
409 assert((isa<CallBase>(AnchorVal) || isa<Argument>(AnchorVal)) &&
410 "Expected call base or argument for positive attribute index!");
411 if (auto *Arg = dyn_cast<Argument>(AnchorVal)) {
412 assert(Arg->getArgNo() == unsigned(getArgNo()) &&
413 "Argument number mismatch!");
414 assert(Arg == &getAssociatedValue() && "Associated value mismatch!");
415 } else {
416 auto &CB = cast<CallBase>(*AnchorVal);
Johannes Doerfert4395b312019-08-14 21:46:28 +0000417 (void)CB;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000418 assert(CB.arg_size() > unsigned(getArgNo()) &&
419 "Call site argument number mismatch!");
420 assert(CB.getArgOperand(getArgNo()) == &getAssociatedValue() &&
421 "Associated value mismatch!");
422 }
423 break;
424 case IRP_INVALID:
425 assert(!AnchorVal && "Expected no value for an invalid position!");
426 break;
427 case IRP_FLOAT:
428 assert((!isa<CallBase>(&getAssociatedValue()) &&
429 !isa<Argument>(&getAssociatedValue())) &&
430 "Expected specialized kind for call base and argument values!");
431 break;
432 case IRP_RETURNED:
433 assert(isa<Function>(AnchorVal) &&
434 "Expected function for a 'returned' position!");
435 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
436 break;
437 case IRP_CALL_SITE_RETURNED:
438 assert((isa<CallBase>(AnchorVal)) &&
439 "Expected call base for 'call site returned' position!");
440 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
441 break;
442 case IRP_CALL_SITE:
443 assert((isa<CallBase>(AnchorVal)) &&
444 "Expected call base for 'call site function' position!");
445 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
446 break;
447 case IRP_FUNCTION:
448 assert(isa<Function>(AnchorVal) &&
449 "Expected function for a 'function' position!");
450 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
451 break;
452 }
453}
454
Stefan Stipanovic53605892019-06-27 11:27:54 +0000455/// -----------------------NoUnwind Function Attribute--------------------------
456
Johannes Doerfert344d0382019-08-07 22:34:26 +0000457struct AANoUnwindImpl : AANoUnwind {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000458 AANoUnwindImpl(const IRPosition &IRP) : AANoUnwind(IRP) {}
Stefan Stipanovic53605892019-06-27 11:27:54 +0000459
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000460 const std::string getAsStr() const override {
Stefan Stipanovic53605892019-06-27 11:27:54 +0000461 return getAssumed() ? "nounwind" : "may-unwind";
462 }
463
464 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +0000465 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic53605892019-06-27 11:27:54 +0000466};
467
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000468struct AANoUnwindFunction final : public AANoUnwindImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000469 AANoUnwindFunction(const IRPosition &IRP) : AANoUnwindImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000470
471 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000472 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000473};
474
Johannes Doerfertece81902019-08-12 22:05:53 +0000475ChangeStatus AANoUnwindImpl::updateImpl(Attributor &A) {
Stefan Stipanovic53605892019-06-27 11:27:54 +0000476
477 // The map from instruction opcodes to those instructions in the function.
Stefan Stipanovic53605892019-06-27 11:27:54 +0000478 auto Opcodes = {
479 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
480 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
481 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
482
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000483 auto CheckForNoUnwind = [&](Instruction &I) {
484 if (!I.mayThrow())
485 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000486
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000487 auto *NoUnwindAA = A.getAAFor<AANoUnwind>(*this, IRPosition::value(I));
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000488 return NoUnwindAA && NoUnwindAA->isAssumedNoUnwind();
489 };
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000490
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000491 if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes))
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000492 return indicatePessimisticFixpoint();
Stefan Stipanovic53605892019-06-27 11:27:54 +0000493
Stefan Stipanovic53605892019-06-27 11:27:54 +0000494 return ChangeStatus::UNCHANGED;
495}
496
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000497/// --------------------- Function Return Values -------------------------------
498
499/// "Attribute" that collects all potential returned values and the return
500/// instructions that they arise from.
501///
502/// If there is a unique returned value R, the manifest method will:
503/// - mark R with the "returned" attribute, if R is an argument.
Johannes Doerferteccdf082019-08-05 23:35:12 +0000504class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000505
506 /// Mapping of values potentially returned by the associated function to the
507 /// return instructions that might return them.
508 DenseMap<Value *, SmallPtrSet<ReturnInst *, 2>> ReturnedValues;
509
Johannes Doerfertdef99282019-08-14 21:29:37 +0000510 SmallPtrSet<CallBase *, 8> UnresolvedCalls;
511
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000512 /// State flags
513 ///
514 ///{
515 bool IsFixed;
516 bool IsValidState;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000517 ///}
518
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000519public:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000520 AAReturnedValuesImpl(const IRPosition &IRP) : AAReturnedValues(IRP) {}
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000521
522 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +0000523 void initialize(Attributor &A) override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000524 // Reset the state.
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000525 IsFixed = false;
526 IsValidState = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000527 ReturnedValues.clear();
528
Johannes Doerfertdef99282019-08-14 21:29:37 +0000529 Function *F = getAssociatedFunction();
530 if (!F || !F->hasExactDefinition()) {
531 indicatePessimisticFixpoint();
532 return;
533 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000534
535 // The map from instruction opcodes to those instructions in the function.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000536 auto &OpcodeInstMap = A.getInfoCache().getOpcodeInstMapForFunction(*F);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000537
538 // Look through all arguments, if one is marked as returned we are done.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000539 for (Argument &Arg : F->args()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000540 if (Arg.hasReturnedAttr()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000541 auto &ReturnInstSet = ReturnedValues[&Arg];
542 for (Instruction *RI : OpcodeInstMap[Instruction::Ret])
543 ReturnInstSet.insert(cast<ReturnInst>(RI));
544
545 indicateOptimisticFixpoint();
546 return;
547 }
548 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000549 }
550
551 /// See AbstractAttribute::manifest(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000552 ChangeStatus manifest(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000553
554 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000555 AbstractState &getState() override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000556
557 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000558 const AbstractState &getState() const override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000559
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000560 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +0000561 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000562
Johannes Doerfertdef99282019-08-14 21:29:37 +0000563 llvm::iterator_range<iterator> returned_values() override {
564 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
565 }
566
567 llvm::iterator_range<const_iterator> returned_values() const override {
568 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
569 }
570
571 const SmallPtrSetImpl<CallBase *> &getUnresolvedCalls() const override {
572 return UnresolvedCalls;
573 }
574
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000575 /// Return the number of potential return values, -1 if unknown.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000576 size_t getNumReturnValues() const override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000577 return isValidState() ? ReturnedValues.size() : -1;
578 }
579
580 /// Return an assumed unique return value if a single candidate is found. If
581 /// there cannot be one, return a nullptr. If it is not clear yet, return the
582 /// Optional::NoneType.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000583 Optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000584
Johannes Doerfert14a04932019-08-07 22:27:24 +0000585 /// See AbstractState::checkForAllReturnedValues(...).
586 bool checkForAllReturnedValuesAndReturnInsts(
587 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
588 &Pred) const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000589
590 /// Pretty print the attribute similar to the IR representation.
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000591 const std::string getAsStr() const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000592
593 /// See AbstractState::isAtFixpoint().
594 bool isAtFixpoint() const override { return IsFixed; }
595
596 /// See AbstractState::isValidState().
597 bool isValidState() const override { return IsValidState; }
598
599 /// See AbstractState::indicateOptimisticFixpoint(...).
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000600 ChangeStatus indicateOptimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000601 IsFixed = true;
602 IsValidState &= true;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000603 return ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000604 }
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000605
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000606 ChangeStatus indicatePessimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000607 IsFixed = true;
608 IsValidState = false;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000609 return ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000610 }
611};
612
613ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) {
614 ChangeStatus Changed = ChangeStatus::UNCHANGED;
615
616 // Bookkeeping.
617 assert(isValidState());
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000618 STATS_DECLTRACK(KnownReturnValues, FunctionReturn,
619 "Number of function with known return values");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000620
621 // Check if we have an assumed unique return value that we could manifest.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000622 Optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000623
624 if (!UniqueRV.hasValue() || !UniqueRV.getValue())
625 return Changed;
626
627 // Bookkeeping.
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000628 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
629 "Number of function with unique return");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000630
631 // If the assumed unique return value is an argument, annotate it.
632 if (auto *UniqueRVArg = dyn_cast<Argument>(UniqueRV.getValue())) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000633 getIRPosition() = IRPosition::argument(*UniqueRVArg);
Johannes Doerferteccdf082019-08-05 23:35:12 +0000634 Changed = IRAttribute::manifest(A) | Changed;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000635 }
636
637 return Changed;
638}
639
640const std::string AAReturnedValuesImpl::getAsStr() const {
641 return (isAtFixpoint() ? "returns(#" : "may-return(#") +
Johannes Doerfert6471bb62019-08-04 18:39:28 +0000642 (isValidState() ? std::to_string(getNumReturnValues()) : "?") +
Johannes Doerfertdef99282019-08-14 21:29:37 +0000643 ")[#UC: " + std::to_string(UnresolvedCalls.size()) + "]";
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000644}
645
Johannes Doerfert14a04932019-08-07 22:27:24 +0000646Optional<Value *>
647AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const {
648 // If checkForAllReturnedValues provides a unique value, ignoring potential
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000649 // undef values that can also be present, it is assumed to be the actual
650 // return value and forwarded to the caller of this method. If there are
651 // multiple, a nullptr is returned indicating there cannot be a unique
652 // returned value.
653 Optional<Value *> UniqueRV;
654
Johannes Doerfert14a04932019-08-07 22:27:24 +0000655 auto Pred = [&](Value &RV) -> bool {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000656 // If we found a second returned value and neither the current nor the saved
657 // one is an undef, there is no unique returned value. Undefs are special
658 // since we can pretend they have any value.
659 if (UniqueRV.hasValue() && UniqueRV != &RV &&
660 !(isa<UndefValue>(RV) || isa<UndefValue>(UniqueRV.getValue()))) {
661 UniqueRV = nullptr;
662 return false;
663 }
664
665 // Do not overwrite a value with an undef.
666 if (!UniqueRV.hasValue() || !isa<UndefValue>(RV))
667 UniqueRV = &RV;
668
669 return true;
670 };
671
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000672 if (!A.checkForAllReturnedValues(Pred, *this))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000673 UniqueRV = nullptr;
674
675 return UniqueRV;
676}
677
Johannes Doerfert14a04932019-08-07 22:27:24 +0000678bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
679 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
680 &Pred) const {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000681 if (!isValidState())
682 return false;
683
684 // Check all returned values but ignore call sites as long as we have not
685 // encountered an overdefined one during an update.
686 for (auto &It : ReturnedValues) {
687 Value *RV = It.first;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000688 const SmallPtrSetImpl<ReturnInst *> &RetInsts = It.second;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000689
Johannes Doerfertdef99282019-08-14 21:29:37 +0000690 CallBase *CB = dyn_cast<CallBase>(RV);
691 if (CB && !UnresolvedCalls.count(CB))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000692 continue;
693
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000694 if (!Pred(*RV, RetInsts))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000695 return false;
696 }
697
698 return true;
699}
700
Johannes Doerfertece81902019-08-12 22:05:53 +0000701ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000702 size_t NumUnresolvedCalls = UnresolvedCalls.size();
703 bool Changed = false;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000704
Johannes Doerfertdef99282019-08-14 21:29:37 +0000705 // State used in the value traversals starting in returned values.
706 struct RVState {
707 // The map in which we collect return values -> return instrs.
708 decltype(ReturnedValues) &RetValsMap;
709 // The flag to indicate a change.
710 bool Changed;
711 // The return instrs we come from.
712 SmallPtrSet<ReturnInst *, 2> RetInsts;
713 };
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000714
Johannes Doerfertdef99282019-08-14 21:29:37 +0000715 // Callback for a leaf value returned by the associated function.
716 auto VisitValueCB = [](Value &Val, RVState &RVS, bool) {
717 auto Size = RVS.RetValsMap[&Val].size();
718 RVS.RetValsMap[&Val].insert(RVS.RetInsts.begin(), RVS.RetInsts.end());
719 bool Inserted = RVS.RetValsMap[&Val].size() != Size;
720 RVS.Changed |= Inserted;
721 LLVM_DEBUG({
722 if (Inserted)
723 dbgs() << "[AAReturnedValues] 1 Add new returned value " << Val
724 << " => " << RVS.RetInsts.size() << "\n";
725 });
726 };
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000727
Johannes Doerfertdef99282019-08-14 21:29:37 +0000728 // Helper method to invoke the generic value traversal.
729 auto VisitReturnedValue = [&](Value &RV, RVState &RVS) {
730 IRPosition RetValPos = IRPosition::value(RV);
731 return genericValueTraversal<AAReturnedValues, RVState>(A, RetValPos, *this,
732 RVS, VisitValueCB);
733 };
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000734
Johannes Doerfertdef99282019-08-14 21:29:37 +0000735 // Callback for all "return intructions" live in the associated function.
736 auto CheckReturnInst = [this, &VisitReturnedValue, &Changed](Instruction &I) {
737 ReturnInst &Ret = cast<ReturnInst>(I);
738 RVState RVS({ReturnedValues, false});
739 RVS.RetInsts.insert(&Ret);
740 Changed |= RVS.Changed;
741 return VisitReturnedValue(*Ret.getReturnValue(), RVS);
742 };
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000743
Johannes Doerfertdef99282019-08-14 21:29:37 +0000744 // Start by discovering returned values from all live returned instructions in
745 // the associated function.
746 if (!A.checkForAllInstructions(CheckReturnInst, *this, {Instruction::Ret}))
747 return indicatePessimisticFixpoint();
748
749 // Once returned values "directly" present in the code are handled we try to
750 // resolve returned calls.
751 decltype(ReturnedValues) NewRVsMap;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000752 for (auto &It : ReturnedValues) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000753 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned value: " << *It.first
754 << " by #" << It.second.size() << " RIs\n");
755 CallBase *CB = dyn_cast<CallBase>(It.first);
756 if (!CB || UnresolvedCalls.count(CB))
757 continue;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000758
Johannes Doerfertdef99282019-08-14 21:29:37 +0000759 const auto *RetValAAPtr =
760 A.getAAFor<AAReturnedValues>(*this, IRPosition::callsite_function(*CB));
761
762 // Skip dead ends, thus if we do not know anything about the returned
763 // call we mark it as unresolved and it will stay that way.
764 if (!RetValAAPtr || !RetValAAPtr->getState().isValidState()) {
765 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Unresolved call: " << *CB
766 << "\n");
767 UnresolvedCalls.insert(CB);
768 continue;
769 }
770
771 const auto &RetValAA = *RetValAAPtr;
772 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Found another AAReturnedValues: "
773 << static_cast<const AbstractAttribute &>(RetValAA)
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000774 << "\n");
775
Johannes Doerfertdef99282019-08-14 21:29:37 +0000776 // If we know something but not everyting about the returned values, keep
777 // track of that too. Hence, remember transitively unresolved calls.
778 UnresolvedCalls.insert(RetValAA.getUnresolvedCalls().begin(),
779 RetValAA.getUnresolvedCalls().end());
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000780
Johannes Doerfertdef99282019-08-14 21:29:37 +0000781 // Now track transitively returned values.
782 for (auto &RetValAAIt : RetValAA.returned_values()) {
783 Value *RetVal = RetValAAIt.first;
784 if (Argument *Arg = dyn_cast<Argument>(RetVal)) {
785 // Arguments are mapped to call site operands and we begin the traversal
786 // again.
787 RVState RVS({NewRVsMap, false, RetValAAIt.second});
788 VisitReturnedValue(*CB->getArgOperand(Arg->getArgNo()), RVS);
789 continue;
790 } else if (isa<CallBase>(RetVal)) {
791 // Call sites are resolved by the callee attribute over time, no need to
792 // do anything for us.
793 continue;
794 } else if (isa<Constant>(RetVal)) {
795 // Constants are valid everywhere, we can simply take them.
796 NewRVsMap[RetVal].insert(It.second.begin(), It.second.end());
797 continue;
798 }
799 // Anything that did not fit in the above categories cannot be resolved,
800 // mark the call as unresolved.
801 LLVM_DEBUG(dbgs() << "[AAReturnedValues] transitively returned value "
802 "cannot be translated: "
803 << *RetVal << "\n");
804 UnresolvedCalls.insert(CB);
Johannes Doerfert4361da22019-08-04 18:38:53 +0000805 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000806 }
807
Johannes Doerfertdef99282019-08-14 21:29:37 +0000808 // To avoid modifications to the ReturnedValues map while we iterate over it
809 // we kept record of potential new entries in a copy map, NewRVsMap.
810 for (auto &It : NewRVsMap) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000811 assert(!It.second.empty() && "Entry does not add anything.");
812 auto &ReturnInsts = ReturnedValues[It.first];
813 for (ReturnInst *RI : It.second)
814 if (ReturnInsts.insert(RI).second) {
815 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Add new returned value "
816 << *It.first << " => " << *RI << "\n");
Johannes Doerfertdef99282019-08-14 21:29:37 +0000817 Changed = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000818 }
819 }
820
Johannes Doerfertdef99282019-08-14 21:29:37 +0000821 Changed |= (NumUnresolvedCalls != UnresolvedCalls.size());
822 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000823}
824
Johannes Doerfertdef99282019-08-14 21:29:37 +0000825struct AAReturnedValuesFunction final : public AAReturnedValuesImpl {
826 AAReturnedValuesFunction(const IRPosition &IRP) : AAReturnedValuesImpl(IRP) {}
827
828 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000829 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(returned) }
Johannes Doerfertdef99282019-08-14 21:29:37 +0000830};
831
Stefan Stipanovic06263672019-07-11 21:37:40 +0000832/// ------------------------ NoSync Function Attribute -------------------------
833
Johannes Doerfert344d0382019-08-07 22:34:26 +0000834struct AANoSyncImpl : AANoSync {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000835 AANoSyncImpl(const IRPosition &IRP) : AANoSync(IRP) {}
Stefan Stipanovic06263672019-07-11 21:37:40 +0000836
Stefan Stipanoviccb5ecae2019-07-12 18:34:06 +0000837 const std::string getAsStr() const override {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000838 return getAssumed() ? "nosync" : "may-sync";
839 }
840
841 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +0000842 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000843
Stefan Stipanovic06263672019-07-11 21:37:40 +0000844 /// Helper function used to determine whether an instruction is non-relaxed
845 /// atomic. In other words, if an atomic instruction does not have unordered
846 /// or monotonic ordering
847 static bool isNonRelaxedAtomic(Instruction *I);
848
849 /// Helper function used to determine whether an instruction is volatile.
850 static bool isVolatile(Instruction *I);
851
Johannes Doerfertc7a1db32019-07-13 01:09:27 +0000852 /// Helper function uset to check if intrinsic is volatile (memcpy, memmove,
853 /// memset).
Stefan Stipanovic06263672019-07-11 21:37:40 +0000854 static bool isNoSyncIntrinsic(Instruction *I);
855};
856
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000857struct AANoSyncFunction final : public AANoSyncImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000858 AANoSyncFunction(const IRPosition &IRP) : AANoSyncImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000859
860 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000861 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000862};
863
864bool AANoSyncImpl::isNonRelaxedAtomic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000865 if (!I->isAtomic())
866 return false;
867
868 AtomicOrdering Ordering;
869 switch (I->getOpcode()) {
870 case Instruction::AtomicRMW:
871 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
872 break;
873 case Instruction::Store:
874 Ordering = cast<StoreInst>(I)->getOrdering();
875 break;
876 case Instruction::Load:
877 Ordering = cast<LoadInst>(I)->getOrdering();
878 break;
879 case Instruction::Fence: {
880 auto *FI = cast<FenceInst>(I);
881 if (FI->getSyncScopeID() == SyncScope::SingleThread)
882 return false;
883 Ordering = FI->getOrdering();
884 break;
885 }
886 case Instruction::AtomicCmpXchg: {
887 AtomicOrdering Success = cast<AtomicCmpXchgInst>(I)->getSuccessOrdering();
888 AtomicOrdering Failure = cast<AtomicCmpXchgInst>(I)->getFailureOrdering();
889 // Only if both are relaxed, than it can be treated as relaxed.
890 // Otherwise it is non-relaxed.
891 if (Success != AtomicOrdering::Unordered &&
892 Success != AtomicOrdering::Monotonic)
893 return true;
894 if (Failure != AtomicOrdering::Unordered &&
895 Failure != AtomicOrdering::Monotonic)
896 return true;
897 return false;
898 }
899 default:
900 llvm_unreachable(
901 "New atomic operations need to be known in the attributor.");
902 }
903
904 // Relaxed.
905 if (Ordering == AtomicOrdering::Unordered ||
906 Ordering == AtomicOrdering::Monotonic)
907 return false;
908 return true;
909}
910
911/// Checks if an intrinsic is nosync. Currently only checks mem* intrinsics.
912/// FIXME: We should ipmrove the handling of intrinsics.
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000913bool AANoSyncImpl::isNoSyncIntrinsic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000914 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
915 switch (II->getIntrinsicID()) {
916 /// Element wise atomic memory intrinsics are can only be unordered,
917 /// therefore nosync.
918 case Intrinsic::memset_element_unordered_atomic:
919 case Intrinsic::memmove_element_unordered_atomic:
920 case Intrinsic::memcpy_element_unordered_atomic:
921 return true;
922 case Intrinsic::memset:
923 case Intrinsic::memmove:
924 case Intrinsic::memcpy:
925 if (!cast<MemIntrinsic>(II)->isVolatile())
926 return true;
927 return false;
928 default:
929 return false;
930 }
931 }
932 return false;
933}
934
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000935bool AANoSyncImpl::isVolatile(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000936 assert(!ImmutableCallSite(I) && !isa<CallBase>(I) &&
937 "Calls should not be checked here");
938
939 switch (I->getOpcode()) {
940 case Instruction::AtomicRMW:
941 return cast<AtomicRMWInst>(I)->isVolatile();
942 case Instruction::Store:
943 return cast<StoreInst>(I)->isVolatile();
944 case Instruction::Load:
945 return cast<LoadInst>(I)->isVolatile();
946 case Instruction::AtomicCmpXchg:
947 return cast<AtomicCmpXchgInst>(I)->isVolatile();
948 default:
949 return false;
950 }
951}
952
Johannes Doerfertece81902019-08-12 22:05:53 +0000953ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000954
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000955 auto CheckRWInstForNoSync = [&](Instruction &I) {
956 /// We are looking for volatile instructions or Non-Relaxed atomics.
957 /// FIXME: We should ipmrove the handling of intrinsics.
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000958
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000959 if (isa<IntrinsicInst>(&I) && isNoSyncIntrinsic(&I))
960 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000961
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000962 if (ImmutableCallSite ICS = ImmutableCallSite(&I)) {
963 if (ICS.hasFnAttr(Attribute::NoSync))
964 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000965
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000966 auto *NoSyncAA =
967 A.getAAFor<AANoSyncImpl>(*this, IRPosition::callsite_function(ICS));
968 if (NoSyncAA && NoSyncAA->isAssumedNoSync())
969 return true;
970 return false;
971 }
Stefan Stipanovic06263672019-07-11 21:37:40 +0000972
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000973 if (!isVolatile(&I) && !isNonRelaxedAtomic(&I))
974 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000975
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000976 return false;
977 };
Stefan Stipanovic06263672019-07-11 21:37:40 +0000978
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000979 auto CheckForNoSync = [&](Instruction &I) {
980 // At this point we handled all read/write effects and they are all
981 // nosync, so they can be skipped.
982 if (I.mayReadOrWriteMemory())
983 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000984
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000985 // non-convergent and readnone imply nosync.
986 return !ImmutableCallSite(&I).isConvergent();
987 };
Stefan Stipanovic06263672019-07-11 21:37:40 +0000988
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000989 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this) ||
990 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this))
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000991 return indicatePessimisticFixpoint();
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000992
Stefan Stipanovic06263672019-07-11 21:37:40 +0000993 return ChangeStatus::UNCHANGED;
994}
995
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000996/// ------------------------ No-Free Attributes ----------------------------
997
Johannes Doerfert344d0382019-08-07 22:34:26 +0000998struct AANoFreeImpl : public AANoFree {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000999 AANoFreeImpl(const IRPosition &IRP) : AANoFree(IRP) {}
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001000
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001001 /// See AbstractAttribute::getAsStr().
1002 const std::string getAsStr() const override {
1003 return getAssumed() ? "nofree" : "may-free";
1004 }
1005
1006 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001007 ChangeStatus updateImpl(Attributor &A) override;
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001008};
1009
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001010struct AANoFreeFunction final : public AANoFreeImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001011 AANoFreeFunction(const IRPosition &IRP) : AANoFreeImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001012
1013 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001014 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001015};
1016
Johannes Doerfertece81902019-08-12 22:05:53 +00001017ChangeStatus AANoFreeImpl::updateImpl(Attributor &A) {
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001018
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001019 auto CheckForNoFree = [&](Instruction &I) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001020 ImmutableCallSite ICS(&I);
1021 if (ICS.hasFnAttr(Attribute::NoFree))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001022 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001023
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001024 auto *NoFreeAA =
1025 A.getAAFor<AANoFreeImpl>(*this, IRPosition::callsite_function(ICS));
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001026 return NoFreeAA && NoFreeAA->isAssumedNoFree();
1027 };
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001028
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001029 if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001030 return indicatePessimisticFixpoint();
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001031 return ChangeStatus::UNCHANGED;
1032}
1033
Hideto Ueno54869ec2019-07-15 06:49:04 +00001034/// ------------------------ NonNull Argument Attribute ------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00001035struct AANonNullImpl : AANonNull {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001036 AANonNullImpl(const IRPosition &IRP) : AANonNull(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001037
Hideto Ueno54869ec2019-07-15 06:49:04 +00001038 /// See AbstractAttribute::getAsStr().
1039 const std::string getAsStr() const override {
1040 return getAssumed() ? "nonnull" : "may-null";
1041 }
1042
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001043 /// See AbstractAttribute::initialize(...).
1044 void initialize(Attributor &A) override {
1045 if (hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
1046 indicateOptimisticFixpoint();
1047 }
1048
Hideto Ueno54869ec2019-07-15 06:49:04 +00001049 /// Generate a predicate that checks if a given value is assumed nonnull.
1050 /// The generated function returns true if a value satisfies any of
1051 /// following conditions.
1052 /// (i) A value is known nonZero(=nonnull).
1053 /// (ii) A value is associated with AANonNull and its isAssumedNonNull() is
1054 /// true.
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001055 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
1056 generatePredicate(Attributor &);
Hideto Ueno54869ec2019-07-15 06:49:04 +00001057};
1058
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001059std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
1060AANonNullImpl::generatePredicate(Attributor &A) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001061 // FIXME: The `AAReturnedValues` should provide the predicate with the
1062 // `ReturnInst` vector as well such that we can use the control flow sensitive
1063 // version of `isKnownNonZero`. This should fix `test11` in
1064 // `test/Transforms/FunctionAttrs/nonnull.ll`
1065
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001066 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
1067 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &RetInsts) -> bool {
Johannes Doerfert26e58462019-08-12 22:21:09 +00001068 if (isKnownNonZero(&RV, A.getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001069 return true;
1070
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001071 if (ImmutableCallSite ICS = ImmutableCallSite(&RV))
1072 if (ICS.hasRetAttr(Attribute::NonNull))
1073 return true;
Hideto Ueno54869ec2019-07-15 06:49:04 +00001074
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001075 auto *NonNullAA = A.getAAFor<AANonNull>(*this, IRPosition::value(RV));
1076 return (NonNullAA && NonNullAA->isAssumedNonNull());
Hideto Ueno54869ec2019-07-15 06:49:04 +00001077 };
1078
1079 return Pred;
1080}
1081
1082/// NonNull attribute for function return value.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001083struct AANonNullReturned final : AANonNullImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001084 AANonNullReturned(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001085
1086 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001087 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001088
1089 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001090 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001091};
1092
Johannes Doerfertece81902019-08-12 22:05:53 +00001093ChangeStatus AANonNullReturned::updateImpl(Attributor &A) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001094
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001095 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
1096 this->generatePredicate(A);
1097
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001098 if (!A.checkForAllReturnedValuesAndReturnInsts(Pred, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001099 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001100 return ChangeStatus::UNCHANGED;
1101}
1102
1103/// NonNull attribute for function argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001104struct AANonNullArgument final : AANonNullImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001105 AANonNullArgument(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001106
1107 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001108 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001109
1110 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001111 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001112};
1113
1114/// NonNull attribute for a call site argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001115struct AANonNullCallSiteArgument final : AANonNullImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001116 AANonNullCallSiteArgument(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001117
1118 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001119 void initialize(Attributor &A) override {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001120 AANonNullImpl::initialize(A);
1121 if (!isKnownNonNull() &&
1122 isKnownNonZero(&getAssociatedValue(), A.getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001123 indicateOptimisticFixpoint();
1124 }
1125
1126 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00001127 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001128
1129 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001130 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001131};
Johannes Doerfert007153e2019-08-05 23:26:06 +00001132
Johannes Doerfertece81902019-08-12 22:05:53 +00001133ChangeStatus AANonNullArgument::updateImpl(Attributor &A) {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001134 unsigned ArgNo = getArgNo();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001135
1136 // Callback function
1137 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) {
1138 assert(CS && "Sanity check: Call site was not initialized properly!");
1139
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001140 IRPosition CSArgPos = IRPosition::callsite_argument(CS, ArgNo);
1141 if (CSArgPos.hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
1142 return true;
Hideto Ueno54869ec2019-07-15 06:49:04 +00001143
1144 // Check that NonNullAA is AANonNullCallSiteArgument.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001145 if (auto *NonNullAA = A.getAAFor<AANonNullImpl>(*this, CSArgPos)) {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001146 ImmutableCallSite ICS(&NonNullAA->getAnchorValue());
Hideto Ueno54869ec2019-07-15 06:49:04 +00001147 if (ICS && CS.getInstruction() == ICS.getInstruction())
1148 return NonNullAA->isAssumedNonNull();
1149 return false;
1150 }
1151
Hideto Ueno54869ec2019-07-15 06:49:04 +00001152 Value *V = CS.getArgOperand(ArgNo);
Johannes Doerfert26e58462019-08-12 22:21:09 +00001153 if (isKnownNonZero(V, A.getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001154 return true;
1155
1156 return false;
1157 };
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001158 if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001159 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001160 return ChangeStatus::UNCHANGED;
1161}
1162
Johannes Doerfertece81902019-08-12 22:05:53 +00001163ChangeStatus AANonNullCallSiteArgument::updateImpl(Attributor &A) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001164 // NOTE: Never look at the argument of the callee in this method.
1165 // If we do this, "nonnull" is always deduced because of the assumption.
1166
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001167 Value &V = getAssociatedValue();
1168 auto *NonNullAA = A.getAAFor<AANonNull>(*this, IRPosition::value(V));
Hideto Ueno54869ec2019-07-15 06:49:04 +00001169
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001170 if (!NonNullAA || !NonNullAA->isAssumedNonNull())
1171 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001172
1173 return ChangeStatus::UNCHANGED;
1174}
1175
Hideto Ueno11d37102019-07-17 15:15:43 +00001176/// ------------------------ Will-Return Attributes ----------------------------
1177
Johannes Doerfert344d0382019-08-07 22:34:26 +00001178struct AAWillReturnImpl : public AAWillReturn {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001179 AAWillReturnImpl(const IRPosition &IRP) : AAWillReturn(IRP) {}
Hideto Ueno11d37102019-07-17 15:15:43 +00001180
Hideto Ueno11d37102019-07-17 15:15:43 +00001181 /// See AbstractAttribute::getAsStr()
1182 const std::string getAsStr() const override {
1183 return getAssumed() ? "willreturn" : "may-noreturn";
1184 }
1185};
1186
1187struct AAWillReturnFunction final : AAWillReturnImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001188 AAWillReturnFunction(const IRPosition &IRP) : AAWillReturnImpl(IRP) {}
Hideto Ueno11d37102019-07-17 15:15:43 +00001189
1190 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001191 void initialize(Attributor &A) override;
Hideto Ueno11d37102019-07-17 15:15:43 +00001192
1193 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001194 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001195
1196 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001197 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
Hideto Ueno11d37102019-07-17 15:15:43 +00001198};
1199
1200// Helper function that checks whether a function has any cycle.
1201// TODO: Replace with more efficent code
1202bool containsCycle(Function &F) {
1203 SmallPtrSet<BasicBlock *, 32> Visited;
1204
1205 // Traverse BB by dfs and check whether successor is already visited.
1206 for (BasicBlock *BB : depth_first(&F)) {
1207 Visited.insert(BB);
1208 for (auto *SuccBB : successors(BB)) {
1209 if (Visited.count(SuccBB))
1210 return true;
1211 }
1212 }
1213 return false;
1214}
1215
1216// Helper function that checks the function have a loop which might become an
1217// endless loop
1218// FIXME: Any cycle is regarded as endless loop for now.
1219// We have to allow some patterns.
1220bool containsPossiblyEndlessLoop(Function &F) { return containsCycle(F); }
1221
Johannes Doerfertece81902019-08-12 22:05:53 +00001222void AAWillReturnFunction::initialize(Attributor &A) {
Johannes Doerfertdef99282019-08-14 21:29:37 +00001223 Function &F = *getAnchorScope();
Hideto Ueno11d37102019-07-17 15:15:43 +00001224
1225 if (containsPossiblyEndlessLoop(F))
1226 indicatePessimisticFixpoint();
1227}
1228
Johannes Doerfertece81902019-08-12 22:05:53 +00001229ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A) {
Hideto Ueno11d37102019-07-17 15:15:43 +00001230 // The map from instruction opcodes to those instructions in the function.
Hideto Ueno11d37102019-07-17 15:15:43 +00001231
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001232 auto CheckForWillReturn = [&](Instruction &I) {
1233 ImmutableCallSite ICS(&I);
1234 if (ICS.hasFnAttr(Attribute::WillReturn))
1235 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001236
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001237 IRPosition IPos = IRPosition::callsite_function(ICS);
1238 auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, IPos);
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001239 if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn())
1240 return false;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001241
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001242 // FIXME: Prohibit any recursion for now.
1243 if (ICS.hasFnAttr(Attribute::NoRecurse))
1244 return true;
Hideto Ueno11d37102019-07-17 15:15:43 +00001245
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001246 auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, IPos);
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001247 return NoRecurseAA && NoRecurseAA->isAssumedNoRecurse();
1248 };
Hideto Ueno11d37102019-07-17 15:15:43 +00001249
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001250 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001251 return indicatePessimisticFixpoint();
Hideto Ueno11d37102019-07-17 15:15:43 +00001252
1253 return ChangeStatus::UNCHANGED;
1254}
1255
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001256/// ------------------------ NoAlias Argument Attribute ------------------------
1257
Johannes Doerfert344d0382019-08-07 22:34:26 +00001258struct AANoAliasImpl : AANoAlias {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001259 AANoAliasImpl(const IRPosition &IRP) : AANoAlias(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001260
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001261 const std::string getAsStr() const override {
1262 return getAssumed() ? "noalias" : "may-alias";
1263 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001264};
1265
1266/// NoAlias attribute for function return value.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001267struct AANoAliasReturned final : AANoAliasImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001268 AANoAliasReturned(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001269
1270 /// See AbstractAttriubute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001271 void initialize(Attributor &A) override {
Johannes Doerfertdef99282019-08-14 21:29:37 +00001272 Function &F = *getAnchorScope();
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001273
1274 // Already noalias.
1275 if (F.returnDoesNotAlias()) {
1276 indicateOptimisticFixpoint();
1277 return;
1278 }
1279 }
1280
1281 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001282 virtual ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001283
1284 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001285 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001286};
1287
Johannes Doerfertece81902019-08-12 22:05:53 +00001288ChangeStatus AANoAliasReturned::updateImpl(Attributor &A) {
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001289
Johannes Doerfert14a04932019-08-07 22:27:24 +00001290 auto CheckReturnValue = [&](Value &RV) -> bool {
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001291 if (Constant *C = dyn_cast<Constant>(&RV))
1292 if (C->isNullValue() || isa<UndefValue>(C))
1293 return true;
1294
1295 /// For now, we can only deduce noalias if we have call sites.
1296 /// FIXME: add more support.
1297 ImmutableCallSite ICS(&RV);
1298 if (!ICS)
1299 return false;
1300
Johannes Doerfert14a04932019-08-07 22:27:24 +00001301 if (!ICS.returnDoesNotAlias()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001302 auto *NoAliasAA =
1303 A.getAAFor<AANoAlias>(*this, IRPosition::callsite_returned(ICS));
Johannes Doerfert14a04932019-08-07 22:27:24 +00001304 if (!NoAliasAA || !NoAliasAA->isAssumedNoAlias())
1305 return false;
1306 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001307
1308 /// FIXME: We can improve capture check in two ways:
1309 /// 1. Use the AANoCapture facilities.
1310 /// 2. Use the location of return insts for escape queries.
1311 if (PointerMayBeCaptured(&RV, /* ReturnCaptures */ false,
1312 /* StoreCaptures */ true))
1313 return false;
1314
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001315 return true;
1316 };
1317
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001318 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001319 return indicatePessimisticFixpoint();
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001320
1321 return ChangeStatus::UNCHANGED;
1322}
1323
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001324/// -------------------AAIsDead Function Attribute-----------------------
1325
Johannes Doerfert344d0382019-08-07 22:34:26 +00001326struct AAIsDeadImpl : public AAIsDead {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001327 AAIsDeadImpl(const IRPosition &IRP) : AAIsDead(IRP) {}
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001328
Johannes Doerfertece81902019-08-12 22:05:53 +00001329 void initialize(Attributor &A) override {
Johannes Doerfertdef99282019-08-14 21:29:37 +00001330 const Function &F = *getAnchorScope();
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001331
1332 ToBeExploredPaths.insert(&(F.getEntryBlock().front()));
1333 AssumedLiveBlocks.insert(&(F.getEntryBlock()));
1334 for (size_t i = 0; i < ToBeExploredPaths.size(); ++i)
Johannes Doerfert4361da22019-08-04 18:38:53 +00001335 if (const Instruction *NextNoReturnI =
1336 findNextNoReturn(A, ToBeExploredPaths[i]))
1337 NoReturnCalls.insert(NextNoReturnI);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001338 }
1339
Johannes Doerfert4361da22019-08-04 18:38:53 +00001340 /// Find the next assumed noreturn instruction in the block of \p I starting
1341 /// from, thus including, \p I.
1342 ///
1343 /// The caller is responsible to monitor the ToBeExploredPaths set as new
1344 /// instructions discovered in other basic block will be placed in there.
1345 ///
1346 /// \returns The next assumed noreturn instructions in the block of \p I
1347 /// starting from, thus including, \p I.
1348 const Instruction *findNextNoReturn(Attributor &A, const Instruction *I);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001349
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001350 /// See AbstractAttribute::getAsStr().
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001351 const std::string getAsStr() const override {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001352 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
Johannes Doerfertdef99282019-08-14 21:29:37 +00001353 std::to_string(getAnchorScope()->size()) + "][#NRI " +
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001354 std::to_string(NoReturnCalls.size()) + "]";
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001355 }
1356
1357 /// See AbstractAttribute::manifest(...).
1358 ChangeStatus manifest(Attributor &A) override {
1359 assert(getState().isValidState() &&
1360 "Attempted to manifest an invalid state!");
1361
1362 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Johannes Doerfertdef99282019-08-14 21:29:37 +00001363 const Function &F = *getAssociatedFunction();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001364
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001365 // Flag to determine if we can change an invoke to a call assuming the
1366 // callee is nounwind. This is not possible if the personality of the
1367 // function allows to catch asynchronous exceptions.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001368 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001369
Johannes Doerfert4361da22019-08-04 18:38:53 +00001370 for (const Instruction *NRC : NoReturnCalls) {
1371 Instruction *I = const_cast<Instruction *>(NRC);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001372 BasicBlock *BB = I->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001373 Instruction *SplitPos = I->getNextNode();
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001374
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001375 if (auto *II = dyn_cast<InvokeInst>(I)) {
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001376 // If we keep the invoke the split position is at the beginning of the
1377 // normal desitination block (it invokes a noreturn function after all).
1378 BasicBlock *NormalDestBB = II->getNormalDest();
1379 SplitPos = &NormalDestBB->front();
1380
Johannes Doerfert4361da22019-08-04 18:38:53 +00001381 /// Invoke is replaced with a call and unreachable is placed after it if
1382 /// the callee is nounwind and noreturn. Otherwise, we keep the invoke
1383 /// and only place an unreachable in the normal successor.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001384 if (Invoke2CallAllowed) {
1385 if (Function *Callee = II->getCalledFunction()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001386 auto *AANoUnw =
1387 A.getAAFor<AANoUnwind>(*this, IRPosition::function(*Callee));
Johannes Doerfert924d2132019-08-05 21:34:45 +00001388 if (Callee->hasFnAttribute(Attribute::NoUnwind) ||
1389 (AANoUnw && AANoUnw->isAssumedNoUnwind())) {
1390 LLVM_DEBUG(dbgs()
1391 << "[AAIsDead] Replace invoke with call inst\n");
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001392 // We do not need an invoke (II) but instead want a call followed
1393 // by an unreachable. However, we do not remove II as other
1394 // abstract attributes might have it cached as part of their
1395 // results. Given that we modify the CFG anyway, we simply keep II
1396 // around but in a new dead block. To avoid II being live through
1397 // a different edge we have to ensure the block we place it in is
1398 // only reached from the current block of II and then not reached
1399 // at all when we insert the unreachable.
1400 SplitBlockPredecessors(NormalDestBB, {BB}, ".i2c");
1401 CallInst *CI = createCallMatchingInvoke(II);
1402 CI->insertBefore(II);
1403 CI->takeName(II);
1404 II->replaceAllUsesWith(CI);
1405 SplitPos = CI->getNextNode();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001406 }
Johannes Doerfert4361da22019-08-04 18:38:53 +00001407 }
1408 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001409 }
1410
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001411 BB = SplitPos->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001412 SplitBlock(BB, SplitPos);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001413 changeToUnreachable(BB->getTerminator(), /* UseLLVMTrap */ false);
1414 HasChanged = ChangeStatus::CHANGED;
1415 }
1416
1417 return HasChanged;
1418 }
1419
1420 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001421 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001422
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001423 /// See AAIsDead::isAssumedDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001424 bool isAssumedDead(const BasicBlock *BB) const override {
Johannes Doerfertdef99282019-08-14 21:29:37 +00001425 assert(BB->getParent() == getAnchorScope() &&
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001426 "BB must be in the same anchor scope function.");
1427
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001428 if (!getAssumed())
1429 return false;
1430 return !AssumedLiveBlocks.count(BB);
1431 }
1432
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001433 /// See AAIsDead::isKnownDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001434 bool isKnownDead(const BasicBlock *BB) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001435 return getKnown() && isAssumedDead(BB);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001436 }
1437
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001438 /// See AAIsDead::isAssumed(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001439 bool isAssumedDead(const Instruction *I) const override {
Johannes Doerfertdef99282019-08-14 21:29:37 +00001440 assert(I->getParent()->getParent() == getAnchorScope() &&
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001441 "Instruction must be in the same anchor scope function.");
1442
Stefan Stipanovic7849e412019-08-03 15:27:41 +00001443 if (!getAssumed())
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001444 return false;
1445
1446 // If it is not in AssumedLiveBlocks then it for sure dead.
1447 // Otherwise, it can still be after noreturn call in a live block.
1448 if (!AssumedLiveBlocks.count(I->getParent()))
1449 return true;
1450
1451 // If it is not after a noreturn call, than it is live.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001452 return isAfterNoReturn(I);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001453 }
1454
1455 /// See AAIsDead::isKnownDead(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001456 bool isKnownDead(const Instruction *I) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001457 return getKnown() && isAssumedDead(I);
1458 }
1459
1460 /// Check if instruction is after noreturn call, in other words, assumed dead.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001461 bool isAfterNoReturn(const Instruction *I) const;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001462
Johannes Doerfert924d2132019-08-05 21:34:45 +00001463 /// Determine if \p F might catch asynchronous exceptions.
1464 static bool mayCatchAsynchronousExceptions(const Function &F) {
1465 return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F);
1466 }
1467
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001468 /// Collection of to be explored paths.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001469 SmallSetVector<const Instruction *, 8> ToBeExploredPaths;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001470
1471 /// Collection of all assumed live BasicBlocks.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001472 DenseSet<const BasicBlock *> AssumedLiveBlocks;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001473
1474 /// Collection of calls with noreturn attribute, assumed or knwon.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001475 SmallSetVector<const Instruction *, 4> NoReturnCalls;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001476};
1477
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001478struct AAIsDeadFunction final : public AAIsDeadImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001479 AAIsDeadFunction(const IRPosition &IRP) : AAIsDeadImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001480
1481 /// See AbstractAttribute::trackStatistics()
1482 void trackStatistics() const override {
1483 STATS_DECL(DeadBlocks, Function,
1484 "Number of basic blocks classified as dead");
1485 BUILD_STAT_NAME(DeadBlocks, Function) +=
Johannes Doerfertdef99282019-08-14 21:29:37 +00001486 getAnchorScope()->size() - AssumedLiveBlocks.size();
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001487 STATS_DECL(PartiallyDeadBlocks, Function,
1488 "Number of basic blocks classified as partially dead");
1489 BUILD_STAT_NAME(PartiallyDeadBlocks, Function) += NoReturnCalls.size();
1490 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001491};
1492
1493bool AAIsDeadImpl::isAfterNoReturn(const Instruction *I) const {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001494 const Instruction *PrevI = I->getPrevNode();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001495 while (PrevI) {
1496 if (NoReturnCalls.count(PrevI))
1497 return true;
1498 PrevI = PrevI->getPrevNode();
1499 }
1500 return false;
1501}
1502
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001503const Instruction *AAIsDeadImpl::findNextNoReturn(Attributor &A,
1504 const Instruction *I) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001505 const BasicBlock *BB = I->getParent();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001506 const Function &F = *BB->getParent();
1507
1508 // Flag to determine if we can change an invoke to a call assuming the callee
1509 // is nounwind. This is not possible if the personality of the function allows
1510 // to catch asynchronous exceptions.
1511 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001512
1513 // TODO: We should have a function that determines if an "edge" is dead.
1514 // Edges could be from an instruction to the next or from a terminator
1515 // to the successor. For now, we need to special case the unwind block
1516 // of InvokeInst below.
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001517
1518 while (I) {
1519 ImmutableCallSite ICS(I);
1520
1521 if (ICS) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001522 const IRPosition &IPos = IRPosition::callsite_function(ICS);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001523 // Regarless of the no-return property of an invoke instruction we only
1524 // learn that the regular successor is not reachable through this
1525 // instruction but the unwind block might still be.
1526 if (auto *Invoke = dyn_cast<InvokeInst>(I)) {
1527 // Use nounwind to justify the unwind block is dead as well.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001528 auto *AANoUnw = A.getAAFor<AANoUnwind>(*this, IPos);
Johannes Doerfert924d2132019-08-05 21:34:45 +00001529 if (!Invoke2CallAllowed ||
1530 (!AANoUnw || !AANoUnw->isAssumedNoUnwind())) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001531 AssumedLiveBlocks.insert(Invoke->getUnwindDest());
1532 ToBeExploredPaths.insert(&Invoke->getUnwindDest()->front());
1533 }
1534 }
1535
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001536 auto *NoReturnAA = A.getAAFor<AANoReturn>(*this, IPos);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001537 if (ICS.hasFnAttr(Attribute::NoReturn) ||
1538 (NoReturnAA && NoReturnAA->isAssumedNoReturn()))
1539 return I;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001540 }
1541
1542 I = I->getNextNode();
1543 }
1544
1545 // get new paths (reachable blocks).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001546 for (const BasicBlock *SuccBB : successors(BB)) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001547 AssumedLiveBlocks.insert(SuccBB);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001548 ToBeExploredPaths.insert(&SuccBB->front());
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001549 }
1550
Johannes Doerfert4361da22019-08-04 18:38:53 +00001551 // No noreturn instruction found.
1552 return nullptr;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001553}
1554
Johannes Doerfertece81902019-08-12 22:05:53 +00001555ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001556 // Temporary collection to iterate over existing noreturn instructions. This
1557 // will alow easier modification of NoReturnCalls collection
Johannes Doerfert4361da22019-08-04 18:38:53 +00001558 SmallVector<const Instruction *, 8> NoReturnChanged;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001559 ChangeStatus Status = ChangeStatus::UNCHANGED;
1560
Johannes Doerfert4361da22019-08-04 18:38:53 +00001561 for (const Instruction *I : NoReturnCalls)
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001562 NoReturnChanged.push_back(I);
1563
Johannes Doerfert4361da22019-08-04 18:38:53 +00001564 for (const Instruction *I : NoReturnChanged) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001565 size_t Size = ToBeExploredPaths.size();
1566
Johannes Doerfert4361da22019-08-04 18:38:53 +00001567 const Instruction *NextNoReturnI = findNextNoReturn(A, I);
1568 if (NextNoReturnI != I) {
1569 Status = ChangeStatus::CHANGED;
1570 NoReturnCalls.remove(I);
1571 if (NextNoReturnI)
1572 NoReturnCalls.insert(NextNoReturnI);
1573 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001574
Johannes Doerfert4361da22019-08-04 18:38:53 +00001575 // Explore new paths.
1576 while (Size != ToBeExploredPaths.size()) {
1577 Status = ChangeStatus::CHANGED;
1578 if (const Instruction *NextNoReturnI =
1579 findNextNoReturn(A, ToBeExploredPaths[Size++]))
1580 NoReturnCalls.insert(NextNoReturnI);
1581 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001582 }
1583
Johannes Doerfertdef99282019-08-14 21:29:37 +00001584 LLVM_DEBUG(dbgs() << "[AAIsDead] AssumedLiveBlocks: "
1585 << AssumedLiveBlocks.size() << " Total number of blocks: "
1586 << getAnchorScope()->size() << "\n");
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001587
Johannes Doerfertd6207812019-08-07 22:32:38 +00001588 // If we know everything is live there is no need to query for liveness.
1589 if (NoReturnCalls.empty() &&
Johannes Doerfertdef99282019-08-14 21:29:37 +00001590 getAnchorScope()->size() == AssumedLiveBlocks.size()) {
Johannes Doerfertd6207812019-08-07 22:32:38 +00001591 // Indicating a pessimistic fixpoint will cause the state to be "invalid"
1592 // which will cause the Attributor to not return the AAIsDead on request,
1593 // which will prevent us from querying isAssumedDead().
1594 indicatePessimisticFixpoint();
1595 assert(!isValidState() && "Expected an invalid state!");
1596 }
1597
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001598 return Status;
1599}
1600
Hideto Ueno19c07af2019-07-23 08:16:17 +00001601/// -------------------- Dereferenceable Argument Attribute --------------------
1602
1603struct DerefState : AbstractState {
1604
1605 /// State representing for dereferenceable bytes.
1606 IntegerState DerefBytesState;
1607
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001608 /// State representing that whether the value is globaly dereferenceable.
1609 BooleanState GlobalState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001610
1611 /// See AbstractState::isValidState()
1612 bool isValidState() const override { return DerefBytesState.isValidState(); }
1613
Johannes Doerfertb6acee52019-08-04 17:55:15 +00001614 /// See AbstractState::isAtFixpoint()
Hideto Ueno19c07af2019-07-23 08:16:17 +00001615 bool isAtFixpoint() const override {
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001616 return !isValidState() ||
1617 (DerefBytesState.isAtFixpoint() && GlobalState.isAtFixpoint());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001618 }
1619
1620 /// See AbstractState::indicateOptimisticFixpoint(...)
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001621 ChangeStatus indicateOptimisticFixpoint() override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001622 DerefBytesState.indicateOptimisticFixpoint();
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001623 GlobalState.indicateOptimisticFixpoint();
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001624 return ChangeStatus::UNCHANGED;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001625 }
1626
1627 /// See AbstractState::indicatePessimisticFixpoint(...)
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001628 ChangeStatus indicatePessimisticFixpoint() override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001629 DerefBytesState.indicatePessimisticFixpoint();
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001630 GlobalState.indicatePessimisticFixpoint();
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001631 return ChangeStatus::CHANGED;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001632 }
1633
1634 /// Update known dereferenceable bytes.
1635 void takeKnownDerefBytesMaximum(uint64_t Bytes) {
1636 DerefBytesState.takeKnownMaximum(Bytes);
1637 }
1638
1639 /// Update assumed dereferenceable bytes.
1640 void takeAssumedDerefBytesMinimum(uint64_t Bytes) {
1641 DerefBytesState.takeAssumedMinimum(Bytes);
1642 }
1643
Hideto Ueno19c07af2019-07-23 08:16:17 +00001644 /// Equality for DerefState.
1645 bool operator==(const DerefState &R) {
1646 return this->DerefBytesState == R.DerefBytesState &&
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001647 this->GlobalState == R.GlobalState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001648 }
Johannes Doerferte1e844d2019-08-14 21:35:20 +00001649
1650 /// Inequality for IntegerState.
1651 bool operator!=(const DerefState &R) { return !(*this == R); }
1652
1653 /// See IntegerState::operator^=
1654 DerefState operator^=(const DerefState &R) {
1655 DerefBytesState ^= R.DerefBytesState;
1656 GlobalState ^= R.GlobalState;
1657 return *this;
1658 }
1659
1660 /// See IntegerState::operator&=
1661 DerefState operator&=(const DerefState &R) {
1662 DerefBytesState &= R.DerefBytesState;
1663 GlobalState &= R.GlobalState;
1664 return *this;
1665 }
1666
1667 /// See IntegerState::operator|=
1668 DerefState operator|=(const DerefState &R) {
1669 DerefBytesState |= R.DerefBytesState;
1670 GlobalState |= R.GlobalState;
1671 return *this;
1672 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001673};
Hideto Ueno19c07af2019-07-23 08:16:17 +00001674
Johannes Doerferteccdf082019-08-05 23:35:12 +00001675struct AADereferenceableImpl : AADereferenceable, DerefState {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001676 AADereferenceableImpl(const IRPosition &IRP) : AADereferenceable(IRP) {}
Johannes Doerfert344d0382019-08-07 22:34:26 +00001677 using StateType = DerefState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001678
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001679 void initialize(Attributor &A) override {
1680 SmallVector<Attribute, 4> Attrs;
1681 getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
1682 Attrs);
1683 for (const Attribute &Attr : Attrs)
1684 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
1685
1686 NonNullAA = A.getAAFor<AANonNull>(*this, getIRPosition());
1687 }
1688
Hideto Ueno19c07af2019-07-23 08:16:17 +00001689 /// See AbstractAttribute::getState()
1690 /// {
Johannes Doerfert344d0382019-08-07 22:34:26 +00001691 StateType &getState() override { return *this; }
1692 const StateType &getState() const override { return *this; }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001693 /// }
1694
1695 /// See AADereferenceable::getAssumedDereferenceableBytes().
1696 uint32_t getAssumedDereferenceableBytes() const override {
1697 return DerefBytesState.getAssumed();
1698 }
1699
1700 /// See AADereferenceable::getKnownDereferenceableBytes().
1701 uint32_t getKnownDereferenceableBytes() const override {
1702 return DerefBytesState.getKnown();
1703 }
1704
Hideto Ueno19c07af2019-07-23 08:16:17 +00001705 /// See AADereferenceable::isAssumedGlobal().
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001706 bool isAssumedGlobal() const override { return GlobalState.getAssumed(); }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001707
1708 /// See AADereferenceable::isKnownGlobal().
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001709 bool isKnownGlobal() const override { return GlobalState.getKnown(); }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001710
Hideto Ueno19c07af2019-07-23 08:16:17 +00001711 bool isAssumedNonNull() const override {
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001712 return NonNullAA && NonNullAA->isAssumedNonNull();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001713 }
1714
Johannes Doerferteccdf082019-08-05 23:35:12 +00001715 void getDeducedAttributes(LLVMContext &Ctx,
1716 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001717 // TODO: Add *_globally support
1718 if (isAssumedNonNull())
1719 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
1720 Ctx, getAssumedDereferenceableBytes()));
1721 else
1722 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
1723 Ctx, getAssumedDereferenceableBytes()));
1724 }
1725 uint64_t computeAssumedDerefenceableBytes(Attributor &A, Value &V,
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001726 bool &IsGlobal);
Hideto Ueno19c07af2019-07-23 08:16:17 +00001727
1728 /// See AbstractAttribute::getAsStr().
1729 const std::string getAsStr() const override {
1730 if (!getAssumedDereferenceableBytes())
1731 return "unknown-dereferenceable";
1732 return std::string("dereferenceable") +
1733 (isAssumedNonNull() ? "" : "_or_null") +
1734 (isAssumedGlobal() ? "_globally" : "") + "<" +
1735 std::to_string(getKnownDereferenceableBytes()) + "-" +
1736 std::to_string(getAssumedDereferenceableBytes()) + ">";
1737 }
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001738
1739private:
1740 const AANonNull *NonNullAA = nullptr;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001741};
1742
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001743struct AADereferenceableReturned final : AADereferenceableImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001744 AADereferenceableReturned(const IRPosition &IRP)
1745 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001746
1747 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001748 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001749
1750 /// See AbstractAttribute::trackStatistics()
1751 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001752 STATS_DECLTRACK_FNRET_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001753 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001754};
1755
1756// Helper function that returns dereferenceable bytes.
1757static uint64_t calcDifferenceIfBaseIsNonNull(int64_t DerefBytes,
1758 int64_t Offset, bool IsNonNull) {
1759 if (!IsNonNull)
1760 return 0;
1761 return std::max((int64_t)0, DerefBytes - Offset);
1762}
1763
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001764uint64_t
1765AADereferenceableImpl::computeAssumedDerefenceableBytes(Attributor &A, Value &V,
1766 bool &IsGlobal) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001767 // TODO: Tracking the globally flag.
1768 IsGlobal = false;
1769
1770 // First, we try to get information about V from Attributor.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001771 if (auto *DerefAA =
1772 A.getAAFor<AADereferenceable>(*this, IRPosition::value(V))) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001773 return DerefAA->getAssumedDereferenceableBytes();
1774 }
1775
1776 // Otherwise, we try to compute assumed bytes from base pointer.
Johannes Doerfert26e58462019-08-12 22:21:09 +00001777 const DataLayout &DL = A.getDataLayout();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001778 unsigned IdxWidth =
1779 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
1780 APInt Offset(IdxWidth, 0);
1781 Value *Base = V.stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
1782
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001783 if (auto *BaseDerefAA =
1784 A.getAAFor<AADereferenceable>(*this, IRPosition::value(*Base))) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001785 return calcDifferenceIfBaseIsNonNull(
1786 BaseDerefAA->getAssumedDereferenceableBytes(), Offset.getSExtValue(),
1787 Offset != 0 || BaseDerefAA->isAssumedNonNull());
1788 }
1789
1790 // Then, use IR information.
1791
1792 if (isDereferenceablePointer(Base, Base->getType(), DL))
1793 return calcDifferenceIfBaseIsNonNull(
1794 DL.getTypeStoreSize(Base->getType()->getPointerElementType()),
1795 Offset.getSExtValue(),
Johannes Doerfertdef99282019-08-14 21:29:37 +00001796 !NullPointerIsDefined(getAnchorScope(),
Hideto Ueno19c07af2019-07-23 08:16:17 +00001797 V.getType()->getPointerAddressSpace()));
1798
Hideto Ueno19c07af2019-07-23 08:16:17 +00001799 return 0;
1800}
Johannes Doerfert007153e2019-08-05 23:26:06 +00001801
Johannes Doerfertece81902019-08-12 22:05:53 +00001802ChangeStatus AADereferenceableReturned::updateImpl(Attributor &A) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001803 auto BeforeState = static_cast<DerefState>(*this);
1804
Hideto Ueno19c07af2019-07-23 08:16:17 +00001805 bool IsGlobal = isAssumedGlobal();
1806
Johannes Doerfert14a04932019-08-07 22:27:24 +00001807 auto CheckReturnValue = [&](Value &RV) -> bool {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001808 takeAssumedDerefBytesMinimum(
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001809 computeAssumedDerefenceableBytes(A, RV, IsGlobal));
Hideto Ueno19c07af2019-07-23 08:16:17 +00001810 return isValidState();
1811 };
1812
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001813 if (A.checkForAllReturnedValues(CheckReturnValue, *this)) {
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001814 GlobalState.intersectAssumedBits(IsGlobal);
Hideto Ueno19c07af2019-07-23 08:16:17 +00001815 return BeforeState == static_cast<DerefState>(*this)
1816 ? ChangeStatus::UNCHANGED
1817 : ChangeStatus::CHANGED;
1818 }
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001819 return indicatePessimisticFixpoint();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001820}
1821
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001822struct AADereferenceableArgument final : AADereferenceableImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001823 AADereferenceableArgument(const IRPosition &IRP)
1824 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001825
Hideto Ueno19c07af2019-07-23 08:16:17 +00001826 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001827 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001828
1829 /// See AbstractAttribute::trackStatistics()
1830 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001831 STATS_DECLTRACK_ARG_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001832 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001833};
1834
Johannes Doerfertece81902019-08-12 22:05:53 +00001835ChangeStatus AADereferenceableArgument::updateImpl(Attributor &A) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001836 Argument &Arg = cast<Argument>(getAnchorValue());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001837
1838 auto BeforeState = static_cast<DerefState>(*this);
1839
1840 unsigned ArgNo = Arg.getArgNo();
1841
Hideto Ueno19c07af2019-07-23 08:16:17 +00001842 bool IsGlobal = isAssumedGlobal();
1843
1844 // Callback function
1845 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) -> bool {
1846 assert(CS && "Sanity check: Call site was not initialized properly!");
1847
1848 // Check that DereferenceableAA is AADereferenceableCallSiteArgument.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001849 if (auto *DereferenceableAA = A.getAAFor<AADereferenceable>(
1850 *this, IRPosition::callsite_argument(CS, ArgNo))) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001851 ImmutableCallSite ICS(
1852 &DereferenceableAA->getIRPosition().getAnchorValue());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001853 if (ICS && CS.getInstruction() == ICS.getInstruction()) {
1854 takeAssumedDerefBytesMinimum(
1855 DereferenceableAA->getAssumedDereferenceableBytes());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001856 IsGlobal &= DereferenceableAA->isAssumedGlobal();
1857 return isValidState();
1858 }
1859 }
1860
1861 takeAssumedDerefBytesMinimum(computeAssumedDerefenceableBytes(
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001862 A, *CS.getArgOperand(ArgNo), IsGlobal));
Hideto Ueno19c07af2019-07-23 08:16:17 +00001863
1864 return isValidState();
1865 };
1866
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001867 if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001868 return indicatePessimisticFixpoint();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001869
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001870 GlobalState.intersectAssumedBits(IsGlobal);
Hideto Ueno19c07af2019-07-23 08:16:17 +00001871
1872 return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
1873 : ChangeStatus::CHANGED;
1874}
1875
1876/// Dereferenceable attribute for a call site argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001877struct AADereferenceableCallSiteArgument final : AADereferenceableImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001878 AADereferenceableCallSiteArgument(const IRPosition &IRP)
1879 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001880
1881 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00001882 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001883
1884 /// See AbstractAttribute::trackStatistics()
1885 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001886 STATS_DECLTRACK_CSARG_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001887 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001888};
1889
Johannes Doerfertece81902019-08-12 22:05:53 +00001890ChangeStatus AADereferenceableCallSiteArgument::updateImpl(Attributor &A) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001891 // NOTE: Never look at the argument of the callee in this method.
1892 // If we do this, "dereferenceable" is always deduced because of the
1893 // assumption.
1894
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001895 Value &V = getAssociatedValue();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001896
1897 auto BeforeState = static_cast<DerefState>(*this);
1898
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001899 bool IsGlobal = isAssumedGlobal();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001900
1901 takeAssumedDerefBytesMinimum(
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001902 computeAssumedDerefenceableBytes(A, V, IsGlobal));
1903 GlobalState.intersectAssumedBits(IsGlobal);
Hideto Ueno19c07af2019-07-23 08:16:17 +00001904
1905 return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
1906 : ChangeStatus::CHANGED;
1907}
1908
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001909// ------------------------ Align Argument Attribute ------------------------
1910
Johannes Doerfert344d0382019-08-07 22:34:26 +00001911struct AAAlignImpl : AAAlign {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001912 AAAlignImpl(const IRPosition &IRP) : AAAlign(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001913
1914 // Max alignemnt value allowed in IR
1915 static const unsigned MAX_ALIGN = 1U << 29;
1916
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001917 const std::string getAsStr() const override {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001918 return getAssumedAlign() ? ("align<" + std::to_string(getKnownAlign()) +
1919 "-" + std::to_string(getAssumedAlign()) + ">")
1920 : "unknown-align";
1921 }
1922
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001923 /// See AbstractAttriubute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001924 void initialize(Attributor &A) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001925 takeAssumedMinimum(MAX_ALIGN);
1926
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001927 SmallVector<Attribute, 4> Attrs;
1928 getAttrs({Attribute::Alignment}, Attrs);
1929 for (const Attribute &Attr : Attrs)
1930 takeKnownMaximum(Attr.getValueAsInt());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001931 }
1932
1933 /// See AbstractAttribute::getDeducedAttributes
1934 virtual void
Johannes Doerferteccdf082019-08-05 23:35:12 +00001935 getDeducedAttributes(LLVMContext &Ctx,
1936 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001937 Attrs.emplace_back(Attribute::getWithAlignment(Ctx, getAssumedAlign()));
1938 }
1939};
1940
1941/// Align attribute for function return value.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001942struct AAAlignReturned final : AAAlignImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001943 AAAlignReturned(const IRPosition &IRP) : AAAlignImpl(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001944
1945 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001946 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001947
1948 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001949 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001950};
1951
Johannes Doerfertece81902019-08-12 22:05:53 +00001952ChangeStatus AAAlignReturned::updateImpl(Attributor &A) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001953
1954 // Currently, align<n> is deduced if alignments in return values are assumed
1955 // as greater than n. We reach pessimistic fixpoint if any of the return value
1956 // wouldn't have align. If no assumed state was used for reasoning, an
1957 // optimistic fixpoint is reached earlier.
1958
1959 base_t BeforeState = getAssumed();
Johannes Doerfert14a04932019-08-07 22:27:24 +00001960 auto CheckReturnValue =
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001961 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &RetInsts) -> bool {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001962 auto *AlignAA = A.getAAFor<AAAlign>(*this, IRPosition::value(RV));
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001963
1964 if (AlignAA)
1965 takeAssumedMinimum(AlignAA->getAssumedAlign());
1966 else
1967 // Use IR information.
Johannes Doerfert26e58462019-08-12 22:21:09 +00001968 takeAssumedMinimum(RV.getPointerAlignment(A.getDataLayout()));
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001969
1970 return isValidState();
1971 };
1972
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001973 if (!A.checkForAllReturnedValuesAndReturnInsts(CheckReturnValue, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001974 return indicatePessimisticFixpoint();
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001975
1976 return (getAssumed() != BeforeState) ? ChangeStatus::CHANGED
1977 : ChangeStatus::UNCHANGED;
1978}
1979
1980/// Align attribute for function argument.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001981struct AAAlignArgument final : AAAlignImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001982 AAAlignArgument(const IRPosition &IRP) : AAAlignImpl(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001983
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001984 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001985 virtual ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001986
1987 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001988 void trackStatistics() const override{STATS_DECLTRACK_ARG_ATTR(aligned)};
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001989};
1990
Johannes Doerfertece81902019-08-12 22:05:53 +00001991ChangeStatus AAAlignArgument::updateImpl(Attributor &A) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001992
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001993 Argument &Arg = cast<Argument>(getAnchorValue());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001994
1995 unsigned ArgNo = Arg.getArgNo();
Johannes Doerfert26e58462019-08-12 22:21:09 +00001996 const DataLayout &DL = A.getDataLayout();
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001997
1998 auto BeforeState = getAssumed();
1999
2000 // Callback function
2001 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) {
2002 assert(CS && "Sanity check: Call site was not initialized properly!");
2003
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002004 auto *AlignAA =
2005 A.getAAFor<AAAlign>(*this, IRPosition::callsite_argument(CS, ArgNo));
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002006
2007 // Check that AlignAA is AAAlignCallSiteArgument.
2008 if (AlignAA) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002009 ImmutableCallSite ICS(&AlignAA->getIRPosition().getAnchorValue());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002010 if (ICS && CS.getInstruction() == ICS.getInstruction()) {
2011 takeAssumedMinimum(AlignAA->getAssumedAlign());
2012 return isValidState();
2013 }
2014 }
2015
2016 Value *V = CS.getArgOperand(ArgNo);
2017 takeAssumedMinimum(V->getPointerAlignment(DL));
2018 return isValidState();
2019 };
2020
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002021 if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002022 indicatePessimisticFixpoint();
2023
2024 return BeforeState == getAssumed() ? ChangeStatus::UNCHANGED
2025 : ChangeStatus ::CHANGED;
2026}
2027
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002028struct AAAlignCallSiteArgument final : AAAlignImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002029 AAAlignCallSiteArgument(const IRPosition &IRP) : AAAlignImpl(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002030
2031 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002032 void initialize(Attributor &A) override {
Johannes Doerfert26e58462019-08-12 22:21:09 +00002033 takeKnownMaximum(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002034 getAssociatedValue().getPointerAlignment(A.getDataLayout()));
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002035 }
2036
2037 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00002038 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002039
2040 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002041 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002042};
2043
Johannes Doerfertece81902019-08-12 22:05:53 +00002044ChangeStatus AAAlignCallSiteArgument::updateImpl(Attributor &A) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002045 // NOTE: Never look at the argument of the callee in this method.
2046 // If we do this, "align" is always deduced because of the assumption.
2047
2048 auto BeforeState = getAssumed();
2049
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002050 Value &V = getAssociatedValue();
2051 auto *AlignAA = A.getAAFor<AAAlign>(*this, IRPosition::value(V));
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002052
2053 if (AlignAA)
2054 takeAssumedMinimum(AlignAA->getAssumedAlign());
2055 else
2056 indicatePessimisticFixpoint();
2057
2058 return BeforeState == getAssumed() ? ChangeStatus::UNCHANGED
2059 : ChangeStatus::CHANGED;
2060}
2061
Johannes Doerferte83f3032019-08-05 23:22:05 +00002062/// ------------------ Function No-Return Attribute ----------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00002063struct AANoReturnImpl : public AANoReturn {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002064 AANoReturnImpl(const IRPosition &IRP) : AANoReturn(IRP) {}
Johannes Doerferte83f3032019-08-05 23:22:05 +00002065
Johannes Doerferte83f3032019-08-05 23:22:05 +00002066 /// See AbstractAttribute::getAsStr().
2067 const std::string getAsStr() const override {
2068 return getAssumed() ? "noreturn" : "may-return";
2069 }
2070
2071 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002072 void initialize(Attributor &A) override {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002073 if (hasAttr({getAttrKind()}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002074 indicateOptimisticFixpoint();
2075 }
2076
2077 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00002078 virtual ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002079 auto CheckForNoReturn = [](Instruction &) { return false; };
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002080 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002081 {(unsigned)Instruction::Ret}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002082 return indicatePessimisticFixpoint();
Johannes Doerferte83f3032019-08-05 23:22:05 +00002083 return ChangeStatus::UNCHANGED;
2084 }
2085};
2086
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002087struct AANoReturnFunction final : AANoReturnImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002088 AANoReturnFunction(const IRPosition &IRP) : AANoReturnImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002089
2090 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002091 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002092};
2093
Johannes Doerfertaade7822019-06-05 03:02:24 +00002094/// ----------------------------------------------------------------------------
2095/// Attributor
2096/// ----------------------------------------------------------------------------
2097
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002098bool Attributor::isAssumedDead(const AbstractAttribute &AA,
2099 const AAIsDead *LivenessAA) {
2100 const Instruction *CtxI = AA.getIRPosition().getCtxI();
2101 if (!CtxI)
2102 return false;
2103
2104 if (!LivenessAA)
2105 LivenessAA =
2106 getAAFor<AAIsDead>(AA, IRPosition::function(*CtxI->getFunction()));
2107 if (!LivenessAA || !LivenessAA->isAssumedDead(CtxI))
2108 return false;
2109
2110 // TODO: Do not track dependences automatically but add it here as only a
2111 // "is-assumed-dead" result causes a dependence.
2112 return true;
2113}
2114
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002115bool Attributor::checkForAllCallSites(const function_ref<bool(CallSite)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002116 const AbstractAttribute &QueryingAA,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002117 bool RequireAllCallSites) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002118 // We can try to determine information from
2119 // the call sites. However, this is only possible all call sites are known,
2120 // hence the function has internal linkage.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002121 const IRPosition &IRP = QueryingAA.getIRPosition();
2122 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2123 if (!AssociatedFunction)
2124 return false;
2125
2126 if (RequireAllCallSites && !AssociatedFunction->hasInternalLinkage()) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002127 LLVM_DEBUG(
2128 dbgs()
Johannes Doerfert5304b722019-08-14 22:04:28 +00002129 << "[Attributor] Function " << AssociatedFunction->getName()
Hideto Ueno54869ec2019-07-15 06:49:04 +00002130 << " has no internal linkage, hence not all call sites are known\n");
2131 return false;
2132 }
2133
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002134 for (const Use &U : AssociatedFunction->uses()) {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002135 Instruction *I = cast<Instruction>(U.getUser());
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002136 Function *Caller = I->getFunction();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002137
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002138 auto *LivenessAA =
2139 getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*Caller));
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002140
2141 // Skip dead calls.
2142 if (LivenessAA && LivenessAA->isAssumedDead(I))
2143 continue;
Hideto Ueno54869ec2019-07-15 06:49:04 +00002144
2145 CallSite CS(U.getUser());
Hideto Ueno54869ec2019-07-15 06:49:04 +00002146 if (!CS || !CS.isCallee(&U) || !CS.getCaller()->hasExactDefinition()) {
2147 if (!RequireAllCallSites)
2148 continue;
2149
Johannes Doerfert5304b722019-08-14 22:04:28 +00002150 LLVM_DEBUG(dbgs() << "[Attributor] User " << *U.getUser()
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002151 << " is an invalid use of "
2152 << AssociatedFunction->getName() << "\n");
Hideto Ueno54869ec2019-07-15 06:49:04 +00002153 return false;
2154 }
2155
2156 if (Pred(CS))
2157 continue;
2158
Johannes Doerfert5304b722019-08-14 22:04:28 +00002159 LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for "
Hideto Ueno54869ec2019-07-15 06:49:04 +00002160 << *CS.getInstruction() << "\n");
2161 return false;
2162 }
2163
2164 return true;
2165}
2166
Johannes Doerfert14a04932019-08-07 22:27:24 +00002167bool Attributor::checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert14a04932019-08-07 22:27:24 +00002168 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
2169 &Pred,
2170 const AbstractAttribute &QueryingAA) {
2171
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002172 const IRPosition &IRP = QueryingAA.getIRPosition();
2173 // Since we need to provide return instructions we have to have an exact
2174 // definition.
2175 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2176 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
Johannes Doerfert14a04932019-08-07 22:27:24 +00002177 return false;
2178
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002179 // If this is a call site query we use the call site specific return values
2180 // and liveness information.
2181 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2182 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
2183 if (!AARetVal || !AARetVal->getState().isValidState())
2184 return false;
2185
Johannes Doerfertdef99282019-08-14 21:29:37 +00002186 return AARetVal->checkForAllReturnedValuesAndReturnInsts(Pred);
Johannes Doerfert14a04932019-08-07 22:27:24 +00002187}
2188
2189bool Attributor::checkForAllReturnedValues(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002190 const function_ref<bool(Value &)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002191 const AbstractAttribute &QueryingAA) {
2192
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002193 const IRPosition &IRP = QueryingAA.getIRPosition();
2194 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2195 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
Johannes Doerfert14a04932019-08-07 22:27:24 +00002196 return false;
2197
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002198 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2199 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
2200 if (!AARetVal || !AARetVal->getState().isValidState())
2201 return false;
2202
Johannes Doerfertdef99282019-08-14 21:29:37 +00002203 return AARetVal->checkForAllReturnedValuesAndReturnInsts(
2204 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &) {
2205 return Pred(RV);
2206 });
Johannes Doerfert14a04932019-08-07 22:27:24 +00002207}
2208
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002209bool Attributor::checkForAllInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002210 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00002211 const AbstractAttribute &QueryingAA, const ArrayRef<unsigned> &Opcodes) {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002212
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002213 const IRPosition &IRP = QueryingAA.getIRPosition();
2214 // Since we need to provide instructions we have to have an exact definition.
2215 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2216 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
2217 return false;
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002218
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002219 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2220 const auto &LivenessAA = getAAFor<AAIsDead>(QueryingAA, QueryIRP);
2221
2222 auto &OpcodeInstMap =
2223 InfoCache.getOpcodeInstMapForFunction(*AssociatedFunction);
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002224 for (unsigned Opcode : Opcodes) {
2225 for (Instruction *I : OpcodeInstMap[Opcode]) {
2226 // Skip dead instructions.
2227 if (LivenessAA && LivenessAA->isAssumedDead(I))
2228 continue;
2229
2230 if (!Pred(*I))
2231 return false;
2232 }
2233 }
2234
2235 return true;
2236}
2237
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002238bool Attributor::checkForAllReadWriteInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002239 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00002240 AbstractAttribute &QueryingAA) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002241
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002242 const Function *AssociatedFunction =
2243 QueryingAA.getIRPosition().getAssociatedFunction();
2244 if (!AssociatedFunction)
2245 return false;
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002246
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002247 const auto &LivenessAA =
2248 getAAFor<AAIsDead>(QueryingAA, QueryingAA.getIRPosition());
2249
2250 for (Instruction *I :
2251 InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002252 // Skip dead instructions.
2253 if (LivenessAA && LivenessAA->isAssumedDead(I))
2254 continue;
2255
2256 if (!Pred(*I))
2257 return false;
2258 }
2259
2260 return true;
2261}
2262
Johannes Doerfertece81902019-08-12 22:05:53 +00002263ChangeStatus Attributor::run() {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002264 // Initialize all abstract attributes.
2265 for (AbstractAttribute *AA : AllAbstractAttributes)
Johannes Doerfertece81902019-08-12 22:05:53 +00002266 AA->initialize(*this);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002267
2268 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
2269 << AllAbstractAttributes.size()
2270 << " abstract attributes.\n");
2271
Stefan Stipanovic53605892019-06-27 11:27:54 +00002272 // Now that all abstract attributes are collected and initialized we start
2273 // the abstract analysis.
Johannes Doerfertaade7822019-06-05 03:02:24 +00002274
2275 unsigned IterationCounter = 1;
2276
2277 SmallVector<AbstractAttribute *, 64> ChangedAAs;
2278 SetVector<AbstractAttribute *> Worklist;
2279 Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
2280
2281 do {
2282 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
2283 << ", Worklist size: " << Worklist.size() << "\n");
2284
2285 // Add all abstract attributes that are potentially dependent on one that
2286 // changed to the work list.
2287 for (AbstractAttribute *ChangedAA : ChangedAAs) {
2288 auto &QuerriedAAs = QueryMap[ChangedAA];
2289 Worklist.insert(QuerriedAAs.begin(), QuerriedAAs.end());
2290 }
2291
2292 // Reset the changed set.
2293 ChangedAAs.clear();
2294
2295 // Update all abstract attribute in the work list and record the ones that
2296 // changed.
2297 for (AbstractAttribute *AA : Worklist)
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002298 if (!isAssumedDead(*AA, nullptr))
2299 if (AA->update(*this) == ChangeStatus::CHANGED)
2300 ChangedAAs.push_back(AA);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002301
2302 // Reset the work list and repopulate with the changed abstract attributes.
2303 // Note that dependent ones are added above.
2304 Worklist.clear();
2305 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2306
2307 } while (!Worklist.empty() && ++IterationCounter < MaxFixpointIterations);
2308
2309 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
2310 << IterationCounter << "/" << MaxFixpointIterations
2311 << " iterations\n");
2312
2313 bool FinishedAtFixpoint = Worklist.empty();
2314
2315 // Reset abstract arguments not settled in a sound fixpoint by now. This
2316 // happens when we stopped the fixpoint iteration early. Note that only the
2317 // ones marked as "changed" *and* the ones transitively depending on them
2318 // need to be reverted to a pessimistic state. Others might not be in a
2319 // fixpoint state but we can use the optimistic results for them anyway.
2320 SmallPtrSet<AbstractAttribute *, 32> Visited;
2321 for (unsigned u = 0; u < ChangedAAs.size(); u++) {
2322 AbstractAttribute *ChangedAA = ChangedAAs[u];
2323 if (!Visited.insert(ChangedAA).second)
2324 continue;
2325
2326 AbstractState &State = ChangedAA->getState();
2327 if (!State.isAtFixpoint()) {
2328 State.indicatePessimisticFixpoint();
2329
2330 NumAttributesTimedOut++;
2331 }
2332
2333 auto &QuerriedAAs = QueryMap[ChangedAA];
2334 ChangedAAs.append(QuerriedAAs.begin(), QuerriedAAs.end());
2335 }
2336
2337 LLVM_DEBUG({
2338 if (!Visited.empty())
2339 dbgs() << "\n[Attributor] Finalized " << Visited.size()
2340 << " abstract attributes.\n";
2341 });
2342
2343 unsigned NumManifested = 0;
2344 unsigned NumAtFixpoint = 0;
2345 ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
2346 for (AbstractAttribute *AA : AllAbstractAttributes) {
2347 AbstractState &State = AA->getState();
2348
2349 // If there is not already a fixpoint reached, we can now take the
2350 // optimistic state. This is correct because we enforced a pessimistic one
2351 // on abstract attributes that were transitively dependent on a changed one
2352 // already above.
2353 if (!State.isAtFixpoint())
2354 State.indicateOptimisticFixpoint();
2355
2356 // If the state is invalid, we do not try to manifest it.
2357 if (!State.isValidState())
2358 continue;
2359
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002360 // Skip dead code.
2361 if (isAssumedDead(*AA, nullptr))
2362 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002363 // Manifest the state and record if we changed the IR.
2364 ChangeStatus LocalChange = AA->manifest(*this);
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002365 if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled())
2366 AA->trackStatistics();
2367
Johannes Doerfertaade7822019-06-05 03:02:24 +00002368 ManifestChange = ManifestChange | LocalChange;
2369
2370 NumAtFixpoint++;
2371 NumManifested += (LocalChange == ChangeStatus::CHANGED);
2372 }
2373
2374 (void)NumManifested;
2375 (void)NumAtFixpoint;
2376 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
2377 << " arguments while " << NumAtFixpoint
2378 << " were in a valid fixpoint state\n");
2379
2380 // If verification is requested, we finished this run at a fixpoint, and the
2381 // IR was changed, we re-run the whole fixpoint analysis, starting at
2382 // re-initialization of the arguments. This re-run should not result in an IR
2383 // change. Though, the (virtual) state of attributes at the end of the re-run
2384 // might be more optimistic than the known state or the IR state if the better
2385 // state cannot be manifested.
2386 if (VerifyAttributor && FinishedAtFixpoint &&
2387 ManifestChange == ChangeStatus::CHANGED) {
2388 VerifyAttributor = false;
Johannes Doerfertece81902019-08-12 22:05:53 +00002389 ChangeStatus VerifyStatus = run();
Johannes Doerfertaade7822019-06-05 03:02:24 +00002390 if (VerifyStatus != ChangeStatus::UNCHANGED)
2391 llvm_unreachable(
2392 "Attributor verification failed, re-run did result in an IR change "
2393 "even after a fixpoint was reached in the original run. (False "
2394 "positives possible!)");
2395 VerifyAttributor = true;
2396 }
2397
2398 NumAttributesManifested += NumManifested;
2399 NumAttributesValidFixpoint += NumAtFixpoint;
2400
2401 return ManifestChange;
2402}
2403
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002404/// Helper function that checks if an abstract attribute of type \p AAType
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002405/// should be created for IR position \p IRP and if so creates and registers it
2406/// with the Attributor \p A.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002407///
2408/// This method will look at the provided whitelist. If one is given and the
2409/// kind \p AAType::ID is not contained, no abstract attribute is created.
2410///
2411/// \returns The created abstract argument, or nullptr if none was created.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002412template <typename AAType>
Johannes Doerfert5304b722019-08-14 22:04:28 +00002413static AAType *checkAndRegisterAA(const IRPosition &IRP, Attributor &A,
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002414 DenseSet<const char *> *Whitelist) {
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002415 if (Whitelist && !Whitelist->count(&AAType::ID))
2416 return nullptr;
2417
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002418 return &A.registerAA<AAType>(*new AAType(IRP));
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002419}
2420
Johannes Doerfertaade7822019-06-05 03:02:24 +00002421void Attributor::identifyDefaultAbstractAttributes(
Johannes Doerfertece81902019-08-12 22:05:53 +00002422 Function &F, DenseSet<const char *> *Whitelist) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002423
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002424 IRPosition FPos = IRPosition::function(F);
2425
Johannes Doerfert305b9612019-08-04 18:40:01 +00002426 // Check for dead BasicBlocks in every function.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002427 // We need dead instruction detection because we do not want to deal with
2428 // broken IR in which SSA rules do not apply.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002429 checkAndRegisterAA<AAIsDeadFunction>(FPos, *this, /* Whitelist */ nullptr);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002430
2431 // Every function might be "will-return".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002432 checkAndRegisterAA<AAWillReturnFunction>(FPos, *this, Whitelist);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002433
Stefan Stipanovic53605892019-06-27 11:27:54 +00002434 // Every function can be nounwind.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002435 checkAndRegisterAA<AANoUnwindFunction>(FPos, *this, Whitelist);
Stefan Stipanovic53605892019-06-27 11:27:54 +00002436
Stefan Stipanovic06263672019-07-11 21:37:40 +00002437 // Every function might be marked "nosync"
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002438 checkAndRegisterAA<AANoSyncFunction>(FPos, *this, Whitelist);
Stefan Stipanovic06263672019-07-11 21:37:40 +00002439
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002440 // Every function might be "no-free".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002441 checkAndRegisterAA<AANoFreeFunction>(FPos, *this, Whitelist);
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002442
Johannes Doerferte83f3032019-08-05 23:22:05 +00002443 // Every function might be "no-return".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002444 checkAndRegisterAA<AANoReturnFunction>(FPos, *this, Whitelist);
Johannes Doerferte83f3032019-08-05 23:22:05 +00002445
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002446 // Return attributes are only appropriate if the return type is non void.
2447 Type *ReturnType = F.getReturnType();
2448 if (!ReturnType->isVoidTy()) {
2449 // Argument attribute "returned" --- Create only one per function even
2450 // though it is an argument attribute.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002451 checkAndRegisterAA<AAReturnedValuesFunction>(FPos, *this, Whitelist);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002452
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002453 if (ReturnType->isPointerTy()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002454 IRPosition RetPos = IRPosition::returned(F);
2455
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002456 // Every function with pointer return type might be marked align.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002457 checkAndRegisterAA<AAAlignReturned>(RetPos, *this, Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002458
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002459 // Every function with pointer return type might be marked nonnull.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002460 checkAndRegisterAA<AANonNullReturned>(RetPos, *this, Whitelist);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002461
2462 // Every function with pointer return type might be marked noalias.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002463 checkAndRegisterAA<AANoAliasReturned>(RetPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002464
2465 // Every function with pointer return type might be marked
2466 // dereferenceable.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002467 checkAndRegisterAA<AADereferenceableReturned>(RetPos, *this, Whitelist);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002468 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00002469 }
2470
Hideto Ueno54869ec2019-07-15 06:49:04 +00002471 for (Argument &Arg : F.args()) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002472 if (Arg.getType()->isPointerTy()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002473 IRPosition ArgPos = IRPosition::argument(Arg);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002474 // Every argument with pointer type might be marked nonnull.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002475 checkAndRegisterAA<AANonNullArgument>(ArgPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002476
2477 // Every argument with pointer type might be marked dereferenceable.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002478 checkAndRegisterAA<AADereferenceableArgument>(ArgPos, *this, Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002479
2480 // Every argument with pointer type might be marked align.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002481 checkAndRegisterAA<AAAlignArgument>(ArgPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002482 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002483 }
2484
Johannes Doerfertaade7822019-06-05 03:02:24 +00002485 // Walk all instructions to find more attribute opportunities and also
2486 // interesting instructions that might be queried by abstract attributes
2487 // during their initialization or update.
2488 auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
2489 auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
2490
2491 for (Instruction &I : instructions(&F)) {
2492 bool IsInterestingOpcode = false;
2493
2494 // To allow easy access to all instructions in a function with a given
2495 // opcode we store them in the InfoCache. As not all opcodes are interesting
2496 // to concrete attributes we only cache the ones that are as identified in
2497 // the following switch.
2498 // Note: There are no concrete attributes now so this is initially empty.
Stefan Stipanovic53605892019-06-27 11:27:54 +00002499 switch (I.getOpcode()) {
2500 default:
2501 assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) &&
2502 "New call site/base instruction type needs to be known int the "
2503 "attributor.");
2504 break;
2505 case Instruction::Call:
2506 case Instruction::CallBr:
2507 case Instruction::Invoke:
2508 case Instruction::CleanupRet:
2509 case Instruction::CatchSwitch:
2510 case Instruction::Resume:
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002511 case Instruction::Ret:
Stefan Stipanovic53605892019-06-27 11:27:54 +00002512 IsInterestingOpcode = true;
2513 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002514 if (IsInterestingOpcode)
2515 InstOpcodeMap[I.getOpcode()].push_back(&I);
2516 if (I.mayReadOrWriteMemory())
2517 ReadOrWriteInsts.push_back(&I);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002518
2519 CallSite CS(&I);
2520 if (CS && CS.getCalledFunction()) {
2521 for (int i = 0, e = CS.getCalledFunction()->arg_size(); i < e; i++) {
2522 if (!CS.getArgument(i)->getType()->isPointerTy())
2523 continue;
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002524 IRPosition CSArgPos = IRPosition::callsite_argument(CS, i);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002525
2526 // Call site argument attribute "non-null".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002527 checkAndRegisterAA<AANonNullCallSiteArgument>(CSArgPos, *this,
2528 Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002529
2530 // Call site argument attribute "dereferenceable".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002531 checkAndRegisterAA<AADereferenceableCallSiteArgument>(CSArgPos, *this,
2532 Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002533
2534 // Call site argument attribute "align".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002535 checkAndRegisterAA<AAAlignCallSiteArgument>(CSArgPos, *this, Whitelist);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002536 }
2537 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002538 }
2539}
2540
2541/// Helpers to ease debugging through output streams and print calls.
2542///
2543///{
2544raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
2545 return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
2546}
2547
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002548raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002549 switch (AP) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002550 case IRPosition::IRP_INVALID:
2551 return OS << "inv";
2552 case IRPosition::IRP_FLOAT:
2553 return OS << "flt";
2554 case IRPosition::IRP_RETURNED:
2555 return OS << "fn_ret";
2556 case IRPosition::IRP_CALL_SITE_RETURNED:
2557 return OS << "cs_ret";
2558 case IRPosition::IRP_FUNCTION:
2559 return OS << "fn";
2560 case IRPosition::IRP_CALL_SITE:
2561 return OS << "cs";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002562 case IRPosition::IRP_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002563 return OS << "arg";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002564 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002565 return OS << "cs_arg";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002566 }
2567 llvm_unreachable("Unknown attribute position!");
2568}
2569
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002570raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002571 const Value &AV = Pos.getAssociatedValue();
2572 return OS << "{" << Pos.getPositionKind() << ":" << AV.getName() << " ["
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002573 << Pos.getAnchorValue().getName() << "@" << Pos.getArgNo() << "]}";
2574}
2575
Johannes Doerfertacc80792019-08-12 22:07:34 +00002576raw_ostream &llvm::operator<<(raw_ostream &OS, const IntegerState &S) {
2577 return OS << "(" << S.getKnown() << "-" << S.getAssumed() << ")"
2578 << static_cast<const AbstractState &>(S);
2579}
2580
Johannes Doerfertaade7822019-06-05 03:02:24 +00002581raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
2582 return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
2583}
2584
2585raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
2586 AA.print(OS);
2587 return OS;
2588}
2589
2590void AbstractAttribute::print(raw_ostream &OS) const {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002591 OS << "[P: " << getIRPosition() << "][" << getAsStr() << "][S: " << getState()
2592 << "]";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002593}
2594///}
2595
2596/// ----------------------------------------------------------------------------
2597/// Pass (Manager) Boilerplate
2598/// ----------------------------------------------------------------------------
2599
2600static bool runAttributorOnModule(Module &M) {
2601 if (DisableAttributor)
2602 return false;
2603
2604 LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << M.size()
2605 << " functions.\n");
2606
2607 // Create an Attributor and initially empty information cache that is filled
2608 // while we identify default attribute opportunities.
Johannes Doerfertece81902019-08-12 22:05:53 +00002609 InformationCache InfoCache(M.getDataLayout());
2610 Attributor A(InfoCache);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002611
2612 for (Function &F : M) {
2613 // TODO: Not all attributes require an exact definition. Find a way to
2614 // enable deduction for some but not all attributes in case the
2615 // definition might be changed at runtime, see also
2616 // http://lists.llvm.org/pipermail/llvm-dev/2018-February/121275.html.
2617 // TODO: We could always determine abstract attributes and if sufficient
2618 // information was found we could duplicate the functions that do not
2619 // have an exact definition.
2620 if (!F.hasExactDefinition()) {
2621 NumFnWithoutExactDefinition++;
2622 continue;
2623 }
2624
2625 // For now we ignore naked and optnone functions.
2626 if (F.hasFnAttribute(Attribute::Naked) ||
2627 F.hasFnAttribute(Attribute::OptimizeNone))
2628 continue;
2629
2630 NumFnWithExactDefinition++;
2631
2632 // Populate the Attributor with abstract attribute opportunities in the
2633 // function and the information cache with IR information.
Johannes Doerfertece81902019-08-12 22:05:53 +00002634 A.identifyDefaultAbstractAttributes(F);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002635 }
2636
Johannes Doerfertece81902019-08-12 22:05:53 +00002637 return A.run() == ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002638}
2639
2640PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
2641 if (runAttributorOnModule(M)) {
2642 // FIXME: Think about passes we will preserve and add them here.
2643 return PreservedAnalyses::none();
2644 }
2645 return PreservedAnalyses::all();
2646}
2647
2648namespace {
2649
2650struct AttributorLegacyPass : public ModulePass {
2651 static char ID;
2652
2653 AttributorLegacyPass() : ModulePass(ID) {
2654 initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry());
2655 }
2656
2657 bool runOnModule(Module &M) override {
2658 if (skipModule(M))
2659 return false;
2660 return runAttributorOnModule(M);
2661 }
2662
2663 void getAnalysisUsage(AnalysisUsage &AU) const override {
2664 // FIXME: Think about passes we will preserve and add them here.
2665 AU.setPreservesCFG();
2666 }
2667};
2668
2669} // end anonymous namespace
2670
2671Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); }
2672
2673char AttributorLegacyPass::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002674
2675const char AAReturnedValues::ID = 0;
2676const char AANoUnwind::ID = 0;
2677const char AANoSync::ID = 0;
Johannes Doerferteccdf082019-08-05 23:35:12 +00002678const char AANoFree::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002679const char AANonNull::ID = 0;
2680const char AANoRecurse::ID = 0;
2681const char AAWillReturn::ID = 0;
2682const char AANoAlias::ID = 0;
2683const char AANoReturn::ID = 0;
2684const char AAIsDead::ID = 0;
2685const char AADereferenceable::ID = 0;
2686const char AAAlign::ID = 0;
2687
Johannes Doerfertaade7822019-06-05 03:02:24 +00002688INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor",
2689 "Deduce and propagate attributes", false, false)
2690INITIALIZE_PASS_END(AttributorLegacyPass, "attributor",
2691 "Deduce and propagate attributes", false, false)