blob: 2f062bfac5e8d0e3e715c75e794e825a5f72ed08 [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
61// attribute and choose the right STATS_DECL_AND_TRACK_********* macro,
62// e.g.,:
63// void trackStatistics() const override {
64// STATS_DECL_AND_TRACK_ARG_ATTR(returned)
65// }
66// If there is a single "increment" side one can use the macro
67// STATS_DECL_AND_TRACK with a custom message. If there are multiple increment
68// 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));
75#define STATS_DECL_AND_TRACK(NAME, TYPE, MSG) \
76 STATS_DECL(NAME, TYPE, MSG) \
77 STATS_TRACK(NAME, TYPE)
78#define STATS_DECL_AND_TRACK_ARG_ATTR(NAME) \
79 STATS_DECL_AND_TRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
80#define STATS_DECL_AND_TRACK_CSARG_ATTR(NAME) \
81 STATS_DECL_AND_TRACK(NAME, CSArguments, \
82 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
83#define STATS_DECL_AND_TRACK_FN_ATTR(NAME) \
84 STATS_DECL_AND_TRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
85#define STATS_DECL_AND_TRACK_FNRET_ATTR(NAME) \
86 STATS_DECL_AND_TRACK(NAME, FunctionReturn, \
87 BUILD_STAT_MSG_IR_ATTR(function returns, NAME));
Johannes Doerfertaccd3e82019-07-08 23:27:20 +000088
Johannes Doerfertaade7822019-06-05 03:02:24 +000089// TODO: Determine a good default value.
90//
91// In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads
92// (when run with the first 5 abstract attributes). The results also indicate
93// that we never reach 32 iterations but always find a fixpoint sooner.
94//
95// This will become more evolved once we perform two interleaved fixpoint
96// iterations: bottom-up and top-down.
97static cl::opt<unsigned>
98 MaxFixpointIterations("attributor-max-iterations", cl::Hidden,
99 cl::desc("Maximal number of fixpoint iterations."),
100 cl::init(32));
101
102static cl::opt<bool> DisableAttributor(
103 "attributor-disable", cl::Hidden,
104 cl::desc("Disable the attributor inter-procedural deduction pass."),
Johannes Doerfert282d34e2019-06-14 14:53:41 +0000105 cl::init(true));
Johannes Doerfertaade7822019-06-05 03:02:24 +0000106
107static cl::opt<bool> VerifyAttributor(
108 "attributor-verify", cl::Hidden,
109 cl::desc("Verify the Attributor deduction and "
110 "manifestation of attributes -- may issue false-positive errors"),
111 cl::init(false));
112
113/// Logic operators for the change status enum class.
114///
115///{
116ChangeStatus llvm::operator|(ChangeStatus l, ChangeStatus r) {
117 return l == ChangeStatus::CHANGED ? l : r;
118}
119ChangeStatus llvm::operator&(ChangeStatus l, ChangeStatus r) {
120 return l == ChangeStatus::UNCHANGED ? l : r;
121}
122///}
123
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000124template <typename StateTy>
125using followValueCB_t = std::function<bool(Value *, StateTy &State)>;
126template <typename StateTy>
127using visitValueCB_t = std::function<void(Value *, StateTy &State)>;
128
129/// Recursively visit all values that might become \p InitV at some point. This
130/// will be done by looking through cast instructions, selects, phis, and calls
131/// with the "returned" attribute. The callback \p FollowValueCB is asked before
132/// a potential origin value is looked at. If no \p FollowValueCB is passed, a
133/// default one is used that will make sure we visit every value only once. Once
134/// we cannot look through the value any further, the callback \p VisitValueCB
135/// is invoked and passed the current value and the \p State. To limit how much
136/// effort is invested, we will never visit more than \p MaxValues values.
137template <typename StateTy>
138static bool genericValueTraversal(
139 Value *InitV, StateTy &State, visitValueCB_t<StateTy> &VisitValueCB,
140 followValueCB_t<StateTy> *FollowValueCB = nullptr, int MaxValues = 8) {
141
142 SmallPtrSet<Value *, 16> Visited;
143 followValueCB_t<bool> DefaultFollowValueCB = [&](Value *Val, bool &) {
144 return Visited.insert(Val).second;
145 };
146
147 if (!FollowValueCB)
148 FollowValueCB = &DefaultFollowValueCB;
149
150 SmallVector<Value *, 16> Worklist;
151 Worklist.push_back(InitV);
152
153 int Iteration = 0;
154 do {
155 Value *V = Worklist.pop_back_val();
156
157 // Check if we should process the current value. To prevent endless
158 // recursion keep a record of the values we followed!
159 if (!(*FollowValueCB)(V, State))
160 continue;
161
162 // Make sure we limit the compile time for complex expressions.
163 if (Iteration++ >= MaxValues)
164 return false;
165
166 // Explicitly look through calls with a "returned" attribute if we do
167 // not have a pointer as stripPointerCasts only works on them.
168 if (V->getType()->isPointerTy()) {
169 V = V->stripPointerCasts();
170 } else {
171 CallSite CS(V);
172 if (CS && CS.getCalledFunction()) {
173 Value *NewV = nullptr;
174 for (Argument &Arg : CS.getCalledFunction()->args())
175 if (Arg.hasReturnedAttr()) {
176 NewV = CS.getArgOperand(Arg.getArgNo());
177 break;
178 }
179 if (NewV) {
180 Worklist.push_back(NewV);
181 continue;
182 }
183 }
184 }
185
186 // Look through select instructions, visit both potential values.
187 if (auto *SI = dyn_cast<SelectInst>(V)) {
188 Worklist.push_back(SI->getTrueValue());
189 Worklist.push_back(SI->getFalseValue());
190 continue;
191 }
192
193 // Look through phi nodes, visit all operands.
194 if (auto *PHI = dyn_cast<PHINode>(V)) {
195 Worklist.append(PHI->op_begin(), PHI->op_end());
196 continue;
197 }
198
199 // Once a leaf is reached we inform the user through the callback.
200 VisitValueCB(V, State);
201 } while (!Worklist.empty());
202
203 // All values have been visited.
204 return true;
205}
206
Johannes Doerfertaade7822019-06-05 03:02:24 +0000207/// Return true if \p New is equal or worse than \p Old.
208static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) {
209 if (!Old.isIntAttribute())
210 return true;
211
212 return Old.getValueAsInt() >= New.getValueAsInt();
213}
214
215/// Return true if the information provided by \p Attr was added to the
216/// attribute list \p Attrs. This is only the case if it was not already present
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000217/// in \p Attrs at the position describe by \p PK and \p AttrIdx.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000218static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000219 AttributeList &Attrs, int AttrIdx) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000220
221 if (Attr.isEnumAttribute()) {
222 Attribute::AttrKind Kind = Attr.getKindAsEnum();
223 if (Attrs.hasAttribute(AttrIdx, Kind))
224 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
225 return false;
226 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
227 return true;
228 }
229 if (Attr.isStringAttribute()) {
230 StringRef Kind = Attr.getKindAsString();
231 if (Attrs.hasAttribute(AttrIdx, Kind))
232 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
233 return false;
234 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
235 return true;
236 }
Hideto Ueno19c07af2019-07-23 08:16:17 +0000237 if (Attr.isIntAttribute()) {
238 Attribute::AttrKind Kind = Attr.getKindAsEnum();
239 if (Attrs.hasAttribute(AttrIdx, Kind))
240 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
241 return false;
242 Attrs = Attrs.removeAttribute(Ctx, AttrIdx, Kind);
243 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
244 return true;
245 }
Johannes Doerfertaade7822019-06-05 03:02:24 +0000246
247 llvm_unreachable("Expected enum or string attribute!");
248}
249
Johannes Doerfertece81902019-08-12 22:05:53 +0000250ChangeStatus AbstractAttribute::update(Attributor &A) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000251 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
252 if (getState().isAtFixpoint())
253 return HasChanged;
254
255 LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");
256
Johannes Doerfertece81902019-08-12 22:05:53 +0000257 HasChanged = updateImpl(A);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000258
259 LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
260 << "\n");
261
262 return HasChanged;
263}
264
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000265ChangeStatus
266IRAttributeManifest::manifestAttrs(Attributor &A, IRPosition &IRP,
267 const ArrayRef<Attribute> &DeducedAttrs) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000268 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000269
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000270 Function *ScopeFn = IRP.getAssociatedFunction();
Kristina Brooks26e60f02019-08-06 19:53:19 +0000271 IRPosition::Kind PK = IRP.getPositionKind();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000272
Johannes Doerfertaade7822019-06-05 03:02:24 +0000273 // In the following some generic code that will manifest attributes in
274 // DeducedAttrs if they improve the current IR. Due to the different
275 // annotation positions we use the underlying AttributeList interface.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000276
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000277 AttributeList Attrs;
278 switch (PK) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000279 case IRPosition::IRP_INVALID:
280 case IRPosition::IRP_FLOAT:
281 llvm_unreachable("Cannot manifest at a floating or invalid position!");
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000282 case IRPosition::IRP_ARGUMENT:
283 case IRPosition::IRP_FUNCTION:
284 case IRPosition::IRP_RETURNED:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000285 Attrs = ScopeFn->getAttributes();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000286 break;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000287 case IRPosition::IRP_CALL_SITE:
288 case IRPosition::IRP_CALL_SITE_RETURNED:
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000289 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000290 Attrs = ImmutableCallSite(&IRP.getAnchorValue()).getAttributes();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000291 break;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000292 }
293
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000294 LLVMContext &Ctx = IRP.getAnchorValue().getContext();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000295 for (const Attribute &Attr : DeducedAttrs) {
Kristina Brooks26e60f02019-08-06 19:53:19 +0000296 if (!addIfNotExistent(Ctx, Attr, Attrs, IRP.getAttrIdx()))
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000297 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000298
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000299 HasChanged = ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000300 }
301
302 if (HasChanged == ChangeStatus::UNCHANGED)
303 return HasChanged;
304
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000305 switch (PK) {
306 case IRPosition::IRP_ARGUMENT:
307 case IRPosition::IRP_FUNCTION:
308 case IRPosition::IRP_RETURNED:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000309 ScopeFn->setAttributes(Attrs);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000310 break;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000311 case IRPosition::IRP_CALL_SITE:
312 case IRPosition::IRP_CALL_SITE_RETURNED:
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000313 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000314 CallSite(&IRP.getAnchorValue()).setAttributes(Attrs);
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000315 case IRPosition::IRP_FLOAT:
316 case IRPosition::IRP_INVALID:
317 break;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000318 }
319
320 return HasChanged;
321}
322
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000323const IRPosition IRPosition::EmptyKey(255);
324const IRPosition IRPosition::TombstoneKey(256);
325
326SubsumingPositionIterator::SubsumingPositionIterator(const IRPosition &IRP) {
327 IRPositions.emplace_back(IRP);
328
329 ImmutableCallSite ICS(&IRP.getAnchorValue());
330 switch (IRP.getPositionKind()) {
331 case IRPosition::IRP_INVALID:
332 case IRPosition::IRP_FLOAT:
333 case IRPosition::IRP_FUNCTION:
334 return;
335 case IRPosition::IRP_ARGUMENT:
336 case IRPosition::IRP_RETURNED:
337 IRPositions.emplace_back(
338 IRPosition::function(*IRP.getAssociatedFunction()));
339 return;
340 case IRPosition::IRP_CALL_SITE:
341 assert(ICS && "Expected call site!");
342 // TODO: We need to look at the operand bundles similar to the redirection
343 // in CallBase.
344 if (!ICS.hasOperandBundles())
345 if (const Function *Callee = ICS.getCalledFunction())
346 IRPositions.emplace_back(IRPosition::function(*Callee));
347 return;
348 case IRPosition::IRP_CALL_SITE_RETURNED:
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::returned(*Callee));
355 IRPositions.emplace_back(IRPosition::function(*Callee));
356 }
357 }
358 IRPositions.emplace_back(
359 IRPosition::callsite_function(cast<CallBase>(*ICS.getInstruction())));
360 return;
361 case IRPosition::IRP_CALL_SITE_ARGUMENT: {
362 int ArgNo = IRP.getArgNo();
363 assert(ICS && ArgNo >= 0 && "Expected call site!");
364 // TODO: We need to look at the operand bundles similar to the redirection
365 // in CallBase.
366 if (!ICS.hasOperandBundles()) {
367 const Function *Callee = ICS.getCalledFunction();
368 if (Callee && Callee->arg_size() > unsigned(ArgNo))
369 IRPositions.emplace_back(IRPosition::argument(*Callee->getArg(ArgNo)));
370 if (Callee)
371 IRPositions.emplace_back(IRPosition::function(*Callee));
372 }
373 IRPositions.emplace_back(IRPosition::value(IRP.getAssociatedValue()));
374 return;
375 }
376 }
377}
378
379bool IRPosition::hasAttr(ArrayRef<Attribute::AttrKind> AKs) const {
380 for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this))
381 for (Attribute::AttrKind AK : AKs)
382 if (EquivIRP.getAttr(AK).getKindAsEnum() == AK)
383 return true;
384 return false;
385}
386
387void IRPosition::getAttrs(ArrayRef<Attribute::AttrKind> AKs,
388 SmallVectorImpl<Attribute> &Attrs) const {
389 for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this))
390 for (Attribute::AttrKind AK : AKs) {
391 const Attribute &Attr = EquivIRP.getAttr(AK);
392 if (Attr.getKindAsEnum() == AK)
393 Attrs.push_back(Attr);
394 }
395}
396
397void IRPosition::verify() {
398 switch (KindOrArgNo) {
399 default:
400 assert(KindOrArgNo >= 0 && "Expected argument or call site argument!");
401 assert((isa<CallBase>(AnchorVal) || isa<Argument>(AnchorVal)) &&
402 "Expected call base or argument for positive attribute index!");
403 if (auto *Arg = dyn_cast<Argument>(AnchorVal)) {
404 assert(Arg->getArgNo() == unsigned(getArgNo()) &&
405 "Argument number mismatch!");
406 assert(Arg == &getAssociatedValue() && "Associated value mismatch!");
407 } else {
408 auto &CB = cast<CallBase>(*AnchorVal);
409 assert(CB.arg_size() > unsigned(getArgNo()) &&
410 "Call site argument number mismatch!");
411 assert(CB.getArgOperand(getArgNo()) == &getAssociatedValue() &&
412 "Associated value mismatch!");
413 }
414 break;
415 case IRP_INVALID:
416 assert(!AnchorVal && "Expected no value for an invalid position!");
417 break;
418 case IRP_FLOAT:
419 assert((!isa<CallBase>(&getAssociatedValue()) &&
420 !isa<Argument>(&getAssociatedValue())) &&
421 "Expected specialized kind for call base and argument values!");
422 break;
423 case IRP_RETURNED:
424 assert(isa<Function>(AnchorVal) &&
425 "Expected function for a 'returned' position!");
426 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
427 break;
428 case IRP_CALL_SITE_RETURNED:
429 assert((isa<CallBase>(AnchorVal)) &&
430 "Expected call base for 'call site returned' position!");
431 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
432 break;
433 case IRP_CALL_SITE:
434 assert((isa<CallBase>(AnchorVal)) &&
435 "Expected call base for 'call site function' position!");
436 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
437 break;
438 case IRP_FUNCTION:
439 assert(isa<Function>(AnchorVal) &&
440 "Expected function for a 'function' position!");
441 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
442 break;
443 }
444}
445
Stefan Stipanovic53605892019-06-27 11:27:54 +0000446/// -----------------------NoUnwind Function Attribute--------------------------
447
Johannes Doerfert344d0382019-08-07 22:34:26 +0000448struct AANoUnwindImpl : AANoUnwind {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000449 AANoUnwindImpl(const IRPosition &IRP) : AANoUnwind(IRP) {}
Stefan Stipanovic53605892019-06-27 11:27:54 +0000450
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000451 const std::string getAsStr() const override {
Stefan Stipanovic53605892019-06-27 11:27:54 +0000452 return getAssumed() ? "nounwind" : "may-unwind";
453 }
454
455 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +0000456 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic53605892019-06-27 11:27:54 +0000457};
458
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000459struct AANoUnwindFunction final : public AANoUnwindImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000460 AANoUnwindFunction(const IRPosition &IRP) : AANoUnwindImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000461
462 /// See AbstractAttribute::trackStatistics()
463 void trackStatistics() const override {
464 STATS_DECL_AND_TRACK_FN_ATTR(nounwind)
465 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000466};
467
Johannes Doerfertece81902019-08-12 22:05:53 +0000468ChangeStatus AANoUnwindImpl::updateImpl(Attributor &A) {
Stefan Stipanovic53605892019-06-27 11:27:54 +0000469
470 // The map from instruction opcodes to those instructions in the function.
Stefan Stipanovic53605892019-06-27 11:27:54 +0000471 auto Opcodes = {
472 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
473 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
474 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
475
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000476 auto CheckForNoUnwind = [&](Instruction &I) {
477 if (!I.mayThrow())
478 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000479
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000480 auto *NoUnwindAA = A.getAAFor<AANoUnwind>(*this, IRPosition::value(I));
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000481 return NoUnwindAA && NoUnwindAA->isAssumedNoUnwind();
482 };
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000483
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000484 if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes))
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000485 return indicatePessimisticFixpoint();
Stefan Stipanovic53605892019-06-27 11:27:54 +0000486
Stefan Stipanovic53605892019-06-27 11:27:54 +0000487 return ChangeStatus::UNCHANGED;
488}
489
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000490/// --------------------- Function Return Values -------------------------------
491
492/// "Attribute" that collects all potential returned values and the return
493/// instructions that they arise from.
494///
495/// If there is a unique returned value R, the manifest method will:
496/// - mark R with the "returned" attribute, if R is an argument.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000497///
498/// TODO: We should use liveness during construction of the returned values map
499/// and before we set HasOverdefinedReturnedCalls.
Johannes Doerferteccdf082019-08-05 23:35:12 +0000500class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000501
502 /// Mapping of values potentially returned by the associated function to the
503 /// return instructions that might return them.
504 DenseMap<Value *, SmallPtrSet<ReturnInst *, 2>> ReturnedValues;
505
506 /// State flags
507 ///
508 ///{
509 bool IsFixed;
510 bool IsValidState;
511 bool HasOverdefinedReturnedCalls;
512 ///}
513
514 /// Collect values that could become \p V in the set \p Values, each mapped to
515 /// \p ReturnInsts.
516 void collectValuesRecursively(
517 Attributor &A, Value *V, SmallPtrSetImpl<ReturnInst *> &ReturnInsts,
518 DenseMap<Value *, SmallPtrSet<ReturnInst *, 2>> &Values) {
519
520 visitValueCB_t<bool> VisitValueCB = [&](Value *Val, bool &) {
521 assert(!isa<Instruction>(Val) ||
522 &getAnchorScope() == cast<Instruction>(Val)->getFunction());
523 Values[Val].insert(ReturnInsts.begin(), ReturnInsts.end());
524 };
525
526 bool UnusedBool;
527 bool Success = genericValueTraversal(V, UnusedBool, VisitValueCB);
528
529 // If we did abort the above traversal we haven't see all the values.
530 // Consequently, we cannot know if the information we would derive is
531 // accurate so we give up early.
532 if (!Success)
533 indicatePessimisticFixpoint();
534 }
535
536public:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000537 AAReturnedValuesImpl(const IRPosition &IRP) : AAReturnedValues(IRP) {}
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000538
539 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +0000540 void initialize(Attributor &A) override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000541 // Reset the state.
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000542 IsFixed = false;
543 IsValidState = true;
544 HasOverdefinedReturnedCalls = false;
545 ReturnedValues.clear();
546
Johannes Doerfertbeb51502019-08-07 22:36:15 +0000547 Function &F = getAnchorScope();
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000548
549 // The map from instruction opcodes to those instructions in the function.
Johannes Doerfertece81902019-08-12 22:05:53 +0000550 auto &OpcodeInstMap = A.getInfoCache().getOpcodeInstMapForFunction(F);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000551
552 // Look through all arguments, if one is marked as returned we are done.
553 for (Argument &Arg : F.args()) {
554 if (Arg.hasReturnedAttr()) {
555
556 auto &ReturnInstSet = ReturnedValues[&Arg];
557 for (Instruction *RI : OpcodeInstMap[Instruction::Ret])
558 ReturnInstSet.insert(cast<ReturnInst>(RI));
559
560 indicateOptimisticFixpoint();
561 return;
562 }
563 }
564
565 // If no argument was marked as returned we look at all return instructions
566 // and collect potentially returned values.
567 for (Instruction *RI : OpcodeInstMap[Instruction::Ret]) {
568 SmallPtrSet<ReturnInst *, 1> RISet({cast<ReturnInst>(RI)});
569 collectValuesRecursively(A, cast<ReturnInst>(RI)->getReturnValue(), RISet,
570 ReturnedValues);
571 }
572 }
573
574 /// See AbstractAttribute::manifest(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000575 ChangeStatus manifest(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000576
577 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000578 AbstractState &getState() override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000579
580 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000581 const AbstractState &getState() const override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000582
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000583 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +0000584 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000585
586 /// Return the number of potential return values, -1 if unknown.
587 size_t getNumReturnValues() const {
588 return isValidState() ? ReturnedValues.size() : -1;
589 }
590
591 /// Return an assumed unique return value if a single candidate is found. If
592 /// there cannot be one, return a nullptr. If it is not clear yet, return the
593 /// Optional::NoneType.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000594 Optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000595
Johannes Doerfert14a04932019-08-07 22:27:24 +0000596 /// See AbstractState::checkForAllReturnedValues(...).
597 bool checkForAllReturnedValuesAndReturnInsts(
598 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
599 &Pred) const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000600
601 /// Pretty print the attribute similar to the IR representation.
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000602 const std::string getAsStr() const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000603
604 /// See AbstractState::isAtFixpoint().
605 bool isAtFixpoint() const override { return IsFixed; }
606
607 /// See AbstractState::isValidState().
608 bool isValidState() const override { return IsValidState; }
609
610 /// See AbstractState::indicateOptimisticFixpoint(...).
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000611 ChangeStatus indicateOptimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000612 IsFixed = true;
613 IsValidState &= true;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000614 return ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000615 }
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000616
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000617 ChangeStatus indicatePessimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000618 IsFixed = true;
619 IsValidState = false;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000620 return ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000621 }
622};
623
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000624struct AAReturnedValuesFunction final : public AAReturnedValuesImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000625 AAReturnedValuesFunction(const IRPosition &IRP) : AAReturnedValuesImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000626
627 /// See AbstractAttribute::trackStatistics()
628 void trackStatistics() const override {
629 STATS_DECL_AND_TRACK_ARG_ATTR(returned)
630 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000631};
632
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000633ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) {
634 ChangeStatus Changed = ChangeStatus::UNCHANGED;
635
636 // Bookkeeping.
637 assert(isValidState());
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000638 STATS_DECL_AND_TRACK(KnownReturnValues, FunctionReturn,
639 "Number of function with known return values");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000640
641 // Check if we have an assumed unique return value that we could manifest.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000642 Optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000643
644 if (!UniqueRV.hasValue() || !UniqueRV.getValue())
645 return Changed;
646
647 // Bookkeeping.
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000648 STATS_DECL_AND_TRACK(UniqueReturnValue, FunctionReturn,
649 "Number of function with unique return");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000650
651 // If the assumed unique return value is an argument, annotate it.
652 if (auto *UniqueRVArg = dyn_cast<Argument>(UniqueRV.getValue())) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000653 getIRPosition() = IRPosition::argument(*UniqueRVArg);
Johannes Doerferteccdf082019-08-05 23:35:12 +0000654 Changed = IRAttribute::manifest(A) | Changed;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000655 }
656
657 return Changed;
658}
659
660const std::string AAReturnedValuesImpl::getAsStr() const {
661 return (isAtFixpoint() ? "returns(#" : "may-return(#") +
Johannes Doerfert6471bb62019-08-04 18:39:28 +0000662 (isValidState() ? std::to_string(getNumReturnValues()) : "?") +
663 ")[OD: " + std::to_string(HasOverdefinedReturnedCalls) + "]";
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000664}
665
Johannes Doerfert14a04932019-08-07 22:27:24 +0000666Optional<Value *>
667AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const {
668 // If checkForAllReturnedValues provides a unique value, ignoring potential
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000669 // undef values that can also be present, it is assumed to be the actual
670 // return value and forwarded to the caller of this method. If there are
671 // multiple, a nullptr is returned indicating there cannot be a unique
672 // returned value.
673 Optional<Value *> UniqueRV;
674
Johannes Doerfert14a04932019-08-07 22:27:24 +0000675 auto Pred = [&](Value &RV) -> bool {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000676 // If we found a second returned value and neither the current nor the saved
677 // one is an undef, there is no unique returned value. Undefs are special
678 // since we can pretend they have any value.
679 if (UniqueRV.hasValue() && UniqueRV != &RV &&
680 !(isa<UndefValue>(RV) || isa<UndefValue>(UniqueRV.getValue()))) {
681 UniqueRV = nullptr;
682 return false;
683 }
684
685 // Do not overwrite a value with an undef.
686 if (!UniqueRV.hasValue() || !isa<UndefValue>(RV))
687 UniqueRV = &RV;
688
689 return true;
690 };
691
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000692 if (!A.checkForAllReturnedValues(Pred, *this))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000693 UniqueRV = nullptr;
694
695 return UniqueRV;
696}
697
Johannes Doerfert14a04932019-08-07 22:27:24 +0000698bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
699 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
700 &Pred) const {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000701 if (!isValidState())
702 return false;
703
704 // Check all returned values but ignore call sites as long as we have not
705 // encountered an overdefined one during an update.
706 for (auto &It : ReturnedValues) {
707 Value *RV = It.first;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000708 const SmallPtrSetImpl<ReturnInst *> &RetInsts = It.second;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000709
710 ImmutableCallSite ICS(RV);
711 if (ICS && !HasOverdefinedReturnedCalls)
712 continue;
713
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000714 if (!Pred(*RV, RetInsts))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000715 return false;
716 }
717
718 return true;
719}
720
Johannes Doerfertece81902019-08-12 22:05:53 +0000721ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000722
723 // Check if we know of any values returned by the associated function,
724 // if not, we are done.
725 if (getNumReturnValues() == 0) {
726 indicateOptimisticFixpoint();
727 return ChangeStatus::UNCHANGED;
728 }
729
730 // Check if any of the returned values is a call site we can refine.
731 decltype(ReturnedValues) AddRVs;
732 bool HasCallSite = false;
733
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000734 // Keep track of any change to trigger updates on dependent attributes.
735 ChangeStatus Changed = ChangeStatus::UNCHANGED;
736
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000737 auto *LivenessAA = A.getAAFor<AAIsDead>(*this, getIRPosition());
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000738
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000739 // Look at all returned call sites.
740 for (auto &It : ReturnedValues) {
741 SmallPtrSet<ReturnInst *, 2> &ReturnInsts = It.second;
742 Value *RV = It.first;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000743
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000744 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Potentially returned value " << *RV
745 << "\n");
746
747 // Only call sites can change during an update, ignore the rest.
748 CallSite RetCS(RV);
749 if (!RetCS)
750 continue;
751
752 // For now, any call site we see will prevent us from directly fixing the
753 // state. However, if the information on the callees is fixed, the call
754 // sites will be removed and we will fix the information for this state.
755 HasCallSite = true;
756
Johannes Doerfert4361da22019-08-04 18:38:53 +0000757 // Ignore dead ReturnValues.
758 if (LivenessAA &&
759 !LivenessAA->isLiveInstSet(ReturnInsts.begin(), ReturnInsts.end())) {
760 LLVM_DEBUG(dbgs() << "[AAReturnedValues] all returns are assumed dead, "
761 "skip it for now\n");
762 continue;
763 }
764
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000765 // Try to find a assumed unique return value for the called function.
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000766 auto *RetCSAA = A.getAAFor<AAReturnedValuesImpl>(
767 *this, IRPosition::callsite_returned(RetCS));
Johannes Doerfert0a7f4cd2019-07-13 01:09:21 +0000768 if (!RetCSAA) {
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000769 if (!HasOverdefinedReturnedCalls)
770 Changed = ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000771 HasOverdefinedReturnedCalls = true;
772 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned call site (" << *RV
773 << ") with " << (RetCSAA ? "invalid" : "no")
774 << " associated state\n");
775 continue;
776 }
777
778 // Try to find a assumed unique return value for the called function.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000779 Optional<Value *> AssumedUniqueRV = RetCSAA->getAssumedUniqueReturnValue(A);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000780
781 // If no assumed unique return value was found due to the lack of
782 // candidates, we may need to resolve more calls (through more update
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000783 // iterations) or the called function will not return. Either way, we
784 // simply stick with the call sites as return values. Because there were
785 // not multiple possibilities, we do not treat it as overdefined.
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000786 if (!AssumedUniqueRV.hasValue())
787 continue;
788
789 // If multiple, non-refinable values were found, there cannot be a unique
790 // return value for the called function. The returned call is overdefined!
791 if (!AssumedUniqueRV.getValue()) {
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000792 if (!HasOverdefinedReturnedCalls)
793 Changed = ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000794 HasOverdefinedReturnedCalls = true;
795 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned call site has multiple "
796 "potentially returned values\n");
797 continue;
798 }
799
800 LLVM_DEBUG({
801 bool UniqueRVIsKnown = RetCSAA->isAtFixpoint();
802 dbgs() << "[AAReturnedValues] Returned call site "
803 << (UniqueRVIsKnown ? "known" : "assumed")
804 << " unique return value: " << *AssumedUniqueRV << "\n";
805 });
806
807 // The assumed unique return value.
808 Value *AssumedRetVal = AssumedUniqueRV.getValue();
809
810 // If the assumed unique return value is an argument, lookup the matching
811 // call site operand and recursively collect new returned values.
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000812 // If it is not an argument, it is just put into the set of returned
813 // values as we would have already looked through casts, phis, and similar
814 // values.
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000815 if (Argument *AssumedRetArg = dyn_cast<Argument>(AssumedRetVal))
816 collectValuesRecursively(A,
817 RetCS.getArgOperand(AssumedRetArg->getArgNo()),
818 ReturnInsts, AddRVs);
819 else
820 AddRVs[AssumedRetVal].insert(ReturnInsts.begin(), ReturnInsts.end());
821 }
822
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000823 for (auto &It : AddRVs) {
824 assert(!It.second.empty() && "Entry does not add anything.");
825 auto &ReturnInsts = ReturnedValues[It.first];
826 for (ReturnInst *RI : It.second)
827 if (ReturnInsts.insert(RI).second) {
828 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Add new returned value "
829 << *It.first << " => " << *RI << "\n");
830 Changed = ChangeStatus::CHANGED;
831 }
832 }
833
834 // If there is no call site in the returned values we are done.
835 if (!HasCallSite) {
836 indicateOptimisticFixpoint();
837 return ChangeStatus::CHANGED;
838 }
839
840 return Changed;
841}
842
Stefan Stipanovic06263672019-07-11 21:37:40 +0000843/// ------------------------ NoSync Function Attribute -------------------------
844
Johannes Doerfert344d0382019-08-07 22:34:26 +0000845struct AANoSyncImpl : AANoSync {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000846 AANoSyncImpl(const IRPosition &IRP) : AANoSync(IRP) {}
Stefan Stipanovic06263672019-07-11 21:37:40 +0000847
Stefan Stipanoviccb5ecae2019-07-12 18:34:06 +0000848 const std::string getAsStr() const override {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000849 return getAssumed() ? "nosync" : "may-sync";
850 }
851
852 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +0000853 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000854
Stefan Stipanovic06263672019-07-11 21:37:40 +0000855 /// Helper function used to determine whether an instruction is non-relaxed
856 /// atomic. In other words, if an atomic instruction does not have unordered
857 /// or monotonic ordering
858 static bool isNonRelaxedAtomic(Instruction *I);
859
860 /// Helper function used to determine whether an instruction is volatile.
861 static bool isVolatile(Instruction *I);
862
Johannes Doerfertc7a1db32019-07-13 01:09:27 +0000863 /// Helper function uset to check if intrinsic is volatile (memcpy, memmove,
864 /// memset).
Stefan Stipanovic06263672019-07-11 21:37:40 +0000865 static bool isNoSyncIntrinsic(Instruction *I);
866};
867
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000868struct AANoSyncFunction final : public AANoSyncImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000869 AANoSyncFunction(const IRPosition &IRP) : AANoSyncImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000870
871 /// See AbstractAttribute::trackStatistics()
872 void trackStatistics() const override { STATS_DECL_AND_TRACK_FN_ATTR(nosync) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000873};
874
875bool AANoSyncImpl::isNonRelaxedAtomic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000876 if (!I->isAtomic())
877 return false;
878
879 AtomicOrdering Ordering;
880 switch (I->getOpcode()) {
881 case Instruction::AtomicRMW:
882 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
883 break;
884 case Instruction::Store:
885 Ordering = cast<StoreInst>(I)->getOrdering();
886 break;
887 case Instruction::Load:
888 Ordering = cast<LoadInst>(I)->getOrdering();
889 break;
890 case Instruction::Fence: {
891 auto *FI = cast<FenceInst>(I);
892 if (FI->getSyncScopeID() == SyncScope::SingleThread)
893 return false;
894 Ordering = FI->getOrdering();
895 break;
896 }
897 case Instruction::AtomicCmpXchg: {
898 AtomicOrdering Success = cast<AtomicCmpXchgInst>(I)->getSuccessOrdering();
899 AtomicOrdering Failure = cast<AtomicCmpXchgInst>(I)->getFailureOrdering();
900 // Only if both are relaxed, than it can be treated as relaxed.
901 // Otherwise it is non-relaxed.
902 if (Success != AtomicOrdering::Unordered &&
903 Success != AtomicOrdering::Monotonic)
904 return true;
905 if (Failure != AtomicOrdering::Unordered &&
906 Failure != AtomicOrdering::Monotonic)
907 return true;
908 return false;
909 }
910 default:
911 llvm_unreachable(
912 "New atomic operations need to be known in the attributor.");
913 }
914
915 // Relaxed.
916 if (Ordering == AtomicOrdering::Unordered ||
917 Ordering == AtomicOrdering::Monotonic)
918 return false;
919 return true;
920}
921
922/// Checks if an intrinsic is nosync. Currently only checks mem* intrinsics.
923/// FIXME: We should ipmrove the handling of intrinsics.
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000924bool AANoSyncImpl::isNoSyncIntrinsic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000925 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
926 switch (II->getIntrinsicID()) {
927 /// Element wise atomic memory intrinsics are can only be unordered,
928 /// therefore nosync.
929 case Intrinsic::memset_element_unordered_atomic:
930 case Intrinsic::memmove_element_unordered_atomic:
931 case Intrinsic::memcpy_element_unordered_atomic:
932 return true;
933 case Intrinsic::memset:
934 case Intrinsic::memmove:
935 case Intrinsic::memcpy:
936 if (!cast<MemIntrinsic>(II)->isVolatile())
937 return true;
938 return false;
939 default:
940 return false;
941 }
942 }
943 return false;
944}
945
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000946bool AANoSyncImpl::isVolatile(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000947 assert(!ImmutableCallSite(I) && !isa<CallBase>(I) &&
948 "Calls should not be checked here");
949
950 switch (I->getOpcode()) {
951 case Instruction::AtomicRMW:
952 return cast<AtomicRMWInst>(I)->isVolatile();
953 case Instruction::Store:
954 return cast<StoreInst>(I)->isVolatile();
955 case Instruction::Load:
956 return cast<LoadInst>(I)->isVolatile();
957 case Instruction::AtomicCmpXchg:
958 return cast<AtomicCmpXchgInst>(I)->isVolatile();
959 default:
960 return false;
961 }
962}
963
Johannes Doerfertece81902019-08-12 22:05:53 +0000964ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000965
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000966 auto CheckRWInstForNoSync = [&](Instruction &I) {
967 /// We are looking for volatile instructions or Non-Relaxed atomics.
968 /// FIXME: We should ipmrove the handling of intrinsics.
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000969
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000970 if (isa<IntrinsicInst>(&I) && isNoSyncIntrinsic(&I))
971 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000972
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000973 if (ImmutableCallSite ICS = ImmutableCallSite(&I)) {
974 if (ICS.hasFnAttr(Attribute::NoSync))
975 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000976
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000977 auto *NoSyncAA =
978 A.getAAFor<AANoSyncImpl>(*this, IRPosition::callsite_function(ICS));
979 if (NoSyncAA && NoSyncAA->isAssumedNoSync())
980 return true;
981 return false;
982 }
Stefan Stipanovic06263672019-07-11 21:37:40 +0000983
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000984 if (!isVolatile(&I) && !isNonRelaxedAtomic(&I))
985 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000986
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000987 return false;
988 };
Stefan Stipanovic06263672019-07-11 21:37:40 +0000989
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000990 auto CheckForNoSync = [&](Instruction &I) {
991 // At this point we handled all read/write effects and they are all
992 // nosync, so they can be skipped.
993 if (I.mayReadOrWriteMemory())
994 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000995
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000996 // non-convergent and readnone imply nosync.
997 return !ImmutableCallSite(&I).isConvergent();
998 };
Stefan Stipanovic06263672019-07-11 21:37:40 +0000999
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001000 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this) ||
1001 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001002 return indicatePessimisticFixpoint();
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001003
Stefan Stipanovic06263672019-07-11 21:37:40 +00001004 return ChangeStatus::UNCHANGED;
1005}
1006
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001007/// ------------------------ No-Free Attributes ----------------------------
1008
Johannes Doerfert344d0382019-08-07 22:34:26 +00001009struct AANoFreeImpl : public AANoFree {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001010 AANoFreeImpl(const IRPosition &IRP) : AANoFree(IRP) {}
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001011
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001012 /// See AbstractAttribute::getAsStr().
1013 const std::string getAsStr() const override {
1014 return getAssumed() ? "nofree" : "may-free";
1015 }
1016
1017 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001018 ChangeStatus updateImpl(Attributor &A) override;
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001019};
1020
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001021struct AANoFreeFunction final : public AANoFreeImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001022 AANoFreeFunction(const IRPosition &IRP) : AANoFreeImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001023
1024 /// See AbstractAttribute::trackStatistics()
1025 void trackStatistics() const override { STATS_DECL_AND_TRACK_FN_ATTR(nofree) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001026};
1027
Johannes Doerfertece81902019-08-12 22:05:53 +00001028ChangeStatus AANoFreeImpl::updateImpl(Attributor &A) {
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001029
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001030 auto CheckForNoFree = [&](Instruction &I) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001031 ImmutableCallSite ICS(&I);
1032 if (ICS.hasFnAttr(Attribute::NoFree))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001033 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001034
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001035 auto *NoFreeAA =
1036 A.getAAFor<AANoFreeImpl>(*this, IRPosition::callsite_function(ICS));
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001037 return NoFreeAA && NoFreeAA->isAssumedNoFree();
1038 };
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001039
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001040 if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001041 return indicatePessimisticFixpoint();
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001042 return ChangeStatus::UNCHANGED;
1043}
1044
Hideto Ueno54869ec2019-07-15 06:49:04 +00001045/// ------------------------ NonNull Argument Attribute ------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00001046struct AANonNullImpl : AANonNull {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001047 AANonNullImpl(const IRPosition &IRP) : AANonNull(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001048
Hideto Ueno54869ec2019-07-15 06:49:04 +00001049 /// See AbstractAttribute::getAsStr().
1050 const std::string getAsStr() const override {
1051 return getAssumed() ? "nonnull" : "may-null";
1052 }
1053
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001054 /// See AbstractAttribute::initialize(...).
1055 void initialize(Attributor &A) override {
1056 if (hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
1057 indicateOptimisticFixpoint();
1058 }
1059
Hideto Ueno54869ec2019-07-15 06:49:04 +00001060 /// Generate a predicate that checks if a given value is assumed nonnull.
1061 /// The generated function returns true if a value satisfies any of
1062 /// following conditions.
1063 /// (i) A value is known nonZero(=nonnull).
1064 /// (ii) A value is associated with AANonNull and its isAssumedNonNull() is
1065 /// true.
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001066 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
1067 generatePredicate(Attributor &);
Hideto Ueno54869ec2019-07-15 06:49:04 +00001068};
1069
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001070std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
1071AANonNullImpl::generatePredicate(Attributor &A) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001072 // FIXME: The `AAReturnedValues` should provide the predicate with the
1073 // `ReturnInst` vector as well such that we can use the control flow sensitive
1074 // version of `isKnownNonZero`. This should fix `test11` in
1075 // `test/Transforms/FunctionAttrs/nonnull.ll`
1076
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001077 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
1078 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &RetInsts) -> bool {
Johannes Doerfert26e58462019-08-12 22:21:09 +00001079 if (isKnownNonZero(&RV, A.getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001080 return true;
1081
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001082 if (ImmutableCallSite ICS = ImmutableCallSite(&RV))
1083 if (ICS.hasRetAttr(Attribute::NonNull))
1084 return true;
Hideto Ueno54869ec2019-07-15 06:49:04 +00001085
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001086 auto *NonNullAA = A.getAAFor<AANonNull>(*this, IRPosition::value(RV));
1087 return (NonNullAA && NonNullAA->isAssumedNonNull());
Hideto Ueno54869ec2019-07-15 06:49:04 +00001088 };
1089
1090 return Pred;
1091}
1092
1093/// NonNull attribute for function return value.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001094struct AANonNullReturned final : AANonNullImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001095 AANonNullReturned(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001096
1097 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001098 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001099
1100 /// See AbstractAttribute::trackStatistics()
1101 void trackStatistics() const override {
1102 STATS_DECL_AND_TRACK_FNRET_ATTR(nonnull)
1103 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001104};
1105
Johannes Doerfertece81902019-08-12 22:05:53 +00001106ChangeStatus AANonNullReturned::updateImpl(Attributor &A) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001107
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001108 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
1109 this->generatePredicate(A);
1110
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001111 if (!A.checkForAllReturnedValuesAndReturnInsts(Pred, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001112 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001113 return ChangeStatus::UNCHANGED;
1114}
1115
1116/// NonNull attribute for function argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001117struct AANonNullArgument final : AANonNullImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001118 AANonNullArgument(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001119
1120 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001121 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001122
1123 /// See AbstractAttribute::trackStatistics()
1124 void trackStatistics() const override {
1125 STATS_DECL_AND_TRACK_ARG_ATTR(nonnull)
1126 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001127};
1128
1129/// NonNull attribute for a call site argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001130struct AANonNullCallSiteArgument final : AANonNullImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001131 AANonNullCallSiteArgument(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001132
1133 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001134 void initialize(Attributor &A) override {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001135 AANonNullImpl::initialize(A);
1136 if (!isKnownNonNull() &&
1137 isKnownNonZero(&getAssociatedValue(), A.getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001138 indicateOptimisticFixpoint();
1139 }
1140
1141 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00001142 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001143
1144 /// See AbstractAttribute::trackStatistics()
1145 void trackStatistics() const override {
1146 STATS_DECL_AND_TRACK_CSARG_ATTR(nonnull)
1147 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001148};
Johannes Doerfert007153e2019-08-05 23:26:06 +00001149
Johannes Doerfertece81902019-08-12 22:05:53 +00001150ChangeStatus AANonNullArgument::updateImpl(Attributor &A) {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001151 unsigned ArgNo = getArgNo();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001152
1153 // Callback function
1154 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) {
1155 assert(CS && "Sanity check: Call site was not initialized properly!");
1156
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001157 IRPosition CSArgPos = IRPosition::callsite_argument(CS, ArgNo);
1158 if (CSArgPos.hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
1159 return true;
Hideto Ueno54869ec2019-07-15 06:49:04 +00001160
1161 // Check that NonNullAA is AANonNullCallSiteArgument.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001162 if (auto *NonNullAA = A.getAAFor<AANonNullImpl>(*this, CSArgPos)) {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001163 ImmutableCallSite ICS(&NonNullAA->getAnchorValue());
Hideto Ueno54869ec2019-07-15 06:49:04 +00001164 if (ICS && CS.getInstruction() == ICS.getInstruction())
1165 return NonNullAA->isAssumedNonNull();
1166 return false;
1167 }
1168
Hideto Ueno54869ec2019-07-15 06:49:04 +00001169 Value *V = CS.getArgOperand(ArgNo);
Johannes Doerfert26e58462019-08-12 22:21:09 +00001170 if (isKnownNonZero(V, A.getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001171 return true;
1172
1173 return false;
1174 };
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001175 if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001176 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001177 return ChangeStatus::UNCHANGED;
1178}
1179
Johannes Doerfertece81902019-08-12 22:05:53 +00001180ChangeStatus AANonNullCallSiteArgument::updateImpl(Attributor &A) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001181 // NOTE: Never look at the argument of the callee in this method.
1182 // If we do this, "nonnull" is always deduced because of the assumption.
1183
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001184 Value &V = getAssociatedValue();
1185 auto *NonNullAA = A.getAAFor<AANonNull>(*this, IRPosition::value(V));
Hideto Ueno54869ec2019-07-15 06:49:04 +00001186
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001187 if (!NonNullAA || !NonNullAA->isAssumedNonNull())
1188 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001189
1190 return ChangeStatus::UNCHANGED;
1191}
1192
Hideto Ueno11d37102019-07-17 15:15:43 +00001193/// ------------------------ Will-Return Attributes ----------------------------
1194
Johannes Doerfert344d0382019-08-07 22:34:26 +00001195struct AAWillReturnImpl : public AAWillReturn {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001196 AAWillReturnImpl(const IRPosition &IRP) : AAWillReturn(IRP) {}
Hideto Ueno11d37102019-07-17 15:15:43 +00001197
Hideto Ueno11d37102019-07-17 15:15:43 +00001198 /// See AbstractAttribute::getAsStr()
1199 const std::string getAsStr() const override {
1200 return getAssumed() ? "willreturn" : "may-noreturn";
1201 }
1202};
1203
1204struct AAWillReturnFunction final : AAWillReturnImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001205 AAWillReturnFunction(const IRPosition &IRP) : AAWillReturnImpl(IRP) {}
Hideto Ueno11d37102019-07-17 15:15:43 +00001206
1207 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001208 void initialize(Attributor &A) override;
Hideto Ueno11d37102019-07-17 15:15:43 +00001209
1210 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001211 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001212
1213 /// See AbstractAttribute::trackStatistics()
1214 void trackStatistics() const override {
1215 STATS_DECL_AND_TRACK_FN_ATTR(willreturn)
1216 }
Hideto Ueno11d37102019-07-17 15:15:43 +00001217};
1218
1219// Helper function that checks whether a function has any cycle.
1220// TODO: Replace with more efficent code
1221bool containsCycle(Function &F) {
1222 SmallPtrSet<BasicBlock *, 32> Visited;
1223
1224 // Traverse BB by dfs and check whether successor is already visited.
1225 for (BasicBlock *BB : depth_first(&F)) {
1226 Visited.insert(BB);
1227 for (auto *SuccBB : successors(BB)) {
1228 if (Visited.count(SuccBB))
1229 return true;
1230 }
1231 }
1232 return false;
1233}
1234
1235// Helper function that checks the function have a loop which might become an
1236// endless loop
1237// FIXME: Any cycle is regarded as endless loop for now.
1238// We have to allow some patterns.
1239bool containsPossiblyEndlessLoop(Function &F) { return containsCycle(F); }
1240
Johannes Doerfertece81902019-08-12 22:05:53 +00001241void AAWillReturnFunction::initialize(Attributor &A) {
Hideto Ueno11d37102019-07-17 15:15:43 +00001242 Function &F = getAnchorScope();
1243
1244 if (containsPossiblyEndlessLoop(F))
1245 indicatePessimisticFixpoint();
1246}
1247
Johannes Doerfertece81902019-08-12 22:05:53 +00001248ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A) {
Hideto Ueno11d37102019-07-17 15:15:43 +00001249 // The map from instruction opcodes to those instructions in the function.
Hideto Ueno11d37102019-07-17 15:15:43 +00001250
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001251 auto CheckForWillReturn = [&](Instruction &I) {
1252 ImmutableCallSite ICS(&I);
1253 if (ICS.hasFnAttr(Attribute::WillReturn))
1254 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001255
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001256 IRPosition IPos = IRPosition::callsite_function(ICS);
1257 auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, IPos);
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001258 if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn())
1259 return false;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001260
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001261 // FIXME: Prohibit any recursion for now.
1262 if (ICS.hasFnAttr(Attribute::NoRecurse))
1263 return true;
Hideto Ueno11d37102019-07-17 15:15:43 +00001264
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001265 auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, IPos);
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001266 return NoRecurseAA && NoRecurseAA->isAssumedNoRecurse();
1267 };
Hideto Ueno11d37102019-07-17 15:15:43 +00001268
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001269 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001270 return indicatePessimisticFixpoint();
Hideto Ueno11d37102019-07-17 15:15:43 +00001271
1272 return ChangeStatus::UNCHANGED;
1273}
1274
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001275/// ------------------------ NoAlias Argument Attribute ------------------------
1276
Johannes Doerfert344d0382019-08-07 22:34:26 +00001277struct AANoAliasImpl : AANoAlias {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001278 AANoAliasImpl(const IRPosition &IRP) : AANoAlias(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001279
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001280 const std::string getAsStr() const override {
1281 return getAssumed() ? "noalias" : "may-alias";
1282 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001283};
1284
1285/// NoAlias attribute for function return value.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001286struct AANoAliasReturned final : AANoAliasImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001287 AANoAliasReturned(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001288
1289 /// See AbstractAttriubute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001290 void initialize(Attributor &A) override {
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001291 Function &F = getAnchorScope();
1292
1293 // Already noalias.
1294 if (F.returnDoesNotAlias()) {
1295 indicateOptimisticFixpoint();
1296 return;
1297 }
1298 }
1299
1300 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001301 virtual ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001302
1303 /// See AbstractAttribute::trackStatistics()
1304 void trackStatistics() const override {
1305 STATS_DECL_AND_TRACK_FNRET_ATTR(noalias)
1306 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001307};
1308
Johannes Doerfertece81902019-08-12 22:05:53 +00001309ChangeStatus AANoAliasReturned::updateImpl(Attributor &A) {
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001310
Johannes Doerfert14a04932019-08-07 22:27:24 +00001311 auto CheckReturnValue = [&](Value &RV) -> bool {
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001312 if (Constant *C = dyn_cast<Constant>(&RV))
1313 if (C->isNullValue() || isa<UndefValue>(C))
1314 return true;
1315
1316 /// For now, we can only deduce noalias if we have call sites.
1317 /// FIXME: add more support.
1318 ImmutableCallSite ICS(&RV);
1319 if (!ICS)
1320 return false;
1321
Johannes Doerfert14a04932019-08-07 22:27:24 +00001322 if (!ICS.returnDoesNotAlias()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001323 auto *NoAliasAA =
1324 A.getAAFor<AANoAlias>(*this, IRPosition::callsite_returned(ICS));
Johannes Doerfert14a04932019-08-07 22:27:24 +00001325 if (!NoAliasAA || !NoAliasAA->isAssumedNoAlias())
1326 return false;
1327 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001328
1329 /// FIXME: We can improve capture check in two ways:
1330 /// 1. Use the AANoCapture facilities.
1331 /// 2. Use the location of return insts for escape queries.
1332 if (PointerMayBeCaptured(&RV, /* ReturnCaptures */ false,
1333 /* StoreCaptures */ true))
1334 return false;
1335
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001336 return true;
1337 };
1338
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001339 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001340 return indicatePessimisticFixpoint();
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001341
1342 return ChangeStatus::UNCHANGED;
1343}
1344
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001345/// -------------------AAIsDead Function Attribute-----------------------
1346
Johannes Doerfert344d0382019-08-07 22:34:26 +00001347struct AAIsDeadImpl : public AAIsDead {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001348 AAIsDeadImpl(const IRPosition &IRP) : AAIsDead(IRP) {}
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001349
Johannes Doerfertece81902019-08-12 22:05:53 +00001350 void initialize(Attributor &A) override {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001351 const Function &F = getAnchorScope();
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001352
1353 ToBeExploredPaths.insert(&(F.getEntryBlock().front()));
1354 AssumedLiveBlocks.insert(&(F.getEntryBlock()));
1355 for (size_t i = 0; i < ToBeExploredPaths.size(); ++i)
Johannes Doerfert4361da22019-08-04 18:38:53 +00001356 if (const Instruction *NextNoReturnI =
1357 findNextNoReturn(A, ToBeExploredPaths[i]))
1358 NoReturnCalls.insert(NextNoReturnI);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001359 }
1360
Johannes Doerfert4361da22019-08-04 18:38:53 +00001361 /// Find the next assumed noreturn instruction in the block of \p I starting
1362 /// from, thus including, \p I.
1363 ///
1364 /// The caller is responsible to monitor the ToBeExploredPaths set as new
1365 /// instructions discovered in other basic block will be placed in there.
1366 ///
1367 /// \returns The next assumed noreturn instructions in the block of \p I
1368 /// starting from, thus including, \p I.
1369 const Instruction *findNextNoReturn(Attributor &A, const Instruction *I);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001370
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001371 /// See AbstractAttribute::getAsStr().
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001372 const std::string getAsStr() const override {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001373 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
1374 std::to_string(getAnchorScope().size()) + "][#NRI " +
1375 std::to_string(NoReturnCalls.size()) + "]";
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001376 }
1377
1378 /// See AbstractAttribute::manifest(...).
1379 ChangeStatus manifest(Attributor &A) override {
1380 assert(getState().isValidState() &&
1381 "Attempted to manifest an invalid state!");
1382
1383 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Johannes Doerfert924d2132019-08-05 21:34:45 +00001384 const Function &F = getAnchorScope();
1385
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001386 // Flag to determine if we can change an invoke to a call assuming the
1387 // callee is nounwind. This is not possible if the personality of the
1388 // function allows to catch asynchronous exceptions.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001389 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001390
Johannes Doerfert4361da22019-08-04 18:38:53 +00001391 for (const Instruction *NRC : NoReturnCalls) {
1392 Instruction *I = const_cast<Instruction *>(NRC);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001393 BasicBlock *BB = I->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001394 Instruction *SplitPos = I->getNextNode();
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001395
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001396 if (auto *II = dyn_cast<InvokeInst>(I)) {
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001397 // If we keep the invoke the split position is at the beginning of the
1398 // normal desitination block (it invokes a noreturn function after all).
1399 BasicBlock *NormalDestBB = II->getNormalDest();
1400 SplitPos = &NormalDestBB->front();
1401
Johannes Doerfert4361da22019-08-04 18:38:53 +00001402 /// Invoke is replaced with a call and unreachable is placed after it if
1403 /// the callee is nounwind and noreturn. Otherwise, we keep the invoke
1404 /// and only place an unreachable in the normal successor.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001405 if (Invoke2CallAllowed) {
1406 if (Function *Callee = II->getCalledFunction()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001407 auto *AANoUnw =
1408 A.getAAFor<AANoUnwind>(*this, IRPosition::function(*Callee));
Johannes Doerfert924d2132019-08-05 21:34:45 +00001409 if (Callee->hasFnAttribute(Attribute::NoUnwind) ||
1410 (AANoUnw && AANoUnw->isAssumedNoUnwind())) {
1411 LLVM_DEBUG(dbgs()
1412 << "[AAIsDead] Replace invoke with call inst\n");
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001413 // We do not need an invoke (II) but instead want a call followed
1414 // by an unreachable. However, we do not remove II as other
1415 // abstract attributes might have it cached as part of their
1416 // results. Given that we modify the CFG anyway, we simply keep II
1417 // around but in a new dead block. To avoid II being live through
1418 // a different edge we have to ensure the block we place it in is
1419 // only reached from the current block of II and then not reached
1420 // at all when we insert the unreachable.
1421 SplitBlockPredecessors(NormalDestBB, {BB}, ".i2c");
1422 CallInst *CI = createCallMatchingInvoke(II);
1423 CI->insertBefore(II);
1424 CI->takeName(II);
1425 II->replaceAllUsesWith(CI);
1426 SplitPos = CI->getNextNode();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001427 }
Johannes Doerfert4361da22019-08-04 18:38:53 +00001428 }
1429 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001430 }
1431
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001432 BB = SplitPos->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001433 SplitBlock(BB, SplitPos);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001434 changeToUnreachable(BB->getTerminator(), /* UseLLVMTrap */ false);
1435 HasChanged = ChangeStatus::CHANGED;
1436 }
1437
1438 return HasChanged;
1439 }
1440
1441 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001442 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001443
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001444 /// See AAIsDead::isAssumedDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001445 bool isAssumedDead(const BasicBlock *BB) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001446 assert(BB->getParent() == &getAnchorScope() &&
1447 "BB must be in the same anchor scope function.");
1448
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001449 if (!getAssumed())
1450 return false;
1451 return !AssumedLiveBlocks.count(BB);
1452 }
1453
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001454 /// See AAIsDead::isKnownDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001455 bool isKnownDead(const BasicBlock *BB) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001456 return getKnown() && isAssumedDead(BB);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001457 }
1458
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001459 /// See AAIsDead::isAssumed(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001460 bool isAssumedDead(const Instruction *I) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001461 assert(I->getParent()->getParent() == &getAnchorScope() &&
1462 "Instruction must be in the same anchor scope function.");
1463
Stefan Stipanovic7849e412019-08-03 15:27:41 +00001464 if (!getAssumed())
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001465 return false;
1466
1467 // If it is not in AssumedLiveBlocks then it for sure dead.
1468 // Otherwise, it can still be after noreturn call in a live block.
1469 if (!AssumedLiveBlocks.count(I->getParent()))
1470 return true;
1471
1472 // If it is not after a noreturn call, than it is live.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001473 return isAfterNoReturn(I);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001474 }
1475
1476 /// See AAIsDead::isKnownDead(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001477 bool isKnownDead(const Instruction *I) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001478 return getKnown() && isAssumedDead(I);
1479 }
1480
1481 /// Check if instruction is after noreturn call, in other words, assumed dead.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001482 bool isAfterNoReturn(const Instruction *I) const;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001483
Johannes Doerfert924d2132019-08-05 21:34:45 +00001484 /// Determine if \p F might catch asynchronous exceptions.
1485 static bool mayCatchAsynchronousExceptions(const Function &F) {
1486 return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F);
1487 }
1488
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001489 /// Collection of to be explored paths.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001490 SmallSetVector<const Instruction *, 8> ToBeExploredPaths;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001491
1492 /// Collection of all assumed live BasicBlocks.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001493 DenseSet<const BasicBlock *> AssumedLiveBlocks;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001494
1495 /// Collection of calls with noreturn attribute, assumed or knwon.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001496 SmallSetVector<const Instruction *, 4> NoReturnCalls;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001497};
1498
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001499struct AAIsDeadFunction final : public AAIsDeadImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001500 AAIsDeadFunction(const IRPosition &IRP) : AAIsDeadImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001501
1502 /// See AbstractAttribute::trackStatistics()
1503 void trackStatistics() const override {
1504 STATS_DECL(DeadBlocks, Function,
1505 "Number of basic blocks classified as dead");
1506 BUILD_STAT_NAME(DeadBlocks, Function) +=
1507 getAnchorScope().size() - AssumedLiveBlocks.size();
1508 STATS_DECL(PartiallyDeadBlocks, Function,
1509 "Number of basic blocks classified as partially dead");
1510 BUILD_STAT_NAME(PartiallyDeadBlocks, Function) += NoReturnCalls.size();
1511 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001512};
1513
1514bool AAIsDeadImpl::isAfterNoReturn(const Instruction *I) const {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001515 const Instruction *PrevI = I->getPrevNode();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001516 while (PrevI) {
1517 if (NoReturnCalls.count(PrevI))
1518 return true;
1519 PrevI = PrevI->getPrevNode();
1520 }
1521 return false;
1522}
1523
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001524const Instruction *AAIsDeadImpl::findNextNoReturn(Attributor &A,
1525 const Instruction *I) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001526 const BasicBlock *BB = I->getParent();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001527 const Function &F = *BB->getParent();
1528
1529 // Flag to determine if we can change an invoke to a call assuming the callee
1530 // is nounwind. This is not possible if the personality of the function allows
1531 // to catch asynchronous exceptions.
1532 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001533
1534 // TODO: We should have a function that determines if an "edge" is dead.
1535 // Edges could be from an instruction to the next or from a terminator
1536 // to the successor. For now, we need to special case the unwind block
1537 // of InvokeInst below.
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001538
1539 while (I) {
1540 ImmutableCallSite ICS(I);
1541
1542 if (ICS) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001543 const IRPosition &IPos = IRPosition::callsite_function(ICS);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001544 // Regarless of the no-return property of an invoke instruction we only
1545 // learn that the regular successor is not reachable through this
1546 // instruction but the unwind block might still be.
1547 if (auto *Invoke = dyn_cast<InvokeInst>(I)) {
1548 // Use nounwind to justify the unwind block is dead as well.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001549 auto *AANoUnw = A.getAAFor<AANoUnwind>(*this, IPos);
Johannes Doerfert924d2132019-08-05 21:34:45 +00001550 if (!Invoke2CallAllowed ||
1551 (!AANoUnw || !AANoUnw->isAssumedNoUnwind())) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001552 AssumedLiveBlocks.insert(Invoke->getUnwindDest());
1553 ToBeExploredPaths.insert(&Invoke->getUnwindDest()->front());
1554 }
1555 }
1556
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001557 auto *NoReturnAA = A.getAAFor<AANoReturn>(*this, IPos);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001558 if (ICS.hasFnAttr(Attribute::NoReturn) ||
1559 (NoReturnAA && NoReturnAA->isAssumedNoReturn()))
1560 return I;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001561 }
1562
1563 I = I->getNextNode();
1564 }
1565
1566 // get new paths (reachable blocks).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001567 for (const BasicBlock *SuccBB : successors(BB)) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001568 AssumedLiveBlocks.insert(SuccBB);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001569 ToBeExploredPaths.insert(&SuccBB->front());
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001570 }
1571
Johannes Doerfert4361da22019-08-04 18:38:53 +00001572 // No noreturn instruction found.
1573 return nullptr;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001574}
1575
Johannes Doerfertece81902019-08-12 22:05:53 +00001576ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001577 // Temporary collection to iterate over existing noreturn instructions. This
1578 // will alow easier modification of NoReturnCalls collection
Johannes Doerfert4361da22019-08-04 18:38:53 +00001579 SmallVector<const Instruction *, 8> NoReturnChanged;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001580 ChangeStatus Status = ChangeStatus::UNCHANGED;
1581
Johannes Doerfert4361da22019-08-04 18:38:53 +00001582 for (const Instruction *I : NoReturnCalls)
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001583 NoReturnChanged.push_back(I);
1584
Johannes Doerfert4361da22019-08-04 18:38:53 +00001585 for (const Instruction *I : NoReturnChanged) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001586 size_t Size = ToBeExploredPaths.size();
1587
Johannes Doerfert4361da22019-08-04 18:38:53 +00001588 const Instruction *NextNoReturnI = findNextNoReturn(A, I);
1589 if (NextNoReturnI != I) {
1590 Status = ChangeStatus::CHANGED;
1591 NoReturnCalls.remove(I);
1592 if (NextNoReturnI)
1593 NoReturnCalls.insert(NextNoReturnI);
1594 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001595
Johannes Doerfert4361da22019-08-04 18:38:53 +00001596 // Explore new paths.
1597 while (Size != ToBeExploredPaths.size()) {
1598 Status = ChangeStatus::CHANGED;
1599 if (const Instruction *NextNoReturnI =
1600 findNextNoReturn(A, ToBeExploredPaths[Size++]))
1601 NoReturnCalls.insert(NextNoReturnI);
1602 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001603 }
1604
Hideto Ueno19c07af2019-07-23 08:16:17 +00001605 LLVM_DEBUG(
1606 dbgs() << "[AAIsDead] AssumedLiveBlocks: " << AssumedLiveBlocks.size()
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001607 << " Total number of blocks: " << getAnchorScope().size() << "\n");
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001608
Johannes Doerfertd6207812019-08-07 22:32:38 +00001609 // If we know everything is live there is no need to query for liveness.
1610 if (NoReturnCalls.empty() &&
1611 getAnchorScope().size() == AssumedLiveBlocks.size()) {
1612 // Indicating a pessimistic fixpoint will cause the state to be "invalid"
1613 // which will cause the Attributor to not return the AAIsDead on request,
1614 // which will prevent us from querying isAssumedDead().
1615 indicatePessimisticFixpoint();
1616 assert(!isValidState() && "Expected an invalid state!");
1617 }
1618
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001619 return Status;
1620}
1621
Hideto Ueno19c07af2019-07-23 08:16:17 +00001622/// -------------------- Dereferenceable Argument Attribute --------------------
1623
1624struct DerefState : AbstractState {
1625
1626 /// State representing for dereferenceable bytes.
1627 IntegerState DerefBytesState;
1628
1629 /// State representing that whether the value is nonnull or global.
1630 IntegerState NonNullGlobalState;
1631
1632 /// Bits encoding for NonNullGlobalState.
1633 enum {
1634 DEREF_NONNULL = 1 << 0,
1635 DEREF_GLOBAL = 1 << 1,
1636 };
1637
1638 /// See AbstractState::isValidState()
1639 bool isValidState() const override { return DerefBytesState.isValidState(); }
1640
Johannes Doerfertb6acee52019-08-04 17:55:15 +00001641 /// See AbstractState::isAtFixpoint()
Hideto Ueno19c07af2019-07-23 08:16:17 +00001642 bool isAtFixpoint() const override {
Johannes Doerfertb6acee52019-08-04 17:55:15 +00001643 return !isValidState() || (DerefBytesState.isAtFixpoint() &&
1644 NonNullGlobalState.isAtFixpoint());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001645 }
1646
1647 /// See AbstractState::indicateOptimisticFixpoint(...)
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001648 ChangeStatus indicateOptimisticFixpoint() override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001649 DerefBytesState.indicateOptimisticFixpoint();
1650 NonNullGlobalState.indicateOptimisticFixpoint();
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001651 return ChangeStatus::UNCHANGED;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001652 }
1653
1654 /// See AbstractState::indicatePessimisticFixpoint(...)
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001655 ChangeStatus indicatePessimisticFixpoint() override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001656 DerefBytesState.indicatePessimisticFixpoint();
1657 NonNullGlobalState.indicatePessimisticFixpoint();
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001658 return ChangeStatus::CHANGED;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001659 }
1660
1661 /// Update known dereferenceable bytes.
1662 void takeKnownDerefBytesMaximum(uint64_t Bytes) {
1663 DerefBytesState.takeKnownMaximum(Bytes);
1664 }
1665
1666 /// Update assumed dereferenceable bytes.
1667 void takeAssumedDerefBytesMinimum(uint64_t Bytes) {
1668 DerefBytesState.takeAssumedMinimum(Bytes);
1669 }
1670
1671 /// Update assumed NonNullGlobalState
1672 void updateAssumedNonNullGlobalState(bool IsNonNull, bool IsGlobal) {
1673 if (!IsNonNull)
1674 NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
1675 if (!IsGlobal)
1676 NonNullGlobalState.removeAssumedBits(DEREF_GLOBAL);
1677 }
1678
1679 /// Equality for DerefState.
1680 bool operator==(const DerefState &R) {
1681 return this->DerefBytesState == R.DerefBytesState &&
1682 this->NonNullGlobalState == R.NonNullGlobalState;
1683 }
1684};
Hideto Ueno19c07af2019-07-23 08:16:17 +00001685
Johannes Doerferteccdf082019-08-05 23:35:12 +00001686struct AADereferenceableImpl : AADereferenceable, DerefState {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001687 AADereferenceableImpl(const IRPosition &IRP) : AADereferenceable(IRP) {}
Johannes Doerfert344d0382019-08-07 22:34:26 +00001688 using StateType = DerefState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001689
1690 /// See AbstractAttribute::getState()
1691 /// {
Johannes Doerfert344d0382019-08-07 22:34:26 +00001692 StateType &getState() override { return *this; }
1693 const StateType &getState() const override { return *this; }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001694 /// }
1695
1696 /// See AADereferenceable::getAssumedDereferenceableBytes().
1697 uint32_t getAssumedDereferenceableBytes() const override {
1698 return DerefBytesState.getAssumed();
1699 }
1700
1701 /// See AADereferenceable::getKnownDereferenceableBytes().
1702 uint32_t getKnownDereferenceableBytes() const override {
1703 return DerefBytesState.getKnown();
1704 }
1705
1706 // Helper function for syncing nonnull state.
1707 void syncNonNull(const AANonNull *NonNullAA) {
1708 if (!NonNullAA) {
1709 NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
1710 return;
1711 }
1712
1713 if (NonNullAA->isKnownNonNull())
1714 NonNullGlobalState.addKnownBits(DEREF_NONNULL);
1715
1716 if (!NonNullAA->isAssumedNonNull())
1717 NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
1718 }
1719
1720 /// See AADereferenceable::isAssumedGlobal().
1721 bool isAssumedGlobal() const override {
1722 return NonNullGlobalState.isAssumed(DEREF_GLOBAL);
1723 }
1724
1725 /// See AADereferenceable::isKnownGlobal().
1726 bool isKnownGlobal() const override {
1727 return NonNullGlobalState.isKnown(DEREF_GLOBAL);
1728 }
1729
1730 /// See AADereferenceable::isAssumedNonNull().
1731 bool isAssumedNonNull() const override {
1732 return NonNullGlobalState.isAssumed(DEREF_NONNULL);
1733 }
1734
1735 /// See AADereferenceable::isKnownNonNull().
1736 bool isKnownNonNull() const override {
1737 return NonNullGlobalState.isKnown(DEREF_NONNULL);
1738 }
1739
Johannes Doerferteccdf082019-08-05 23:35:12 +00001740 void getDeducedAttributes(LLVMContext &Ctx,
1741 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001742 // TODO: Add *_globally support
1743 if (isAssumedNonNull())
1744 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
1745 Ctx, getAssumedDereferenceableBytes()));
1746 else
1747 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
1748 Ctx, getAssumedDereferenceableBytes()));
1749 }
1750 uint64_t computeAssumedDerefenceableBytes(Attributor &A, Value &V,
1751 bool &IsNonNull, bool &IsGlobal);
1752
Johannes Doerfertece81902019-08-12 22:05:53 +00001753 void initialize(Attributor &A) override {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001754 SmallVector<Attribute, 4> Attrs;
1755 getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
1756 Attrs);
1757 for (const Attribute &Attr : Attrs)
1758 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001759 }
1760
1761 /// See AbstractAttribute::getAsStr().
1762 const std::string getAsStr() const override {
1763 if (!getAssumedDereferenceableBytes())
1764 return "unknown-dereferenceable";
1765 return std::string("dereferenceable") +
1766 (isAssumedNonNull() ? "" : "_or_null") +
1767 (isAssumedGlobal() ? "_globally" : "") + "<" +
1768 std::to_string(getKnownDereferenceableBytes()) + "-" +
1769 std::to_string(getAssumedDereferenceableBytes()) + ">";
1770 }
1771};
1772
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001773struct AADereferenceableReturned final : AADereferenceableImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001774 AADereferenceableReturned(const IRPosition &IRP)
1775 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001776
1777 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001778 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001779
1780 /// See AbstractAttribute::trackStatistics()
1781 void trackStatistics() const override {
1782 STATS_DECL_AND_TRACK_FNRET_ATTR(dereferenceable)
1783 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001784};
1785
1786// Helper function that returns dereferenceable bytes.
1787static uint64_t calcDifferenceIfBaseIsNonNull(int64_t DerefBytes,
1788 int64_t Offset, bool IsNonNull) {
1789 if (!IsNonNull)
1790 return 0;
1791 return std::max((int64_t)0, DerefBytes - Offset);
1792}
1793
1794uint64_t AADereferenceableImpl::computeAssumedDerefenceableBytes(
1795 Attributor &A, Value &V, bool &IsNonNull, bool &IsGlobal) {
1796 // TODO: Tracking the globally flag.
1797 IsGlobal = false;
1798
1799 // First, we try to get information about V from Attributor.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001800 if (auto *DerefAA =
1801 A.getAAFor<AADereferenceable>(*this, IRPosition::value(V))) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001802 IsNonNull &= DerefAA->isAssumedNonNull();
1803 return DerefAA->getAssumedDereferenceableBytes();
1804 }
1805
1806 // Otherwise, we try to compute assumed bytes from base pointer.
Johannes Doerfert26e58462019-08-12 22:21:09 +00001807 const DataLayout &DL = A.getDataLayout();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001808 unsigned IdxWidth =
1809 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
1810 APInt Offset(IdxWidth, 0);
1811 Value *Base = V.stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
1812
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001813 if (auto *BaseDerefAA =
1814 A.getAAFor<AADereferenceable>(*this, IRPosition::value(*Base))) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001815 IsNonNull &= Offset != 0;
1816 return calcDifferenceIfBaseIsNonNull(
1817 BaseDerefAA->getAssumedDereferenceableBytes(), Offset.getSExtValue(),
1818 Offset != 0 || BaseDerefAA->isAssumedNonNull());
1819 }
1820
1821 // Then, use IR information.
1822
1823 if (isDereferenceablePointer(Base, Base->getType(), DL))
1824 return calcDifferenceIfBaseIsNonNull(
1825 DL.getTypeStoreSize(Base->getType()->getPointerElementType()),
1826 Offset.getSExtValue(),
1827 !NullPointerIsDefined(&getAnchorScope(),
1828 V.getType()->getPointerAddressSpace()));
1829
1830 IsNonNull = false;
1831 return 0;
1832}
Johannes Doerfert007153e2019-08-05 23:26:06 +00001833
Johannes Doerfertece81902019-08-12 22:05:53 +00001834ChangeStatus AADereferenceableReturned::updateImpl(Attributor &A) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001835 auto BeforeState = static_cast<DerefState>(*this);
1836
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001837 syncNonNull(A.getAAFor<AANonNull>(*this, getIRPosition()));
Hideto Ueno19c07af2019-07-23 08:16:17 +00001838
Hideto Ueno19c07af2019-07-23 08:16:17 +00001839 bool IsNonNull = isAssumedNonNull();
1840 bool IsGlobal = isAssumedGlobal();
1841
Johannes Doerfert14a04932019-08-07 22:27:24 +00001842 auto CheckReturnValue = [&](Value &RV) -> bool {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001843 takeAssumedDerefBytesMinimum(
1844 computeAssumedDerefenceableBytes(A, RV, IsNonNull, IsGlobal));
1845 return isValidState();
1846 };
1847
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001848 if (A.checkForAllReturnedValues(CheckReturnValue, *this)) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001849 updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
1850 return BeforeState == static_cast<DerefState>(*this)
1851 ? ChangeStatus::UNCHANGED
1852 : ChangeStatus::CHANGED;
1853 }
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001854 return indicatePessimisticFixpoint();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001855}
1856
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001857struct AADereferenceableArgument final : AADereferenceableImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001858 AADereferenceableArgument(const IRPosition &IRP)
1859 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001860
Hideto Ueno19c07af2019-07-23 08:16:17 +00001861 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001862 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001863
1864 /// See AbstractAttribute::trackStatistics()
1865 void trackStatistics() const override {
1866 STATS_DECL_AND_TRACK_ARG_ATTR(dereferenceable)
1867 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001868};
1869
Johannes Doerfertece81902019-08-12 22:05:53 +00001870ChangeStatus AADereferenceableArgument::updateImpl(Attributor &A) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001871 Argument &Arg = cast<Argument>(getAnchorValue());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001872
1873 auto BeforeState = static_cast<DerefState>(*this);
1874
1875 unsigned ArgNo = Arg.getArgNo();
1876
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001877 syncNonNull(A.getAAFor<AANonNull>(*this, getIRPosition()));
Hideto Ueno19c07af2019-07-23 08:16:17 +00001878
1879 bool IsNonNull = isAssumedNonNull();
1880 bool IsGlobal = isAssumedGlobal();
1881
1882 // Callback function
1883 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) -> bool {
1884 assert(CS && "Sanity check: Call site was not initialized properly!");
1885
1886 // Check that DereferenceableAA is AADereferenceableCallSiteArgument.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001887 if (auto *DereferenceableAA = A.getAAFor<AADereferenceable>(
1888 *this, IRPosition::callsite_argument(CS, ArgNo))) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001889 ImmutableCallSite ICS(
1890 &DereferenceableAA->getIRPosition().getAnchorValue());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001891 if (ICS && CS.getInstruction() == ICS.getInstruction()) {
1892 takeAssumedDerefBytesMinimum(
1893 DereferenceableAA->getAssumedDereferenceableBytes());
1894 IsNonNull &= DereferenceableAA->isAssumedNonNull();
1895 IsGlobal &= DereferenceableAA->isAssumedGlobal();
1896 return isValidState();
1897 }
1898 }
1899
1900 takeAssumedDerefBytesMinimum(computeAssumedDerefenceableBytes(
1901 A, *CS.getArgOperand(ArgNo), IsNonNull, IsGlobal));
1902
1903 return isValidState();
1904 };
1905
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001906 if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001907 return indicatePessimisticFixpoint();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001908
1909 updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
1910
1911 return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
1912 : ChangeStatus::CHANGED;
1913}
1914
1915/// Dereferenceable attribute for a call site argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001916struct AADereferenceableCallSiteArgument final : AADereferenceableImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001917 AADereferenceableCallSiteArgument(const IRPosition &IRP)
1918 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001919
1920 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00001921 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001922
1923 /// See AbstractAttribute::trackStatistics()
1924 void trackStatistics() const override {
1925 STATS_DECL_AND_TRACK_CSARG_ATTR(dereferenceable)
1926 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001927};
1928
Johannes Doerfertece81902019-08-12 22:05:53 +00001929ChangeStatus AADereferenceableCallSiteArgument::updateImpl(Attributor &A) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001930 // NOTE: Never look at the argument of the callee in this method.
1931 // If we do this, "dereferenceable" is always deduced because of the
1932 // assumption.
1933
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001934 Value &V = getAssociatedValue();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001935
1936 auto BeforeState = static_cast<DerefState>(*this);
1937
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001938 syncNonNull(A.getAAFor<AANonNull>(*this, getIRPosition()));
Hideto Ueno19c07af2019-07-23 08:16:17 +00001939 bool IsNonNull = isAssumedNonNull();
1940 bool IsGlobal = isKnownGlobal();
1941
1942 takeAssumedDerefBytesMinimum(
1943 computeAssumedDerefenceableBytes(A, V, IsNonNull, IsGlobal));
1944 updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
1945
1946 return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
1947 : ChangeStatus::CHANGED;
1948}
1949
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001950// ------------------------ Align Argument Attribute ------------------------
1951
Johannes Doerfert344d0382019-08-07 22:34:26 +00001952struct AAAlignImpl : AAAlign {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001953 AAAlignImpl(const IRPosition &IRP) : AAAlign(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001954
1955 // Max alignemnt value allowed in IR
1956 static const unsigned MAX_ALIGN = 1U << 29;
1957
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001958 const std::string getAsStr() const override {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001959 return getAssumedAlign() ? ("align<" + std::to_string(getKnownAlign()) +
1960 "-" + std::to_string(getAssumedAlign()) + ">")
1961 : "unknown-align";
1962 }
1963
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001964 /// See AbstractAttriubute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001965 void initialize(Attributor &A) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001966 takeAssumedMinimum(MAX_ALIGN);
1967
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001968 SmallVector<Attribute, 4> Attrs;
1969 getAttrs({Attribute::Alignment}, Attrs);
1970 for (const Attribute &Attr : Attrs)
1971 takeKnownMaximum(Attr.getValueAsInt());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001972 }
1973
1974 /// See AbstractAttribute::getDeducedAttributes
1975 virtual void
Johannes Doerferteccdf082019-08-05 23:35:12 +00001976 getDeducedAttributes(LLVMContext &Ctx,
1977 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001978 Attrs.emplace_back(Attribute::getWithAlignment(Ctx, getAssumedAlign()));
1979 }
1980};
1981
1982/// Align attribute for function return value.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001983struct AAAlignReturned final : AAAlignImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001984 AAAlignReturned(const IRPosition &IRP) : AAAlignImpl(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001985
1986 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001987 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001988
1989 /// See AbstractAttribute::trackStatistics()
1990 void trackStatistics() const override {
1991 STATS_DECL_AND_TRACK_FNRET_ATTR(aligned)
1992 }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001993};
1994
Johannes Doerfertece81902019-08-12 22:05:53 +00001995ChangeStatus AAAlignReturned::updateImpl(Attributor &A) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001996
1997 // Currently, align<n> is deduced if alignments in return values are assumed
1998 // as greater than n. We reach pessimistic fixpoint if any of the return value
1999 // wouldn't have align. If no assumed state was used for reasoning, an
2000 // optimistic fixpoint is reached earlier.
2001
2002 base_t BeforeState = getAssumed();
Johannes Doerfert14a04932019-08-07 22:27:24 +00002003 auto CheckReturnValue =
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002004 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &RetInsts) -> bool {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002005 auto *AlignAA = A.getAAFor<AAAlign>(*this, IRPosition::value(RV));
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002006
2007 if (AlignAA)
2008 takeAssumedMinimum(AlignAA->getAssumedAlign());
2009 else
2010 // Use IR information.
Johannes Doerfert26e58462019-08-12 22:21:09 +00002011 takeAssumedMinimum(RV.getPointerAlignment(A.getDataLayout()));
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002012
2013 return isValidState();
2014 };
2015
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002016 if (!A.checkForAllReturnedValuesAndReturnInsts(CheckReturnValue, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00002017 return indicatePessimisticFixpoint();
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002018
2019 return (getAssumed() != BeforeState) ? ChangeStatus::CHANGED
2020 : ChangeStatus::UNCHANGED;
2021}
2022
2023/// Align attribute for function argument.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002024struct AAAlignArgument final : AAAlignImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002025 AAAlignArgument(const IRPosition &IRP) : AAAlignImpl(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002026
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002027 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002028 virtual ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002029
2030 /// See AbstractAttribute::trackStatistics()
2031 void trackStatistics() const override{STATS_DECL_AND_TRACK_ARG_ATTR(aligned)};
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002032};
2033
Johannes Doerfertece81902019-08-12 22:05:53 +00002034ChangeStatus AAAlignArgument::updateImpl(Attributor &A) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002035
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002036 Argument &Arg = cast<Argument>(getAnchorValue());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002037
2038 unsigned ArgNo = Arg.getArgNo();
Johannes Doerfert26e58462019-08-12 22:21:09 +00002039 const DataLayout &DL = A.getDataLayout();
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002040
2041 auto BeforeState = getAssumed();
2042
2043 // Callback function
2044 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) {
2045 assert(CS && "Sanity check: Call site was not initialized properly!");
2046
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002047 auto *AlignAA =
2048 A.getAAFor<AAAlign>(*this, IRPosition::callsite_argument(CS, ArgNo));
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002049
2050 // Check that AlignAA is AAAlignCallSiteArgument.
2051 if (AlignAA) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002052 ImmutableCallSite ICS(&AlignAA->getIRPosition().getAnchorValue());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002053 if (ICS && CS.getInstruction() == ICS.getInstruction()) {
2054 takeAssumedMinimum(AlignAA->getAssumedAlign());
2055 return isValidState();
2056 }
2057 }
2058
2059 Value *V = CS.getArgOperand(ArgNo);
2060 takeAssumedMinimum(V->getPointerAlignment(DL));
2061 return isValidState();
2062 };
2063
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002064 if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002065 indicatePessimisticFixpoint();
2066
2067 return BeforeState == getAssumed() ? ChangeStatus::UNCHANGED
2068 : ChangeStatus ::CHANGED;
2069}
2070
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002071struct AAAlignCallSiteArgument final : AAAlignImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002072 AAAlignCallSiteArgument(const IRPosition &IRP) : AAAlignImpl(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002073
2074 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002075 void initialize(Attributor &A) override {
Johannes Doerfert26e58462019-08-12 22:21:09 +00002076 takeKnownMaximum(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002077 getAssociatedValue().getPointerAlignment(A.getDataLayout()));
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002078 }
2079
2080 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00002081 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002082
2083 /// See AbstractAttribute::trackStatistics()
2084 void trackStatistics() const override {
2085 STATS_DECL_AND_TRACK_CSARG_ATTR(aligned)
2086 }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002087};
2088
Johannes Doerfertece81902019-08-12 22:05:53 +00002089ChangeStatus AAAlignCallSiteArgument::updateImpl(Attributor &A) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002090 // NOTE: Never look at the argument of the callee in this method.
2091 // If we do this, "align" is always deduced because of the assumption.
2092
2093 auto BeforeState = getAssumed();
2094
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002095 Value &V = getAssociatedValue();
2096 auto *AlignAA = A.getAAFor<AAAlign>(*this, IRPosition::value(V));
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002097
2098 if (AlignAA)
2099 takeAssumedMinimum(AlignAA->getAssumedAlign());
2100 else
2101 indicatePessimisticFixpoint();
2102
2103 return BeforeState == getAssumed() ? ChangeStatus::UNCHANGED
2104 : ChangeStatus::CHANGED;
2105}
2106
Johannes Doerferte83f3032019-08-05 23:22:05 +00002107/// ------------------ Function No-Return Attribute ----------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00002108struct AANoReturnImpl : public AANoReturn {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002109 AANoReturnImpl(const IRPosition &IRP) : AANoReturn(IRP) {}
Johannes Doerferte83f3032019-08-05 23:22:05 +00002110
Johannes Doerferte83f3032019-08-05 23:22:05 +00002111 /// See AbstractAttribute::getAsStr().
2112 const std::string getAsStr() const override {
2113 return getAssumed() ? "noreturn" : "may-return";
2114 }
2115
2116 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002117 void initialize(Attributor &A) override {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002118 if (hasAttr({getAttrKind()}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002119 indicateOptimisticFixpoint();
2120 }
2121
2122 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00002123 virtual ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002124 auto CheckForNoReturn = [](Instruction &) { return false; };
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002125 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002126 {(unsigned)Instruction::Ret}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002127 return indicatePessimisticFixpoint();
Johannes Doerferte83f3032019-08-05 23:22:05 +00002128 return ChangeStatus::UNCHANGED;
2129 }
2130};
2131
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002132struct AANoReturnFunction final : AANoReturnImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002133 AANoReturnFunction(const IRPosition &IRP) : AANoReturnImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002134
2135 /// See AbstractAttribute::trackStatistics()
2136 void trackStatistics() const override {
2137 STATS_DECL_AND_TRACK_FN_ATTR(noreturn)
2138 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002139};
2140
Johannes Doerfertaade7822019-06-05 03:02:24 +00002141/// ----------------------------------------------------------------------------
2142/// Attributor
2143/// ----------------------------------------------------------------------------
2144
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002145bool Attributor::isAssumedDead(const AbstractAttribute &AA,
2146 const AAIsDead *LivenessAA) {
2147 const Instruction *CtxI = AA.getIRPosition().getCtxI();
2148 if (!CtxI)
2149 return false;
2150
2151 if (!LivenessAA)
2152 LivenessAA =
2153 getAAFor<AAIsDead>(AA, IRPosition::function(*CtxI->getFunction()));
2154 if (!LivenessAA || !LivenessAA->isAssumedDead(CtxI))
2155 return false;
2156
2157 // TODO: Do not track dependences automatically but add it here as only a
2158 // "is-assumed-dead" result causes a dependence.
2159 return true;
2160}
2161
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002162bool Attributor::checkForAllCallSites(const function_ref<bool(CallSite)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002163 const AbstractAttribute &QueryingAA,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002164 bool RequireAllCallSites) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002165 // We can try to determine information from
2166 // the call sites. However, this is only possible all call sites are known,
2167 // hence the function has internal linkage.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002168 const IRPosition &IRP = QueryingAA.getIRPosition();
2169 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2170 if (!AssociatedFunction)
2171 return false;
2172
2173 if (RequireAllCallSites && !AssociatedFunction->hasInternalLinkage()) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002174 LLVM_DEBUG(
2175 dbgs()
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002176 << "Attributor: Function " << AssociatedFunction->getName()
Hideto Ueno54869ec2019-07-15 06:49:04 +00002177 << " has no internal linkage, hence not all call sites are known\n");
2178 return false;
2179 }
2180
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002181 for (const Use &U : AssociatedFunction->uses()) {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002182 Instruction *I = cast<Instruction>(U.getUser());
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002183 Function *Caller = I->getFunction();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002184
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002185 auto *LivenessAA =
2186 getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*Caller));
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002187
2188 // Skip dead calls.
2189 if (LivenessAA && LivenessAA->isAssumedDead(I))
2190 continue;
Hideto Ueno54869ec2019-07-15 06:49:04 +00002191
2192 CallSite CS(U.getUser());
Hideto Ueno54869ec2019-07-15 06:49:04 +00002193 if (!CS || !CS.isCallee(&U) || !CS.getCaller()->hasExactDefinition()) {
2194 if (!RequireAllCallSites)
2195 continue;
2196
2197 LLVM_DEBUG(dbgs() << "Attributor: User " << *U.getUser()
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002198 << " is an invalid use of "
2199 << AssociatedFunction->getName() << "\n");
Hideto Ueno54869ec2019-07-15 06:49:04 +00002200 return false;
2201 }
2202
2203 if (Pred(CS))
2204 continue;
2205
2206 LLVM_DEBUG(dbgs() << "Attributor: Call site callback failed for "
2207 << *CS.getInstruction() << "\n");
2208 return false;
2209 }
2210
2211 return true;
2212}
2213
Johannes Doerfert14a04932019-08-07 22:27:24 +00002214bool Attributor::checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert14a04932019-08-07 22:27:24 +00002215 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
2216 &Pred,
2217 const AbstractAttribute &QueryingAA) {
2218
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002219 const IRPosition &IRP = QueryingAA.getIRPosition();
2220 // Since we need to provide return instructions we have to have an exact
2221 // definition.
2222 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2223 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
Johannes Doerfert14a04932019-08-07 22:27:24 +00002224 return false;
2225
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002226 // If this is a call site query we use the call site specific return values
2227 // and liveness information.
2228 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2229 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
2230 if (!AARetVal || !AARetVal->getState().isValidState())
2231 return false;
2232
2233 auto *LivenessAA =
2234 getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*AssociatedFunction));
Johannes Doerfert14a04932019-08-07 22:27:24 +00002235 if (!LivenessAA)
2236 return AARetVal->checkForAllReturnedValuesAndReturnInsts(Pred);
2237
2238 auto LivenessFilter = [&](Value &RV,
2239 const SmallPtrSetImpl<ReturnInst *> &ReturnInsts) {
2240 SmallPtrSet<ReturnInst *, 4> FilteredReturnInsts;
2241 for (ReturnInst *RI : ReturnInsts)
2242 if (!LivenessAA->isAssumedDead(RI))
2243 FilteredReturnInsts.insert(RI);
2244 if (!FilteredReturnInsts.empty())
2245 return Pred(RV, FilteredReturnInsts);
2246 return true;
2247 };
2248
2249 return AARetVal->checkForAllReturnedValuesAndReturnInsts(LivenessFilter);
2250}
2251
2252bool Attributor::checkForAllReturnedValues(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002253 const function_ref<bool(Value &)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002254 const AbstractAttribute &QueryingAA) {
2255
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002256 const IRPosition &IRP = QueryingAA.getIRPosition();
2257 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2258 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
Johannes Doerfert14a04932019-08-07 22:27:24 +00002259 return false;
2260
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002261 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2262 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
2263 if (!AARetVal || !AARetVal->getState().isValidState())
2264 return false;
2265
2266 auto *LivenessAA =
2267 getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*AssociatedFunction));
Johannes Doerfert14a04932019-08-07 22:27:24 +00002268 if (!LivenessAA)
2269 return AARetVal->checkForAllReturnedValuesAndReturnInsts(
2270 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &) {
2271 return Pred(RV);
2272 });
2273
2274 auto LivenessFilter = [&](Value &RV,
2275 const SmallPtrSetImpl<ReturnInst *> &ReturnInsts) {
2276 if (LivenessAA->isLiveInstSet(ReturnInsts.begin(), ReturnInsts.end()))
2277 return Pred(RV);
2278 return true;
2279 };
2280
2281 return AARetVal->checkForAllReturnedValuesAndReturnInsts(LivenessFilter);
2282}
2283
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002284bool Attributor::checkForAllInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002285 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00002286 const AbstractAttribute &QueryingAA, const ArrayRef<unsigned> &Opcodes) {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002287
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002288 const IRPosition &IRP = QueryingAA.getIRPosition();
2289 // Since we need to provide instructions we have to have an exact definition.
2290 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2291 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
2292 return false;
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002293
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002294 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2295 const auto &LivenessAA = getAAFor<AAIsDead>(QueryingAA, QueryIRP);
2296
2297 auto &OpcodeInstMap =
2298 InfoCache.getOpcodeInstMapForFunction(*AssociatedFunction);
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002299 for (unsigned Opcode : Opcodes) {
2300 for (Instruction *I : OpcodeInstMap[Opcode]) {
2301 // Skip dead instructions.
2302 if (LivenessAA && LivenessAA->isAssumedDead(I))
2303 continue;
2304
2305 if (!Pred(*I))
2306 return false;
2307 }
2308 }
2309
2310 return true;
2311}
2312
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002313bool Attributor::checkForAllReadWriteInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002314 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00002315 AbstractAttribute &QueryingAA) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002316
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002317 const Function *AssociatedFunction =
2318 QueryingAA.getIRPosition().getAssociatedFunction();
2319 if (!AssociatedFunction)
2320 return false;
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002321
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002322 const auto &LivenessAA =
2323 getAAFor<AAIsDead>(QueryingAA, QueryingAA.getIRPosition());
2324
2325 for (Instruction *I :
2326 InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002327 // Skip dead instructions.
2328 if (LivenessAA && LivenessAA->isAssumedDead(I))
2329 continue;
2330
2331 if (!Pred(*I))
2332 return false;
2333 }
2334
2335 return true;
2336}
2337
Johannes Doerfertece81902019-08-12 22:05:53 +00002338ChangeStatus Attributor::run() {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002339 // Initialize all abstract attributes.
2340 for (AbstractAttribute *AA : AllAbstractAttributes)
Johannes Doerfertece81902019-08-12 22:05:53 +00002341 AA->initialize(*this);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002342
2343 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
2344 << AllAbstractAttributes.size()
2345 << " abstract attributes.\n");
2346
Stefan Stipanovic53605892019-06-27 11:27:54 +00002347 // Now that all abstract attributes are collected and initialized we start
2348 // the abstract analysis.
Johannes Doerfertaade7822019-06-05 03:02:24 +00002349
2350 unsigned IterationCounter = 1;
2351
2352 SmallVector<AbstractAttribute *, 64> ChangedAAs;
2353 SetVector<AbstractAttribute *> Worklist;
2354 Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
2355
2356 do {
2357 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
2358 << ", Worklist size: " << Worklist.size() << "\n");
2359
2360 // Add all abstract attributes that are potentially dependent on one that
2361 // changed to the work list.
2362 for (AbstractAttribute *ChangedAA : ChangedAAs) {
2363 auto &QuerriedAAs = QueryMap[ChangedAA];
2364 Worklist.insert(QuerriedAAs.begin(), QuerriedAAs.end());
2365 }
2366
2367 // Reset the changed set.
2368 ChangedAAs.clear();
2369
2370 // Update all abstract attribute in the work list and record the ones that
2371 // changed.
2372 for (AbstractAttribute *AA : Worklist)
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002373 if (!isAssumedDead(*AA, nullptr))
2374 if (AA->update(*this) == ChangeStatus::CHANGED)
2375 ChangedAAs.push_back(AA);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002376
2377 // Reset the work list and repopulate with the changed abstract attributes.
2378 // Note that dependent ones are added above.
2379 Worklist.clear();
2380 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2381
2382 } while (!Worklist.empty() && ++IterationCounter < MaxFixpointIterations);
2383
2384 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
2385 << IterationCounter << "/" << MaxFixpointIterations
2386 << " iterations\n");
2387
2388 bool FinishedAtFixpoint = Worklist.empty();
2389
2390 // Reset abstract arguments not settled in a sound fixpoint by now. This
2391 // happens when we stopped the fixpoint iteration early. Note that only the
2392 // ones marked as "changed" *and* the ones transitively depending on them
2393 // need to be reverted to a pessimistic state. Others might not be in a
2394 // fixpoint state but we can use the optimistic results for them anyway.
2395 SmallPtrSet<AbstractAttribute *, 32> Visited;
2396 for (unsigned u = 0; u < ChangedAAs.size(); u++) {
2397 AbstractAttribute *ChangedAA = ChangedAAs[u];
2398 if (!Visited.insert(ChangedAA).second)
2399 continue;
2400
2401 AbstractState &State = ChangedAA->getState();
2402 if (!State.isAtFixpoint()) {
2403 State.indicatePessimisticFixpoint();
2404
2405 NumAttributesTimedOut++;
2406 }
2407
2408 auto &QuerriedAAs = QueryMap[ChangedAA];
2409 ChangedAAs.append(QuerriedAAs.begin(), QuerriedAAs.end());
2410 }
2411
2412 LLVM_DEBUG({
2413 if (!Visited.empty())
2414 dbgs() << "\n[Attributor] Finalized " << Visited.size()
2415 << " abstract attributes.\n";
2416 });
2417
2418 unsigned NumManifested = 0;
2419 unsigned NumAtFixpoint = 0;
2420 ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
2421 for (AbstractAttribute *AA : AllAbstractAttributes) {
2422 AbstractState &State = AA->getState();
2423
2424 // If there is not already a fixpoint reached, we can now take the
2425 // optimistic state. This is correct because we enforced a pessimistic one
2426 // on abstract attributes that were transitively dependent on a changed one
2427 // already above.
2428 if (!State.isAtFixpoint())
2429 State.indicateOptimisticFixpoint();
2430
2431 // If the state is invalid, we do not try to manifest it.
2432 if (!State.isValidState())
2433 continue;
2434
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002435 // Skip dead code.
2436 if (isAssumedDead(*AA, nullptr))
2437 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002438 // Manifest the state and record if we changed the IR.
2439 ChangeStatus LocalChange = AA->manifest(*this);
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002440 if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled())
2441 AA->trackStatistics();
2442
Johannes Doerfertaade7822019-06-05 03:02:24 +00002443 ManifestChange = ManifestChange | LocalChange;
2444
2445 NumAtFixpoint++;
2446 NumManifested += (LocalChange == ChangeStatus::CHANGED);
2447 }
2448
2449 (void)NumManifested;
2450 (void)NumAtFixpoint;
2451 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
2452 << " arguments while " << NumAtFixpoint
2453 << " were in a valid fixpoint state\n");
2454
2455 // If verification is requested, we finished this run at a fixpoint, and the
2456 // IR was changed, we re-run the whole fixpoint analysis, starting at
2457 // re-initialization of the arguments. This re-run should not result in an IR
2458 // change. Though, the (virtual) state of attributes at the end of the re-run
2459 // might be more optimistic than the known state or the IR state if the better
2460 // state cannot be manifested.
2461 if (VerifyAttributor && FinishedAtFixpoint &&
2462 ManifestChange == ChangeStatus::CHANGED) {
2463 VerifyAttributor = false;
Johannes Doerfertece81902019-08-12 22:05:53 +00002464 ChangeStatus VerifyStatus = run();
Johannes Doerfertaade7822019-06-05 03:02:24 +00002465 if (VerifyStatus != ChangeStatus::UNCHANGED)
2466 llvm_unreachable(
2467 "Attributor verification failed, re-run did result in an IR change "
2468 "even after a fixpoint was reached in the original run. (False "
2469 "positives possible!)");
2470 VerifyAttributor = true;
2471 }
2472
2473 NumAttributesManifested += NumManifested;
2474 NumAttributesValidFixpoint += NumAtFixpoint;
2475
2476 return ManifestChange;
2477}
2478
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002479/// Helper function that checks if an abstract attribute of type \p AAType
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002480/// should be created for IR position \p IRP and if so creates and registers it
2481/// with the Attributor \p A.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002482///
2483/// This method will look at the provided whitelist. If one is given and the
2484/// kind \p AAType::ID is not contained, no abstract attribute is created.
2485///
2486/// \returns The created abstract argument, or nullptr if none was created.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002487template <typename AAType>
2488static AAType *checkAndRegisterAA(IRPosition &IRP, Attributor &A,
2489 DenseSet<const char *> *Whitelist) {
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002490 if (Whitelist && !Whitelist->count(&AAType::ID))
2491 return nullptr;
2492
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002493 return &A.registerAA<AAType>(*new AAType(IRP));
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002494}
2495
Johannes Doerfertaade7822019-06-05 03:02:24 +00002496void Attributor::identifyDefaultAbstractAttributes(
Johannes Doerfertece81902019-08-12 22:05:53 +00002497 Function &F, DenseSet<const char *> *Whitelist) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002498
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002499 IRPosition FPos = IRPosition::function(F);
2500
Johannes Doerfert305b9612019-08-04 18:40:01 +00002501 // Check for dead BasicBlocks in every function.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002502 // We need dead instruction detection because we do not want to deal with
2503 // broken IR in which SSA rules do not apply.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002504 checkAndRegisterAA<AAIsDeadFunction>(FPos, *this, /* Whitelist */ nullptr);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002505
2506 // Every function might be "will-return".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002507 checkAndRegisterAA<AAWillReturnFunction>(FPos, *this, Whitelist);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002508
Stefan Stipanovic53605892019-06-27 11:27:54 +00002509 // Every function can be nounwind.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002510 checkAndRegisterAA<AANoUnwindFunction>(FPos, *this, Whitelist);
Stefan Stipanovic53605892019-06-27 11:27:54 +00002511
Stefan Stipanovic06263672019-07-11 21:37:40 +00002512 // Every function might be marked "nosync"
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002513 checkAndRegisterAA<AANoSyncFunction>(FPos, *this, Whitelist);
Stefan Stipanovic06263672019-07-11 21:37:40 +00002514
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002515 // Every function might be "no-free".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002516 checkAndRegisterAA<AANoFreeFunction>(FPos, *this, Whitelist);
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002517
Johannes Doerferte83f3032019-08-05 23:22:05 +00002518 // Every function might be "no-return".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002519 checkAndRegisterAA<AANoReturnFunction>(FPos, *this, Whitelist);
Johannes Doerferte83f3032019-08-05 23:22:05 +00002520
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002521 // Return attributes are only appropriate if the return type is non void.
2522 Type *ReturnType = F.getReturnType();
2523 if (!ReturnType->isVoidTy()) {
2524 // Argument attribute "returned" --- Create only one per function even
2525 // though it is an argument attribute.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002526 checkAndRegisterAA<AAReturnedValuesFunction>(FPos, *this, Whitelist);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002527
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002528 if (ReturnType->isPointerTy()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002529 IRPosition RetPos = IRPosition::returned(F);
2530
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002531 // Every function with pointer return type might be marked align.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002532 checkAndRegisterAA<AAAlignReturned>(RetPos, *this, Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002533
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002534 // Every function with pointer return type might be marked nonnull.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002535 checkAndRegisterAA<AANonNullReturned>(RetPos, *this, Whitelist);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002536
2537 // Every function with pointer return type might be marked noalias.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002538 checkAndRegisterAA<AANoAliasReturned>(RetPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002539
2540 // Every function with pointer return type might be marked
2541 // dereferenceable.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002542 checkAndRegisterAA<AADereferenceableReturned>(RetPos, *this, Whitelist);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002543 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00002544 }
2545
Hideto Ueno54869ec2019-07-15 06:49:04 +00002546 for (Argument &Arg : F.args()) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002547 if (Arg.getType()->isPointerTy()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002548 IRPosition ArgPos = IRPosition::argument(Arg);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002549 // Every argument with pointer type might be marked nonnull.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002550 checkAndRegisterAA<AANonNullArgument>(ArgPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002551
2552 // Every argument with pointer type might be marked dereferenceable.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002553 checkAndRegisterAA<AADereferenceableArgument>(ArgPos, *this, Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002554
2555 // Every argument with pointer type might be marked align.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002556 checkAndRegisterAA<AAAlignArgument>(ArgPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002557 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002558 }
2559
Johannes Doerfertaade7822019-06-05 03:02:24 +00002560 // Walk all instructions to find more attribute opportunities and also
2561 // interesting instructions that might be queried by abstract attributes
2562 // during their initialization or update.
2563 auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
2564 auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
2565
2566 for (Instruction &I : instructions(&F)) {
2567 bool IsInterestingOpcode = false;
2568
2569 // To allow easy access to all instructions in a function with a given
2570 // opcode we store them in the InfoCache. As not all opcodes are interesting
2571 // to concrete attributes we only cache the ones that are as identified in
2572 // the following switch.
2573 // Note: There are no concrete attributes now so this is initially empty.
Stefan Stipanovic53605892019-06-27 11:27:54 +00002574 switch (I.getOpcode()) {
2575 default:
2576 assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) &&
2577 "New call site/base instruction type needs to be known int the "
2578 "attributor.");
2579 break;
2580 case Instruction::Call:
2581 case Instruction::CallBr:
2582 case Instruction::Invoke:
2583 case Instruction::CleanupRet:
2584 case Instruction::CatchSwitch:
2585 case Instruction::Resume:
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002586 case Instruction::Ret:
Stefan Stipanovic53605892019-06-27 11:27:54 +00002587 IsInterestingOpcode = true;
2588 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002589 if (IsInterestingOpcode)
2590 InstOpcodeMap[I.getOpcode()].push_back(&I);
2591 if (I.mayReadOrWriteMemory())
2592 ReadOrWriteInsts.push_back(&I);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002593
2594 CallSite CS(&I);
2595 if (CS && CS.getCalledFunction()) {
2596 for (int i = 0, e = CS.getCalledFunction()->arg_size(); i < e; i++) {
2597 if (!CS.getArgument(i)->getType()->isPointerTy())
2598 continue;
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002599 IRPosition CSArgPos = IRPosition::callsite_argument(CS, i);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002600
2601 // Call site argument attribute "non-null".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002602 checkAndRegisterAA<AANonNullCallSiteArgument>(CSArgPos, *this,
2603 Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002604
2605 // Call site argument attribute "dereferenceable".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002606 checkAndRegisterAA<AADereferenceableCallSiteArgument>(CSArgPos, *this,
2607 Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002608
2609 // Call site argument attribute "align".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002610 checkAndRegisterAA<AAAlignCallSiteArgument>(CSArgPos, *this, Whitelist);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002611 }
2612 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002613 }
2614}
2615
2616/// Helpers to ease debugging through output streams and print calls.
2617///
2618///{
2619raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
2620 return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
2621}
2622
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002623raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002624 switch (AP) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002625 case IRPosition::IRP_INVALID:
2626 return OS << "inv";
2627 case IRPosition::IRP_FLOAT:
2628 return OS << "flt";
2629 case IRPosition::IRP_RETURNED:
2630 return OS << "fn_ret";
2631 case IRPosition::IRP_CALL_SITE_RETURNED:
2632 return OS << "cs_ret";
2633 case IRPosition::IRP_FUNCTION:
2634 return OS << "fn";
2635 case IRPosition::IRP_CALL_SITE:
2636 return OS << "cs";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002637 case IRPosition::IRP_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002638 return OS << "arg";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002639 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002640 return OS << "cs_arg";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002641 }
2642 llvm_unreachable("Unknown attribute position!");
2643}
2644
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002645raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002646 const Value &AV = Pos.getAssociatedValue();
2647 return OS << "{" << Pos.getPositionKind() << ":" << AV.getName() << " ["
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002648 << Pos.getAnchorValue().getName() << "@" << Pos.getArgNo() << "]}";
2649}
2650
Johannes Doerfertacc80792019-08-12 22:07:34 +00002651raw_ostream &llvm::operator<<(raw_ostream &OS, const IntegerState &S) {
2652 return OS << "(" << S.getKnown() << "-" << S.getAssumed() << ")"
2653 << static_cast<const AbstractState &>(S);
2654}
2655
Johannes Doerfertaade7822019-06-05 03:02:24 +00002656raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
2657 return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
2658}
2659
2660raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
2661 AA.print(OS);
2662 return OS;
2663}
2664
2665void AbstractAttribute::print(raw_ostream &OS) const {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002666 OS << "[P: " << getIRPosition() << "][" << getAsStr() << "][S: " << getState()
2667 << "]";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002668}
2669///}
2670
2671/// ----------------------------------------------------------------------------
2672/// Pass (Manager) Boilerplate
2673/// ----------------------------------------------------------------------------
2674
2675static bool runAttributorOnModule(Module &M) {
2676 if (DisableAttributor)
2677 return false;
2678
2679 LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << M.size()
2680 << " functions.\n");
2681
2682 // Create an Attributor and initially empty information cache that is filled
2683 // while we identify default attribute opportunities.
Johannes Doerfertece81902019-08-12 22:05:53 +00002684 InformationCache InfoCache(M.getDataLayout());
2685 Attributor A(InfoCache);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002686
2687 for (Function &F : M) {
2688 // TODO: Not all attributes require an exact definition. Find a way to
2689 // enable deduction for some but not all attributes in case the
2690 // definition might be changed at runtime, see also
2691 // http://lists.llvm.org/pipermail/llvm-dev/2018-February/121275.html.
2692 // TODO: We could always determine abstract attributes and if sufficient
2693 // information was found we could duplicate the functions that do not
2694 // have an exact definition.
2695 if (!F.hasExactDefinition()) {
2696 NumFnWithoutExactDefinition++;
2697 continue;
2698 }
2699
2700 // For now we ignore naked and optnone functions.
2701 if (F.hasFnAttribute(Attribute::Naked) ||
2702 F.hasFnAttribute(Attribute::OptimizeNone))
2703 continue;
2704
2705 NumFnWithExactDefinition++;
2706
2707 // Populate the Attributor with abstract attribute opportunities in the
2708 // function and the information cache with IR information.
Johannes Doerfertece81902019-08-12 22:05:53 +00002709 A.identifyDefaultAbstractAttributes(F);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002710 }
2711
Johannes Doerfertece81902019-08-12 22:05:53 +00002712 return A.run() == ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002713}
2714
2715PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
2716 if (runAttributorOnModule(M)) {
2717 // FIXME: Think about passes we will preserve and add them here.
2718 return PreservedAnalyses::none();
2719 }
2720 return PreservedAnalyses::all();
2721}
2722
2723namespace {
2724
2725struct AttributorLegacyPass : public ModulePass {
2726 static char ID;
2727
2728 AttributorLegacyPass() : ModulePass(ID) {
2729 initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry());
2730 }
2731
2732 bool runOnModule(Module &M) override {
2733 if (skipModule(M))
2734 return false;
2735 return runAttributorOnModule(M);
2736 }
2737
2738 void getAnalysisUsage(AnalysisUsage &AU) const override {
2739 // FIXME: Think about passes we will preserve and add them here.
2740 AU.setPreservesCFG();
2741 }
2742};
2743
2744} // end anonymous namespace
2745
2746Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); }
2747
2748char AttributorLegacyPass::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002749
2750const char AAReturnedValues::ID = 0;
2751const char AANoUnwind::ID = 0;
2752const char AANoSync::ID = 0;
Johannes Doerferteccdf082019-08-05 23:35:12 +00002753const char AANoFree::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002754const char AANonNull::ID = 0;
2755const char AANoRecurse::ID = 0;
2756const char AAWillReturn::ID = 0;
2757const char AANoAlias::ID = 0;
2758const char AANoReturn::ID = 0;
2759const char AAIsDead::ID = 0;
2760const char AADereferenceable::ID = 0;
2761const char AAAlign::ID = 0;
2762
Johannes Doerfertaade7822019-06-05 03:02:24 +00002763INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor",
2764 "Deduce and propagate attributes", false, false)
2765INITIALIZE_PASS_END(AttributorLegacyPass, "attributor",
2766 "Deduce and propagate attributes", false, false)