blob: e518994f1532d4c2af4f8260fca2ee8c1543e4bf [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 Doerfertdeb9ea32019-08-23 15:42:19 +0000685 /// Mapping to remember the number of returned values for a call site such
686 /// that we can avoid updates if nothing changed.
687 DenseMap<const CallBase *, unsigned> NumReturnedValuesPerKnownAA;
688
689 /// Set of unresolved calls returned by the associated function.
Johannes Doerfert695089e2019-08-23 15:23:49 +0000690 SmallSetVector<CallBase *, 4> UnresolvedCalls;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000691
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000692 /// State flags
693 ///
694 ///{
Johannes Doerfertdeb9ea32019-08-23 15:42:19 +0000695 bool IsFixed = false;
696 bool IsValidState = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000697 ///}
698
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000699public:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000700 AAReturnedValuesImpl(const IRPosition &IRP) : AAReturnedValues(IRP) {}
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000701
702 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +0000703 void initialize(Attributor &A) override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000704 // Reset the state.
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000705 IsFixed = false;
706 IsValidState = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000707 ReturnedValues.clear();
708
Johannes Doerfertdef99282019-08-14 21:29:37 +0000709 Function *F = getAssociatedFunction();
710 if (!F || !F->hasExactDefinition()) {
711 indicatePessimisticFixpoint();
712 return;
713 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000714
715 // The map from instruction opcodes to those instructions in the function.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000716 auto &OpcodeInstMap = A.getInfoCache().getOpcodeInstMapForFunction(*F);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000717
718 // Look through all arguments, if one is marked as returned we are done.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000719 for (Argument &Arg : F->args()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000720 if (Arg.hasReturnedAttr()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000721 auto &ReturnInstSet = ReturnedValues[&Arg];
722 for (Instruction *RI : OpcodeInstMap[Instruction::Ret])
723 ReturnInstSet.insert(cast<ReturnInst>(RI));
724
725 indicateOptimisticFixpoint();
726 return;
727 }
728 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000729 }
730
731 /// See AbstractAttribute::manifest(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000732 ChangeStatus manifest(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000733
734 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000735 AbstractState &getState() override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000736
737 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000738 const AbstractState &getState() const override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000739
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000740 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +0000741 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000742
Johannes Doerfertdef99282019-08-14 21:29:37 +0000743 llvm::iterator_range<iterator> returned_values() override {
744 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
745 }
746
747 llvm::iterator_range<const_iterator> returned_values() const override {
748 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
749 }
750
Johannes Doerfert695089e2019-08-23 15:23:49 +0000751 const SmallSetVector<CallBase *, 4> &getUnresolvedCalls() const override {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000752 return UnresolvedCalls;
753 }
754
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000755 /// Return the number of potential return values, -1 if unknown.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000756 size_t getNumReturnValues() const override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000757 return isValidState() ? ReturnedValues.size() : -1;
758 }
759
760 /// Return an assumed unique return value if a single candidate is found. If
761 /// there cannot be one, return a nullptr. If it is not clear yet, return the
762 /// Optional::NoneType.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000763 Optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000764
Johannes Doerfert14a04932019-08-07 22:27:24 +0000765 /// See AbstractState::checkForAllReturnedValues(...).
766 bool checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +0000767 const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)>
Johannes Doerfert14a04932019-08-07 22:27:24 +0000768 &Pred) const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000769
770 /// Pretty print the attribute similar to the IR representation.
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000771 const std::string getAsStr() const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000772
773 /// See AbstractState::isAtFixpoint().
774 bool isAtFixpoint() const override { return IsFixed; }
775
776 /// See AbstractState::isValidState().
777 bool isValidState() const override { return IsValidState; }
778
779 /// See AbstractState::indicateOptimisticFixpoint(...).
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000780 ChangeStatus indicateOptimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000781 IsFixed = true;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000782 return ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000783 }
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000784
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000785 ChangeStatus indicatePessimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000786 IsFixed = true;
787 IsValidState = false;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000788 return ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000789 }
790};
791
792ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) {
793 ChangeStatus Changed = ChangeStatus::UNCHANGED;
794
795 // Bookkeeping.
796 assert(isValidState());
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000797 STATS_DECLTRACK(KnownReturnValues, FunctionReturn,
798 "Number of function with known return values");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000799
800 // Check if we have an assumed unique return value that we could manifest.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000801 Optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000802
803 if (!UniqueRV.hasValue() || !UniqueRV.getValue())
804 return Changed;
805
806 // Bookkeeping.
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000807 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
808 "Number of function with unique return");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000809
810 // If the assumed unique return value is an argument, annotate it.
811 if (auto *UniqueRVArg = dyn_cast<Argument>(UniqueRV.getValue())) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000812 getIRPosition() = IRPosition::argument(*UniqueRVArg);
Johannes Doerferteccdf082019-08-05 23:35:12 +0000813 Changed = IRAttribute::manifest(A) | Changed;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000814 }
815
816 return Changed;
817}
818
819const std::string AAReturnedValuesImpl::getAsStr() const {
820 return (isAtFixpoint() ? "returns(#" : "may-return(#") +
Johannes Doerfert6471bb62019-08-04 18:39:28 +0000821 (isValidState() ? std::to_string(getNumReturnValues()) : "?") +
Johannes Doerfertdef99282019-08-14 21:29:37 +0000822 ")[#UC: " + std::to_string(UnresolvedCalls.size()) + "]";
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000823}
824
Johannes Doerfert14a04932019-08-07 22:27:24 +0000825Optional<Value *>
826AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const {
827 // If checkForAllReturnedValues provides a unique value, ignoring potential
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000828 // undef values that can also be present, it is assumed to be the actual
829 // return value and forwarded to the caller of this method. If there are
830 // multiple, a nullptr is returned indicating there cannot be a unique
831 // returned value.
832 Optional<Value *> UniqueRV;
833
Johannes Doerfert14a04932019-08-07 22:27:24 +0000834 auto Pred = [&](Value &RV) -> bool {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000835 // If we found a second returned value and neither the current nor the saved
836 // one is an undef, there is no unique returned value. Undefs are special
837 // since we can pretend they have any value.
838 if (UniqueRV.hasValue() && UniqueRV != &RV &&
839 !(isa<UndefValue>(RV) || isa<UndefValue>(UniqueRV.getValue()))) {
840 UniqueRV = nullptr;
841 return false;
842 }
843
844 // Do not overwrite a value with an undef.
845 if (!UniqueRV.hasValue() || !isa<UndefValue>(RV))
846 UniqueRV = &RV;
847
848 return true;
849 };
850
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000851 if (!A.checkForAllReturnedValues(Pred, *this))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000852 UniqueRV = nullptr;
853
854 return UniqueRV;
855}
856
Johannes Doerfert14a04932019-08-07 22:27:24 +0000857bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +0000858 const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)>
Johannes Doerfert14a04932019-08-07 22:27:24 +0000859 &Pred) const {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000860 if (!isValidState())
861 return false;
862
863 // Check all returned values but ignore call sites as long as we have not
864 // encountered an overdefined one during an update.
865 for (auto &It : ReturnedValues) {
866 Value *RV = It.first;
867
Johannes Doerfertdef99282019-08-14 21:29:37 +0000868 CallBase *CB = dyn_cast<CallBase>(RV);
869 if (CB && !UnresolvedCalls.count(CB))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000870 continue;
871
Johannes Doerfert695089e2019-08-23 15:23:49 +0000872 if (!Pred(*RV, It.second))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000873 return false;
874 }
875
876 return true;
877}
878
Johannes Doerfertece81902019-08-12 22:05:53 +0000879ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000880 size_t NumUnresolvedCalls = UnresolvedCalls.size();
881 bool Changed = false;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000882
Johannes Doerfertdef99282019-08-14 21:29:37 +0000883 // State used in the value traversals starting in returned values.
884 struct RVState {
885 // The map in which we collect return values -> return instrs.
886 decltype(ReturnedValues) &RetValsMap;
887 // The flag to indicate a change.
Johannes Doerfert056f1b52019-08-19 19:14:10 +0000888 bool &Changed;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000889 // The return instrs we come from.
Johannes Doerfert695089e2019-08-23 15:23:49 +0000890 SmallSetVector<ReturnInst *, 4> RetInsts;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000891 };
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000892
Johannes Doerfertdef99282019-08-14 21:29:37 +0000893 // Callback for a leaf value returned by the associated function.
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000894 auto VisitValueCB = [](Value &Val, RVState &RVS, bool) -> bool {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000895 auto Size = RVS.RetValsMap[&Val].size();
896 RVS.RetValsMap[&Val].insert(RVS.RetInsts.begin(), RVS.RetInsts.end());
897 bool Inserted = RVS.RetValsMap[&Val].size() != Size;
898 RVS.Changed |= Inserted;
899 LLVM_DEBUG({
900 if (Inserted)
901 dbgs() << "[AAReturnedValues] 1 Add new returned value " << Val
902 << " => " << RVS.RetInsts.size() << "\n";
903 });
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000904 return true;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000905 };
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000906
Johannes Doerfertdef99282019-08-14 21:29:37 +0000907 // Helper method to invoke the generic value traversal.
908 auto VisitReturnedValue = [&](Value &RV, RVState &RVS) {
909 IRPosition RetValPos = IRPosition::value(RV);
910 return genericValueTraversal<AAReturnedValues, RVState>(A, RetValPos, *this,
911 RVS, VisitValueCB);
912 };
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000913
Johannes Doerfertdef99282019-08-14 21:29:37 +0000914 // Callback for all "return intructions" live in the associated function.
915 auto CheckReturnInst = [this, &VisitReturnedValue, &Changed](Instruction &I) {
916 ReturnInst &Ret = cast<ReturnInst>(I);
Johannes Doerfert056f1b52019-08-19 19:14:10 +0000917 RVState RVS({ReturnedValues, Changed, {}});
Johannes Doerfertdef99282019-08-14 21:29:37 +0000918 RVS.RetInsts.insert(&Ret);
Johannes Doerfertdef99282019-08-14 21:29:37 +0000919 return VisitReturnedValue(*Ret.getReturnValue(), RVS);
920 };
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000921
Johannes Doerfertdef99282019-08-14 21:29:37 +0000922 // Start by discovering returned values from all live returned instructions in
923 // the associated function.
924 if (!A.checkForAllInstructions(CheckReturnInst, *this, {Instruction::Ret}))
925 return indicatePessimisticFixpoint();
926
927 // Once returned values "directly" present in the code are handled we try to
928 // resolve returned calls.
929 decltype(ReturnedValues) NewRVsMap;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000930 for (auto &It : ReturnedValues) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000931 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned value: " << *It.first
932 << " by #" << It.second.size() << " RIs\n");
933 CallBase *CB = dyn_cast<CallBase>(It.first);
934 if (!CB || UnresolvedCalls.count(CB))
935 continue;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000936
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000937 const auto &RetValAA =
Johannes Doerfertdef99282019-08-14 21:29:37 +0000938 A.getAAFor<AAReturnedValues>(*this, IRPosition::callsite_function(*CB));
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000939 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Found another AAReturnedValues: "
940 << static_cast<const AbstractAttribute &>(RetValAA)
941 << "\n");
Johannes Doerfertdef99282019-08-14 21:29:37 +0000942
943 // Skip dead ends, thus if we do not know anything about the returned
944 // call we mark it as unresolved and it will stay that way.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000945 if (!RetValAA.getState().isValidState()) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000946 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Unresolved call: " << *CB
947 << "\n");
948 UnresolvedCalls.insert(CB);
949 continue;
950 }
951
Johannes Doerfertde7674c2019-08-19 21:35:31 +0000952 // Do not try to learn partial information. If the callee has unresolved
953 // return values we will treat the call as unresolved/opaque.
954 auto &RetValAAUnresolvedCalls = RetValAA.getUnresolvedCalls();
955 if (!RetValAAUnresolvedCalls.empty()) {
956 UnresolvedCalls.insert(CB);
957 continue;
958 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000959
Johannes Doerfertde7674c2019-08-19 21:35:31 +0000960 // Now check if we can track transitively returned values. If possible, thus
961 // if all return value can be represented in the current scope, do so.
962 bool Unresolved = false;
963 for (auto &RetValAAIt : RetValAA.returned_values()) {
964 Value *RetVal = RetValAAIt.first;
965 if (isa<Argument>(RetVal) || isa<CallBase>(RetVal) ||
966 isa<Constant>(RetVal))
967 continue;
968 // Anything that did not fit in the above categories cannot be resolved,
969 // mark the call as unresolved.
970 LLVM_DEBUG(dbgs() << "[AAReturnedValues] transitively returned value "
971 "cannot be translated: "
972 << *RetVal << "\n");
973 UnresolvedCalls.insert(CB);
974 Unresolved = true;
975 break;
976 }
977
978 if (Unresolved)
979 continue;
980
Johannes Doerfertdeb9ea32019-08-23 15:42:19 +0000981 // Now track transitively returned values.
982 unsigned &NumRetAA = NumReturnedValuesPerKnownAA[CB];
983 if (NumRetAA == RetValAA.getNumReturnValues()) {
984 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Skip call as it has not "
985 "changed since it was seen last\n");
986 continue;
987 }
988 NumRetAA = RetValAA.getNumReturnValues();
989
Johannes Doerfertdef99282019-08-14 21:29:37 +0000990 for (auto &RetValAAIt : RetValAA.returned_values()) {
991 Value *RetVal = RetValAAIt.first;
992 if (Argument *Arg = dyn_cast<Argument>(RetVal)) {
993 // Arguments are mapped to call site operands and we begin the traversal
994 // again.
Johannes Doerfert056f1b52019-08-19 19:14:10 +0000995 bool Unused = false;
996 RVState RVS({NewRVsMap, Unused, RetValAAIt.second});
Johannes Doerfertdef99282019-08-14 21:29:37 +0000997 VisitReturnedValue(*CB->getArgOperand(Arg->getArgNo()), RVS);
998 continue;
999 } else if (isa<CallBase>(RetVal)) {
1000 // Call sites are resolved by the callee attribute over time, no need to
1001 // do anything for us.
1002 continue;
1003 } else if (isa<Constant>(RetVal)) {
1004 // Constants are valid everywhere, we can simply take them.
1005 NewRVsMap[RetVal].insert(It.second.begin(), It.second.end());
1006 continue;
1007 }
Johannes Doerfert4361da22019-08-04 18:38:53 +00001008 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001009 }
1010
Johannes Doerfertdef99282019-08-14 21:29:37 +00001011 // To avoid modifications to the ReturnedValues map while we iterate over it
1012 // we kept record of potential new entries in a copy map, NewRVsMap.
1013 for (auto &It : NewRVsMap) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001014 assert(!It.second.empty() && "Entry does not add anything.");
1015 auto &ReturnInsts = ReturnedValues[It.first];
1016 for (ReturnInst *RI : It.second)
Johannes Doerfert695089e2019-08-23 15:23:49 +00001017 if (ReturnInsts.insert(RI)) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001018 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Add new returned value "
1019 << *It.first << " => " << *RI << "\n");
Johannes Doerfertdef99282019-08-14 21:29:37 +00001020 Changed = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001021 }
1022 }
1023
Johannes Doerfertdef99282019-08-14 21:29:37 +00001024 Changed |= (NumUnresolvedCalls != UnresolvedCalls.size());
1025 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001026}
1027
Johannes Doerfertdef99282019-08-14 21:29:37 +00001028struct AAReturnedValuesFunction final : public AAReturnedValuesImpl {
1029 AAReturnedValuesFunction(const IRPosition &IRP) : AAReturnedValuesImpl(IRP) {}
1030
1031 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001032 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(returned) }
Johannes Doerfertdef99282019-08-14 21:29:37 +00001033};
1034
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001035/// Returned values information for a call sites.
1036using AAReturnedValuesCallSite = AAReturnedValuesFunction;
1037
Stefan Stipanovic06263672019-07-11 21:37:40 +00001038/// ------------------------ NoSync Function Attribute -------------------------
1039
Johannes Doerfert344d0382019-08-07 22:34:26 +00001040struct AANoSyncImpl : AANoSync {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001041 AANoSyncImpl(const IRPosition &IRP) : AANoSync(IRP) {}
Stefan Stipanovic06263672019-07-11 21:37:40 +00001042
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001043 /// See AbstractAttribute::initialize(...).
1044 void initialize(Attributor &A) override {
1045 if (hasAttr({Attribute::NoSync}))
1046 indicateOptimisticFixpoint();
1047 }
1048
Stefan Stipanoviccb5ecae2019-07-12 18:34:06 +00001049 const std::string getAsStr() const override {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001050 return getAssumed() ? "nosync" : "may-sync";
1051 }
1052
1053 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001054 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001055
Stefan Stipanovic06263672019-07-11 21:37:40 +00001056 /// Helper function used to determine whether an instruction is non-relaxed
1057 /// atomic. In other words, if an atomic instruction does not have unordered
1058 /// or monotonic ordering
1059 static bool isNonRelaxedAtomic(Instruction *I);
1060
1061 /// Helper function used to determine whether an instruction is volatile.
1062 static bool isVolatile(Instruction *I);
1063
Johannes Doerfertc7a1db32019-07-13 01:09:27 +00001064 /// Helper function uset to check if intrinsic is volatile (memcpy, memmove,
1065 /// memset).
Stefan Stipanovic06263672019-07-11 21:37:40 +00001066 static bool isNoSyncIntrinsic(Instruction *I);
1067};
1068
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001069bool AANoSyncImpl::isNonRelaxedAtomic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001070 if (!I->isAtomic())
1071 return false;
1072
1073 AtomicOrdering Ordering;
1074 switch (I->getOpcode()) {
1075 case Instruction::AtomicRMW:
1076 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
1077 break;
1078 case Instruction::Store:
1079 Ordering = cast<StoreInst>(I)->getOrdering();
1080 break;
1081 case Instruction::Load:
1082 Ordering = cast<LoadInst>(I)->getOrdering();
1083 break;
1084 case Instruction::Fence: {
1085 auto *FI = cast<FenceInst>(I);
1086 if (FI->getSyncScopeID() == SyncScope::SingleThread)
1087 return false;
1088 Ordering = FI->getOrdering();
1089 break;
1090 }
1091 case Instruction::AtomicCmpXchg: {
1092 AtomicOrdering Success = cast<AtomicCmpXchgInst>(I)->getSuccessOrdering();
1093 AtomicOrdering Failure = cast<AtomicCmpXchgInst>(I)->getFailureOrdering();
1094 // Only if both are relaxed, than it can be treated as relaxed.
1095 // Otherwise it is non-relaxed.
1096 if (Success != AtomicOrdering::Unordered &&
1097 Success != AtomicOrdering::Monotonic)
1098 return true;
1099 if (Failure != AtomicOrdering::Unordered &&
1100 Failure != AtomicOrdering::Monotonic)
1101 return true;
1102 return false;
1103 }
1104 default:
1105 llvm_unreachable(
1106 "New atomic operations need to be known in the attributor.");
1107 }
1108
1109 // Relaxed.
1110 if (Ordering == AtomicOrdering::Unordered ||
1111 Ordering == AtomicOrdering::Monotonic)
1112 return false;
1113 return true;
1114}
1115
1116/// Checks if an intrinsic is nosync. Currently only checks mem* intrinsics.
1117/// FIXME: We should ipmrove the handling of intrinsics.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001118bool AANoSyncImpl::isNoSyncIntrinsic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001119 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
1120 switch (II->getIntrinsicID()) {
1121 /// Element wise atomic memory intrinsics are can only be unordered,
1122 /// therefore nosync.
1123 case Intrinsic::memset_element_unordered_atomic:
1124 case Intrinsic::memmove_element_unordered_atomic:
1125 case Intrinsic::memcpy_element_unordered_atomic:
1126 return true;
1127 case Intrinsic::memset:
1128 case Intrinsic::memmove:
1129 case Intrinsic::memcpy:
1130 if (!cast<MemIntrinsic>(II)->isVolatile())
1131 return true;
1132 return false;
1133 default:
1134 return false;
1135 }
1136 }
1137 return false;
1138}
1139
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001140bool AANoSyncImpl::isVolatile(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001141 assert(!ImmutableCallSite(I) && !isa<CallBase>(I) &&
1142 "Calls should not be checked here");
1143
1144 switch (I->getOpcode()) {
1145 case Instruction::AtomicRMW:
1146 return cast<AtomicRMWInst>(I)->isVolatile();
1147 case Instruction::Store:
1148 return cast<StoreInst>(I)->isVolatile();
1149 case Instruction::Load:
1150 return cast<LoadInst>(I)->isVolatile();
1151 case Instruction::AtomicCmpXchg:
1152 return cast<AtomicCmpXchgInst>(I)->isVolatile();
1153 default:
1154 return false;
1155 }
1156}
1157
Johannes Doerfertece81902019-08-12 22:05:53 +00001158ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001159
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001160 auto CheckRWInstForNoSync = [&](Instruction &I) {
1161 /// We are looking for volatile instructions or Non-Relaxed atomics.
1162 /// FIXME: We should ipmrove the handling of intrinsics.
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001163
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001164 if (isa<IntrinsicInst>(&I) && isNoSyncIntrinsic(&I))
1165 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001166
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001167 if (ImmutableCallSite ICS = ImmutableCallSite(&I)) {
1168 if (ICS.hasFnAttr(Attribute::NoSync))
1169 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001170
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001171 const auto &NoSyncAA =
1172 A.getAAFor<AANoSync>(*this, IRPosition::callsite_function(ICS));
1173 if (NoSyncAA.isAssumedNoSync())
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001174 return true;
1175 return false;
1176 }
Stefan Stipanovic06263672019-07-11 21:37:40 +00001177
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001178 if (!isVolatile(&I) && !isNonRelaxedAtomic(&I))
1179 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001180
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001181 return false;
1182 };
Stefan Stipanovic06263672019-07-11 21:37:40 +00001183
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001184 auto CheckForNoSync = [&](Instruction &I) {
1185 // At this point we handled all read/write effects and they are all
1186 // nosync, so they can be skipped.
1187 if (I.mayReadOrWriteMemory())
1188 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001189
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001190 // non-convergent and readnone imply nosync.
1191 return !ImmutableCallSite(&I).isConvergent();
1192 };
Stefan Stipanovic06263672019-07-11 21:37:40 +00001193
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001194 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this) ||
1195 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001196 return indicatePessimisticFixpoint();
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001197
Stefan Stipanovic06263672019-07-11 21:37:40 +00001198 return ChangeStatus::UNCHANGED;
1199}
1200
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001201struct AANoSyncFunction final : public AANoSyncImpl {
1202 AANoSyncFunction(const IRPosition &IRP) : AANoSyncImpl(IRP) {}
1203
1204 /// See AbstractAttribute::trackStatistics()
1205 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }
1206};
1207
1208/// NoSync attribute deduction for a call sites.
1209using AANoSyncCallSite = AANoSyncFunction;
1210
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001211/// ------------------------ No-Free Attributes ----------------------------
1212
Johannes Doerfert344d0382019-08-07 22:34:26 +00001213struct AANoFreeImpl : public AANoFree {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001214 AANoFreeImpl(const IRPosition &IRP) : AANoFree(IRP) {}
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001215
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001216 /// See AbstractAttribute::initialize(...).
1217 void initialize(Attributor &A) override {
1218 if (hasAttr({Attribute::NoFree}))
1219 indicateOptimisticFixpoint();
1220 }
1221
1222 /// See AbstractAttribute::updateImpl(...).
1223 ChangeStatus updateImpl(Attributor &A) override {
1224 auto CheckForNoFree = [&](Instruction &I) {
1225 ImmutableCallSite ICS(&I);
1226 if (ICS.hasFnAttr(Attribute::NoFree))
1227 return true;
1228
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001229 const auto &NoFreeAA =
1230 A.getAAFor<AANoFree>(*this, IRPosition::callsite_function(ICS));
1231 return NoFreeAA.isAssumedNoFree();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001232 };
1233
1234 if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this))
1235 return indicatePessimisticFixpoint();
1236 return ChangeStatus::UNCHANGED;
1237 }
1238
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001239 /// See AbstractAttribute::getAsStr().
1240 const std::string getAsStr() const override {
1241 return getAssumed() ? "nofree" : "may-free";
1242 }
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001243};
1244
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001245struct AANoFreeFunction final : public AANoFreeImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001246 AANoFreeFunction(const IRPosition &IRP) : AANoFreeImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001247
1248 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001249 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001250};
1251
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001252/// NoFree attribute deduction for a call sites.
1253using AANoFreeCallSite = AANoFreeFunction;
1254
Hideto Ueno54869ec2019-07-15 06:49:04 +00001255/// ------------------------ NonNull Argument Attribute ------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00001256struct AANonNullImpl : AANonNull {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001257 AANonNullImpl(const IRPosition &IRP) : AANonNull(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001258
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001259 /// See AbstractAttribute::initialize(...).
1260 void initialize(Attributor &A) override {
1261 if (hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
1262 indicateOptimisticFixpoint();
1263 }
1264
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001265 /// See AbstractAttribute::getAsStr().
1266 const std::string getAsStr() const override {
1267 return getAssumed() ? "nonnull" : "may-null";
1268 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001269};
1270
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001271/// NonNull attribute for a floating value.
1272struct AANonNullFloating : AANonNullImpl {
1273 AANonNullFloating(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001274
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001275 /// See AbstractAttribute::initialize(...).
1276 void initialize(Attributor &A) override {
1277 AANonNullImpl::initialize(A);
Hideto Ueno54869ec2019-07-15 06:49:04 +00001278
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001279 if (isAtFixpoint())
1280 return;
Hideto Ueno54869ec2019-07-15 06:49:04 +00001281
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001282 const IRPosition &IRP = getIRPosition();
1283 const Value &V = IRP.getAssociatedValue();
1284 const DataLayout &DL = A.getDataLayout();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001285
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001286 // TODO: This context sensitive query should be removed once we can do
1287 // context sensitive queries in the genericValueTraversal below.
1288 if (isKnownNonZero(&V, DL, 0, /* TODO: AC */ nullptr, IRP.getCtxI(),
1289 /* TODO: DT */ nullptr))
1290 indicateOptimisticFixpoint();
1291 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001292
1293 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001294 ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001295 const DataLayout &DL = A.getDataLayout();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001296
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001297 auto VisitValueCB = [&](Value &V, AAAlign::StateType &T,
1298 bool Stripped) -> bool {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001299 const auto &AA = A.getAAFor<AANonNull>(*this, IRPosition::value(V));
1300 if (!Stripped && this == &AA) {
1301 if (!isKnownNonZero(&V, DL, 0, /* TODO: AC */ nullptr,
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001302 /* TODO: CtxI */ nullptr,
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001303 /* TODO: DT */ nullptr))
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001304 T.indicatePessimisticFixpoint();
1305 } else {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001306 // Use abstract attribute information.
1307 const AANonNull::StateType &NS =
1308 static_cast<const AANonNull::StateType &>(AA.getState());
1309 T ^= NS;
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001310 }
1311 return T.isValidState();
1312 };
1313
1314 StateType T;
1315 if (!genericValueTraversal<AANonNull, StateType>(A, getIRPosition(), *this,
1316 T, VisitValueCB))
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001317 return indicatePessimisticFixpoint();
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001318
1319 return clampStateAndIndicateChange(getState(), T);
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001320 }
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001321
1322 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001323 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001324};
1325
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001326/// NonNull attribute for function return value.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001327struct AANonNullReturned final
1328 : AAReturnedFromReturnedValues<AANonNull, AANonNullImpl> {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001329 AANonNullReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001330 : AAReturnedFromReturnedValues<AANonNull, AANonNullImpl>(IRP) {}
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001331
1332 /// See AbstractAttribute::trackStatistics()
1333 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
1334};
1335
Hideto Ueno54869ec2019-07-15 06:49:04 +00001336/// NonNull attribute for function argument.
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001337struct AANonNullArgument final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001338 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001339 AANonNullArgument(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001340 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001341
1342 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001343 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001344};
1345
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001346struct AANonNullCallSiteArgument final : AANonNullFloating {
1347 AANonNullCallSiteArgument(const IRPosition &IRP) : AANonNullFloating(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001348
1349 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert5427aa82019-08-21 20:57:20 +00001350 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnul) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001351};
Johannes Doerfert007153e2019-08-05 23:26:06 +00001352
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001353/// NonNull attribute for a call site return position.
1354struct AANonNullCallSiteReturned final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001355 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl> {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001356 AANonNullCallSiteReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001357 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl>(IRP) {}
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001358
1359 /// See AbstractAttribute::trackStatistics()
1360 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull) }
1361};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001362
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001363/// ------------------------ No-Recurse Attributes ----------------------------
1364
1365struct AANoRecurseImpl : public AANoRecurse {
1366 AANoRecurseImpl(const IRPosition &IRP) : AANoRecurse(IRP) {}
1367
1368 /// See AbstractAttribute::initialize(...).
1369 void initialize(Attributor &A) override {
1370 if (hasAttr({getAttrKind()})) {
1371 indicateOptimisticFixpoint();
1372 return;
1373 }
1374 }
1375
1376 /// See AbstractAttribute::getAsStr()
1377 const std::string getAsStr() const override {
1378 return getAssumed() ? "norecurse" : "may-recurse";
1379 }
1380};
1381
1382struct AANoRecurseFunction final : AANoRecurseImpl {
1383 AANoRecurseFunction(const IRPosition &IRP) : AANoRecurseImpl(IRP) {}
1384
1385 /// See AbstractAttribute::updateImpl(...).
1386 ChangeStatus updateImpl(Attributor &A) override {
1387 // TODO: Implement this.
1388 return indicatePessimisticFixpoint();
1389 }
1390
1391 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
1392};
1393
1394using AANoRecurseCallSite = AANoRecurseFunction;
1395
Hideto Ueno11d37102019-07-17 15:15:43 +00001396/// ------------------------ Will-Return Attributes ----------------------------
1397
Hideto Ueno11d37102019-07-17 15:15:43 +00001398// Helper function that checks whether a function has any cycle.
1399// TODO: Replace with more efficent code
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001400static bool containsCycle(Function &F) {
Hideto Ueno11d37102019-07-17 15:15:43 +00001401 SmallPtrSet<BasicBlock *, 32> Visited;
1402
1403 // Traverse BB by dfs and check whether successor is already visited.
1404 for (BasicBlock *BB : depth_first(&F)) {
1405 Visited.insert(BB);
1406 for (auto *SuccBB : successors(BB)) {
1407 if (Visited.count(SuccBB))
1408 return true;
1409 }
1410 }
1411 return false;
1412}
1413
1414// Helper function that checks the function have a loop which might become an
1415// endless loop
1416// FIXME: Any cycle is regarded as endless loop for now.
1417// We have to allow some patterns.
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001418static bool containsPossiblyEndlessLoop(Function *F) {
1419 return !F || !F->hasExactDefinition() || containsCycle(*F);
Hideto Ueno11d37102019-07-17 15:15:43 +00001420}
1421
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001422struct AAWillReturnImpl : public AAWillReturn {
1423 AAWillReturnImpl(const IRPosition &IRP) : AAWillReturn(IRP) {}
Hideto Ueno11d37102019-07-17 15:15:43 +00001424
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001425 /// See AbstractAttribute::initialize(...).
1426 void initialize(Attributor &A) override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001427 if (hasAttr({Attribute::WillReturn})) {
1428 indicateOptimisticFixpoint();
1429 return;
1430 }
Hideto Ueno11d37102019-07-17 15:15:43 +00001431
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001432 Function *F = getAssociatedFunction();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001433 if (containsPossiblyEndlessLoop(F))
1434 indicatePessimisticFixpoint();
1435 }
Hideto Ueno11d37102019-07-17 15:15:43 +00001436
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001437 /// See AbstractAttribute::updateImpl(...).
1438 ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001439 auto CheckForWillReturn = [&](Instruction &I) {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001440 IRPosition IPos = IRPosition::callsite_function(ImmutableCallSite(&I));
1441 const auto &WillReturnAA = A.getAAFor<AAWillReturn>(*this, IPos);
1442 if (WillReturnAA.isKnownWillReturn())
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001443 return true;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001444 if (!WillReturnAA.isAssumedWillReturn())
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001445 return false;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001446 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(*this, IPos);
1447 return NoRecurseAA.isAssumedNoRecurse();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001448 };
1449
1450 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this))
1451 return indicatePessimisticFixpoint();
1452
1453 return ChangeStatus::UNCHANGED;
1454 }
1455
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001456 /// See AbstractAttribute::getAsStr()
1457 const std::string getAsStr() const override {
1458 return getAssumed() ? "willreturn" : "may-noreturn";
1459 }
1460};
1461
1462struct AAWillReturnFunction final : AAWillReturnImpl {
1463 AAWillReturnFunction(const IRPosition &IRP) : AAWillReturnImpl(IRP) {}
1464
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001465 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001466 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) }
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001467};
Hideto Ueno11d37102019-07-17 15:15:43 +00001468
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001469/// WillReturn attribute deduction for a call sites.
1470using AAWillReturnCallSite = AAWillReturnFunction;
1471
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001472/// ------------------------ NoAlias Argument Attribute ------------------------
1473
Johannes Doerfert344d0382019-08-07 22:34:26 +00001474struct AANoAliasImpl : AANoAlias {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001475 AANoAliasImpl(const IRPosition &IRP) : AANoAlias(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001476
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001477 /// See AbstractAttribute::initialize(...).
1478 void initialize(Attributor &A) override {
1479 if (hasAttr({Attribute::NoAlias}))
1480 indicateOptimisticFixpoint();
1481 }
1482
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001483 const std::string getAsStr() const override {
1484 return getAssumed() ? "noalias" : "may-alias";
1485 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001486};
1487
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001488/// NoAlias attribute for a floating value.
1489struct AANoAliasFloating final : AANoAliasImpl {
1490 AANoAliasFloating(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
1491
1492 /// See AbstractAttribute::updateImpl(...).
1493 ChangeStatus updateImpl(Attributor &A) override {
1494 // TODO: Implement this.
1495 return indicatePessimisticFixpoint();
1496 }
1497
1498 /// See AbstractAttribute::trackStatistics()
1499 void trackStatistics() const override {
1500 STATS_DECLTRACK_FLOATING_ATTR(noalias)
1501 }
1502};
1503
1504/// NoAlias attribute for an argument.
1505struct AANoAliasArgument final : AANoAliasImpl {
1506 AANoAliasArgument(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
1518struct AANoAliasCallSiteArgument final : AANoAliasImpl {
1519 AANoAliasCallSiteArgument(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
1520
1521 /// See AbstractAttribute::updateImpl(...).
1522 ChangeStatus updateImpl(Attributor &A) override {
1523 // TODO: Implement this.
1524 return indicatePessimisticFixpoint();
1525 }
1526
1527 /// See AbstractAttribute::trackStatistics()
1528 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
1529};
1530
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001531/// NoAlias attribute for function return value.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001532struct AANoAliasReturned final : AANoAliasImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001533 AANoAliasReturned(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001534
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001535 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001536 virtual ChangeStatus updateImpl(Attributor &A) override {
1537
1538 auto CheckReturnValue = [&](Value &RV) -> bool {
1539 if (Constant *C = dyn_cast<Constant>(&RV))
1540 if (C->isNullValue() || isa<UndefValue>(C))
1541 return true;
1542
1543 /// For now, we can only deduce noalias if we have call sites.
1544 /// FIXME: add more support.
1545 ImmutableCallSite ICS(&RV);
1546 if (!ICS)
1547 return false;
1548
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001549 const auto &NoAliasAA =
1550 A.getAAFor<AANoAlias>(*this, IRPosition::callsite_returned(ICS));
1551 if (!NoAliasAA.isAssumedNoAlias())
1552 return false;
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001553
1554 /// FIXME: We can improve capture check in two ways:
1555 /// 1. Use the AANoCapture facilities.
1556 /// 2. Use the location of return insts for escape queries.
1557 if (PointerMayBeCaptured(&RV, /* ReturnCaptures */ false,
1558 /* StoreCaptures */ true))
1559 return false;
1560
1561 return true;
1562 };
1563
1564 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
1565 return indicatePessimisticFixpoint();
1566
1567 return ChangeStatus::UNCHANGED;
1568 }
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001569
1570 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001571 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001572};
1573
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001574/// NoAlias attribute deduction for a call site return value.
1575using AANoAliasCallSiteReturned = AANoAliasReturned;
1576
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001577/// -------------------AAIsDead Function Attribute-----------------------
1578
Johannes Doerfert344d0382019-08-07 22:34:26 +00001579struct AAIsDeadImpl : public AAIsDead {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001580 AAIsDeadImpl(const IRPosition &IRP) : AAIsDead(IRP) {}
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001581
Johannes Doerfertece81902019-08-12 22:05:53 +00001582 void initialize(Attributor &A) override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001583 const Function *F = getAssociatedFunction();
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001584
1585 if (F->hasInternalLinkage())
1586 return;
1587
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001588 if (!F || !F->hasExactDefinition()) {
1589 indicatePessimisticFixpoint();
1590 return;
1591 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001592
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001593 exploreFromEntry(A, F);
1594 }
1595
1596 void exploreFromEntry(Attributor &A, const Function *F) {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001597 ToBeExploredPaths.insert(&(F->getEntryBlock().front()));
1598 AssumedLiveBlocks.insert(&(F->getEntryBlock()));
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001599
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001600 for (size_t i = 0; i < ToBeExploredPaths.size(); ++i)
Johannes Doerfert4361da22019-08-04 18:38:53 +00001601 if (const Instruction *NextNoReturnI =
1602 findNextNoReturn(A, ToBeExploredPaths[i]))
1603 NoReturnCalls.insert(NextNoReturnI);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001604 }
1605
Johannes Doerfert4361da22019-08-04 18:38:53 +00001606 /// Find the next assumed noreturn instruction in the block of \p I starting
1607 /// from, thus including, \p I.
1608 ///
1609 /// The caller is responsible to monitor the ToBeExploredPaths set as new
1610 /// instructions discovered in other basic block will be placed in there.
1611 ///
1612 /// \returns The next assumed noreturn instructions in the block of \p I
1613 /// starting from, thus including, \p I.
1614 const Instruction *findNextNoReturn(Attributor &A, const Instruction *I);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001615
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001616 /// See AbstractAttribute::getAsStr().
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001617 const std::string getAsStr() const override {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001618 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001619 std::to_string(getAssociatedFunction()->size()) + "][#NRI " +
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001620 std::to_string(NoReturnCalls.size()) + "]";
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001621 }
1622
1623 /// See AbstractAttribute::manifest(...).
1624 ChangeStatus manifest(Attributor &A) override {
1625 assert(getState().isValidState() &&
1626 "Attempted to manifest an invalid state!");
1627
1628 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001629 Function &F = *getAssociatedFunction();
1630
1631 if (AssumedLiveBlocks.empty()) {
1632 F.replaceAllUsesWith(UndefValue::get(F.getType()));
1633 return ChangeStatus::CHANGED;
1634 }
Johannes Doerfert924d2132019-08-05 21:34:45 +00001635
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001636 // Flag to determine if we can change an invoke to a call assuming the
1637 // callee is nounwind. This is not possible if the personality of the
1638 // function allows to catch asynchronous exceptions.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001639 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001640
Johannes Doerfert4361da22019-08-04 18:38:53 +00001641 for (const Instruction *NRC : NoReturnCalls) {
1642 Instruction *I = const_cast<Instruction *>(NRC);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001643 BasicBlock *BB = I->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001644 Instruction *SplitPos = I->getNextNode();
Johannes Doerfertd4108052019-08-21 20:56:41 +00001645 // TODO: mark stuff before unreachable instructions as dead.
1646 if (isa_and_nonnull<UnreachableInst>(SplitPos))
1647 continue;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001648
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001649 if (auto *II = dyn_cast<InvokeInst>(I)) {
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001650 // If we keep the invoke the split position is at the beginning of the
1651 // normal desitination block (it invokes a noreturn function after all).
1652 BasicBlock *NormalDestBB = II->getNormalDest();
1653 SplitPos = &NormalDestBB->front();
1654
Johannes Doerfert4361da22019-08-04 18:38:53 +00001655 /// Invoke is replaced with a call and unreachable is placed after it if
1656 /// the callee is nounwind and noreturn. Otherwise, we keep the invoke
1657 /// and only place an unreachable in the normal successor.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001658 if (Invoke2CallAllowed) {
Michael Liaoa99086d2019-08-20 21:02:31 +00001659 if (II->getCalledFunction()) {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001660 const IRPosition &IPos = IRPosition::callsite_function(*II);
1661 const auto &AANoUnw = A.getAAFor<AANoUnwind>(*this, IPos);
1662 if (AANoUnw.isAssumedNoUnwind()) {
Johannes Doerfert924d2132019-08-05 21:34:45 +00001663 LLVM_DEBUG(dbgs()
1664 << "[AAIsDead] Replace invoke with call inst\n");
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001665 // We do not need an invoke (II) but instead want a call followed
1666 // by an unreachable. However, we do not remove II as other
1667 // abstract attributes might have it cached as part of their
1668 // results. Given that we modify the CFG anyway, we simply keep II
1669 // around but in a new dead block. To avoid II being live through
1670 // a different edge we have to ensure the block we place it in is
1671 // only reached from the current block of II and then not reached
1672 // at all when we insert the unreachable.
1673 SplitBlockPredecessors(NormalDestBB, {BB}, ".i2c");
1674 CallInst *CI = createCallMatchingInvoke(II);
1675 CI->insertBefore(II);
1676 CI->takeName(II);
1677 II->replaceAllUsesWith(CI);
1678 SplitPos = CI->getNextNode();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001679 }
Johannes Doerfert4361da22019-08-04 18:38:53 +00001680 }
1681 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001682 }
1683
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001684 BB = SplitPos->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001685 SplitBlock(BB, SplitPos);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001686 changeToUnreachable(BB->getTerminator(), /* UseLLVMTrap */ false);
1687 HasChanged = ChangeStatus::CHANGED;
1688 }
1689
1690 return HasChanged;
1691 }
1692
1693 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001694 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001695
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001696 /// See AAIsDead::isAssumedDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001697 bool isAssumedDead(const BasicBlock *BB) const override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001698 assert(BB->getParent() == getAssociatedFunction() &&
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001699 "BB must be in the same anchor scope function.");
1700
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001701 if (!getAssumed())
1702 return false;
1703 return !AssumedLiveBlocks.count(BB);
1704 }
1705
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001706 /// See AAIsDead::isKnownDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001707 bool isKnownDead(const BasicBlock *BB) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001708 return getKnown() && isAssumedDead(BB);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001709 }
1710
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001711 /// See AAIsDead::isAssumed(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001712 bool isAssumedDead(const Instruction *I) const override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001713 assert(I->getParent()->getParent() == getAssociatedFunction() &&
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001714 "Instruction must be in the same anchor scope function.");
1715
Stefan Stipanovic7849e412019-08-03 15:27:41 +00001716 if (!getAssumed())
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001717 return false;
1718
1719 // If it is not in AssumedLiveBlocks then it for sure dead.
1720 // Otherwise, it can still be after noreturn call in a live block.
1721 if (!AssumedLiveBlocks.count(I->getParent()))
1722 return true;
1723
1724 // If it is not after a noreturn call, than it is live.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001725 return isAfterNoReturn(I);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001726 }
1727
1728 /// See AAIsDead::isKnownDead(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001729 bool isKnownDead(const Instruction *I) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001730 return getKnown() && isAssumedDead(I);
1731 }
1732
1733 /// Check if instruction is after noreturn call, in other words, assumed dead.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001734 bool isAfterNoReturn(const Instruction *I) const;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001735
Johannes Doerfert924d2132019-08-05 21:34:45 +00001736 /// Determine if \p F might catch asynchronous exceptions.
1737 static bool mayCatchAsynchronousExceptions(const Function &F) {
1738 return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F);
1739 }
1740
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001741 /// Collection of to be explored paths.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001742 SmallSetVector<const Instruction *, 8> ToBeExploredPaths;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001743
1744 /// Collection of all assumed live BasicBlocks.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001745 DenseSet<const BasicBlock *> AssumedLiveBlocks;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001746
1747 /// Collection of calls with noreturn attribute, assumed or knwon.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001748 SmallSetVector<const Instruction *, 4> NoReturnCalls;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001749};
1750
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001751struct AAIsDeadFunction final : public AAIsDeadImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001752 AAIsDeadFunction(const IRPosition &IRP) : AAIsDeadImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001753
1754 /// See AbstractAttribute::trackStatistics()
1755 void trackStatistics() const override {
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001756 STATS_DECL(DeadInternalFunction, Function,
1757 "Number of internal functions classified as dead (no live callsite)");
1758 BUILD_STAT_NAME(DeadInternalFunction, Function) +=
1759 (getAssociatedFunction()->hasInternalLinkage() &&
1760 AssumedLiveBlocks.empty())
1761 ? 1
1762 : 0;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001763 STATS_DECL(DeadBlocks, Function,
1764 "Number of basic blocks classified as dead");
1765 BUILD_STAT_NAME(DeadBlocks, Function) +=
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001766 getAssociatedFunction()->size() - AssumedLiveBlocks.size();
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001767 STATS_DECL(PartiallyDeadBlocks, Function,
1768 "Number of basic blocks classified as partially dead");
1769 BUILD_STAT_NAME(PartiallyDeadBlocks, Function) += NoReturnCalls.size();
1770 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001771};
1772
1773bool AAIsDeadImpl::isAfterNoReturn(const Instruction *I) const {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001774 const Instruction *PrevI = I->getPrevNode();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001775 while (PrevI) {
1776 if (NoReturnCalls.count(PrevI))
1777 return true;
1778 PrevI = PrevI->getPrevNode();
1779 }
1780 return false;
1781}
1782
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001783const Instruction *AAIsDeadImpl::findNextNoReturn(Attributor &A,
1784 const Instruction *I) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001785 const BasicBlock *BB = I->getParent();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001786 const Function &F = *BB->getParent();
1787
1788 // Flag to determine if we can change an invoke to a call assuming the callee
1789 // is nounwind. This is not possible if the personality of the function allows
1790 // to catch asynchronous exceptions.
1791 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001792
1793 // TODO: We should have a function that determines if an "edge" is dead.
1794 // Edges could be from an instruction to the next or from a terminator
1795 // to the successor. For now, we need to special case the unwind block
1796 // of InvokeInst below.
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001797
1798 while (I) {
1799 ImmutableCallSite ICS(I);
1800
1801 if (ICS) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001802 const IRPosition &IPos = IRPosition::callsite_function(ICS);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001803 // Regarless of the no-return property of an invoke instruction we only
1804 // learn that the regular successor is not reachable through this
1805 // instruction but the unwind block might still be.
1806 if (auto *Invoke = dyn_cast<InvokeInst>(I)) {
1807 // Use nounwind to justify the unwind block is dead as well.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001808 const auto &AANoUnw = A.getAAFor<AANoUnwind>(*this, IPos);
1809 if (!Invoke2CallAllowed || !AANoUnw.isAssumedNoUnwind()) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001810 AssumedLiveBlocks.insert(Invoke->getUnwindDest());
1811 ToBeExploredPaths.insert(&Invoke->getUnwindDest()->front());
1812 }
1813 }
1814
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001815 const auto &NoReturnAA = A.getAAFor<AANoReturn>(*this, IPos);
1816 if (NoReturnAA.isAssumedNoReturn())
Johannes Doerfert4361da22019-08-04 18:38:53 +00001817 return I;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001818 }
1819
1820 I = I->getNextNode();
1821 }
1822
1823 // get new paths (reachable blocks).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001824 for (const BasicBlock *SuccBB : successors(BB)) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001825 AssumedLiveBlocks.insert(SuccBB);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001826 ToBeExploredPaths.insert(&SuccBB->front());
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001827 }
1828
Johannes Doerfert4361da22019-08-04 18:38:53 +00001829 // No noreturn instruction found.
1830 return nullptr;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001831}
1832
Johannes Doerfertece81902019-08-12 22:05:53 +00001833ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A) {
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001834 const Function *F = getAssociatedFunction();
1835 ChangeStatus Status = ChangeStatus::UNCHANGED;
1836
1837 if (F->hasInternalLinkage() && AssumedLiveBlocks.empty()) {
1838 auto CallSiteCheck = [&](CallSite) { return false; };
1839
1840 // All callsites of F are dead.
1841 if (A.checkForAllCallSites(CallSiteCheck, *this, true))
1842 return ChangeStatus::UNCHANGED;
1843
1844 // There exists at least one live call site, so we explore the function.
1845 Status = ChangeStatus::CHANGED;
1846
1847 exploreFromEntry(A, F);
1848 }
1849
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001850 // Temporary collection to iterate over existing noreturn instructions. This
1851 // will alow easier modification of NoReturnCalls collection
Johannes Doerfert4361da22019-08-04 18:38:53 +00001852 SmallVector<const Instruction *, 8> NoReturnChanged;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001853
Johannes Doerfert4361da22019-08-04 18:38:53 +00001854 for (const Instruction *I : NoReturnCalls)
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001855 NoReturnChanged.push_back(I);
1856
Johannes Doerfert4361da22019-08-04 18:38:53 +00001857 for (const Instruction *I : NoReturnChanged) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001858 size_t Size = ToBeExploredPaths.size();
1859
Johannes Doerfert4361da22019-08-04 18:38:53 +00001860 const Instruction *NextNoReturnI = findNextNoReturn(A, I);
1861 if (NextNoReturnI != I) {
1862 Status = ChangeStatus::CHANGED;
1863 NoReturnCalls.remove(I);
1864 if (NextNoReturnI)
1865 NoReturnCalls.insert(NextNoReturnI);
1866 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001867
Johannes Doerfert4361da22019-08-04 18:38:53 +00001868 // Explore new paths.
1869 while (Size != ToBeExploredPaths.size()) {
1870 Status = ChangeStatus::CHANGED;
1871 if (const Instruction *NextNoReturnI =
1872 findNextNoReturn(A, ToBeExploredPaths[Size++]))
1873 NoReturnCalls.insert(NextNoReturnI);
1874 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001875 }
1876
Johannes Doerfertdef99282019-08-14 21:29:37 +00001877 LLVM_DEBUG(dbgs() << "[AAIsDead] AssumedLiveBlocks: "
1878 << AssumedLiveBlocks.size() << " Total number of blocks: "
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001879 << getAssociatedFunction()->size() << "\n");
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001880
Johannes Doerfertd6207812019-08-07 22:32:38 +00001881 // If we know everything is live there is no need to query for liveness.
1882 if (NoReturnCalls.empty() &&
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001883 getAssociatedFunction()->size() == AssumedLiveBlocks.size()) {
Johannes Doerfertd6207812019-08-07 22:32:38 +00001884 // Indicating a pessimistic fixpoint will cause the state to be "invalid"
1885 // which will cause the Attributor to not return the AAIsDead on request,
1886 // which will prevent us from querying isAssumedDead().
1887 indicatePessimisticFixpoint();
1888 assert(!isValidState() && "Expected an invalid state!");
1889 }
1890
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001891 return Status;
1892}
1893
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001894/// Liveness information for a call sites.
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001895//
1896// TODO: Once we have call site specific value information we can provide call
1897// site specific liveness liveness information and then it makes sense to
1898// specialize attributes for call sites instead of redirecting requests to
1899// the callee.
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001900using AAIsDeadCallSite = AAIsDeadFunction;
1901
Hideto Ueno19c07af2019-07-23 08:16:17 +00001902/// -------------------- Dereferenceable Argument Attribute --------------------
1903
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001904template <>
1905ChangeStatus clampStateAndIndicateChange<DerefState>(DerefState &S,
1906 const DerefState &R) {
1907 ChangeStatus CS0 = clampStateAndIndicateChange<IntegerState>(
1908 S.DerefBytesState, R.DerefBytesState);
1909 ChangeStatus CS1 =
1910 clampStateAndIndicateChange<IntegerState>(S.GlobalState, R.GlobalState);
1911 return CS0 | CS1;
1912}
1913
Hideto Ueno70576ca2019-08-22 14:18:29 +00001914struct AADereferenceableImpl : AADereferenceable {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001915 AADereferenceableImpl(const IRPosition &IRP) : AADereferenceable(IRP) {}
Johannes Doerfert344d0382019-08-07 22:34:26 +00001916 using StateType = DerefState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001917
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001918 void initialize(Attributor &A) override {
1919 SmallVector<Attribute, 4> Attrs;
1920 getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
1921 Attrs);
1922 for (const Attribute &Attr : Attrs)
1923 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
1924
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001925 NonNullAA = &A.getAAFor<AANonNull>(*this, getIRPosition());
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00001926 }
1927
Hideto Ueno19c07af2019-07-23 08:16:17 +00001928 /// See AbstractAttribute::getState()
1929 /// {
Johannes Doerfert344d0382019-08-07 22:34:26 +00001930 StateType &getState() override { return *this; }
1931 const StateType &getState() const override { return *this; }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001932 /// }
1933
Johannes Doerferteccdf082019-08-05 23:35:12 +00001934 void getDeducedAttributes(LLVMContext &Ctx,
1935 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001936 // TODO: Add *_globally support
1937 if (isAssumedNonNull())
1938 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
1939 Ctx, getAssumedDereferenceableBytes()));
1940 else
1941 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
1942 Ctx, getAssumedDereferenceableBytes()));
1943 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001944
1945 /// See AbstractAttribute::getAsStr().
1946 const std::string getAsStr() const override {
1947 if (!getAssumedDereferenceableBytes())
1948 return "unknown-dereferenceable";
1949 return std::string("dereferenceable") +
1950 (isAssumedNonNull() ? "" : "_or_null") +
1951 (isAssumedGlobal() ? "_globally" : "") + "<" +
1952 std::to_string(getKnownDereferenceableBytes()) + "-" +
1953 std::to_string(getAssumedDereferenceableBytes()) + ">";
1954 }
1955};
1956
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001957/// Dereferenceable attribute for a floating value.
1958struct AADereferenceableFloating : AADereferenceableImpl {
1959 AADereferenceableFloating(const IRPosition &IRP)
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001960 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001961
1962 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001963 ChangeStatus updateImpl(Attributor &A) override {
1964 const DataLayout &DL = A.getDataLayout();
1965
1966 auto VisitValueCB = [&](Value &V, DerefState &T, bool Stripped) -> bool {
1967 unsigned IdxWidth =
1968 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
1969 APInt Offset(IdxWidth, 0);
1970 const Value *Base =
1971 V.stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
1972
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001973 const auto &AA =
1974 A.getAAFor<AADereferenceable>(*this, IRPosition::value(*Base));
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001975 int64_t DerefBytes = 0;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001976 if (!Stripped && this == &AA) {
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001977 // Use IR information if we did not strip anything.
1978 // TODO: track globally.
1979 bool CanBeNull;
1980 DerefBytes = Base->getPointerDereferenceableBytes(DL, CanBeNull);
1981 T.GlobalState.indicatePessimisticFixpoint();
1982 } else {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001983 const DerefState &DS = static_cast<const DerefState &>(AA.getState());
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001984 DerefBytes = DS.DerefBytesState.getAssumed();
1985 T.GlobalState &= DS.GlobalState;
1986 }
1987
Johannes Doerfert2f2d7c32019-08-23 15:45:46 +00001988 // For now we do not try to "increase" dereferenceability due to negative
1989 // indices as we first have to come up with code to deal with loops and
1990 // for overflows of the dereferenceable bytes.
1991 if (Offset.getSExtValue() < 0)
1992 Offset = 0;
1993
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001994 T.takeAssumedDerefBytesMinimum(
1995 std::max(int64_t(0), DerefBytes - Offset.getSExtValue()));
1996
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001997 if (!Stripped && this == &AA) {
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00001998 T.takeKnownDerefBytesMaximum(
1999 std::max(int64_t(0), DerefBytes - Offset.getSExtValue()));
2000 T.indicatePessimisticFixpoint();
2001 }
2002
2003 return T.isValidState();
2004 };
2005
2006 DerefState T;
2007 if (!genericValueTraversal<AADereferenceable, DerefState>(
2008 A, getIRPosition(), *this, T, VisitValueCB))
2009 return indicatePessimisticFixpoint();
2010
2011 return clampStateAndIndicateChange(getState(), T);
2012 }
2013
2014 /// See AbstractAttribute::trackStatistics()
2015 void trackStatistics() const override {
2016 STATS_DECLTRACK_FLOATING_ATTR(dereferenceable)
2017 }
2018};
2019
2020/// Dereferenceable attribute for a return value.
2021struct AADereferenceableReturned final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002022 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl,
2023 DerefState> {
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002024 AADereferenceableReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002025 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl,
2026 DerefState>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002027
2028 /// See AbstractAttribute::trackStatistics()
2029 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002030 STATS_DECLTRACK_FNRET_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002031 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002032};
2033
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002034/// Dereferenceable attribute for an argument
2035struct AADereferenceableArgument final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002036 : AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl,
2037 DerefState> {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002038 AADereferenceableArgument(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002039 : AAArgumentFromCallSiteArguments<AADereferenceable,
2040 AADereferenceableImpl, DerefState>(
2041 IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002042
2043 /// See AbstractAttribute::trackStatistics()
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002044 void trackStatistics() const override{
Johannes Doerfert169af992019-08-20 06:09:56 +00002045 STATS_DECLTRACK_ARG_ATTR(dereferenceable)
2046 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002047};
2048
Hideto Ueno19c07af2019-07-23 08:16:17 +00002049/// Dereferenceable attribute for a call site argument.
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002050struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002051 AADereferenceableCallSiteArgument(const IRPosition &IRP)
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002052 : AADereferenceableFloating(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002053
2054 /// See AbstractAttribute::trackStatistics()
2055 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002056 STATS_DECLTRACK_CSARG_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002057 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002058};
2059
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002060/// Dereferenceable attribute deduction for a call site return value.
2061using AADereferenceableCallSiteReturned = AADereferenceableReturned;
2062
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002063// ------------------------ Align Argument Attribute ------------------------
2064
Johannes Doerfert344d0382019-08-07 22:34:26 +00002065struct AAAlignImpl : AAAlign {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002066 AAAlignImpl(const IRPosition &IRP) : AAAlign(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002067
2068 // Max alignemnt value allowed in IR
2069 static const unsigned MAX_ALIGN = 1U << 29;
2070
Johannes Doerfert234eda52019-08-16 19:51:23 +00002071 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002072 void initialize(Attributor &A) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002073 takeAssumedMinimum(MAX_ALIGN);
2074
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002075 SmallVector<Attribute, 4> Attrs;
2076 getAttrs({Attribute::Alignment}, Attrs);
2077 for (const Attribute &Attr : Attrs)
2078 takeKnownMaximum(Attr.getValueAsInt());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002079 }
2080
2081 /// See AbstractAttribute::getDeducedAttributes
2082 virtual void
Johannes Doerferteccdf082019-08-05 23:35:12 +00002083 getDeducedAttributes(LLVMContext &Ctx,
2084 SmallVectorImpl<Attribute> &Attrs) const override {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002085 if (getAssumedAlign() > 1)
2086 Attrs.emplace_back(Attribute::getWithAlignment(Ctx, getAssumedAlign()));
2087 }
2088
2089 /// See AbstractAttribute::getAsStr().
2090 const std::string getAsStr() const override {
2091 return getAssumedAlign() ? ("align<" + std::to_string(getKnownAlign()) +
2092 "-" + std::to_string(getAssumedAlign()) + ">")
2093 : "unknown-align";
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002094 }
2095};
2096
Johannes Doerfert234eda52019-08-16 19:51:23 +00002097/// Align attribute for a floating value.
2098struct AAAlignFloating : AAAlignImpl {
2099 AAAlignFloating(const IRPosition &IRP) : AAAlignImpl(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002100
2101 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert234eda52019-08-16 19:51:23 +00002102 ChangeStatus updateImpl(Attributor &A) override {
2103 const DataLayout &DL = A.getDataLayout();
2104
Johannes Doerfertb9b87912019-08-20 06:02:39 +00002105 auto VisitValueCB = [&](Value &V, AAAlign::StateType &T,
2106 bool Stripped) -> bool {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002107 const auto &AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V));
2108 if (!Stripped && this == &AA) {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002109 // Use only IR information if we did not strip anything.
2110 T.takeKnownMaximum(V.getPointerAlignment(DL));
2111 T.indicatePessimisticFixpoint();
Johannes Doerfert234eda52019-08-16 19:51:23 +00002112 } else {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002113 // Use abstract attribute information.
2114 const AAAlign::StateType &DS =
2115 static_cast<const AAAlign::StateType &>(AA.getState());
2116 T ^= DS;
Johannes Doerfert234eda52019-08-16 19:51:23 +00002117 }
Johannes Doerfertb9b87912019-08-20 06:02:39 +00002118 return T.isValidState();
Johannes Doerfert234eda52019-08-16 19:51:23 +00002119 };
2120
2121 StateType T;
2122 if (!genericValueTraversal<AAAlign, StateType>(A, getIRPosition(), *this, T,
2123 VisitValueCB))
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002124 return indicatePessimisticFixpoint();
Johannes Doerfert234eda52019-08-16 19:51:23 +00002125
Johannes Doerfert028b2aa2019-08-20 05:57:01 +00002126 // TODO: If we know we visited all incoming values, thus no are assumed
2127 // dead, we can take the known information from the state T.
Johannes Doerfert234eda52019-08-16 19:51:23 +00002128 return clampStateAndIndicateChange(getState(), T);
2129 }
2130
2131 /// See AbstractAttribute::trackStatistics()
2132 void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) }
2133};
2134
2135/// Align attribute for function return value.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002136struct AAAlignReturned final
2137 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002138 AAAlignReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002139 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002140
2141 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002142 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002143};
2144
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002145/// Align attribute for function argument.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002146struct AAAlignArgument final
2147 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002148 AAAlignArgument(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002149 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002150
2151 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert169af992019-08-20 06:09:56 +00002152 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002153};
2154
Johannes Doerfert234eda52019-08-16 19:51:23 +00002155struct AAAlignCallSiteArgument final : AAAlignFloating {
2156 AAAlignCallSiteArgument(const IRPosition &IRP) : AAAlignFloating(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002157
2158 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002159 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002160};
2161
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002162/// Align attribute deduction for a call site return value.
2163using AAAlignCallSiteReturned = AAAlignReturned;
2164
Johannes Doerferte83f3032019-08-05 23:22:05 +00002165/// ------------------ Function No-Return Attribute ----------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00002166struct AANoReturnImpl : public AANoReturn {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002167 AANoReturnImpl(const IRPosition &IRP) : AANoReturn(IRP) {}
Johannes Doerferte83f3032019-08-05 23:22:05 +00002168
Johannes Doerferte83f3032019-08-05 23:22:05 +00002169 /// See AbstractAttribute::getAsStr().
2170 const std::string getAsStr() const override {
2171 return getAssumed() ? "noreturn" : "may-return";
2172 }
2173
2174 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002175 void initialize(Attributor &A) override {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002176 if (hasAttr({getAttrKind()}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002177 indicateOptimisticFixpoint();
2178 }
2179
2180 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00002181 virtual ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002182 auto CheckForNoReturn = [](Instruction &) { return false; };
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002183 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002184 {(unsigned)Instruction::Ret}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002185 return indicatePessimisticFixpoint();
Johannes Doerferte83f3032019-08-05 23:22:05 +00002186 return ChangeStatus::UNCHANGED;
2187 }
2188};
2189
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002190struct AANoReturnFunction final : AANoReturnImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002191 AANoReturnFunction(const IRPosition &IRP) : AANoReturnImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002192
2193 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002194 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002195};
2196
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002197/// NoReturn attribute deduction for a call sites.
2198using AANoReturnCallSite = AANoReturnFunction;
2199
Johannes Doerfertaade7822019-06-05 03:02:24 +00002200/// ----------------------------------------------------------------------------
2201/// Attributor
2202/// ----------------------------------------------------------------------------
2203
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002204bool Attributor::isAssumedDead(const AbstractAttribute &AA,
2205 const AAIsDead *LivenessAA) {
2206 const Instruction *CtxI = AA.getIRPosition().getCtxI();
2207 if (!CtxI)
2208 return false;
2209
2210 if (!LivenessAA)
2211 LivenessAA =
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002212 &getAAFor<AAIsDead>(AA, IRPosition::function(*CtxI->getFunction()));
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00002213
2214 // Don't check liveness for AAIsDead.
2215 if (&AA == LivenessAA)
2216 return false;
2217
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002218 if (!LivenessAA->isAssumedDead(CtxI))
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002219 return false;
2220
2221 // TODO: Do not track dependences automatically but add it here as only a
2222 // "is-assumed-dead" result causes a dependence.
2223 return true;
2224}
2225
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002226bool Attributor::checkForAllCallSites(const function_ref<bool(CallSite)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002227 const AbstractAttribute &QueryingAA,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002228 bool RequireAllCallSites) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002229 // We can try to determine information from
2230 // the call sites. However, this is only possible all call sites are known,
2231 // hence the function has internal linkage.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002232 const IRPosition &IRP = QueryingAA.getIRPosition();
2233 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2234 if (!AssociatedFunction)
2235 return false;
2236
2237 if (RequireAllCallSites && !AssociatedFunction->hasInternalLinkage()) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002238 LLVM_DEBUG(
2239 dbgs()
Johannes Doerfert5304b722019-08-14 22:04:28 +00002240 << "[Attributor] Function " << AssociatedFunction->getName()
Hideto Ueno54869ec2019-07-15 06:49:04 +00002241 << " has no internal linkage, hence not all call sites are known\n");
2242 return false;
2243 }
2244
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002245 for (const Use &U : AssociatedFunction->uses()) {
Johannes Doerfertd98f9752019-08-21 21:48:56 +00002246 Instruction *I = dyn_cast<Instruction>(U.getUser());
2247 // TODO: Deal with abstract call sites here.
2248 if (!I)
2249 return false;
2250
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002251 Function *Caller = I->getFunction();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002252
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002253 const auto &LivenessAA =
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002254 getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*Caller));
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002255
2256 // Skip dead calls.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002257 if (LivenessAA.isAssumedDead(I))
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002258 continue;
Hideto Ueno54869ec2019-07-15 06:49:04 +00002259
2260 CallSite CS(U.getUser());
Hideto Ueno54869ec2019-07-15 06:49:04 +00002261 if (!CS || !CS.isCallee(&U) || !CS.getCaller()->hasExactDefinition()) {
2262 if (!RequireAllCallSites)
2263 continue;
2264
Johannes Doerfert5304b722019-08-14 22:04:28 +00002265 LLVM_DEBUG(dbgs() << "[Attributor] User " << *U.getUser()
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002266 << " is an invalid use of "
2267 << AssociatedFunction->getName() << "\n");
Hideto Ueno54869ec2019-07-15 06:49:04 +00002268 return false;
2269 }
2270
2271 if (Pred(CS))
2272 continue;
2273
Johannes Doerfert5304b722019-08-14 22:04:28 +00002274 LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for "
Hideto Ueno54869ec2019-07-15 06:49:04 +00002275 << *CS.getInstruction() << "\n");
2276 return false;
2277 }
2278
2279 return true;
2280}
2281
Johannes Doerfert14a04932019-08-07 22:27:24 +00002282bool Attributor::checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +00002283 const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)>
Johannes Doerfert14a04932019-08-07 22:27:24 +00002284 &Pred,
2285 const AbstractAttribute &QueryingAA) {
2286
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002287 const IRPosition &IRP = QueryingAA.getIRPosition();
2288 // Since we need to provide return instructions we have to have an exact
2289 // definition.
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 // If this is a call site query we use the call site specific return values
2295 // and liveness information.
2296 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2297 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002298 if (!AARetVal.getState().isValidState())
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002299 return false;
2300
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002301 return AARetVal.checkForAllReturnedValuesAndReturnInsts(Pred);
Johannes Doerfert14a04932019-08-07 22:27:24 +00002302}
2303
2304bool Attributor::checkForAllReturnedValues(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002305 const function_ref<bool(Value &)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002306 const AbstractAttribute &QueryingAA) {
2307
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002308 const IRPosition &IRP = QueryingAA.getIRPosition();
2309 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2310 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
Johannes Doerfert14a04932019-08-07 22:27:24 +00002311 return false;
2312
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002313 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2314 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002315 if (!AARetVal.getState().isValidState())
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002316 return false;
2317
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002318 return AARetVal.checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +00002319 [&](Value &RV, const SmallSetVector<ReturnInst *, 4> &) {
Johannes Doerfertdef99282019-08-14 21:29:37 +00002320 return Pred(RV);
2321 });
Johannes Doerfert14a04932019-08-07 22:27:24 +00002322}
2323
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002324bool Attributor::checkForAllInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002325 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00002326 const AbstractAttribute &QueryingAA, const ArrayRef<unsigned> &Opcodes) {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002327
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002328 const IRPosition &IRP = QueryingAA.getIRPosition();
2329 // Since we need to provide instructions we have to have an exact definition.
2330 const Function *AssociatedFunction = IRP.getAssociatedFunction();
2331 if (!AssociatedFunction || !AssociatedFunction->hasExactDefinition())
2332 return false;
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002333
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002334 const IRPosition &QueryIRP = IRPosition::function_scope(IRP);
2335 const auto &LivenessAA = getAAFor<AAIsDead>(QueryingAA, QueryIRP);
2336
2337 auto &OpcodeInstMap =
2338 InfoCache.getOpcodeInstMapForFunction(*AssociatedFunction);
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002339 for (unsigned Opcode : Opcodes) {
2340 for (Instruction *I : OpcodeInstMap[Opcode]) {
2341 // Skip dead instructions.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002342 if (LivenessAA.isAssumedDead(I))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002343 continue;
2344
2345 if (!Pred(*I))
2346 return false;
2347 }
2348 }
2349
2350 return true;
2351}
2352
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002353bool Attributor::checkForAllReadWriteInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002354 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00002355 AbstractAttribute &QueryingAA) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002356
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002357 const Function *AssociatedFunction =
2358 QueryingAA.getIRPosition().getAssociatedFunction();
2359 if (!AssociatedFunction)
2360 return false;
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002361
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002362 const auto &LivenessAA =
2363 getAAFor<AAIsDead>(QueryingAA, QueryingAA.getIRPosition());
2364
2365 for (Instruction *I :
2366 InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002367 // Skip dead instructions.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002368 if (LivenessAA.isAssumedDead(I))
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002369 continue;
2370
2371 if (!Pred(*I))
2372 return false;
2373 }
2374
2375 return true;
2376}
2377
Johannes Doerfertece81902019-08-12 22:05:53 +00002378ChangeStatus Attributor::run() {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002379 // Initialize all abstract attributes, allow new ones to be created.
2380 for (unsigned u = 0; u < AllAbstractAttributes.size(); u++)
2381 AllAbstractAttributes[u]->initialize(*this);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002382
2383 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
2384 << AllAbstractAttributes.size()
2385 << " abstract attributes.\n");
2386
Stefan Stipanovic53605892019-06-27 11:27:54 +00002387 // Now that all abstract attributes are collected and initialized we start
2388 // the abstract analysis.
Johannes Doerfertaade7822019-06-05 03:02:24 +00002389
2390 unsigned IterationCounter = 1;
2391
2392 SmallVector<AbstractAttribute *, 64> ChangedAAs;
2393 SetVector<AbstractAttribute *> Worklist;
2394 Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
2395
2396 do {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002397 // Remember the size to determine new attributes.
2398 size_t NumAAs = AllAbstractAttributes.size();
Johannes Doerfertaade7822019-06-05 03:02:24 +00002399 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
2400 << ", Worklist size: " << Worklist.size() << "\n");
2401
2402 // Add all abstract attributes that are potentially dependent on one that
2403 // changed to the work list.
2404 for (AbstractAttribute *ChangedAA : ChangedAAs) {
2405 auto &QuerriedAAs = QueryMap[ChangedAA];
2406 Worklist.insert(QuerriedAAs.begin(), QuerriedAAs.end());
2407 }
2408
2409 // Reset the changed set.
2410 ChangedAAs.clear();
2411
2412 // Update all abstract attribute in the work list and record the ones that
2413 // changed.
2414 for (AbstractAttribute *AA : Worklist)
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002415 if (!isAssumedDead(*AA, nullptr))
2416 if (AA->update(*this) == ChangeStatus::CHANGED)
2417 ChangedAAs.push_back(AA);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002418
Johannes Doerfert9543f142019-08-23 15:24:57 +00002419 // Add attributes to the changed set if they have been created in the last
2420 // iteration.
2421 ChangedAAs.append(AllAbstractAttributes.begin() + NumAAs,
2422 AllAbstractAttributes.end());
2423
Johannes Doerfertaade7822019-06-05 03:02:24 +00002424 // Reset the work list and repopulate with the changed abstract attributes.
2425 // Note that dependent ones are added above.
2426 Worklist.clear();
2427 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2428
2429 } while (!Worklist.empty() && ++IterationCounter < MaxFixpointIterations);
2430
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002431 size_t NumFinalAAs = AllAbstractAttributes.size();
2432
Johannes Doerfertaade7822019-06-05 03:02:24 +00002433 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
2434 << IterationCounter << "/" << MaxFixpointIterations
2435 << " iterations\n");
2436
2437 bool FinishedAtFixpoint = Worklist.empty();
2438
2439 // Reset abstract arguments not settled in a sound fixpoint by now. This
2440 // happens when we stopped the fixpoint iteration early. Note that only the
2441 // ones marked as "changed" *and* the ones transitively depending on them
2442 // need to be reverted to a pessimistic state. Others might not be in a
2443 // fixpoint state but we can use the optimistic results for them anyway.
2444 SmallPtrSet<AbstractAttribute *, 32> Visited;
2445 for (unsigned u = 0; u < ChangedAAs.size(); u++) {
2446 AbstractAttribute *ChangedAA = ChangedAAs[u];
2447 if (!Visited.insert(ChangedAA).second)
2448 continue;
2449
2450 AbstractState &State = ChangedAA->getState();
2451 if (!State.isAtFixpoint()) {
2452 State.indicatePessimisticFixpoint();
2453
2454 NumAttributesTimedOut++;
2455 }
2456
2457 auto &QuerriedAAs = QueryMap[ChangedAA];
2458 ChangedAAs.append(QuerriedAAs.begin(), QuerriedAAs.end());
2459 }
2460
2461 LLVM_DEBUG({
2462 if (!Visited.empty())
2463 dbgs() << "\n[Attributor] Finalized " << Visited.size()
2464 << " abstract attributes.\n";
2465 });
2466
2467 unsigned NumManifested = 0;
2468 unsigned NumAtFixpoint = 0;
2469 ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
2470 for (AbstractAttribute *AA : AllAbstractAttributes) {
2471 AbstractState &State = AA->getState();
2472
2473 // If there is not already a fixpoint reached, we can now take the
2474 // optimistic state. This is correct because we enforced a pessimistic one
2475 // on abstract attributes that were transitively dependent on a changed one
2476 // already above.
2477 if (!State.isAtFixpoint())
2478 State.indicateOptimisticFixpoint();
2479
2480 // If the state is invalid, we do not try to manifest it.
2481 if (!State.isValidState())
2482 continue;
2483
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00002484 // Skip dead code.
2485 if (isAssumedDead(*AA, nullptr))
2486 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002487 // Manifest the state and record if we changed the IR.
2488 ChangeStatus LocalChange = AA->manifest(*this);
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002489 if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled())
2490 AA->trackStatistics();
2491
Johannes Doerfertaade7822019-06-05 03:02:24 +00002492 ManifestChange = ManifestChange | LocalChange;
2493
2494 NumAtFixpoint++;
2495 NumManifested += (LocalChange == ChangeStatus::CHANGED);
2496 }
2497
2498 (void)NumManifested;
2499 (void)NumAtFixpoint;
2500 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
2501 << " arguments while " << NumAtFixpoint
2502 << " were in a valid fixpoint state\n");
2503
2504 // If verification is requested, we finished this run at a fixpoint, and the
2505 // IR was changed, we re-run the whole fixpoint analysis, starting at
2506 // re-initialization of the arguments. This re-run should not result in an IR
2507 // change. Though, the (virtual) state of attributes at the end of the re-run
2508 // might be more optimistic than the known state or the IR state if the better
2509 // state cannot be manifested.
2510 if (VerifyAttributor && FinishedAtFixpoint &&
2511 ManifestChange == ChangeStatus::CHANGED) {
2512 VerifyAttributor = false;
Johannes Doerfertece81902019-08-12 22:05:53 +00002513 ChangeStatus VerifyStatus = run();
Johannes Doerfertaade7822019-06-05 03:02:24 +00002514 if (VerifyStatus != ChangeStatus::UNCHANGED)
2515 llvm_unreachable(
2516 "Attributor verification failed, re-run did result in an IR change "
2517 "even after a fixpoint was reached in the original run. (False "
2518 "positives possible!)");
2519 VerifyAttributor = true;
2520 }
2521
2522 NumAttributesManifested += NumManifested;
2523 NumAttributesValidFixpoint += NumAtFixpoint;
2524
Fangrui Songf1826172019-08-20 07:21:43 +00002525 (void)NumFinalAAs;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002526 assert(
2527 NumFinalAAs == AllAbstractAttributes.size() &&
2528 "Expected the final number of abstract attributes to remain unchanged!");
Johannes Doerfertaade7822019-06-05 03:02:24 +00002529 return ManifestChange;
2530}
2531
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002532/// Helper function that checks if an abstract attribute of type \p AAType
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002533/// should be created for IR position \p IRP and if so creates and registers it
2534/// with the Attributor \p A.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002535///
2536/// This method will look at the provided whitelist. If one is given and the
2537/// kind \p AAType::ID is not contained, no abstract attribute is created.
2538///
2539/// \returns The created abstract argument, or nullptr if none was created.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002540template <typename AAType>
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002541static const AAType *checkAndRegisterAA(const IRPosition &IRP, Attributor &A,
2542 DenseSet<const char *> *Whitelist) {
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002543 if (Whitelist && !Whitelist->count(&AAType::ID))
2544 return nullptr;
2545
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002546 return &A.registerAA<AAType>(*new AAType(IRP));
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002547}
2548
Johannes Doerfertaade7822019-06-05 03:02:24 +00002549void Attributor::identifyDefaultAbstractAttributes(
Johannes Doerfertece81902019-08-12 22:05:53 +00002550 Function &F, DenseSet<const char *> *Whitelist) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002551
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002552 IRPosition FPos = IRPosition::function(F);
2553
Johannes Doerfert305b9612019-08-04 18:40:01 +00002554 // Check for dead BasicBlocks in every function.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002555 // We need dead instruction detection because we do not want to deal with
2556 // broken IR in which SSA rules do not apply.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002557 checkAndRegisterAA<AAIsDeadFunction>(FPos, *this, /* Whitelist */ nullptr);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002558
2559 // Every function might be "will-return".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002560 checkAndRegisterAA<AAWillReturnFunction>(FPos, *this, Whitelist);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002561
Stefan Stipanovic53605892019-06-27 11:27:54 +00002562 // Every function can be nounwind.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002563 checkAndRegisterAA<AANoUnwindFunction>(FPos, *this, Whitelist);
Stefan Stipanovic53605892019-06-27 11:27:54 +00002564
Stefan Stipanovic06263672019-07-11 21:37:40 +00002565 // Every function might be marked "nosync"
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002566 checkAndRegisterAA<AANoSyncFunction>(FPos, *this, Whitelist);
Stefan Stipanovic06263672019-07-11 21:37:40 +00002567
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002568 // Every function might be "no-free".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002569 checkAndRegisterAA<AANoFreeFunction>(FPos, *this, Whitelist);
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002570
Johannes Doerferte83f3032019-08-05 23:22:05 +00002571 // Every function might be "no-return".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002572 checkAndRegisterAA<AANoReturnFunction>(FPos, *this, Whitelist);
Johannes Doerferte83f3032019-08-05 23:22:05 +00002573
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002574 // Return attributes are only appropriate if the return type is non void.
2575 Type *ReturnType = F.getReturnType();
2576 if (!ReturnType->isVoidTy()) {
2577 // Argument attribute "returned" --- Create only one per function even
2578 // though it is an argument attribute.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002579 checkAndRegisterAA<AAReturnedValuesFunction>(FPos, *this, Whitelist);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002580
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002581 if (ReturnType->isPointerTy()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002582 IRPosition RetPos = IRPosition::returned(F);
2583
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002584 // Every function with pointer return type might be marked align.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002585 checkAndRegisterAA<AAAlignReturned>(RetPos, *this, Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002586
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002587 // Every function with pointer return type might be marked nonnull.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002588 checkAndRegisterAA<AANonNullReturned>(RetPos, *this, Whitelist);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002589
2590 // Every function with pointer return type might be marked noalias.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002591 checkAndRegisterAA<AANoAliasReturned>(RetPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002592
2593 // Every function with pointer return type might be marked
2594 // dereferenceable.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002595 checkAndRegisterAA<AADereferenceableReturned>(RetPos, *this, Whitelist);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002596 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00002597 }
2598
Hideto Ueno54869ec2019-07-15 06:49:04 +00002599 for (Argument &Arg : F.args()) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002600 if (Arg.getType()->isPointerTy()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002601 IRPosition ArgPos = IRPosition::argument(Arg);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002602 // Every argument with pointer type might be marked nonnull.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002603 checkAndRegisterAA<AANonNullArgument>(ArgPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002604
2605 // Every argument with pointer type might be marked dereferenceable.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002606 checkAndRegisterAA<AADereferenceableArgument>(ArgPos, *this, Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002607
2608 // Every argument with pointer type might be marked align.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002609 checkAndRegisterAA<AAAlignArgument>(ArgPos, *this, Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002610 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002611 }
2612
Johannes Doerfertaade7822019-06-05 03:02:24 +00002613 // Walk all instructions to find more attribute opportunities and also
2614 // interesting instructions that might be queried by abstract attributes
2615 // during their initialization or update.
2616 auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
2617 auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
2618
2619 for (Instruction &I : instructions(&F)) {
2620 bool IsInterestingOpcode = false;
2621
2622 // To allow easy access to all instructions in a function with a given
2623 // opcode we store them in the InfoCache. As not all opcodes are interesting
2624 // to concrete attributes we only cache the ones that are as identified in
2625 // the following switch.
2626 // Note: There are no concrete attributes now so this is initially empty.
Stefan Stipanovic53605892019-06-27 11:27:54 +00002627 switch (I.getOpcode()) {
2628 default:
2629 assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) &&
2630 "New call site/base instruction type needs to be known int the "
2631 "attributor.");
2632 break;
2633 case Instruction::Call:
2634 case Instruction::CallBr:
2635 case Instruction::Invoke:
2636 case Instruction::CleanupRet:
2637 case Instruction::CatchSwitch:
2638 case Instruction::Resume:
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002639 case Instruction::Ret:
Stefan Stipanovic53605892019-06-27 11:27:54 +00002640 IsInterestingOpcode = true;
2641 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002642 if (IsInterestingOpcode)
2643 InstOpcodeMap[I.getOpcode()].push_back(&I);
2644 if (I.mayReadOrWriteMemory())
2645 ReadOrWriteInsts.push_back(&I);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002646
2647 CallSite CS(&I);
2648 if (CS && CS.getCalledFunction()) {
2649 for (int i = 0, e = CS.getCalledFunction()->arg_size(); i < e; i++) {
2650 if (!CS.getArgument(i)->getType()->isPointerTy())
2651 continue;
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002652 IRPosition CSArgPos = IRPosition::callsite_argument(CS, i);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002653
2654 // Call site argument attribute "non-null".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002655 checkAndRegisterAA<AANonNullCallSiteArgument>(CSArgPos, *this,
2656 Whitelist);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002657
2658 // Call site argument attribute "dereferenceable".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002659 checkAndRegisterAA<AADereferenceableCallSiteArgument>(CSArgPos, *this,
2660 Whitelist);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002661
2662 // Call site argument attribute "align".
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002663 checkAndRegisterAA<AAAlignCallSiteArgument>(CSArgPos, *this, Whitelist);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002664 }
2665 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002666 }
2667}
2668
2669/// Helpers to ease debugging through output streams and print calls.
2670///
2671///{
2672raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
2673 return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
2674}
2675
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002676raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002677 switch (AP) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002678 case IRPosition::IRP_INVALID:
2679 return OS << "inv";
2680 case IRPosition::IRP_FLOAT:
2681 return OS << "flt";
2682 case IRPosition::IRP_RETURNED:
2683 return OS << "fn_ret";
2684 case IRPosition::IRP_CALL_SITE_RETURNED:
2685 return OS << "cs_ret";
2686 case IRPosition::IRP_FUNCTION:
2687 return OS << "fn";
2688 case IRPosition::IRP_CALL_SITE:
2689 return OS << "cs";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002690 case IRPosition::IRP_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002691 return OS << "arg";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002692 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002693 return OS << "cs_arg";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002694 }
2695 llvm_unreachable("Unknown attribute position!");
2696}
2697
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002698raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002699 const Value &AV = Pos.getAssociatedValue();
2700 return OS << "{" << Pos.getPositionKind() << ":" << AV.getName() << " ["
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002701 << Pos.getAnchorValue().getName() << "@" << Pos.getArgNo() << "]}";
2702}
2703
Johannes Doerfertacc80792019-08-12 22:07:34 +00002704raw_ostream &llvm::operator<<(raw_ostream &OS, const IntegerState &S) {
2705 return OS << "(" << S.getKnown() << "-" << S.getAssumed() << ")"
2706 << static_cast<const AbstractState &>(S);
2707}
2708
Johannes Doerfertaade7822019-06-05 03:02:24 +00002709raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
2710 return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
2711}
2712
2713raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
2714 AA.print(OS);
2715 return OS;
2716}
2717
2718void AbstractAttribute::print(raw_ostream &OS) const {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002719 OS << "[P: " << getIRPosition() << "][" << getAsStr() << "][S: " << getState()
2720 << "]";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002721}
2722///}
2723
2724/// ----------------------------------------------------------------------------
2725/// Pass (Manager) Boilerplate
2726/// ----------------------------------------------------------------------------
2727
2728static bool runAttributorOnModule(Module &M) {
2729 if (DisableAttributor)
2730 return false;
2731
2732 LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << M.size()
2733 << " functions.\n");
2734
2735 // Create an Attributor and initially empty information cache that is filled
2736 // while we identify default attribute opportunities.
Johannes Doerfertece81902019-08-12 22:05:53 +00002737 InformationCache InfoCache(M.getDataLayout());
2738 Attributor A(InfoCache);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002739
2740 for (Function &F : M) {
2741 // TODO: Not all attributes require an exact definition. Find a way to
2742 // enable deduction for some but not all attributes in case the
2743 // definition might be changed at runtime, see also
2744 // http://lists.llvm.org/pipermail/llvm-dev/2018-February/121275.html.
2745 // TODO: We could always determine abstract attributes and if sufficient
2746 // information was found we could duplicate the functions that do not
2747 // have an exact definition.
2748 if (!F.hasExactDefinition()) {
2749 NumFnWithoutExactDefinition++;
2750 continue;
2751 }
2752
2753 // For now we ignore naked and optnone functions.
2754 if (F.hasFnAttribute(Attribute::Naked) ||
2755 F.hasFnAttribute(Attribute::OptimizeNone))
2756 continue;
2757
2758 NumFnWithExactDefinition++;
2759
2760 // Populate the Attributor with abstract attribute opportunities in the
2761 // function and the information cache with IR information.
Johannes Doerfertece81902019-08-12 22:05:53 +00002762 A.identifyDefaultAbstractAttributes(F);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002763 }
2764
Johannes Doerfertece81902019-08-12 22:05:53 +00002765 return A.run() == ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002766}
2767
2768PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
2769 if (runAttributorOnModule(M)) {
2770 // FIXME: Think about passes we will preserve and add them here.
2771 return PreservedAnalyses::none();
2772 }
2773 return PreservedAnalyses::all();
2774}
2775
2776namespace {
2777
2778struct AttributorLegacyPass : public ModulePass {
2779 static char ID;
2780
2781 AttributorLegacyPass() : ModulePass(ID) {
2782 initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry());
2783 }
2784
2785 bool runOnModule(Module &M) override {
2786 if (skipModule(M))
2787 return false;
2788 return runAttributorOnModule(M);
2789 }
2790
2791 void getAnalysisUsage(AnalysisUsage &AU) const override {
2792 // FIXME: Think about passes we will preserve and add them here.
2793 AU.setPreservesCFG();
2794 }
2795};
2796
2797} // end anonymous namespace
2798
2799Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); }
2800
2801char AttributorLegacyPass::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002802
2803const char AAReturnedValues::ID = 0;
2804const char AANoUnwind::ID = 0;
2805const char AANoSync::ID = 0;
Johannes Doerferteccdf082019-08-05 23:35:12 +00002806const char AANoFree::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002807const char AANonNull::ID = 0;
2808const char AANoRecurse::ID = 0;
2809const char AAWillReturn::ID = 0;
2810const char AANoAlias::ID = 0;
2811const char AANoReturn::ID = 0;
2812const char AAIsDead::ID = 0;
2813const char AADereferenceable::ID = 0;
2814const char AAAlign::ID = 0;
2815
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002816// Macro magic to create the static generator function for attributes that
2817// follow the naming scheme.
2818
2819#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
2820 case IRPosition::PK: \
2821 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
2822
2823#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
2824 case IRPosition::PK: \
2825 AA = new CLASS##SUFFIX(IRP); \
2826 break;
2827
2828#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
2829 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
2830 CLASS *AA = nullptr; \
2831 switch (IRP.getPositionKind()) { \
2832 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
2833 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
2834 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
2835 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
2836 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
2837 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
2838 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
2839 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
2840 } \
2841 AA->initialize(A); \
2842 return *AA; \
2843 }
2844
2845#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
2846 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
2847 CLASS *AA = nullptr; \
2848 switch (IRP.getPositionKind()) { \
2849 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
2850 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
2851 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
2852 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
2853 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
2854 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
2855 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
2856 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
2857 } \
2858 AA->initialize(A); \
2859 return *AA; \
2860 }
2861
2862CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind)
2863CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync)
2864CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)
2865CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse)
2866CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn)
2867CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn)
2868CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead)
2869CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReturnedValues)
2870
2871CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull)
2872CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias)
2873CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable)
2874CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign)
2875
2876#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
2877#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
2878#undef SWITCH_PK_CREATE
2879#undef SWITCH_PK_INV
2880
Johannes Doerfertaade7822019-06-05 03:02:24 +00002881INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor",
2882 "Deduce and propagate attributes", false, false)
2883INITIALIZE_PASS_END(AttributorLegacyPass, "attributor",
2884 "Deduce and propagate attributes", false, false)