blob: 373e491c846eb1f4e2aff632af9932b57eebc454 [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/SmallPtrSet.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/Statistic.h"
Stefan Stipanovic69ebb022019-07-22 19:36:27 +000023#include "llvm/Analysis/CaptureTracking.h"
Johannes Doerfert924d2132019-08-05 21:34:45 +000024#include "llvm/Analysis/EHPersonalities.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000025#include "llvm/Analysis/GlobalsModRef.h"
Hideto Ueno19c07af2019-07-23 08:16:17 +000026#include "llvm/Analysis/Loads.h"
Hideto Ueno54869ec2019-07-15 06:49:04 +000027#include "llvm/Analysis/ValueTracking.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000028#include "llvm/IR/Argument.h"
29#include "llvm/IR/Attributes.h"
Hideto Ueno11d37102019-07-17 15:15:43 +000030#include "llvm/IR/CFG.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000031#include "llvm/IR/InstIterator.h"
Stefan Stipanovic06263672019-07-11 21:37:40 +000032#include "llvm/IR/IntrinsicInst.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000033#include "llvm/Support/CommandLine.h"
34#include "llvm/Support/Debug.h"
35#include "llvm/Support/raw_ostream.h"
Stefan Stipanovic6058b862019-07-22 23:58:23 +000036#include "llvm/Transforms/Utils/BasicBlockUtils.h"
37#include "llvm/Transforms/Utils/Local.h"
38
Johannes Doerfertaade7822019-06-05 03:02:24 +000039#include <cassert>
40
41using namespace llvm;
42
43#define DEBUG_TYPE "attributor"
44
45STATISTIC(NumFnWithExactDefinition,
46 "Number of function with exact definitions");
47STATISTIC(NumFnWithoutExactDefinition,
48 "Number of function without exact definitions");
49STATISTIC(NumAttributesTimedOut,
50 "Number of abstract attributes timed out before fixpoint");
51STATISTIC(NumAttributesValidFixpoint,
52 "Number of abstract attributes in a valid fixpoint state");
53STATISTIC(NumAttributesManifested,
54 "Number of abstract attributes manifested in IR");
55
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000056// Some helper macros to deal with statistics tracking.
57//
58// Usage:
59// For simple IR attribute tracking overload trackStatistics in the abstract
Johannes Doerfert17b578b2019-08-14 21:46:25 +000060// attribute and choose the right STATS_DECLTRACK_********* macro,
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000061// e.g.,:
62// void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +000063// STATS_DECLTRACK_ARG_ATTR(returned)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000064// }
65// If there is a single "increment" side one can use the macro
Johannes Doerfert17b578b2019-08-14 21:46:25 +000066// STATS_DECLTRACK with a custom message. If there are multiple increment
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000067// sides, STATS_DECL and STATS_TRACK can also be used separatly.
68//
69#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
70 ("Number of " #TYPE " marked '" #NAME "'")
71#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
72#define STATS_DECL(NAME, TYPE, MSG) STATISTIC(BUILD_STAT_NAME(NAME, TYPE), MSG);
73#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
Johannes Doerfert17b578b2019-08-14 21:46:25 +000074#define STATS_DECLTRACK(NAME, TYPE, MSG) \
Johannes Doerfert169af992019-08-20 06:09:56 +000075 { \
76 STATS_DECL(NAME, TYPE, MSG) \
77 STATS_TRACK(NAME, TYPE) \
78 }
Johannes Doerfert17b578b2019-08-14 21:46:25 +000079#define STATS_DECLTRACK_ARG_ATTR(NAME) \
80 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
81#define STATS_DECLTRACK_CSARG_ATTR(NAME) \
82 STATS_DECLTRACK(NAME, CSArguments, \
83 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
84#define STATS_DECLTRACK_FN_ATTR(NAME) \
85 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
86#define STATS_DECLTRACK_CS_ATTR(NAME) \
87 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
88#define STATS_DECLTRACK_FNRET_ATTR(NAME) \
89 STATS_DECLTRACK(NAME, FunctionReturn, \
Johannes Doerfert2db85282019-08-21 20:56:56 +000090 BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
Johannes Doerfert17b578b2019-08-14 21:46:25 +000091#define STATS_DECLTRACK_CSRET_ATTR(NAME) \
92 STATS_DECLTRACK(NAME, CSReturn, \
93 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
94#define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
95 STATS_DECLTRACK(NAME, Floating, \
96 ("Number of floating values known to be '" #NAME "'"))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +000097
Johannes Doerfertaade7822019-06-05 03:02:24 +000098// TODO: Determine a good default value.
99//
100// In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads
101// (when run with the first 5 abstract attributes). The results also indicate
102// that we never reach 32 iterations but always find a fixpoint sooner.
103//
104// This will become more evolved once we perform two interleaved fixpoint
105// iterations: bottom-up and top-down.
106static cl::opt<unsigned>
107 MaxFixpointIterations("attributor-max-iterations", cl::Hidden,
108 cl::desc("Maximal number of fixpoint iterations."),
109 cl::init(32));
110
111static cl::opt<bool> DisableAttributor(
112 "attributor-disable", cl::Hidden,
113 cl::desc("Disable the attributor inter-procedural deduction pass."),
Johannes Doerfert282d34e2019-06-14 14:53:41 +0000114 cl::init(true));
Johannes Doerfertaade7822019-06-05 03:02:24 +0000115
116static cl::opt<bool> VerifyAttributor(
117 "attributor-verify", cl::Hidden,
118 cl::desc("Verify the Attributor deduction and "
119 "manifestation of attributes -- may issue false-positive errors"),
120 cl::init(false));
121
122/// Logic operators for the change status enum class.
123///
124///{
125ChangeStatus llvm::operator|(ChangeStatus l, ChangeStatus r) {
126 return l == ChangeStatus::CHANGED ? l : r;
127}
128ChangeStatus llvm::operator&(ChangeStatus l, ChangeStatus r) {
129 return l == ChangeStatus::UNCHANGED ? l : r;
130}
131///}
132
Johannes Doerfertdef99282019-08-14 21:29:37 +0000133/// Recursively visit all values that might become \p IRP at some point. This
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000134/// will be done by looking through cast instructions, selects, phis, and calls
Johannes Doerfertdef99282019-08-14 21:29:37 +0000135/// with the "returned" attribute. Once we cannot look through the value any
136/// further, the callback \p VisitValueCB is invoked and passed the current
137/// value, the \p State, and a flag to indicate if we stripped anything. To
138/// limit how much effort is invested, we will never visit more values than
139/// specified by \p MaxValues.
140template <typename AAType, typename StateTy>
141bool genericValueTraversal(
142 Attributor &A, IRPosition IRP, const AAType &QueryingAA, StateTy &State,
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000143 const function_ref<bool(Value &, StateTy &, bool)> &VisitValueCB,
Johannes Doerfertdef99282019-08-14 21:29:37 +0000144 int MaxValues = 8) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000145
Johannes Doerfertdef99282019-08-14 21:29:37 +0000146 const AAIsDead *LivenessAA = nullptr;
147 if (IRP.getAnchorScope())
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000148 LivenessAA = &A.getAAFor<AAIsDead>(
Johannes Doerfertdef99282019-08-14 21:29:37 +0000149 QueryingAA, IRPosition::function(*IRP.getAnchorScope()));
150
151 // TODO: Use Positions here to allow context sensitivity in VisitValueCB
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000152 SmallPtrSet<Value *, 16> Visited;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000153 SmallVector<Value *, 16> Worklist;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000154 Worklist.push_back(&IRP.getAssociatedValue());
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000155
156 int Iteration = 0;
157 do {
158 Value *V = Worklist.pop_back_val();
159
160 // Check if we should process the current value. To prevent endless
161 // recursion keep a record of the values we followed!
Johannes Doerfertdef99282019-08-14 21:29:37 +0000162 if (!Visited.insert(V).second)
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000163 continue;
164
165 // Make sure we limit the compile time for complex expressions.
166 if (Iteration++ >= MaxValues)
167 return false;
168
169 // Explicitly look through calls with a "returned" attribute if we do
170 // not have a pointer as stripPointerCasts only works on them.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000171 Value *NewV = nullptr;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000172 if (V->getType()->isPointerTy()) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000173 NewV = V->stripPointerCasts();
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000174 } else {
175 CallSite CS(V);
176 if (CS && CS.getCalledFunction()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000177 for (Argument &Arg : CS.getCalledFunction()->args())
178 if (Arg.hasReturnedAttr()) {
179 NewV = CS.getArgOperand(Arg.getArgNo());
180 break;
181 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000182 }
183 }
Johannes Doerfertdef99282019-08-14 21:29:37 +0000184 if (NewV && NewV != V) {
185 Worklist.push_back(NewV);
186 continue;
187 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000188
189 // Look through select instructions, visit both potential values.
190 if (auto *SI = dyn_cast<SelectInst>(V)) {
191 Worklist.push_back(SI->getTrueValue());
192 Worklist.push_back(SI->getFalseValue());
193 continue;
194 }
195
Johannes Doerfertdef99282019-08-14 21:29:37 +0000196 // Look through phi nodes, visit all live operands.
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000197 if (auto *PHI = dyn_cast<PHINode>(V)) {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000198 assert(LivenessAA &&
199 "Expected liveness in the presence of instructions!");
Johannes Doerfertdef99282019-08-14 21:29:37 +0000200 for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
201 const BasicBlock *IncomingBB = PHI->getIncomingBlock(u);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000202 if (!LivenessAA->isAssumedDead(IncomingBB->getTerminator()))
Johannes Doerfertdef99282019-08-14 21:29:37 +0000203 Worklist.push_back(PHI->getIncomingValue(u));
204 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000205 continue;
206 }
207
208 // Once a leaf is reached we inform the user through the callback.
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000209 if (!VisitValueCB(*V, State, Iteration > 1))
210 return false;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000211 } while (!Worklist.empty());
212
213 // All values have been visited.
214 return true;
215}
216
Johannes Doerfertaade7822019-06-05 03:02:24 +0000217/// Return true if \p New is equal or worse than \p Old.
218static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) {
219 if (!Old.isIntAttribute())
220 return true;
221
222 return Old.getValueAsInt() >= New.getValueAsInt();
223}
224
225/// Return true if the information provided by \p Attr was added to the
226/// attribute list \p Attrs. This is only the case if it was not already present
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000227/// in \p Attrs at the position describe by \p PK and \p AttrIdx.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000228static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000229 AttributeList &Attrs, int AttrIdx) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000230
231 if (Attr.isEnumAttribute()) {
232 Attribute::AttrKind Kind = Attr.getKindAsEnum();
233 if (Attrs.hasAttribute(AttrIdx, Kind))
234 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
235 return false;
236 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
237 return true;
238 }
239 if (Attr.isStringAttribute()) {
240 StringRef Kind = Attr.getKindAsString();
241 if (Attrs.hasAttribute(AttrIdx, Kind))
242 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
243 return false;
244 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
245 return true;
246 }
Hideto Ueno19c07af2019-07-23 08:16:17 +0000247 if (Attr.isIntAttribute()) {
248 Attribute::AttrKind Kind = Attr.getKindAsEnum();
249 if (Attrs.hasAttribute(AttrIdx, Kind))
250 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
251 return false;
252 Attrs = Attrs.removeAttribute(Ctx, AttrIdx, Kind);
253 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
254 return true;
255 }
Johannes Doerfertaade7822019-06-05 03:02:24 +0000256
257 llvm_unreachable("Expected enum or string attribute!");
258}
259
Johannes Doerfertece81902019-08-12 22:05:53 +0000260ChangeStatus AbstractAttribute::update(Attributor &A) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000261 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
262 if (getState().isAtFixpoint())
263 return HasChanged;
264
265 LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");
266
Johannes Doerfertece81902019-08-12 22:05:53 +0000267 HasChanged = updateImpl(A);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000268
269 LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
270 << "\n");
271
272 return HasChanged;
273}
274
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000275ChangeStatus
276IRAttributeManifest::manifestAttrs(Attributor &A, IRPosition &IRP,
277 const ArrayRef<Attribute> &DeducedAttrs) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000278 Function *ScopeFn = IRP.getAssociatedFunction();
Kristina Brooks26e60f02019-08-06 19:53:19 +0000279 IRPosition::Kind PK = IRP.getPositionKind();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000280
Johannes Doerfertaade7822019-06-05 03:02:24 +0000281 // In the following some generic code that will manifest attributes in
282 // DeducedAttrs if they improve the current IR. Due to the different
283 // annotation positions we use the underlying AttributeList interface.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000284
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000285 AttributeList Attrs;
286 switch (PK) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000287 case IRPosition::IRP_INVALID:
288 case IRPosition::IRP_FLOAT:
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000289 return ChangeStatus::UNCHANGED;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000290 case IRPosition::IRP_ARGUMENT:
291 case IRPosition::IRP_FUNCTION:
292 case IRPosition::IRP_RETURNED:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000293 Attrs = ScopeFn->getAttributes();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000294 break;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000295 case IRPosition::IRP_CALL_SITE:
296 case IRPosition::IRP_CALL_SITE_RETURNED:
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000297 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000298 Attrs = ImmutableCallSite(&IRP.getAnchorValue()).getAttributes();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000299 break;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000300 }
301
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000302 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000303 LLVMContext &Ctx = IRP.getAnchorValue().getContext();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000304 for (const Attribute &Attr : DeducedAttrs) {
Kristina Brooks26e60f02019-08-06 19:53:19 +0000305 if (!addIfNotExistent(Ctx, Attr, Attrs, IRP.getAttrIdx()))
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000306 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000307
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000308 HasChanged = ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000309 }
310
311 if (HasChanged == ChangeStatus::UNCHANGED)
312 return HasChanged;
313
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000314 switch (PK) {
315 case IRPosition::IRP_ARGUMENT:
316 case IRPosition::IRP_FUNCTION:
317 case IRPosition::IRP_RETURNED:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000318 ScopeFn->setAttributes(Attrs);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000319 break;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000320 case IRPosition::IRP_CALL_SITE:
321 case IRPosition::IRP_CALL_SITE_RETURNED:
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000322 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000323 CallSite(&IRP.getAnchorValue()).setAttributes(Attrs);
Johannes Doerfert4395b312019-08-14 21:46:28 +0000324 break;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000325 case IRPosition::IRP_INVALID:
Johannes Doerfert4395b312019-08-14 21:46:28 +0000326 case IRPosition::IRP_FLOAT:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000327 break;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000328 }
329
330 return HasChanged;
331}
332
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000333const IRPosition IRPosition::EmptyKey(255);
334const IRPosition IRPosition::TombstoneKey(256);
335
336SubsumingPositionIterator::SubsumingPositionIterator(const IRPosition &IRP) {
337 IRPositions.emplace_back(IRP);
338
339 ImmutableCallSite ICS(&IRP.getAnchorValue());
340 switch (IRP.getPositionKind()) {
341 case IRPosition::IRP_INVALID:
342 case IRPosition::IRP_FLOAT:
343 case IRPosition::IRP_FUNCTION:
344 return;
345 case IRPosition::IRP_ARGUMENT:
346 case IRPosition::IRP_RETURNED:
347 IRPositions.emplace_back(
348 IRPosition::function(*IRP.getAssociatedFunction()));
349 return;
350 case IRPosition::IRP_CALL_SITE:
351 assert(ICS && "Expected call site!");
352 // TODO: We need to look at the operand bundles similar to the redirection
353 // in CallBase.
354 if (!ICS.hasOperandBundles())
355 if (const Function *Callee = ICS.getCalledFunction())
356 IRPositions.emplace_back(IRPosition::function(*Callee));
357 return;
358 case IRPosition::IRP_CALL_SITE_RETURNED:
359 assert(ICS && "Expected call site!");
360 // TODO: We need to look at the operand bundles similar to the redirection
361 // in CallBase.
362 if (!ICS.hasOperandBundles()) {
363 if (const Function *Callee = ICS.getCalledFunction()) {
364 IRPositions.emplace_back(IRPosition::returned(*Callee));
365 IRPositions.emplace_back(IRPosition::function(*Callee));
366 }
367 }
368 IRPositions.emplace_back(
369 IRPosition::callsite_function(cast<CallBase>(*ICS.getInstruction())));
370 return;
371 case IRPosition::IRP_CALL_SITE_ARGUMENT: {
372 int ArgNo = IRP.getArgNo();
373 assert(ICS && ArgNo >= 0 && "Expected call site!");
374 // TODO: We need to look at the operand bundles similar to the redirection
375 // in CallBase.
376 if (!ICS.hasOperandBundles()) {
377 const Function *Callee = ICS.getCalledFunction();
378 if (Callee && Callee->arg_size() > unsigned(ArgNo))
379 IRPositions.emplace_back(IRPosition::argument(*Callee->getArg(ArgNo)));
380 if (Callee)
381 IRPositions.emplace_back(IRPosition::function(*Callee));
382 }
383 IRPositions.emplace_back(IRPosition::value(IRP.getAssociatedValue()));
384 return;
385 }
386 }
387}
388
389bool IRPosition::hasAttr(ArrayRef<Attribute::AttrKind> AKs) const {
390 for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this))
391 for (Attribute::AttrKind AK : AKs)
392 if (EquivIRP.getAttr(AK).getKindAsEnum() == AK)
393 return true;
394 return false;
395}
396
397void IRPosition::getAttrs(ArrayRef<Attribute::AttrKind> AKs,
398 SmallVectorImpl<Attribute> &Attrs) const {
399 for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this))
400 for (Attribute::AttrKind AK : AKs) {
401 const Attribute &Attr = EquivIRP.getAttr(AK);
402 if (Attr.getKindAsEnum() == AK)
403 Attrs.push_back(Attr);
404 }
405}
406
407void IRPosition::verify() {
408 switch (KindOrArgNo) {
409 default:
410 assert(KindOrArgNo >= 0 && "Expected argument or call site argument!");
411 assert((isa<CallBase>(AnchorVal) || isa<Argument>(AnchorVal)) &&
412 "Expected call base or argument for positive attribute index!");
413 if (auto *Arg = dyn_cast<Argument>(AnchorVal)) {
414 assert(Arg->getArgNo() == unsigned(getArgNo()) &&
415 "Argument number mismatch!");
416 assert(Arg == &getAssociatedValue() && "Associated value mismatch!");
417 } else {
418 auto &CB = cast<CallBase>(*AnchorVal);
Johannes Doerfert4395b312019-08-14 21:46:28 +0000419 (void)CB;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000420 assert(CB.arg_size() > unsigned(getArgNo()) &&
421 "Call site argument number mismatch!");
422 assert(CB.getArgOperand(getArgNo()) == &getAssociatedValue() &&
423 "Associated value mismatch!");
424 }
425 break;
426 case IRP_INVALID:
427 assert(!AnchorVal && "Expected no value for an invalid position!");
428 break;
429 case IRP_FLOAT:
430 assert((!isa<CallBase>(&getAssociatedValue()) &&
431 !isa<Argument>(&getAssociatedValue())) &&
432 "Expected specialized kind for call base and argument values!");
433 break;
434 case IRP_RETURNED:
435 assert(isa<Function>(AnchorVal) &&
436 "Expected function for a 'returned' position!");
437 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
438 break;
439 case IRP_CALL_SITE_RETURNED:
440 assert((isa<CallBase>(AnchorVal)) &&
441 "Expected call base for 'call site returned' position!");
442 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
443 break;
444 case IRP_CALL_SITE:
445 assert((isa<CallBase>(AnchorVal)) &&
446 "Expected call base for 'call site function' position!");
447 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
448 break;
449 case IRP_FUNCTION:
450 assert(isa<Function>(AnchorVal) &&
451 "Expected function for a 'function' position!");
452 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
453 break;
454 }
455}
456
Johannes Doerfert234eda52019-08-16 19:51:23 +0000457/// Helper functions to clamp a state \p S of type \p StateType with the
458/// information in \p R and indicate/return if \p S did change (as-in update is
459/// required to be run again).
460///
461///{
462template <typename StateType>
463ChangeStatus clampStateAndIndicateChange(StateType &S, const StateType &R);
464
465template <>
466ChangeStatus clampStateAndIndicateChange<IntegerState>(IntegerState &S,
467 const IntegerState &R) {
468 auto Assumed = S.getAssumed();
469 S ^= R;
470 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
471 : ChangeStatus::CHANGED;
472}
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000473
474template <>
475ChangeStatus clampStateAndIndicateChange<BooleanState>(BooleanState &S,
476 const BooleanState &R) {
477 return clampStateAndIndicateChange<IntegerState>(S, R);
478}
Johannes Doerfert234eda52019-08-16 19:51:23 +0000479///}
480
481/// Clamp the information known for all returned values of a function
482/// (identified by \p QueryingAA) into \p S.
483template <typename AAType, typename StateType = typename AAType::StateType>
484static void clampReturnedValueStates(Attributor &A, const AAType &QueryingAA,
485 StateType &S) {
486 LLVM_DEBUG(dbgs() << "[Attributor] Clamp return value states for "
487 << static_cast<const AbstractAttribute &>(QueryingAA)
488 << " into " << S << "\n");
489
490 assert((QueryingAA.getIRPosition().getPositionKind() ==
491 IRPosition::IRP_RETURNED ||
492 QueryingAA.getIRPosition().getPositionKind() ==
493 IRPosition::IRP_CALL_SITE_RETURNED) &&
494 "Can only clamp returned value states for a function returned or call "
495 "site returned position!");
496
497 // Use an optional state as there might not be any return values and we want
498 // to join (IntegerState::operator&) the state of all there are.
499 Optional<StateType> T;
500
501 // Callback for each possibly returned value.
502 auto CheckReturnValue = [&](Value &RV) -> bool {
503 const IRPosition &RVPos = IRPosition::value(RV);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000504 const AAType &AA = A.getAAFor<AAType>(QueryingAA, RVPos);
505 LLVM_DEBUG(dbgs() << "[Attributor] RV: " << RV << " AA: " << AA.getAsStr()
506 << " @ " << RVPos << "\n");
507 const StateType &AAS = static_cast<const StateType &>(AA.getState());
Johannes Doerfert234eda52019-08-16 19:51:23 +0000508 if (T.hasValue())
509 *T &= AAS;
510 else
511 T = AAS;
512 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " RV State: " << T
513 << "\n");
514 return T->isValidState();
515 };
516
517 if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA))
518 S.indicatePessimisticFixpoint();
519 else if (T.hasValue())
520 S ^= *T;
521}
522
523/// Helper class for generic deduction: return value -> returned position.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000524template <typename AAType, typename Base,
525 typename StateType = typename AAType::StateType>
526struct AAReturnedFromReturnedValues : public Base {
527 AAReturnedFromReturnedValues(const IRPosition &IRP) : Base(IRP) {}
Johannes Doerfert234eda52019-08-16 19:51:23 +0000528
529 /// See AbstractAttribute::updateImpl(...).
530 ChangeStatus updateImpl(Attributor &A) override {
531 StateType S;
532 clampReturnedValueStates<AAType, StateType>(A, *this, S);
Johannes Doerfert028b2aa2019-08-20 05:57:01 +0000533 // TODO: If we know we visited all returned values, thus no are assumed
534 // dead, we can take the known information from the state T.
Johannes Doerfert234eda52019-08-16 19:51:23 +0000535 return clampStateAndIndicateChange<StateType>(this->getState(), S);
536 }
537};
538
539/// Clamp the information known at all call sites for a given argument
540/// (identified by \p QueryingAA) into \p S.
541template <typename AAType, typename StateType = typename AAType::StateType>
542static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
543 StateType &S) {
544 LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for "
545 << static_cast<const AbstractAttribute &>(QueryingAA)
546 << " into " << S << "\n");
547
548 assert(QueryingAA.getIRPosition().getPositionKind() ==
549 IRPosition::IRP_ARGUMENT &&
550 "Can only clamp call site argument states for an argument position!");
551
552 // Use an optional state as there might not be any return values and we want
553 // to join (IntegerState::operator&) the state of all there are.
554 Optional<StateType> T;
555
556 // The argument number which is also the call site argument number.
557 unsigned ArgNo = QueryingAA.getIRPosition().getArgNo();
558
559 auto CallSiteCheck = [&](CallSite CS) {
560 const IRPosition &CSArgPos = IRPosition::callsite_argument(CS, ArgNo);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000561 const AAType &AA = A.getAAFor<AAType>(QueryingAA, CSArgPos);
Johannes Doerfert234eda52019-08-16 19:51:23 +0000562 LLVM_DEBUG(dbgs() << "[Attributor] CS: " << *CS.getInstruction()
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000563 << " AA: " << AA.getAsStr() << " @" << CSArgPos << "\n");
564 const StateType &AAS = static_cast<const StateType &>(AA.getState());
Johannes Doerfert234eda52019-08-16 19:51:23 +0000565 if (T.hasValue())
566 *T &= AAS;
567 else
568 T = AAS;
569 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " CSA State: " << T
570 << "\n");
571 return T->isValidState();
572 };
573
574 if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true))
575 S.indicatePessimisticFixpoint();
576 else if (T.hasValue())
577 S ^= *T;
578}
579
580/// Helper class for generic deduction: call site argument -> argument position.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000581template <typename AAType, typename Base,
582 typename StateType = typename AAType::StateType>
583struct AAArgumentFromCallSiteArguments : public Base {
584 AAArgumentFromCallSiteArguments(const IRPosition &IRP) : Base(IRP) {}
Johannes Doerfert234eda52019-08-16 19:51:23 +0000585
586 /// See AbstractAttribute::updateImpl(...).
587 ChangeStatus updateImpl(Attributor &A) override {
588 StateType S;
589 clampCallSiteArgumentStates<AAType, StateType>(A, *this, S);
Johannes Doerfert028b2aa2019-08-20 05:57:01 +0000590 // TODO: If we know we visited all incoming values, thus no are assumed
591 // dead, we can take the known information from the state T.
Johannes Doerfert234eda52019-08-16 19:51:23 +0000592 return clampStateAndIndicateChange<StateType>(this->getState(), S);
593 }
594};
595
596/// Helper class for generic replication: function returned -> cs returned.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000597template <typename AAType, typename Base>
598struct AACallSiteReturnedFromReturned : public Base {
599 AACallSiteReturnedFromReturned(const IRPosition &IRP) : Base(IRP) {}
Johannes Doerfert234eda52019-08-16 19:51:23 +0000600
601 /// See AbstractAttribute::updateImpl(...).
602 ChangeStatus updateImpl(Attributor &A) override {
603 assert(this->getIRPosition().getPositionKind() ==
604 IRPosition::IRP_CALL_SITE_RETURNED &&
605 "Can only wrap function returned positions for call site returned "
606 "positions!");
607 auto &S = this->getState();
608
609 const Function *AssociatedFunction =
610 this->getIRPosition().getAssociatedFunction();
611 if (!AssociatedFunction)
612 return S.indicatePessimisticFixpoint();
613
614 IRPosition FnPos = IRPosition::returned(*AssociatedFunction);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000615 const AAType &AA = A.getAAFor<AAType>(*this, FnPos);
Johannes Doerfert234eda52019-08-16 19:51:23 +0000616 return clampStateAndIndicateChange(
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000617 S, static_cast<const typename AAType::StateType &>(AA.getState()));
Johannes Doerfert234eda52019-08-16 19:51:23 +0000618 }
619};
620
Stefan Stipanovic53605892019-06-27 11:27:54 +0000621/// -----------------------NoUnwind Function Attribute--------------------------
622
Johannes Doerfert344d0382019-08-07 22:34:26 +0000623struct AANoUnwindImpl : AANoUnwind {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000624 AANoUnwindImpl(const IRPosition &IRP) : AANoUnwind(IRP) {}
Stefan Stipanovic53605892019-06-27 11:27:54 +0000625
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +0000626 /// See AbstractAttribute::initialize(...).
627 void initialize(Attributor &A) override {
628 if (hasAttr({Attribute::NoUnwind}))
629 indicateOptimisticFixpoint();
630 }
631
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000632 const std::string getAsStr() const override {
Stefan Stipanovic53605892019-06-27 11:27:54 +0000633 return getAssumed() ? "nounwind" : "may-unwind";
634 }
635
636 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +0000637 ChangeStatus updateImpl(Attributor &A) override {
638 auto Opcodes = {
639 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
640 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
641 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
642
643 auto CheckForNoUnwind = [&](Instruction &I) {
644 if (!I.mayThrow())
645 return true;
646
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000647 if (ImmutableCallSite ICS = ImmutableCallSite(&I)) {
648 const auto &NoUnwindAA =
649 A.getAAFor<AANoUnwind>(*this, IRPosition::callsite_function(ICS));
650 return NoUnwindAA.isAssumedNoUnwind();
651 }
652 return false;
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +0000653 };
654
655 if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes))
656 return indicatePessimisticFixpoint();
657
658 return ChangeStatus::UNCHANGED;
659 }
Stefan Stipanovic53605892019-06-27 11:27:54 +0000660};
661
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000662struct AANoUnwindFunction final : public AANoUnwindImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000663 AANoUnwindFunction(const IRPosition &IRP) : AANoUnwindImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000664
665 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000666 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000667};
668
Johannes Doerfert66cf87e2019-08-16 19:49:00 +0000669/// NoUnwind attribute deduction for a call sites.
670using AANoUnwindCallSite = AANoUnwindFunction;
671
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000672/// --------------------- Function Return Values -------------------------------
673
674/// "Attribute" that collects all potential returned values and the return
675/// instructions that they arise from.
676///
677/// If there is a unique returned value R, the manifest method will:
678/// - mark R with the "returned" attribute, if R is an argument.
Johannes Doerferteccdf082019-08-05 23:35:12 +0000679class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000680
681 /// Mapping of values potentially returned by the associated function to the
682 /// return instructions that might return them.
Johannes Doerfert695089e2019-08-23 15:23:49 +0000683 DenseMap<Value *, SmallSetVector<ReturnInst *, 4>> ReturnedValues;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000684
Johannes Doerfert695089e2019-08-23 15:23:49 +0000685 SmallSetVector<CallBase *, 4> UnresolvedCalls;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000686
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000687 /// State flags
688 ///
689 ///{
690 bool IsFixed;
691 bool IsValidState;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000692 ///}
693
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000694public:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000695 AAReturnedValuesImpl(const IRPosition &IRP) : AAReturnedValues(IRP) {}
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000696
697 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +0000698 void initialize(Attributor &A) override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000699 // Reset the state.
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000700 IsFixed = false;
701 IsValidState = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000702 ReturnedValues.clear();
703
Johannes Doerfertdef99282019-08-14 21:29:37 +0000704 Function *F = getAssociatedFunction();
705 if (!F || !F->hasExactDefinition()) {
706 indicatePessimisticFixpoint();
707 return;
708 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000709
710 // The map from instruction opcodes to those instructions in the function.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000711 auto &OpcodeInstMap = A.getInfoCache().getOpcodeInstMapForFunction(*F);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000712
713 // Look through all arguments, if one is marked as returned we are done.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000714 for (Argument &Arg : F->args()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000715 if (Arg.hasReturnedAttr()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000716 auto &ReturnInstSet = ReturnedValues[&Arg];
717 for (Instruction *RI : OpcodeInstMap[Instruction::Ret])
718 ReturnInstSet.insert(cast<ReturnInst>(RI));
719
720 indicateOptimisticFixpoint();
721 return;
722 }
723 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000724 }
725
726 /// See AbstractAttribute::manifest(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000727 ChangeStatus manifest(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000728
729 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000730 AbstractState &getState() override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000731
732 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000733 const AbstractState &getState() const override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000734
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000735 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +0000736 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000737
Johannes Doerfertdef99282019-08-14 21:29:37 +0000738 llvm::iterator_range<iterator> returned_values() override {
739 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
740 }
741
742 llvm::iterator_range<const_iterator> returned_values() const override {
743 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
744 }
745
Johannes Doerfert695089e2019-08-23 15:23:49 +0000746 const SmallSetVector<CallBase *, 4> &getUnresolvedCalls() const override {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000747 return UnresolvedCalls;
748 }
749
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000750 /// Return the number of potential return values, -1 if unknown.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000751 size_t getNumReturnValues() const override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000752 return isValidState() ? ReturnedValues.size() : -1;
753 }
754
755 /// Return an assumed unique return value if a single candidate is found. If
756 /// there cannot be one, return a nullptr. If it is not clear yet, return the
757 /// Optional::NoneType.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000758 Optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000759
Johannes Doerfert14a04932019-08-07 22:27:24 +0000760 /// See AbstractState::checkForAllReturnedValues(...).
761 bool checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +0000762 const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)>
Johannes Doerfert14a04932019-08-07 22:27:24 +0000763 &Pred) const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000764
765 /// Pretty print the attribute similar to the IR representation.
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000766 const std::string getAsStr() const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000767
768 /// See AbstractState::isAtFixpoint().
769 bool isAtFixpoint() const override { return IsFixed; }
770
771 /// See AbstractState::isValidState().
772 bool isValidState() const override { return IsValidState; }
773
774 /// See AbstractState::indicateOptimisticFixpoint(...).
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000775 ChangeStatus indicateOptimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000776 IsFixed = true;
777 IsValidState &= true;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000778 return ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000779 }
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000780
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000781 ChangeStatus indicatePessimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000782 IsFixed = true;
783 IsValidState = false;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000784 return ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000785 }
786};
787
788ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) {
789 ChangeStatus Changed = ChangeStatus::UNCHANGED;
790
791 // Bookkeeping.
792 assert(isValidState());
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000793 STATS_DECLTRACK(KnownReturnValues, FunctionReturn,
794 "Number of function with known return values");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000795
796 // Check if we have an assumed unique return value that we could manifest.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000797 Optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000798
799 if (!UniqueRV.hasValue() || !UniqueRV.getValue())
800 return Changed;
801
802 // Bookkeeping.
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000803 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
804 "Number of function with unique return");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000805
806 // If the assumed unique return value is an argument, annotate it.
807 if (auto *UniqueRVArg = dyn_cast<Argument>(UniqueRV.getValue())) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000808 getIRPosition() = IRPosition::argument(*UniqueRVArg);
Johannes Doerferteccdf082019-08-05 23:35:12 +0000809 Changed = IRAttribute::manifest(A) | Changed;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000810 }
811
812 return Changed;
813}
814
815const std::string AAReturnedValuesImpl::getAsStr() const {
816 return (isAtFixpoint() ? "returns(#" : "may-return(#") +
Johannes Doerfert6471bb62019-08-04 18:39:28 +0000817 (isValidState() ? std::to_string(getNumReturnValues()) : "?") +
Johannes Doerfertdef99282019-08-14 21:29:37 +0000818 ")[#UC: " + std::to_string(UnresolvedCalls.size()) + "]";
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000819}
820
Johannes Doerfert14a04932019-08-07 22:27:24 +0000821Optional<Value *>
822AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const {
823 // If checkForAllReturnedValues provides a unique value, ignoring potential
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000824 // undef values that can also be present, it is assumed to be the actual
825 // return value and forwarded to the caller of this method. If there are
826 // multiple, a nullptr is returned indicating there cannot be a unique
827 // returned value.
828 Optional<Value *> UniqueRV;
829
Johannes Doerfert14a04932019-08-07 22:27:24 +0000830 auto Pred = [&](Value &RV) -> bool {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000831 // If we found a second returned value and neither the current nor the saved
832 // one is an undef, there is no unique returned value. Undefs are special
833 // since we can pretend they have any value.
834 if (UniqueRV.hasValue() && UniqueRV != &RV &&
835 !(isa<UndefValue>(RV) || isa<UndefValue>(UniqueRV.getValue()))) {
836 UniqueRV = nullptr;
837 return false;
838 }
839
840 // Do not overwrite a value with an undef.
841 if (!UniqueRV.hasValue() || !isa<UndefValue>(RV))
842 UniqueRV = &RV;
843
844 return true;
845 };
846
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000847 if (!A.checkForAllReturnedValues(Pred, *this))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000848 UniqueRV = nullptr;
849
850 return UniqueRV;
851}
852
Johannes Doerfert14a04932019-08-07 22:27:24 +0000853bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +0000854 const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)>
Johannes Doerfert14a04932019-08-07 22:27:24 +0000855 &Pred) const {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000856 if (!isValidState())
857 return false;
858
859 // Check all returned values but ignore call sites as long as we have not
860 // encountered an overdefined one during an update.
861 for (auto &It : ReturnedValues) {
862 Value *RV = It.first;
863
Johannes Doerfertdef99282019-08-14 21:29:37 +0000864 CallBase *CB = dyn_cast<CallBase>(RV);
865 if (CB && !UnresolvedCalls.count(CB))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000866 continue;
867
Johannes Doerfert695089e2019-08-23 15:23:49 +0000868 if (!Pred(*RV, It.second))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000869 return false;
870 }
871
872 return true;
873}
874
Johannes Doerfertece81902019-08-12 22:05:53 +0000875ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000876 size_t NumUnresolvedCalls = UnresolvedCalls.size();
877 bool Changed = false;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000878
Johannes Doerfertdef99282019-08-14 21:29:37 +0000879 // State used in the value traversals starting in returned values.
880 struct RVState {
881 // The map in which we collect return values -> return instrs.
882 decltype(ReturnedValues) &RetValsMap;
883 // The flag to indicate a change.
Johannes Doerfert056f1b52019-08-19 19:14:10 +0000884 bool &Changed;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000885 // The return instrs we come from.
Johannes Doerfert695089e2019-08-23 15:23:49 +0000886 SmallSetVector<ReturnInst *, 4> RetInsts;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000887 };
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000888
Johannes Doerfertdef99282019-08-14 21:29:37 +0000889 // Callback for a leaf value returned by the associated function.
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000890 auto VisitValueCB = [](Value &Val, RVState &RVS, bool) -> bool {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000891 auto Size = RVS.RetValsMap[&Val].size();
892 RVS.RetValsMap[&Val].insert(RVS.RetInsts.begin(), RVS.RetInsts.end());
893 bool Inserted = RVS.RetValsMap[&Val].size() != Size;
894 RVS.Changed |= Inserted;
895 LLVM_DEBUG({
896 if (Inserted)
897 dbgs() << "[AAReturnedValues] 1 Add new returned value " << Val
898 << " => " << RVS.RetInsts.size() << "\n";
899 });
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000900 return true;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000901 };
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000902
Johannes Doerfertdef99282019-08-14 21:29:37 +0000903 // Helper method to invoke the generic value traversal.
904 auto VisitReturnedValue = [&](Value &RV, RVState &RVS) {
905 IRPosition RetValPos = IRPosition::value(RV);
906 return genericValueTraversal<AAReturnedValues, RVState>(A, RetValPos, *this,
907 RVS, VisitValueCB);
908 };
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000909
Johannes Doerfertdef99282019-08-14 21:29:37 +0000910 // Callback for all "return intructions" live in the associated function.
911 auto CheckReturnInst = [this, &VisitReturnedValue, &Changed](Instruction &I) {
912 ReturnInst &Ret = cast<ReturnInst>(I);
Johannes Doerfert056f1b52019-08-19 19:14:10 +0000913 RVState RVS({ReturnedValues, Changed, {}});
Johannes Doerfertdef99282019-08-14 21:29:37 +0000914 RVS.RetInsts.insert(&Ret);
Johannes Doerfertdef99282019-08-14 21:29:37 +0000915 return VisitReturnedValue(*Ret.getReturnValue(), RVS);
916 };
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000917
Johannes Doerfertdef99282019-08-14 21:29:37 +0000918 // Start by discovering returned values from all live returned instructions in
919 // the associated function.
920 if (!A.checkForAllInstructions(CheckReturnInst, *this, {Instruction::Ret}))
921 return indicatePessimisticFixpoint();
922
923 // Once returned values "directly" present in the code are handled we try to
924 // resolve returned calls.
925 decltype(ReturnedValues) NewRVsMap;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000926 for (auto &It : ReturnedValues) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000927 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned value: " << *It.first
928 << " by #" << It.second.size() << " RIs\n");
929 CallBase *CB = dyn_cast<CallBase>(It.first);
930 if (!CB || UnresolvedCalls.count(CB))
931 continue;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000932
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000933 const auto &RetValAA =
Johannes Doerfertdef99282019-08-14 21:29:37 +0000934 A.getAAFor<AAReturnedValues>(*this, IRPosition::callsite_function(*CB));
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000935 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Found another AAReturnedValues: "
936 << static_cast<const AbstractAttribute &>(RetValAA)
937 << "\n");
Johannes Doerfertdef99282019-08-14 21:29:37 +0000938
939 // Skip dead ends, thus if we do not know anything about the returned
940 // call we mark it as unresolved and it will stay that way.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000941 if (!RetValAA.getState().isValidState()) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000942 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Unresolved call: " << *CB
943 << "\n");
944 UnresolvedCalls.insert(CB);
945 continue;
946 }
947
Johannes Doerfertde7674c2019-08-19 21:35:31 +0000948 // Do not try to learn partial information. If the callee has unresolved
949 // return values we will treat the call as unresolved/opaque.
950 auto &RetValAAUnresolvedCalls = RetValAA.getUnresolvedCalls();
951 if (!RetValAAUnresolvedCalls.empty()) {
952 UnresolvedCalls.insert(CB);
953 continue;
954 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000955
Johannes Doerfertde7674c2019-08-19 21:35:31 +0000956 // Now check if we can track transitively returned values. If possible, thus
957 // if all return value can be represented in the current scope, do so.
958 bool Unresolved = false;
959 for (auto &RetValAAIt : RetValAA.returned_values()) {
960 Value *RetVal = RetValAAIt.first;
961 if (isa<Argument>(RetVal) || isa<CallBase>(RetVal) ||
962 isa<Constant>(RetVal))
963 continue;
964 // Anything that did not fit in the above categories cannot be resolved,
965 // mark the call as unresolved.
966 LLVM_DEBUG(dbgs() << "[AAReturnedValues] transitively returned value "
967 "cannot be translated: "
968 << *RetVal << "\n");
969 UnresolvedCalls.insert(CB);
970 Unresolved = true;
971 break;
972 }
973
974 if (Unresolved)
975 continue;
976
Johannes Doerfertdef99282019-08-14 21:29:37 +0000977 for (auto &RetValAAIt : RetValAA.returned_values()) {
978 Value *RetVal = RetValAAIt.first;
979 if (Argument *Arg = dyn_cast<Argument>(RetVal)) {
980 // Arguments are mapped to call site operands and we begin the traversal
981 // again.
Johannes Doerfert056f1b52019-08-19 19:14:10 +0000982 bool Unused = false;
983 RVState RVS({NewRVsMap, Unused, RetValAAIt.second});
Johannes Doerfertdef99282019-08-14 21:29:37 +0000984 VisitReturnedValue(*CB->getArgOperand(Arg->getArgNo()), RVS);
985 continue;
986 } else if (isa<CallBase>(RetVal)) {
987 // Call sites are resolved by the callee attribute over time, no need to
988 // do anything for us.
989 continue;
990 } else if (isa<Constant>(RetVal)) {
991 // Constants are valid everywhere, we can simply take them.
992 NewRVsMap[RetVal].insert(It.second.begin(), It.second.end());
993 continue;
994 }
Johannes Doerfert4361da22019-08-04 18:38:53 +0000995 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000996 }
997
Johannes Doerfertdef99282019-08-14 21:29:37 +0000998 // To avoid modifications to the ReturnedValues map while we iterate over it
999 // we kept record of potential new entries in a copy map, NewRVsMap.
1000 for (auto &It : NewRVsMap) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001001 assert(!It.second.empty() && "Entry does not add anything.");
1002 auto &ReturnInsts = ReturnedValues[It.first];
1003 for (ReturnInst *RI : It.second)
Johannes Doerfert695089e2019-08-23 15:23:49 +00001004 if (ReturnInsts.insert(RI)) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001005 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Add new returned value "
1006 << *It.first << " => " << *RI << "\n");
Johannes Doerfertdef99282019-08-14 21:29:37 +00001007 Changed = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001008 }
1009 }
1010
Johannes Doerfertdef99282019-08-14 21:29:37 +00001011 Changed |= (NumUnresolvedCalls != UnresolvedCalls.size());
1012 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001013}
1014
Johannes Doerfertdef99282019-08-14 21:29:37 +00001015struct AAReturnedValuesFunction final : public AAReturnedValuesImpl {
1016 AAReturnedValuesFunction(const IRPosition &IRP) : AAReturnedValuesImpl(IRP) {}
1017
1018 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001019 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(returned) }
Johannes Doerfertdef99282019-08-14 21:29:37 +00001020};
1021
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001022/// Returned values information for a call sites.
1023using AAReturnedValuesCallSite = AAReturnedValuesFunction;
1024
Stefan Stipanovic06263672019-07-11 21:37:40 +00001025/// ------------------------ NoSync Function Attribute -------------------------
1026
Johannes Doerfert344d0382019-08-07 22:34:26 +00001027struct AANoSyncImpl : AANoSync {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001028 AANoSyncImpl(const IRPosition &IRP) : AANoSync(IRP) {}
Stefan Stipanovic06263672019-07-11 21:37:40 +00001029
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001030 /// See AbstractAttribute::initialize(...).
1031 void initialize(Attributor &A) override {
1032 if (hasAttr({Attribute::NoSync}))
1033 indicateOptimisticFixpoint();
1034 }
1035
Stefan Stipanoviccb5ecae2019-07-12 18:34:06 +00001036 const std::string getAsStr() const override {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001037 return getAssumed() ? "nosync" : "may-sync";
1038 }
1039
1040 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001041 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001042
Stefan Stipanovic06263672019-07-11 21:37:40 +00001043 /// Helper function used to determine whether an instruction is non-relaxed
1044 /// atomic. In other words, if an atomic instruction does not have unordered
1045 /// or monotonic ordering
1046 static bool isNonRelaxedAtomic(Instruction *I);
1047
1048 /// Helper function used to determine whether an instruction is volatile.
1049 static bool isVolatile(Instruction *I);
1050
Johannes Doerfertc7a1db32019-07-13 01:09:27 +00001051 /// Helper function uset to check if intrinsic is volatile (memcpy, memmove,
1052 /// memset).
Stefan Stipanovic06263672019-07-11 21:37:40 +00001053 static bool isNoSyncIntrinsic(Instruction *I);
1054};
1055
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001056bool AANoSyncImpl::isNonRelaxedAtomic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001057 if (!I->isAtomic())
1058 return false;
1059
1060 AtomicOrdering Ordering;
1061 switch (I->getOpcode()) {
1062 case Instruction::AtomicRMW:
1063 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
1064 break;
1065 case Instruction::Store:
1066 Ordering = cast<StoreInst>(I)->getOrdering();
1067 break;
1068 case Instruction::Load:
1069 Ordering = cast<LoadInst>(I)->getOrdering();
1070 break;
1071 case Instruction::Fence: {
1072 auto *FI = cast<FenceInst>(I);
1073 if (FI->getSyncScopeID() == SyncScope::SingleThread)
1074 return false;
1075 Ordering = FI->getOrdering();
1076 break;
1077 }
1078 case Instruction::AtomicCmpXchg: {
1079 AtomicOrdering Success = cast<AtomicCmpXchgInst>(I)->getSuccessOrdering();
1080 AtomicOrdering Failure = cast<AtomicCmpXchgInst>(I)->getFailureOrdering();
1081 // Only if both are relaxed, than it can be treated as relaxed.
1082 // Otherwise it is non-relaxed.
1083 if (Success != AtomicOrdering::Unordered &&
1084 Success != AtomicOrdering::Monotonic)
1085 return true;
1086 if (Failure != AtomicOrdering::Unordered &&
1087 Failure != AtomicOrdering::Monotonic)
1088 return true;
1089 return false;
1090 }
1091 default:
1092 llvm_unreachable(
1093 "New atomic operations need to be known in the attributor.");
1094 }
1095
1096 // Relaxed.
1097 if (Ordering == AtomicOrdering::Unordered ||
1098 Ordering == AtomicOrdering::Monotonic)
1099 return false;
1100 return true;
1101}
1102
1103/// Checks if an intrinsic is nosync. Currently only checks mem* intrinsics.
1104/// FIXME: We should ipmrove the handling of intrinsics.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001105bool AANoSyncImpl::isNoSyncIntrinsic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001106 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
1107 switch (II->getIntrinsicID()) {
1108 /// Element wise atomic memory intrinsics are can only be unordered,
1109 /// therefore nosync.
1110 case Intrinsic::memset_element_unordered_atomic:
1111 case Intrinsic::memmove_element_unordered_atomic:
1112 case Intrinsic::memcpy_element_unordered_atomic:
1113 return true;
1114 case Intrinsic::memset:
1115 case Intrinsic::memmove:
1116 case Intrinsic::memcpy:
1117 if (!cast<MemIntrinsic>(II)->isVolatile())
1118 return true;
1119 return false;
1120 default:
1121 return false;
1122 }
1123 }
1124 return false;
1125}
1126
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001127bool AANoSyncImpl::isVolatile(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001128 assert(!ImmutableCallSite(I) && !isa<CallBase>(I) &&
1129 "Calls should not be checked here");
1130
1131 switch (I->getOpcode()) {
1132 case Instruction::AtomicRMW:
1133 return cast<AtomicRMWInst>(I)->isVolatile();
1134 case Instruction::Store:
1135 return cast<StoreInst>(I)->isVolatile();
1136 case Instruction::Load:
1137 return cast<LoadInst>(I)->isVolatile();
1138 case Instruction::AtomicCmpXchg:
1139 return cast<AtomicCmpXchgInst>(I)->isVolatile();
1140 default:
1141 return false;
1142 }
1143}
1144
Johannes Doerfertece81902019-08-12 22:05:53 +00001145ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001146
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001147 auto CheckRWInstForNoSync = [&](Instruction &I) {
1148 /// We are looking for volatile instructions or Non-Relaxed atomics.
1149 /// FIXME: We should ipmrove the handling of intrinsics.
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001150
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001151 if (isa<IntrinsicInst>(&I) && isNoSyncIntrinsic(&I))
1152 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001153
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001154 if (ImmutableCallSite ICS = ImmutableCallSite(&I)) {
1155 if (ICS.hasFnAttr(Attribute::NoSync))
1156 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001157
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001158 const auto &NoSyncAA =
1159 A.getAAFor<AANoSync>(*this, IRPosition::callsite_function(ICS));
1160 if (NoSyncAA.isAssumedNoSync())
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001161 return true;
1162 return false;
1163 }
Stefan Stipanovic06263672019-07-11 21:37:40 +00001164
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001165 if (!isVolatile(&I) && !isNonRelaxedAtomic(&I))
1166 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001167
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001168 return false;
1169 };
Stefan Stipanovic06263672019-07-11 21:37:40 +00001170
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001171 auto CheckForNoSync = [&](Instruction &I) {
1172 // At this point we handled all read/write effects and they are all
1173 // nosync, so they can be skipped.
1174 if (I.mayReadOrWriteMemory())
1175 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001176
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001177 // non-convergent and readnone imply nosync.
1178 return !ImmutableCallSite(&I).isConvergent();
1179 };
Stefan Stipanovic06263672019-07-11 21:37:40 +00001180
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001181 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this) ||
1182 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001183 return indicatePessimisticFixpoint();
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001184
Stefan Stipanovic06263672019-07-11 21:37:40 +00001185 return ChangeStatus::UNCHANGED;
1186}
1187
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001188struct AANoSyncFunction final : public AANoSyncImpl {
1189 AANoSyncFunction(const IRPosition &IRP) : AANoSyncImpl(IRP) {}
1190
1191 /// See AbstractAttribute::trackStatistics()
1192 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }
1193};
1194
1195/// NoSync attribute deduction for a call sites.
1196using AANoSyncCallSite = AANoSyncFunction;
1197
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001198/// ------------------------ No-Free Attributes ----------------------------
1199
Johannes Doerfert344d0382019-08-07 22:34:26 +00001200struct AANoFreeImpl : public AANoFree {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001201 AANoFreeImpl(const IRPosition &IRP) : AANoFree(IRP) {}
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001202
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001203 /// See AbstractAttribute::initialize(...).
1204 void initialize(Attributor &A) override {
1205 if (hasAttr({Attribute::NoFree}))
1206 indicateOptimisticFixpoint();
1207 }
1208
1209 /// See AbstractAttribute::updateImpl(...).
1210 ChangeStatus updateImpl(Attributor &A) override {
1211 auto CheckForNoFree = [&](Instruction &I) {
1212 ImmutableCallSite ICS(&I);
1213 if (ICS.hasFnAttr(Attribute::NoFree))
1214 return true;
1215
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001216 const auto &NoFreeAA =
1217 A.getAAFor<AANoFree>(*this, IRPosition::callsite_function(ICS));
1218 return NoFreeAA.isAssumedNoFree();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001219 };
1220
1221 if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this))
1222 return indicatePessimisticFixpoint();
1223 return ChangeStatus::UNCHANGED;
1224 }
1225
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001226 /// See AbstractAttribute::getAsStr().
1227 const std::string getAsStr() const override {
1228 return getAssumed() ? "nofree" : "may-free";
1229 }
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001230};
1231
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001232struct AANoFreeFunction final : public AANoFreeImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001233 AANoFreeFunction(const IRPosition &IRP) : AANoFreeImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001234
1235 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001236 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001237};
1238
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001239/// NoFree attribute deduction for a call sites.
1240using AANoFreeCallSite = AANoFreeFunction;
1241
Hideto Ueno54869ec2019-07-15 06:49:04 +00001242/// ------------------------ NonNull Argument Attribute ------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00001243struct AANonNullImpl : AANonNull {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001244 AANonNullImpl(const IRPosition &IRP) : AANonNull(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001245
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001246 /// See AbstractAttribute::initialize(...).
1247 void initialize(Attributor &A) override {
1248 if (hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
1249 indicateOptimisticFixpoint();
1250 }
1251
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001252 /// See AbstractAttribute::getAsStr().
1253 const std::string getAsStr() const override {
1254 return getAssumed() ? "nonnull" : "may-null";
1255 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001256};
1257
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001258/// NonNull attribute for a floating value.
1259struct AANonNullFloating : AANonNullImpl {
1260 AANonNullFloating(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001261
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001262 /// See AbstractAttribute::initialize(...).
1263 void initialize(Attributor &A) override {
1264 AANonNullImpl::initialize(A);
Hideto Ueno54869ec2019-07-15 06:49:04 +00001265
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001266 if (isAtFixpoint())
1267 return;
Hideto Ueno54869ec2019-07-15 06:49:04 +00001268
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001269 const IRPosition &IRP = getIRPosition();
1270 const Value &V = IRP.getAssociatedValue();
1271 const DataLayout &DL = A.getDataLayout();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001272
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001273 // TODO: This context sensitive query should be removed once we can do
1274 // context sensitive queries in the genericValueTraversal below.
1275 if (isKnownNonZero(&V, DL, 0, /* TODO: AC */ nullptr, IRP.getCtxI(),
1276 /* TODO: DT */ nullptr))
1277 indicateOptimisticFixpoint();
1278 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001279
1280 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001281 ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001282 const DataLayout &DL = A.getDataLayout();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001283
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001284 auto VisitValueCB = [&](Value &V, AAAlign::StateType &T,
1285 bool Stripped) -> bool {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001286 const auto &AA = A.getAAFor<AANonNull>(*this, IRPosition::value(V));
1287 if (!Stripped && this == &AA) {
1288 if (!isKnownNonZero(&V, DL, 0, /* TODO: AC */ nullptr,
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001289 /* TODO: CtxI */ nullptr,
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001290 /* TODO: DT */ nullptr))
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001291 T.indicatePessimisticFixpoint();
1292 } else {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001293 // Use abstract attribute information.
1294 const AANonNull::StateType &NS =
1295 static_cast<const AANonNull::StateType &>(AA.getState());
1296 T ^= NS;
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001297 }
1298 return T.isValidState();
1299 };
1300
1301 StateType T;
1302 if (!genericValueTraversal<AANonNull, StateType>(A, getIRPosition(), *this,
1303 T, VisitValueCB))
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001304 return indicatePessimisticFixpoint();
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001305
1306 return clampStateAndIndicateChange(getState(), T);
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001307 }
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001308
1309 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001310 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001311};
1312
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001313/// NonNull attribute for function return value.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001314struct AANonNullReturned final
1315 : AAReturnedFromReturnedValues<AANonNull, AANonNullImpl> {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001316 AANonNullReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001317 : AAReturnedFromReturnedValues<AANonNull, AANonNullImpl>(IRP) {}
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001318
1319 /// See AbstractAttribute::trackStatistics()
1320 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
1321};
1322
Hideto Ueno54869ec2019-07-15 06:49:04 +00001323/// NonNull attribute for function argument.
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001324struct AANonNullArgument final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001325 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001326 AANonNullArgument(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001327 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001328
1329 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001330 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001331};
1332
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001333struct AANonNullCallSiteArgument final : AANonNullFloating {
1334 AANonNullCallSiteArgument(const IRPosition &IRP) : AANonNullFloating(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001335
1336 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert5427aa82019-08-21 20:57:20 +00001337 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnul) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001338};
Johannes Doerfert007153e2019-08-05 23:26:06 +00001339
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001340/// NonNull attribute for a call site return position.
1341struct AANonNullCallSiteReturned final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001342 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl> {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001343 AANonNullCallSiteReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001344 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl>(IRP) {}
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001345
1346 /// See AbstractAttribute::trackStatistics()
1347 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull) }
1348};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001349
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001350/// ------------------------ No-Recurse Attributes ----------------------------
1351
1352struct AANoRecurseImpl : public AANoRecurse {
1353 AANoRecurseImpl(const IRPosition &IRP) : AANoRecurse(IRP) {}
1354
1355 /// See AbstractAttribute::initialize(...).
1356 void initialize(Attributor &A) override {
1357 if (hasAttr({getAttrKind()})) {
1358 indicateOptimisticFixpoint();
1359 return;
1360 }
1361 }
1362
1363 /// See AbstractAttribute::getAsStr()
1364 const std::string getAsStr() const override {
1365 return getAssumed() ? "norecurse" : "may-recurse";
1366 }
1367};
1368
1369struct AANoRecurseFunction final : AANoRecurseImpl {
1370 AANoRecurseFunction(const IRPosition &IRP) : AANoRecurseImpl(IRP) {}
1371
1372 /// See AbstractAttribute::updateImpl(...).
1373 ChangeStatus updateImpl(Attributor &A) override {
1374 // TODO: Implement this.
1375 return indicatePessimisticFixpoint();
1376 }
1377
1378 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
1379};
1380
1381using AANoRecurseCallSite = AANoRecurseFunction;
1382
Hideto Ueno11d37102019-07-17 15:15:43 +00001383/// ------------------------ Will-Return Attributes ----------------------------
1384
Hideto Ueno11d37102019-07-17 15:15:43 +00001385// Helper function that checks whether a function has any cycle.
1386// TODO: Replace with more efficent code
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001387static bool containsCycle(Function &F) {
Hideto Ueno11d37102019-07-17 15:15:43 +00001388 SmallPtrSet<BasicBlock *, 32> Visited;
1389
1390 // Traverse BB by dfs and check whether successor is already visited.
1391 for (BasicBlock *BB : depth_first(&F)) {
1392 Visited.insert(BB);
1393 for (auto *SuccBB : successors(BB)) {
1394 if (Visited.count(SuccBB))
1395 return true;
1396 }
1397 }
1398 return false;
1399}
1400
1401// Helper function that checks the function have a loop which might become an
1402// endless loop
1403// FIXME: Any cycle is regarded as endless loop for now.
1404// We have to allow some patterns.
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001405static bool containsPossiblyEndlessLoop(Function *F) {
1406 return !F || !F->hasExactDefinition() || containsCycle(*F);
Hideto Ueno11d37102019-07-17 15:15:43 +00001407}
1408
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001409struct AAWillReturnImpl : public AAWillReturn {
1410 AAWillReturnImpl(const IRPosition &IRP) : AAWillReturn(IRP) {}
Hideto Ueno11d37102019-07-17 15:15:43 +00001411
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001412 /// See AbstractAttribute::initialize(...).
1413 void initialize(Attributor &A) override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001414 if (hasAttr({Attribute::WillReturn})) {
1415 indicateOptimisticFixpoint();
1416 return;
1417 }
Hideto Ueno11d37102019-07-17 15:15:43 +00001418
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001419 Function *F = getAssociatedFunction();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001420 if (containsPossiblyEndlessLoop(F))
1421 indicatePessimisticFixpoint();
1422 }
Hideto Ueno11d37102019-07-17 15:15:43 +00001423
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001424 /// See AbstractAttribute::updateImpl(...).
1425 ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001426 auto CheckForWillReturn = [&](Instruction &I) {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001427 IRPosition IPos = IRPosition::callsite_function(ImmutableCallSite(&I));
1428 const auto &WillReturnAA = A.getAAFor<AAWillReturn>(*this, IPos);
1429 if (WillReturnAA.isKnownWillReturn())
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001430 return true;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001431 if (!WillReturnAA.isAssumedWillReturn())
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001432 return false;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001433 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(*this, IPos);
1434 return NoRecurseAA.isAssumedNoRecurse();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001435 };
1436
1437 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this))
1438 return indicatePessimisticFixpoint();
1439
1440 return ChangeStatus::UNCHANGED;
1441 }
1442
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001443 /// See AbstractAttribute::getAsStr()
1444 const std::string getAsStr() const override {
1445 return getAssumed() ? "willreturn" : "may-noreturn";
1446 }
1447};
1448
1449struct AAWillReturnFunction final : AAWillReturnImpl {
1450 AAWillReturnFunction(const IRPosition &IRP) : AAWillReturnImpl(IRP) {}
1451
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001452 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001453 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) }
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001454};
Hideto Ueno11d37102019-07-17 15:15:43 +00001455
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001456/// WillReturn attribute deduction for a call sites.
1457using AAWillReturnCallSite = AAWillReturnFunction;
1458
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001459/// ------------------------ NoAlias Argument Attribute ------------------------
1460
Johannes Doerfert344d0382019-08-07 22:34:26 +00001461struct AANoAliasImpl : AANoAlias {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001462 AANoAliasImpl(const IRPosition &IRP) : AANoAlias(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001463
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001464 /// See AbstractAttribute::initialize(...).
1465 void initialize(Attributor &A) override {
1466 if (hasAttr({Attribute::NoAlias}))
1467 indicateOptimisticFixpoint();
1468 }
1469
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001470 const std::string getAsStr() const override {
1471 return getAssumed() ? "noalias" : "may-alias";
1472 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001473};
1474
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001475/// NoAlias attribute for a floating value.
1476struct AANoAliasFloating final : AANoAliasImpl {
1477 AANoAliasFloating(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
1478
1479 /// See AbstractAttribute::updateImpl(...).
1480 ChangeStatus updateImpl(Attributor &A) override {
1481 // TODO: Implement this.
1482 return indicatePessimisticFixpoint();
1483 }
1484
1485 /// See AbstractAttribute::trackStatistics()
1486 void trackStatistics() const override {
1487 STATS_DECLTRACK_FLOATING_ATTR(noalias)
1488 }
1489};
1490
1491/// NoAlias attribute for an argument.
1492struct AANoAliasArgument final : AANoAliasImpl {
1493 AANoAliasArgument(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
1494
1495 /// See AbstractAttribute::updateImpl(...).
1496 ChangeStatus updateImpl(Attributor &A) override {
1497 // TODO: Implement this.
1498 return indicatePessimisticFixpoint();
1499 }
1500
1501 /// See AbstractAttribute::trackStatistics()
1502 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
1503};
1504
1505struct AANoAliasCallSiteArgument final : AANoAliasImpl {
1506 AANoAliasCallSiteArgument(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
1507
1508 /// See AbstractAttribute::updateImpl(...).
1509 ChangeStatus updateImpl(Attributor &A) override {
1510 // TODO: Implement this.
1511 return indicatePessimisticFixpoint();
1512 }
1513
1514 /// See AbstractAttribute::trackStatistics()
1515 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
1516};
1517
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001518/// NoAlias attribute for function return value.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001519struct AANoAliasReturned final : AANoAliasImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001520 AANoAliasReturned(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001521
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001522 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001523 virtual ChangeStatus updateImpl(Attributor &A) override {
1524
1525 auto CheckReturnValue = [&](Value &RV) -> bool {
1526 if (Constant *C = dyn_cast<Constant>(&RV))
1527 if (C->isNullValue() || isa<UndefValue>(C))
1528 return true;
1529
1530 /// For now, we can only deduce noalias if we have call sites.
1531 /// FIXME: add more support.
1532 ImmutableCallSite ICS(&RV);
1533 if (!ICS)
1534 return false;
1535
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001536 const auto &NoAliasAA =
1537 A.getAAFor<AANoAlias>(*this, IRPosition::callsite_returned(ICS));
1538 if (!NoAliasAA.isAssumedNoAlias())
1539 return false;
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001540
1541 /// FIXME: We can improve capture check in two ways:
1542 /// 1. Use the AANoCapture facilities.
1543 /// 2. Use the location of return insts for escape queries.
1544 if (PointerMayBeCaptured(&RV, /* ReturnCaptures */ false,
1545 /* StoreCaptures */ true))
1546 return false;
1547
1548 return true;
1549 };
1550
1551 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
1552 return indicatePessimisticFixpoint();
1553
1554 return ChangeStatus::UNCHANGED;
1555 }
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001556
1557 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001558 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001559};
1560
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001561/// NoAlias attribute deduction for a call site return value.
1562using AANoAliasCallSiteReturned = AANoAliasReturned;
1563
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001564/// -------------------AAIsDead Function Attribute-----------------------
1565
Johannes Doerfert344d0382019-08-07 22:34:26 +00001566struct AAIsDeadImpl : public AAIsDead {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001567 AAIsDeadImpl(const IRPosition &IRP) : AAIsDead(IRP) {}
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001568
Johannes Doerfertece81902019-08-12 22:05:53 +00001569 void initialize(Attributor &A) override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001570 const Function *F = getAssociatedFunction();
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001571
1572 if (F->hasInternalLinkage())
1573 return;
1574
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001575 if (!F || !F->hasExactDefinition()) {
1576 indicatePessimisticFixpoint();
1577 return;
1578 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001579
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001580 exploreFromEntry(A, F);
1581 }
1582
1583 void exploreFromEntry(Attributor &A, const Function *F) {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001584 ToBeExploredPaths.insert(&(F->getEntryBlock().front()));
1585 AssumedLiveBlocks.insert(&(F->getEntryBlock()));
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001586
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001587 for (size_t i = 0; i < ToBeExploredPaths.size(); ++i)
Johannes Doerfert4361da22019-08-04 18:38:53 +00001588 if (const Instruction *NextNoReturnI =
1589 findNextNoReturn(A, ToBeExploredPaths[i]))
1590 NoReturnCalls.insert(NextNoReturnI);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001591 }
1592
Johannes Doerfert4361da22019-08-04 18:38:53 +00001593 /// Find the next assumed noreturn instruction in the block of \p I starting
1594 /// from, thus including, \p I.
1595 ///
1596 /// The caller is responsible to monitor the ToBeExploredPaths set as new
1597 /// instructions discovered in other basic block will be placed in there.
1598 ///
1599 /// \returns The next assumed noreturn instructions in the block of \p I
1600 /// starting from, thus including, \p I.
1601 const Instruction *findNextNoReturn(Attributor &A, const Instruction *I);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001602
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001603 /// See AbstractAttribute::getAsStr().
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001604 const std::string getAsStr() const override {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001605 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001606 std::to_string(getAssociatedFunction()->size()) + "][#NRI " +
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001607 std::to_string(NoReturnCalls.size()) + "]";
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001608 }
1609
1610 /// See AbstractAttribute::manifest(...).
1611 ChangeStatus manifest(Attributor &A) override {
1612 assert(getState().isValidState() &&
1613 "Attempted to manifest an invalid state!");
1614
1615 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001616 Function &F = *getAssociatedFunction();
1617
1618 if (AssumedLiveBlocks.empty()) {
1619 F.replaceAllUsesWith(UndefValue::get(F.getType()));
1620 return ChangeStatus::CHANGED;
1621 }
Johannes Doerfert924d2132019-08-05 21:34:45 +00001622
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001623 // Flag to determine if we can change an invoke to a call assuming the
1624 // callee is nounwind. This is not possible if the personality of the
1625 // function allows to catch asynchronous exceptions.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001626 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001627
Johannes Doerfert4361da22019-08-04 18:38:53 +00001628 for (const Instruction *NRC : NoReturnCalls) {
1629 Instruction *I = const_cast<Instruction *>(NRC);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001630 BasicBlock *BB = I->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001631 Instruction *SplitPos = I->getNextNode();
Johannes Doerfertd4108052019-08-21 20:56:41 +00001632 // TODO: mark stuff before unreachable instructions as dead.
1633 if (isa_and_nonnull<UnreachableInst>(SplitPos))
1634 continue;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001635
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001636 if (auto *II = dyn_cast<InvokeInst>(I)) {
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001637 // If we keep the invoke the split position is at the beginning of the
1638 // normal desitination block (it invokes a noreturn function after all).
1639 BasicBlock *NormalDestBB = II->getNormalDest();
1640 SplitPos = &NormalDestBB->front();
1641
Johannes Doerfert4361da22019-08-04 18:38:53 +00001642 /// Invoke is replaced with a call and unreachable is placed after it if
1643 /// the callee is nounwind and noreturn. Otherwise, we keep the invoke
1644 /// and only place an unreachable in the normal successor.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001645 if (Invoke2CallAllowed) {
Michael Liaoa99086d2019-08-20 21:02:31 +00001646 if (II->getCalledFunction()) {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001647 const IRPosition &IPos = IRPosition::callsite_function(*II);
1648 const auto &AANoUnw = A.getAAFor<AANoUnwind>(*this, IPos);
1649 if (AANoUnw.isAssumedNoUnwind()) {
Johannes Doerfert924d2132019-08-05 21:34:45 +00001650 LLVM_DEBUG(dbgs()
1651 << "[AAIsDead] Replace invoke with call inst\n");
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001652 // We do not need an invoke (II) but instead want a call followed
1653 // by an unreachable. However, we do not remove II as other
1654 // abstract attributes might have it cached as part of their
1655 // results. Given that we modify the CFG anyway, we simply keep II
1656 // around but in a new dead block. To avoid II being live through
1657 // a different edge we have to ensure the block we place it in is
1658 // only reached from the current block of II and then not reached
1659 // at all when we insert the unreachable.
1660 SplitBlockPredecessors(NormalDestBB, {BB}, ".i2c");
1661 CallInst *CI = createCallMatchingInvoke(II);
1662 CI->insertBefore(II);
1663 CI->takeName(II);
1664 II->replaceAllUsesWith(CI);
1665 SplitPos = CI->getNextNode();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001666 }
Johannes Doerfert4361da22019-08-04 18:38:53 +00001667 }
1668 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001669 }
1670
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001671 BB = SplitPos->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001672 SplitBlock(BB, SplitPos);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001673 changeToUnreachable(BB->getTerminator(), /* UseLLVMTrap */ false);
1674 HasChanged = ChangeStatus::CHANGED;
1675 }
1676
1677 return HasChanged;
1678 }
1679
1680 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001681 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001682
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001683 /// See AAIsDead::isAssumedDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001684 bool isAssumedDead(const BasicBlock *BB) const override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001685 assert(BB->getParent() == getAssociatedFunction() &&
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001686 "BB must be in the same anchor scope function.");
1687
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001688 if (!getAssumed())
1689 return false;
1690 return !AssumedLiveBlocks.count(BB);
1691 }
1692
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001693 /// See AAIsDead::isKnownDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001694 bool isKnownDead(const BasicBlock *BB) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001695 return getKnown() && isAssumedDead(BB);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001696 }
1697
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001698 /// See AAIsDead::isAssumed(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001699 bool isAssumedDead(const Instruction *I) const override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001700 assert(I->getParent()->getParent() == getAssociatedFunction() &&
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001701 "Instruction must be in the same anchor scope function.");
1702
Stefan Stipanovic7849e412019-08-03 15:27:41 +00001703 if (!getAssumed())
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001704 return false;
1705
1706 // If it is not in AssumedLiveBlocks then it for sure dead.
1707 // Otherwise, it can still be after noreturn call in a live block.
1708 if (!AssumedLiveBlocks.count(I->getParent()))
1709 return true;
1710
1711 // If it is not after a noreturn call, than it is live.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001712 return isAfterNoReturn(I);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001713 }
1714
1715 /// See AAIsDead::isKnownDead(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001716 bool isKnownDead(const Instruction *I) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001717 return getKnown() && isAssumedDead(I);
1718 }
1719
1720 /// Check if instruction is after noreturn call, in other words, assumed dead.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001721 bool isAfterNoReturn(const Instruction *I) const;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001722
Johannes Doerfert924d2132019-08-05 21:34:45 +00001723 /// Determine if \p F might catch asynchronous exceptions.
1724 static bool mayCatchAsynchronousExceptions(const Function &F) {
1725 return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F);
1726 }
1727
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001728 /// Collection of to be explored paths.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001729 SmallSetVector<const Instruction *, 8> ToBeExploredPaths;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001730
1731 /// Collection of all assumed live BasicBlocks.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001732 DenseSet<const BasicBlock *> AssumedLiveBlocks;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001733
1734 /// Collection of calls with noreturn attribute, assumed or knwon.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001735 SmallSetVector<const Instruction *, 4> NoReturnCalls;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001736};
1737
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001738struct AAIsDeadFunction final : public AAIsDeadImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001739 AAIsDeadFunction(const IRPosition &IRP) : AAIsDeadImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001740
1741 /// See AbstractAttribute::trackStatistics()
1742 void trackStatistics() const override {
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001743 STATS_DECL(DeadInternalFunction, Function,
1744 "Number of internal functions classified as dead (no live callsite)");
1745 BUILD_STAT_NAME(DeadInternalFunction, Function) +=
1746 (getAssociatedFunction()->hasInternalLinkage() &&
1747 AssumedLiveBlocks.empty())
1748 ? 1
1749 : 0;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001750 STATS_DECL(DeadBlocks, Function,
1751 "Number of basic blocks classified as dead");
1752 BUILD_STAT_NAME(DeadBlocks, Function) +=
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001753 getAssociatedFunction()->size() - AssumedLiveBlocks.size();
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001754 STATS_DECL(PartiallyDeadBlocks, Function,
1755 "Number of basic blocks classified as partially dead");
1756 BUILD_STAT_NAME(PartiallyDeadBlocks, Function) += NoReturnCalls.size();
1757 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001758};
1759
1760bool AAIsDeadImpl::isAfterNoReturn(const Instruction *I) const {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001761 const Instruction *PrevI = I->getPrevNode();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001762 while (PrevI) {
1763 if (NoReturnCalls.count(PrevI))
1764 return true;
1765 PrevI = PrevI->getPrevNode();
1766 }
1767 return false;
1768}
1769
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001770const Instruction *AAIsDeadImpl::findNextNoReturn(Attributor &A,
1771 const Instruction *I) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001772 const BasicBlock *BB = I->getParent();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001773 const Function &F = *BB->getParent();
1774
1775 // Flag to determine if we can change an invoke to a call assuming the callee
1776 // is nounwind. This is not possible if the personality of the function allows
1777 // to catch asynchronous exceptions.
1778 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001779
1780 // TODO: We should have a function that determines if an "edge" is dead.
1781 // Edges could be from an instruction to the next or from a terminator
1782 // to the successor. For now, we need to special case the unwind block
1783 // of InvokeInst below.
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001784
1785 while (I) {
1786 ImmutableCallSite ICS(I);
1787
1788 if (ICS) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001789 const IRPosition &IPos = IRPosition::callsite_function(ICS);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001790 // Regarless of the no-return property of an invoke instruction we only
1791 // learn that the regular successor is not reachable through this
1792 // instruction but the unwind block might still be.
1793 if (auto *Invoke = dyn_cast<InvokeInst>(I)) {
1794 // Use nounwind to justify the unwind block is dead as well.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001795 const auto &AANoUnw = A.getAAFor<AANoUnwind>(*this, IPos);
1796 if (!Invoke2CallAllowed || !AANoUnw.isAssumedNoUnwind()) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001797 AssumedLiveBlocks.insert(Invoke->getUnwindDest());
1798 ToBeExploredPaths.insert(&Invoke->getUnwindDest()->front());
1799 }
1800 }
1801
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001802 const auto &NoReturnAA = A.getAAFor<AANoReturn>(*this, IPos);
1803 if (NoReturnAA.isAssumedNoReturn())
Johannes Doerfert4361da22019-08-04 18:38:53 +00001804 return I;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001805 }
1806
1807 I = I->getNextNode();
1808 }
1809
1810 // get new paths (reachable blocks).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001811 for (const BasicBlock *SuccBB : successors(BB)) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001812 AssumedLiveBlocks.insert(SuccBB);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001813 ToBeExploredPaths.insert(&SuccBB->front());
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001814 }
1815
Johannes Doerfert4361da22019-08-04 18:38:53 +00001816 // No noreturn instruction found.
1817 return nullptr;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001818}
1819
Johannes Doerfertece81902019-08-12 22:05:53 +00001820ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A) {
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001821 const Function *F = getAssociatedFunction();
1822 ChangeStatus Status = ChangeStatus::UNCHANGED;
1823
1824 if (F->hasInternalLinkage() && AssumedLiveBlocks.empty()) {
1825 auto CallSiteCheck = [&](CallSite) { return false; };
1826
1827 // All callsites of F are dead.
1828 if (A.checkForAllCallSites(CallSiteCheck, *this, true))
1829 return ChangeStatus::UNCHANGED;
1830
1831 // There exists at least one live call site, so we explore the function.
1832 Status = ChangeStatus::CHANGED;
1833
1834 exploreFromEntry(A, F);
1835 }
1836
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001837 // Temporary collection to iterate over existing noreturn instructions. This
1838 // will alow easier modification of NoReturnCalls collection
Johannes Doerfert4361da22019-08-04 18:38:53 +00001839 SmallVector<const Instruction *, 8> NoReturnChanged;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001840
Johannes Doerfert4361da22019-08-04 18:38:53 +00001841 for (const Instruction *I : NoReturnCalls)
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001842 NoReturnChanged.push_back(I);
1843
Johannes Doerfert4361da22019-08-04 18:38:53 +00001844 for (const Instruction *I : NoReturnChanged) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001845 size_t Size = ToBeExploredPaths.size();
1846
Johannes Doerfert4361da22019-08-04 18:38:53 +00001847 const Instruction *NextNoReturnI = findNextNoReturn(A, I);
1848 if (NextNoReturnI != I) {
1849 Status = ChangeStatus::CHANGED;
1850 NoReturnCalls.remove(I);
1851 if (NextNoReturnI)
1852 NoReturnCalls.insert(NextNoReturnI);
1853 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001854
Johannes Doerfert4361da22019-08-04 18:38:53 +00001855 // Explore new paths.
1856 while (Size != ToBeExploredPaths.size()) {
1857 Status = ChangeStatus::CHANGED;
1858 if (const Instruction *NextNoReturnI =
1859 findNextNoReturn(A, ToBeExploredPaths[Size++]))
1860 NoReturnCalls.insert(NextNoReturnI);
1861 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001862 }
1863
Johannes Doerfertdef99282019-08-14 21:29:37 +00001864 LLVM_DEBUG(dbgs() << "[AAIsDead] AssumedLiveBlocks: "
1865 << AssumedLiveBlocks.size() << " Total number of blocks: "
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001866 << getAssociatedFunction()->size() << "\n");
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001867
Johannes Doerfertd6207812019-08-07 22:32:38 +00001868 // If we know everything is live there is no need to query for liveness.
1869 if (NoReturnCalls.empty() &&
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001870 getAssociatedFunction()->size() == AssumedLiveBlocks.size()) {
Johannes Doerfertd6207812019-08-07 22:32:38 +00001871 // Indicating a pessimistic fixpoint will cause the state to be "invalid"
1872 // which will cause the Attributor to not return the AAIsDead on request,
1873 // which will prevent us from querying isAssumedDead().
1874 indicatePessimisticFixpoint();
1875 assert(!isValidState() && "Expected an invalid state!");
1876 }
1877
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001878 return Status;
1879}
1880
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001881/// Liveness information for a call sites.
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001882//
1883// TODO: Once we have call site specific value information we can provide call
1884// site specific liveness liveness information and then it makes sense to
1885// specialize attributes for call sites instead of redirecting requests to
1886// the callee.
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001887using AAIsDeadCallSite = AAIsDeadFunction;
1888
Hideto Ueno19c07af2019-07-23 08:16:17 +00001889/// -------------------- Dereferenceable Argument Attribute --------------------
1890
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001891template <>
1892ChangeStatus clampStateAndIndicateChange<DerefState>(DerefState &S,
1893 const DerefState &R) {
1894 ChangeStatus CS0 = clampStateAndIndicateChange<IntegerState>(
1895 S.DerefBytesState, R.DerefBytesState);
1896 ChangeStatus CS1 =
1897 clampStateAndIndicateChange<IntegerState>(S.GlobalState, R.GlobalState);
1898 return CS0 | CS1;
1899}
1900
Hideto Ueno70576ca2019-08-22 14:18:29 +00001901struct AADereferenceableImpl : AADereferenceable {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001902 AADereferenceableImpl(const IRPosition &IRP) : AADereferenceable(IRP) {}
Johannes Doerfert344d0382019-08-07 22:34:26 +00001903 using StateType = DerefState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001904
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001905 void initialize(Attributor &A) override {
1906 SmallVector<Attribute, 4> Attrs;
1907 getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
1908 Attrs);
1909 for (const Attribute &Attr : Attrs)
1910 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
1911
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001912 NonNullAA = &A.getAAFor<AANonNull>(*this, getIRPosition());
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001913 }
1914
Hideto Ueno19c07af2019-07-23 08:16:17 +00001915 /// See AbstractAttribute::getState()
1916 /// {
Johannes Doerfert344d0382019-08-07 22:34:26 +00001917 StateType &getState() override { return *this; }
1918 const StateType &getState() const override { return *this; }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001919 /// }
1920
Johannes Doerferteccdf082019-08-05 23:35:12 +00001921 void getDeducedAttributes(LLVMContext &Ctx,
1922 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001923 // TODO: Add *_globally support
1924 if (isAssumedNonNull())
1925 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
1926 Ctx, getAssumedDereferenceableBytes()));
1927 else
1928 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
1929 Ctx, getAssumedDereferenceableBytes()));
1930 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001931
1932 /// See AbstractAttribute::getAsStr().
1933 const std::string getAsStr() const override {
1934 if (!getAssumedDereferenceableBytes())
1935 return "unknown-dereferenceable";
1936 return std::string("dereferenceable") +
1937 (isAssumedNonNull() ? "" : "_or_null") +
1938 (isAssumedGlobal() ? "_globally" : "") + "<" +
1939 std::to_string(getKnownDereferenceableBytes()) + "-" +
1940 std::to_string(getAssumedDereferenceableBytes()) + ">";
1941 }
1942};
1943
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001944/// Dereferenceable attribute for a floating value.
1945struct AADereferenceableFloating : AADereferenceableImpl {
1946 AADereferenceableFloating(const IRPosition &IRP)
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001947 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001948
1949 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001950 ChangeStatus updateImpl(Attributor &A) override {
1951 const DataLayout &DL = A.getDataLayout();
1952
1953 auto VisitValueCB = [&](Value &V, DerefState &T, bool Stripped) -> bool {
1954 unsigned IdxWidth =
1955 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
1956 APInt Offset(IdxWidth, 0);
1957 const Value *Base =
1958 V.stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
1959
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001960 const auto &AA =
1961 A.getAAFor<AADereferenceable>(*this, IRPosition::value(*Base));
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001962 int64_t DerefBytes = 0;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001963 if (!Stripped && this == &AA) {
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001964 // Use IR information if we did not strip anything.
1965 // TODO: track globally.
1966 bool CanBeNull;
1967 DerefBytes = Base->getPointerDereferenceableBytes(DL, CanBeNull);
1968 T.GlobalState.indicatePessimisticFixpoint();
1969 } else {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001970 const DerefState &DS = static_cast<const DerefState &>(AA.getState());
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001971 DerefBytes = DS.DerefBytesState.getAssumed();
1972 T.GlobalState &= DS.GlobalState;
1973 }
1974
1975 T.takeAssumedDerefBytesMinimum(
1976 std::max(int64_t(0), DerefBytes - Offset.getSExtValue()));
1977
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001978 if (!Stripped && this == &AA) {
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001979 T.takeKnownDerefBytesMaximum(
1980 std::max(int64_t(0), DerefBytes - Offset.getSExtValue()));
1981 T.indicatePessimisticFixpoint();
1982 }
1983
1984 return T.isValidState();
1985 };
1986
1987 DerefState T;
1988 if (!genericValueTraversal<AADereferenceable, DerefState>(
1989 A, getIRPosition(), *this, T, VisitValueCB))
1990 return indicatePessimisticFixpoint();
1991
1992 return clampStateAndIndicateChange(getState(), T);
1993 }
1994
1995 /// See AbstractAttribute::trackStatistics()
1996 void trackStatistics() const override {
1997 STATS_DECLTRACK_FLOATING_ATTR(dereferenceable)
1998 }
1999};
2000
2001/// Dereferenceable attribute for a return value.
2002struct AADereferenceableReturned final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002003 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl,
2004 DerefState> {
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002005 AADereferenceableReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002006 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl,
2007 DerefState>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002008
2009 /// See AbstractAttribute::trackStatistics()
2010 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002011 STATS_DECLTRACK_FNRET_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002012 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002013};
2014
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002015/// Dereferenceable attribute for an argument
2016struct AADereferenceableArgument final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002017 : AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl,
2018 DerefState> {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002019 AADereferenceableArgument(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002020 : AAArgumentFromCallSiteArguments<AADereferenceable,
2021 AADereferenceableImpl, DerefState>(
2022 IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002023
2024 /// See AbstractAttribute::trackStatistics()
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002025 void trackStatistics() const override{
Johannes Doerfert169af992019-08-20 06:09:56 +00002026 STATS_DECLTRACK_ARG_ATTR(dereferenceable)
2027 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002028};
2029
Hideto Ueno19c07af2019-07-23 08:16:17 +00002030/// Dereferenceable attribute for a call site argument.
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002031struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002032 AADereferenceableCallSiteArgument(const IRPosition &IRP)
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002033 : AADereferenceableFloating(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002034
2035 /// See AbstractAttribute::trackStatistics()
2036 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002037 STATS_DECLTRACK_CSARG_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002038 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002039};
2040
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002041/// Dereferenceable attribute deduction for a call site return value.
2042using AADereferenceableCallSiteReturned = AADereferenceableReturned;
2043
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002044// ------------------------ Align Argument Attribute ------------------------
2045
Johannes Doerfert344d0382019-08-07 22:34:26 +00002046struct AAAlignImpl : AAAlign {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002047 AAAlignImpl(const IRPosition &IRP) : AAAlign(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002048
2049 // Max alignemnt value allowed in IR
2050 static const unsigned MAX_ALIGN = 1U << 29;
2051
Johannes Doerfert234eda52019-08-16 19:51:23 +00002052 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002053 void initialize(Attributor &A) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002054 takeAssumedMinimum(MAX_ALIGN);
2055
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002056 SmallVector<Attribute, 4> Attrs;
2057 getAttrs({Attribute::Alignment}, Attrs);
2058 for (const Attribute &Attr : Attrs)
2059 takeKnownMaximum(Attr.getValueAsInt());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002060 }
2061
2062 /// See AbstractAttribute::getDeducedAttributes
2063 virtual void
Johannes Doerferteccdf082019-08-05 23:35:12 +00002064 getDeducedAttributes(LLVMContext &Ctx,
2065 SmallVectorImpl<Attribute> &Attrs) const override {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002066 if (getAssumedAlign() > 1)
2067 Attrs.emplace_back(Attribute::getWithAlignment(Ctx, getAssumedAlign()));
2068 }
2069
2070 /// See AbstractAttribute::getAsStr().
2071 const std::string getAsStr() const override {
2072 return getAssumedAlign() ? ("align<" + std::to_string(getKnownAlign()) +
2073 "-" + std::to_string(getAssumedAlign()) + ">")
2074 : "unknown-align";
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002075 }
2076};
2077
Johannes Doerfert234eda52019-08-16 19:51:23 +00002078/// Align attribute for a floating value.
2079struct AAAlignFloating : AAAlignImpl {
2080 AAAlignFloating(const IRPosition &IRP) : AAAlignImpl(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002081
2082 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert234eda52019-08-16 19:51:23 +00002083 ChangeStatus updateImpl(Attributor &A) override {
2084 const DataLayout &DL = A.getDataLayout();
2085
Johannes Doerfertb9b87912019-08-20 06:02:39 +00002086 auto VisitValueCB = [&](Value &V, AAAlign::StateType &T,
2087 bool Stripped) -> bool {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002088 const auto &AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V));
2089 if (!Stripped && this == &AA) {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002090 // Use only IR information if we did not strip anything.
2091 T.takeKnownMaximum(V.getPointerAlignment(DL));
2092 T.indicatePessimisticFixpoint();
Johannes Doerfert234eda52019-08-16 19:51:23 +00002093 } else {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002094 // Use abstract attribute information.
2095 const AAAlign::StateType &DS =
2096 static_cast<const AAAlign::StateType &>(AA.getState());
2097 T ^= DS;
Johannes Doerfert234eda52019-08-16 19:51:23 +00002098 }
Johannes Doerfertb9b87912019-08-20 06:02:39 +00002099 return T.isValidState();
Johannes Doerfert234eda52019-08-16 19:51:23 +00002100 };
2101
2102 StateType T;
2103 if (!genericValueTraversal<AAAlign, StateType>(A, getIRPosition(), *this, T,
2104 VisitValueCB))
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002105 return indicatePessimisticFixpoint();
Johannes Doerfert234eda52019-08-16 19:51:23 +00002106
Johannes Doerfert028b2aa2019-08-20 05:57:01 +00002107 // TODO: If we know we visited all incoming values, thus no are assumed
2108 // dead, we can take the known information from the state T.
Johannes Doerfert234eda52019-08-16 19:51:23 +00002109 return clampStateAndIndicateChange(getState(), T);
2110 }
2111
2112 /// See AbstractAttribute::trackStatistics()
2113 void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) }
2114};
2115
2116/// Align attribute for function return value.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002117struct AAAlignReturned final
2118 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002119 AAAlignReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002120 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002121
2122 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002123 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002124};
2125
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002126/// Align attribute for function argument.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002127struct AAAlignArgument final
2128 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002129 AAAlignArgument(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002130 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002131
2132 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert169af992019-08-20 06:09:56 +00002133 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002134};
2135
Johannes Doerfert234eda52019-08-16 19:51:23 +00002136struct AAAlignCallSiteArgument final : AAAlignFloating {
2137 AAAlignCallSiteArgument(const IRPosition &IRP) : AAAlignFloating(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002138
2139 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002140 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002141};
2142
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002143/// Align attribute deduction for a call site return value.
2144using AAAlignCallSiteReturned = AAAlignReturned;
2145
Johannes Doerferte83f3032019-08-05 23:22:05 +00002146/// ------------------ Function No-Return Attribute ----------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00002147struct AANoReturnImpl : public AANoReturn {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002148 AANoReturnImpl(const IRPosition &IRP) : AANoReturn(IRP) {}
Johannes Doerferte83f3032019-08-05 23:22:05 +00002149
Johannes Doerferte83f3032019-08-05 23:22:05 +00002150 /// See AbstractAttribute::getAsStr().
2151 const std::string getAsStr() const override {
2152 return getAssumed() ? "noreturn" : "may-return";
2153 }
2154
2155 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002156 void initialize(Attributor &A) override {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002157 if (hasAttr({getAttrKind()}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002158 indicateOptimisticFixpoint();
2159 }
2160
2161 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00002162 virtual ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002163 auto CheckForNoReturn = [](Instruction &) { return false; };
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002164 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002165 {(unsigned)Instruction::Ret}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002166 return indicatePessimisticFixpoint();
Johannes Doerferte83f3032019-08-05 23:22:05 +00002167 return ChangeStatus::UNCHANGED;
2168 }
2169};
2170
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002171struct AANoReturnFunction final : AANoReturnImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002172 AANoReturnFunction(const IRPosition &IRP) : AANoReturnImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002173
2174 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002175 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002176};
2177
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002178/// NoReturn attribute deduction for a call sites.
2179using AANoReturnCallSite = AANoReturnFunction;
2180
Johannes Doerfertaade7822019-06-05 03:02:24 +00002181/// ----------------------------------------------------------------------------
2182/// Attributor
2183/// ----------------------------------------------------------------------------
2184
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002185bool Attributor::isAssumedDead(const AbstractAttribute &AA,
2186 const AAIsDead *LivenessAA) {
2187 const Instruction *CtxI = AA.getIRPosition().getCtxI();
2188 if (!CtxI)
2189 return false;
2190
2191 if (!LivenessAA)
2192 LivenessAA =
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002193 &getAAFor<AAIsDead>(AA, IRPosition::function(*CtxI->getFunction()));
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00002194
2195 // Don't check liveness for AAIsDead.
2196 if (&AA == LivenessAA)
2197 return false;
2198
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002199 if (!LivenessAA->isAssumedDead(CtxI))
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002200 return false;
2201
2202 // TODO: Do not track dependences automatically but add it here as only a
2203 // "is-assumed-dead" result causes a dependence.
2204 return true;
2205}
2206
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002207bool Attributor::checkForAllCallSites(const function_ref<bool(CallSite)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002208 const AbstractAttribute &QueryingAA,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002209 bool RequireAllCallSites) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002210 // We can try to determine information from
2211 // the call sites. However, this is only possible all call sites are known,
2212 // hence the function has internal linkage.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002213 const IRPosition &IRP = QueryingAA.getIRPosition();
2214 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2215 if (!AssociatedFunction)
2216 return false;
2217
2218 if (RequireAllCallSites && !AssociatedFunction->hasInternalLinkage()) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002219 LLVM_DEBUG(
2220 dbgs()
Johannes Doerfert5304b722019-08-14 22:04:28 +00002221 << "[Attributor] Function " << AssociatedFunction->getName()
Hideto Ueno54869ec2019-07-15 06:49:04 +00002222 << " has no internal linkage, hence not all call sites are known\n");
2223 return false;
2224 }
2225
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002226 for (const Use &U : AssociatedFunction->uses()) {
Johannes Doerfertd98f9752019-08-21 21:48:56 +00002227 Instruction *I = dyn_cast<Instruction>(U.getUser());
2228 // TODO: Deal with abstract call sites here.
2229 if (!I)
2230 return false;
2231
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002232 Function *Caller = I->getFunction();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002233
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002234 const auto &LivenessAA =
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002235 getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*Caller));
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002236
2237 // Skip dead calls.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002238 if (LivenessAA.isAssumedDead(I))
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002239 continue;
Hideto Ueno54869ec2019-07-15 06:49:04 +00002240
2241 CallSite CS(U.getUser());
Hideto Ueno54869ec2019-07-15 06:49:04 +00002242 if (!CS || !CS.isCallee(&U) || !CS.getCaller()->hasExactDefinition()) {
2243 if (!RequireAllCallSites)
2244 continue;
2245
Johannes Doerfert5304b722019-08-14 22:04:28 +00002246 LLVM_DEBUG(dbgs() << "[Attributor] User " << *U.getUser()
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002247 << " is an invalid use of "
2248 << AssociatedFunction->getName() << "\n");
Hideto Ueno54869ec2019-07-15 06:49:04 +00002249 return false;
2250 }
2251
2252 if (Pred(CS))
2253 continue;
2254
Johannes Doerfert5304b722019-08-14 22:04:28 +00002255 LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for "
Hideto Ueno54869ec2019-07-15 06:49:04 +00002256 << *CS.getInstruction() << "\n");
2257 return false;
2258 }
2259
2260 return true;
2261}
2262
Johannes Doerfert14a04932019-08-07 22:27:24 +00002263bool Attributor::checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +00002264 const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)>
Johannes Doerfert14a04932019-08-07 22:27:24 +00002265 &Pred,
2266 const AbstractAttribute &QueryingAA) {
2267
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002268 const IRPosition &IRP = QueryingAA.getIRPosition();
2269 // Since we need to provide return instructions we have to have an exact
2270 // definition.
2271 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2272 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
Johannes Doerfert14a04932019-08-07 22:27:24 +00002273 return false;
2274
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002275 // If this is a call site query we use the call site specific return values
2276 // and liveness information.
2277 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2278 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002279 if (!AARetVal.getState().isValidState())
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002280 return false;
2281
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002282 return AARetVal.checkForAllReturnedValuesAndReturnInsts(Pred);
Johannes Doerfert14a04932019-08-07 22:27:24 +00002283}
2284
2285bool Attributor::checkForAllReturnedValues(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002286 const function_ref<bool(Value &)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002287 const AbstractAttribute &QueryingAA) {
2288
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002289 const IRPosition &IRP = QueryingAA.getIRPosition();
2290 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2291 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
Johannes Doerfert14a04932019-08-07 22:27:24 +00002292 return false;
2293
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002294 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2295 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002296 if (!AARetVal.getState().isValidState())
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002297 return false;
2298
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002299 return AARetVal.checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +00002300 [&](Value &RV, const SmallSetVector<ReturnInst *, 4> &) {
Johannes Doerfertdef99282019-08-14 21:29:37 +00002301 return Pred(RV);
2302 });
Johannes Doerfert14a04932019-08-07 22:27:24 +00002303}
2304
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002305bool Attributor::checkForAllInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002306 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00002307 const AbstractAttribute &QueryingAA, const ArrayRef<unsigned> &Opcodes) {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002308
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002309 const IRPosition &IRP = QueryingAA.getIRPosition();
2310 // Since we need to provide instructions we have to have an exact definition.
2311 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2312 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
2313 return false;
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002314
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002315 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2316 const auto &LivenessAA = getAAFor<AAIsDead>(QueryingAA, QueryIRP);
2317
2318 auto &OpcodeInstMap =
2319 InfoCache.getOpcodeInstMapForFunction(*AssociatedFunction);
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002320 for (unsigned Opcode : Opcodes) {
2321 for (Instruction *I : OpcodeInstMap[Opcode]) {
2322 // Skip dead instructions.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002323 if (LivenessAA.isAssumedDead(I))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002324 continue;
2325
2326 if (!Pred(*I))
2327 return false;
2328 }
2329 }
2330
2331 return true;
2332}
2333
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002334bool Attributor::checkForAllReadWriteInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002335 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00002336 AbstractAttribute &QueryingAA) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002337
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002338 const Function *AssociatedFunction =
2339 QueryingAA.getIRPosition().getAssociatedFunction();
2340 if (!AssociatedFunction)
2341 return false;
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002342
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002343 const auto &LivenessAA =
2344 getAAFor<AAIsDead>(QueryingAA, QueryingAA.getIRPosition());
2345
2346 for (Instruction *I :
2347 InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002348 // Skip dead instructions.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002349 if (LivenessAA.isAssumedDead(I))
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002350 continue;
2351
2352 if (!Pred(*I))
2353 return false;
2354 }
2355
2356 return true;
2357}
2358
Johannes Doerfertece81902019-08-12 22:05:53 +00002359ChangeStatus Attributor::run() {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002360 // Initialize all abstract attributes, allow new ones to be created.
2361 for (unsigned u = 0; u < AllAbstractAttributes.size(); u++)
2362 AllAbstractAttributes[u]->initialize(*this);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002363
2364 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
2365 << AllAbstractAttributes.size()
2366 << " abstract attributes.\n");
2367
Stefan Stipanovic53605892019-06-27 11:27:54 +00002368 // Now that all abstract attributes are collected and initialized we start
2369 // the abstract analysis.
Johannes Doerfertaade7822019-06-05 03:02:24 +00002370
2371 unsigned IterationCounter = 1;
2372
2373 SmallVector<AbstractAttribute *, 64> ChangedAAs;
2374 SetVector<AbstractAttribute *> Worklist;
2375 Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
2376
2377 do {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002378 // Remember the size to determine new attributes.
2379 size_t NumAAs = AllAbstractAttributes.size();
Johannes Doerfertaade7822019-06-05 03:02:24 +00002380 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
2381 << ", Worklist size: " << Worklist.size() << "\n");
2382
2383 // Add all abstract attributes that are potentially dependent on one that
2384 // changed to the work list.
2385 for (AbstractAttribute *ChangedAA : ChangedAAs) {
2386 auto &QuerriedAAs = QueryMap[ChangedAA];
2387 Worklist.insert(QuerriedAAs.begin(), QuerriedAAs.end());
2388 }
2389
2390 // Reset the changed set.
2391 ChangedAAs.clear();
2392
2393 // Update all abstract attribute in the work list and record the ones that
2394 // changed.
2395 for (AbstractAttribute *AA : Worklist)
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002396 if (!isAssumedDead(*AA, nullptr))
2397 if (AA->update(*this) == ChangeStatus::CHANGED)
2398 ChangedAAs.push_back(AA);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002399
Johannes Doerfert9543f142019-08-23 15:24:57 +00002400 // Add attributes to the changed set if they have been created in the last
2401 // iteration.
2402 ChangedAAs.append(AllAbstractAttributes.begin() + NumAAs,
2403 AllAbstractAttributes.end());
2404
Johannes Doerfertaade7822019-06-05 03:02:24 +00002405 // Reset the work list and repopulate with the changed abstract attributes.
2406 // Note that dependent ones are added above.
2407 Worklist.clear();
2408 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2409
2410 } while (!Worklist.empty() && ++IterationCounter < MaxFixpointIterations);
2411
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002412 size_t NumFinalAAs = AllAbstractAttributes.size();
2413
Johannes Doerfertaade7822019-06-05 03:02:24 +00002414 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
2415 << IterationCounter << "/" << MaxFixpointIterations
2416 << " iterations\n");
2417
2418 bool FinishedAtFixpoint = Worklist.empty();
2419
2420 // Reset abstract arguments not settled in a sound fixpoint by now. This
2421 // happens when we stopped the fixpoint iteration early. Note that only the
2422 // ones marked as "changed" *and* the ones transitively depending on them
2423 // need to be reverted to a pessimistic state. Others might not be in a
2424 // fixpoint state but we can use the optimistic results for them anyway.
2425 SmallPtrSet<AbstractAttribute *, 32> Visited;
2426 for (unsigned u = 0; u < ChangedAAs.size(); u++) {
2427 AbstractAttribute *ChangedAA = ChangedAAs[u];
2428 if (!Visited.insert(ChangedAA).second)
2429 continue;
2430
2431 AbstractState &State = ChangedAA->getState();
2432 if (!State.isAtFixpoint()) {
2433 State.indicatePessimisticFixpoint();
2434
2435 NumAttributesTimedOut++;
2436 }
2437
2438 auto &QuerriedAAs = QueryMap[ChangedAA];
2439 ChangedAAs.append(QuerriedAAs.begin(), QuerriedAAs.end());
2440 }
2441
2442 LLVM_DEBUG({
2443 if (!Visited.empty())
2444 dbgs() << "\n[Attributor] Finalized " << Visited.size()
2445 << " abstract attributes.\n";
2446 });
2447
2448 unsigned NumManifested = 0;
2449 unsigned NumAtFixpoint = 0;
2450 ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
2451 for (AbstractAttribute *AA : AllAbstractAttributes) {
2452 AbstractState &State = AA->getState();
2453
2454 // If there is not already a fixpoint reached, we can now take the
2455 // optimistic state. This is correct because we enforced a pessimistic one
2456 // on abstract attributes that were transitively dependent on a changed one
2457 // already above.
2458 if (!State.isAtFixpoint())
2459 State.indicateOptimisticFixpoint();
2460
2461 // If the state is invalid, we do not try to manifest it.
2462 if (!State.isValidState())
2463 continue;
2464
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002465 // Skip dead code.
2466 if (isAssumedDead(*AA, nullptr))
2467 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002468 // Manifest the state and record if we changed the IR.
2469 ChangeStatus LocalChange = AA->manifest(*this);
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002470 if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled())
2471 AA->trackStatistics();
2472
Johannes Doerfertaade7822019-06-05 03:02:24 +00002473 ManifestChange = ManifestChange | LocalChange;
2474
2475 NumAtFixpoint++;
2476 NumManifested += (LocalChange == ChangeStatus::CHANGED);
2477 }
2478
2479 (void)NumManifested;
2480 (void)NumAtFixpoint;
2481 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
2482 << " arguments while " << NumAtFixpoint
2483 << " were in a valid fixpoint state\n");
2484
2485 // If verification is requested, we finished this run at a fixpoint, and the
2486 // IR was changed, we re-run the whole fixpoint analysis, starting at
2487 // re-initialization of the arguments. This re-run should not result in an IR
2488 // change. Though, the (virtual) state of attributes at the end of the re-run
2489 // might be more optimistic than the known state or the IR state if the better
2490 // state cannot be manifested.
2491 if (VerifyAttributor && FinishedAtFixpoint &&
2492 ManifestChange == ChangeStatus::CHANGED) {
2493 VerifyAttributor = false;
Johannes Doerfertece81902019-08-12 22:05:53 +00002494 ChangeStatus VerifyStatus = run();
Johannes Doerfertaade7822019-06-05 03:02:24 +00002495 if (VerifyStatus != ChangeStatus::UNCHANGED)
2496 llvm_unreachable(
2497 "Attributor verification failed, re-run did result in an IR change "
2498 "even after a fixpoint was reached in the original run. (False "
2499 "positives possible!)");
2500 VerifyAttributor = true;
2501 }
2502
2503 NumAttributesManifested += NumManifested;
2504 NumAttributesValidFixpoint += NumAtFixpoint;
2505
Fangrui Songf1826172019-08-20 07:21:43 +00002506 (void)NumFinalAAs;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002507 assert(
2508 NumFinalAAs == AllAbstractAttributes.size() &&
2509 "Expected the final number of abstract attributes to remain unchanged!");
Johannes Doerfertaade7822019-06-05 03:02:24 +00002510 return ManifestChange;
2511}
2512
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002513/// Helper function that checks if an abstract attribute of type \p AAType
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002514/// should be created for IR position \p IRP and if so creates and registers it
2515/// with the Attributor \p A.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002516///
2517/// This method will look at the provided whitelist. If one is given and the
2518/// kind \p AAType::ID is not contained, no abstract attribute is created.
2519///
2520/// \returns The created abstract argument, or nullptr if none was created.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002521template <typename AAType>
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002522static const AAType *checkAndRegisterAA(const IRPosition &IRP, Attributor &A,
2523 DenseSet<const char *> *Whitelist) {
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002524 if (Whitelist && !Whitelist->count(&AAType::ID))
2525 return nullptr;
2526
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002527 return &A.registerAA<AAType>(*new AAType(IRP));
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002528}
2529
Johannes Doerfertaade7822019-06-05 03:02:24 +00002530void Attributor::identifyDefaultAbstractAttributes(
Johannes Doerfertece81902019-08-12 22:05:53 +00002531 Function &F, DenseSet<const char *> *Whitelist) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002532
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002533 IRPosition FPos = IRPosition::function(F);
2534
Johannes Doerfert305b9612019-08-04 18:40:01 +00002535 // Check for dead BasicBlocks in every function.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002536 // We need dead instruction detection because we do not want to deal with
2537 // broken IR in which SSA rules do not apply.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002538 checkAndRegisterAA<AAIsDeadFunction>(FPos, *this, /* Whitelist */ nullptr);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002539
2540 // Every function might be "will-return".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002541 checkAndRegisterAA<AAWillReturnFunction>(FPos, *this, Whitelist);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002542
Stefan Stipanovic53605892019-06-27 11:27:54 +00002543 // Every function can be nounwind.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002544 checkAndRegisterAA<AANoUnwindFunction>(FPos, *this, Whitelist);
Stefan Stipanovic53605892019-06-27 11:27:54 +00002545
Stefan Stipanovic06263672019-07-11 21:37:40 +00002546 // Every function might be marked "nosync"
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002547 checkAndRegisterAA<AANoSyncFunction>(FPos, *this, Whitelist);
Stefan Stipanovic06263672019-07-11 21:37:40 +00002548
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002549 // Every function might be "no-free".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002550 checkAndRegisterAA<AANoFreeFunction>(FPos, *this, Whitelist);
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002551
Johannes Doerferte83f3032019-08-05 23:22:05 +00002552 // Every function might be "no-return".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002553 checkAndRegisterAA<AANoReturnFunction>(FPos, *this, Whitelist);
Johannes Doerferte83f3032019-08-05 23:22:05 +00002554
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002555 // Return attributes are only appropriate if the return type is non void.
2556 Type *ReturnType = F.getReturnType();
2557 if (!ReturnType->isVoidTy()) {
2558 // Argument attribute "returned" --- Create only one per function even
2559 // though it is an argument attribute.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002560 checkAndRegisterAA<AAReturnedValuesFunction>(FPos, *this, Whitelist);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002561
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002562 if (ReturnType->isPointerTy()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002563 IRPosition RetPos = IRPosition::returned(F);
2564
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002565 // Every function with pointer return type might be marked align.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002566 checkAndRegisterAA<AAAlignReturned>(RetPos, *this, Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002567
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002568 // Every function with pointer return type might be marked nonnull.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002569 checkAndRegisterAA<AANonNullReturned>(RetPos, *this, Whitelist);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002570
2571 // Every function with pointer return type might be marked noalias.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002572 checkAndRegisterAA<AANoAliasReturned>(RetPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002573
2574 // Every function with pointer return type might be marked
2575 // dereferenceable.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002576 checkAndRegisterAA<AADereferenceableReturned>(RetPos, *this, Whitelist);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002577 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00002578 }
2579
Hideto Ueno54869ec2019-07-15 06:49:04 +00002580 for (Argument &Arg : F.args()) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002581 if (Arg.getType()->isPointerTy()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002582 IRPosition ArgPos = IRPosition::argument(Arg);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002583 // Every argument with pointer type might be marked nonnull.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002584 checkAndRegisterAA<AANonNullArgument>(ArgPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002585
2586 // Every argument with pointer type might be marked dereferenceable.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002587 checkAndRegisterAA<AADereferenceableArgument>(ArgPos, *this, Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002588
2589 // Every argument with pointer type might be marked align.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002590 checkAndRegisterAA<AAAlignArgument>(ArgPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002591 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002592 }
2593
Johannes Doerfertaade7822019-06-05 03:02:24 +00002594 // Walk all instructions to find more attribute opportunities and also
2595 // interesting instructions that might be queried by abstract attributes
2596 // during their initialization or update.
2597 auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
2598 auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
2599
2600 for (Instruction &I : instructions(&F)) {
2601 bool IsInterestingOpcode = false;
2602
2603 // To allow easy access to all instructions in a function with a given
2604 // opcode we store them in the InfoCache. As not all opcodes are interesting
2605 // to concrete attributes we only cache the ones that are as identified in
2606 // the following switch.
2607 // Note: There are no concrete attributes now so this is initially empty.
Stefan Stipanovic53605892019-06-27 11:27:54 +00002608 switch (I.getOpcode()) {
2609 default:
2610 assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) &&
2611 "New call site/base instruction type needs to be known int the "
2612 "attributor.");
2613 break;
2614 case Instruction::Call:
2615 case Instruction::CallBr:
2616 case Instruction::Invoke:
2617 case Instruction::CleanupRet:
2618 case Instruction::CatchSwitch:
2619 case Instruction::Resume:
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002620 case Instruction::Ret:
Stefan Stipanovic53605892019-06-27 11:27:54 +00002621 IsInterestingOpcode = true;
2622 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002623 if (IsInterestingOpcode)
2624 InstOpcodeMap[I.getOpcode()].push_back(&I);
2625 if (I.mayReadOrWriteMemory())
2626 ReadOrWriteInsts.push_back(&I);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002627
2628 CallSite CS(&I);
2629 if (CS && CS.getCalledFunction()) {
2630 for (int i = 0, e = CS.getCalledFunction()->arg_size(); i < e; i++) {
2631 if (!CS.getArgument(i)->getType()->isPointerTy())
2632 continue;
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002633 IRPosition CSArgPos = IRPosition::callsite_argument(CS, i);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002634
2635 // Call site argument attribute "non-null".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002636 checkAndRegisterAA<AANonNullCallSiteArgument>(CSArgPos, *this,
2637 Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002638
2639 // Call site argument attribute "dereferenceable".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002640 checkAndRegisterAA<AADereferenceableCallSiteArgument>(CSArgPos, *this,
2641 Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002642
2643 // Call site argument attribute "align".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002644 checkAndRegisterAA<AAAlignCallSiteArgument>(CSArgPos, *this, Whitelist);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002645 }
2646 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002647 }
2648}
2649
2650/// Helpers to ease debugging through output streams and print calls.
2651///
2652///{
2653raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
2654 return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
2655}
2656
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002657raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002658 switch (AP) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002659 case IRPosition::IRP_INVALID:
2660 return OS << "inv";
2661 case IRPosition::IRP_FLOAT:
2662 return OS << "flt";
2663 case IRPosition::IRP_RETURNED:
2664 return OS << "fn_ret";
2665 case IRPosition::IRP_CALL_SITE_RETURNED:
2666 return OS << "cs_ret";
2667 case IRPosition::IRP_FUNCTION:
2668 return OS << "fn";
2669 case IRPosition::IRP_CALL_SITE:
2670 return OS << "cs";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002671 case IRPosition::IRP_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002672 return OS << "arg";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002673 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002674 return OS << "cs_arg";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002675 }
2676 llvm_unreachable("Unknown attribute position!");
2677}
2678
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002679raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002680 const Value &AV = Pos.getAssociatedValue();
2681 return OS << "{" << Pos.getPositionKind() << ":" << AV.getName() << " ["
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002682 << Pos.getAnchorValue().getName() << "@" << Pos.getArgNo() << "]}";
2683}
2684
Johannes Doerfertacc80792019-08-12 22:07:34 +00002685raw_ostream &llvm::operator<<(raw_ostream &OS, const IntegerState &S) {
2686 return OS << "(" << S.getKnown() << "-" << S.getAssumed() << ")"
2687 << static_cast<const AbstractState &>(S);
2688}
2689
Johannes Doerfertaade7822019-06-05 03:02:24 +00002690raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
2691 return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
2692}
2693
2694raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
2695 AA.print(OS);
2696 return OS;
2697}
2698
2699void AbstractAttribute::print(raw_ostream &OS) const {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002700 OS << "[P: " << getIRPosition() << "][" << getAsStr() << "][S: " << getState()
2701 << "]";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002702}
2703///}
2704
2705/// ----------------------------------------------------------------------------
2706/// Pass (Manager) Boilerplate
2707/// ----------------------------------------------------------------------------
2708
2709static bool runAttributorOnModule(Module &M) {
2710 if (DisableAttributor)
2711 return false;
2712
2713 LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << M.size()
2714 << " functions.\n");
2715
2716 // Create an Attributor and initially empty information cache that is filled
2717 // while we identify default attribute opportunities.
Johannes Doerfertece81902019-08-12 22:05:53 +00002718 InformationCache InfoCache(M.getDataLayout());
2719 Attributor A(InfoCache);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002720
2721 for (Function &F : M) {
2722 // TODO: Not all attributes require an exact definition. Find a way to
2723 // enable deduction for some but not all attributes in case the
2724 // definition might be changed at runtime, see also
2725 // http://lists.llvm.org/pipermail/llvm-dev/2018-February/121275.html.
2726 // TODO: We could always determine abstract attributes and if sufficient
2727 // information was found we could duplicate the functions that do not
2728 // have an exact definition.
2729 if (!F.hasExactDefinition()) {
2730 NumFnWithoutExactDefinition++;
2731 continue;
2732 }
2733
2734 // For now we ignore naked and optnone functions.
2735 if (F.hasFnAttribute(Attribute::Naked) ||
2736 F.hasFnAttribute(Attribute::OptimizeNone))
2737 continue;
2738
2739 NumFnWithExactDefinition++;
2740
2741 // Populate the Attributor with abstract attribute opportunities in the
2742 // function and the information cache with IR information.
Johannes Doerfertece81902019-08-12 22:05:53 +00002743 A.identifyDefaultAbstractAttributes(F);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002744 }
2745
Johannes Doerfertece81902019-08-12 22:05:53 +00002746 return A.run() == ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002747}
2748
2749PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
2750 if (runAttributorOnModule(M)) {
2751 // FIXME: Think about passes we will preserve and add them here.
2752 return PreservedAnalyses::none();
2753 }
2754 return PreservedAnalyses::all();
2755}
2756
2757namespace {
2758
2759struct AttributorLegacyPass : public ModulePass {
2760 static char ID;
2761
2762 AttributorLegacyPass() : ModulePass(ID) {
2763 initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry());
2764 }
2765
2766 bool runOnModule(Module &M) override {
2767 if (skipModule(M))
2768 return false;
2769 return runAttributorOnModule(M);
2770 }
2771
2772 void getAnalysisUsage(AnalysisUsage &AU) const override {
2773 // FIXME: Think about passes we will preserve and add them here.
2774 AU.setPreservesCFG();
2775 }
2776};
2777
2778} // end anonymous namespace
2779
2780Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); }
2781
2782char AttributorLegacyPass::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002783
2784const char AAReturnedValues::ID = 0;
2785const char AANoUnwind::ID = 0;
2786const char AANoSync::ID = 0;
Johannes Doerferteccdf082019-08-05 23:35:12 +00002787const char AANoFree::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002788const char AANonNull::ID = 0;
2789const char AANoRecurse::ID = 0;
2790const char AAWillReturn::ID = 0;
2791const char AANoAlias::ID = 0;
2792const char AANoReturn::ID = 0;
2793const char AAIsDead::ID = 0;
2794const char AADereferenceable::ID = 0;
2795const char AAAlign::ID = 0;
2796
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002797// Macro magic to create the static generator function for attributes that
2798// follow the naming scheme.
2799
2800#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
2801 case IRPosition::PK: \
2802 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
2803
2804#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
2805 case IRPosition::PK: \
2806 AA = new CLASS##SUFFIX(IRP); \
2807 break;
2808
2809#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
2810 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
2811 CLASS *AA = nullptr; \
2812 switch (IRP.getPositionKind()) { \
2813 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
2814 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
2815 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
2816 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
2817 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
2818 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
2819 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
2820 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
2821 } \
2822 AA->initialize(A); \
2823 return *AA; \
2824 }
2825
2826#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
2827 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
2828 CLASS *AA = nullptr; \
2829 switch (IRP.getPositionKind()) { \
2830 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
2831 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
2832 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
2833 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
2834 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
2835 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
2836 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
2837 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
2838 } \
2839 AA->initialize(A); \
2840 return *AA; \
2841 }
2842
2843CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind)
2844CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync)
2845CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)
2846CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse)
2847CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn)
2848CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn)
2849CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead)
2850CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReturnedValues)
2851
2852CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull)
2853CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias)
2854CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable)
2855CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign)
2856
2857#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
2858#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
2859#undef SWITCH_PK_CREATE
2860#undef SWITCH_PK_INV
2861
Johannes Doerfertaade7822019-06-05 03:02:24 +00002862INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor",
2863 "Deduce and propagate attributes", false, false)
2864INITIALIZE_PASS_END(AttributorLegacyPass, "attributor",
2865 "Deduce and propagate attributes", false, false)