blob: 34fe5552a40d58f605919603008af14eca15132b [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
Johannes Doerfert234eda52019-08-16 19:51:23 +0000455/// Helper functions to clamp a state \p S of type \p StateType with the
456/// information in \p R and indicate/return if \p S did change (as-in update is
457/// required to be run again).
458///
459///{
460template <typename StateType>
461ChangeStatus clampStateAndIndicateChange(StateType &S, const StateType &R);
462
463template <>
464ChangeStatus clampStateAndIndicateChange<IntegerState>(IntegerState &S,
465 const IntegerState &R) {
466 auto Assumed = S.getAssumed();
467 S ^= R;
468 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
469 : ChangeStatus::CHANGED;
470}
471///}
472
473/// Clamp the information known for all returned values of a function
474/// (identified by \p QueryingAA) into \p S.
475template <typename AAType, typename StateType = typename AAType::StateType>
476static void clampReturnedValueStates(Attributor &A, const AAType &QueryingAA,
477 StateType &S) {
478 LLVM_DEBUG(dbgs() << "[Attributor] Clamp return value states for "
479 << static_cast<const AbstractAttribute &>(QueryingAA)
480 << " into " << S << "\n");
481
482 assert((QueryingAA.getIRPosition().getPositionKind() ==
483 IRPosition::IRP_RETURNED ||
484 QueryingAA.getIRPosition().getPositionKind() ==
485 IRPosition::IRP_CALL_SITE_RETURNED) &&
486 "Can only clamp returned value states for a function returned or call "
487 "site returned position!");
488
489 // Use an optional state as there might not be any return values and we want
490 // to join (IntegerState::operator&) the state of all there are.
491 Optional<StateType> T;
492
493 // Callback for each possibly returned value.
494 auto CheckReturnValue = [&](Value &RV) -> bool {
495 const IRPosition &RVPos = IRPosition::value(RV);
496 const AAType *AA = A.getAAFor<AAType>(QueryingAA, RVPos);
497 LLVM_DEBUG(dbgs() << "[Attributor] RV: " << RV
498 << " AA: " << (AA ? AA->getAsStr() : "n/a") << " @ "
499 << RVPos << "\n");
500 // TODO: We should create abstract attributes on-demand, patches are already
501 // prepared, pending approval.
502 if (!AA || AA->getIRPosition() != RVPos)
503 return false;
504 const StateType &AAS = static_cast<const StateType &>(AA->getState());
505 if (T.hasValue())
506 *T &= AAS;
507 else
508 T = AAS;
509 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " RV State: " << T
510 << "\n");
511 return T->isValidState();
512 };
513
514 if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA))
515 S.indicatePessimisticFixpoint();
516 else if (T.hasValue())
517 S ^= *T;
518}
519
520/// Helper class for generic deduction: return value -> returned position.
521template <typename AAType, typename StateType = typename AAType::StateType>
522struct AAReturnedFromReturnedValues : public AAType {
523 AAReturnedFromReturnedValues(const IRPosition &IRP) : AAType(IRP) {}
524
525 /// See AbstractAttribute::updateImpl(...).
526 ChangeStatus updateImpl(Attributor &A) override {
527 StateType S;
528 clampReturnedValueStates<AAType, StateType>(A, *this, S);
529 return clampStateAndIndicateChange<StateType>(this->getState(), S);
530 }
531};
532
533/// Clamp the information known at all call sites for a given argument
534/// (identified by \p QueryingAA) into \p S.
535template <typename AAType, typename StateType = typename AAType::StateType>
536static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
537 StateType &S) {
538 LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for "
539 << static_cast<const AbstractAttribute &>(QueryingAA)
540 << " into " << S << "\n");
541
542 assert(QueryingAA.getIRPosition().getPositionKind() ==
543 IRPosition::IRP_ARGUMENT &&
544 "Can only clamp call site argument states for an argument position!");
545
546 // Use an optional state as there might not be any return values and we want
547 // to join (IntegerState::operator&) the state of all there are.
548 Optional<StateType> T;
549
550 // The argument number which is also the call site argument number.
551 unsigned ArgNo = QueryingAA.getIRPosition().getArgNo();
552
553 auto CallSiteCheck = [&](CallSite CS) {
554 const IRPosition &CSArgPos = IRPosition::callsite_argument(CS, ArgNo);
555 const AAType *AA = A.getAAFor<AAType>(QueryingAA, CSArgPos);
556 LLVM_DEBUG(dbgs() << "[Attributor] CS: " << *CS.getInstruction()
557 << " AA: " << (AA ? AA->getAsStr() : "n/a") << " @"
558 << CSArgPos << "\n");
559 // TODO: We should create abstract attributes on-demand, patches are already
560 // prepared, pending approval.
561 if (!AA || AA->getIRPosition() != CSArgPos)
562 return false;
563 const StateType &AAS = static_cast<const StateType &>(AA->getState());
564 if (T.hasValue())
565 *T &= AAS;
566 else
567 T = AAS;
568 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " CSA State: " << T
569 << "\n");
570 return T->isValidState();
571 };
572
573 if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true))
574 S.indicatePessimisticFixpoint();
575 else if (T.hasValue())
576 S ^= *T;
577}
578
579/// Helper class for generic deduction: call site argument -> argument position.
580template <typename AAType, typename StateType = typename AAType::StateType>
581struct AAArgumentFromCallSiteArguments : public AAType {
582 AAArgumentFromCallSiteArguments(const IRPosition &IRP) : AAType(IRP) {}
583
584 /// See AbstractAttribute::updateImpl(...).
585 ChangeStatus updateImpl(Attributor &A) override {
586 StateType S;
587 clampCallSiteArgumentStates<AAType, StateType>(A, *this, S);
588 return clampStateAndIndicateChange<StateType>(this->getState(), S);
589 }
590};
591
592/// Helper class for generic replication: function returned -> cs returned.
593template <typename AAType>
594struct AACallSiteReturnedFromReturned : public AAType {
595 AACallSiteReturnedFromReturned(const IRPosition &IRP) : AAType(IRP) {}
596
597 /// See AbstractAttribute::updateImpl(...).
598 ChangeStatus updateImpl(Attributor &A) override {
599 assert(this->getIRPosition().getPositionKind() ==
600 IRPosition::IRP_CALL_SITE_RETURNED &&
601 "Can only wrap function returned positions for call site returned "
602 "positions!");
603 auto &S = this->getState();
604
605 const Function *AssociatedFunction =
606 this->getIRPosition().getAssociatedFunction();
607 if (!AssociatedFunction)
608 return S.indicatePessimisticFixpoint();
609
610 IRPosition FnPos = IRPosition::returned(*AssociatedFunction);
611 // TODO: We should create abstract attributes on-demand, patches are already
612 // prepared, pending approval.
613 const AAType *AA = A.getAAFor<AAType>(*this, FnPos);
614 if (!AA)
615 return S.indicatePessimisticFixpoint();
616 return clampStateAndIndicateChange(
617 S, static_cast<const typename AAType::StateType &>(AA->getState()));
618 }
619};
620
Stefan Stipanovic53605892019-06-27 11:27:54 +0000621/// -----------------------NoUnwind Function Attribute--------------------------
622
Johannes Doerfert344d0382019-08-07 22:34:26 +0000623struct AANoUnwindImpl : AANoUnwind {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000624 AANoUnwindImpl(const IRPosition &IRP) : AANoUnwind(IRP) {}
Stefan Stipanovic53605892019-06-27 11:27:54 +0000625
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +0000626 /// See AbstractAttribute::initialize(...).
627 void initialize(Attributor &A) override {
628 if (hasAttr({Attribute::NoUnwind}))
629 indicateOptimisticFixpoint();
630 }
631
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000632 const std::string getAsStr() const override {
Stefan Stipanovic53605892019-06-27 11:27:54 +0000633 return getAssumed() ? "nounwind" : "may-unwind";
634 }
635
636 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +0000637 ChangeStatus updateImpl(Attributor &A) override {
638 auto Opcodes = {
639 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
640 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
641 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
642
643 auto CheckForNoUnwind = [&](Instruction &I) {
644 if (!I.mayThrow())
645 return true;
646
647 auto *NoUnwindAA = A.getAAFor<AANoUnwind>(*this, IRPosition::value(I));
648 return NoUnwindAA && NoUnwindAA->isAssumedNoUnwind();
649 };
650
651 if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes))
652 return indicatePessimisticFixpoint();
653
654 return ChangeStatus::UNCHANGED;
655 }
Stefan Stipanovic53605892019-06-27 11:27:54 +0000656};
657
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000658struct AANoUnwindFunction final : public AANoUnwindImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000659 AANoUnwindFunction(const IRPosition &IRP) : AANoUnwindImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000660
661 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000662 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000663};
664
Johannes Doerfert66cf87e2019-08-16 19:49:00 +0000665/// NoUnwind attribute deduction for a call sites.
666using AANoUnwindCallSite = AANoUnwindFunction;
667
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000668/// --------------------- Function Return Values -------------------------------
669
670/// "Attribute" that collects all potential returned values and the return
671/// instructions that they arise from.
672///
673/// If there is a unique returned value R, the manifest method will:
674/// - mark R with the "returned" attribute, if R is an argument.
Johannes Doerferteccdf082019-08-05 23:35:12 +0000675class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000676
677 /// Mapping of values potentially returned by the associated function to the
678 /// return instructions that might return them.
679 DenseMap<Value *, SmallPtrSet<ReturnInst *, 2>> ReturnedValues;
680
Johannes Doerfertdef99282019-08-14 21:29:37 +0000681 SmallPtrSet<CallBase *, 8> UnresolvedCalls;
682
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000683 /// State flags
684 ///
685 ///{
686 bool IsFixed;
687 bool IsValidState;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000688 ///}
689
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000690public:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000691 AAReturnedValuesImpl(const IRPosition &IRP) : AAReturnedValues(IRP) {}
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000692
693 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +0000694 void initialize(Attributor &A) override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000695 // Reset the state.
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000696 IsFixed = false;
697 IsValidState = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000698 ReturnedValues.clear();
699
Johannes Doerfertdef99282019-08-14 21:29:37 +0000700 Function *F = getAssociatedFunction();
701 if (!F || !F->hasExactDefinition()) {
702 indicatePessimisticFixpoint();
703 return;
704 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000705
706 // The map from instruction opcodes to those instructions in the function.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000707 auto &OpcodeInstMap = A.getInfoCache().getOpcodeInstMapForFunction(*F);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000708
709 // Look through all arguments, if one is marked as returned we are done.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000710 for (Argument &Arg : F->args()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000711 if (Arg.hasReturnedAttr()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000712 auto &ReturnInstSet = ReturnedValues[&Arg];
713 for (Instruction *RI : OpcodeInstMap[Instruction::Ret])
714 ReturnInstSet.insert(cast<ReturnInst>(RI));
715
716 indicateOptimisticFixpoint();
717 return;
718 }
719 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000720 }
721
722 /// See AbstractAttribute::manifest(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000723 ChangeStatus manifest(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000724
725 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000726 AbstractState &getState() override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000727
728 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000729 const AbstractState &getState() const override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000730
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000731 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +0000732 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000733
Johannes Doerfertdef99282019-08-14 21:29:37 +0000734 llvm::iterator_range<iterator> returned_values() override {
735 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
736 }
737
738 llvm::iterator_range<const_iterator> returned_values() const override {
739 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
740 }
741
742 const SmallPtrSetImpl<CallBase *> &getUnresolvedCalls() const override {
743 return UnresolvedCalls;
744 }
745
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000746 /// Return the number of potential return values, -1 if unknown.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000747 size_t getNumReturnValues() const override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000748 return isValidState() ? ReturnedValues.size() : -1;
749 }
750
751 /// Return an assumed unique return value if a single candidate is found. If
752 /// there cannot be one, return a nullptr. If it is not clear yet, return the
753 /// Optional::NoneType.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000754 Optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000755
Johannes Doerfert14a04932019-08-07 22:27:24 +0000756 /// See AbstractState::checkForAllReturnedValues(...).
757 bool checkForAllReturnedValuesAndReturnInsts(
758 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
759 &Pred) const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000760
761 /// Pretty print the attribute similar to the IR representation.
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000762 const std::string getAsStr() const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000763
764 /// See AbstractState::isAtFixpoint().
765 bool isAtFixpoint() const override { return IsFixed; }
766
767 /// See AbstractState::isValidState().
768 bool isValidState() const override { return IsValidState; }
769
770 /// See AbstractState::indicateOptimisticFixpoint(...).
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000771 ChangeStatus indicateOptimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000772 IsFixed = true;
773 IsValidState &= true;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000774 return ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000775 }
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000776
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000777 ChangeStatus indicatePessimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000778 IsFixed = true;
779 IsValidState = false;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000780 return ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000781 }
782};
783
784ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) {
785 ChangeStatus Changed = ChangeStatus::UNCHANGED;
786
787 // Bookkeeping.
788 assert(isValidState());
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000789 STATS_DECLTRACK(KnownReturnValues, FunctionReturn,
790 "Number of function with known return values");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000791
792 // Check if we have an assumed unique return value that we could manifest.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000793 Optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000794
795 if (!UniqueRV.hasValue() || !UniqueRV.getValue())
796 return Changed;
797
798 // Bookkeeping.
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000799 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
800 "Number of function with unique return");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000801
802 // If the assumed unique return value is an argument, annotate it.
803 if (auto *UniqueRVArg = dyn_cast<Argument>(UniqueRV.getValue())) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000804 getIRPosition() = IRPosition::argument(*UniqueRVArg);
Johannes Doerferteccdf082019-08-05 23:35:12 +0000805 Changed = IRAttribute::manifest(A) | Changed;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000806 }
807
808 return Changed;
809}
810
811const std::string AAReturnedValuesImpl::getAsStr() const {
812 return (isAtFixpoint() ? "returns(#" : "may-return(#") +
Johannes Doerfert6471bb62019-08-04 18:39:28 +0000813 (isValidState() ? std::to_string(getNumReturnValues()) : "?") +
Johannes Doerfertdef99282019-08-14 21:29:37 +0000814 ")[#UC: " + std::to_string(UnresolvedCalls.size()) + "]";
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000815}
816
Johannes Doerfert14a04932019-08-07 22:27:24 +0000817Optional<Value *>
818AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const {
819 // If checkForAllReturnedValues provides a unique value, ignoring potential
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000820 // undef values that can also be present, it is assumed to be the actual
821 // return value and forwarded to the caller of this method. If there are
822 // multiple, a nullptr is returned indicating there cannot be a unique
823 // returned value.
824 Optional<Value *> UniqueRV;
825
Johannes Doerfert14a04932019-08-07 22:27:24 +0000826 auto Pred = [&](Value &RV) -> bool {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000827 // If we found a second returned value and neither the current nor the saved
828 // one is an undef, there is no unique returned value. Undefs are special
829 // since we can pretend they have any value.
830 if (UniqueRV.hasValue() && UniqueRV != &RV &&
831 !(isa<UndefValue>(RV) || isa<UndefValue>(UniqueRV.getValue()))) {
832 UniqueRV = nullptr;
833 return false;
834 }
835
836 // Do not overwrite a value with an undef.
837 if (!UniqueRV.hasValue() || !isa<UndefValue>(RV))
838 UniqueRV = &RV;
839
840 return true;
841 };
842
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000843 if (!A.checkForAllReturnedValues(Pred, *this))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000844 UniqueRV = nullptr;
845
846 return UniqueRV;
847}
848
Johannes Doerfert14a04932019-08-07 22:27:24 +0000849bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
850 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
851 &Pred) const {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000852 if (!isValidState())
853 return false;
854
855 // Check all returned values but ignore call sites as long as we have not
856 // encountered an overdefined one during an update.
857 for (auto &It : ReturnedValues) {
858 Value *RV = It.first;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000859 const SmallPtrSetImpl<ReturnInst *> &RetInsts = It.second;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000860
Johannes Doerfertdef99282019-08-14 21:29:37 +0000861 CallBase *CB = dyn_cast<CallBase>(RV);
862 if (CB && !UnresolvedCalls.count(CB))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000863 continue;
864
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000865 if (!Pred(*RV, RetInsts))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000866 return false;
867 }
868
869 return true;
870}
871
Johannes Doerfertece81902019-08-12 22:05:53 +0000872ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000873 size_t NumUnresolvedCalls = UnresolvedCalls.size();
874 bool Changed = false;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000875
Johannes Doerfertdef99282019-08-14 21:29:37 +0000876 // State used in the value traversals starting in returned values.
877 struct RVState {
878 // The map in which we collect return values -> return instrs.
879 decltype(ReturnedValues) &RetValsMap;
880 // The flag to indicate a change.
Johannes Doerfert056f1b52019-08-19 19:14:10 +0000881 bool &Changed;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000882 // The return instrs we come from.
883 SmallPtrSet<ReturnInst *, 2> RetInsts;
884 };
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000885
Johannes Doerfertdef99282019-08-14 21:29:37 +0000886 // Callback for a leaf value returned by the associated function.
887 auto VisitValueCB = [](Value &Val, RVState &RVS, bool) {
888 auto Size = RVS.RetValsMap[&Val].size();
889 RVS.RetValsMap[&Val].insert(RVS.RetInsts.begin(), RVS.RetInsts.end());
890 bool Inserted = RVS.RetValsMap[&Val].size() != Size;
891 RVS.Changed |= Inserted;
892 LLVM_DEBUG({
893 if (Inserted)
894 dbgs() << "[AAReturnedValues] 1 Add new returned value " << Val
895 << " => " << RVS.RetInsts.size() << "\n";
896 });
897 };
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000898
Johannes Doerfertdef99282019-08-14 21:29:37 +0000899 // Helper method to invoke the generic value traversal.
900 auto VisitReturnedValue = [&](Value &RV, RVState &RVS) {
901 IRPosition RetValPos = IRPosition::value(RV);
902 return genericValueTraversal<AAReturnedValues, RVState>(A, RetValPos, *this,
903 RVS, VisitValueCB);
904 };
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000905
Johannes Doerfertdef99282019-08-14 21:29:37 +0000906 // Callback for all "return intructions" live in the associated function.
907 auto CheckReturnInst = [this, &VisitReturnedValue, &Changed](Instruction &I) {
908 ReturnInst &Ret = cast<ReturnInst>(I);
Johannes Doerfert056f1b52019-08-19 19:14:10 +0000909 RVState RVS({ReturnedValues, Changed, {}});
Johannes Doerfertdef99282019-08-14 21:29:37 +0000910 RVS.RetInsts.insert(&Ret);
Johannes Doerfertdef99282019-08-14 21:29:37 +0000911 return VisitReturnedValue(*Ret.getReturnValue(), RVS);
912 };
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000913
Johannes Doerfertdef99282019-08-14 21:29:37 +0000914 // Start by discovering returned values from all live returned instructions in
915 // the associated function.
916 if (!A.checkForAllInstructions(CheckReturnInst, *this, {Instruction::Ret}))
917 return indicatePessimisticFixpoint();
918
919 // Once returned values "directly" present in the code are handled we try to
920 // resolve returned calls.
921 decltype(ReturnedValues) NewRVsMap;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000922 for (auto &It : ReturnedValues) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000923 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned value: " << *It.first
924 << " by #" << It.second.size() << " RIs\n");
925 CallBase *CB = dyn_cast<CallBase>(It.first);
926 if (!CB || UnresolvedCalls.count(CB))
927 continue;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000928
Johannes Doerfertdef99282019-08-14 21:29:37 +0000929 const auto *RetValAAPtr =
930 A.getAAFor<AAReturnedValues>(*this, IRPosition::callsite_function(*CB));
931
932 // Skip dead ends, thus if we do not know anything about the returned
933 // call we mark it as unresolved and it will stay that way.
934 if (!RetValAAPtr || !RetValAAPtr->getState().isValidState()) {
935 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Unresolved call: " << *CB
936 << "\n");
937 UnresolvedCalls.insert(CB);
938 continue;
939 }
940
941 const auto &RetValAA = *RetValAAPtr;
942 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Found another AAReturnedValues: "
943 << static_cast<const AbstractAttribute &>(RetValAA)
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000944 << "\n");
945
David L. Jonesb1752f62019-08-19 07:16:24 +0000946 // If we know something but not everyting about the returned values, keep
947 // track of that too. Hence, remember transitively unresolved calls.
948 UnresolvedCalls.insert(RetValAA.getUnresolvedCalls().begin(),
949 RetValAA.getUnresolvedCalls().end());
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000950
David L. Jonesb1752f62019-08-19 07:16:24 +0000951 // Now track transitively returned values.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000952 for (auto &RetValAAIt : RetValAA.returned_values()) {
953 Value *RetVal = RetValAAIt.first;
954 if (Argument *Arg = dyn_cast<Argument>(RetVal)) {
955 // Arguments are mapped to call site operands and we begin the traversal
956 // again.
Johannes Doerfert056f1b52019-08-19 19:14:10 +0000957 bool Unused = false;
958 RVState RVS({NewRVsMap, Unused, RetValAAIt.second});
Johannes Doerfertdef99282019-08-14 21:29:37 +0000959 VisitReturnedValue(*CB->getArgOperand(Arg->getArgNo()), RVS);
960 continue;
961 } else if (isa<CallBase>(RetVal)) {
962 // Call sites are resolved by the callee attribute over time, no need to
963 // do anything for us.
964 continue;
965 } else if (isa<Constant>(RetVal)) {
966 // Constants are valid everywhere, we can simply take them.
967 NewRVsMap[RetVal].insert(It.second.begin(), It.second.end());
968 continue;
969 }
David L. Jonesb1752f62019-08-19 07:16:24 +0000970 // Anything that did not fit in the above categories cannot be resolved,
971 // mark the call as unresolved.
972 LLVM_DEBUG(dbgs() << "[AAReturnedValues] transitively returned value "
973 "cannot be translated: "
974 << *RetVal << "\n");
975 UnresolvedCalls.insert(CB);
Johannes Doerfert4361da22019-08-04 18:38:53 +0000976 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000977 }
978
Johannes Doerfertdef99282019-08-14 21:29:37 +0000979 // To avoid modifications to the ReturnedValues map while we iterate over it
980 // we kept record of potential new entries in a copy map, NewRVsMap.
981 for (auto &It : NewRVsMap) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000982 assert(!It.second.empty() && "Entry does not add anything.");
983 auto &ReturnInsts = ReturnedValues[It.first];
984 for (ReturnInst *RI : It.second)
985 if (ReturnInsts.insert(RI).second) {
986 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Add new returned value "
987 << *It.first << " => " << *RI << "\n");
Johannes Doerfertdef99282019-08-14 21:29:37 +0000988 Changed = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000989 }
990 }
991
Johannes Doerfertdef99282019-08-14 21:29:37 +0000992 Changed |= (NumUnresolvedCalls != UnresolvedCalls.size());
993 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000994}
995
Johannes Doerfertdef99282019-08-14 21:29:37 +0000996struct AAReturnedValuesFunction final : public AAReturnedValuesImpl {
997 AAReturnedValuesFunction(const IRPosition &IRP) : AAReturnedValuesImpl(IRP) {}
998
999 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001000 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(returned) }
Johannes Doerfertdef99282019-08-14 21:29:37 +00001001};
1002
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001003/// Returned values information for a call sites.
1004using AAReturnedValuesCallSite = AAReturnedValuesFunction;
1005
Stefan Stipanovic06263672019-07-11 21:37:40 +00001006/// ------------------------ NoSync Function Attribute -------------------------
1007
Johannes Doerfert344d0382019-08-07 22:34:26 +00001008struct AANoSyncImpl : AANoSync {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001009 AANoSyncImpl(const IRPosition &IRP) : AANoSync(IRP) {}
Stefan Stipanovic06263672019-07-11 21:37:40 +00001010
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001011 /// See AbstractAttribute::initialize(...).
1012 void initialize(Attributor &A) override {
1013 if (hasAttr({Attribute::NoSync}))
1014 indicateOptimisticFixpoint();
1015 }
1016
Stefan Stipanoviccb5ecae2019-07-12 18:34:06 +00001017 const std::string getAsStr() const override {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001018 return getAssumed() ? "nosync" : "may-sync";
1019 }
1020
1021 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001022 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001023
Stefan Stipanovic06263672019-07-11 21:37:40 +00001024 /// Helper function used to determine whether an instruction is non-relaxed
1025 /// atomic. In other words, if an atomic instruction does not have unordered
1026 /// or monotonic ordering
1027 static bool isNonRelaxedAtomic(Instruction *I);
1028
1029 /// Helper function used to determine whether an instruction is volatile.
1030 static bool isVolatile(Instruction *I);
1031
Johannes Doerfertc7a1db32019-07-13 01:09:27 +00001032 /// Helper function uset to check if intrinsic is volatile (memcpy, memmove,
1033 /// memset).
Stefan Stipanovic06263672019-07-11 21:37:40 +00001034 static bool isNoSyncIntrinsic(Instruction *I);
1035};
1036
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001037bool AANoSyncImpl::isNonRelaxedAtomic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001038 if (!I->isAtomic())
1039 return false;
1040
1041 AtomicOrdering Ordering;
1042 switch (I->getOpcode()) {
1043 case Instruction::AtomicRMW:
1044 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
1045 break;
1046 case Instruction::Store:
1047 Ordering = cast<StoreInst>(I)->getOrdering();
1048 break;
1049 case Instruction::Load:
1050 Ordering = cast<LoadInst>(I)->getOrdering();
1051 break;
1052 case Instruction::Fence: {
1053 auto *FI = cast<FenceInst>(I);
1054 if (FI->getSyncScopeID() == SyncScope::SingleThread)
1055 return false;
1056 Ordering = FI->getOrdering();
1057 break;
1058 }
1059 case Instruction::AtomicCmpXchg: {
1060 AtomicOrdering Success = cast<AtomicCmpXchgInst>(I)->getSuccessOrdering();
1061 AtomicOrdering Failure = cast<AtomicCmpXchgInst>(I)->getFailureOrdering();
1062 // Only if both are relaxed, than it can be treated as relaxed.
1063 // Otherwise it is non-relaxed.
1064 if (Success != AtomicOrdering::Unordered &&
1065 Success != AtomicOrdering::Monotonic)
1066 return true;
1067 if (Failure != AtomicOrdering::Unordered &&
1068 Failure != AtomicOrdering::Monotonic)
1069 return true;
1070 return false;
1071 }
1072 default:
1073 llvm_unreachable(
1074 "New atomic operations need to be known in the attributor.");
1075 }
1076
1077 // Relaxed.
1078 if (Ordering == AtomicOrdering::Unordered ||
1079 Ordering == AtomicOrdering::Monotonic)
1080 return false;
1081 return true;
1082}
1083
1084/// Checks if an intrinsic is nosync. Currently only checks mem* intrinsics.
1085/// FIXME: We should ipmrove the handling of intrinsics.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001086bool AANoSyncImpl::isNoSyncIntrinsic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001087 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
1088 switch (II->getIntrinsicID()) {
1089 /// Element wise atomic memory intrinsics are can only be unordered,
1090 /// therefore nosync.
1091 case Intrinsic::memset_element_unordered_atomic:
1092 case Intrinsic::memmove_element_unordered_atomic:
1093 case Intrinsic::memcpy_element_unordered_atomic:
1094 return true;
1095 case Intrinsic::memset:
1096 case Intrinsic::memmove:
1097 case Intrinsic::memcpy:
1098 if (!cast<MemIntrinsic>(II)->isVolatile())
1099 return true;
1100 return false;
1101 default:
1102 return false;
1103 }
1104 }
1105 return false;
1106}
1107
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001108bool AANoSyncImpl::isVolatile(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001109 assert(!ImmutableCallSite(I) && !isa<CallBase>(I) &&
1110 "Calls should not be checked here");
1111
1112 switch (I->getOpcode()) {
1113 case Instruction::AtomicRMW:
1114 return cast<AtomicRMWInst>(I)->isVolatile();
1115 case Instruction::Store:
1116 return cast<StoreInst>(I)->isVolatile();
1117 case Instruction::Load:
1118 return cast<LoadInst>(I)->isVolatile();
1119 case Instruction::AtomicCmpXchg:
1120 return cast<AtomicCmpXchgInst>(I)->isVolatile();
1121 default:
1122 return false;
1123 }
1124}
1125
Johannes Doerfertece81902019-08-12 22:05:53 +00001126ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001127
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001128 auto CheckRWInstForNoSync = [&](Instruction &I) {
1129 /// We are looking for volatile instructions or Non-Relaxed atomics.
1130 /// FIXME: We should ipmrove the handling of intrinsics.
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001131
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001132 if (isa<IntrinsicInst>(&I) && isNoSyncIntrinsic(&I))
1133 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001134
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001135 if (ImmutableCallSite ICS = ImmutableCallSite(&I)) {
1136 if (ICS.hasFnAttr(Attribute::NoSync))
1137 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001138
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001139 auto *NoSyncAA =
1140 A.getAAFor<AANoSyncImpl>(*this, IRPosition::callsite_function(ICS));
1141 if (NoSyncAA && NoSyncAA->isAssumedNoSync())
1142 return true;
1143 return false;
1144 }
Stefan Stipanovic06263672019-07-11 21:37:40 +00001145
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001146 if (!isVolatile(&I) && !isNonRelaxedAtomic(&I))
1147 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001148
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001149 return false;
1150 };
Stefan Stipanovic06263672019-07-11 21:37:40 +00001151
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001152 auto CheckForNoSync = [&](Instruction &I) {
1153 // At this point we handled all read/write effects and they are all
1154 // nosync, so they can be skipped.
1155 if (I.mayReadOrWriteMemory())
1156 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001157
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001158 // non-convergent and readnone imply nosync.
1159 return !ImmutableCallSite(&I).isConvergent();
1160 };
Stefan Stipanovic06263672019-07-11 21:37:40 +00001161
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001162 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this) ||
1163 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001164 return indicatePessimisticFixpoint();
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001165
Stefan Stipanovic06263672019-07-11 21:37:40 +00001166 return ChangeStatus::UNCHANGED;
1167}
1168
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001169struct AANoSyncFunction final : public AANoSyncImpl {
1170 AANoSyncFunction(const IRPosition &IRP) : AANoSyncImpl(IRP) {}
1171
1172 /// See AbstractAttribute::trackStatistics()
1173 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }
1174};
1175
1176/// NoSync attribute deduction for a call sites.
1177using AANoSyncCallSite = AANoSyncFunction;
1178
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001179/// ------------------------ No-Free Attributes ----------------------------
1180
Johannes Doerfert344d0382019-08-07 22:34:26 +00001181struct AANoFreeImpl : public AANoFree {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001182 AANoFreeImpl(const IRPosition &IRP) : AANoFree(IRP) {}
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001183
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001184 /// See AbstractAttribute::initialize(...).
1185 void initialize(Attributor &A) override {
1186 if (hasAttr({Attribute::NoFree}))
1187 indicateOptimisticFixpoint();
1188 }
1189
1190 /// See AbstractAttribute::updateImpl(...).
1191 ChangeStatus updateImpl(Attributor &A) override {
1192 auto CheckForNoFree = [&](Instruction &I) {
1193 ImmutableCallSite ICS(&I);
1194 if (ICS.hasFnAttr(Attribute::NoFree))
1195 return true;
1196
1197 auto *NoFreeAA =
1198 A.getAAFor<AANoFreeImpl>(*this, IRPosition::callsite_function(ICS));
1199 return NoFreeAA && NoFreeAA->isAssumedNoFree();
1200 };
1201
1202 if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this))
1203 return indicatePessimisticFixpoint();
1204 return ChangeStatus::UNCHANGED;
1205 }
1206
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001207 /// See AbstractAttribute::getAsStr().
1208 const std::string getAsStr() const override {
1209 return getAssumed() ? "nofree" : "may-free";
1210 }
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001211};
1212
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001213struct AANoFreeFunction final : public AANoFreeImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001214 AANoFreeFunction(const IRPosition &IRP) : AANoFreeImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001215
1216 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001217 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001218};
1219
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001220/// NoFree attribute deduction for a call sites.
1221using AANoFreeCallSite = AANoFreeFunction;
1222
Hideto Ueno54869ec2019-07-15 06:49:04 +00001223/// ------------------------ NonNull Argument Attribute ------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00001224struct AANonNullImpl : AANonNull {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001225 AANonNullImpl(const IRPosition &IRP) : AANonNull(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001226
Hideto Ueno54869ec2019-07-15 06:49:04 +00001227 /// See AbstractAttribute::getAsStr().
1228 const std::string getAsStr() const override {
1229 return getAssumed() ? "nonnull" : "may-null";
1230 }
1231
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001232 /// See AbstractAttribute::initialize(...).
1233 void initialize(Attributor &A) override {
1234 if (hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
1235 indicateOptimisticFixpoint();
1236 }
1237
Hideto Ueno54869ec2019-07-15 06:49:04 +00001238 /// Generate a predicate that checks if a given value is assumed nonnull.
1239 /// The generated function returns true if a value satisfies any of
1240 /// following conditions.
1241 /// (i) A value is known nonZero(=nonnull).
1242 /// (ii) A value is associated with AANonNull and its isAssumedNonNull() is
1243 /// true.
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001244 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
1245 generatePredicate(Attributor &);
Hideto Ueno54869ec2019-07-15 06:49:04 +00001246};
1247
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001248std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
1249AANonNullImpl::generatePredicate(Attributor &A) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001250 // FIXME: The `AAReturnedValues` should provide the predicate with the
1251 // `ReturnInst` vector as well such that we can use the control flow sensitive
1252 // version of `isKnownNonZero`. This should fix `test11` in
1253 // `test/Transforms/FunctionAttrs/nonnull.ll`
1254
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001255 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
1256 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &RetInsts) -> bool {
Johannes Doerfert26e58462019-08-12 22:21:09 +00001257 if (isKnownNonZero(&RV, A.getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001258 return true;
1259
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001260 if (ImmutableCallSite ICS = ImmutableCallSite(&RV))
1261 if (ICS.hasRetAttr(Attribute::NonNull))
1262 return true;
Hideto Ueno54869ec2019-07-15 06:49:04 +00001263
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001264 auto *NonNullAA = A.getAAFor<AANonNull>(*this, IRPosition::value(RV));
1265 return (NonNullAA && NonNullAA->isAssumedNonNull());
Hideto Ueno54869ec2019-07-15 06:49:04 +00001266 };
1267
1268 return Pred;
1269}
1270
1271/// NonNull attribute for function return value.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001272struct AANonNullReturned final : AANonNullImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001273 AANonNullReturned(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001274
1275 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001276 ChangeStatus updateImpl(Attributor &A) override {
1277 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
1278 this->generatePredicate(A);
1279
1280 if (!A.checkForAllReturnedValuesAndReturnInsts(Pred, *this))
1281 return indicatePessimisticFixpoint();
1282 return ChangeStatus::UNCHANGED;
1283 }
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001284
1285 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001286 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001287};
1288
Hideto Ueno54869ec2019-07-15 06:49:04 +00001289/// NonNull attribute for function argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001290struct AANonNullArgument final : AANonNullImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001291 AANonNullArgument(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001292
1293 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001294 ChangeStatus updateImpl(Attributor &A) override {
1295 unsigned ArgNo = getArgNo();
1296
1297 // Callback function
1298 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) {
1299 assert(CS && "Sanity check: Call site was not initialized properly!");
1300
1301 IRPosition CSArgPos = IRPosition::callsite_argument(CS, ArgNo);
1302 if (CSArgPos.hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
1303 return true;
1304
1305 // Check that NonNullAA is AANonNullCallSiteArgument.
1306 if (auto *NonNullAA = A.getAAFor<AANonNullImpl>(*this, CSArgPos)) {
1307 ImmutableCallSite ICS(&NonNullAA->getAnchorValue());
1308 if (ICS && CS.getInstruction() == ICS.getInstruction())
1309 return NonNullAA->isAssumedNonNull();
1310 return false;
1311 }
1312
1313 Value *V = CS.getArgOperand(ArgNo);
1314 if (isKnownNonZero(V, A.getDataLayout()))
1315 return true;
1316
1317 return false;
1318 };
1319 if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
1320 return indicatePessimisticFixpoint();
1321 return ChangeStatus::UNCHANGED;
1322 }
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001323
1324 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001325 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001326};
1327
1328/// NonNull attribute for a call site argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001329struct AANonNullCallSiteArgument final : AANonNullImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001330 AANonNullCallSiteArgument(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001331
1332 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001333 void initialize(Attributor &A) override {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001334 AANonNullImpl::initialize(A);
1335 if (!isKnownNonNull() &&
1336 isKnownNonZero(&getAssociatedValue(), A.getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001337 indicateOptimisticFixpoint();
1338 }
1339
1340 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001341 ChangeStatus updateImpl(Attributor &A) override {
1342 // NOTE: Never look at the argument of the callee in this method.
1343 // If we do this, "nonnull" is always deduced because of the
1344 // assumption.
1345
1346 Value &V = getAssociatedValue();
1347 auto *NonNullAA = A.getAAFor<AANonNull>(*this, IRPosition::value(V));
1348
1349 if (!NonNullAA || !NonNullAA->isAssumedNonNull())
1350 return indicatePessimisticFixpoint();
1351
1352 return ChangeStatus::UNCHANGED;
1353 }
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001354
1355 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001356 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001357};
Johannes Doerfert007153e2019-08-05 23:26:06 +00001358
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001359/// NonNull attribute deduction for a call sites.
1360using AANonNullCallSiteReturned = AANonNullReturned;
1361
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001362/// ------------------------ No-Recurse Attributes ----------------------------
1363
1364struct AANoRecurseImpl : public AANoRecurse {
1365 AANoRecurseImpl(const IRPosition &IRP) : AANoRecurse(IRP) {}
1366
1367 /// See AbstractAttribute::initialize(...).
1368 void initialize(Attributor &A) override {
1369 if (hasAttr({getAttrKind()})) {
1370 indicateOptimisticFixpoint();
1371 return;
1372 }
1373 }
1374
1375 /// See AbstractAttribute::getAsStr()
1376 const std::string getAsStr() const override {
1377 return getAssumed() ? "norecurse" : "may-recurse";
1378 }
1379};
1380
1381struct AANoRecurseFunction final : AANoRecurseImpl {
1382 AANoRecurseFunction(const IRPosition &IRP) : AANoRecurseImpl(IRP) {}
1383
1384 /// See AbstractAttribute::updateImpl(...).
1385 ChangeStatus updateImpl(Attributor &A) override {
1386 // TODO: Implement this.
1387 return indicatePessimisticFixpoint();
1388 }
1389
1390 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
1391};
1392
1393using AANoRecurseCallSite = AANoRecurseFunction;
1394
Hideto Ueno11d37102019-07-17 15:15:43 +00001395/// ------------------------ Will-Return Attributes ----------------------------
1396
Hideto Ueno11d37102019-07-17 15:15:43 +00001397// Helper function that checks whether a function has any cycle.
1398// TODO: Replace with more efficent code
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001399static bool containsCycle(Function &F) {
Hideto Ueno11d37102019-07-17 15:15:43 +00001400 SmallPtrSet<BasicBlock *, 32> Visited;
1401
1402 // Traverse BB by dfs and check whether successor is already visited.
1403 for (BasicBlock *BB : depth_first(&F)) {
1404 Visited.insert(BB);
1405 for (auto *SuccBB : successors(BB)) {
1406 if (Visited.count(SuccBB))
1407 return true;
1408 }
1409 }
1410 return false;
1411}
1412
1413// Helper function that checks the function have a loop which might become an
1414// endless loop
1415// FIXME: Any cycle is regarded as endless loop for now.
1416// We have to allow some patterns.
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001417static bool containsPossiblyEndlessLoop(Function *F) {
1418 return !F || !F->hasExactDefinition() || containsCycle(*F);
Hideto Ueno11d37102019-07-17 15:15:43 +00001419}
1420
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001421struct AAWillReturnImpl : public AAWillReturn {
1422 AAWillReturnImpl(const IRPosition &IRP) : AAWillReturn(IRP) {}
Hideto Ueno11d37102019-07-17 15:15:43 +00001423
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001424 /// See AbstractAttribute::initialize(...).
1425 void initialize(Attributor &A) override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001426 if (hasAttr({Attribute::WillReturn})) {
1427 indicateOptimisticFixpoint();
1428 return;
1429 }
Hideto Ueno11d37102019-07-17 15:15:43 +00001430
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001431 Function *F = getAssociatedFunction();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001432 if (containsPossiblyEndlessLoop(F))
1433 indicatePessimisticFixpoint();
1434 }
Hideto Ueno11d37102019-07-17 15:15:43 +00001435
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001436 /// See AbstractAttribute::updateImpl(...).
1437 ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001438 auto CheckForWillReturn = [&](Instruction &I) {
1439 ImmutableCallSite ICS(&I);
1440 if (ICS.hasFnAttr(Attribute::WillReturn))
1441 return true;
1442
1443 IRPosition IPos = IRPosition::callsite_function(ICS);
1444 auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, IPos);
1445 if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn())
1446 return false;
1447
1448 // FIXME: Prohibit any recursion for now.
1449 if (ICS.hasFnAttr(Attribute::NoRecurse))
1450 return true;
1451
1452 auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, IPos);
1453 return NoRecurseAA && NoRecurseAA->isAssumedNoRecurse();
1454 };
1455
1456 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this))
1457 return indicatePessimisticFixpoint();
1458
1459 return ChangeStatus::UNCHANGED;
1460 }
1461
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001462 /// See AbstractAttribute::getAsStr()
1463 const std::string getAsStr() const override {
1464 return getAssumed() ? "willreturn" : "may-noreturn";
1465 }
1466};
1467
1468struct AAWillReturnFunction final : AAWillReturnImpl {
1469 AAWillReturnFunction(const IRPosition &IRP) : AAWillReturnImpl(IRP) {}
1470
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001471 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001472 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) }
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001473};
Hideto Ueno11d37102019-07-17 15:15:43 +00001474
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001475/// WillReturn attribute deduction for a call sites.
1476using AAWillReturnCallSite = AAWillReturnFunction;
1477
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001478/// ------------------------ NoAlias Argument Attribute ------------------------
1479
Johannes Doerfert344d0382019-08-07 22:34:26 +00001480struct AANoAliasImpl : AANoAlias {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001481 AANoAliasImpl(const IRPosition &IRP) : AANoAlias(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001482
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001483 /// See AbstractAttribute::initialize(...).
1484 void initialize(Attributor &A) override {
1485 if (hasAttr({Attribute::NoAlias}))
1486 indicateOptimisticFixpoint();
1487 }
1488
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001489 const std::string getAsStr() const override {
1490 return getAssumed() ? "noalias" : "may-alias";
1491 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001492};
1493
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001494/// NoAlias attribute for a floating value.
1495struct AANoAliasFloating final : AANoAliasImpl {
1496 AANoAliasFloating(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
1497
1498 /// See AbstractAttribute::updateImpl(...).
1499 ChangeStatus updateImpl(Attributor &A) override {
1500 // TODO: Implement this.
1501 return indicatePessimisticFixpoint();
1502 }
1503
1504 /// See AbstractAttribute::trackStatistics()
1505 void trackStatistics() const override {
1506 STATS_DECLTRACK_FLOATING_ATTR(noalias)
1507 }
1508};
1509
1510/// NoAlias attribute for an argument.
1511struct AANoAliasArgument final : AANoAliasImpl {
1512 AANoAliasArgument(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
1513
1514 /// See AbstractAttribute::updateImpl(...).
1515 ChangeStatus updateImpl(Attributor &A) override {
1516 // TODO: Implement this.
1517 return indicatePessimisticFixpoint();
1518 }
1519
1520 /// See AbstractAttribute::trackStatistics()
1521 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
1522};
1523
1524struct AANoAliasCallSiteArgument final : AANoAliasImpl {
1525 AANoAliasCallSiteArgument(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
1526
1527 /// See AbstractAttribute::updateImpl(...).
1528 ChangeStatus updateImpl(Attributor &A) override {
1529 // TODO: Implement this.
1530 return indicatePessimisticFixpoint();
1531 }
1532
1533 /// See AbstractAttribute::trackStatistics()
1534 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
1535};
1536
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001537/// NoAlias attribute for function return value.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001538struct AANoAliasReturned final : AANoAliasImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001539 AANoAliasReturned(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001540
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001541 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001542 virtual ChangeStatus updateImpl(Attributor &A) override {
1543
1544 auto CheckReturnValue = [&](Value &RV) -> bool {
1545 if (Constant *C = dyn_cast<Constant>(&RV))
1546 if (C->isNullValue() || isa<UndefValue>(C))
1547 return true;
1548
1549 /// For now, we can only deduce noalias if we have call sites.
1550 /// FIXME: add more support.
1551 ImmutableCallSite ICS(&RV);
1552 if (!ICS)
1553 return false;
1554
1555 if (!ICS.returnDoesNotAlias()) {
1556 auto *NoAliasAA =
1557 A.getAAFor<AANoAlias>(*this, IRPosition::callsite_returned(ICS));
1558 if (!NoAliasAA || !NoAliasAA->isAssumedNoAlias())
1559 return false;
1560 }
1561
1562 /// FIXME: We can improve capture check in two ways:
1563 /// 1. Use the AANoCapture facilities.
1564 /// 2. Use the location of return insts for escape queries.
1565 if (PointerMayBeCaptured(&RV, /* ReturnCaptures */ false,
1566 /* StoreCaptures */ true))
1567 return false;
1568
1569 return true;
1570 };
1571
1572 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
1573 return indicatePessimisticFixpoint();
1574
1575 return ChangeStatus::UNCHANGED;
1576 }
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001577
1578 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001579 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001580};
1581
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001582/// NoAlias attribute deduction for a call site return value.
1583using AANoAliasCallSiteReturned = AANoAliasReturned;
1584
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001585/// -------------------AAIsDead Function Attribute-----------------------
1586
Johannes Doerfert344d0382019-08-07 22:34:26 +00001587struct AAIsDeadImpl : public AAIsDead {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001588 AAIsDeadImpl(const IRPosition &IRP) : AAIsDead(IRP) {}
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001589
Johannes Doerfertece81902019-08-12 22:05:53 +00001590 void initialize(Attributor &A) override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001591 const Function *F = getAssociatedFunction();
1592 if (!F || !F->hasExactDefinition()) {
1593 indicatePessimisticFixpoint();
1594 return;
1595 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001596
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001597 ToBeExploredPaths.insert(&(F->getEntryBlock().front()));
1598 AssumedLiveBlocks.insert(&(F->getEntryBlock()));
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001599 for (size_t i = 0; i < ToBeExploredPaths.size(); ++i)
Johannes Doerfert4361da22019-08-04 18:38:53 +00001600 if (const Instruction *NextNoReturnI =
1601 findNextNoReturn(A, ToBeExploredPaths[i]))
1602 NoReturnCalls.insert(NextNoReturnI);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001603 }
1604
Johannes Doerfert4361da22019-08-04 18:38:53 +00001605 /// Find the next assumed noreturn instruction in the block of \p I starting
1606 /// from, thus including, \p I.
1607 ///
1608 /// The caller is responsible to monitor the ToBeExploredPaths set as new
1609 /// instructions discovered in other basic block will be placed in there.
1610 ///
1611 /// \returns The next assumed noreturn instructions in the block of \p I
1612 /// starting from, thus including, \p I.
1613 const Instruction *findNextNoReturn(Attributor &A, const Instruction *I);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001614
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001615 /// See AbstractAttribute::getAsStr().
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001616 const std::string getAsStr() const override {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001617 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001618 std::to_string(getAssociatedFunction()->size()) + "][#NRI " +
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001619 std::to_string(NoReturnCalls.size()) + "]";
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001620 }
1621
1622 /// See AbstractAttribute::manifest(...).
1623 ChangeStatus manifest(Attributor &A) override {
1624 assert(getState().isValidState() &&
1625 "Attempted to manifest an invalid state!");
1626
1627 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Johannes Doerfertdef99282019-08-14 21:29:37 +00001628 const Function &F = *getAssociatedFunction();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001629
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001630 // Flag to determine if we can change an invoke to a call assuming the
1631 // callee is nounwind. This is not possible if the personality of the
1632 // function allows to catch asynchronous exceptions.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001633 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001634
Johannes Doerfert4361da22019-08-04 18:38:53 +00001635 for (const Instruction *NRC : NoReturnCalls) {
1636 Instruction *I = const_cast<Instruction *>(NRC);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001637 BasicBlock *BB = I->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001638 Instruction *SplitPos = I->getNextNode();
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001639
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001640 if (auto *II = dyn_cast<InvokeInst>(I)) {
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001641 // If we keep the invoke the split position is at the beginning of the
1642 // normal desitination block (it invokes a noreturn function after all).
1643 BasicBlock *NormalDestBB = II->getNormalDest();
1644 SplitPos = &NormalDestBB->front();
1645
Johannes Doerfert4361da22019-08-04 18:38:53 +00001646 /// Invoke is replaced with a call and unreachable is placed after it if
1647 /// the callee is nounwind and noreturn. Otherwise, we keep the invoke
1648 /// and only place an unreachable in the normal successor.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001649 if (Invoke2CallAllowed) {
1650 if (Function *Callee = II->getCalledFunction()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001651 auto *AANoUnw =
1652 A.getAAFor<AANoUnwind>(*this, IRPosition::function(*Callee));
Johannes Doerfert924d2132019-08-05 21:34:45 +00001653 if (Callee->hasFnAttribute(Attribute::NoUnwind) ||
1654 (AANoUnw && AANoUnw->isAssumedNoUnwind())) {
1655 LLVM_DEBUG(dbgs()
1656 << "[AAIsDead] Replace invoke with call inst\n");
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001657 // We do not need an invoke (II) but instead want a call followed
1658 // by an unreachable. However, we do not remove II as other
1659 // abstract attributes might have it cached as part of their
1660 // results. Given that we modify the CFG anyway, we simply keep II
1661 // around but in a new dead block. To avoid II being live through
1662 // a different edge we have to ensure the block we place it in is
1663 // only reached from the current block of II and then not reached
1664 // at all when we insert the unreachable.
1665 SplitBlockPredecessors(NormalDestBB, {BB}, ".i2c");
1666 CallInst *CI = createCallMatchingInvoke(II);
1667 CI->insertBefore(II);
1668 CI->takeName(II);
1669 II->replaceAllUsesWith(CI);
1670 SplitPos = CI->getNextNode();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001671 }
Johannes Doerfert4361da22019-08-04 18:38:53 +00001672 }
1673 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001674 }
1675
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001676 BB = SplitPos->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001677 SplitBlock(BB, SplitPos);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001678 changeToUnreachable(BB->getTerminator(), /* UseLLVMTrap */ false);
1679 HasChanged = ChangeStatus::CHANGED;
1680 }
1681
1682 return HasChanged;
1683 }
1684
1685 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001686 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001687
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001688 /// See AAIsDead::isAssumedDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001689 bool isAssumedDead(const BasicBlock *BB) const override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001690 assert(BB->getParent() == getAssociatedFunction() &&
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001691 "BB must be in the same anchor scope function.");
1692
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001693 if (!getAssumed())
1694 return false;
1695 return !AssumedLiveBlocks.count(BB);
1696 }
1697
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001698 /// See AAIsDead::isKnownDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001699 bool isKnownDead(const BasicBlock *BB) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001700 return getKnown() && isAssumedDead(BB);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001701 }
1702
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001703 /// See AAIsDead::isAssumed(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001704 bool isAssumedDead(const Instruction *I) const override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001705 assert(I->getParent()->getParent() == getAssociatedFunction() &&
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001706 "Instruction must be in the same anchor scope function.");
1707
Stefan Stipanovic7849e412019-08-03 15:27:41 +00001708 if (!getAssumed())
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001709 return false;
1710
1711 // If it is not in AssumedLiveBlocks then it for sure dead.
1712 // Otherwise, it can still be after noreturn call in a live block.
1713 if (!AssumedLiveBlocks.count(I->getParent()))
1714 return true;
1715
1716 // If it is not after a noreturn call, than it is live.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001717 return isAfterNoReturn(I);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001718 }
1719
1720 /// See AAIsDead::isKnownDead(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001721 bool isKnownDead(const Instruction *I) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001722 return getKnown() && isAssumedDead(I);
1723 }
1724
1725 /// Check if instruction is after noreturn call, in other words, assumed dead.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001726 bool isAfterNoReturn(const Instruction *I) const;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001727
Johannes Doerfert924d2132019-08-05 21:34:45 +00001728 /// Determine if \p F might catch asynchronous exceptions.
1729 static bool mayCatchAsynchronousExceptions(const Function &F) {
1730 return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F);
1731 }
1732
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001733 /// Collection of to be explored paths.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001734 SmallSetVector<const Instruction *, 8> ToBeExploredPaths;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001735
1736 /// Collection of all assumed live BasicBlocks.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001737 DenseSet<const BasicBlock *> AssumedLiveBlocks;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001738
1739 /// Collection of calls with noreturn attribute, assumed or knwon.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001740 SmallSetVector<const Instruction *, 4> NoReturnCalls;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001741};
1742
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001743struct AAIsDeadFunction final : public AAIsDeadImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001744 AAIsDeadFunction(const IRPosition &IRP) : AAIsDeadImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001745
1746 /// See AbstractAttribute::trackStatistics()
1747 void trackStatistics() const override {
1748 STATS_DECL(DeadBlocks, Function,
1749 "Number of basic blocks classified as dead");
1750 BUILD_STAT_NAME(DeadBlocks, Function) +=
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001751 getAssociatedFunction()->size() - AssumedLiveBlocks.size();
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001752 STATS_DECL(PartiallyDeadBlocks, Function,
1753 "Number of basic blocks classified as partially dead");
1754 BUILD_STAT_NAME(PartiallyDeadBlocks, Function) += NoReturnCalls.size();
1755 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001756};
1757
1758bool AAIsDeadImpl::isAfterNoReturn(const Instruction *I) const {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001759 const Instruction *PrevI = I->getPrevNode();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001760 while (PrevI) {
1761 if (NoReturnCalls.count(PrevI))
1762 return true;
1763 PrevI = PrevI->getPrevNode();
1764 }
1765 return false;
1766}
1767
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001768const Instruction *AAIsDeadImpl::findNextNoReturn(Attributor &A,
1769 const Instruction *I) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001770 const BasicBlock *BB = I->getParent();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001771 const Function &F = *BB->getParent();
1772
1773 // Flag to determine if we can change an invoke to a call assuming the callee
1774 // is nounwind. This is not possible if the personality of the function allows
1775 // to catch asynchronous exceptions.
1776 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001777
1778 // TODO: We should have a function that determines if an "edge" is dead.
1779 // Edges could be from an instruction to the next or from a terminator
1780 // to the successor. For now, we need to special case the unwind block
1781 // of InvokeInst below.
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001782
1783 while (I) {
1784 ImmutableCallSite ICS(I);
1785
1786 if (ICS) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001787 const IRPosition &IPos = IRPosition::callsite_function(ICS);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001788 // Regarless of the no-return property of an invoke instruction we only
1789 // learn that the regular successor is not reachable through this
1790 // instruction but the unwind block might still be.
1791 if (auto *Invoke = dyn_cast<InvokeInst>(I)) {
1792 // Use nounwind to justify the unwind block is dead as well.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001793 auto *AANoUnw = A.getAAFor<AANoUnwind>(*this, IPos);
Johannes Doerfert924d2132019-08-05 21:34:45 +00001794 if (!Invoke2CallAllowed ||
1795 (!AANoUnw || !AANoUnw->isAssumedNoUnwind())) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001796 AssumedLiveBlocks.insert(Invoke->getUnwindDest());
1797 ToBeExploredPaths.insert(&Invoke->getUnwindDest()->front());
1798 }
1799 }
1800
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001801 auto *NoReturnAA = A.getAAFor<AANoReturn>(*this, IPos);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001802 if (ICS.hasFnAttr(Attribute::NoReturn) ||
1803 (NoReturnAA && NoReturnAA->isAssumedNoReturn()))
1804 return I;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001805 }
1806
1807 I = I->getNextNode();
1808 }
1809
1810 // get new paths (reachable blocks).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001811 for (const BasicBlock *SuccBB : successors(BB)) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001812 AssumedLiveBlocks.insert(SuccBB);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001813 ToBeExploredPaths.insert(&SuccBB->front());
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001814 }
1815
Johannes Doerfert4361da22019-08-04 18:38:53 +00001816 // No noreturn instruction found.
1817 return nullptr;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001818}
1819
Johannes Doerfertece81902019-08-12 22:05:53 +00001820ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001821 // Temporary collection to iterate over existing noreturn instructions. This
1822 // will alow easier modification of NoReturnCalls collection
Johannes Doerfert4361da22019-08-04 18:38:53 +00001823 SmallVector<const Instruction *, 8> NoReturnChanged;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001824 ChangeStatus Status = ChangeStatus::UNCHANGED;
1825
Johannes Doerfert4361da22019-08-04 18:38:53 +00001826 for (const Instruction *I : NoReturnCalls)
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001827 NoReturnChanged.push_back(I);
1828
Johannes Doerfert4361da22019-08-04 18:38:53 +00001829 for (const Instruction *I : NoReturnChanged) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001830 size_t Size = ToBeExploredPaths.size();
1831
Johannes Doerfert4361da22019-08-04 18:38:53 +00001832 const Instruction *NextNoReturnI = findNextNoReturn(A, I);
1833 if (NextNoReturnI != I) {
1834 Status = ChangeStatus::CHANGED;
1835 NoReturnCalls.remove(I);
1836 if (NextNoReturnI)
1837 NoReturnCalls.insert(NextNoReturnI);
1838 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001839
Johannes Doerfert4361da22019-08-04 18:38:53 +00001840 // Explore new paths.
1841 while (Size != ToBeExploredPaths.size()) {
1842 Status = ChangeStatus::CHANGED;
1843 if (const Instruction *NextNoReturnI =
1844 findNextNoReturn(A, ToBeExploredPaths[Size++]))
1845 NoReturnCalls.insert(NextNoReturnI);
1846 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001847 }
1848
Johannes Doerfertdef99282019-08-14 21:29:37 +00001849 LLVM_DEBUG(dbgs() << "[AAIsDead] AssumedLiveBlocks: "
1850 << AssumedLiveBlocks.size() << " Total number of blocks: "
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001851 << getAssociatedFunction()->size() << "\n");
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001852
Johannes Doerfertd6207812019-08-07 22:32:38 +00001853 // If we know everything is live there is no need to query for liveness.
1854 if (NoReturnCalls.empty() &&
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001855 getAssociatedFunction()->size() == AssumedLiveBlocks.size()) {
Johannes Doerfertd6207812019-08-07 22:32:38 +00001856 // Indicating a pessimistic fixpoint will cause the state to be "invalid"
1857 // which will cause the Attributor to not return the AAIsDead on request,
1858 // which will prevent us from querying isAssumedDead().
1859 indicatePessimisticFixpoint();
1860 assert(!isValidState() && "Expected an invalid state!");
1861 }
1862
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001863 return Status;
1864}
1865
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001866/// Liveness information for a call sites.
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001867//
1868// TODO: Once we have call site specific value information we can provide call
1869// site specific liveness liveness information and then it makes sense to
1870// specialize attributes for call sites instead of redirecting requests to
1871// the callee.
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001872using AAIsDeadCallSite = AAIsDeadFunction;
1873
Hideto Ueno19c07af2019-07-23 08:16:17 +00001874/// -------------------- Dereferenceable Argument Attribute --------------------
1875
1876struct DerefState : AbstractState {
1877
1878 /// State representing for dereferenceable bytes.
1879 IntegerState DerefBytesState;
1880
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001881 /// State representing that whether the value is globaly dereferenceable.
1882 BooleanState GlobalState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001883
1884 /// See AbstractState::isValidState()
1885 bool isValidState() const override { return DerefBytesState.isValidState(); }
1886
Johannes Doerfertb6acee52019-08-04 17:55:15 +00001887 /// See AbstractState::isAtFixpoint()
Hideto Ueno19c07af2019-07-23 08:16:17 +00001888 bool isAtFixpoint() const override {
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001889 return !isValidState() ||
1890 (DerefBytesState.isAtFixpoint() && GlobalState.isAtFixpoint());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001891 }
1892
1893 /// See AbstractState::indicateOptimisticFixpoint(...)
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001894 ChangeStatus indicateOptimisticFixpoint() override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001895 DerefBytesState.indicateOptimisticFixpoint();
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001896 GlobalState.indicateOptimisticFixpoint();
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001897 return ChangeStatus::UNCHANGED;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001898 }
1899
1900 /// See AbstractState::indicatePessimisticFixpoint(...)
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001901 ChangeStatus indicatePessimisticFixpoint() override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001902 DerefBytesState.indicatePessimisticFixpoint();
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001903 GlobalState.indicatePessimisticFixpoint();
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001904 return ChangeStatus::CHANGED;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001905 }
1906
1907 /// Update known dereferenceable bytes.
1908 void takeKnownDerefBytesMaximum(uint64_t Bytes) {
1909 DerefBytesState.takeKnownMaximum(Bytes);
1910 }
1911
1912 /// Update assumed dereferenceable bytes.
1913 void takeAssumedDerefBytesMinimum(uint64_t Bytes) {
1914 DerefBytesState.takeAssumedMinimum(Bytes);
1915 }
1916
Hideto Ueno19c07af2019-07-23 08:16:17 +00001917 /// Equality for DerefState.
1918 bool operator==(const DerefState &R) {
1919 return this->DerefBytesState == R.DerefBytesState &&
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001920 this->GlobalState == R.GlobalState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001921 }
Johannes Doerferte1e844d2019-08-14 21:35:20 +00001922
1923 /// Inequality for IntegerState.
1924 bool operator!=(const DerefState &R) { return !(*this == R); }
1925
1926 /// See IntegerState::operator^=
1927 DerefState operator^=(const DerefState &R) {
1928 DerefBytesState ^= R.DerefBytesState;
1929 GlobalState ^= R.GlobalState;
1930 return *this;
1931 }
1932
1933 /// See IntegerState::operator&=
1934 DerefState operator&=(const DerefState &R) {
1935 DerefBytesState &= R.DerefBytesState;
1936 GlobalState &= R.GlobalState;
1937 return *this;
1938 }
1939
1940 /// See IntegerState::operator|=
1941 DerefState operator|=(const DerefState &R) {
1942 DerefBytesState |= R.DerefBytesState;
1943 GlobalState |= R.GlobalState;
1944 return *this;
1945 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001946};
Hideto Ueno19c07af2019-07-23 08:16:17 +00001947
Johannes Doerferteccdf082019-08-05 23:35:12 +00001948struct AADereferenceableImpl : AADereferenceable, DerefState {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001949 AADereferenceableImpl(const IRPosition &IRP) : AADereferenceable(IRP) {}
Johannes Doerfert344d0382019-08-07 22:34:26 +00001950 using StateType = DerefState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001951
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001952 void initialize(Attributor &A) override {
1953 SmallVector<Attribute, 4> Attrs;
1954 getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
1955 Attrs);
1956 for (const Attribute &Attr : Attrs)
1957 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
1958
1959 NonNullAA = A.getAAFor<AANonNull>(*this, getIRPosition());
1960 }
1961
Hideto Ueno19c07af2019-07-23 08:16:17 +00001962 /// See AbstractAttribute::getState()
1963 /// {
Johannes Doerfert344d0382019-08-07 22:34:26 +00001964 StateType &getState() override { return *this; }
1965 const StateType &getState() const override { return *this; }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001966 /// }
1967
1968 /// See AADereferenceable::getAssumedDereferenceableBytes().
1969 uint32_t getAssumedDereferenceableBytes() const override {
1970 return DerefBytesState.getAssumed();
1971 }
1972
1973 /// See AADereferenceable::getKnownDereferenceableBytes().
1974 uint32_t getKnownDereferenceableBytes() const override {
1975 return DerefBytesState.getKnown();
1976 }
1977
Hideto Ueno19c07af2019-07-23 08:16:17 +00001978 /// See AADereferenceable::isAssumedGlobal().
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001979 bool isAssumedGlobal() const override { return GlobalState.getAssumed(); }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001980
1981 /// See AADereferenceable::isKnownGlobal().
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001982 bool isKnownGlobal() const override { return GlobalState.getKnown(); }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001983
Hideto Ueno19c07af2019-07-23 08:16:17 +00001984 bool isAssumedNonNull() const override {
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001985 return NonNullAA && NonNullAA->isAssumedNonNull();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001986 }
1987
Johannes Doerferteccdf082019-08-05 23:35:12 +00001988 void getDeducedAttributes(LLVMContext &Ctx,
1989 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001990 // TODO: Add *_globally support
1991 if (isAssumedNonNull())
1992 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
1993 Ctx, getAssumedDereferenceableBytes()));
1994 else
1995 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
1996 Ctx, getAssumedDereferenceableBytes()));
1997 }
1998 uint64_t computeAssumedDerefenceableBytes(Attributor &A, Value &V,
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001999 bool &IsGlobal);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002000
2001 /// See AbstractAttribute::getAsStr().
2002 const std::string getAsStr() const override {
2003 if (!getAssumedDereferenceableBytes())
2004 return "unknown-dereferenceable";
2005 return std::string("dereferenceable") +
2006 (isAssumedNonNull() ? "" : "_or_null") +
2007 (isAssumedGlobal() ? "_globally" : "") + "<" +
2008 std::to_string(getKnownDereferenceableBytes()) + "-" +
2009 std::to_string(getAssumedDereferenceableBytes()) + ">";
2010 }
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00002011
2012private:
2013 const AANonNull *NonNullAA = nullptr;
Hideto Ueno19c07af2019-07-23 08:16:17 +00002014};
2015
Johannes Doerfertbeb51502019-08-07 22:36:15 +00002016struct AADereferenceableReturned final : AADereferenceableImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002017 AADereferenceableReturned(const IRPosition &IRP)
2018 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00002019
2020 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002021 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002022
2023 /// See AbstractAttribute::trackStatistics()
2024 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002025 STATS_DECLTRACK_FNRET_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002026 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002027};
2028
2029// Helper function that returns dereferenceable bytes.
2030static uint64_t calcDifferenceIfBaseIsNonNull(int64_t DerefBytes,
2031 int64_t Offset, bool IsNonNull) {
2032 if (!IsNonNull)
2033 return 0;
2034 return std::max((int64_t)0, DerefBytes - Offset);
2035}
2036
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00002037uint64_t
2038AADereferenceableImpl::computeAssumedDerefenceableBytes(Attributor &A, Value &V,
2039 bool &IsGlobal) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002040 // TODO: Tracking the globally flag.
2041 IsGlobal = false;
2042
2043 // First, we try to get information about V from Attributor.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002044 if (auto *DerefAA =
2045 A.getAAFor<AADereferenceable>(*this, IRPosition::value(V))) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002046 return DerefAA->getAssumedDereferenceableBytes();
2047 }
2048
2049 // Otherwise, we try to compute assumed bytes from base pointer.
Johannes Doerfert26e58462019-08-12 22:21:09 +00002050 const DataLayout &DL = A.getDataLayout();
Hideto Ueno19c07af2019-07-23 08:16:17 +00002051 unsigned IdxWidth =
2052 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
2053 APInt Offset(IdxWidth, 0);
2054 Value *Base = V.stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
2055
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002056 if (auto *BaseDerefAA =
2057 A.getAAFor<AADereferenceable>(*this, IRPosition::value(*Base))) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002058 return calcDifferenceIfBaseIsNonNull(
2059 BaseDerefAA->getAssumedDereferenceableBytes(), Offset.getSExtValue(),
2060 Offset != 0 || BaseDerefAA->isAssumedNonNull());
2061 }
2062
2063 // Then, use IR information.
2064
2065 if (isDereferenceablePointer(Base, Base->getType(), DL))
2066 return calcDifferenceIfBaseIsNonNull(
2067 DL.getTypeStoreSize(Base->getType()->getPointerElementType()),
2068 Offset.getSExtValue(),
Johannes Doerfertdef99282019-08-14 21:29:37 +00002069 !NullPointerIsDefined(getAnchorScope(),
Hideto Ueno19c07af2019-07-23 08:16:17 +00002070 V.getType()->getPointerAddressSpace()));
2071
Hideto Ueno19c07af2019-07-23 08:16:17 +00002072 return 0;
2073}
Johannes Doerfert007153e2019-08-05 23:26:06 +00002074
Johannes Doerfertece81902019-08-12 22:05:53 +00002075ChangeStatus AADereferenceableReturned::updateImpl(Attributor &A) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002076 auto BeforeState = static_cast<DerefState>(*this);
2077
Hideto Ueno19c07af2019-07-23 08:16:17 +00002078 bool IsGlobal = isAssumedGlobal();
2079
Johannes Doerfert14a04932019-08-07 22:27:24 +00002080 auto CheckReturnValue = [&](Value &RV) -> bool {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002081 takeAssumedDerefBytesMinimum(
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00002082 computeAssumedDerefenceableBytes(A, RV, IsGlobal));
Hideto Ueno19c07af2019-07-23 08:16:17 +00002083 return isValidState();
2084 };
2085
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002086 if (A.checkForAllReturnedValues(CheckReturnValue, *this)) {
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00002087 GlobalState.intersectAssumedBits(IsGlobal);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002088 return BeforeState == static_cast<DerefState>(*this)
2089 ? ChangeStatus::UNCHANGED
2090 : ChangeStatus::CHANGED;
2091 }
Johannes Doerfertd1c37932019-08-04 18:37:38 +00002092 return indicatePessimisticFixpoint();
Hideto Ueno19c07af2019-07-23 08:16:17 +00002093}
2094
Johannes Doerfertbeb51502019-08-07 22:36:15 +00002095struct AADereferenceableArgument final : AADereferenceableImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002096 AADereferenceableArgument(const IRPosition &IRP)
2097 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00002098
Hideto Ueno19c07af2019-07-23 08:16:17 +00002099 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002100 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002101
2102 /// See AbstractAttribute::trackStatistics()
2103 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002104 STATS_DECLTRACK_ARG_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002105 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002106};
2107
Johannes Doerfertece81902019-08-12 22:05:53 +00002108ChangeStatus AADereferenceableArgument::updateImpl(Attributor &A) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002109 Argument &Arg = cast<Argument>(getAnchorValue());
Hideto Ueno19c07af2019-07-23 08:16:17 +00002110
2111 auto BeforeState = static_cast<DerefState>(*this);
2112
2113 unsigned ArgNo = Arg.getArgNo();
2114
Hideto Ueno19c07af2019-07-23 08:16:17 +00002115 bool IsGlobal = isAssumedGlobal();
2116
2117 // Callback function
2118 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) -> bool {
2119 assert(CS && "Sanity check: Call site was not initialized properly!");
2120
2121 // Check that DereferenceableAA is AADereferenceableCallSiteArgument.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002122 if (auto *DereferenceableAA = A.getAAFor<AADereferenceable>(
2123 *this, IRPosition::callsite_argument(CS, ArgNo))) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002124 ImmutableCallSite ICS(
2125 &DereferenceableAA->getIRPosition().getAnchorValue());
Hideto Ueno19c07af2019-07-23 08:16:17 +00002126 if (ICS && CS.getInstruction() == ICS.getInstruction()) {
2127 takeAssumedDerefBytesMinimum(
2128 DereferenceableAA->getAssumedDereferenceableBytes());
Hideto Ueno19c07af2019-07-23 08:16:17 +00002129 IsGlobal &= DereferenceableAA->isAssumedGlobal();
2130 return isValidState();
2131 }
2132 }
2133
2134 takeAssumedDerefBytesMinimum(computeAssumedDerefenceableBytes(
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00002135 A, *CS.getArgOperand(ArgNo), IsGlobal));
Hideto Ueno19c07af2019-07-23 08:16:17 +00002136
2137 return isValidState();
2138 };
2139
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002140 if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00002141 return indicatePessimisticFixpoint();
Hideto Ueno19c07af2019-07-23 08:16:17 +00002142
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00002143 GlobalState.intersectAssumedBits(IsGlobal);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002144
2145 return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
2146 : ChangeStatus::CHANGED;
2147}
2148
2149/// Dereferenceable attribute for a call site argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00002150struct AADereferenceableCallSiteArgument final : AADereferenceableImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002151 AADereferenceableCallSiteArgument(const IRPosition &IRP)
2152 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00002153
2154 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00002155 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002156
2157 /// See AbstractAttribute::trackStatistics()
2158 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002159 STATS_DECLTRACK_CSARG_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002160 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002161};
2162
Johannes Doerfertece81902019-08-12 22:05:53 +00002163ChangeStatus AADereferenceableCallSiteArgument::updateImpl(Attributor &A) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002164 // NOTE: Never look at the argument of the callee in this method.
2165 // If we do this, "dereferenceable" is always deduced because of the
2166 // assumption.
2167
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002168 Value &V = getAssociatedValue();
Hideto Ueno19c07af2019-07-23 08:16:17 +00002169
2170 auto BeforeState = static_cast<DerefState>(*this);
2171
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00002172 bool IsGlobal = isAssumedGlobal();
Hideto Ueno19c07af2019-07-23 08:16:17 +00002173
2174 takeAssumedDerefBytesMinimum(
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00002175 computeAssumedDerefenceableBytes(A, V, IsGlobal));
2176 GlobalState.intersectAssumedBits(IsGlobal);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002177
2178 return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
2179 : ChangeStatus::CHANGED;
2180}
2181
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002182/// Dereferenceable attribute deduction for a call site return value.
2183using AADereferenceableCallSiteReturned = AADereferenceableReturned;
2184
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002185// ------------------------ Align Argument Attribute ------------------------
2186
Johannes Doerfert344d0382019-08-07 22:34:26 +00002187struct AAAlignImpl : AAAlign {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002188 AAAlignImpl(const IRPosition &IRP) : AAAlign(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002189
2190 // Max alignemnt value allowed in IR
2191 static const unsigned MAX_ALIGN = 1U << 29;
2192
Johannes Doerfert234eda52019-08-16 19:51:23 +00002193 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002194 void initialize(Attributor &A) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002195 takeAssumedMinimum(MAX_ALIGN);
2196
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002197 SmallVector<Attribute, 4> Attrs;
2198 getAttrs({Attribute::Alignment}, Attrs);
2199 for (const Attribute &Attr : Attrs)
2200 takeKnownMaximum(Attr.getValueAsInt());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002201 }
2202
2203 /// See AbstractAttribute::getDeducedAttributes
2204 virtual void
Johannes Doerferteccdf082019-08-05 23:35:12 +00002205 getDeducedAttributes(LLVMContext &Ctx,
2206 SmallVectorImpl<Attribute> &Attrs) const override {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002207 if (getAssumedAlign() > 1)
2208 Attrs.emplace_back(Attribute::getWithAlignment(Ctx, getAssumedAlign()));
2209 }
2210
2211 /// See AbstractAttribute::getAsStr().
2212 const std::string getAsStr() const override {
2213 return getAssumedAlign() ? ("align<" + std::to_string(getKnownAlign()) +
2214 "-" + std::to_string(getAssumedAlign()) + ">")
2215 : "unknown-align";
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002216 }
2217};
2218
Johannes Doerfert234eda52019-08-16 19:51:23 +00002219/// Align attribute for a floating value.
2220struct AAAlignFloating : AAAlignImpl {
2221 AAAlignFloating(const IRPosition &IRP) : AAAlignImpl(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002222
2223 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert234eda52019-08-16 19:51:23 +00002224 ChangeStatus updateImpl(Attributor &A) override {
2225 const DataLayout &DL = A.getDataLayout();
2226
2227 auto VisitValueCB = [&](Value &V, AAAlign::StateType &T, bool Stripped) {
2228 if (!Stripped &&
2229 getIRPosition().getPositionKind() == IRPosition::IRP_FLOAT) {
2230 // Use only IR information if we did not strip anything.
2231 T.takeKnownMaximum(V.getPointerAlignment(DL));
2232 T.indicatePessimisticFixpoint();
2233 } else if (const auto *AA =
2234 A.getAAFor<AAAlign>(*this, IRPosition::value(V))) {
2235 // Try to use abstract attribute information.
2236 const AAAlign::StateType &DS =
2237 static_cast<const AAAlign::StateType &>(AA->getState());
2238 T.takeAssumedMinimum(DS.getAssumed());
2239 } else {
2240 // Last resort, look into the IR.
2241 T.takeKnownMaximum(V.getPointerAlignment(DL));
2242 T.indicatePessimisticFixpoint();
2243 }
2244 };
2245
2246 StateType T;
2247 if (!genericValueTraversal<AAAlign, StateType>(A, getIRPosition(), *this, T,
2248 VisitValueCB))
2249 indicatePessimisticFixpoint();
2250
2251 return clampStateAndIndicateChange(getState(), T);
2252 }
2253
2254 /// See AbstractAttribute::trackStatistics()
2255 void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) }
2256};
2257
2258/// Align attribute for function return value.
2259struct AAAlignReturned final : AAReturnedFromReturnedValues<AAAlignImpl> {
2260 AAAlignReturned(const IRPosition &IRP)
2261 : AAReturnedFromReturnedValues<AAAlignImpl>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002262
2263 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002264 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002265};
2266
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002267/// Align attribute for function argument.
Johannes Doerfert234eda52019-08-16 19:51:23 +00002268struct AAAlignArgument final : AAArgumentFromCallSiteArguments<AAAlignImpl> {
2269 AAAlignArgument(const IRPosition &IRP)
2270 : AAArgumentFromCallSiteArguments<AAAlignImpl>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002271
2272 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002273 void trackStatistics() const override{STATS_DECLTRACK_ARG_ATTR(aligned)};
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002274};
2275
Johannes Doerfert234eda52019-08-16 19:51:23 +00002276struct AAAlignCallSiteArgument final : AAAlignFloating {
2277 AAAlignCallSiteArgument(const IRPosition &IRP) : AAAlignFloating(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002278
2279 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002280 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002281};
2282
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002283/// Align attribute deduction for a call site return value.
2284using AAAlignCallSiteReturned = AAAlignReturned;
2285
Johannes Doerferte83f3032019-08-05 23:22:05 +00002286/// ------------------ Function No-Return Attribute ----------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00002287struct AANoReturnImpl : public AANoReturn {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002288 AANoReturnImpl(const IRPosition &IRP) : AANoReturn(IRP) {}
Johannes Doerferte83f3032019-08-05 23:22:05 +00002289
Johannes Doerferte83f3032019-08-05 23:22:05 +00002290 /// See AbstractAttribute::getAsStr().
2291 const std::string getAsStr() const override {
2292 return getAssumed() ? "noreturn" : "may-return";
2293 }
2294
2295 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002296 void initialize(Attributor &A) override {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002297 if (hasAttr({getAttrKind()}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002298 indicateOptimisticFixpoint();
2299 }
2300
2301 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00002302 virtual ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002303 auto CheckForNoReturn = [](Instruction &) { return false; };
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002304 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002305 {(unsigned)Instruction::Ret}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002306 return indicatePessimisticFixpoint();
Johannes Doerferte83f3032019-08-05 23:22:05 +00002307 return ChangeStatus::UNCHANGED;
2308 }
2309};
2310
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002311struct AANoReturnFunction final : AANoReturnImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002312 AANoReturnFunction(const IRPosition &IRP) : AANoReturnImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002313
2314 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002315 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002316};
2317
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002318/// NoReturn attribute deduction for a call sites.
2319using AANoReturnCallSite = AANoReturnFunction;
2320
Johannes Doerfertaade7822019-06-05 03:02:24 +00002321/// ----------------------------------------------------------------------------
2322/// Attributor
2323/// ----------------------------------------------------------------------------
2324
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002325bool Attributor::isAssumedDead(const AbstractAttribute &AA,
2326 const AAIsDead *LivenessAA) {
2327 const Instruction *CtxI = AA.getIRPosition().getCtxI();
2328 if (!CtxI)
2329 return false;
2330
2331 if (!LivenessAA)
2332 LivenessAA =
2333 getAAFor<AAIsDead>(AA, IRPosition::function(*CtxI->getFunction()));
2334 if (!LivenessAA || !LivenessAA->isAssumedDead(CtxI))
2335 return false;
2336
2337 // TODO: Do not track dependences automatically but add it here as only a
2338 // "is-assumed-dead" result causes a dependence.
2339 return true;
2340}
2341
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002342bool Attributor::checkForAllCallSites(const function_ref<bool(CallSite)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002343 const AbstractAttribute &QueryingAA,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002344 bool RequireAllCallSites) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002345 // We can try to determine information from
2346 // the call sites. However, this is only possible all call sites are known,
2347 // hence the function has internal linkage.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002348 const IRPosition &IRP = QueryingAA.getIRPosition();
2349 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2350 if (!AssociatedFunction)
2351 return false;
2352
2353 if (RequireAllCallSites && !AssociatedFunction->hasInternalLinkage()) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002354 LLVM_DEBUG(
2355 dbgs()
Johannes Doerfert5304b722019-08-14 22:04:28 +00002356 << "[Attributor] Function " << AssociatedFunction->getName()
Hideto Ueno54869ec2019-07-15 06:49:04 +00002357 << " has no internal linkage, hence not all call sites are known\n");
2358 return false;
2359 }
2360
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002361 for (const Use &U : AssociatedFunction->uses()) {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002362 Instruction *I = cast<Instruction>(U.getUser());
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002363 Function *Caller = I->getFunction();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002364
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002365 auto *LivenessAA =
2366 getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*Caller));
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002367
2368 // Skip dead calls.
2369 if (LivenessAA && LivenessAA->isAssumedDead(I))
2370 continue;
Hideto Ueno54869ec2019-07-15 06:49:04 +00002371
2372 CallSite CS(U.getUser());
Hideto Ueno54869ec2019-07-15 06:49:04 +00002373 if (!CS || !CS.isCallee(&U) || !CS.getCaller()->hasExactDefinition()) {
2374 if (!RequireAllCallSites)
2375 continue;
2376
Johannes Doerfert5304b722019-08-14 22:04:28 +00002377 LLVM_DEBUG(dbgs() << "[Attributor] User " << *U.getUser()
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002378 << " is an invalid use of "
2379 << AssociatedFunction->getName() << "\n");
Hideto Ueno54869ec2019-07-15 06:49:04 +00002380 return false;
2381 }
2382
2383 if (Pred(CS))
2384 continue;
2385
Johannes Doerfert5304b722019-08-14 22:04:28 +00002386 LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for "
Hideto Ueno54869ec2019-07-15 06:49:04 +00002387 << *CS.getInstruction() << "\n");
2388 return false;
2389 }
2390
2391 return true;
2392}
2393
Johannes Doerfert14a04932019-08-07 22:27:24 +00002394bool Attributor::checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert14a04932019-08-07 22:27:24 +00002395 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
2396 &Pred,
2397 const AbstractAttribute &QueryingAA) {
2398
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002399 const IRPosition &IRP = QueryingAA.getIRPosition();
2400 // Since we need to provide return instructions we have to have an exact
2401 // definition.
2402 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2403 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
Johannes Doerfert14a04932019-08-07 22:27:24 +00002404 return false;
2405
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002406 // If this is a call site query we use the call site specific return values
2407 // and liveness information.
2408 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2409 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
2410 if (!AARetVal || !AARetVal->getState().isValidState())
2411 return false;
2412
Johannes Doerfertdef99282019-08-14 21:29:37 +00002413 return AARetVal->checkForAllReturnedValuesAndReturnInsts(Pred);
Johannes Doerfert14a04932019-08-07 22:27:24 +00002414}
2415
2416bool Attributor::checkForAllReturnedValues(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002417 const function_ref<bool(Value &)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002418 const AbstractAttribute &QueryingAA) {
2419
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002420 const IRPosition &IRP = QueryingAA.getIRPosition();
2421 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2422 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
Johannes Doerfert14a04932019-08-07 22:27:24 +00002423 return false;
2424
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002425 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2426 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
2427 if (!AARetVal || !AARetVal->getState().isValidState())
2428 return false;
2429
Johannes Doerfertdef99282019-08-14 21:29:37 +00002430 return AARetVal->checkForAllReturnedValuesAndReturnInsts(
2431 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &) {
2432 return Pred(RV);
2433 });
Johannes Doerfert14a04932019-08-07 22:27:24 +00002434}
2435
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002436bool Attributor::checkForAllInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002437 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00002438 const AbstractAttribute &QueryingAA, const ArrayRef<unsigned> &Opcodes) {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002439
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002440 const IRPosition &IRP = QueryingAA.getIRPosition();
2441 // Since we need to provide instructions we have to have an exact definition.
2442 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2443 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
2444 return false;
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002445
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002446 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2447 const auto &LivenessAA = getAAFor<AAIsDead>(QueryingAA, QueryIRP);
2448
2449 auto &OpcodeInstMap =
2450 InfoCache.getOpcodeInstMapForFunction(*AssociatedFunction);
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002451 for (unsigned Opcode : Opcodes) {
2452 for (Instruction *I : OpcodeInstMap[Opcode]) {
2453 // Skip dead instructions.
2454 if (LivenessAA && LivenessAA->isAssumedDead(I))
2455 continue;
2456
2457 if (!Pred(*I))
2458 return false;
2459 }
2460 }
2461
2462 return true;
2463}
2464
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002465bool Attributor::checkForAllReadWriteInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002466 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00002467 AbstractAttribute &QueryingAA) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002468
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002469 const Function *AssociatedFunction =
2470 QueryingAA.getIRPosition().getAssociatedFunction();
2471 if (!AssociatedFunction)
2472 return false;
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002473
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002474 const auto &LivenessAA =
2475 getAAFor<AAIsDead>(QueryingAA, QueryingAA.getIRPosition());
2476
2477 for (Instruction *I :
2478 InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002479 // Skip dead instructions.
2480 if (LivenessAA && LivenessAA->isAssumedDead(I))
2481 continue;
2482
2483 if (!Pred(*I))
2484 return false;
2485 }
2486
2487 return true;
2488}
2489
Johannes Doerfertece81902019-08-12 22:05:53 +00002490ChangeStatus Attributor::run() {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002491 // Initialize all abstract attributes.
2492 for (AbstractAttribute *AA : AllAbstractAttributes)
Johannes Doerfertece81902019-08-12 22:05:53 +00002493 AA->initialize(*this);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002494
2495 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
2496 << AllAbstractAttributes.size()
2497 << " abstract attributes.\n");
2498
Stefan Stipanovic53605892019-06-27 11:27:54 +00002499 // Now that all abstract attributes are collected and initialized we start
2500 // the abstract analysis.
Johannes Doerfertaade7822019-06-05 03:02:24 +00002501
2502 unsigned IterationCounter = 1;
2503
2504 SmallVector<AbstractAttribute *, 64> ChangedAAs;
2505 SetVector<AbstractAttribute *> Worklist;
2506 Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
2507
2508 do {
2509 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
2510 << ", Worklist size: " << Worklist.size() << "\n");
2511
2512 // Add all abstract attributes that are potentially dependent on one that
2513 // changed to the work list.
2514 for (AbstractAttribute *ChangedAA : ChangedAAs) {
2515 auto &QuerriedAAs = QueryMap[ChangedAA];
2516 Worklist.insert(QuerriedAAs.begin(), QuerriedAAs.end());
2517 }
2518
2519 // Reset the changed set.
2520 ChangedAAs.clear();
2521
2522 // Update all abstract attribute in the work list and record the ones that
2523 // changed.
2524 for (AbstractAttribute *AA : Worklist)
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002525 if (!isAssumedDead(*AA, nullptr))
2526 if (AA->update(*this) == ChangeStatus::CHANGED)
2527 ChangedAAs.push_back(AA);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002528
2529 // Reset the work list and repopulate with the changed abstract attributes.
2530 // Note that dependent ones are added above.
2531 Worklist.clear();
2532 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2533
2534 } while (!Worklist.empty() && ++IterationCounter < MaxFixpointIterations);
2535
2536 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
2537 << IterationCounter << "/" << MaxFixpointIterations
2538 << " iterations\n");
2539
2540 bool FinishedAtFixpoint = Worklist.empty();
2541
2542 // Reset abstract arguments not settled in a sound fixpoint by now. This
2543 // happens when we stopped the fixpoint iteration early. Note that only the
2544 // ones marked as "changed" *and* the ones transitively depending on them
2545 // need to be reverted to a pessimistic state. Others might not be in a
2546 // fixpoint state but we can use the optimistic results for them anyway.
2547 SmallPtrSet<AbstractAttribute *, 32> Visited;
2548 for (unsigned u = 0; u < ChangedAAs.size(); u++) {
2549 AbstractAttribute *ChangedAA = ChangedAAs[u];
2550 if (!Visited.insert(ChangedAA).second)
2551 continue;
2552
2553 AbstractState &State = ChangedAA->getState();
2554 if (!State.isAtFixpoint()) {
2555 State.indicatePessimisticFixpoint();
2556
2557 NumAttributesTimedOut++;
2558 }
2559
2560 auto &QuerriedAAs = QueryMap[ChangedAA];
2561 ChangedAAs.append(QuerriedAAs.begin(), QuerriedAAs.end());
2562 }
2563
2564 LLVM_DEBUG({
2565 if (!Visited.empty())
2566 dbgs() << "\n[Attributor] Finalized " << Visited.size()
2567 << " abstract attributes.\n";
2568 });
2569
2570 unsigned NumManifested = 0;
2571 unsigned NumAtFixpoint = 0;
2572 ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
2573 for (AbstractAttribute *AA : AllAbstractAttributes) {
2574 AbstractState &State = AA->getState();
2575
2576 // If there is not already a fixpoint reached, we can now take the
2577 // optimistic state. This is correct because we enforced a pessimistic one
2578 // on abstract attributes that were transitively dependent on a changed one
2579 // already above.
2580 if (!State.isAtFixpoint())
2581 State.indicateOptimisticFixpoint();
2582
2583 // If the state is invalid, we do not try to manifest it.
2584 if (!State.isValidState())
2585 continue;
2586
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002587 // Skip dead code.
2588 if (isAssumedDead(*AA, nullptr))
2589 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002590 // Manifest the state and record if we changed the IR.
2591 ChangeStatus LocalChange = AA->manifest(*this);
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002592 if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled())
2593 AA->trackStatistics();
2594
Johannes Doerfertaade7822019-06-05 03:02:24 +00002595 ManifestChange = ManifestChange | LocalChange;
2596
2597 NumAtFixpoint++;
2598 NumManifested += (LocalChange == ChangeStatus::CHANGED);
2599 }
2600
2601 (void)NumManifested;
2602 (void)NumAtFixpoint;
2603 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
2604 << " arguments while " << NumAtFixpoint
2605 << " were in a valid fixpoint state\n");
2606
2607 // If verification is requested, we finished this run at a fixpoint, and the
2608 // IR was changed, we re-run the whole fixpoint analysis, starting at
2609 // re-initialization of the arguments. This re-run should not result in an IR
2610 // change. Though, the (virtual) state of attributes at the end of the re-run
2611 // might be more optimistic than the known state or the IR state if the better
2612 // state cannot be manifested.
2613 if (VerifyAttributor && FinishedAtFixpoint &&
2614 ManifestChange == ChangeStatus::CHANGED) {
2615 VerifyAttributor = false;
Johannes Doerfertece81902019-08-12 22:05:53 +00002616 ChangeStatus VerifyStatus = run();
Johannes Doerfertaade7822019-06-05 03:02:24 +00002617 if (VerifyStatus != ChangeStatus::UNCHANGED)
2618 llvm_unreachable(
2619 "Attributor verification failed, re-run did result in an IR change "
2620 "even after a fixpoint was reached in the original run. (False "
2621 "positives possible!)");
2622 VerifyAttributor = true;
2623 }
2624
2625 NumAttributesManifested += NumManifested;
2626 NumAttributesValidFixpoint += NumAtFixpoint;
2627
2628 return ManifestChange;
2629}
2630
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002631/// Helper function that checks if an abstract attribute of type \p AAType
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002632/// should be created for IR position \p IRP and if so creates and registers it
2633/// with the Attributor \p A.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002634///
2635/// This method will look at the provided whitelist. If one is given and the
2636/// kind \p AAType::ID is not contained, no abstract attribute is created.
2637///
2638/// \returns The created abstract argument, or nullptr if none was created.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002639template <typename AAType>
Johannes Doerfert5304b722019-08-14 22:04:28 +00002640static AAType *checkAndRegisterAA(const IRPosition &IRP, Attributor &A,
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002641 DenseSet<const char *> *Whitelist) {
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002642 if (Whitelist && !Whitelist->count(&AAType::ID))
2643 return nullptr;
2644
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002645 return &A.registerAA<AAType>(*new AAType(IRP));
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002646}
2647
Johannes Doerfertaade7822019-06-05 03:02:24 +00002648void Attributor::identifyDefaultAbstractAttributes(
Johannes Doerfertece81902019-08-12 22:05:53 +00002649 Function &F, DenseSet<const char *> *Whitelist) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002650
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002651 IRPosition FPos = IRPosition::function(F);
2652
Johannes Doerfert305b9612019-08-04 18:40:01 +00002653 // Check for dead BasicBlocks in every function.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002654 // We need dead instruction detection because we do not want to deal with
2655 // broken IR in which SSA rules do not apply.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002656 checkAndRegisterAA<AAIsDeadFunction>(FPos, *this, /* Whitelist */ nullptr);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002657
2658 // Every function might be "will-return".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002659 checkAndRegisterAA<AAWillReturnFunction>(FPos, *this, Whitelist);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002660
Stefan Stipanovic53605892019-06-27 11:27:54 +00002661 // Every function can be nounwind.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002662 checkAndRegisterAA<AANoUnwindFunction>(FPos, *this, Whitelist);
Stefan Stipanovic53605892019-06-27 11:27:54 +00002663
Stefan Stipanovic06263672019-07-11 21:37:40 +00002664 // Every function might be marked "nosync"
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002665 checkAndRegisterAA<AANoSyncFunction>(FPos, *this, Whitelist);
Stefan Stipanovic06263672019-07-11 21:37:40 +00002666
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002667 // Every function might be "no-free".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002668 checkAndRegisterAA<AANoFreeFunction>(FPos, *this, Whitelist);
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002669
Johannes Doerferte83f3032019-08-05 23:22:05 +00002670 // Every function might be "no-return".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002671 checkAndRegisterAA<AANoReturnFunction>(FPos, *this, Whitelist);
Johannes Doerferte83f3032019-08-05 23:22:05 +00002672
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002673 // Return attributes are only appropriate if the return type is non void.
2674 Type *ReturnType = F.getReturnType();
2675 if (!ReturnType->isVoidTy()) {
2676 // Argument attribute "returned" --- Create only one per function even
2677 // though it is an argument attribute.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002678 checkAndRegisterAA<AAReturnedValuesFunction>(FPos, *this, Whitelist);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002679
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002680 if (ReturnType->isPointerTy()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002681 IRPosition RetPos = IRPosition::returned(F);
2682
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002683 // Every function with pointer return type might be marked align.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002684 checkAndRegisterAA<AAAlignReturned>(RetPos, *this, Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002685
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002686 // Every function with pointer return type might be marked nonnull.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002687 checkAndRegisterAA<AANonNullReturned>(RetPos, *this, Whitelist);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002688
2689 // Every function with pointer return type might be marked noalias.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002690 checkAndRegisterAA<AANoAliasReturned>(RetPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002691
2692 // Every function with pointer return type might be marked
2693 // dereferenceable.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002694 checkAndRegisterAA<AADereferenceableReturned>(RetPos, *this, Whitelist);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002695 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00002696 }
2697
Hideto Ueno54869ec2019-07-15 06:49:04 +00002698 for (Argument &Arg : F.args()) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002699 if (Arg.getType()->isPointerTy()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002700 IRPosition ArgPos = IRPosition::argument(Arg);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002701 // Every argument with pointer type might be marked nonnull.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002702 checkAndRegisterAA<AANonNullArgument>(ArgPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002703
2704 // Every argument with pointer type might be marked dereferenceable.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002705 checkAndRegisterAA<AADereferenceableArgument>(ArgPos, *this, Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002706
2707 // Every argument with pointer type might be marked align.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002708 checkAndRegisterAA<AAAlignArgument>(ArgPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002709 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002710 }
2711
Johannes Doerfertaade7822019-06-05 03:02:24 +00002712 // Walk all instructions to find more attribute opportunities and also
2713 // interesting instructions that might be queried by abstract attributes
2714 // during their initialization or update.
2715 auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
2716 auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
2717
2718 for (Instruction &I : instructions(&F)) {
2719 bool IsInterestingOpcode = false;
2720
2721 // To allow easy access to all instructions in a function with a given
2722 // opcode we store them in the InfoCache. As not all opcodes are interesting
2723 // to concrete attributes we only cache the ones that are as identified in
2724 // the following switch.
2725 // Note: There are no concrete attributes now so this is initially empty.
Stefan Stipanovic53605892019-06-27 11:27:54 +00002726 switch (I.getOpcode()) {
2727 default:
2728 assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) &&
2729 "New call site/base instruction type needs to be known int the "
2730 "attributor.");
2731 break;
2732 case Instruction::Call:
2733 case Instruction::CallBr:
2734 case Instruction::Invoke:
2735 case Instruction::CleanupRet:
2736 case Instruction::CatchSwitch:
2737 case Instruction::Resume:
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002738 case Instruction::Ret:
Stefan Stipanovic53605892019-06-27 11:27:54 +00002739 IsInterestingOpcode = true;
2740 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002741 if (IsInterestingOpcode)
2742 InstOpcodeMap[I.getOpcode()].push_back(&I);
2743 if (I.mayReadOrWriteMemory())
2744 ReadOrWriteInsts.push_back(&I);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002745
2746 CallSite CS(&I);
2747 if (CS && CS.getCalledFunction()) {
2748 for (int i = 0, e = CS.getCalledFunction()->arg_size(); i < e; i++) {
2749 if (!CS.getArgument(i)->getType()->isPointerTy())
2750 continue;
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002751 IRPosition CSArgPos = IRPosition::callsite_argument(CS, i);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002752
2753 // Call site argument attribute "non-null".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002754 checkAndRegisterAA<AANonNullCallSiteArgument>(CSArgPos, *this,
2755 Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002756
2757 // Call site argument attribute "dereferenceable".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002758 checkAndRegisterAA<AADereferenceableCallSiteArgument>(CSArgPos, *this,
2759 Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002760
2761 // Call site argument attribute "align".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002762 checkAndRegisterAA<AAAlignCallSiteArgument>(CSArgPos, *this, Whitelist);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002763 }
2764 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002765 }
2766}
2767
2768/// Helpers to ease debugging through output streams and print calls.
2769///
2770///{
2771raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
2772 return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
2773}
2774
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002775raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002776 switch (AP) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002777 case IRPosition::IRP_INVALID:
2778 return OS << "inv";
2779 case IRPosition::IRP_FLOAT:
2780 return OS << "flt";
2781 case IRPosition::IRP_RETURNED:
2782 return OS << "fn_ret";
2783 case IRPosition::IRP_CALL_SITE_RETURNED:
2784 return OS << "cs_ret";
2785 case IRPosition::IRP_FUNCTION:
2786 return OS << "fn";
2787 case IRPosition::IRP_CALL_SITE:
2788 return OS << "cs";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002789 case IRPosition::IRP_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002790 return OS << "arg";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002791 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002792 return OS << "cs_arg";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002793 }
2794 llvm_unreachable("Unknown attribute position!");
2795}
2796
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002797raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002798 const Value &AV = Pos.getAssociatedValue();
2799 return OS << "{" << Pos.getPositionKind() << ":" << AV.getName() << " ["
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002800 << Pos.getAnchorValue().getName() << "@" << Pos.getArgNo() << "]}";
2801}
2802
Johannes Doerfertacc80792019-08-12 22:07:34 +00002803raw_ostream &llvm::operator<<(raw_ostream &OS, const IntegerState &S) {
2804 return OS << "(" << S.getKnown() << "-" << S.getAssumed() << ")"
2805 << static_cast<const AbstractState &>(S);
2806}
2807
Johannes Doerfertaade7822019-06-05 03:02:24 +00002808raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
2809 return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
2810}
2811
2812raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
2813 AA.print(OS);
2814 return OS;
2815}
2816
2817void AbstractAttribute::print(raw_ostream &OS) const {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002818 OS << "[P: " << getIRPosition() << "][" << getAsStr() << "][S: " << getState()
2819 << "]";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002820}
2821///}
2822
2823/// ----------------------------------------------------------------------------
2824/// Pass (Manager) Boilerplate
2825/// ----------------------------------------------------------------------------
2826
2827static bool runAttributorOnModule(Module &M) {
2828 if (DisableAttributor)
2829 return false;
2830
2831 LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << M.size()
2832 << " functions.\n");
2833
2834 // Create an Attributor and initially empty information cache that is filled
2835 // while we identify default attribute opportunities.
Johannes Doerfertece81902019-08-12 22:05:53 +00002836 InformationCache InfoCache(M.getDataLayout());
2837 Attributor A(InfoCache);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002838
2839 for (Function &F : M) {
2840 // TODO: Not all attributes require an exact definition. Find a way to
2841 // enable deduction for some but not all attributes in case the
2842 // definition might be changed at runtime, see also
2843 // http://lists.llvm.org/pipermail/llvm-dev/2018-February/121275.html.
2844 // TODO: We could always determine abstract attributes and if sufficient
2845 // information was found we could duplicate the functions that do not
2846 // have an exact definition.
2847 if (!F.hasExactDefinition()) {
2848 NumFnWithoutExactDefinition++;
2849 continue;
2850 }
2851
2852 // For now we ignore naked and optnone functions.
2853 if (F.hasFnAttribute(Attribute::Naked) ||
2854 F.hasFnAttribute(Attribute::OptimizeNone))
2855 continue;
2856
2857 NumFnWithExactDefinition++;
2858
2859 // Populate the Attributor with abstract attribute opportunities in the
2860 // function and the information cache with IR information.
Johannes Doerfertece81902019-08-12 22:05:53 +00002861 A.identifyDefaultAbstractAttributes(F);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002862 }
2863
Johannes Doerfertece81902019-08-12 22:05:53 +00002864 return A.run() == ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002865}
2866
2867PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
2868 if (runAttributorOnModule(M)) {
2869 // FIXME: Think about passes we will preserve and add them here.
2870 return PreservedAnalyses::none();
2871 }
2872 return PreservedAnalyses::all();
2873}
2874
2875namespace {
2876
2877struct AttributorLegacyPass : public ModulePass {
2878 static char ID;
2879
2880 AttributorLegacyPass() : ModulePass(ID) {
2881 initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry());
2882 }
2883
2884 bool runOnModule(Module &M) override {
2885 if (skipModule(M))
2886 return false;
2887 return runAttributorOnModule(M);
2888 }
2889
2890 void getAnalysisUsage(AnalysisUsage &AU) const override {
2891 // FIXME: Think about passes we will preserve and add them here.
2892 AU.setPreservesCFG();
2893 }
2894};
2895
2896} // end anonymous namespace
2897
2898Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); }
2899
2900char AttributorLegacyPass::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002901
2902const char AAReturnedValues::ID = 0;
2903const char AANoUnwind::ID = 0;
2904const char AANoSync::ID = 0;
Johannes Doerferteccdf082019-08-05 23:35:12 +00002905const char AANoFree::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002906const char AANonNull::ID = 0;
2907const char AANoRecurse::ID = 0;
2908const char AAWillReturn::ID = 0;
2909const char AANoAlias::ID = 0;
2910const char AANoReturn::ID = 0;
2911const char AAIsDead::ID = 0;
2912const char AADereferenceable::ID = 0;
2913const char AAAlign::ID = 0;
2914
Johannes Doerfertaade7822019-06-05 03:02:24 +00002915INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor",
2916 "Deduce and propagate attributes", false, false)
2917INITIALIZE_PASS_END(AttributorLegacyPass, "attributor",
2918 "Deduce and propagate attributes", false, false)