blob: 0f5d2aa8e170164fc7be31f08566c35d87227438 [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"
Stefan Stipanovic431141c2019-09-15 21:47:41 +000027#include "llvm/Analysis/MemoryBuiltins.h"
Hideto Ueno54869ec2019-07-15 06:49:04 +000028#include "llvm/Analysis/ValueTracking.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000029#include "llvm/IR/Argument.h"
30#include "llvm/IR/Attributes.h"
Hideto Ueno11d37102019-07-17 15:15:43 +000031#include "llvm/IR/CFG.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000032#include "llvm/IR/InstIterator.h"
Stefan Stipanovic06263672019-07-11 21:37:40 +000033#include "llvm/IR/IntrinsicInst.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000034#include "llvm/Support/CommandLine.h"
35#include "llvm/Support/Debug.h"
36#include "llvm/Support/raw_ostream.h"
Stefan Stipanovic6058b862019-07-22 23:58:23 +000037#include "llvm/Transforms/Utils/BasicBlockUtils.h"
38#include "llvm/Transforms/Utils/Local.h"
39
Johannes Doerfertaade7822019-06-05 03:02:24 +000040#include <cassert>
41
42using namespace llvm;
43
44#define DEBUG_TYPE "attributor"
45
46STATISTIC(NumFnWithExactDefinition,
47 "Number of function with exact definitions");
48STATISTIC(NumFnWithoutExactDefinition,
49 "Number of function without exact definitions");
50STATISTIC(NumAttributesTimedOut,
51 "Number of abstract attributes timed out before fixpoint");
52STATISTIC(NumAttributesValidFixpoint,
53 "Number of abstract attributes in a valid fixpoint state");
54STATISTIC(NumAttributesManifested,
55 "Number of abstract attributes manifested in IR");
56
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000057// Some helper macros to deal with statistics tracking.
58//
59// Usage:
60// For simple IR attribute tracking overload trackStatistics in the abstract
Johannes Doerfert17b578b2019-08-14 21:46:25 +000061// attribute and choose the right STATS_DECLTRACK_********* macro,
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000062// e.g.,:
63// void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +000064// STATS_DECLTRACK_ARG_ATTR(returned)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000065// }
66// If there is a single "increment" side one can use the macro
Johannes Doerfert17b578b2019-08-14 21:46:25 +000067// STATS_DECLTRACK with a custom message. If there are multiple increment
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000068// sides, STATS_DECL and STATS_TRACK can also be used separatly.
69//
70#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
71 ("Number of " #TYPE " marked '" #NAME "'")
72#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
Johannes Doerferta7a3b3a2019-09-04 19:01:08 +000073#define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);
74#define STATS_DECL(NAME, TYPE, MSG) \
75 STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000076#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
Johannes Doerfert17b578b2019-08-14 21:46:25 +000077#define STATS_DECLTRACK(NAME, TYPE, MSG) \
Johannes Doerfert169af992019-08-20 06:09:56 +000078 { \
79 STATS_DECL(NAME, TYPE, MSG) \
80 STATS_TRACK(NAME, TYPE) \
81 }
Johannes Doerfert17b578b2019-08-14 21:46:25 +000082#define STATS_DECLTRACK_ARG_ATTR(NAME) \
83 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
84#define STATS_DECLTRACK_CSARG_ATTR(NAME) \
85 STATS_DECLTRACK(NAME, CSArguments, \
86 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
87#define STATS_DECLTRACK_FN_ATTR(NAME) \
88 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
89#define STATS_DECLTRACK_CS_ATTR(NAME) \
90 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
91#define STATS_DECLTRACK_FNRET_ATTR(NAME) \
92 STATS_DECLTRACK(NAME, FunctionReturn, \
Johannes Doerfert2db85282019-08-21 20:56:56 +000093 BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
Johannes Doerfert17b578b2019-08-14 21:46:25 +000094#define STATS_DECLTRACK_CSRET_ATTR(NAME) \
95 STATS_DECLTRACK(NAME, CSReturn, \
96 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
97#define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
98 STATS_DECLTRACK(NAME, Floating, \
99 ("Number of floating values known to be '" #NAME "'"))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000100
Johannes Doerfertaade7822019-06-05 03:02:24 +0000101// TODO: Determine a good default value.
102//
103// In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads
104// (when run with the first 5 abstract attributes). The results also indicate
105// that we never reach 32 iterations but always find a fixpoint sooner.
106//
107// This will become more evolved once we perform two interleaved fixpoint
108// iterations: bottom-up and top-down.
109static cl::opt<unsigned>
110 MaxFixpointIterations("attributor-max-iterations", cl::Hidden,
111 cl::desc("Maximal number of fixpoint iterations."),
112 cl::init(32));
Johannes Doerfertb504eb82019-08-26 18:55:47 +0000113static cl::opt<bool> VerifyMaxFixpointIterations(
114 "attributor-max-iterations-verify", cl::Hidden,
115 cl::desc("Verify that max-iterations is a tight bound for a fixpoint"),
116 cl::init(false));
Johannes Doerfertaade7822019-06-05 03:02:24 +0000117
118static cl::opt<bool> DisableAttributor(
119 "attributor-disable", cl::Hidden,
120 cl::desc("Disable the attributor inter-procedural deduction pass."),
Johannes Doerfert282d34e2019-06-14 14:53:41 +0000121 cl::init(true));
Johannes Doerfertaade7822019-06-05 03:02:24 +0000122
Johannes Doerfert7516a5e2019-09-03 20:37:24 +0000123static cl::opt<bool> ManifestInternal(
124 "attributor-manifest-internal", cl::Hidden,
125 cl::desc("Manifest Attributor internal string attributes."),
126 cl::init(false));
127
Johannes Doerfertaade7822019-06-05 03:02:24 +0000128static cl::opt<bool> VerifyAttributor(
129 "attributor-verify", cl::Hidden,
130 cl::desc("Verify the Attributor deduction and "
131 "manifestation of attributes -- may issue false-positive errors"),
132 cl::init(false));
133
Johannes Doerfertf7ca0fe2019-08-28 16:58:52 +0000134static cl::opt<unsigned> DepRecInterval(
135 "attributor-dependence-recompute-interval", cl::Hidden,
136 cl::desc("Number of iterations until dependences are recomputed."),
137 cl::init(4));
138
Stefan Stipanovic431141c2019-09-15 21:47:41 +0000139static cl::opt<bool> EnableHeapToStack("enable-heap-to-stack-conversion",
140 cl::init(true), cl::Hidden);
141
142static cl::opt<int> MaxHeapToStackSize("max-heap-to-stack-size",
143 cl::init(128), cl::Hidden);
144
Johannes Doerfertaade7822019-06-05 03:02:24 +0000145/// Logic operators for the change status enum class.
146///
147///{
148ChangeStatus llvm::operator|(ChangeStatus l, ChangeStatus r) {
149 return l == ChangeStatus::CHANGED ? l : r;
150}
151ChangeStatus llvm::operator&(ChangeStatus l, ChangeStatus r) {
152 return l == ChangeStatus::UNCHANGED ? l : r;
153}
154///}
155
Johannes Doerfertdef99282019-08-14 21:29:37 +0000156/// Recursively visit all values that might become \p IRP at some point. This
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000157/// will be done by looking through cast instructions, selects, phis, and calls
Johannes Doerfertdef99282019-08-14 21:29:37 +0000158/// with the "returned" attribute. Once we cannot look through the value any
159/// further, the callback \p VisitValueCB is invoked and passed the current
160/// value, the \p State, and a flag to indicate if we stripped anything. To
161/// limit how much effort is invested, we will never visit more values than
162/// specified by \p MaxValues.
163template <typename AAType, typename StateTy>
Benjamin Kramerdf4b9a32019-09-17 12:56:29 +0000164static bool genericValueTraversal(
Johannes Doerfertdef99282019-08-14 21:29:37 +0000165 Attributor &A, IRPosition IRP, const AAType &QueryingAA, StateTy &State,
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000166 const function_ref<bool(Value &, StateTy &, bool)> &VisitValueCB,
Johannes Doerfertdef99282019-08-14 21:29:37 +0000167 int MaxValues = 8) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000168
Johannes Doerfertdef99282019-08-14 21:29:37 +0000169 const AAIsDead *LivenessAA = nullptr;
170 if (IRP.getAnchorScope())
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000171 LivenessAA = &A.getAAFor<AAIsDead>(
Johannes Doerfert19b00432019-08-26 17:48:05 +0000172 QueryingAA, IRPosition::function(*IRP.getAnchorScope()),
173 /* TrackDependence */ false);
174 bool AnyDead = false;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000175
176 // TODO: Use Positions here to allow context sensitivity in VisitValueCB
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000177 SmallPtrSet<Value *, 16> Visited;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000178 SmallVector<Value *, 16> Worklist;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000179 Worklist.push_back(&IRP.getAssociatedValue());
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000180
181 int Iteration = 0;
182 do {
183 Value *V = Worklist.pop_back_val();
184
185 // Check if we should process the current value. To prevent endless
186 // recursion keep a record of the values we followed!
Johannes Doerfertdef99282019-08-14 21:29:37 +0000187 if (!Visited.insert(V).second)
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000188 continue;
189
190 // Make sure we limit the compile time for complex expressions.
191 if (Iteration++ >= MaxValues)
192 return false;
193
194 // Explicitly look through calls with a "returned" attribute if we do
195 // not have a pointer as stripPointerCasts only works on them.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000196 Value *NewV = nullptr;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000197 if (V->getType()->isPointerTy()) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000198 NewV = V->stripPointerCasts();
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000199 } else {
200 CallSite CS(V);
201 if (CS && CS.getCalledFunction()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000202 for (Argument &Arg : CS.getCalledFunction()->args())
203 if (Arg.hasReturnedAttr()) {
204 NewV = CS.getArgOperand(Arg.getArgNo());
205 break;
206 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000207 }
208 }
Johannes Doerfertdef99282019-08-14 21:29:37 +0000209 if (NewV && NewV != V) {
210 Worklist.push_back(NewV);
211 continue;
212 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000213
214 // Look through select instructions, visit both potential values.
215 if (auto *SI = dyn_cast<SelectInst>(V)) {
216 Worklist.push_back(SI->getTrueValue());
217 Worklist.push_back(SI->getFalseValue());
218 continue;
219 }
220
Johannes Doerfertdef99282019-08-14 21:29:37 +0000221 // Look through phi nodes, visit all live operands.
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000222 if (auto *PHI = dyn_cast<PHINode>(V)) {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000223 assert(LivenessAA &&
224 "Expected liveness in the presence of instructions!");
Johannes Doerfertdef99282019-08-14 21:29:37 +0000225 for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
226 const BasicBlock *IncomingBB = PHI->getIncomingBlock(u);
Johannes Doerfert19b00432019-08-26 17:48:05 +0000227 if (LivenessAA->isAssumedDead(IncomingBB->getTerminator())) {
Hideto Uenof2b9dc42019-09-07 07:03:05 +0000228 AnyDead = true;
Johannes Doerfert19b00432019-08-26 17:48:05 +0000229 continue;
230 }
231 Worklist.push_back(PHI->getIncomingValue(u));
Johannes Doerfertdef99282019-08-14 21:29:37 +0000232 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000233 continue;
234 }
235
236 // Once a leaf is reached we inform the user through the callback.
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000237 if (!VisitValueCB(*V, State, Iteration > 1))
238 return false;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000239 } while (!Worklist.empty());
240
Johannes Doerfert19b00432019-08-26 17:48:05 +0000241 // If we actually used liveness information so we have to record a dependence.
242 if (AnyDead)
243 A.recordDependence(*LivenessAA, QueryingAA);
244
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000245 // All values have been visited.
246 return true;
247}
248
Johannes Doerfertaade7822019-06-05 03:02:24 +0000249/// Return true if \p New is equal or worse than \p Old.
250static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) {
251 if (!Old.isIntAttribute())
252 return true;
253
254 return Old.getValueAsInt() >= New.getValueAsInt();
255}
256
257/// Return true if the information provided by \p Attr was added to the
258/// attribute list \p Attrs. This is only the case if it was not already present
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000259/// in \p Attrs at the position describe by \p PK and \p AttrIdx.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000260static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000261 AttributeList &Attrs, int AttrIdx) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000262
263 if (Attr.isEnumAttribute()) {
264 Attribute::AttrKind Kind = Attr.getKindAsEnum();
265 if (Attrs.hasAttribute(AttrIdx, Kind))
266 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
267 return false;
268 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
269 return true;
270 }
271 if (Attr.isStringAttribute()) {
272 StringRef Kind = Attr.getKindAsString();
273 if (Attrs.hasAttribute(AttrIdx, Kind))
274 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
275 return false;
276 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
277 return true;
278 }
Hideto Ueno19c07af2019-07-23 08:16:17 +0000279 if (Attr.isIntAttribute()) {
280 Attribute::AttrKind Kind = Attr.getKindAsEnum();
281 if (Attrs.hasAttribute(AttrIdx, Kind))
282 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
283 return false;
284 Attrs = Attrs.removeAttribute(Ctx, AttrIdx, Kind);
285 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
286 return true;
287 }
Johannes Doerfertaade7822019-06-05 03:02:24 +0000288
289 llvm_unreachable("Expected enum or string attribute!");
290}
291
Johannes Doerfertece81902019-08-12 22:05:53 +0000292ChangeStatus AbstractAttribute::update(Attributor &A) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000293 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
294 if (getState().isAtFixpoint())
295 return HasChanged;
296
297 LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");
298
Johannes Doerfertece81902019-08-12 22:05:53 +0000299 HasChanged = updateImpl(A);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000300
301 LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
302 << "\n");
303
304 return HasChanged;
305}
306
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000307ChangeStatus
308IRAttributeManifest::manifestAttrs(Attributor &A, IRPosition &IRP,
309 const ArrayRef<Attribute> &DeducedAttrs) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000310 Function *ScopeFn = IRP.getAssociatedFunction();
Kristina Brooks26e60f02019-08-06 19:53:19 +0000311 IRPosition::Kind PK = IRP.getPositionKind();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000312
Johannes Doerfertaade7822019-06-05 03:02:24 +0000313 // In the following some generic code that will manifest attributes in
314 // DeducedAttrs if they improve the current IR. Due to the different
315 // annotation positions we use the underlying AttributeList interface.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000316
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000317 AttributeList Attrs;
318 switch (PK) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000319 case IRPosition::IRP_INVALID:
320 case IRPosition::IRP_FLOAT:
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000321 return ChangeStatus::UNCHANGED;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000322 case IRPosition::IRP_ARGUMENT:
323 case IRPosition::IRP_FUNCTION:
324 case IRPosition::IRP_RETURNED:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000325 Attrs = ScopeFn->getAttributes();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000326 break;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000327 case IRPosition::IRP_CALL_SITE:
328 case IRPosition::IRP_CALL_SITE_RETURNED:
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000329 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000330 Attrs = ImmutableCallSite(&IRP.getAnchorValue()).getAttributes();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000331 break;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000332 }
333
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000334 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000335 LLVMContext &Ctx = IRP.getAnchorValue().getContext();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000336 for (const Attribute &Attr : DeducedAttrs) {
Kristina Brooks26e60f02019-08-06 19:53:19 +0000337 if (!addIfNotExistent(Ctx, Attr, Attrs, IRP.getAttrIdx()))
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000338 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000339
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000340 HasChanged = ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000341 }
342
343 if (HasChanged == ChangeStatus::UNCHANGED)
344 return HasChanged;
345
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000346 switch (PK) {
347 case IRPosition::IRP_ARGUMENT:
348 case IRPosition::IRP_FUNCTION:
349 case IRPosition::IRP_RETURNED:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000350 ScopeFn->setAttributes(Attrs);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000351 break;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000352 case IRPosition::IRP_CALL_SITE:
353 case IRPosition::IRP_CALL_SITE_RETURNED:
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000354 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000355 CallSite(&IRP.getAnchorValue()).setAttributes(Attrs);
Johannes Doerfert4395b312019-08-14 21:46:28 +0000356 break;
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000357 case IRPosition::IRP_INVALID:
Johannes Doerfert4395b312019-08-14 21:46:28 +0000358 case IRPosition::IRP_FLOAT:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000359 break;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000360 }
361
362 return HasChanged;
363}
364
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000365const IRPosition IRPosition::EmptyKey(255);
366const IRPosition IRPosition::TombstoneKey(256);
367
368SubsumingPositionIterator::SubsumingPositionIterator(const IRPosition &IRP) {
369 IRPositions.emplace_back(IRP);
370
371 ImmutableCallSite ICS(&IRP.getAnchorValue());
372 switch (IRP.getPositionKind()) {
373 case IRPosition::IRP_INVALID:
374 case IRPosition::IRP_FLOAT:
375 case IRPosition::IRP_FUNCTION:
376 return;
377 case IRPosition::IRP_ARGUMENT:
378 case IRPosition::IRP_RETURNED:
379 IRPositions.emplace_back(
380 IRPosition::function(*IRP.getAssociatedFunction()));
381 return;
382 case IRPosition::IRP_CALL_SITE:
383 assert(ICS && "Expected call site!");
384 // TODO: We need to look at the operand bundles similar to the redirection
385 // in CallBase.
386 if (!ICS.hasOperandBundles())
387 if (const Function *Callee = ICS.getCalledFunction())
388 IRPositions.emplace_back(IRPosition::function(*Callee));
389 return;
390 case IRPosition::IRP_CALL_SITE_RETURNED:
391 assert(ICS && "Expected call site!");
392 // TODO: We need to look at the operand bundles similar to the redirection
393 // in CallBase.
394 if (!ICS.hasOperandBundles()) {
395 if (const Function *Callee = ICS.getCalledFunction()) {
396 IRPositions.emplace_back(IRPosition::returned(*Callee));
397 IRPositions.emplace_back(IRPosition::function(*Callee));
398 }
399 }
400 IRPositions.emplace_back(
401 IRPosition::callsite_function(cast<CallBase>(*ICS.getInstruction())));
402 return;
403 case IRPosition::IRP_CALL_SITE_ARGUMENT: {
404 int ArgNo = IRP.getArgNo();
405 assert(ICS && ArgNo >= 0 && "Expected call site!");
406 // TODO: We need to look at the operand bundles similar to the redirection
407 // in CallBase.
408 if (!ICS.hasOperandBundles()) {
409 const Function *Callee = ICS.getCalledFunction();
410 if (Callee && Callee->arg_size() > unsigned(ArgNo))
411 IRPositions.emplace_back(IRPosition::argument(*Callee->getArg(ArgNo)));
412 if (Callee)
413 IRPositions.emplace_back(IRPosition::function(*Callee));
414 }
415 IRPositions.emplace_back(IRPosition::value(IRP.getAssociatedValue()));
416 return;
417 }
418 }
419}
420
421bool IRPosition::hasAttr(ArrayRef<Attribute::AttrKind> AKs) const {
422 for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this))
423 for (Attribute::AttrKind AK : AKs)
424 if (EquivIRP.getAttr(AK).getKindAsEnum() == AK)
425 return true;
426 return false;
427}
428
429void IRPosition::getAttrs(ArrayRef<Attribute::AttrKind> AKs,
430 SmallVectorImpl<Attribute> &Attrs) const {
431 for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this))
432 for (Attribute::AttrKind AK : AKs) {
433 const Attribute &Attr = EquivIRP.getAttr(AK);
434 if (Attr.getKindAsEnum() == AK)
435 Attrs.push_back(Attr);
436 }
437}
438
439void IRPosition::verify() {
440 switch (KindOrArgNo) {
441 default:
442 assert(KindOrArgNo >= 0 && "Expected argument or call site argument!");
443 assert((isa<CallBase>(AnchorVal) || isa<Argument>(AnchorVal)) &&
444 "Expected call base or argument for positive attribute index!");
Simon Pilgrim920b0402019-08-29 10:08:45 +0000445 if (isa<Argument>(AnchorVal)) {
446 assert(cast<Argument>(AnchorVal)->getArgNo() == unsigned(getArgNo()) &&
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000447 "Argument number mismatch!");
Simon Pilgrim920b0402019-08-29 10:08:45 +0000448 assert(cast<Argument>(AnchorVal) == &getAssociatedValue() &&
449 "Associated value mismatch!");
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000450 } else {
Simon Pilgrim920b0402019-08-29 10:08:45 +0000451 assert(cast<CallBase>(*AnchorVal).arg_size() > unsigned(getArgNo()) &&
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000452 "Call site argument number mismatch!");
Simon Pilgrim920b0402019-08-29 10:08:45 +0000453 assert(cast<CallBase>(*AnchorVal).getArgOperand(getArgNo()) ==
454 &getAssociatedValue() &&
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000455 "Associated value mismatch!");
456 }
457 break;
458 case IRP_INVALID:
459 assert(!AnchorVal && "Expected no value for an invalid position!");
460 break;
461 case IRP_FLOAT:
462 assert((!isa<CallBase>(&getAssociatedValue()) &&
463 !isa<Argument>(&getAssociatedValue())) &&
464 "Expected specialized kind for call base and argument values!");
465 break;
466 case IRP_RETURNED:
467 assert(isa<Function>(AnchorVal) &&
468 "Expected function for a 'returned' position!");
469 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
470 break;
471 case IRP_CALL_SITE_RETURNED:
472 assert((isa<CallBase>(AnchorVal)) &&
473 "Expected call base for 'call site returned' position!");
474 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
475 break;
476 case IRP_CALL_SITE:
477 assert((isa<CallBase>(AnchorVal)) &&
478 "Expected call base for 'call site function' position!");
479 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
480 break;
481 case IRP_FUNCTION:
482 assert(isa<Function>(AnchorVal) &&
483 "Expected function for a 'function' position!");
484 assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!");
485 break;
486 }
487}
488
Benjamin Kramerdf4b9a32019-09-17 12:56:29 +0000489namespace {
Johannes Doerfert234eda52019-08-16 19:51:23 +0000490/// Helper functions to clamp a state \p S of type \p StateType with the
491/// information in \p R and indicate/return if \p S did change (as-in update is
492/// required to be run again).
493///
494///{
495template <typename StateType>
496ChangeStatus clampStateAndIndicateChange(StateType &S, const StateType &R);
497
498template <>
499ChangeStatus clampStateAndIndicateChange<IntegerState>(IntegerState &S,
500 const IntegerState &R) {
501 auto Assumed = S.getAssumed();
502 S ^= R;
503 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
504 : ChangeStatus::CHANGED;
505}
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000506
507template <>
508ChangeStatus clampStateAndIndicateChange<BooleanState>(BooleanState &S,
509 const BooleanState &R) {
510 return clampStateAndIndicateChange<IntegerState>(S, R);
511}
Johannes Doerfert234eda52019-08-16 19:51:23 +0000512///}
513
514/// Clamp the information known for all returned values of a function
515/// (identified by \p QueryingAA) into \p S.
516template <typename AAType, typename StateType = typename AAType::StateType>
517static void clampReturnedValueStates(Attributor &A, const AAType &QueryingAA,
518 StateType &S) {
519 LLVM_DEBUG(dbgs() << "[Attributor] Clamp return value states for "
520 << static_cast<const AbstractAttribute &>(QueryingAA)
521 << " into " << S << "\n");
522
523 assert((QueryingAA.getIRPosition().getPositionKind() ==
524 IRPosition::IRP_RETURNED ||
525 QueryingAA.getIRPosition().getPositionKind() ==
526 IRPosition::IRP_CALL_SITE_RETURNED) &&
527 "Can only clamp returned value states for a function returned or call "
528 "site returned position!");
529
530 // Use an optional state as there might not be any return values and we want
531 // to join (IntegerState::operator&) the state of all there are.
532 Optional<StateType> T;
533
534 // Callback for each possibly returned value.
535 auto CheckReturnValue = [&](Value &RV) -> bool {
536 const IRPosition &RVPos = IRPosition::value(RV);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000537 const AAType &AA = A.getAAFor<AAType>(QueryingAA, RVPos);
538 LLVM_DEBUG(dbgs() << "[Attributor] RV: " << RV << " AA: " << AA.getAsStr()
539 << " @ " << RVPos << "\n");
540 const StateType &AAS = static_cast<const StateType &>(AA.getState());
Johannes Doerfert234eda52019-08-16 19:51:23 +0000541 if (T.hasValue())
542 *T &= AAS;
543 else
544 T = AAS;
545 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " RV State: " << T
546 << "\n");
547 return T->isValidState();
548 };
549
550 if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA))
551 S.indicatePessimisticFixpoint();
552 else if (T.hasValue())
553 S ^= *T;
554}
555
556/// Helper class for generic deduction: return value -> returned position.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000557template <typename AAType, typename Base,
558 typename StateType = typename AAType::StateType>
559struct AAReturnedFromReturnedValues : public Base {
560 AAReturnedFromReturnedValues(const IRPosition &IRP) : Base(IRP) {}
Johannes Doerfert234eda52019-08-16 19:51:23 +0000561
562 /// See AbstractAttribute::updateImpl(...).
563 ChangeStatus updateImpl(Attributor &A) override {
564 StateType S;
565 clampReturnedValueStates<AAType, StateType>(A, *this, S);
Johannes Doerfert028b2aa2019-08-20 05:57:01 +0000566 // TODO: If we know we visited all returned values, thus no are assumed
567 // dead, we can take the known information from the state T.
Johannes Doerfert234eda52019-08-16 19:51:23 +0000568 return clampStateAndIndicateChange<StateType>(this->getState(), S);
569 }
570};
571
572/// Clamp the information known at all call sites for a given argument
573/// (identified by \p QueryingAA) into \p S.
574template <typename AAType, typename StateType = typename AAType::StateType>
575static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
576 StateType &S) {
577 LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for "
578 << static_cast<const AbstractAttribute &>(QueryingAA)
579 << " into " << S << "\n");
580
581 assert(QueryingAA.getIRPosition().getPositionKind() ==
582 IRPosition::IRP_ARGUMENT &&
583 "Can only clamp call site argument states for an argument position!");
584
585 // Use an optional state as there might not be any return values and we want
586 // to join (IntegerState::operator&) the state of all there are.
587 Optional<StateType> T;
588
589 // The argument number which is also the call site argument number.
590 unsigned ArgNo = QueryingAA.getIRPosition().getArgNo();
591
592 auto CallSiteCheck = [&](CallSite CS) {
593 const IRPosition &CSArgPos = IRPosition::callsite_argument(CS, ArgNo);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000594 const AAType &AA = A.getAAFor<AAType>(QueryingAA, CSArgPos);
Johannes Doerfert234eda52019-08-16 19:51:23 +0000595 LLVM_DEBUG(dbgs() << "[Attributor] CS: " << *CS.getInstruction()
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000596 << " AA: " << AA.getAsStr() << " @" << CSArgPos << "\n");
597 const StateType &AAS = static_cast<const StateType &>(AA.getState());
Johannes Doerfert234eda52019-08-16 19:51:23 +0000598 if (T.hasValue())
599 *T &= AAS;
600 else
601 T = AAS;
602 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " CSA State: " << T
603 << "\n");
604 return T->isValidState();
605 };
606
607 if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true))
608 S.indicatePessimisticFixpoint();
609 else if (T.hasValue())
610 S ^= *T;
611}
612
613/// Helper class for generic deduction: call site argument -> argument position.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000614template <typename AAType, typename Base,
615 typename StateType = typename AAType::StateType>
616struct AAArgumentFromCallSiteArguments : public Base {
617 AAArgumentFromCallSiteArguments(const IRPosition &IRP) : Base(IRP) {}
Johannes Doerfert234eda52019-08-16 19:51:23 +0000618
619 /// See AbstractAttribute::updateImpl(...).
620 ChangeStatus updateImpl(Attributor &A) override {
621 StateType S;
622 clampCallSiteArgumentStates<AAType, StateType>(A, *this, S);
Johannes Doerfert028b2aa2019-08-20 05:57:01 +0000623 // TODO: If we know we visited all incoming values, thus no are assumed
624 // dead, we can take the known information from the state T.
Johannes Doerfert234eda52019-08-16 19:51:23 +0000625 return clampStateAndIndicateChange<StateType>(this->getState(), S);
626 }
627};
628
629/// Helper class for generic replication: function returned -> cs returned.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000630template <typename AAType, typename Base>
631struct AACallSiteReturnedFromReturned : public Base {
632 AACallSiteReturnedFromReturned(const IRPosition &IRP) : Base(IRP) {}
Johannes Doerfert234eda52019-08-16 19:51:23 +0000633
634 /// See AbstractAttribute::updateImpl(...).
635 ChangeStatus updateImpl(Attributor &A) override {
636 assert(this->getIRPosition().getPositionKind() ==
637 IRPosition::IRP_CALL_SITE_RETURNED &&
638 "Can only wrap function returned positions for call site returned "
639 "positions!");
640 auto &S = this->getState();
641
642 const Function *AssociatedFunction =
643 this->getIRPosition().getAssociatedFunction();
644 if (!AssociatedFunction)
645 return S.indicatePessimisticFixpoint();
646
647 IRPosition FnPos = IRPosition::returned(*AssociatedFunction);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000648 const AAType &AA = A.getAAFor<AAType>(*this, FnPos);
Johannes Doerfert234eda52019-08-16 19:51:23 +0000649 return clampStateAndIndicateChange(
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000650 S, static_cast<const typename AAType::StateType &>(AA.getState()));
Johannes Doerfert234eda52019-08-16 19:51:23 +0000651 }
652};
653
Stefan Stipanovic53605892019-06-27 11:27:54 +0000654/// -----------------------NoUnwind Function Attribute--------------------------
655
Johannes Doerfert344d0382019-08-07 22:34:26 +0000656struct AANoUnwindImpl : AANoUnwind {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000657 AANoUnwindImpl(const IRPosition &IRP) : AANoUnwind(IRP) {}
Stefan Stipanovic53605892019-06-27 11:27:54 +0000658
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000659 const std::string getAsStr() const override {
Stefan Stipanovic53605892019-06-27 11:27:54 +0000660 return getAssumed() ? "nounwind" : "may-unwind";
661 }
662
663 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +0000664 ChangeStatus updateImpl(Attributor &A) override {
665 auto Opcodes = {
666 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
667 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
668 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
669
670 auto CheckForNoUnwind = [&](Instruction &I) {
671 if (!I.mayThrow())
672 return true;
673
Johannes Doerfert12cbbab2019-08-20 06:15:50 +0000674 if (ImmutableCallSite ICS = ImmutableCallSite(&I)) {
675 const auto &NoUnwindAA =
676 A.getAAFor<AANoUnwind>(*this, IRPosition::callsite_function(ICS));
677 return NoUnwindAA.isAssumedNoUnwind();
678 }
679 return false;
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +0000680 };
681
682 if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes))
683 return indicatePessimisticFixpoint();
684
685 return ChangeStatus::UNCHANGED;
686 }
Stefan Stipanovic53605892019-06-27 11:27:54 +0000687};
688
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000689struct AANoUnwindFunction final : public AANoUnwindImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000690 AANoUnwindFunction(const IRPosition &IRP) : AANoUnwindImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000691
692 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000693 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000694};
695
Johannes Doerfert66cf87e2019-08-16 19:49:00 +0000696/// NoUnwind attribute deduction for a call sites.
Johannes Doerfert3fac6682019-08-30 15:24:52 +0000697struct AANoUnwindCallSite final : AANoUnwindImpl {
698 AANoUnwindCallSite(const IRPosition &IRP) : AANoUnwindImpl(IRP) {}
699
700 /// See AbstractAttribute::initialize(...).
701 void initialize(Attributor &A) override {
702 AANoUnwindImpl::initialize(A);
703 Function *F = getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +0000704 if (!F)
Johannes Doerfert3fac6682019-08-30 15:24:52 +0000705 indicatePessimisticFixpoint();
706 }
707
708 /// See AbstractAttribute::updateImpl(...).
709 ChangeStatus updateImpl(Attributor &A) override {
710 // TODO: Once we have call site specific value information we can provide
711 // call site specific liveness information and then it makes
712 // sense to specialize attributes for call sites arguments instead of
713 // redirecting requests to the callee argument.
714 Function *F = getAssociatedFunction();
715 const IRPosition &FnPos = IRPosition::function(*F);
716 auto &FnAA = A.getAAFor<AANoUnwind>(*this, FnPos);
717 return clampStateAndIndicateChange(
718 getState(),
719 static_cast<const AANoUnwind::StateType &>(FnAA.getState()));
720 }
721
722 /// See AbstractAttribute::trackStatistics()
723 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nounwind); }
724};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +0000725
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000726/// --------------------- Function Return Values -------------------------------
727
728/// "Attribute" that collects all potential returned values and the return
729/// instructions that they arise from.
730///
731/// If there is a unique returned value R, the manifest method will:
732/// - mark R with the "returned" attribute, if R is an argument.
Johannes Doerferteccdf082019-08-05 23:35:12 +0000733class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000734
735 /// Mapping of values potentially returned by the associated function to the
736 /// return instructions that might return them.
Johannes Doerferta4a308c2019-08-26 17:51:23 +0000737 MapVector<Value *, SmallSetVector<ReturnInst *, 4>> ReturnedValues;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000738
Johannes Doerfertdeb9ea32019-08-23 15:42:19 +0000739 /// Mapping to remember the number of returned values for a call site such
740 /// that we can avoid updates if nothing changed.
741 DenseMap<const CallBase *, unsigned> NumReturnedValuesPerKnownAA;
742
743 /// Set of unresolved calls returned by the associated function.
Johannes Doerfert695089e2019-08-23 15:23:49 +0000744 SmallSetVector<CallBase *, 4> UnresolvedCalls;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000745
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000746 /// State flags
747 ///
748 ///{
Johannes Doerfertdeb9ea32019-08-23 15:42:19 +0000749 bool IsFixed = false;
750 bool IsValidState = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000751 ///}
752
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000753public:
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000754 AAReturnedValuesImpl(const IRPosition &IRP) : AAReturnedValues(IRP) {}
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000755
756 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +0000757 void initialize(Attributor &A) override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000758 // Reset the state.
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000759 IsFixed = false;
760 IsValidState = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000761 ReturnedValues.clear();
762
Johannes Doerfertdef99282019-08-14 21:29:37 +0000763 Function *F = getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +0000764 if (!F) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000765 indicatePessimisticFixpoint();
766 return;
767 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000768
769 // The map from instruction opcodes to those instructions in the function.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000770 auto &OpcodeInstMap = A.getInfoCache().getOpcodeInstMapForFunction(*F);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000771
772 // Look through all arguments, if one is marked as returned we are done.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000773 for (Argument &Arg : F->args()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000774 if (Arg.hasReturnedAttr()) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000775 auto &ReturnInstSet = ReturnedValues[&Arg];
776 for (Instruction *RI : OpcodeInstMap[Instruction::Ret])
777 ReturnInstSet.insert(cast<ReturnInst>(RI));
778
779 indicateOptimisticFixpoint();
780 return;
781 }
782 }
Johannes Doerfertb0412e42019-09-04 16:16:13 +0000783
784 if (!F->hasExactDefinition())
785 indicatePessimisticFixpoint();
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000786 }
787
788 /// See AbstractAttribute::manifest(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000789 ChangeStatus manifest(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000790
791 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000792 AbstractState &getState() override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000793
794 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000795 const AbstractState &getState() const override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000796
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000797 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +0000798 ChangeStatus updateImpl(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000799
Johannes Doerfertdef99282019-08-14 21:29:37 +0000800 llvm::iterator_range<iterator> returned_values() override {
801 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
802 }
803
804 llvm::iterator_range<const_iterator> returned_values() const override {
805 return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end());
806 }
807
Johannes Doerfert695089e2019-08-23 15:23:49 +0000808 const SmallSetVector<CallBase *, 4> &getUnresolvedCalls() const override {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000809 return UnresolvedCalls;
810 }
811
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000812 /// Return the number of potential return values, -1 if unknown.
Johannes Doerfertdef99282019-08-14 21:29:37 +0000813 size_t getNumReturnValues() const override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000814 return isValidState() ? ReturnedValues.size() : -1;
815 }
816
817 /// Return an assumed unique return value if a single candidate is found. If
818 /// there cannot be one, return a nullptr. If it is not clear yet, return the
819 /// Optional::NoneType.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000820 Optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000821
Johannes Doerfert14a04932019-08-07 22:27:24 +0000822 /// See AbstractState::checkForAllReturnedValues(...).
823 bool checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +0000824 const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)>
Johannes Doerfert14a04932019-08-07 22:27:24 +0000825 &Pred) const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000826
827 /// Pretty print the attribute similar to the IR representation.
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000828 const std::string getAsStr() const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000829
830 /// See AbstractState::isAtFixpoint().
831 bool isAtFixpoint() const override { return IsFixed; }
832
833 /// See AbstractState::isValidState().
834 bool isValidState() const override { return IsValidState; }
835
836 /// See AbstractState::indicateOptimisticFixpoint(...).
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000837 ChangeStatus indicateOptimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000838 IsFixed = true;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000839 return ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000840 }
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000841
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000842 ChangeStatus indicatePessimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000843 IsFixed = true;
844 IsValidState = false;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000845 return ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000846 }
847};
848
849ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) {
850 ChangeStatus Changed = ChangeStatus::UNCHANGED;
851
852 // Bookkeeping.
853 assert(isValidState());
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000854 STATS_DECLTRACK(KnownReturnValues, FunctionReturn,
855 "Number of function with known return values");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000856
857 // Check if we have an assumed unique return value that we could manifest.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000858 Optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000859
860 if (!UniqueRV.hasValue() || !UniqueRV.getValue())
861 return Changed;
862
863 // Bookkeeping.
Johannes Doerfert17b578b2019-08-14 21:46:25 +0000864 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
865 "Number of function with unique return");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000866
Johannes Doerfert23400e612019-08-23 17:41:37 +0000867 // Callback to replace the uses of CB with the constant C.
868 auto ReplaceCallSiteUsersWith = [](CallBase &CB, Constant &C) {
869 if (CB.getNumUses() == 0)
870 return ChangeStatus::UNCHANGED;
871 CB.replaceAllUsesWith(&C);
872 return ChangeStatus::CHANGED;
873 };
874
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000875 // If the assumed unique return value is an argument, annotate it.
876 if (auto *UniqueRVArg = dyn_cast<Argument>(UniqueRV.getValue())) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000877 getIRPosition() = IRPosition::argument(*UniqueRVArg);
Johannes Doerfert23400e612019-08-23 17:41:37 +0000878 Changed = IRAttribute::manifest(A);
879 } else if (auto *RVC = dyn_cast<Constant>(UniqueRV.getValue())) {
880 // We can replace the returned value with the unique returned constant.
881 Value &AnchorValue = getAnchorValue();
882 if (Function *F = dyn_cast<Function>(&AnchorValue)) {
883 for (const Use &U : F->uses())
884 if (CallBase *CB = dyn_cast<CallBase>(U.getUser()))
Johannes Doerferte7c6f972019-09-14 02:57:50 +0000885 if (CB->isCallee(&U)) {
886 Constant *RVCCast =
887 ConstantExpr::getTruncOrBitCast(RVC, CB->getType());
888 Changed = ReplaceCallSiteUsersWith(*CB, *RVCCast) | Changed;
889 }
Johannes Doerfert23400e612019-08-23 17:41:37 +0000890 } else {
891 assert(isa<CallBase>(AnchorValue) &&
892 "Expcected a function or call base anchor!");
Johannes Doerferte7c6f972019-09-14 02:57:50 +0000893 Constant *RVCCast =
894 ConstantExpr::getTruncOrBitCast(RVC, AnchorValue.getType());
895 Changed = ReplaceCallSiteUsersWith(cast<CallBase>(AnchorValue), *RVCCast);
Johannes Doerfert23400e612019-08-23 17:41:37 +0000896 }
897 if (Changed == ChangeStatus::CHANGED)
898 STATS_DECLTRACK(UniqueConstantReturnValue, FunctionReturn,
899 "Number of function returns replaced by constant return");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000900 }
901
902 return Changed;
903}
904
905const std::string AAReturnedValuesImpl::getAsStr() const {
906 return (isAtFixpoint() ? "returns(#" : "may-return(#") +
Johannes Doerfert6471bb62019-08-04 18:39:28 +0000907 (isValidState() ? std::to_string(getNumReturnValues()) : "?") +
Johannes Doerfertdef99282019-08-14 21:29:37 +0000908 ")[#UC: " + std::to_string(UnresolvedCalls.size()) + "]";
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000909}
910
Johannes Doerfert14a04932019-08-07 22:27:24 +0000911Optional<Value *>
912AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const {
913 // If checkForAllReturnedValues provides a unique value, ignoring potential
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000914 // undef values that can also be present, it is assumed to be the actual
915 // return value and forwarded to the caller of this method. If there are
916 // multiple, a nullptr is returned indicating there cannot be a unique
917 // returned value.
918 Optional<Value *> UniqueRV;
919
Johannes Doerfert14a04932019-08-07 22:27:24 +0000920 auto Pred = [&](Value &RV) -> bool {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000921 // If we found a second returned value and neither the current nor the saved
922 // one is an undef, there is no unique returned value. Undefs are special
923 // since we can pretend they have any value.
924 if (UniqueRV.hasValue() && UniqueRV != &RV &&
925 !(isa<UndefValue>(RV) || isa<UndefValue>(UniqueRV.getValue()))) {
926 UniqueRV = nullptr;
927 return false;
928 }
929
930 // Do not overwrite a value with an undef.
931 if (!UniqueRV.hasValue() || !isa<UndefValue>(RV))
932 UniqueRV = &RV;
933
934 return true;
935 };
936
Johannes Doerfert710ebb02019-08-14 21:18:01 +0000937 if (!A.checkForAllReturnedValues(Pred, *this))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000938 UniqueRV = nullptr;
939
940 return UniqueRV;
941}
942
Johannes Doerfert14a04932019-08-07 22:27:24 +0000943bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +0000944 const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)>
Johannes Doerfert14a04932019-08-07 22:27:24 +0000945 &Pred) const {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000946 if (!isValidState())
947 return false;
948
949 // Check all returned values but ignore call sites as long as we have not
950 // encountered an overdefined one during an update.
951 for (auto &It : ReturnedValues) {
952 Value *RV = It.first;
953
Johannes Doerfertdef99282019-08-14 21:29:37 +0000954 CallBase *CB = dyn_cast<CallBase>(RV);
955 if (CB && !UnresolvedCalls.count(CB))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000956 continue;
957
Johannes Doerfert695089e2019-08-23 15:23:49 +0000958 if (!Pred(*RV, It.second))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000959 return false;
960 }
961
962 return true;
963}
964
Johannes Doerfertece81902019-08-12 22:05:53 +0000965ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000966 size_t NumUnresolvedCalls = UnresolvedCalls.size();
967 bool Changed = false;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000968
Johannes Doerfertdef99282019-08-14 21:29:37 +0000969 // State used in the value traversals starting in returned values.
970 struct RVState {
971 // The map in which we collect return values -> return instrs.
972 decltype(ReturnedValues) &RetValsMap;
973 // The flag to indicate a change.
Johannes Doerfert056f1b52019-08-19 19:14:10 +0000974 bool &Changed;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000975 // The return instrs we come from.
Johannes Doerfert695089e2019-08-23 15:23:49 +0000976 SmallSetVector<ReturnInst *, 4> RetInsts;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000977 };
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000978
Johannes Doerfertdef99282019-08-14 21:29:37 +0000979 // Callback for a leaf value returned by the associated function.
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000980 auto VisitValueCB = [](Value &Val, RVState &RVS, bool) -> bool {
Johannes Doerfertdef99282019-08-14 21:29:37 +0000981 auto Size = RVS.RetValsMap[&Val].size();
982 RVS.RetValsMap[&Val].insert(RVS.RetInsts.begin(), RVS.RetInsts.end());
983 bool Inserted = RVS.RetValsMap[&Val].size() != Size;
984 RVS.Changed |= Inserted;
985 LLVM_DEBUG({
986 if (Inserted)
987 dbgs() << "[AAReturnedValues] 1 Add new returned value " << Val
988 << " => " << RVS.RetInsts.size() << "\n";
989 });
Johannes Doerfertb9b87912019-08-20 06:02:39 +0000990 return true;
Johannes Doerfertdef99282019-08-14 21:29:37 +0000991 };
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000992
Johannes Doerfertdef99282019-08-14 21:29:37 +0000993 // Helper method to invoke the generic value traversal.
994 auto VisitReturnedValue = [&](Value &RV, RVState &RVS) {
995 IRPosition RetValPos = IRPosition::value(RV);
996 return genericValueTraversal<AAReturnedValues, RVState>(A, RetValPos, *this,
997 RVS, VisitValueCB);
998 };
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000999
Johannes Doerfertdef99282019-08-14 21:29:37 +00001000 // Callback for all "return intructions" live in the associated function.
1001 auto CheckReturnInst = [this, &VisitReturnedValue, &Changed](Instruction &I) {
1002 ReturnInst &Ret = cast<ReturnInst>(I);
Johannes Doerfert056f1b52019-08-19 19:14:10 +00001003 RVState RVS({ReturnedValues, Changed, {}});
Johannes Doerfertdef99282019-08-14 21:29:37 +00001004 RVS.RetInsts.insert(&Ret);
Johannes Doerfertdef99282019-08-14 21:29:37 +00001005 return VisitReturnedValue(*Ret.getReturnValue(), RVS);
1006 };
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001007
Johannes Doerfertdef99282019-08-14 21:29:37 +00001008 // Start by discovering returned values from all live returned instructions in
1009 // the associated function.
1010 if (!A.checkForAllInstructions(CheckReturnInst, *this, {Instruction::Ret}))
1011 return indicatePessimisticFixpoint();
1012
1013 // Once returned values "directly" present in the code are handled we try to
1014 // resolve returned calls.
1015 decltype(ReturnedValues) NewRVsMap;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001016 for (auto &It : ReturnedValues) {
Johannes Doerfertdef99282019-08-14 21:29:37 +00001017 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned value: " << *It.first
1018 << " by #" << It.second.size() << " RIs\n");
1019 CallBase *CB = dyn_cast<CallBase>(It.first);
1020 if (!CB || UnresolvedCalls.count(CB))
1021 continue;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001022
Johannes Doerfert07a5c122019-08-28 14:09:14 +00001023 if (!CB->getCalledFunction()) {
1024 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Unresolved call: " << *CB
1025 << "\n");
1026 UnresolvedCalls.insert(CB);
1027 continue;
1028 }
1029
1030 // TODO: use the function scope once we have call site AAReturnedValues.
1031 const auto &RetValAA = A.getAAFor<AAReturnedValues>(
1032 *this, IRPosition::function(*CB->getCalledFunction()));
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001033 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Found another AAReturnedValues: "
1034 << static_cast<const AbstractAttribute &>(RetValAA)
1035 << "\n");
Johannes Doerfertdef99282019-08-14 21:29:37 +00001036
1037 // Skip dead ends, thus if we do not know anything about the returned
1038 // call we mark it as unresolved and it will stay that way.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001039 if (!RetValAA.getState().isValidState()) {
Johannes Doerfertdef99282019-08-14 21:29:37 +00001040 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Unresolved call: " << *CB
1041 << "\n");
1042 UnresolvedCalls.insert(CB);
1043 continue;
1044 }
1045
Johannes Doerfertde7674c2019-08-19 21:35:31 +00001046 // Do not try to learn partial information. If the callee has unresolved
1047 // return values we will treat the call as unresolved/opaque.
1048 auto &RetValAAUnresolvedCalls = RetValAA.getUnresolvedCalls();
1049 if (!RetValAAUnresolvedCalls.empty()) {
1050 UnresolvedCalls.insert(CB);
1051 continue;
1052 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001053
Johannes Doerfertde7674c2019-08-19 21:35:31 +00001054 // Now check if we can track transitively returned values. If possible, thus
1055 // if all return value can be represented in the current scope, do so.
1056 bool Unresolved = false;
1057 for (auto &RetValAAIt : RetValAA.returned_values()) {
1058 Value *RetVal = RetValAAIt.first;
1059 if (isa<Argument>(RetVal) || isa<CallBase>(RetVal) ||
1060 isa<Constant>(RetVal))
1061 continue;
1062 // Anything that did not fit in the above categories cannot be resolved,
1063 // mark the call as unresolved.
1064 LLVM_DEBUG(dbgs() << "[AAReturnedValues] transitively returned value "
1065 "cannot be translated: "
1066 << *RetVal << "\n");
1067 UnresolvedCalls.insert(CB);
1068 Unresolved = true;
1069 break;
1070 }
1071
1072 if (Unresolved)
1073 continue;
1074
Johannes Doerfertdeb9ea32019-08-23 15:42:19 +00001075 // Now track transitively returned values.
1076 unsigned &NumRetAA = NumReturnedValuesPerKnownAA[CB];
1077 if (NumRetAA == RetValAA.getNumReturnValues()) {
1078 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Skip call as it has not "
1079 "changed since it was seen last\n");
1080 continue;
1081 }
1082 NumRetAA = RetValAA.getNumReturnValues();
1083
Johannes Doerfertdef99282019-08-14 21:29:37 +00001084 for (auto &RetValAAIt : RetValAA.returned_values()) {
1085 Value *RetVal = RetValAAIt.first;
1086 if (Argument *Arg = dyn_cast<Argument>(RetVal)) {
1087 // Arguments are mapped to call site operands and we begin the traversal
1088 // again.
Johannes Doerfert056f1b52019-08-19 19:14:10 +00001089 bool Unused = false;
1090 RVState RVS({NewRVsMap, Unused, RetValAAIt.second});
Johannes Doerfertdef99282019-08-14 21:29:37 +00001091 VisitReturnedValue(*CB->getArgOperand(Arg->getArgNo()), RVS);
1092 continue;
1093 } else if (isa<CallBase>(RetVal)) {
1094 // Call sites are resolved by the callee attribute over time, no need to
1095 // do anything for us.
1096 continue;
1097 } else if (isa<Constant>(RetVal)) {
1098 // Constants are valid everywhere, we can simply take them.
1099 NewRVsMap[RetVal].insert(It.second.begin(), It.second.end());
1100 continue;
1101 }
Johannes Doerfert4361da22019-08-04 18:38:53 +00001102 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001103 }
1104
Johannes Doerfertdef99282019-08-14 21:29:37 +00001105 // To avoid modifications to the ReturnedValues map while we iterate over it
1106 // we kept record of potential new entries in a copy map, NewRVsMap.
1107 for (auto &It : NewRVsMap) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001108 assert(!It.second.empty() && "Entry does not add anything.");
1109 auto &ReturnInsts = ReturnedValues[It.first];
1110 for (ReturnInst *RI : It.second)
Johannes Doerfert695089e2019-08-23 15:23:49 +00001111 if (ReturnInsts.insert(RI)) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001112 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Add new returned value "
1113 << *It.first << " => " << *RI << "\n");
Johannes Doerfertdef99282019-08-14 21:29:37 +00001114 Changed = true;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001115 }
1116 }
1117
Johannes Doerfertdef99282019-08-14 21:29:37 +00001118 Changed |= (NumUnresolvedCalls != UnresolvedCalls.size());
1119 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00001120}
1121
Johannes Doerfertdef99282019-08-14 21:29:37 +00001122struct AAReturnedValuesFunction final : public AAReturnedValuesImpl {
1123 AAReturnedValuesFunction(const IRPosition &IRP) : AAReturnedValuesImpl(IRP) {}
1124
1125 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001126 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(returned) }
Johannes Doerfertdef99282019-08-14 21:29:37 +00001127};
1128
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001129/// Returned values information for a call sites.
Johannes Doerfert07a5c122019-08-28 14:09:14 +00001130struct AAReturnedValuesCallSite final : AAReturnedValuesImpl {
1131 AAReturnedValuesCallSite(const IRPosition &IRP) : AAReturnedValuesImpl(IRP) {}
1132
1133 /// See AbstractAttribute::initialize(...).
1134 void initialize(Attributor &A) override {
1135 // TODO: Once we have call site specific value information we can provide
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001136 // call site specific liveness information and then it makes
Johannes Doerfert07a5c122019-08-28 14:09:14 +00001137 // sense to specialize attributes for call sites instead of
1138 // redirecting requests to the callee.
1139 llvm_unreachable("Abstract attributes for returned values are not "
1140 "supported for call sites yet!");
1141 }
1142
1143 /// See AbstractAttribute::updateImpl(...).
1144 ChangeStatus updateImpl(Attributor &A) override {
1145 return indicatePessimisticFixpoint();
1146 }
1147
1148 /// See AbstractAttribute::trackStatistics()
1149 void trackStatistics() const override {}
1150};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001151
Stefan Stipanovic06263672019-07-11 21:37:40 +00001152/// ------------------------ NoSync Function Attribute -------------------------
1153
Johannes Doerfert344d0382019-08-07 22:34:26 +00001154struct AANoSyncImpl : AANoSync {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001155 AANoSyncImpl(const IRPosition &IRP) : AANoSync(IRP) {}
Stefan Stipanovic06263672019-07-11 21:37:40 +00001156
Stefan Stipanoviccb5ecae2019-07-12 18:34:06 +00001157 const std::string getAsStr() const override {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001158 return getAssumed() ? "nosync" : "may-sync";
1159 }
1160
1161 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001162 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001163
Stefan Stipanovic06263672019-07-11 21:37:40 +00001164 /// Helper function used to determine whether an instruction is non-relaxed
1165 /// atomic. In other words, if an atomic instruction does not have unordered
1166 /// or monotonic ordering
1167 static bool isNonRelaxedAtomic(Instruction *I);
1168
1169 /// Helper function used to determine whether an instruction is volatile.
1170 static bool isVolatile(Instruction *I);
1171
Johannes Doerfertc7a1db32019-07-13 01:09:27 +00001172 /// Helper function uset to check if intrinsic is volatile (memcpy, memmove,
1173 /// memset).
Stefan Stipanovic06263672019-07-11 21:37:40 +00001174 static bool isNoSyncIntrinsic(Instruction *I);
1175};
1176
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001177bool AANoSyncImpl::isNonRelaxedAtomic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001178 if (!I->isAtomic())
1179 return false;
1180
1181 AtomicOrdering Ordering;
1182 switch (I->getOpcode()) {
1183 case Instruction::AtomicRMW:
1184 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
1185 break;
1186 case Instruction::Store:
1187 Ordering = cast<StoreInst>(I)->getOrdering();
1188 break;
1189 case Instruction::Load:
1190 Ordering = cast<LoadInst>(I)->getOrdering();
1191 break;
1192 case Instruction::Fence: {
1193 auto *FI = cast<FenceInst>(I);
1194 if (FI->getSyncScopeID() == SyncScope::SingleThread)
1195 return false;
1196 Ordering = FI->getOrdering();
1197 break;
1198 }
1199 case Instruction::AtomicCmpXchg: {
1200 AtomicOrdering Success = cast<AtomicCmpXchgInst>(I)->getSuccessOrdering();
1201 AtomicOrdering Failure = cast<AtomicCmpXchgInst>(I)->getFailureOrdering();
1202 // Only if both are relaxed, than it can be treated as relaxed.
1203 // Otherwise it is non-relaxed.
1204 if (Success != AtomicOrdering::Unordered &&
1205 Success != AtomicOrdering::Monotonic)
1206 return true;
1207 if (Failure != AtomicOrdering::Unordered &&
1208 Failure != AtomicOrdering::Monotonic)
1209 return true;
1210 return false;
1211 }
1212 default:
1213 llvm_unreachable(
1214 "New atomic operations need to be known in the attributor.");
1215 }
1216
1217 // Relaxed.
1218 if (Ordering == AtomicOrdering::Unordered ||
1219 Ordering == AtomicOrdering::Monotonic)
1220 return false;
1221 return true;
1222}
1223
1224/// Checks if an intrinsic is nosync. Currently only checks mem* intrinsics.
1225/// FIXME: We should ipmrove the handling of intrinsics.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001226bool AANoSyncImpl::isNoSyncIntrinsic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001227 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
1228 switch (II->getIntrinsicID()) {
1229 /// Element wise atomic memory intrinsics are can only be unordered,
1230 /// therefore nosync.
1231 case Intrinsic::memset_element_unordered_atomic:
1232 case Intrinsic::memmove_element_unordered_atomic:
1233 case Intrinsic::memcpy_element_unordered_atomic:
1234 return true;
1235 case Intrinsic::memset:
1236 case Intrinsic::memmove:
1237 case Intrinsic::memcpy:
1238 if (!cast<MemIntrinsic>(II)->isVolatile())
1239 return true;
1240 return false;
1241 default:
1242 return false;
1243 }
1244 }
1245 return false;
1246}
1247
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001248bool AANoSyncImpl::isVolatile(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001249 assert(!ImmutableCallSite(I) && !isa<CallBase>(I) &&
1250 "Calls should not be checked here");
1251
1252 switch (I->getOpcode()) {
1253 case Instruction::AtomicRMW:
1254 return cast<AtomicRMWInst>(I)->isVolatile();
1255 case Instruction::Store:
1256 return cast<StoreInst>(I)->isVolatile();
1257 case Instruction::Load:
1258 return cast<LoadInst>(I)->isVolatile();
1259 case Instruction::AtomicCmpXchg:
1260 return cast<AtomicCmpXchgInst>(I)->isVolatile();
1261 default:
1262 return false;
1263 }
1264}
1265
Johannes Doerfertece81902019-08-12 22:05:53 +00001266ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
Stefan Stipanovic06263672019-07-11 21:37:40 +00001267
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001268 auto CheckRWInstForNoSync = [&](Instruction &I) {
1269 /// We are looking for volatile instructions or Non-Relaxed atomics.
1270 /// FIXME: We should ipmrove the handling of intrinsics.
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001271
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001272 if (isa<IntrinsicInst>(&I) && isNoSyncIntrinsic(&I))
1273 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001274
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001275 if (ImmutableCallSite ICS = ImmutableCallSite(&I)) {
1276 if (ICS.hasFnAttr(Attribute::NoSync))
1277 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001278
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001279 const auto &NoSyncAA =
1280 A.getAAFor<AANoSync>(*this, IRPosition::callsite_function(ICS));
1281 if (NoSyncAA.isAssumedNoSync())
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001282 return true;
1283 return false;
1284 }
Stefan Stipanovic06263672019-07-11 21:37:40 +00001285
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001286 if (!isVolatile(&I) && !isNonRelaxedAtomic(&I))
1287 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001288
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001289 return false;
1290 };
Stefan Stipanovic06263672019-07-11 21:37:40 +00001291
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001292 auto CheckForNoSync = [&](Instruction &I) {
1293 // At this point we handled all read/write effects and they are all
1294 // nosync, so they can be skipped.
1295 if (I.mayReadOrWriteMemory())
1296 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +00001297
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001298 // non-convergent and readnone imply nosync.
1299 return !ImmutableCallSite(&I).isConvergent();
1300 };
Stefan Stipanovic06263672019-07-11 21:37:40 +00001301
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001302 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this) ||
1303 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this))
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001304 return indicatePessimisticFixpoint();
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00001305
Stefan Stipanovic06263672019-07-11 21:37:40 +00001306 return ChangeStatus::UNCHANGED;
1307}
1308
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001309struct AANoSyncFunction final : public AANoSyncImpl {
1310 AANoSyncFunction(const IRPosition &IRP) : AANoSyncImpl(IRP) {}
1311
1312 /// See AbstractAttribute::trackStatistics()
1313 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }
1314};
1315
1316/// NoSync attribute deduction for a call sites.
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001317struct AANoSyncCallSite final : AANoSyncImpl {
1318 AANoSyncCallSite(const IRPosition &IRP) : AANoSyncImpl(IRP) {}
1319
1320 /// See AbstractAttribute::initialize(...).
1321 void initialize(Attributor &A) override {
1322 AANoSyncImpl::initialize(A);
1323 Function *F = getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00001324 if (!F)
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001325 indicatePessimisticFixpoint();
1326 }
1327
1328 /// See AbstractAttribute::updateImpl(...).
1329 ChangeStatus updateImpl(Attributor &A) override {
1330 // TODO: Once we have call site specific value information we can provide
1331 // call site specific liveness information and then it makes
1332 // sense to specialize attributes for call sites arguments instead of
1333 // redirecting requests to the callee argument.
1334 Function *F = getAssociatedFunction();
1335 const IRPosition &FnPos = IRPosition::function(*F);
1336 auto &FnAA = A.getAAFor<AANoSync>(*this, FnPos);
1337 return clampStateAndIndicateChange(
1338 getState(), static_cast<const AANoSync::StateType &>(FnAA.getState()));
1339 }
1340
1341 /// See AbstractAttribute::trackStatistics()
1342 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nosync); }
1343};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001344
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001345/// ------------------------ No-Free Attributes ----------------------------
1346
Johannes Doerfert344d0382019-08-07 22:34:26 +00001347struct AANoFreeImpl : public AANoFree {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001348 AANoFreeImpl(const IRPosition &IRP) : AANoFree(IRP) {}
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001349
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001350 /// See AbstractAttribute::updateImpl(...).
1351 ChangeStatus updateImpl(Attributor &A) override {
1352 auto CheckForNoFree = [&](Instruction &I) {
1353 ImmutableCallSite ICS(&I);
1354 if (ICS.hasFnAttr(Attribute::NoFree))
1355 return true;
1356
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001357 const auto &NoFreeAA =
1358 A.getAAFor<AANoFree>(*this, IRPosition::callsite_function(ICS));
1359 return NoFreeAA.isAssumedNoFree();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001360 };
1361
1362 if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this))
1363 return indicatePessimisticFixpoint();
1364 return ChangeStatus::UNCHANGED;
1365 }
1366
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001367 /// See AbstractAttribute::getAsStr().
1368 const std::string getAsStr() const override {
1369 return getAssumed() ? "nofree" : "may-free";
1370 }
Hideto Ueno65bbaf92019-07-12 17:38:51 +00001371};
1372
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001373struct AANoFreeFunction final : public AANoFreeImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001374 AANoFreeFunction(const IRPosition &IRP) : AANoFreeImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001375
1376 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001377 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001378};
1379
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001380/// NoFree attribute deduction for a call sites.
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001381struct AANoFreeCallSite final : AANoFreeImpl {
1382 AANoFreeCallSite(const IRPosition &IRP) : AANoFreeImpl(IRP) {}
1383
1384 /// See AbstractAttribute::initialize(...).
1385 void initialize(Attributor &A) override {
1386 AANoFreeImpl::initialize(A);
1387 Function *F = getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00001388 if (!F)
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001389 indicatePessimisticFixpoint();
1390 }
1391
1392 /// See AbstractAttribute::updateImpl(...).
1393 ChangeStatus updateImpl(Attributor &A) override {
1394 // TODO: Once we have call site specific value information we can provide
1395 // call site specific liveness information and then it makes
1396 // sense to specialize attributes for call sites arguments instead of
1397 // redirecting requests to the callee argument.
1398 Function *F = getAssociatedFunction();
1399 const IRPosition &FnPos = IRPosition::function(*F);
1400 auto &FnAA = A.getAAFor<AANoFree>(*this, FnPos);
1401 return clampStateAndIndicateChange(
1402 getState(), static_cast<const AANoFree::StateType &>(FnAA.getState()));
1403 }
1404
1405 /// See AbstractAttribute::trackStatistics()
1406 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nofree); }
1407};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001408
Hideto Ueno54869ec2019-07-15 06:49:04 +00001409/// ------------------------ NonNull Argument Attribute ------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00001410struct AANonNullImpl : AANonNull {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001411 AANonNullImpl(const IRPosition &IRP) : AANonNull(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001412
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001413 /// See AbstractAttribute::initialize(...).
1414 void initialize(Attributor &A) override {
1415 if (hasAttr({Attribute::NonNull, Attribute::Dereferenceable}))
1416 indicateOptimisticFixpoint();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00001417 else
1418 AANonNull::initialize(A);
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001419 }
1420
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001421 /// See AbstractAttribute::getAsStr().
1422 const std::string getAsStr() const override {
1423 return getAssumed() ? "nonnull" : "may-null";
1424 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001425};
1426
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001427/// NonNull attribute for a floating value.
1428struct AANonNullFloating : AANonNullImpl {
1429 AANonNullFloating(const IRPosition &IRP) : AANonNullImpl(IRP) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001430
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001431 /// See AbstractAttribute::initialize(...).
1432 void initialize(Attributor &A) override {
1433 AANonNullImpl::initialize(A);
Hideto Ueno54869ec2019-07-15 06:49:04 +00001434
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001435 if (isAtFixpoint())
1436 return;
Hideto Ueno54869ec2019-07-15 06:49:04 +00001437
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001438 const IRPosition &IRP = getIRPosition();
1439 const Value &V = IRP.getAssociatedValue();
1440 const DataLayout &DL = A.getDataLayout();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001441
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001442 // TODO: This context sensitive query should be removed once we can do
1443 // context sensitive queries in the genericValueTraversal below.
1444 if (isKnownNonZero(&V, DL, 0, /* TODO: AC */ nullptr, IRP.getCtxI(),
1445 /* TODO: DT */ nullptr))
1446 indicateOptimisticFixpoint();
1447 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001448
1449 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001450 ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001451 const DataLayout &DL = A.getDataLayout();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001452
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001453 auto VisitValueCB = [&](Value &V, AAAlign::StateType &T,
1454 bool Stripped) -> bool {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001455 const auto &AA = A.getAAFor<AANonNull>(*this, IRPosition::value(V));
1456 if (!Stripped && this == &AA) {
1457 if (!isKnownNonZero(&V, DL, 0, /* TODO: AC */ nullptr,
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001458 /* TODO: CtxI */ nullptr,
1459 /* TODO: DT */ nullptr))
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001460 T.indicatePessimisticFixpoint();
1461 } else {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001462 // Use abstract attribute information.
1463 const AANonNull::StateType &NS =
1464 static_cast<const AANonNull::StateType &>(AA.getState());
1465 T ^= NS;
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001466 }
1467 return T.isValidState();
1468 };
1469
1470 StateType T;
1471 if (!genericValueTraversal<AANonNull, StateType>(A, getIRPosition(), *this,
1472 T, VisitValueCB))
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001473 return indicatePessimisticFixpoint();
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001474
1475 return clampStateAndIndicateChange(getState(), T);
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001476 }
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001477
1478 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001479 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001480};
1481
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001482/// NonNull attribute for function return value.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001483struct AANonNullReturned final
1484 : AAReturnedFromReturnedValues<AANonNull, AANonNullImpl> {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001485 AANonNullReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001486 : AAReturnedFromReturnedValues<AANonNull, AANonNullImpl>(IRP) {}
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001487
1488 /// See AbstractAttribute::trackStatistics()
1489 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
1490};
1491
Hideto Ueno54869ec2019-07-15 06:49:04 +00001492/// NonNull attribute for function argument.
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001493struct AANonNullArgument final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001494 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001495 AANonNullArgument(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001496 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001497
1498 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001499 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001500};
1501
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001502struct AANonNullCallSiteArgument final : AANonNullFloating {
1503 AANonNullCallSiteArgument(const IRPosition &IRP) : AANonNullFloating(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001504
1505 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert1aac1822019-08-29 01:26:09 +00001506 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001507};
Johannes Doerfert007153e2019-08-05 23:26:06 +00001508
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001509/// NonNull attribute for a call site return position.
1510struct AANonNullCallSiteReturned final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001511 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl> {
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001512 AANonNullCallSiteReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001513 : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl>(IRP) {}
Johannes Doerfertb9b87912019-08-20 06:02:39 +00001514
1515 /// See AbstractAttribute::trackStatistics()
1516 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull) }
1517};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001518
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001519/// ------------------------ No-Recurse Attributes ----------------------------
1520
1521struct AANoRecurseImpl : public AANoRecurse {
1522 AANoRecurseImpl(const IRPosition &IRP) : AANoRecurse(IRP) {}
1523
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001524 /// See AbstractAttribute::getAsStr()
1525 const std::string getAsStr() const override {
1526 return getAssumed() ? "norecurse" : "may-recurse";
1527 }
1528};
1529
1530struct AANoRecurseFunction final : AANoRecurseImpl {
1531 AANoRecurseFunction(const IRPosition &IRP) : AANoRecurseImpl(IRP) {}
1532
1533 /// See AbstractAttribute::updateImpl(...).
1534 ChangeStatus updateImpl(Attributor &A) override {
1535 // TODO: Implement this.
1536 return indicatePessimisticFixpoint();
1537 }
1538
1539 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
1540};
1541
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001542/// NoRecurse attribute deduction for a call sites.
1543struct AANoRecurseCallSite final : AANoRecurseImpl {
1544 AANoRecurseCallSite(const IRPosition &IRP) : AANoRecurseImpl(IRP) {}
1545
1546 /// See AbstractAttribute::initialize(...).
1547 void initialize(Attributor &A) override {
1548 AANoRecurseImpl::initialize(A);
1549 Function *F = getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00001550 if (!F)
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001551 indicatePessimisticFixpoint();
1552 }
1553
1554 /// See AbstractAttribute::updateImpl(...).
1555 ChangeStatus updateImpl(Attributor &A) override {
1556 // TODO: Once we have call site specific value information we can provide
1557 // call site specific liveness information and then it makes
1558 // sense to specialize attributes for call sites arguments instead of
1559 // redirecting requests to the callee argument.
1560 Function *F = getAssociatedFunction();
1561 const IRPosition &FnPos = IRPosition::function(*F);
1562 auto &FnAA = A.getAAFor<AANoRecurse>(*this, FnPos);
1563 return clampStateAndIndicateChange(
1564 getState(),
1565 static_cast<const AANoRecurse::StateType &>(FnAA.getState()));
1566 }
1567
1568 /// See AbstractAttribute::trackStatistics()
1569 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(norecurse); }
1570};
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001571
Hideto Ueno11d37102019-07-17 15:15:43 +00001572/// ------------------------ Will-Return Attributes ----------------------------
1573
Hideto Ueno11d37102019-07-17 15:15:43 +00001574// Helper function that checks whether a function has any cycle.
1575// TODO: Replace with more efficent code
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001576static bool containsCycle(Function &F) {
Hideto Ueno11d37102019-07-17 15:15:43 +00001577 SmallPtrSet<BasicBlock *, 32> Visited;
1578
1579 // Traverse BB by dfs and check whether successor is already visited.
1580 for (BasicBlock *BB : depth_first(&F)) {
1581 Visited.insert(BB);
1582 for (auto *SuccBB : successors(BB)) {
1583 if (Visited.count(SuccBB))
1584 return true;
1585 }
1586 }
1587 return false;
1588}
1589
1590// Helper function that checks the function have a loop which might become an
1591// endless loop
1592// FIXME: Any cycle is regarded as endless loop for now.
1593// We have to allow some patterns.
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001594static bool containsPossiblyEndlessLoop(Function *F) {
1595 return !F || !F->hasExactDefinition() || containsCycle(*F);
Hideto Ueno11d37102019-07-17 15:15:43 +00001596}
1597
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001598struct AAWillReturnImpl : public AAWillReturn {
1599 AAWillReturnImpl(const IRPosition &IRP) : AAWillReturn(IRP) {}
Hideto Ueno11d37102019-07-17 15:15:43 +00001600
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001601 /// See AbstractAttribute::initialize(...).
1602 void initialize(Attributor &A) override {
Johannes Doerfertb0412e42019-09-04 16:16:13 +00001603 AAWillReturn::initialize(A);
Hideto Ueno11d37102019-07-17 15:15:43 +00001604
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001605 Function *F = getAssociatedFunction();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001606 if (containsPossiblyEndlessLoop(F))
1607 indicatePessimisticFixpoint();
1608 }
Hideto Ueno11d37102019-07-17 15:15:43 +00001609
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001610 /// See AbstractAttribute::updateImpl(...).
1611 ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001612 auto CheckForWillReturn = [&](Instruction &I) {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001613 IRPosition IPos = IRPosition::callsite_function(ImmutableCallSite(&I));
1614 const auto &WillReturnAA = A.getAAFor<AAWillReturn>(*this, IPos);
1615 if (WillReturnAA.isKnownWillReturn())
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001616 return true;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001617 if (!WillReturnAA.isAssumedWillReturn())
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001618 return false;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001619 const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(*this, IPos);
1620 return NoRecurseAA.isAssumedNoRecurse();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001621 };
1622
1623 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this))
1624 return indicatePessimisticFixpoint();
1625
1626 return ChangeStatus::UNCHANGED;
1627 }
1628
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001629 /// See AbstractAttribute::getAsStr()
1630 const std::string getAsStr() const override {
1631 return getAssumed() ? "willreturn" : "may-noreturn";
1632 }
1633};
1634
1635struct AAWillReturnFunction final : AAWillReturnImpl {
1636 AAWillReturnFunction(const IRPosition &IRP) : AAWillReturnImpl(IRP) {}
1637
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001638 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001639 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) }
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001640};
Hideto Ueno11d37102019-07-17 15:15:43 +00001641
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001642/// WillReturn attribute deduction for a call sites.
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001643struct AAWillReturnCallSite final : AAWillReturnImpl {
1644 AAWillReturnCallSite(const IRPosition &IRP) : AAWillReturnImpl(IRP) {}
1645
1646 /// See AbstractAttribute::initialize(...).
1647 void initialize(Attributor &A) override {
1648 AAWillReturnImpl::initialize(A);
1649 Function *F = getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00001650 if (!F)
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001651 indicatePessimisticFixpoint();
1652 }
1653
1654 /// See AbstractAttribute::updateImpl(...).
1655 ChangeStatus updateImpl(Attributor &A) override {
1656 // TODO: Once we have call site specific value information we can provide
1657 // call site specific liveness information and then it makes
1658 // sense to specialize attributes for call sites arguments instead of
1659 // redirecting requests to the callee argument.
1660 Function *F = getAssociatedFunction();
1661 const IRPosition &FnPos = IRPosition::function(*F);
1662 auto &FnAA = A.getAAFor<AAWillReturn>(*this, FnPos);
1663 return clampStateAndIndicateChange(
1664 getState(),
1665 static_cast<const AAWillReturn::StateType &>(FnAA.getState()));
1666 }
1667
1668 /// See AbstractAttribute::trackStatistics()
1669 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(willreturn); }
1670};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001671
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001672/// ------------------------ NoAlias Argument Attribute ------------------------
1673
Johannes Doerfert344d0382019-08-07 22:34:26 +00001674struct AANoAliasImpl : AANoAlias {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001675 AANoAliasImpl(const IRPosition &IRP) : AANoAlias(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001676
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001677 const std::string getAsStr() const override {
1678 return getAssumed() ? "noalias" : "may-alias";
1679 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001680};
1681
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001682/// NoAlias attribute for a floating value.
1683struct AANoAliasFloating final : AANoAliasImpl {
1684 AANoAliasFloating(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
1685
Hideto Uenocbab3342019-08-29 05:52:00 +00001686 /// See AbstractAttribute::initialize(...).
1687 void initialize(Attributor &A) override {
Hideto Ueno1d68ed82019-09-11 07:00:33 +00001688 AANoAliasImpl::initialize(A);
1689 if (isa<AllocaInst>(getAnchorValue()))
1690 indicateOptimisticFixpoint();
Hideto Uenocbab3342019-08-29 05:52:00 +00001691 }
1692
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001693 /// See AbstractAttribute::updateImpl(...).
1694 ChangeStatus updateImpl(Attributor &A) override {
1695 // TODO: Implement this.
1696 return indicatePessimisticFixpoint();
1697 }
1698
1699 /// See AbstractAttribute::trackStatistics()
1700 void trackStatistics() const override {
1701 STATS_DECLTRACK_FLOATING_ATTR(noalias)
1702 }
1703};
1704
1705/// NoAlias attribute for an argument.
Hideto Uenocbab3342019-08-29 05:52:00 +00001706struct AANoAliasArgument final
1707 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
1708 AANoAliasArgument(const IRPosition &IRP)
1709 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>(IRP) {}
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001710
1711 /// See AbstractAttribute::trackStatistics()
1712 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
1713};
1714
1715struct AANoAliasCallSiteArgument final : AANoAliasImpl {
1716 AANoAliasCallSiteArgument(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
1717
Hideto Uenocbab3342019-08-29 05:52:00 +00001718 /// See AbstractAttribute::initialize(...).
1719 void initialize(Attributor &A) override {
Hideto Ueno6381b142019-08-30 10:00:32 +00001720 // See callsite argument attribute and callee argument attribute.
1721 ImmutableCallSite ICS(&getAnchorValue());
1722 if (ICS.paramHasAttr(getArgNo(), Attribute::NoAlias))
1723 indicateOptimisticFixpoint();
Hideto Uenocbab3342019-08-29 05:52:00 +00001724 }
1725
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001726 /// See AbstractAttribute::updateImpl(...).
1727 ChangeStatus updateImpl(Attributor &A) override {
Hideto Ueno1d68ed82019-09-11 07:00:33 +00001728 // We can deduce "noalias" if the following conditions hold.
1729 // (i) Associated value is assumed to be noalias in the definition.
1730 // (ii) Associated value is assumed to be no-capture in all the uses
1731 // possibly executed before this callsite.
1732 // (iii) There is no other pointer argument which could alias with the
1733 // value.
1734
1735 const Value &V = getAssociatedValue();
1736 const IRPosition IRP = IRPosition::value(V);
1737
1738 // (i) Check whether noalias holds in the definition.
1739
1740 auto &NoAliasAA = A.getAAFor<AANoAlias>(*this, IRP);
1741
1742 if (!NoAliasAA.isAssumedNoAlias())
1743 return indicatePessimisticFixpoint();
1744
1745 LLVM_DEBUG(dbgs() << "[Attributor][AANoAliasCSArg] " << V
1746 << " is assumed NoAlias in the definition\n");
1747
1748 // (ii) Check whether the value is captured in the scope using AANoCapture.
1749 // FIXME: This is conservative though, it is better to look at CFG and
1750 // check only uses possibly executed before this callsite.
1751
1752 auto &NoCaptureAA = A.getAAFor<AANoCapture>(*this, IRP);
1753 if (!NoCaptureAA.isAssumedNoCaptureMaybeReturned())
1754 return indicatePessimisticFixpoint();
1755
1756 // (iii) Check there is no other pointer argument which could alias with the
1757 // value.
1758 ImmutableCallSite ICS(&getAnchorValue());
1759 for (unsigned i = 0; i < ICS.getNumArgOperands(); i++) {
1760 if (getArgNo() == (int)i)
1761 continue;
1762 const Value *ArgOp = ICS.getArgOperand(i);
1763 if (!ArgOp->getType()->isPointerTy())
1764 continue;
1765
Hideto Ueno30d86f12019-09-17 06:53:27 +00001766 if (const Function *F = getAnchorScope()) {
1767 if (AAResults *AAR = A.getInfoCache().getAAResultsForFunction(*F)) {
1768 LLVM_DEBUG(dbgs()
1769 << "[Attributor][NoAliasCSArg] Check alias between "
1770 "callsite arguments "
1771 << AAR->isNoAlias(&getAssociatedValue(), ArgOp) << " "
1772 << getAssociatedValue() << " " << *ArgOp << "\n");
Hideto Ueno1d68ed82019-09-11 07:00:33 +00001773
Hideto Ueno30d86f12019-09-17 06:53:27 +00001774 if (AAR->isNoAlias(&getAssociatedValue(), ArgOp))
1775 continue;
1776 }
1777 }
Hideto Ueno1d68ed82019-09-11 07:00:33 +00001778 return indicatePessimisticFixpoint();
1779 }
1780
1781 return ChangeStatus::UNCHANGED;
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001782 }
1783
1784 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert56e9b602019-09-04 20:34:57 +00001785 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noalias) }
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001786};
1787
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001788/// NoAlias attribute for function return value.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001789struct AANoAliasReturned final : AANoAliasImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001790 AANoAliasReturned(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001791
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001792 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001793 virtual ChangeStatus updateImpl(Attributor &A) override {
1794
1795 auto CheckReturnValue = [&](Value &RV) -> bool {
1796 if (Constant *C = dyn_cast<Constant>(&RV))
1797 if (C->isNullValue() || isa<UndefValue>(C))
1798 return true;
1799
1800 /// For now, we can only deduce noalias if we have call sites.
1801 /// FIXME: add more support.
1802 ImmutableCallSite ICS(&RV);
1803 if (!ICS)
1804 return false;
1805
Johannes Doerfert7516a5e2019-09-03 20:37:24 +00001806 const IRPosition &RVPos = IRPosition::value(RV);
1807 const auto &NoAliasAA = A.getAAFor<AANoAlias>(*this, RVPos);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001808 if (!NoAliasAA.isAssumedNoAlias())
1809 return false;
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001810
Johannes Doerfert7516a5e2019-09-03 20:37:24 +00001811 const auto &NoCaptureAA = A.getAAFor<AANoCapture>(*this, RVPos);
1812 return NoCaptureAA.isAssumedNoCaptureMaybeReturned();
Johannes Doerfertfe6dbad2019-08-16 19:36:17 +00001813 };
1814
1815 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
1816 return indicatePessimisticFixpoint();
1817
1818 return ChangeStatus::UNCHANGED;
1819 }
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001820
1821 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00001822 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001823};
1824
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001825/// NoAlias attribute deduction for a call site return value.
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001826struct AANoAliasCallSiteReturned final : AANoAliasImpl {
1827 AANoAliasCallSiteReturned(const IRPosition &IRP) : AANoAliasImpl(IRP) {}
1828
1829 /// See AbstractAttribute::initialize(...).
1830 void initialize(Attributor &A) override {
1831 AANoAliasImpl::initialize(A);
1832 Function *F = getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00001833 if (!F)
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001834 indicatePessimisticFixpoint();
1835 }
1836
1837 /// See AbstractAttribute::updateImpl(...).
1838 ChangeStatus updateImpl(Attributor &A) override {
1839 // TODO: Once we have call site specific value information we can provide
1840 // call site specific liveness information and then it makes
1841 // sense to specialize attributes for call sites arguments instead of
1842 // redirecting requests to the callee argument.
1843 Function *F = getAssociatedFunction();
1844 const IRPosition &FnPos = IRPosition::returned(*F);
1845 auto &FnAA = A.getAAFor<AANoAlias>(*this, FnPos);
1846 return clampStateAndIndicateChange(
1847 getState(), static_cast<const AANoAlias::StateType &>(FnAA.getState()));
1848 }
1849
1850 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert56e9b602019-09-04 20:34:57 +00001851 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noalias); }
Johannes Doerfert3fac6682019-08-30 15:24:52 +00001852};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00001853
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001854/// -------------------AAIsDead Function Attribute-----------------------
1855
Johannes Doerfert344d0382019-08-07 22:34:26 +00001856struct AAIsDeadImpl : public AAIsDead {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00001857 AAIsDeadImpl(const IRPosition &IRP) : AAIsDead(IRP) {}
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001858
Johannes Doerfertece81902019-08-12 22:05:53 +00001859 void initialize(Attributor &A) override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001860 const Function *F = getAssociatedFunction();
Johannes Doerfert97fd5822019-09-04 16:26:20 +00001861 if (F && !F->isDeclaration())
1862 exploreFromEntry(A, F);
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001863 }
1864
1865 void exploreFromEntry(Attributor &A, const Function *F) {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001866 ToBeExploredPaths.insert(&(F->getEntryBlock().front()));
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001867
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001868 for (size_t i = 0; i < ToBeExploredPaths.size(); ++i)
Johannes Doerfert4361da22019-08-04 18:38:53 +00001869 if (const Instruction *NextNoReturnI =
1870 findNextNoReturn(A, ToBeExploredPaths[i]))
1871 NoReturnCalls.insert(NextNoReturnI);
Johannes Doerfert3ab9e8b2019-09-17 10:52:41 +00001872
1873 // Mark the block live after we looked for no-return instructions.
1874 assumeLive(A, F->getEntryBlock());
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001875 }
1876
Johannes Doerfert4361da22019-08-04 18:38:53 +00001877 /// Find the next assumed noreturn instruction in the block of \p I starting
1878 /// from, thus including, \p I.
1879 ///
1880 /// The caller is responsible to monitor the ToBeExploredPaths set as new
1881 /// instructions discovered in other basic block will be placed in there.
1882 ///
1883 /// \returns The next assumed noreturn instructions in the block of \p I
1884 /// starting from, thus including, \p I.
1885 const Instruction *findNextNoReturn(Attributor &A, const Instruction *I);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001886
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001887 /// See AbstractAttribute::getAsStr().
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001888 const std::string getAsStr() const override {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001889 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001890 std::to_string(getAssociatedFunction()->size()) + "][#NRI " +
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001891 std::to_string(NoReturnCalls.size()) + "]";
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001892 }
1893
1894 /// See AbstractAttribute::manifest(...).
1895 ChangeStatus manifest(Attributor &A) override {
1896 assert(getState().isValidState() &&
1897 "Attempted to manifest an invalid state!");
1898
1899 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001900 Function &F = *getAssociatedFunction();
1901
1902 if (AssumedLiveBlocks.empty()) {
Johannes Doerfertb19cd272019-09-03 20:42:16 +00001903 A.deleteAfterManifest(F);
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00001904 return ChangeStatus::CHANGED;
1905 }
Johannes Doerfert924d2132019-08-05 21:34:45 +00001906
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001907 // Flag to determine if we can change an invoke to a call assuming the
1908 // callee is nounwind. This is not possible if the personality of the
1909 // function allows to catch asynchronous exceptions.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001910 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001911
Johannes Doerfert4361da22019-08-04 18:38:53 +00001912 for (const Instruction *NRC : NoReturnCalls) {
1913 Instruction *I = const_cast<Instruction *>(NRC);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001914 BasicBlock *BB = I->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001915 Instruction *SplitPos = I->getNextNode();
Johannes Doerfertd4108052019-08-21 20:56:41 +00001916 // TODO: mark stuff before unreachable instructions as dead.
1917 if (isa_and_nonnull<UnreachableInst>(SplitPos))
1918 continue;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001919
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001920 if (auto *II = dyn_cast<InvokeInst>(I)) {
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001921 // If we keep the invoke the split position is at the beginning of the
1922 // normal desitination block (it invokes a noreturn function after all).
1923 BasicBlock *NormalDestBB = II->getNormalDest();
1924 SplitPos = &NormalDestBB->front();
1925
Johannes Doerfert4361da22019-08-04 18:38:53 +00001926 /// Invoke is replaced with a call and unreachable is placed after it if
1927 /// the callee is nounwind and noreturn. Otherwise, we keep the invoke
1928 /// and only place an unreachable in the normal successor.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001929 if (Invoke2CallAllowed) {
Michael Liaoa99086d2019-08-20 21:02:31 +00001930 if (II->getCalledFunction()) {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00001931 const IRPosition &IPos = IRPosition::callsite_function(*II);
1932 const auto &AANoUnw = A.getAAFor<AANoUnwind>(*this, IPos);
1933 if (AANoUnw.isAssumedNoUnwind()) {
Johannes Doerfert924d2132019-08-05 21:34:45 +00001934 LLVM_DEBUG(dbgs()
1935 << "[AAIsDead] Replace invoke with call inst\n");
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001936 // We do not need an invoke (II) but instead want a call followed
1937 // by an unreachable. However, we do not remove II as other
1938 // abstract attributes might have it cached as part of their
1939 // results. Given that we modify the CFG anyway, we simply keep II
1940 // around but in a new dead block. To avoid II being live through
1941 // a different edge we have to ensure the block we place it in is
1942 // only reached from the current block of II and then not reached
1943 // at all when we insert the unreachable.
1944 SplitBlockPredecessors(NormalDestBB, {BB}, ".i2c");
1945 CallInst *CI = createCallMatchingInvoke(II);
1946 CI->insertBefore(II);
1947 CI->takeName(II);
1948 II->replaceAllUsesWith(CI);
1949 SplitPos = CI->getNextNode();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001950 }
Johannes Doerfert4361da22019-08-04 18:38:53 +00001951 }
1952 }
Johannes Doerfertb19cd272019-09-03 20:42:16 +00001953
Johannes Doerfert7ab52532019-09-04 20:34:52 +00001954 if (SplitPos == &NormalDestBB->front()) {
1955 // If this is an invoke of a noreturn function the edge to the normal
1956 // destination block is dead but not necessarily the block itself.
1957 // TODO: We need to move to an edge based system during deduction and
1958 // also manifest.
1959 assert(!NormalDestBB->isLandingPad() &&
1960 "Expected the normal destination not to be a landingpad!");
1961 BasicBlock *SplitBB =
1962 SplitBlockPredecessors(NormalDestBB, {BB}, ".dead");
1963 // The split block is live even if it contains only an unreachable
1964 // instruction at the end.
1965 assumeLive(A, *SplitBB);
1966 SplitPos = SplitBB->getTerminator();
1967 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001968 }
1969
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001970 BB = SplitPos->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001971 SplitBlock(BB, SplitPos);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001972 changeToUnreachable(BB->getTerminator(), /* UseLLVMTrap */ false);
1973 HasChanged = ChangeStatus::CHANGED;
1974 }
1975
Johannes Doerfertb19cd272019-09-03 20:42:16 +00001976 for (BasicBlock &BB : F)
1977 if (!AssumedLiveBlocks.count(&BB))
1978 A.deleteAfterManifest(BB);
1979
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001980 return HasChanged;
1981 }
1982
1983 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00001984 ChangeStatus updateImpl(Attributor &A) override;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001985
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001986 /// See AAIsDead::isAssumedDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001987 bool isAssumedDead(const BasicBlock *BB) const override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00001988 assert(BB->getParent() == getAssociatedFunction() &&
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001989 "BB must be in the same anchor scope function.");
1990
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001991 if (!getAssumed())
1992 return false;
1993 return !AssumedLiveBlocks.count(BB);
1994 }
1995
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001996 /// See AAIsDead::isKnownDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001997 bool isKnownDead(const BasicBlock *BB) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001998 return getKnown() && isAssumedDead(BB);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001999 }
2000
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002001 /// See AAIsDead::isAssumed(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00002002 bool isAssumedDead(const Instruction *I) const override {
Johannes Doerfert6dedc782019-08-16 21:31:11 +00002003 assert(I->getParent()->getParent() == getAssociatedFunction() &&
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002004 "Instruction must be in the same anchor scope function.");
2005
Stefan Stipanovic7849e412019-08-03 15:27:41 +00002006 if (!getAssumed())
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002007 return false;
2008
2009 // If it is not in AssumedLiveBlocks then it for sure dead.
2010 // Otherwise, it can still be after noreturn call in a live block.
2011 if (!AssumedLiveBlocks.count(I->getParent()))
2012 return true;
2013
2014 // If it is not after a noreturn call, than it is live.
Johannes Doerfert4361da22019-08-04 18:38:53 +00002015 return isAfterNoReturn(I);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002016 }
2017
2018 /// See AAIsDead::isKnownDead(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00002019 bool isKnownDead(const Instruction *I) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002020 return getKnown() && isAssumedDead(I);
2021 }
2022
2023 /// Check if instruction is after noreturn call, in other words, assumed dead.
Johannes Doerfert4361da22019-08-04 18:38:53 +00002024 bool isAfterNoReturn(const Instruction *I) const;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002025
Johannes Doerfert924d2132019-08-05 21:34:45 +00002026 /// Determine if \p F might catch asynchronous exceptions.
2027 static bool mayCatchAsynchronousExceptions(const Function &F) {
2028 return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F);
2029 }
2030
Johannes Doerfert2f622062019-09-04 16:35:20 +00002031 /// Assume \p BB is (partially) live now and indicate to the Attributor \p A
2032 /// that internal function called from \p BB should now be looked at.
2033 void assumeLive(Attributor &A, const BasicBlock &BB) {
2034 if (!AssumedLiveBlocks.insert(&BB).second)
2035 return;
2036
2037 // We assume that all of BB is (probably) live now and if there are calls to
2038 // internal functions we will assume that those are now live as well. This
2039 // is a performance optimization for blocks with calls to a lot of internal
2040 // functions. It can however cause dead functions to be treated as live.
2041 for (const Instruction &I : BB)
2042 if (ImmutableCallSite ICS = ImmutableCallSite(&I))
2043 if (const Function *F = ICS.getCalledFunction())
2044 if (F->hasInternalLinkage())
2045 A.markLiveInternalFunction(*F);
2046 }
2047
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002048 /// Collection of to be explored paths.
Johannes Doerfert4361da22019-08-04 18:38:53 +00002049 SmallSetVector<const Instruction *, 8> ToBeExploredPaths;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002050
2051 /// Collection of all assumed live BasicBlocks.
Johannes Doerfert4361da22019-08-04 18:38:53 +00002052 DenseSet<const BasicBlock *> AssumedLiveBlocks;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002053
2054 /// Collection of calls with noreturn attribute, assumed or knwon.
Johannes Doerfert4361da22019-08-04 18:38:53 +00002055 SmallSetVector<const Instruction *, 4> NoReturnCalls;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002056};
2057
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002058struct AAIsDeadFunction final : public AAIsDeadImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002059 AAIsDeadFunction(const IRPosition &IRP) : AAIsDeadImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002060
2061 /// See AbstractAttribute::trackStatistics()
2062 void trackStatistics() const override {
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002063 STATS_DECL(PartiallyDeadBlocks, Function,
2064 "Number of basic blocks classified as partially dead");
2065 BUILD_STAT_NAME(PartiallyDeadBlocks, Function) += NoReturnCalls.size();
2066 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002067};
2068
2069bool AAIsDeadImpl::isAfterNoReturn(const Instruction *I) const {
Johannes Doerfert4361da22019-08-04 18:38:53 +00002070 const Instruction *PrevI = I->getPrevNode();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002071 while (PrevI) {
2072 if (NoReturnCalls.count(PrevI))
2073 return true;
2074 PrevI = PrevI->getPrevNode();
2075 }
2076 return false;
2077}
2078
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002079const Instruction *AAIsDeadImpl::findNextNoReturn(Attributor &A,
2080 const Instruction *I) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00002081 const BasicBlock *BB = I->getParent();
Johannes Doerfert924d2132019-08-05 21:34:45 +00002082 const Function &F = *BB->getParent();
2083
2084 // Flag to determine if we can change an invoke to a call assuming the callee
2085 // is nounwind. This is not possible if the personality of the function allows
2086 // to catch asynchronous exceptions.
2087 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Johannes Doerfert4361da22019-08-04 18:38:53 +00002088
2089 // TODO: We should have a function that determines if an "edge" is dead.
2090 // Edges could be from an instruction to the next or from a terminator
2091 // to the successor. For now, we need to special case the unwind block
2092 // of InvokeInst below.
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002093
2094 while (I) {
2095 ImmutableCallSite ICS(I);
2096
2097 if (ICS) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002098 const IRPosition &IPos = IRPosition::callsite_function(ICS);
Johannes Doerfert4361da22019-08-04 18:38:53 +00002099 // Regarless of the no-return property of an invoke instruction we only
2100 // learn that the regular successor is not reachable through this
2101 // instruction but the unwind block might still be.
2102 if (auto *Invoke = dyn_cast<InvokeInst>(I)) {
2103 // Use nounwind to justify the unwind block is dead as well.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002104 const auto &AANoUnw = A.getAAFor<AANoUnwind>(*this, IPos);
2105 if (!Invoke2CallAllowed || !AANoUnw.isAssumedNoUnwind()) {
Johannes Doerfert2f622062019-09-04 16:35:20 +00002106 assumeLive(A, *Invoke->getUnwindDest());
Johannes Doerfert4361da22019-08-04 18:38:53 +00002107 ToBeExploredPaths.insert(&Invoke->getUnwindDest()->front());
2108 }
2109 }
2110
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002111 const auto &NoReturnAA = A.getAAFor<AANoReturn>(*this, IPos);
2112 if (NoReturnAA.isAssumedNoReturn())
Johannes Doerfert4361da22019-08-04 18:38:53 +00002113 return I;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002114 }
2115
2116 I = I->getNextNode();
2117 }
2118
2119 // get new paths (reachable blocks).
Johannes Doerfert4361da22019-08-04 18:38:53 +00002120 for (const BasicBlock *SuccBB : successors(BB)) {
Johannes Doerfert2f622062019-09-04 16:35:20 +00002121 assumeLive(A, *SuccBB);
Johannes Doerfert4361da22019-08-04 18:38:53 +00002122 ToBeExploredPaths.insert(&SuccBB->front());
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002123 }
2124
Johannes Doerfert4361da22019-08-04 18:38:53 +00002125 // No noreturn instruction found.
2126 return nullptr;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002127}
2128
Johannes Doerfertece81902019-08-12 22:05:53 +00002129ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A) {
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00002130 ChangeStatus Status = ChangeStatus::UNCHANGED;
2131
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002132 // Temporary collection to iterate over existing noreturn instructions. This
2133 // will alow easier modification of NoReturnCalls collection
Johannes Doerfert4361da22019-08-04 18:38:53 +00002134 SmallVector<const Instruction *, 8> NoReturnChanged;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002135
Johannes Doerfert4361da22019-08-04 18:38:53 +00002136 for (const Instruction *I : NoReturnCalls)
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002137 NoReturnChanged.push_back(I);
2138
Johannes Doerfert4361da22019-08-04 18:38:53 +00002139 for (const Instruction *I : NoReturnChanged) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002140 size_t Size = ToBeExploredPaths.size();
2141
Johannes Doerfert4361da22019-08-04 18:38:53 +00002142 const Instruction *NextNoReturnI = findNextNoReturn(A, I);
2143 if (NextNoReturnI != I) {
2144 Status = ChangeStatus::CHANGED;
2145 NoReturnCalls.remove(I);
2146 if (NextNoReturnI)
2147 NoReturnCalls.insert(NextNoReturnI);
2148 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002149
Johannes Doerfert4361da22019-08-04 18:38:53 +00002150 // Explore new paths.
2151 while (Size != ToBeExploredPaths.size()) {
2152 Status = ChangeStatus::CHANGED;
2153 if (const Instruction *NextNoReturnI =
2154 findNextNoReturn(A, ToBeExploredPaths[Size++]))
2155 NoReturnCalls.insert(NextNoReturnI);
2156 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002157 }
2158
Johannes Doerfertdef99282019-08-14 21:29:37 +00002159 LLVM_DEBUG(dbgs() << "[AAIsDead] AssumedLiveBlocks: "
2160 << AssumedLiveBlocks.size() << " Total number of blocks: "
Johannes Doerfert6dedc782019-08-16 21:31:11 +00002161 << getAssociatedFunction()->size() << "\n");
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002162
Johannes Doerfertd6207812019-08-07 22:32:38 +00002163 // If we know everything is live there is no need to query for liveness.
2164 if (NoReturnCalls.empty() &&
Johannes Doerfert6dedc782019-08-16 21:31:11 +00002165 getAssociatedFunction()->size() == AssumedLiveBlocks.size()) {
Johannes Doerfertd6207812019-08-07 22:32:38 +00002166 // Indicating a pessimistic fixpoint will cause the state to be "invalid"
2167 // which will cause the Attributor to not return the AAIsDead on request,
2168 // which will prevent us from querying isAssumedDead().
2169 indicatePessimisticFixpoint();
2170 assert(!isValidState() && "Expected an invalid state!");
Johannes Doerfert62a9c1d2019-08-29 01:26:58 +00002171 Status = ChangeStatus::CHANGED;
Johannes Doerfertd6207812019-08-07 22:32:38 +00002172 }
2173
Stefan Stipanovic6058b862019-07-22 23:58:23 +00002174 return Status;
2175}
2176
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002177/// Liveness information for a call sites.
Johannes Doerfert07a5c122019-08-28 14:09:14 +00002178struct AAIsDeadCallSite final : AAIsDeadImpl {
2179 AAIsDeadCallSite(const IRPosition &IRP) : AAIsDeadImpl(IRP) {}
2180
2181 /// See AbstractAttribute::initialize(...).
2182 void initialize(Attributor &A) override {
2183 // TODO: Once we have call site specific value information we can provide
Johannes Doerfert3fac6682019-08-30 15:24:52 +00002184 // call site specific liveness information and then it makes
Johannes Doerfert07a5c122019-08-28 14:09:14 +00002185 // sense to specialize attributes for call sites instead of
2186 // redirecting requests to the callee.
2187 llvm_unreachable("Abstract attributes for liveness are not "
2188 "supported for call sites yet!");
2189 }
2190
2191 /// See AbstractAttribute::updateImpl(...).
2192 ChangeStatus updateImpl(Attributor &A) override {
2193 return indicatePessimisticFixpoint();
2194 }
2195
2196 /// See AbstractAttribute::trackStatistics()
2197 void trackStatistics() const override {}
2198};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002199
Hideto Ueno19c07af2019-07-23 08:16:17 +00002200/// -------------------- Dereferenceable Argument Attribute --------------------
2201
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002202template <>
2203ChangeStatus clampStateAndIndicateChange<DerefState>(DerefState &S,
2204 const DerefState &R) {
2205 ChangeStatus CS0 = clampStateAndIndicateChange<IntegerState>(
2206 S.DerefBytesState, R.DerefBytesState);
2207 ChangeStatus CS1 =
2208 clampStateAndIndicateChange<IntegerState>(S.GlobalState, R.GlobalState);
2209 return CS0 | CS1;
2210}
2211
Hideto Ueno70576ca2019-08-22 14:18:29 +00002212struct AADereferenceableImpl : AADereferenceable {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002213 AADereferenceableImpl(const IRPosition &IRP) : AADereferenceable(IRP) {}
Johannes Doerfert344d0382019-08-07 22:34:26 +00002214 using StateType = DerefState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00002215
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00002216 void initialize(Attributor &A) override {
2217 SmallVector<Attribute, 4> Attrs;
2218 getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
2219 Attrs);
2220 for (const Attribute &Attr : Attrs)
2221 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
2222
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002223 NonNullAA = &A.getAAFor<AANonNull>(*this, getIRPosition());
Johannes Doerfertb0412e42019-09-04 16:16:13 +00002224
2225 const IRPosition &IRP = this->getIRPosition();
2226 bool IsFnInterface = IRP.isFnInterfaceKind();
2227 const Function *FnScope = IRP.getAnchorScope();
2228 if (IsFnInterface && (!FnScope || !FnScope->hasExactDefinition()))
2229 indicatePessimisticFixpoint();
Johannes Doerfert6a1274a2019-08-14 21:31:32 +00002230 }
2231
Hideto Ueno19c07af2019-07-23 08:16:17 +00002232 /// See AbstractAttribute::getState()
2233 /// {
Johannes Doerfert344d0382019-08-07 22:34:26 +00002234 StateType &getState() override { return *this; }
2235 const StateType &getState() const override { return *this; }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002236 /// }
2237
Johannes Doerferteccdf082019-08-05 23:35:12 +00002238 void getDeducedAttributes(LLVMContext &Ctx,
2239 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002240 // TODO: Add *_globally support
2241 if (isAssumedNonNull())
2242 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
2243 Ctx, getAssumedDereferenceableBytes()));
2244 else
2245 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
2246 Ctx, getAssumedDereferenceableBytes()));
2247 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002248
2249 /// See AbstractAttribute::getAsStr().
2250 const std::string getAsStr() const override {
2251 if (!getAssumedDereferenceableBytes())
2252 return "unknown-dereferenceable";
2253 return std::string("dereferenceable") +
2254 (isAssumedNonNull() ? "" : "_or_null") +
2255 (isAssumedGlobal() ? "_globally" : "") + "<" +
2256 std::to_string(getKnownDereferenceableBytes()) + "-" +
2257 std::to_string(getAssumedDereferenceableBytes()) + ">";
2258 }
2259};
2260
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002261/// Dereferenceable attribute for a floating value.
2262struct AADereferenceableFloating : AADereferenceableImpl {
2263 AADereferenceableFloating(const IRPosition &IRP)
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002264 : AADereferenceableImpl(IRP) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00002265
2266 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002267 ChangeStatus updateImpl(Attributor &A) override {
2268 const DataLayout &DL = A.getDataLayout();
2269
2270 auto VisitValueCB = [&](Value &V, DerefState &T, bool Stripped) -> bool {
2271 unsigned IdxWidth =
2272 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
2273 APInt Offset(IdxWidth, 0);
2274 const Value *Base =
2275 V.stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
2276
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002277 const auto &AA =
2278 A.getAAFor<AADereferenceable>(*this, IRPosition::value(*Base));
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002279 int64_t DerefBytes = 0;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002280 if (!Stripped && this == &AA) {
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002281 // Use IR information if we did not strip anything.
2282 // TODO: track globally.
2283 bool CanBeNull;
2284 DerefBytes = Base->getPointerDereferenceableBytes(DL, CanBeNull);
2285 T.GlobalState.indicatePessimisticFixpoint();
2286 } else {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002287 const DerefState &DS = static_cast<const DerefState &>(AA.getState());
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002288 DerefBytes = DS.DerefBytesState.getAssumed();
2289 T.GlobalState &= DS.GlobalState;
2290 }
2291
Johannes Doerfert2f2d7c32019-08-23 15:45:46 +00002292 // For now we do not try to "increase" dereferenceability due to negative
2293 // indices as we first have to come up with code to deal with loops and
2294 // for overflows of the dereferenceable bytes.
Johannes Doerfert785fad32019-08-23 17:29:23 +00002295 int64_t OffsetSExt = Offset.getSExtValue();
2296 if (OffsetSExt < 0)
Johannes Doerfert2f2d7c32019-08-23 15:45:46 +00002297 Offset = 0;
2298
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002299 T.takeAssumedDerefBytesMinimum(
Johannes Doerfert785fad32019-08-23 17:29:23 +00002300 std::max(int64_t(0), DerefBytes - OffsetSExt));
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002301
Johannes Doerfert785fad32019-08-23 17:29:23 +00002302 if (this == &AA) {
2303 if (!Stripped) {
2304 // If nothing was stripped IR information is all we got.
2305 T.takeKnownDerefBytesMaximum(
2306 std::max(int64_t(0), DerefBytes - OffsetSExt));
2307 T.indicatePessimisticFixpoint();
2308 } else if (OffsetSExt > 0) {
2309 // If something was stripped but there is circular reasoning we look
2310 // for the offset. If it is positive we basically decrease the
2311 // dereferenceable bytes in a circluar loop now, which will simply
2312 // drive them down to the known value in a very slow way which we
2313 // can accelerate.
2314 T.indicatePessimisticFixpoint();
2315 }
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002316 }
2317
2318 return T.isValidState();
2319 };
2320
2321 DerefState T;
2322 if (!genericValueTraversal<AADereferenceable, DerefState>(
2323 A, getIRPosition(), *this, T, VisitValueCB))
2324 return indicatePessimisticFixpoint();
2325
2326 return clampStateAndIndicateChange(getState(), T);
2327 }
2328
2329 /// See AbstractAttribute::trackStatistics()
2330 void trackStatistics() const override {
2331 STATS_DECLTRACK_FLOATING_ATTR(dereferenceable)
2332 }
2333};
2334
2335/// Dereferenceable attribute for a return value.
2336struct AADereferenceableReturned final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002337 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl,
2338 DerefState> {
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002339 AADereferenceableReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002340 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl,
2341 DerefState>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002342
2343 /// See AbstractAttribute::trackStatistics()
2344 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002345 STATS_DECLTRACK_FNRET_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002346 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002347};
2348
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002349/// Dereferenceable attribute for an argument
2350struct AADereferenceableArgument final
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002351 : AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl,
2352 DerefState> {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002353 AADereferenceableArgument(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002354 : AAArgumentFromCallSiteArguments<AADereferenceable,
2355 AADereferenceableImpl, DerefState>(
2356 IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002357
2358 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert3fac6682019-08-30 15:24:52 +00002359 void trackStatistics() const override {
Johannes Doerfert169af992019-08-20 06:09:56 +00002360 STATS_DECLTRACK_ARG_ATTR(dereferenceable)
2361 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002362};
2363
Hideto Ueno19c07af2019-07-23 08:16:17 +00002364/// Dereferenceable attribute for a call site argument.
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002365struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002366 AADereferenceableCallSiteArgument(const IRPosition &IRP)
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002367 : AADereferenceableFloating(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002368
2369 /// See AbstractAttribute::trackStatistics()
2370 void trackStatistics() const override {
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002371 STATS_DECLTRACK_CSARG_ATTR(dereferenceable)
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002372 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00002373};
2374
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002375/// Dereferenceable attribute deduction for a call site return value.
Johannes Doerfert3fac6682019-08-30 15:24:52 +00002376struct AADereferenceableCallSiteReturned final : AADereferenceableImpl {
2377 AADereferenceableCallSiteReturned(const IRPosition &IRP)
2378 : AADereferenceableImpl(IRP) {}
2379
2380 /// See AbstractAttribute::initialize(...).
2381 void initialize(Attributor &A) override {
2382 AADereferenceableImpl::initialize(A);
2383 Function *F = getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00002384 if (!F)
Johannes Doerfert3fac6682019-08-30 15:24:52 +00002385 indicatePessimisticFixpoint();
2386 }
2387
2388 /// See AbstractAttribute::updateImpl(...).
2389 ChangeStatus updateImpl(Attributor &A) override {
2390 // TODO: Once we have call site specific value information we can provide
2391 // call site specific liveness information and then it makes
2392 // sense to specialize attributes for call sites arguments instead of
2393 // redirecting requests to the callee argument.
2394 Function *F = getAssociatedFunction();
2395 const IRPosition &FnPos = IRPosition::returned(*F);
2396 auto &FnAA = A.getAAFor<AADereferenceable>(*this, FnPos);
2397 return clampStateAndIndicateChange(
2398 getState(), static_cast<const DerefState &>(FnAA.getState()));
2399 }
2400
2401 /// See AbstractAttribute::trackStatistics()
2402 void trackStatistics() const override {
2403 STATS_DECLTRACK_CS_ATTR(dereferenceable);
2404 }
2405};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002406
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002407// ------------------------ Align Argument Attribute ------------------------
2408
Johannes Doerfert344d0382019-08-07 22:34:26 +00002409struct AAAlignImpl : AAAlign {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002410 AAAlignImpl(const IRPosition &IRP) : AAAlign(IRP) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002411
2412 // Max alignemnt value allowed in IR
2413 static const unsigned MAX_ALIGN = 1U << 29;
2414
Johannes Doerfert234eda52019-08-16 19:51:23 +00002415 /// See AbstractAttribute::initialize(...).
Johannes Doerfertece81902019-08-12 22:05:53 +00002416 void initialize(Attributor &A) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002417 takeAssumedMinimum(MAX_ALIGN);
2418
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002419 SmallVector<Attribute, 4> Attrs;
2420 getAttrs({Attribute::Alignment}, Attrs);
2421 for (const Attribute &Attr : Attrs)
2422 takeKnownMaximum(Attr.getValueAsInt());
Johannes Doerfert97fd5822019-09-04 16:26:20 +00002423
2424 if (getIRPosition().isFnInterfaceKind() &&
2425 (!getAssociatedFunction() ||
2426 !getAssociatedFunction()->hasExactDefinition()))
2427 indicatePessimisticFixpoint();
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002428 }
2429
Johannes Doerfert5a5a1392019-08-23 20:20:10 +00002430 /// See AbstractAttribute::manifest(...).
2431 ChangeStatus manifest(Attributor &A) override {
2432 ChangeStatus Changed = ChangeStatus::UNCHANGED;
2433
2434 // Check for users that allow alignment annotations.
2435 Value &AnchorVal = getIRPosition().getAnchorValue();
2436 for (const Use &U : AnchorVal.uses()) {
2437 if (auto *SI = dyn_cast<StoreInst>(U.getUser())) {
2438 if (SI->getPointerOperand() == &AnchorVal)
2439 if (SI->getAlignment() < getAssumedAlign()) {
2440 STATS_DECLTRACK(AAAlign, Store,
2441 "Number of times alignemnt added to a store");
2442 SI->setAlignment(getAssumedAlign());
2443 Changed = ChangeStatus::CHANGED;
2444 }
2445 } else if (auto *LI = dyn_cast<LoadInst>(U.getUser())) {
2446 if (LI->getPointerOperand() == &AnchorVal)
2447 if (LI->getAlignment() < getAssumedAlign()) {
2448 LI->setAlignment(getAssumedAlign());
2449 STATS_DECLTRACK(AAAlign, Load,
2450 "Number of times alignemnt added to a load");
2451 Changed = ChangeStatus::CHANGED;
2452 }
2453 }
2454 }
2455
Johannes Doerfert81df4522019-08-30 15:22:28 +00002456 return AAAlign::manifest(A) | Changed;
Johannes Doerfert5a5a1392019-08-23 20:20:10 +00002457 }
2458
Johannes Doerfert81df4522019-08-30 15:22:28 +00002459 // TODO: Provide a helper to determine the implied ABI alignment and check in
2460 // the existing manifest method and a new one for AAAlignImpl that value
2461 // to avoid making the alignment explicit if it did not improve.
2462
2463 /// See AbstractAttribute::getDeducedAttributes
2464 virtual void
2465 getDeducedAttributes(LLVMContext &Ctx,
2466 SmallVectorImpl<Attribute> &Attrs) const override {
2467 if (getAssumedAlign() > 1)
2468 Attrs.emplace_back(Attribute::getWithAlignment(Ctx, getAssumedAlign()));
2469 }
2470
2471 /// See AbstractAttribute::getAsStr().
2472 const std::string getAsStr() const override {
2473 return getAssumedAlign() ? ("align<" + std::to_string(getKnownAlign()) +
2474 "-" + std::to_string(getAssumedAlign()) + ">")
2475 : "unknown-align";
2476 }
2477};
2478
2479/// Align attribute for a floating value.
2480struct AAAlignFloating : AAAlignImpl {
2481 AAAlignFloating(const IRPosition &IRP) : AAAlignImpl(IRP) {}
2482
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002483 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert234eda52019-08-16 19:51:23 +00002484 ChangeStatus updateImpl(Attributor &A) override {
2485 const DataLayout &DL = A.getDataLayout();
2486
Johannes Doerfertb9b87912019-08-20 06:02:39 +00002487 auto VisitValueCB = [&](Value &V, AAAlign::StateType &T,
2488 bool Stripped) -> bool {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002489 const auto &AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V));
2490 if (!Stripped && this == &AA) {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002491 // Use only IR information if we did not strip anything.
2492 T.takeKnownMaximum(V.getPointerAlignment(DL));
2493 T.indicatePessimisticFixpoint();
Johannes Doerfert234eda52019-08-16 19:51:23 +00002494 } else {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002495 // Use abstract attribute information.
2496 const AAAlign::StateType &DS =
2497 static_cast<const AAAlign::StateType &>(AA.getState());
2498 T ^= DS;
Johannes Doerfert234eda52019-08-16 19:51:23 +00002499 }
Johannes Doerfertb9b87912019-08-20 06:02:39 +00002500 return T.isValidState();
Johannes Doerfert234eda52019-08-16 19:51:23 +00002501 };
2502
2503 StateType T;
2504 if (!genericValueTraversal<AAAlign, StateType>(A, getIRPosition(), *this, T,
2505 VisitValueCB))
Johannes Doerfertcfcca1a2019-08-20 06:08:35 +00002506 return indicatePessimisticFixpoint();
Johannes Doerfert234eda52019-08-16 19:51:23 +00002507
Johannes Doerfert028b2aa2019-08-20 05:57:01 +00002508 // TODO: If we know we visited all incoming values, thus no are assumed
2509 // dead, we can take the known information from the state T.
Johannes Doerfert234eda52019-08-16 19:51:23 +00002510 return clampStateAndIndicateChange(getState(), T);
2511 }
2512
2513 /// See AbstractAttribute::trackStatistics()
2514 void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) }
2515};
2516
2517/// Align attribute for function return value.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002518struct AAAlignReturned final
2519 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002520 AAAlignReturned(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002521 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002522
2523 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002524 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002525};
2526
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002527/// Align attribute for function argument.
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002528struct AAAlignArgument final
2529 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
Johannes Doerfert234eda52019-08-16 19:51:23 +00002530 AAAlignArgument(const IRPosition &IRP)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00002531 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002532
2533 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert169af992019-08-20 06:09:56 +00002534 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002535};
2536
Johannes Doerfert234eda52019-08-16 19:51:23 +00002537struct AAAlignCallSiteArgument final : AAAlignFloating {
2538 AAAlignCallSiteArgument(const IRPosition &IRP) : AAAlignFloating(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002539
Johannes Doerfert5a5a1392019-08-23 20:20:10 +00002540 /// See AbstractAttribute::manifest(...).
2541 ChangeStatus manifest(Attributor &A) override {
2542 return AAAlignImpl::manifest(A);
2543 }
2544
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002545 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002546 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002547};
2548
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002549/// Align attribute deduction for a call site return value.
Johannes Doerfert3fac6682019-08-30 15:24:52 +00002550struct AAAlignCallSiteReturned final : AAAlignImpl {
2551 AAAlignCallSiteReturned(const IRPosition &IRP) : AAAlignImpl(IRP) {}
2552
2553 /// See AbstractAttribute::initialize(...).
2554 void initialize(Attributor &A) override {
2555 AAAlignImpl::initialize(A);
2556 Function *F = getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00002557 if (!F)
Johannes Doerfert3fac6682019-08-30 15:24:52 +00002558 indicatePessimisticFixpoint();
2559 }
2560
2561 /// See AbstractAttribute::updateImpl(...).
2562 ChangeStatus updateImpl(Attributor &A) override {
2563 // TODO: Once we have call site specific value information we can provide
2564 // call site specific liveness information and then it makes
2565 // sense to specialize attributes for call sites arguments instead of
2566 // redirecting requests to the callee argument.
2567 Function *F = getAssociatedFunction();
2568 const IRPosition &FnPos = IRPosition::returned(*F);
2569 auto &FnAA = A.getAAFor<AAAlign>(*this, FnPos);
2570 return clampStateAndIndicateChange(
2571 getState(), static_cast<const AAAlign::StateType &>(FnAA.getState()));
2572 }
2573
2574 /// See AbstractAttribute::trackStatistics()
2575 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(align); }
2576};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002577
Johannes Doerferte83f3032019-08-05 23:22:05 +00002578/// ------------------ Function No-Return Attribute ----------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00002579struct AANoReturnImpl : public AANoReturn {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002580 AANoReturnImpl(const IRPosition &IRP) : AANoReturn(IRP) {}
Johannes Doerferte83f3032019-08-05 23:22:05 +00002581
Johannes Doerferte83f3032019-08-05 23:22:05 +00002582 /// See AbstractAttribute::getAsStr().
2583 const std::string getAsStr() const override {
2584 return getAssumed() ? "noreturn" : "may-return";
2585 }
2586
Johannes Doerferte83f3032019-08-05 23:22:05 +00002587 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfertece81902019-08-12 22:05:53 +00002588 virtual ChangeStatus updateImpl(Attributor &A) override {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002589 auto CheckForNoReturn = [](Instruction &) { return false; };
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002590 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002591 {(unsigned)Instruction::Ret}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002592 return indicatePessimisticFixpoint();
Johannes Doerferte83f3032019-08-05 23:22:05 +00002593 return ChangeStatus::UNCHANGED;
2594 }
2595};
2596
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002597struct AANoReturnFunction final : AANoReturnImpl {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00002598 AANoReturnFunction(const IRPosition &IRP) : AANoReturnImpl(IRP) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002599
2600 /// See AbstractAttribute::trackStatistics()
Johannes Doerfert17b578b2019-08-14 21:46:25 +00002601 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002602};
2603
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002604/// NoReturn attribute deduction for a call sites.
Johannes Doerfert3fac6682019-08-30 15:24:52 +00002605struct AANoReturnCallSite final : AANoReturnImpl {
2606 AANoReturnCallSite(const IRPosition &IRP) : AANoReturnImpl(IRP) {}
2607
2608 /// See AbstractAttribute::initialize(...).
2609 void initialize(Attributor &A) override {
2610 AANoReturnImpl::initialize(A);
2611 Function *F = getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00002612 if (!F)
Johannes Doerfert3fac6682019-08-30 15:24:52 +00002613 indicatePessimisticFixpoint();
2614 }
2615
2616 /// See AbstractAttribute::updateImpl(...).
2617 ChangeStatus updateImpl(Attributor &A) override {
2618 // TODO: Once we have call site specific value information we can provide
2619 // call site specific liveness information and then it makes
2620 // sense to specialize attributes for call sites arguments instead of
2621 // redirecting requests to the callee argument.
2622 Function *F = getAssociatedFunction();
2623 const IRPosition &FnPos = IRPosition::function(*F);
2624 auto &FnAA = A.getAAFor<AANoReturn>(*this, FnPos);
2625 return clampStateAndIndicateChange(
2626 getState(),
2627 static_cast<const AANoReturn::StateType &>(FnAA.getState()));
2628 }
2629
2630 /// See AbstractAttribute::trackStatistics()
2631 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noreturn); }
2632};
Johannes Doerfert66cf87e2019-08-16 19:49:00 +00002633
Johannes Doerfert7516a5e2019-09-03 20:37:24 +00002634/// ----------------------- Variable Capturing ---------------------------------
2635
2636/// A class to hold the state of for no-capture attributes.
2637struct AANoCaptureImpl : public AANoCapture {
2638 AANoCaptureImpl(const IRPosition &IRP) : AANoCapture(IRP) {}
2639
2640 /// See AbstractAttribute::initialize(...).
2641 void initialize(Attributor &A) override {
Johannes Doerfertb0412e42019-09-04 16:16:13 +00002642 AANoCapture::initialize(A);
Johannes Doerfert7516a5e2019-09-03 20:37:24 +00002643
2644 const IRPosition &IRP = getIRPosition();
2645 const Function *F =
2646 getArgNo() >= 0 ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
2647
2648 // Check what state the associated function can actually capture.
2649 if (F)
2650 determineFunctionCaptureCapabilities(*F, *this);
Johannes Doerfertb0412e42019-09-04 16:16:13 +00002651 else
Johannes Doerfert7516a5e2019-09-03 20:37:24 +00002652 indicatePessimisticFixpoint();
2653 }
2654
2655 /// See AbstractAttribute::updateImpl(...).
2656 ChangeStatus updateImpl(Attributor &A) override;
2657
2658 /// see AbstractAttribute::isAssumedNoCaptureMaybeReturned(...).
2659 virtual void
2660 getDeducedAttributes(LLVMContext &Ctx,
2661 SmallVectorImpl<Attribute> &Attrs) const override {
2662 if (!isAssumedNoCaptureMaybeReturned())
2663 return;
2664
Hideto Ueno37367642019-09-11 06:52:11 +00002665 if (getArgNo() >= 0) {
2666 if (isAssumedNoCapture())
2667 Attrs.emplace_back(Attribute::get(Ctx, Attribute::NoCapture));
2668 else if (ManifestInternal)
2669 Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned"));
2670 }
Johannes Doerfert7516a5e2019-09-03 20:37:24 +00002671 }
2672
2673 /// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known
2674 /// depending on the ability of the function associated with \p IRP to capture
2675 /// state in memory and through "returning/throwing", respectively.
2676 static void determineFunctionCaptureCapabilities(const Function &F,
2677 IntegerState &State) {
2678 // TODO: Once we have memory behavior attributes we should use them here.
2679
2680 // If we know we cannot communicate or write to memory, we do not care about
2681 // ptr2int anymore.
2682 if (F.onlyReadsMemory() && F.doesNotThrow() &&
2683 F.getReturnType()->isVoidTy()) {
2684 State.addKnownBits(NO_CAPTURE);
2685 return;
2686 }
2687
2688 // A function cannot capture state in memory if it only reads memory, it can
2689 // however return/throw state and the state might be influenced by the
2690 // pointer value, e.g., loading from a returned pointer might reveal a bit.
2691 if (F.onlyReadsMemory())
2692 State.addKnownBits(NOT_CAPTURED_IN_MEM);
2693
2694 // A function cannot communicate state back if it does not through
2695 // exceptions and doesn not return values.
2696 if (F.doesNotThrow() && F.getReturnType()->isVoidTy())
2697 State.addKnownBits(NOT_CAPTURED_IN_RET);
2698 }
2699
2700 /// See AbstractState::getAsStr().
2701 const std::string getAsStr() const override {
2702 if (isKnownNoCapture())
2703 return "known not-captured";
2704 if (isAssumedNoCapture())
2705 return "assumed not-captured";
2706 if (isKnownNoCaptureMaybeReturned())
2707 return "known not-captured-maybe-returned";
2708 if (isAssumedNoCaptureMaybeReturned())
2709 return "assumed not-captured-maybe-returned";
2710 return "assumed-captured";
2711 }
2712};
2713
2714/// Attributor-aware capture tracker.
2715struct AACaptureUseTracker final : public CaptureTracker {
2716
2717 /// Create a capture tracker that can lookup in-flight abstract attributes
2718 /// through the Attributor \p A.
2719 ///
2720 /// If a use leads to a potential capture, \p CapturedInMemory is set and the
2721 /// search is stopped. If a use leads to a return instruction,
2722 /// \p CommunicatedBack is set to true and \p CapturedInMemory is not changed.
2723 /// If a use leads to a ptr2int which may capture the value,
2724 /// \p CapturedInInteger is set. If a use is found that is currently assumed
2725 /// "no-capture-maybe-returned", the user is added to the \p PotentialCopies
2726 /// set. All values in \p PotentialCopies are later tracked as well. For every
2727 /// explored use we decrement \p RemainingUsesToExplore. Once it reaches 0,
2728 /// the search is stopped with \p CapturedInMemory and \p CapturedInInteger
2729 /// conservatively set to true.
2730 AACaptureUseTracker(Attributor &A, AANoCapture &NoCaptureAA,
2731 const AAIsDead &IsDeadAA, IntegerState &State,
2732 SmallVectorImpl<const Value *> &PotentialCopies,
2733 unsigned &RemainingUsesToExplore)
2734 : A(A), NoCaptureAA(NoCaptureAA), IsDeadAA(IsDeadAA), State(State),
2735 PotentialCopies(PotentialCopies),
2736 RemainingUsesToExplore(RemainingUsesToExplore) {}
2737
2738 /// Determine if \p V maybe captured. *Also updates the state!*
2739 bool valueMayBeCaptured(const Value *V) {
2740 if (V->getType()->isPointerTy()) {
2741 PointerMayBeCaptured(V, this);
2742 } else {
2743 State.indicatePessimisticFixpoint();
2744 }
2745 return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
2746 }
2747
2748 /// See CaptureTracker::tooManyUses().
2749 void tooManyUses() override {
2750 State.removeAssumedBits(AANoCapture::NO_CAPTURE);
2751 }
2752
2753 bool isDereferenceableOrNull(Value *O, const DataLayout &DL) override {
2754 if (CaptureTracker::isDereferenceableOrNull(O, DL))
2755 return true;
2756 const auto &DerefAA =
2757 A.getAAFor<AADereferenceable>(NoCaptureAA, IRPosition::value(*O));
2758 return DerefAA.getAssumedDereferenceableBytes();
2759 }
2760
2761 /// See CaptureTracker::captured(...).
2762 bool captured(const Use *U) override {
2763 Instruction *UInst = cast<Instruction>(U->getUser());
2764 LLVM_DEBUG(dbgs() << "Check use: " << *U->get() << " in " << *UInst
2765 << "\n");
2766
2767 // Because we may reuse the tracker multiple times we keep track of the
2768 // number of explored uses ourselves as well.
2769 if (RemainingUsesToExplore-- == 0) {
2770 LLVM_DEBUG(dbgs() << " - too many uses to explore!\n");
2771 return isCapturedIn(/* Memory */ true, /* Integer */ true,
2772 /* Return */ true);
2773 }
2774
2775 // Deal with ptr2int by following uses.
2776 if (isa<PtrToIntInst>(UInst)) {
2777 LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n");
2778 return valueMayBeCaptured(UInst);
2779 }
2780
2781 // Explicitly catch return instructions.
2782 if (isa<ReturnInst>(UInst))
2783 return isCapturedIn(/* Memory */ false, /* Integer */ false,
2784 /* Return */ true);
2785
2786 // For now we only use special logic for call sites. However, the tracker
2787 // itself knows about a lot of other non-capturing cases already.
2788 CallSite CS(UInst);
2789 if (!CS || !CS.isArgOperand(U))
2790 return isCapturedIn(/* Memory */ true, /* Integer */ true,
2791 /* Return */ true);
2792
2793 unsigned ArgNo = CS.getArgumentNo(U);
2794 const IRPosition &CSArgPos = IRPosition::callsite_argument(CS, ArgNo);
2795 // If we have a abstract no-capture attribute for the argument we can use
2796 // it to justify a non-capture attribute here. This allows recursion!
2797 auto &ArgNoCaptureAA = A.getAAFor<AANoCapture>(NoCaptureAA, CSArgPos);
2798 if (ArgNoCaptureAA.isAssumedNoCapture())
2799 return isCapturedIn(/* Memory */ false, /* Integer */ false,
2800 /* Return */ false);
2801 if (ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) {
2802 addPotentialCopy(CS);
2803 return isCapturedIn(/* Memory */ false, /* Integer */ false,
2804 /* Return */ false);
2805 }
2806
2807 // Lastly, we could not find a reason no-capture can be assumed so we don't.
2808 return isCapturedIn(/* Memory */ true, /* Integer */ true,
2809 /* Return */ true);
2810 }
2811
2812 /// Register \p CS as potential copy of the value we are checking.
2813 void addPotentialCopy(CallSite CS) {
2814 PotentialCopies.push_back(CS.getInstruction());
2815 }
2816
2817 /// See CaptureTracker::shouldExplore(...).
2818 bool shouldExplore(const Use *U) override {
2819 // Check liveness.
2820 return !IsDeadAA.isAssumedDead(cast<Instruction>(U->getUser()));
2821 }
2822
2823 /// Update the state according to \p CapturedInMem, \p CapturedInInt, and
2824 /// \p CapturedInRet, then return the appropriate value for use in the
2825 /// CaptureTracker::captured() interface.
2826 bool isCapturedIn(bool CapturedInMem, bool CapturedInInt,
2827 bool CapturedInRet) {
2828 LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int "
2829 << CapturedInInt << "|Ret " << CapturedInRet << "]\n");
2830 if (CapturedInMem)
2831 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM);
2832 if (CapturedInInt)
2833 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT);
2834 if (CapturedInRet)
2835 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET);
2836 return !State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
2837 }
2838
2839private:
2840 /// The attributor providing in-flight abstract attributes.
2841 Attributor &A;
2842
2843 /// The abstract attribute currently updated.
2844 AANoCapture &NoCaptureAA;
2845
2846 /// The abstract liveness state.
2847 const AAIsDead &IsDeadAA;
2848
2849 /// The state currently updated.
2850 IntegerState &State;
2851
2852 /// Set of potential copies of the tracked value.
2853 SmallVectorImpl<const Value *> &PotentialCopies;
2854
2855 /// Global counter to limit the number of explored uses.
2856 unsigned &RemainingUsesToExplore;
2857};
2858
2859ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
2860 const IRPosition &IRP = getIRPosition();
2861 const Value *V =
2862 getArgNo() >= 0 ? IRP.getAssociatedArgument() : &IRP.getAssociatedValue();
2863 if (!V)
2864 return indicatePessimisticFixpoint();
2865
2866 const Function *F =
2867 getArgNo() >= 0 ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
2868 assert(F && "Expected a function!");
2869 const auto &IsDeadAA = A.getAAFor<AAIsDead>(*this, IRPosition::function(*F));
2870
2871 AANoCapture::StateType T;
2872 // TODO: Once we have memory behavior attributes we should use them here
2873 // similar to the reasoning in
2874 // AANoCaptureImpl::determineFunctionCaptureCapabilities(...).
2875
2876 // TODO: Use the AAReturnedValues to learn if the argument can return or
2877 // not.
2878
2879 // Use the CaptureTracker interface and logic with the specialized tracker,
2880 // defined in AACaptureUseTracker, that can look at in-flight abstract
2881 // attributes and directly updates the assumed state.
2882 SmallVector<const Value *, 4> PotentialCopies;
2883 unsigned RemainingUsesToExplore = DefaultMaxUsesToExplore;
2884 AACaptureUseTracker Tracker(A, *this, IsDeadAA, T, PotentialCopies,
2885 RemainingUsesToExplore);
2886
2887 // Check all potential copies of the associated value until we can assume
2888 // none will be captured or we have to assume at least one might be.
2889 unsigned Idx = 0;
2890 PotentialCopies.push_back(V);
2891 while (T.isAssumed(NO_CAPTURE_MAYBE_RETURNED) && Idx < PotentialCopies.size())
2892 Tracker.valueMayBeCaptured(PotentialCopies[Idx++]);
2893
2894 AAAlign::StateType &S = getState();
2895 auto Assumed = S.getAssumed();
2896 S.intersectAssumedBits(T.getAssumed());
2897 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
2898 : ChangeStatus::CHANGED;
2899}
2900
2901/// NoCapture attribute for function arguments.
2902struct AANoCaptureArgument final : AANoCaptureImpl {
2903 AANoCaptureArgument(const IRPosition &IRP) : AANoCaptureImpl(IRP) {}
2904
2905 /// See AbstractAttribute::trackStatistics()
2906 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture) }
2907};
2908
2909/// NoCapture attribute for call site arguments.
2910struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
2911 AANoCaptureCallSiteArgument(const IRPosition &IRP) : AANoCaptureImpl(IRP) {}
2912
2913 /// See AbstractAttribute::updateImpl(...).
2914 ChangeStatus updateImpl(Attributor &A) override {
2915 // TODO: Once we have call site specific value information we can provide
2916 // call site specific liveness information and then it makes
2917 // sense to specialize attributes for call sites arguments instead of
2918 // redirecting requests to the callee argument.
2919 Argument *Arg = getAssociatedArgument();
2920 if (!Arg)
2921 return indicatePessimisticFixpoint();
2922 const IRPosition &ArgPos = IRPosition::argument(*Arg);
2923 auto &ArgAA = A.getAAFor<AANoCapture>(*this, ArgPos);
2924 return clampStateAndIndicateChange(
2925 getState(),
2926 static_cast<const AANoCapture::StateType &>(ArgAA.getState()));
2927 }
2928
2929 /// See AbstractAttribute::trackStatistics()
2930 void trackStatistics() const override{STATS_DECLTRACK_CSARG_ATTR(nocapture)};
2931};
2932
2933/// NoCapture attribute for floating values.
2934struct AANoCaptureFloating final : AANoCaptureImpl {
2935 AANoCaptureFloating(const IRPosition &IRP) : AANoCaptureImpl(IRP) {}
2936
2937 /// See AbstractAttribute::trackStatistics()
2938 void trackStatistics() const override {
2939 STATS_DECLTRACK_FLOATING_ATTR(nocapture)
2940 }
2941};
2942
2943/// NoCapture attribute for function return value.
2944struct AANoCaptureReturned final : AANoCaptureImpl {
2945 AANoCaptureReturned(const IRPosition &IRP) : AANoCaptureImpl(IRP) {
2946 llvm_unreachable("NoCapture is not applicable to function returns!");
2947 }
2948
2949 /// See AbstractAttribute::initialize(...).
2950 void initialize(Attributor &A) override {
2951 llvm_unreachable("NoCapture is not applicable to function returns!");
2952 }
2953
2954 /// See AbstractAttribute::updateImpl(...).
2955 ChangeStatus updateImpl(Attributor &A) override {
2956 llvm_unreachable("NoCapture is not applicable to function returns!");
2957 }
2958
2959 /// See AbstractAttribute::trackStatistics()
2960 void trackStatistics() const override {}
2961};
2962
2963/// NoCapture attribute deduction for a call site return value.
2964struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
2965 AANoCaptureCallSiteReturned(const IRPosition &IRP) : AANoCaptureImpl(IRP) {}
2966
2967 /// See AbstractAttribute::trackStatistics()
2968 void trackStatistics() const override {
2969 STATS_DECLTRACK_CSRET_ATTR(nocapture)
2970 }
2971};
2972
Hideto Uenof2b9dc42019-09-07 07:03:05 +00002973/// ------------------ Value Simplify Attribute ----------------------------
2974struct AAValueSimplifyImpl : AAValueSimplify {
2975 AAValueSimplifyImpl(const IRPosition &IRP) : AAValueSimplify(IRP) {}
2976
2977 /// See AbstractAttribute::getAsStr().
2978 const std::string getAsStr() const override {
2979 return getAssumed() ? (getKnown() ? "simplified" : "maybe-simple")
2980 : "not-simple";
2981 }
2982
2983 /// See AbstractAttribute::trackStatistics()
2984 void trackStatistics() const override {}
2985
2986 /// See AAValueSimplify::getAssumedSimplifiedValue()
2987 Optional<Value *> getAssumedSimplifiedValue(Attributor &A) const override {
2988 if (!getAssumed())
2989 return const_cast<Value *>(&getAssociatedValue());
2990 return SimplifiedAssociatedValue;
2991 }
2992 void initialize(Attributor &A) override {}
2993
2994 /// Helper function for querying AAValueSimplify and updating candicate.
2995 /// \param QueryingValue Value trying to unify with SimplifiedValue
2996 /// \param AccumulatedSimplifiedValue Current simplification result.
2997 static bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA,
2998 Value &QueryingValue,
2999 Optional<Value *> &AccumulatedSimplifiedValue) {
3000 // FIXME: Add a typecast support.
3001
3002 auto &ValueSimpifyAA = A.getAAFor<AAValueSimplify>(
3003 QueryingAA, IRPosition::value(QueryingValue));
3004
3005 Optional<Value *> QueryingValueSimplified =
3006 ValueSimpifyAA.getAssumedSimplifiedValue(A);
3007
3008 if (!QueryingValueSimplified.hasValue())
3009 return true;
3010
3011 if (!QueryingValueSimplified.getValue())
3012 return false;
3013
3014 Value &QueryingValueSimplifiedUnwrapped =
3015 *QueryingValueSimplified.getValue();
3016
3017 if (isa<UndefValue>(QueryingValueSimplifiedUnwrapped))
3018 return true;
3019
3020 if (AccumulatedSimplifiedValue.hasValue())
3021 return AccumulatedSimplifiedValue == QueryingValueSimplified;
3022
3023 LLVM_DEBUG(dbgs() << "[Attributor][ValueSimplify] " << QueryingValue
3024 << " is assumed to be "
3025 << QueryingValueSimplifiedUnwrapped << "\n");
3026
3027 AccumulatedSimplifiedValue = QueryingValueSimplified;
3028 return true;
3029 }
3030
3031 /// See AbstractAttribute::manifest(...).
3032 ChangeStatus manifest(Attributor &A) override {
3033 ChangeStatus Changed = ChangeStatus::UNCHANGED;
3034
3035 if (!SimplifiedAssociatedValue.hasValue() ||
3036 !SimplifiedAssociatedValue.getValue())
3037 return Changed;
3038
3039 if (auto *C = dyn_cast<Constant>(SimplifiedAssociatedValue.getValue())) {
3040 // We can replace the AssociatedValue with the constant.
3041 Value &V = getAssociatedValue();
3042 if (!V.user_empty() && &V != C && V.getType() == C->getType()) {
3043 LLVM_DEBUG(dbgs() << "[Attributor][ValueSimplify] " << V << " -> " << *C
3044 << "\n");
3045 V.replaceAllUsesWith(C);
3046 Changed = ChangeStatus::CHANGED;
3047 }
3048 }
3049
3050 return Changed | AAValueSimplify::manifest(A);
3051 }
3052
3053protected:
3054 // An assumed simplified value. Initially, it is set to Optional::None, which
3055 // means that the value is not clear under current assumption. If in the
3056 // pessimistic state, getAssumedSimplifiedValue doesn't return this value but
3057 // returns orignal associated value.
3058 Optional<Value *> SimplifiedAssociatedValue;
3059};
3060
3061struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
3062 AAValueSimplifyArgument(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {}
3063
3064 /// See AbstractAttribute::updateImpl(...).
3065 ChangeStatus updateImpl(Attributor &A) override {
3066 bool HasValueBefore = SimplifiedAssociatedValue.hasValue();
3067
3068 auto PredForCallSite = [&](CallSite CS) {
3069 return checkAndUpdate(A, *this, *CS.getArgOperand(getArgNo()),
3070 SimplifiedAssociatedValue);
3071 };
3072
3073 if (!A.checkForAllCallSites(PredForCallSite, *this, true))
3074 return indicatePessimisticFixpoint();
3075
3076 // If a candicate was found in this update, return CHANGED.
3077 return HasValueBefore == SimplifiedAssociatedValue.hasValue()
3078 ? ChangeStatus::UNCHANGED
3079 : ChangeStatus ::CHANGED;
3080 }
3081
3082 /// See AbstractAttribute::trackStatistics()
3083 void trackStatistics() const override {
3084 STATS_DECLTRACK_ARG_ATTR(value_simplify)
3085 }
3086};
3087
3088struct AAValueSimplifyReturned : AAValueSimplifyImpl {
3089 AAValueSimplifyReturned(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {}
3090
3091 /// See AbstractAttribute::updateImpl(...).
3092 ChangeStatus updateImpl(Attributor &A) override {
3093 bool HasValueBefore = SimplifiedAssociatedValue.hasValue();
3094
3095 auto PredForReturned = [&](Value &V) {
3096 return checkAndUpdate(A, *this, V, SimplifiedAssociatedValue);
3097 };
3098
3099 if (!A.checkForAllReturnedValues(PredForReturned, *this))
3100 return indicatePessimisticFixpoint();
3101
3102 // If a candicate was found in this update, return CHANGED.
3103 return HasValueBefore == SimplifiedAssociatedValue.hasValue()
3104 ? ChangeStatus::UNCHANGED
3105 : ChangeStatus ::CHANGED;
3106 }
3107 /// See AbstractAttribute::trackStatistics()
3108 void trackStatistics() const override {
3109 STATS_DECLTRACK_FNRET_ATTR(value_simplify)
3110 }
3111};
3112
3113struct AAValueSimplifyFloating : AAValueSimplifyImpl {
3114 AAValueSimplifyFloating(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {}
3115
3116 /// See AbstractAttribute::initialize(...).
3117 void initialize(Attributor &A) override {
3118 Value &V = getAnchorValue();
3119
3120 // TODO: add other stuffs
3121 if (isa<Constant>(V) || isa<UndefValue>(V))
3122 indicatePessimisticFixpoint();
3123 }
3124
3125 /// See AbstractAttribute::updateImpl(...).
3126 ChangeStatus updateImpl(Attributor &A) override {
3127 bool HasValueBefore = SimplifiedAssociatedValue.hasValue();
3128
3129 auto VisitValueCB = [&](Value &V, BooleanState, bool Stripped) -> bool {
3130 auto &AA = A.getAAFor<AAValueSimplify>(*this, IRPosition::value(V));
3131 if (!Stripped && this == &AA) {
3132 // TODO: Look the instruction and check recursively.
3133 LLVM_DEBUG(
3134 dbgs() << "[Attributor][ValueSimplify] Can't be stripped more : "
3135 << V << "\n");
3136 indicatePessimisticFixpoint();
3137 return false;
3138 }
3139 return checkAndUpdate(A, *this, V, SimplifiedAssociatedValue);
3140 };
3141
3142 if (!genericValueTraversal<AAValueSimplify, BooleanState>(
3143 A, getIRPosition(), *this, static_cast<BooleanState &>(*this),
3144 VisitValueCB))
3145 return indicatePessimisticFixpoint();
3146
3147 // If a candicate was found in this update, return CHANGED.
3148
3149 return HasValueBefore == SimplifiedAssociatedValue.hasValue()
3150 ? ChangeStatus::UNCHANGED
3151 : ChangeStatus ::CHANGED;
3152 }
3153
3154 /// See AbstractAttribute::trackStatistics()
3155 void trackStatistics() const override {
3156 STATS_DECLTRACK_FLOATING_ATTR(value_simplify)
3157 }
3158};
3159
3160struct AAValueSimplifyFunction : AAValueSimplifyImpl {
3161 AAValueSimplifyFunction(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {}
3162
3163 /// See AbstractAttribute::initialize(...).
3164 void initialize(Attributor &A) override {
3165 SimplifiedAssociatedValue = &getAnchorValue();
3166 indicateOptimisticFixpoint();
3167 }
3168 /// See AbstractAttribute::initialize(...).
3169 ChangeStatus updateImpl(Attributor &A) override {
3170 llvm_unreachable(
3171 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
3172 }
3173 /// See AbstractAttribute::trackStatistics()
3174 void trackStatistics() const override {
3175 STATS_DECLTRACK_FN_ATTR(value_simplify)
3176 }
3177};
3178
3179struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
3180 AAValueSimplifyCallSite(const IRPosition &IRP)
3181 : AAValueSimplifyFunction(IRP) {}
3182 /// See AbstractAttribute::trackStatistics()
3183 void trackStatistics() const override {
3184 STATS_DECLTRACK_CS_ATTR(value_simplify)
3185 }
3186};
3187
3188struct AAValueSimplifyCallSiteReturned : AAValueSimplifyReturned {
3189 AAValueSimplifyCallSiteReturned(const IRPosition &IRP)
3190 : AAValueSimplifyReturned(IRP) {}
3191
3192 void trackStatistics() const override {
3193 STATS_DECLTRACK_CSRET_ATTR(value_simplify)
3194 }
3195};
3196struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
3197 AAValueSimplifyCallSiteArgument(const IRPosition &IRP)
3198 : AAValueSimplifyFloating(IRP) {}
3199
3200 void trackStatistics() const override {
3201 STATS_DECLTRACK_CSARG_ATTR(value_simplify)
3202 }
3203};
3204
Stefan Stipanovic431141c2019-09-15 21:47:41 +00003205/// ----------------------- Heap-To-Stack Conversion ---------------------------
3206struct AAHeapToStackImpl : public AAHeapToStack {
3207 AAHeapToStackImpl(const IRPosition &IRP) : AAHeapToStack(IRP) {}
3208
3209 const std::string getAsStr() const override {
3210 return "[H2S] Mallocs: " + std::to_string(MallocCalls.size());
3211 }
3212
3213 ChangeStatus manifest(Attributor &A) override {
3214 assert(getState().isValidState() &&
3215 "Attempted to manifest an invalid state!");
3216
3217 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
3218 Function *F = getAssociatedFunction();
3219 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
3220
3221 for (Instruction *MallocCall : MallocCalls) {
3222 // This malloc cannot be replaced.
3223 if (BadMallocCalls.count(MallocCall))
3224 continue;
3225
3226 for (Instruction *FreeCall : FreesForMalloc[MallocCall]) {
3227 LLVM_DEBUG(dbgs() << "H2S: Removing free call: " << *FreeCall << "\n");
3228 A.deleteAfterManifest(*FreeCall);
3229 HasChanged = ChangeStatus::CHANGED;
3230 }
3231
3232 LLVM_DEBUG(dbgs() << "H2S: Removing malloc call: " << *MallocCall
3233 << "\n");
3234
3235 Constant *Size;
3236 if (isCallocLikeFn(MallocCall, TLI)) {
3237 auto *Num = cast<ConstantInt>(MallocCall->getOperand(0));
3238 auto *SizeT = dyn_cast<ConstantInt>(MallocCall->getOperand(1));
3239 APInt TotalSize = SizeT->getValue() * Num->getValue();
3240 Size =
3241 ConstantInt::get(MallocCall->getOperand(0)->getType(), TotalSize);
3242 } else {
3243 Size = cast<ConstantInt>(MallocCall->getOperand(0));
3244 }
3245
3246 unsigned AS = cast<PointerType>(MallocCall->getType())->getAddressSpace();
3247 Instruction *AI = new AllocaInst(Type::getInt8Ty(F->getContext()), AS,
3248 Size, "", MallocCall->getNextNode());
3249
3250 if (AI->getType() != MallocCall->getType())
3251 AI = new BitCastInst(AI, MallocCall->getType(), "malloc_bc",
3252 AI->getNextNode());
3253
3254 MallocCall->replaceAllUsesWith(AI);
3255
3256 if (auto *II = dyn_cast<InvokeInst>(MallocCall)) {
3257 auto *NBB = II->getNormalDest();
3258 BranchInst::Create(NBB, MallocCall->getParent());
3259 A.deleteAfterManifest(*MallocCall);
3260 } else {
3261 A.deleteAfterManifest(*MallocCall);
3262 }
3263
3264 if (isCallocLikeFn(MallocCall, TLI)) {
3265 auto *BI = new BitCastInst(AI, MallocCall->getType(), "calloc_bc",
3266 AI->getNextNode());
3267 Value *Ops[] = {
3268 BI, ConstantInt::get(F->getContext(), APInt(8, 0, false)), Size,
3269 ConstantInt::get(Type::getInt1Ty(F->getContext()), false)};
3270
3271 Type *Tys[] = {BI->getType(), MallocCall->getOperand(0)->getType()};
3272 Module *M = F->getParent();
3273 Function *Fn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys);
3274 CallInst::Create(Fn, Ops, "", BI->getNextNode());
3275 }
3276 HasChanged = ChangeStatus::CHANGED;
3277 }
3278
3279 return HasChanged;
3280 }
3281
3282 /// Collection of all malloc calls in a function.
3283 SmallSetVector<Instruction *, 4> MallocCalls;
3284
3285 /// Collection of malloc calls that cannot be converted.
3286 DenseSet<const Instruction *> BadMallocCalls;
3287
3288 /// A map for each malloc call to the set of associated free calls.
3289 DenseMap<Instruction *, SmallPtrSet<Instruction *, 4>> FreesForMalloc;
3290
3291 ChangeStatus updateImpl(Attributor &A) override;
3292};
3293
3294ChangeStatus AAHeapToStackImpl::updateImpl(Attributor &A) {
3295 const Function *F = getAssociatedFunction();
3296 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
3297
3298 auto UsesCheck = [&](Instruction &I) {
3299 SmallPtrSet<const Use *, 8> Visited;
3300 SmallVector<const Use *, 8> Worklist;
3301
3302 for (Use &U : I.uses())
3303 Worklist.push_back(&U);
3304
3305 while (!Worklist.empty()) {
3306 const Use *U = Worklist.pop_back_val();
3307 if (!Visited.insert(U).second)
3308 continue;
3309
3310 auto *UserI = U->getUser();
3311
3312 if (isa<LoadInst>(UserI) || isa<StoreInst>(UserI))
3313 continue;
3314
3315 // NOTE: Right now, if a function that has malloc pointer as an argument
3316 // frees memory, we assume that the malloc pointer is freed.
3317
3318 // TODO: Add nofree callsite argument attribute to indicate that pointer
3319 // argument is not freed.
3320 if (auto *CB = dyn_cast<CallBase>(UserI)) {
3321 if (!CB->isArgOperand(U))
3322 continue;
3323
3324 if (CB->isLifetimeStartOrEnd())
3325 continue;
3326
3327 // Record malloc.
3328 if (isFreeCall(UserI, TLI)) {
3329 FreesForMalloc[&I].insert(
3330 cast<Instruction>(const_cast<User *>(UserI)));
3331 continue;
3332 }
3333
3334 // If a function does not free memory we are fine
3335 const auto &NoFreeAA =
3336 A.getAAFor<AANoFree>(*this, IRPosition::callsite_function(*CB));
3337
3338 unsigned ArgNo = U - CB->arg_begin();
3339 const auto &NoCaptureAA = A.getAAFor<AANoCapture>(
3340 *this, IRPosition::callsite_argument(*CB, ArgNo));
3341
3342 if (!NoCaptureAA.isAssumedNoCapture() || !NoFreeAA.isAssumedNoFree()) {
3343 LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n");
3344 return false;
3345 }
3346 continue;
3347 }
3348
3349 if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI)) {
3350 for (Use &U : UserI->uses())
3351 Worklist.push_back(&U);
3352 continue;
3353 }
3354
3355 // Unknown user.
3356 LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n");
3357 return false;
3358 }
3359 return true;
3360 };
3361
3362 auto MallocCallocCheck = [&](Instruction &I) {
3363 if (isMallocLikeFn(&I, TLI)) {
3364 if (auto *Size = dyn_cast<ConstantInt>(I.getOperand(0)))
3365 if (!Size->getValue().sle(MaxHeapToStackSize))
3366 return true;
3367 } else if (isCallocLikeFn(&I, TLI)) {
3368 bool Overflow = false;
3369 if (auto *Num = dyn_cast<ConstantInt>(I.getOperand(0)))
3370 if (auto *Size = dyn_cast<ConstantInt>(I.getOperand(1)))
3371 if (!(Size->getValue().umul_ov(Num->getValue(), Overflow))
3372 .sle(MaxHeapToStackSize))
3373 if (!Overflow)
3374 return true;
3375 } else {
3376 BadMallocCalls.insert(&I);
3377 return true;
3378 }
3379
3380 if (BadMallocCalls.count(&I))
3381 return true;
3382
3383 if (UsesCheck(I))
3384 MallocCalls.insert(&I);
3385 else
3386 BadMallocCalls.insert(&I);
3387 return true;
3388 };
3389
3390 size_t NumBadMallocs = BadMallocCalls.size();
3391
3392 A.checkForAllCallLikeInstructions(MallocCallocCheck, *this);
3393
3394 if (NumBadMallocs != BadMallocCalls.size())
3395 return ChangeStatus::CHANGED;
3396
3397 return ChangeStatus::UNCHANGED;
3398}
3399
3400struct AAHeapToStackFunction final : public AAHeapToStackImpl {
3401 AAHeapToStackFunction(const IRPosition &IRP) : AAHeapToStackImpl(IRP) {}
3402
3403 /// See AbstractAttribute::trackStatistics()
3404 void trackStatistics() const override {
3405 STATS_DECL(MallocCalls, Function,
3406 "Number of MallocCalls converted to allocas");
3407 BUILD_STAT_NAME(MallocCalls, Function) += MallocCalls.size();
3408 }
3409};
Benjamin Kramerdf4b9a32019-09-17 12:56:29 +00003410} // namespace
Stefan Stipanovic431141c2019-09-15 21:47:41 +00003411
Johannes Doerfertaade7822019-06-05 03:02:24 +00003412/// ----------------------------------------------------------------------------
3413/// Attributor
3414/// ----------------------------------------------------------------------------
3415
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00003416bool Attributor::isAssumedDead(const AbstractAttribute &AA,
3417 const AAIsDead *LivenessAA) {
3418 const Instruction *CtxI = AA.getIRPosition().getCtxI();
3419 if (!CtxI)
3420 return false;
3421
3422 if (!LivenessAA)
3423 LivenessAA =
Johannes Doerfert19b00432019-08-26 17:48:05 +00003424 &getAAFor<AAIsDead>(AA, IRPosition::function(*CtxI->getFunction()),
3425 /* TrackDependence */ false);
Stefan Stipanovic26121ae2019-08-20 23:16:57 +00003426
3427 // Don't check liveness for AAIsDead.
3428 if (&AA == LivenessAA)
3429 return false;
3430
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00003431 if (!LivenessAA->isAssumedDead(CtxI))
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00003432 return false;
3433
Johannes Doerfert19b00432019-08-26 17:48:05 +00003434 // We actually used liveness information so we have to record a dependence.
3435 recordDependence(*LivenessAA, AA);
3436
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00003437 return true;
3438}
3439
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003440bool Attributor::checkForAllCallSites(const function_ref<bool(CallSite)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00003441 const AbstractAttribute &QueryingAA,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00003442 bool RequireAllCallSites) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00003443 // We can try to determine information from
3444 // the call sites. However, this is only possible all call sites are known,
3445 // hence the function has internal linkage.
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003446 const IRPosition &IRP = QueryingAA.getIRPosition();
3447 const Function *AssociatedFunction = IRP.getAssociatedFunction();
3448 if (!AssociatedFunction)
3449 return false;
3450
3451 if (RequireAllCallSites && !AssociatedFunction->hasInternalLinkage()) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00003452 LLVM_DEBUG(
3453 dbgs()
Johannes Doerfert5304b722019-08-14 22:04:28 +00003454 << "[Attributor] Function " << AssociatedFunction->getName()
Hideto Ueno54869ec2019-07-15 06:49:04 +00003455 << " has no internal linkage, hence not all call sites are known\n");
3456 return false;
3457 }
3458
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003459 for (const Use &U : AssociatedFunction->uses()) {
Johannes Doerfertd98f9752019-08-21 21:48:56 +00003460 Instruction *I = dyn_cast<Instruction>(U.getUser());
3461 // TODO: Deal with abstract call sites here.
3462 if (!I)
3463 return false;
3464
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003465 Function *Caller = I->getFunction();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00003466
Johannes Doerfert19b00432019-08-26 17:48:05 +00003467 const auto &LivenessAA = getAAFor<AAIsDead>(
3468 QueryingAA, IRPosition::function(*Caller), /* TrackDependence */ false);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00003469
3470 // Skip dead calls.
Johannes Doerfert19b00432019-08-26 17:48:05 +00003471 if (LivenessAA.isAssumedDead(I)) {
3472 // We actually used liveness information so we have to record a
3473 // dependence.
3474 recordDependence(LivenessAA, QueryingAA);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00003475 continue;
Johannes Doerfert19b00432019-08-26 17:48:05 +00003476 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00003477
3478 CallSite CS(U.getUser());
Johannes Doerfertb0412e42019-09-04 16:16:13 +00003479 if (!CS || !CS.isCallee(&U)) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00003480 if (!RequireAllCallSites)
3481 continue;
3482
Johannes Doerfert5304b722019-08-14 22:04:28 +00003483 LLVM_DEBUG(dbgs() << "[Attributor] User " << *U.getUser()
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003484 << " is an invalid use of "
3485 << AssociatedFunction->getName() << "\n");
Hideto Ueno54869ec2019-07-15 06:49:04 +00003486 return false;
3487 }
3488
3489 if (Pred(CS))
3490 continue;
3491
Johannes Doerfert5304b722019-08-14 22:04:28 +00003492 LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for "
Hideto Ueno54869ec2019-07-15 06:49:04 +00003493 << *CS.getInstruction() << "\n");
3494 return false;
3495 }
3496
3497 return true;
3498}
3499
Johannes Doerfert14a04932019-08-07 22:27:24 +00003500bool Attributor::checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +00003501 const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)>
Johannes Doerfert14a04932019-08-07 22:27:24 +00003502 &Pred,
3503 const AbstractAttribute &QueryingAA) {
3504
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003505 const IRPosition &IRP = QueryingAA.getIRPosition();
3506 // Since we need to provide return instructions we have to have an exact
3507 // definition.
3508 const Function *AssociatedFunction = IRP.getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00003509 if (!AssociatedFunction)
Johannes Doerfert14a04932019-08-07 22:27:24 +00003510 return false;
3511
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003512 // If this is a call site query we use the call site specific return values
3513 // and liveness information.
Johannes Doerfert07a5c122019-08-28 14:09:14 +00003514 // TODO: use the function scope once we have call site AAReturnedValues.
3515 const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction);
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003516 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00003517 if (!AARetVal.getState().isValidState())
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003518 return false;
3519
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00003520 return AARetVal.checkForAllReturnedValuesAndReturnInsts(Pred);
Johannes Doerfert14a04932019-08-07 22:27:24 +00003521}
3522
3523bool Attributor::checkForAllReturnedValues(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003524 const function_ref<bool(Value &)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00003525 const AbstractAttribute &QueryingAA) {
3526
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003527 const IRPosition &IRP = QueryingAA.getIRPosition();
3528 const Function *AssociatedFunction = IRP.getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00003529 if (!AssociatedFunction)
Johannes Doerfert14a04932019-08-07 22:27:24 +00003530 return false;
3531
Johannes Doerfert07a5c122019-08-28 14:09:14 +00003532 // TODO: use the function scope once we have call site AAReturnedValues.
3533 const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction);
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003534 const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP);
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00003535 if (!AARetVal.getState().isValidState())
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003536 return false;
3537
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00003538 return AARetVal.checkForAllReturnedValuesAndReturnInsts(
Johannes Doerfert695089e2019-08-23 15:23:49 +00003539 [&](Value &RV, const SmallSetVector<ReturnInst *, 4> &) {
Johannes Doerfertdef99282019-08-14 21:29:37 +00003540 return Pred(RV);
3541 });
Johannes Doerfert14a04932019-08-07 22:27:24 +00003542}
3543
Johannes Doerfert3ab9e8b2019-09-17 10:52:41 +00003544static bool
3545checkForAllInstructionsImpl(InformationCache::OpcodeInstMapTy &OpcodeInstMap,
3546 const function_ref<bool(Instruction &)> &Pred,
3547 const AAIsDead *LivenessAA, bool &AnyDead,
3548 const ArrayRef<unsigned> &Opcodes) {
3549 for (unsigned Opcode : Opcodes) {
3550 for (Instruction *I : OpcodeInstMap[Opcode]) {
3551 // Skip dead instructions.
3552 if (LivenessAA && LivenessAA->isAssumedDead(I)) {
3553 AnyDead = true;
3554 continue;
3555 }
3556
3557 if (!Pred(*I))
3558 return false;
3559 }
3560 }
3561 return true;
3562}
3563
Johannes Doerfertd0f64002019-08-06 00:32:43 +00003564bool Attributor::checkForAllInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003565 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00003566 const AbstractAttribute &QueryingAA, const ArrayRef<unsigned> &Opcodes) {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00003567
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003568 const IRPosition &IRP = QueryingAA.getIRPosition();
3569 // Since we need to provide instructions we have to have an exact definition.
3570 const Function *AssociatedFunction = IRP.getAssociatedFunction();
Johannes Doerfertb0412e42019-09-04 16:16:13 +00003571 if (!AssociatedFunction)
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003572 return false;
Johannes Doerfertd0f64002019-08-06 00:32:43 +00003573
Johannes Doerfert07a5c122019-08-28 14:09:14 +00003574 // TODO: use the function scope once we have call site AAReturnedValues.
3575 const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction);
Johannes Doerfert19b00432019-08-26 17:48:05 +00003576 const auto &LivenessAA =
3577 getAAFor<AAIsDead>(QueryingAA, QueryIRP, /* TrackDependence */ false);
3578 bool AnyDead = false;
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003579
3580 auto &OpcodeInstMap =
3581 InfoCache.getOpcodeInstMapForFunction(*AssociatedFunction);
Johannes Doerfert3ab9e8b2019-09-17 10:52:41 +00003582 if (!checkForAllInstructionsImpl(OpcodeInstMap, Pred, &LivenessAA, AnyDead, Opcodes))
3583 return false;
Johannes Doerfertd0f64002019-08-06 00:32:43 +00003584
Johannes Doerfert19b00432019-08-26 17:48:05 +00003585 // If we actually used liveness information so we have to record a dependence.
3586 if (AnyDead)
3587 recordDependence(LivenessAA, QueryingAA);
3588
Johannes Doerfertd0f64002019-08-06 00:32:43 +00003589 return true;
3590}
3591
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00003592bool Attributor::checkForAllReadWriteInstructions(
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003593 const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfertece81902019-08-12 22:05:53 +00003594 AbstractAttribute &QueryingAA) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00003595
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003596 const Function *AssociatedFunction =
3597 QueryingAA.getIRPosition().getAssociatedFunction();
3598 if (!AssociatedFunction)
3599 return false;
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00003600
Johannes Doerfert07a5c122019-08-28 14:09:14 +00003601 // TODO: use the function scope once we have call site AAReturnedValues.
3602 const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction);
3603 const auto &LivenessAA =
3604 getAAFor<AAIsDead>(QueryingAA, QueryIRP, /* TrackDependence */ false);
Johannes Doerfert19b00432019-08-26 17:48:05 +00003605 bool AnyDead = false;
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003606
3607 for (Instruction *I :
3608 InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00003609 // Skip dead instructions.
Johannes Doerfert19b00432019-08-26 17:48:05 +00003610 if (LivenessAA.isAssumedDead(I)) {
3611 AnyDead = true;
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00003612 continue;
Johannes Doerfert19b00432019-08-26 17:48:05 +00003613 }
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00003614
3615 if (!Pred(*I))
3616 return false;
3617 }
3618
Johannes Doerfert19b00432019-08-26 17:48:05 +00003619 // If we actually used liveness information so we have to record a dependence.
3620 if (AnyDead)
3621 recordDependence(LivenessAA, QueryingAA);
3622
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00003623 return true;
3624}
3625
Johannes Doerfert2f622062019-09-04 16:35:20 +00003626ChangeStatus Attributor::run(Module &M) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00003627 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
3628 << AllAbstractAttributes.size()
3629 << " abstract attributes.\n");
3630
Stefan Stipanovic53605892019-06-27 11:27:54 +00003631 // Now that all abstract attributes are collected and initialized we start
3632 // the abstract analysis.
Johannes Doerfertaade7822019-06-05 03:02:24 +00003633
3634 unsigned IterationCounter = 1;
3635
3636 SmallVector<AbstractAttribute *, 64> ChangedAAs;
3637 SetVector<AbstractAttribute *> Worklist;
3638 Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
3639
Johannes Doerfertf7ca0fe2019-08-28 16:58:52 +00003640 bool RecomputeDependences = false;
3641
Johannes Doerfertaade7822019-06-05 03:02:24 +00003642 do {
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00003643 // Remember the size to determine new attributes.
3644 size_t NumAAs = AllAbstractAttributes.size();
Johannes Doerfertaade7822019-06-05 03:02:24 +00003645 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
3646 << ", Worklist size: " << Worklist.size() << "\n");
3647
Johannes Doerfertf7ca0fe2019-08-28 16:58:52 +00003648 // If dependences (=QueryMap) are recomputed we have to look at all abstract
3649 // attributes again, regardless of what changed in the last iteration.
3650 if (RecomputeDependences) {
3651 LLVM_DEBUG(
3652 dbgs() << "[Attributor] Run all AAs to recompute dependences\n");
3653 QueryMap.clear();
3654 ChangedAAs.clear();
3655 Worklist.insert(AllAbstractAttributes.begin(),
3656 AllAbstractAttributes.end());
3657 }
3658
Johannes Doerfertaade7822019-06-05 03:02:24 +00003659 // Add all abstract attributes that are potentially dependent on one that
3660 // changed to the work list.
3661 for (AbstractAttribute *ChangedAA : ChangedAAs) {
3662 auto &QuerriedAAs = QueryMap[ChangedAA];
3663 Worklist.insert(QuerriedAAs.begin(), QuerriedAAs.end());
3664 }
3665
Johannes Doerfertb504eb82019-08-26 18:55:47 +00003666 LLVM_DEBUG(dbgs() << "[Attributor] #Iteration: " << IterationCounter
3667 << ", Worklist+Dependent size: " << Worklist.size()
3668 << "\n");
3669
Johannes Doerfertaade7822019-06-05 03:02:24 +00003670 // Reset the changed set.
3671 ChangedAAs.clear();
3672
3673 // Update all abstract attribute in the work list and record the ones that
3674 // changed.
3675 for (AbstractAttribute *AA : Worklist)
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00003676 if (!isAssumedDead(*AA, nullptr))
3677 if (AA->update(*this) == ChangeStatus::CHANGED)
3678 ChangedAAs.push_back(AA);
Johannes Doerfertaade7822019-06-05 03:02:24 +00003679
Johannes Doerfertf7ca0fe2019-08-28 16:58:52 +00003680 // Check if we recompute the dependences in the next iteration.
3681 RecomputeDependences = (DepRecomputeInterval > 0 &&
3682 IterationCounter % DepRecomputeInterval == 0);
3683
Johannes Doerfert9543f142019-08-23 15:24:57 +00003684 // Add attributes to the changed set if they have been created in the last
3685 // iteration.
3686 ChangedAAs.append(AllAbstractAttributes.begin() + NumAAs,
3687 AllAbstractAttributes.end());
3688
Johannes Doerfertaade7822019-06-05 03:02:24 +00003689 // Reset the work list and repopulate with the changed abstract attributes.
3690 // Note that dependent ones are added above.
3691 Worklist.clear();
3692 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
3693
Johannes Doerfertbf112132019-08-29 01:29:44 +00003694 } while (!Worklist.empty() && (IterationCounter++ < MaxFixpointIterations ||
3695 VerifyMaxFixpointIterations));
Johannes Doerfertf7ca0fe2019-08-28 16:58:52 +00003696
Johannes Doerfertaade7822019-06-05 03:02:24 +00003697 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
3698 << IterationCounter << "/" << MaxFixpointIterations
3699 << " iterations\n");
3700
Johannes Doerfertbf112132019-08-29 01:29:44 +00003701 size_t NumFinalAAs = AllAbstractAttributes.size();
Johannes Doerfertb504eb82019-08-26 18:55:47 +00003702
Johannes Doerfertaade7822019-06-05 03:02:24 +00003703 bool FinishedAtFixpoint = Worklist.empty();
3704
3705 // Reset abstract arguments not settled in a sound fixpoint by now. This
3706 // happens when we stopped the fixpoint iteration early. Note that only the
3707 // ones marked as "changed" *and* the ones transitively depending on them
3708 // need to be reverted to a pessimistic state. Others might not be in a
3709 // fixpoint state but we can use the optimistic results for them anyway.
3710 SmallPtrSet<AbstractAttribute *, 32> Visited;
3711 for (unsigned u = 0; u < ChangedAAs.size(); u++) {
3712 AbstractAttribute *ChangedAA = ChangedAAs[u];
3713 if (!Visited.insert(ChangedAA).second)
3714 continue;
3715
3716 AbstractState &State = ChangedAA->getState();
3717 if (!State.isAtFixpoint()) {
3718 State.indicatePessimisticFixpoint();
3719
3720 NumAttributesTimedOut++;
3721 }
3722
3723 auto &QuerriedAAs = QueryMap[ChangedAA];
3724 ChangedAAs.append(QuerriedAAs.begin(), QuerriedAAs.end());
3725 }
3726
3727 LLVM_DEBUG({
3728 if (!Visited.empty())
3729 dbgs() << "\n[Attributor] Finalized " << Visited.size()
3730 << " abstract attributes.\n";
3731 });
3732
3733 unsigned NumManifested = 0;
3734 unsigned NumAtFixpoint = 0;
3735 ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
3736 for (AbstractAttribute *AA : AllAbstractAttributes) {
3737 AbstractState &State = AA->getState();
3738
3739 // If there is not already a fixpoint reached, we can now take the
3740 // optimistic state. This is correct because we enforced a pessimistic one
3741 // on abstract attributes that were transitively dependent on a changed one
3742 // already above.
3743 if (!State.isAtFixpoint())
3744 State.indicateOptimisticFixpoint();
3745
3746 // If the state is invalid, we do not try to manifest it.
3747 if (!State.isValidState())
3748 continue;
3749
Johannes Doerfert9a1a1f92019-08-14 21:25:08 +00003750 // Skip dead code.
3751 if (isAssumedDead(*AA, nullptr))
3752 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +00003753 // Manifest the state and record if we changed the IR.
3754 ChangeStatus LocalChange = AA->manifest(*this);
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00003755 if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled())
3756 AA->trackStatistics();
3757
Johannes Doerfertaade7822019-06-05 03:02:24 +00003758 ManifestChange = ManifestChange | LocalChange;
3759
3760 NumAtFixpoint++;
3761 NumManifested += (LocalChange == ChangeStatus::CHANGED);
3762 }
3763
3764 (void)NumManifested;
3765 (void)NumAtFixpoint;
3766 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
3767 << " arguments while " << NumAtFixpoint
3768 << " were in a valid fixpoint state\n");
3769
3770 // If verification is requested, we finished this run at a fixpoint, and the
3771 // IR was changed, we re-run the whole fixpoint analysis, starting at
3772 // re-initialization of the arguments. This re-run should not result in an IR
3773 // change. Though, the (virtual) state of attributes at the end of the re-run
3774 // might be more optimistic than the known state or the IR state if the better
3775 // state cannot be manifested.
3776 if (VerifyAttributor && FinishedAtFixpoint &&
3777 ManifestChange == ChangeStatus::CHANGED) {
3778 VerifyAttributor = false;
Johannes Doerfert2f622062019-09-04 16:35:20 +00003779 ChangeStatus VerifyStatus = run(M);
Johannes Doerfertaade7822019-06-05 03:02:24 +00003780 if (VerifyStatus != ChangeStatus::UNCHANGED)
3781 llvm_unreachable(
3782 "Attributor verification failed, re-run did result in an IR change "
3783 "even after a fixpoint was reached in the original run. (False "
3784 "positives possible!)");
3785 VerifyAttributor = true;
3786 }
3787
3788 NumAttributesManifested += NumManifested;
3789 NumAttributesValidFixpoint += NumAtFixpoint;
3790
Fangrui Songf1826172019-08-20 07:21:43 +00003791 (void)NumFinalAAs;
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00003792 assert(
3793 NumFinalAAs == AllAbstractAttributes.size() &&
3794 "Expected the final number of abstract attributes to remain unchanged!");
Johannes Doerfert39681e72019-08-27 04:57:54 +00003795
3796 // Delete stuff at the end to avoid invalid references and a nice order.
Johannes Doerfert2f622062019-09-04 16:35:20 +00003797 {
3798 LLVM_DEBUG(dbgs() << "\n[Attributor] Delete at least "
3799 << ToBeDeletedFunctions.size() << " functions and "
3800 << ToBeDeletedBlocks.size() << " blocks and "
3801 << ToBeDeletedInsts.size() << " instructions\n");
3802 for (Instruction *I : ToBeDeletedInsts) {
3803 if (!I->use_empty())
3804 I->replaceAllUsesWith(UndefValue::get(I->getType()));
3805 I->eraseFromParent();
3806 }
Johannes Doerfertb19cd272019-09-03 20:42:16 +00003807
Johannes Doerfert2f622062019-09-04 16:35:20 +00003808 if (unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) {
3809 SmallVector<BasicBlock *, 8> ToBeDeletedBBs;
3810 ToBeDeletedBBs.reserve(NumDeadBlocks);
3811 ToBeDeletedBBs.append(ToBeDeletedBlocks.begin(), ToBeDeletedBlocks.end());
3812 DeleteDeadBlocks(ToBeDeletedBBs);
3813 STATS_DECLTRACK(AAIsDead, BasicBlock,
3814 "Number of dead basic blocks deleted.");
3815 }
Johannes Doerfertb19cd272019-09-03 20:42:16 +00003816
Johannes Doerfert2f622062019-09-04 16:35:20 +00003817 STATS_DECL(AAIsDead, Function, "Number of dead functions deleted.");
3818 for (Function *Fn : ToBeDeletedFunctions) {
3819 Fn->replaceAllUsesWith(UndefValue::get(Fn->getType()));
3820 Fn->eraseFromParent();
3821 STATS_TRACK(AAIsDead, Function);
3822 }
3823
3824 // Identify dead internal functions and delete them. This happens outside
3825 // the other fixpoint analysis as we might treat potentially dead functions
3826 // as live to lower the number of iterations. If they happen to be dead, the
3827 // below fixpoint loop will identify and eliminate them.
3828 SmallVector<Function *, 8> InternalFns;
3829 for (Function &F : M)
3830 if (F.hasInternalLinkage())
3831 InternalFns.push_back(&F);
3832
3833 bool FoundDeadFn = true;
3834 while (FoundDeadFn) {
3835 FoundDeadFn = false;
3836 for (unsigned u = 0, e = InternalFns.size(); u < e; ++u) {
3837 Function *F = InternalFns[u];
3838 if (!F)
3839 continue;
3840
3841 const auto *LivenessAA =
3842 lookupAAFor<AAIsDead>(IRPosition::function(*F));
3843 if (LivenessAA &&
3844 !checkForAllCallSites([](CallSite CS) { return false; },
3845 *LivenessAA, true))
3846 continue;
3847
3848 STATS_TRACK(AAIsDead, Function);
3849 F->replaceAllUsesWith(UndefValue::get(F->getType()));
3850 F->eraseFromParent();
3851 InternalFns[u] = nullptr;
3852 FoundDeadFn = true;
3853 }
3854 }
Johannes Doerfert39681e72019-08-27 04:57:54 +00003855 }
3856
Johannes Doerfertbf112132019-08-29 01:29:44 +00003857 if (VerifyMaxFixpointIterations &&
3858 IterationCounter != MaxFixpointIterations) {
3859 errs() << "\n[Attributor] Fixpoint iteration done after: "
3860 << IterationCounter << "/" << MaxFixpointIterations
3861 << " iterations\n";
3862 llvm_unreachable("The fixpoint was not reached with exactly the number of "
3863 "specified iterations!");
3864 }
3865
Johannes Doerfertaade7822019-06-05 03:02:24 +00003866 return ManifestChange;
3867}
3868
Johannes Doerfert3ab9e8b2019-09-17 10:52:41 +00003869void Attributor::initializeInformationCache(Function &F) {
3870
3871 // Walk all instructions to find interesting instructions that might be
3872 // queried by abstract attributes during their initialization or update.
3873 // This has to happen before we create attributes.
3874 auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
3875 auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
3876
3877 for (Instruction &I : instructions(&F)) {
3878 bool IsInterestingOpcode = false;
3879
3880 // To allow easy access to all instructions in a function with a given
3881 // opcode we store them in the InfoCache. As not all opcodes are interesting
3882 // to concrete attributes we only cache the ones that are as identified in
3883 // the following switch.
3884 // Note: There are no concrete attributes now so this is initially empty.
3885 switch (I.getOpcode()) {
3886 default:
3887 assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) &&
3888 "New call site/base instruction type needs to be known int the "
3889 "Attributor.");
3890 break;
3891 case Instruction::Load:
3892 // The alignment of a pointer is interesting for loads.
3893 case Instruction::Store:
3894 // The alignment of a pointer is interesting for stores.
3895 case Instruction::Call:
3896 case Instruction::CallBr:
3897 case Instruction::Invoke:
3898 case Instruction::CleanupRet:
3899 case Instruction::CatchSwitch:
3900 case Instruction::Resume:
3901 case Instruction::Ret:
3902 IsInterestingOpcode = true;
3903 }
3904 if (IsInterestingOpcode)
3905 InstOpcodeMap[I.getOpcode()].push_back(&I);
3906 if (I.mayReadOrWriteMemory())
3907 ReadOrWriteInsts.push_back(&I);
3908 }
3909}
3910
Hideto Ueno3bb5cbc2019-09-17 05:45:18 +00003911void Attributor::identifyDefaultAbstractAttributes(Function &F) {
Johannes Doerfert2f622062019-09-04 16:35:20 +00003912 if (!VisitedFunctions.insert(&F).second)
3913 return;
Johannes Doerfertaade7822019-06-05 03:02:24 +00003914
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003915 IRPosition FPos = IRPosition::function(F);
3916
Johannes Doerfert305b9612019-08-04 18:40:01 +00003917 // Check for dead BasicBlocks in every function.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00003918 // We need dead instruction detection because we do not want to deal with
3919 // broken IR in which SSA rules do not apply.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003920 getOrCreateAAFor<AAIsDead>(FPos);
Johannes Doerfert305b9612019-08-04 18:40:01 +00003921
3922 // Every function might be "will-return".
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003923 getOrCreateAAFor<AAWillReturn>(FPos);
Johannes Doerfert305b9612019-08-04 18:40:01 +00003924
Stefan Stipanovic53605892019-06-27 11:27:54 +00003925 // Every function can be nounwind.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003926 getOrCreateAAFor<AANoUnwind>(FPos);
Stefan Stipanovic53605892019-06-27 11:27:54 +00003927
Stefan Stipanovic06263672019-07-11 21:37:40 +00003928 // Every function might be marked "nosync"
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003929 getOrCreateAAFor<AANoSync>(FPos);
Stefan Stipanovic06263672019-07-11 21:37:40 +00003930
Hideto Ueno65bbaf92019-07-12 17:38:51 +00003931 // Every function might be "no-free".
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003932 getOrCreateAAFor<AANoFree>(FPos);
Hideto Ueno65bbaf92019-07-12 17:38:51 +00003933
Johannes Doerferte83f3032019-08-05 23:22:05 +00003934 // Every function might be "no-return".
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003935 getOrCreateAAFor<AANoReturn>(FPos);
Johannes Doerferte83f3032019-08-05 23:22:05 +00003936
Stefan Stipanovic431141c2019-09-15 21:47:41 +00003937 // Every function might be applicable for Heap-To-Stack conversion.
3938 if (EnableHeapToStack)
3939 getOrCreateAAFor<AAHeapToStack>(FPos);
3940
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00003941 // Return attributes are only appropriate if the return type is non void.
3942 Type *ReturnType = F.getReturnType();
3943 if (!ReturnType->isVoidTy()) {
3944 // Argument attribute "returned" --- Create only one per function even
3945 // though it is an argument attribute.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003946 getOrCreateAAFor<AAReturnedValues>(FPos);
Hideto Ueno54869ec2019-07-15 06:49:04 +00003947
Hideto Uenof2b9dc42019-09-07 07:03:05 +00003948 IRPosition RetPos = IRPosition::returned(F);
3949
3950 // Every function might be simplified.
3951 getOrCreateAAFor<AAValueSimplify>(RetPos);
3952
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00003953 if (ReturnType->isPointerTy()) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00003954
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00003955 // Every function with pointer return type might be marked align.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003956 getOrCreateAAFor<AAAlign>(RetPos);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00003957
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00003958 // Every function with pointer return type might be marked nonnull.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003959 getOrCreateAAFor<AANonNull>(RetPos);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00003960
3961 // Every function with pointer return type might be marked noalias.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003962 getOrCreateAAFor<AANoAlias>(RetPos);
Hideto Ueno19c07af2019-07-23 08:16:17 +00003963
3964 // Every function with pointer return type might be marked
3965 // dereferenceable.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003966 getOrCreateAAFor<AADereferenceable>(RetPos);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00003967 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00003968 }
3969
Hideto Ueno54869ec2019-07-15 06:49:04 +00003970 for (Argument &Arg : F.args()) {
Hideto Uenof2b9dc42019-09-07 07:03:05 +00003971 IRPosition ArgPos = IRPosition::argument(Arg);
3972
3973 // Every argument might be simplified.
3974 getOrCreateAAFor<AAValueSimplify>(ArgPos);
3975
Hideto Ueno19c07af2019-07-23 08:16:17 +00003976 if (Arg.getType()->isPointerTy()) {
3977 // Every argument with pointer type might be marked nonnull.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003978 getOrCreateAAFor<AANonNull>(ArgPos);
Hideto Ueno19c07af2019-07-23 08:16:17 +00003979
Hideto Uenocbab3342019-08-29 05:52:00 +00003980 // Every argument with pointer type might be marked noalias.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003981 getOrCreateAAFor<AANoAlias>(ArgPos);
Hideto Uenocbab3342019-08-29 05:52:00 +00003982
Hideto Ueno19c07af2019-07-23 08:16:17 +00003983 // Every argument with pointer type might be marked dereferenceable.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003984 getOrCreateAAFor<AADereferenceable>(ArgPos);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00003985
3986 // Every argument with pointer type might be marked align.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003987 getOrCreateAAFor<AAAlign>(ArgPos);
Johannes Doerfert7516a5e2019-09-03 20:37:24 +00003988
3989 // Every argument with pointer type might be marked nocapture.
Johannes Doerfert97fd5822019-09-04 16:26:20 +00003990 getOrCreateAAFor<AANoCapture>(ArgPos);
Hideto Ueno19c07af2019-07-23 08:16:17 +00003991 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00003992 }
3993
Johannes Doerfert3ab9e8b2019-09-17 10:52:41 +00003994 auto CallSitePred = [&](Instruction &I) -> bool {
Hideto Ueno54869ec2019-07-15 06:49:04 +00003995 CallSite CS(&I);
Johannes Doerfert3ab9e8b2019-09-17 10:52:41 +00003996 if (CS.getCalledFunction()) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00003997 for (int i = 0, e = CS.getCalledFunction()->arg_size(); i < e; i++) {
Hideto Uenof2b9dc42019-09-07 07:03:05 +00003998
3999 IRPosition CSArgPos = IRPosition::callsite_argument(CS, i);
4000
4001 // Call site argument might be simplified.
4002 getOrCreateAAFor<AAValueSimplify>(CSArgPos);
4003
Hideto Ueno54869ec2019-07-15 06:49:04 +00004004 if (!CS.getArgument(i)->getType()->isPointerTy())
4005 continue;
4006
4007 // Call site argument attribute "non-null".
Johannes Doerfert97fd5822019-09-04 16:26:20 +00004008 getOrCreateAAFor<AANonNull>(CSArgPos);
Hideto Ueno19c07af2019-07-23 08:16:17 +00004009
Hideto Uenocbab3342019-08-29 05:52:00 +00004010 // Call site argument attribute "no-alias".
Johannes Doerfert97fd5822019-09-04 16:26:20 +00004011 getOrCreateAAFor<AANoAlias>(CSArgPos);
Hideto Uenocbab3342019-08-29 05:52:00 +00004012
Hideto Ueno19c07af2019-07-23 08:16:17 +00004013 // Call site argument attribute "dereferenceable".
Johannes Doerfert97fd5822019-09-04 16:26:20 +00004014 getOrCreateAAFor<AADereferenceable>(CSArgPos);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00004015
4016 // Call site argument attribute "align".
Johannes Doerfert97fd5822019-09-04 16:26:20 +00004017 getOrCreateAAFor<AAAlign>(CSArgPos);
Hideto Ueno54869ec2019-07-15 06:49:04 +00004018 }
4019 }
Johannes Doerfert3ab9e8b2019-09-17 10:52:41 +00004020 return true;
4021 };
4022
4023 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
4024 bool Success, AnyDead = false;
4025 Success = checkForAllInstructionsImpl(
4026 OpcodeInstMap, CallSitePred, nullptr, AnyDead,
4027 {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
4028 (unsigned)Instruction::Call});
4029 (void)Success;
4030 assert(Success && !AnyDead && "Expected the check call to be successful!");
4031
4032 auto LoadStorePred = [&](Instruction &I) -> bool {
4033 if (isa<LoadInst>(I))
4034 getOrCreateAAFor<AAAlign>(
4035 IRPosition::value(*cast<LoadInst>(I).getPointerOperand()));
4036 else
4037 getOrCreateAAFor<AAAlign>(
4038 IRPosition::value(*cast<StoreInst>(I).getPointerOperand()));
4039 return true;
4040 };
4041 Success = checkForAllInstructionsImpl(
4042 OpcodeInstMap, LoadStorePred, nullptr, AnyDead,
4043 {(unsigned)Instruction::Load, (unsigned)Instruction::Store});
4044 (void)Success;
4045 assert(Success && !AnyDead && "Expected the check call to be successful!");
Johannes Doerfertaade7822019-06-05 03:02:24 +00004046}
4047
4048/// Helpers to ease debugging through output streams and print calls.
4049///
4050///{
4051raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
4052 return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
4053}
4054
Johannes Doerfertfb69f762019-08-05 23:32:31 +00004055raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00004056 switch (AP) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00004057 case IRPosition::IRP_INVALID:
4058 return OS << "inv";
4059 case IRPosition::IRP_FLOAT:
4060 return OS << "flt";
4061 case IRPosition::IRP_RETURNED:
4062 return OS << "fn_ret";
4063 case IRPosition::IRP_CALL_SITE_RETURNED:
4064 return OS << "cs_ret";
4065 case IRPosition::IRP_FUNCTION:
4066 return OS << "fn";
4067 case IRPosition::IRP_CALL_SITE:
4068 return OS << "cs";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00004069 case IRPosition::IRP_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00004070 return OS << "arg";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00004071 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00004072 return OS << "cs_arg";
Johannes Doerfertaade7822019-06-05 03:02:24 +00004073 }
4074 llvm_unreachable("Unknown attribute position!");
4075}
4076
Johannes Doerfertfb69f762019-08-05 23:32:31 +00004077raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) {
Johannes Doerfert710ebb02019-08-14 21:18:01 +00004078 const Value &AV = Pos.getAssociatedValue();
4079 return OS << "{" << Pos.getPositionKind() << ":" << AV.getName() << " ["
Johannes Doerfertfb69f762019-08-05 23:32:31 +00004080 << Pos.getAnchorValue().getName() << "@" << Pos.getArgNo() << "]}";
4081}
4082
Johannes Doerfertacc80792019-08-12 22:07:34 +00004083raw_ostream &llvm::operator<<(raw_ostream &OS, const IntegerState &S) {
4084 return OS << "(" << S.getKnown() << "-" << S.getAssumed() << ")"
4085 << static_cast<const AbstractState &>(S);
4086}
4087
Johannes Doerfertaade7822019-06-05 03:02:24 +00004088raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
4089 return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
4090}
4091
4092raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
4093 AA.print(OS);
4094 return OS;
4095}
4096
4097void AbstractAttribute::print(raw_ostream &OS) const {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00004098 OS << "[P: " << getIRPosition() << "][" << getAsStr() << "][S: " << getState()
4099 << "]";
Johannes Doerfertaade7822019-06-05 03:02:24 +00004100}
4101///}
4102
4103/// ----------------------------------------------------------------------------
4104/// Pass (Manager) Boilerplate
4105/// ----------------------------------------------------------------------------
4106
Hideto Ueno3bb5cbc2019-09-17 05:45:18 +00004107static bool runAttributorOnModule(Module &M, AnalysisGetter &AG) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00004108 if (DisableAttributor)
4109 return false;
4110
4111 LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << M.size()
4112 << " functions.\n");
4113
4114 // Create an Attributor and initially empty information cache that is filled
4115 // while we identify default attribute opportunities.
Hideto Ueno3bb5cbc2019-09-17 05:45:18 +00004116 InformationCache InfoCache(M.getDataLayout(), AG);
Johannes Doerfertf7ca0fe2019-08-28 16:58:52 +00004117 Attributor A(InfoCache, DepRecInterval);
Johannes Doerfertaade7822019-06-05 03:02:24 +00004118
Johannes Doerfert3ab9e8b2019-09-17 10:52:41 +00004119 for (Function &F : M)
4120 A.initializeInformationCache(F);
4121
Johannes Doerfertaade7822019-06-05 03:02:24 +00004122 for (Function &F : M) {
Johannes Doerfertb0412e42019-09-04 16:16:13 +00004123 if (F.hasExactDefinition())
4124 NumFnWithExactDefinition++;
4125 else
Johannes Doerfertaade7822019-06-05 03:02:24 +00004126 NumFnWithoutExactDefinition++;
Johannes Doerfertaade7822019-06-05 03:02:24 +00004127
4128 // For now we ignore naked and optnone functions.
4129 if (F.hasFnAttribute(Attribute::Naked) ||
4130 F.hasFnAttribute(Attribute::OptimizeNone))
4131 continue;
4132
Johannes Doerfert2f622062019-09-04 16:35:20 +00004133 // We look at internal functions only on-demand but if any use is not a
4134 // direct call, we have to do it eagerly.
4135 if (F.hasInternalLinkage()) {
4136 if (llvm::all_of(F.uses(), [](const Use &U) {
4137 return ImmutableCallSite(U.getUser()) &&
4138 ImmutableCallSite(U.getUser()).isCallee(&U);
4139 }))
4140 continue;
4141 }
4142
Johannes Doerfertaade7822019-06-05 03:02:24 +00004143 // Populate the Attributor with abstract attribute opportunities in the
4144 // function and the information cache with IR information.
Hideto Ueno3bb5cbc2019-09-17 05:45:18 +00004145 A.identifyDefaultAbstractAttributes(F);
Johannes Doerfertaade7822019-06-05 03:02:24 +00004146 }
4147
Johannes Doerfert2f622062019-09-04 16:35:20 +00004148 return A.run(M) == ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +00004149}
4150
4151PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
Stefan Stipanovic431141c2019-09-15 21:47:41 +00004152 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
4153
Hideto Ueno3bb5cbc2019-09-17 05:45:18 +00004154 AnalysisGetter AG(FAM);
4155 if (runAttributorOnModule(M, AG)) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00004156 // FIXME: Think about passes we will preserve and add them here.
4157 return PreservedAnalyses::none();
4158 }
4159 return PreservedAnalyses::all();
4160}
4161
4162namespace {
4163
4164struct AttributorLegacyPass : public ModulePass {
4165 static char ID;
4166
4167 AttributorLegacyPass() : ModulePass(ID) {
4168 initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry());
4169 }
4170
4171 bool runOnModule(Module &M) override {
4172 if (skipModule(M))
4173 return false;
Stefan Stipanovic431141c2019-09-15 21:47:41 +00004174
Hideto Ueno3bb5cbc2019-09-17 05:45:18 +00004175 AnalysisGetter AG;
4176 return runAttributorOnModule(M, AG);
Johannes Doerfertaade7822019-06-05 03:02:24 +00004177 }
4178
4179 void getAnalysisUsage(AnalysisUsage &AU) const override {
4180 // FIXME: Think about passes we will preserve and add them here.
Stefan Stipanovic431141c2019-09-15 21:47:41 +00004181 AU.addRequired<TargetLibraryInfoWrapperPass>();
Johannes Doerfertaade7822019-06-05 03:02:24 +00004182 }
4183};
4184
4185} // end anonymous namespace
4186
4187Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); }
4188
4189char AttributorLegacyPass::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00004190
4191const char AAReturnedValues::ID = 0;
4192const char AANoUnwind::ID = 0;
4193const char AANoSync::ID = 0;
Johannes Doerferteccdf082019-08-05 23:35:12 +00004194const char AANoFree::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00004195const char AANonNull::ID = 0;
4196const char AANoRecurse::ID = 0;
4197const char AAWillReturn::ID = 0;
4198const char AANoAlias::ID = 0;
4199const char AANoReturn::ID = 0;
4200const char AAIsDead::ID = 0;
4201const char AADereferenceable::ID = 0;
4202const char AAAlign::ID = 0;
Johannes Doerfert7516a5e2019-09-03 20:37:24 +00004203const char AANoCapture::ID = 0;
Hideto Uenof2b9dc42019-09-07 07:03:05 +00004204const char AAValueSimplify::ID = 0;
Stefan Stipanovic431141c2019-09-15 21:47:41 +00004205const char AAHeapToStack::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00004206
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00004207// Macro magic to create the static generator function for attributes that
4208// follow the naming scheme.
4209
4210#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
4211 case IRPosition::PK: \
4212 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
4213
4214#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
4215 case IRPosition::PK: \
4216 AA = new CLASS##SUFFIX(IRP); \
4217 break;
4218
4219#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
4220 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
4221 CLASS *AA = nullptr; \
4222 switch (IRP.getPositionKind()) { \
4223 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
4224 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
4225 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
4226 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
4227 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
4228 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
4229 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
4230 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
4231 } \
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00004232 return *AA; \
4233 }
4234
4235#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
4236 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
4237 CLASS *AA = nullptr; \
4238 switch (IRP.getPositionKind()) { \
4239 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
4240 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
4241 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
4242 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
4243 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
4244 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
4245 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
4246 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
4247 } \
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00004248 return *AA; \
4249 }
4250
Hideto Uenof2b9dc42019-09-07 07:03:05 +00004251#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
4252 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
4253 CLASS *AA = nullptr; \
4254 switch (IRP.getPositionKind()) { \
4255 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
4256 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
4257 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
4258 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
4259 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
4260 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
4261 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
4262 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
4263 } \
4264 return *AA; \
4265 }
4266
Stefan Stipanovic431141c2019-09-15 21:47:41 +00004267#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
4268 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
4269 CLASS *AA = nullptr; \
4270 switch (IRP.getPositionKind()) { \
4271 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
4272 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
4273 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
4274 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
4275 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
4276 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
4277 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
4278 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
4279 } \
4280 AA->initialize(A); \
4281 return *AA; \
4282 }
4283
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00004284CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind)
4285CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync)
4286CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)
4287CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse)
4288CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn)
4289CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn)
4290CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead)
4291CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReturnedValues)
4292
4293CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull)
4294CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias)
4295CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable)
4296CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign)
Johannes Doerfert7516a5e2019-09-03 20:37:24 +00004297CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoCapture)
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00004298
Hideto Uenof2b9dc42019-09-07 07:03:05 +00004299CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify)
4300
Stefan Stipanovic431141c2019-09-15 21:47:41 +00004301CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAHeapToStack)
4302
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00004303#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
4304#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
Hideto Uenof2b9dc42019-09-07 07:03:05 +00004305#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
Johannes Doerfert12cbbab2019-08-20 06:15:50 +00004306#undef SWITCH_PK_CREATE
4307#undef SWITCH_PK_INV
4308
Johannes Doerfertaade7822019-06-05 03:02:24 +00004309INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor",
4310 "Deduce and propagate attributes", false, false)
Stefan Stipanovic431141c2019-09-15 21:47:41 +00004311INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
Johannes Doerfertaade7822019-06-05 03:02:24 +00004312INITIALIZE_PASS_END(AttributorLegacyPass, "attributor",
4313 "Deduce and propagate attributes", false, false)