blob: b3c1223bc772c2e452c277d612d372c34115f287 [file] [log] [blame]
Johannes Doerfertaade7822019-06-05 03:02:24 +00001//===- Attributor.cpp - Module-wide attribute deduction -------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements an inter procedural pass that deduces and/or propagating
10// attributes. This is done in an abstract interpretation style fixpoint
11// iteration. See the Attributor.h file comment and the class descriptions in
12// that file for more information.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/Transforms/IPO/Attributor.h"
17
Hideto Ueno11d37102019-07-17 15:15:43 +000018#include "llvm/ADT/DepthFirstIterator.h"
Stefan Stipanovic6058b862019-07-22 23:58:23 +000019#include "llvm/ADT/STLExtras.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000020#include "llvm/ADT/SetVector.h"
21#include "llvm/ADT/SmallPtrSet.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/Statistic.h"
Stefan Stipanovic69ebb022019-07-22 19:36:27 +000024#include "llvm/Analysis/CaptureTracking.h"
Johannes Doerfert924d2132019-08-05 21:34:45 +000025#include "llvm/Analysis/EHPersonalities.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000026#include "llvm/Analysis/GlobalsModRef.h"
Hideto Ueno19c07af2019-07-23 08:16:17 +000027#include "llvm/Analysis/Loads.h"
Hideto Ueno54869ec2019-07-15 06:49:04 +000028#include "llvm/Analysis/ValueTracking.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000029#include "llvm/IR/Argument.h"
30#include "llvm/IR/Attributes.h"
Hideto Ueno11d37102019-07-17 15:15:43 +000031#include "llvm/IR/CFG.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000032#include "llvm/IR/InstIterator.h"
Stefan Stipanovic06263672019-07-11 21:37:40 +000033#include "llvm/IR/IntrinsicInst.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000034#include "llvm/Support/CommandLine.h"
35#include "llvm/Support/Debug.h"
36#include "llvm/Support/raw_ostream.h"
Stefan Stipanovic6058b862019-07-22 23:58:23 +000037#include "llvm/Transforms/Utils/BasicBlockUtils.h"
38#include "llvm/Transforms/Utils/Local.h"
39
Johannes Doerfertaade7822019-06-05 03:02:24 +000040#include <cassert>
41
42using namespace llvm;
43
44#define DEBUG_TYPE "attributor"
45
46STATISTIC(NumFnWithExactDefinition,
47 "Number of function with exact definitions");
48STATISTIC(NumFnWithoutExactDefinition,
49 "Number of function without exact definitions");
50STATISTIC(NumAttributesTimedOut,
51 "Number of abstract attributes timed out before fixpoint");
52STATISTIC(NumAttributesValidFixpoint,
53 "Number of abstract attributes in a valid fixpoint state");
54STATISTIC(NumAttributesManifested,
55 "Number of abstract attributes manifested in IR");
Stefan Stipanovic53605892019-06-27 11:27:54 +000056STATISTIC(NumFnNoUnwind, "Number of functions marked nounwind");
Johannes Doerfertaade7822019-06-05 03:02:24 +000057
Johannes Doerfertaccd3e82019-07-08 23:27:20 +000058STATISTIC(NumFnUniqueReturned, "Number of function with unique return");
59STATISTIC(NumFnKnownReturns, "Number of function with known return values");
60STATISTIC(NumFnArgumentReturned,
61 "Number of function arguments marked returned");
Stefan Stipanovic06263672019-07-11 21:37:40 +000062STATISTIC(NumFnNoSync, "Number of functions marked nosync");
Hideto Ueno65bbaf92019-07-12 17:38:51 +000063STATISTIC(NumFnNoFree, "Number of functions marked nofree");
Hideto Ueno54869ec2019-07-15 06:49:04 +000064STATISTIC(NumFnReturnedNonNull,
65 "Number of function return values marked nonnull");
66STATISTIC(NumFnArgumentNonNull, "Number of function arguments marked nonnull");
67STATISTIC(NumCSArgumentNonNull, "Number of call site arguments marked nonnull");
Hideto Ueno11d37102019-07-17 15:15:43 +000068STATISTIC(NumFnWillReturn, "Number of functions marked willreturn");
Stefan Stipanovic69ebb022019-07-22 19:36:27 +000069STATISTIC(NumFnArgumentNoAlias, "Number of function arguments marked noalias");
Hideto Ueno19c07af2019-07-23 08:16:17 +000070STATISTIC(NumFnReturnedDereferenceable,
71 "Number of function return values marked dereferenceable");
72STATISTIC(NumFnArgumentDereferenceable,
73 "Number of function arguments marked dereferenceable");
74STATISTIC(NumCSArgumentDereferenceable,
75 "Number of call site arguments marked dereferenceable");
Hideto Uenoe7bea9b2019-07-28 07:04:01 +000076STATISTIC(NumFnReturnedAlign, "Number of function return values marked align");
77STATISTIC(NumFnArgumentAlign, "Number of function arguments marked align");
78STATISTIC(NumCSArgumentAlign, "Number of call site arguments marked align");
Johannes Doerferte83f3032019-08-05 23:22:05 +000079STATISTIC(NumFnNoReturn, "Number of functions marked noreturn");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +000080
Johannes Doerfertaade7822019-06-05 03:02:24 +000081// TODO: Determine a good default value.
82//
83// In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads
84// (when run with the first 5 abstract attributes). The results also indicate
85// that we never reach 32 iterations but always find a fixpoint sooner.
86//
87// This will become more evolved once we perform two interleaved fixpoint
88// iterations: bottom-up and top-down.
89static cl::opt<unsigned>
90 MaxFixpointIterations("attributor-max-iterations", cl::Hidden,
91 cl::desc("Maximal number of fixpoint iterations."),
92 cl::init(32));
93
94static cl::opt<bool> DisableAttributor(
95 "attributor-disable", cl::Hidden,
96 cl::desc("Disable the attributor inter-procedural deduction pass."),
Johannes Doerfert282d34e2019-06-14 14:53:41 +000097 cl::init(true));
Johannes Doerfertaade7822019-06-05 03:02:24 +000098
99static cl::opt<bool> VerifyAttributor(
100 "attributor-verify", cl::Hidden,
101 cl::desc("Verify the Attributor deduction and "
102 "manifestation of attributes -- may issue false-positive errors"),
103 cl::init(false));
104
105/// Logic operators for the change status enum class.
106///
107///{
108ChangeStatus llvm::operator|(ChangeStatus l, ChangeStatus r) {
109 return l == ChangeStatus::CHANGED ? l : r;
110}
111ChangeStatus llvm::operator&(ChangeStatus l, ChangeStatus r) {
112 return l == ChangeStatus::UNCHANGED ? l : r;
113}
114///}
115
116/// Helper to adjust the statistics.
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000117static void bookkeeping(IRPosition::Kind PK, const Attribute &Attr) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000118 if (!AreStatisticsEnabled())
119 return;
120
Stefan Stipanovic53605892019-06-27 11:27:54 +0000121 switch (Attr.getKindAsEnum()) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +0000122 case Attribute::Alignment:
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000123 switch (PK) {
124 case IRPosition::IRP_RETURNED:
Hideto Uenoe7bea9b2019-07-28 07:04:01 +0000125 NumFnReturnedAlign++;
126 break;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000127 case IRPosition::IRP_ARGUMENT:
Hideto Uenoe7bea9b2019-07-28 07:04:01 +0000128 NumFnArgumentAlign++;
129 break;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000130 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Hideto Uenoe7bea9b2019-07-28 07:04:01 +0000131 NumCSArgumentAlign++;
132 break;
133 default:
134 break;
135 }
136 break;
Hideto Ueno19c07af2019-07-23 08:16:17 +0000137 case Attribute::Dereferenceable:
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000138 switch (PK) {
139 case IRPosition::IRP_RETURNED:
Hideto Ueno19c07af2019-07-23 08:16:17 +0000140 NumFnReturnedDereferenceable++;
141 break;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000142 case IRPosition::IRP_ARGUMENT:
Hideto Ueno19c07af2019-07-23 08:16:17 +0000143 NumFnArgumentDereferenceable++;
144 break;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000145 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Hideto Ueno19c07af2019-07-23 08:16:17 +0000146 NumCSArgumentDereferenceable++;
147 break;
148 default:
149 break;
150 }
151 break;
Stefan Stipanovic53605892019-06-27 11:27:54 +0000152 case Attribute::NoUnwind:
153 NumFnNoUnwind++;
154 return;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000155 case Attribute::Returned:
156 NumFnArgumentReturned++;
157 return;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000158 case Attribute::NoSync:
159 NumFnNoSync++;
160 break;
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000161 case Attribute::NoFree:
162 NumFnNoFree++;
163 break;
Hideto Ueno54869ec2019-07-15 06:49:04 +0000164 case Attribute::NonNull:
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000165 switch (PK) {
166 case IRPosition::IRP_RETURNED:
Hideto Ueno54869ec2019-07-15 06:49:04 +0000167 NumFnReturnedNonNull++;
168 break;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000169 case IRPosition::IRP_ARGUMENT:
Hideto Ueno54869ec2019-07-15 06:49:04 +0000170 NumFnArgumentNonNull++;
171 break;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000172 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Hideto Ueno54869ec2019-07-15 06:49:04 +0000173 NumCSArgumentNonNull++;
174 break;
175 default:
176 break;
177 }
178 break;
Hideto Ueno11d37102019-07-17 15:15:43 +0000179 case Attribute::WillReturn:
180 NumFnWillReturn++;
181 break;
Johannes Doerferte83f3032019-08-05 23:22:05 +0000182 case Attribute::NoReturn:
183 NumFnNoReturn++;
184 return;
Stefan Stipanovic69ebb022019-07-22 19:36:27 +0000185 case Attribute::NoAlias:
186 NumFnArgumentNoAlias++;
187 return;
Stefan Stipanovic53605892019-06-27 11:27:54 +0000188 default:
189 return;
190 }
Johannes Doerfertaade7822019-06-05 03:02:24 +0000191}
192
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000193template <typename StateTy>
194using followValueCB_t = std::function<bool(Value *, StateTy &State)>;
195template <typename StateTy>
196using visitValueCB_t = std::function<void(Value *, StateTy &State)>;
197
198/// Recursively visit all values that might become \p InitV at some point. This
199/// will be done by looking through cast instructions, selects, phis, and calls
200/// with the "returned" attribute. The callback \p FollowValueCB is asked before
201/// a potential origin value is looked at. If no \p FollowValueCB is passed, a
202/// default one is used that will make sure we visit every value only once. Once
203/// we cannot look through the value any further, the callback \p VisitValueCB
204/// is invoked and passed the current value and the \p State. To limit how much
205/// effort is invested, we will never visit more than \p MaxValues values.
206template <typename StateTy>
207static bool genericValueTraversal(
208 Value *InitV, StateTy &State, visitValueCB_t<StateTy> &VisitValueCB,
209 followValueCB_t<StateTy> *FollowValueCB = nullptr, int MaxValues = 8) {
210
211 SmallPtrSet<Value *, 16> Visited;
212 followValueCB_t<bool> DefaultFollowValueCB = [&](Value *Val, bool &) {
213 return Visited.insert(Val).second;
214 };
215
216 if (!FollowValueCB)
217 FollowValueCB = &DefaultFollowValueCB;
218
219 SmallVector<Value *, 16> Worklist;
220 Worklist.push_back(InitV);
221
222 int Iteration = 0;
223 do {
224 Value *V = Worklist.pop_back_val();
225
226 // Check if we should process the current value. To prevent endless
227 // recursion keep a record of the values we followed!
228 if (!(*FollowValueCB)(V, State))
229 continue;
230
231 // Make sure we limit the compile time for complex expressions.
232 if (Iteration++ >= MaxValues)
233 return false;
234
235 // Explicitly look through calls with a "returned" attribute if we do
236 // not have a pointer as stripPointerCasts only works on them.
237 if (V->getType()->isPointerTy()) {
238 V = V->stripPointerCasts();
239 } else {
240 CallSite CS(V);
241 if (CS && CS.getCalledFunction()) {
242 Value *NewV = nullptr;
243 for (Argument &Arg : CS.getCalledFunction()->args())
244 if (Arg.hasReturnedAttr()) {
245 NewV = CS.getArgOperand(Arg.getArgNo());
246 break;
247 }
248 if (NewV) {
249 Worklist.push_back(NewV);
250 continue;
251 }
252 }
253 }
254
255 // Look through select instructions, visit both potential values.
256 if (auto *SI = dyn_cast<SelectInst>(V)) {
257 Worklist.push_back(SI->getTrueValue());
258 Worklist.push_back(SI->getFalseValue());
259 continue;
260 }
261
262 // Look through phi nodes, visit all operands.
263 if (auto *PHI = dyn_cast<PHINode>(V)) {
264 Worklist.append(PHI->op_begin(), PHI->op_end());
265 continue;
266 }
267
268 // Once a leaf is reached we inform the user through the callback.
269 VisitValueCB(V, State);
270 } while (!Worklist.empty());
271
272 // All values have been visited.
273 return true;
274}
275
Johannes Doerfertaade7822019-06-05 03:02:24 +0000276/// Return true if \p New is equal or worse than \p Old.
277static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) {
278 if (!Old.isIntAttribute())
279 return true;
280
281 return Old.getValueAsInt() >= New.getValueAsInt();
282}
283
284/// Return true if the information provided by \p Attr was added to the
285/// attribute list \p Attrs. This is only the case if it was not already present
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000286/// in \p Attrs at the position describe by \p PK and \p AttrIdx.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000287static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000288 AttributeList &Attrs, int AttrIdx) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000289
290 if (Attr.isEnumAttribute()) {
291 Attribute::AttrKind Kind = Attr.getKindAsEnum();
292 if (Attrs.hasAttribute(AttrIdx, Kind))
293 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
294 return false;
295 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
296 return true;
297 }
298 if (Attr.isStringAttribute()) {
299 StringRef Kind = Attr.getKindAsString();
300 if (Attrs.hasAttribute(AttrIdx, Kind))
301 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
302 return false;
303 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
304 return true;
305 }
Hideto Ueno19c07af2019-07-23 08:16:17 +0000306 if (Attr.isIntAttribute()) {
307 Attribute::AttrKind Kind = Attr.getKindAsEnum();
308 if (Attrs.hasAttribute(AttrIdx, Kind))
309 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
310 return false;
311 Attrs = Attrs.removeAttribute(Ctx, AttrIdx, Kind);
312 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
313 return true;
314 }
Johannes Doerfertaade7822019-06-05 03:02:24 +0000315
316 llvm_unreachable("Expected enum or string attribute!");
317}
318
Johannes Doerfert007153e2019-08-05 23:26:06 +0000319ChangeStatus AbstractAttribute::update(Attributor &A,
320 InformationCache &InfoCache) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000321 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
322 if (getState().isAtFixpoint())
323 return HasChanged;
324
325 LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");
326
Johannes Doerfert007153e2019-08-05 23:26:06 +0000327 HasChanged = updateImpl(A, InfoCache);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000328
329 LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
330 << "\n");
331
332 return HasChanged;
333}
334
Kristina Brooks26e60f02019-08-06 19:53:19 +0000335 ChangeStatus IRAttributeManifest::manifestAttrs(Attributor &A, IRPosition
336 &IRP, const ArrayRef<Attribute> &DeducedAttrs) {
337 assert(IRP.getAssociatedValue() &&
Johannes Doerfertaade7822019-06-05 03:02:24 +0000338 "Attempted to manifest an attribute without associated value!");
339
340 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000341
Kristina Brooks26e60f02019-08-06 19:53:19 +0000342 Function &ScopeFn = IRP.getAnchorScope();
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000343 LLVMContext &Ctx = ScopeFn.getContext();
Kristina Brooks26e60f02019-08-06 19:53:19 +0000344 IRPosition::Kind PK = IRP.getPositionKind();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000345
Johannes Doerfertaade7822019-06-05 03:02:24 +0000346 // In the following some generic code that will manifest attributes in
347 // DeducedAttrs if they improve the current IR. Due to the different
348 // annotation positions we use the underlying AttributeList interface.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000349
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000350 AttributeList Attrs;
351 switch (PK) {
352 case IRPosition::IRP_ARGUMENT:
353 case IRPosition::IRP_FUNCTION:
354 case IRPosition::IRP_RETURNED:
Johannes Doerfertaade7822019-06-05 03:02:24 +0000355 Attrs = ScopeFn.getAttributes();
356 break;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000357 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000358 Attrs = ImmutableCallSite(&IRP.getAnchorValue()).getAttributes();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000359 break;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000360 }
361
362 for (const Attribute &Attr : DeducedAttrs) {
Kristina Brooks26e60f02019-08-06 19:53:19 +0000363 if (!addIfNotExistent(Ctx, Attr, Attrs, IRP.getAttrIdx()))
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000364 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000365
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000366 HasChanged = ChangeStatus::CHANGED;
367 bookkeeping(PK, Attr);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000368 }
369
370 if (HasChanged == ChangeStatus::UNCHANGED)
371 return HasChanged;
372
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000373 switch (PK) {
374 case IRPosition::IRP_ARGUMENT:
375 case IRPosition::IRP_FUNCTION:
376 case IRPosition::IRP_RETURNED:
Johannes Doerfertaade7822019-06-05 03:02:24 +0000377 ScopeFn.setAttributes(Attrs);
378 break;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000379 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000380 CallSite(&IRP.getAnchorValue()).setAttributes(Attrs);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000381 }
382
383 return HasChanged;
384}
385
Stefan Stipanovic53605892019-06-27 11:27:54 +0000386/// -----------------------NoUnwind Function Attribute--------------------------
387
Johannes Doerfert344d0382019-08-07 22:34:26 +0000388struct AANoUnwindImpl : AANoUnwind {
Johannes Doerferteccdf082019-08-05 23:35:12 +0000389 IRPositionConstructorForward(AANoUnwindImpl, AANoUnwind);
Stefan Stipanovic53605892019-06-27 11:27:54 +0000390
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000391 const std::string getAsStr() const override {
Stefan Stipanovic53605892019-06-27 11:27:54 +0000392 return getAssumed() ? "nounwind" : "may-unwind";
393 }
394
395 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000396 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Stefan Stipanovic53605892019-06-27 11:27:54 +0000397};
398
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000399struct AANoUnwindFunction final : public AANoUnwindImpl {
400 AANoUnwindFunction(Function &F) : AANoUnwindImpl(F, IRP_FUNCTION) {}
401};
402
403ChangeStatus AANoUnwindImpl::updateImpl(Attributor &A,
404 InformationCache &InfoCache) {
Stefan Stipanovic53605892019-06-27 11:27:54 +0000405 Function &F = getAnchorScope();
406
407 // The map from instruction opcodes to those instructions in the function.
Stefan Stipanovic53605892019-06-27 11:27:54 +0000408 auto Opcodes = {
409 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
410 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
411 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
412
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000413 auto CheckForNoUnwind = [&](Instruction &I) {
414 if (!I.mayThrow())
415 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000416
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000417 auto *NoUnwindAA = A.getAAFor<AANoUnwind>(*this, I);
418 return NoUnwindAA && NoUnwindAA->isAssumedNoUnwind();
419 };
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000420
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000421 if (!A.checkForAllInstructions(F, CheckForNoUnwind, *this, InfoCache,
422 Opcodes))
423 return indicatePessimisticFixpoint();
Stefan Stipanovic53605892019-06-27 11:27:54 +0000424
Stefan Stipanovic53605892019-06-27 11:27:54 +0000425 return ChangeStatus::UNCHANGED;
426}
427
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000428/// --------------------- Function Return Values -------------------------------
429
430/// "Attribute" that collects all potential returned values and the return
431/// instructions that they arise from.
432///
433/// If there is a unique returned value R, the manifest method will:
434/// - mark R with the "returned" attribute, if R is an argument.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000435///
436/// TODO: We should use liveness during construction of the returned values map
437/// and before we set HasOverdefinedReturnedCalls.
Johannes Doerferteccdf082019-08-05 23:35:12 +0000438class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000439
440 /// Mapping of values potentially returned by the associated function to the
441 /// return instructions that might return them.
442 DenseMap<Value *, SmallPtrSet<ReturnInst *, 2>> ReturnedValues;
443
444 /// State flags
445 ///
446 ///{
447 bool IsFixed;
448 bool IsValidState;
449 bool HasOverdefinedReturnedCalls;
450 ///}
451
452 /// Collect values that could become \p V in the set \p Values, each mapped to
453 /// \p ReturnInsts.
454 void collectValuesRecursively(
455 Attributor &A, Value *V, SmallPtrSetImpl<ReturnInst *> &ReturnInsts,
456 DenseMap<Value *, SmallPtrSet<ReturnInst *, 2>> &Values) {
457
458 visitValueCB_t<bool> VisitValueCB = [&](Value *Val, bool &) {
459 assert(!isa<Instruction>(Val) ||
460 &getAnchorScope() == cast<Instruction>(Val)->getFunction());
461 Values[Val].insert(ReturnInsts.begin(), ReturnInsts.end());
462 };
463
464 bool UnusedBool;
465 bool Success = genericValueTraversal(V, UnusedBool, VisitValueCB);
466
467 // If we did abort the above traversal we haven't see all the values.
468 // Consequently, we cannot know if the information we would derive is
469 // accurate so we give up early.
470 if (!Success)
471 indicatePessimisticFixpoint();
472 }
473
474public:
Johannes Doerferteccdf082019-08-05 23:35:12 +0000475 IRPositionConstructorForward(AAReturnedValuesImpl, AAReturnedValues);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000476
477 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000478 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000479 // Reset the state.
480 AssociatedVal = nullptr;
481 IsFixed = false;
482 IsValidState = true;
483 HasOverdefinedReturnedCalls = false;
484 ReturnedValues.clear();
485
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000486 Function &F = cast<Function>(getAnchorValue());
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000487
488 // The map from instruction opcodes to those instructions in the function.
489 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
490
491 // Look through all arguments, if one is marked as returned we are done.
492 for (Argument &Arg : F.args()) {
493 if (Arg.hasReturnedAttr()) {
494
495 auto &ReturnInstSet = ReturnedValues[&Arg];
496 for (Instruction *RI : OpcodeInstMap[Instruction::Ret])
497 ReturnInstSet.insert(cast<ReturnInst>(RI));
498
499 indicateOptimisticFixpoint();
500 return;
501 }
502 }
503
504 // If no argument was marked as returned we look at all return instructions
505 // and collect potentially returned values.
506 for (Instruction *RI : OpcodeInstMap[Instruction::Ret]) {
507 SmallPtrSet<ReturnInst *, 1> RISet({cast<ReturnInst>(RI)});
508 collectValuesRecursively(A, cast<ReturnInst>(RI)->getReturnValue(), RISet,
509 ReturnedValues);
510 }
511 }
512
513 /// See AbstractAttribute::manifest(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000514 ChangeStatus manifest(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000515
516 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000517 AbstractState &getState() override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000518
519 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000520 const AbstractState &getState() const override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000521
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000522 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000523 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000524
525 /// Return the number of potential return values, -1 if unknown.
526 size_t getNumReturnValues() const {
527 return isValidState() ? ReturnedValues.size() : -1;
528 }
529
530 /// Return an assumed unique return value if a single candidate is found. If
531 /// there cannot be one, return a nullptr. If it is not clear yet, return the
532 /// Optional::NoneType.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000533 Optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000534
Johannes Doerfert14a04932019-08-07 22:27:24 +0000535 /// See AbstractState::checkForAllReturnedValues(...).
536 bool checkForAllReturnedValuesAndReturnInsts(
537 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
538 &Pred) const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000539
540 /// Pretty print the attribute similar to the IR representation.
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000541 const std::string getAsStr() const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000542
543 /// See AbstractState::isAtFixpoint().
544 bool isAtFixpoint() const override { return IsFixed; }
545
546 /// See AbstractState::isValidState().
547 bool isValidState() const override { return IsValidState; }
548
549 /// See AbstractState::indicateOptimisticFixpoint(...).
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000550 ChangeStatus indicateOptimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000551 IsFixed = true;
552 IsValidState &= true;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000553 return ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000554 }
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000555
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000556 ChangeStatus indicatePessimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000557 IsFixed = true;
558 IsValidState = false;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000559 return ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000560 }
561};
562
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000563struct AAReturnedValuesFunction final : public AAReturnedValuesImpl {
564 AAReturnedValuesFunction(Function &F)
565 : AAReturnedValuesImpl(F, IRP_FUNCTION) {}
566};
567
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000568ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) {
569 ChangeStatus Changed = ChangeStatus::UNCHANGED;
570
571 // Bookkeeping.
572 assert(isValidState());
573 NumFnKnownReturns++;
574
575 // Check if we have an assumed unique return value that we could manifest.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000576 Optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000577
578 if (!UniqueRV.hasValue() || !UniqueRV.getValue())
579 return Changed;
580
581 // Bookkeeping.
582 NumFnUniqueReturned++;
583
584 // If the assumed unique return value is an argument, annotate it.
585 if (auto *UniqueRVArg = dyn_cast<Argument>(UniqueRV.getValue())) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000586 setAssociatedValue(UniqueRVArg);
587 setAttributeIdx(UniqueRVArg->getArgNo() + AttributeList::FirstArgIndex);
Johannes Doerferteccdf082019-08-05 23:35:12 +0000588 Changed = IRAttribute::manifest(A) | Changed;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000589 }
590
591 return Changed;
592}
593
594const std::string AAReturnedValuesImpl::getAsStr() const {
595 return (isAtFixpoint() ? "returns(#" : "may-return(#") +
Johannes Doerfert6471bb62019-08-04 18:39:28 +0000596 (isValidState() ? std::to_string(getNumReturnValues()) : "?") +
597 ")[OD: " + std::to_string(HasOverdefinedReturnedCalls) + "]";
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000598}
599
Johannes Doerfert14a04932019-08-07 22:27:24 +0000600Optional<Value *>
601AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const {
602 // If checkForAllReturnedValues provides a unique value, ignoring potential
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000603 // undef values that can also be present, it is assumed to be the actual
604 // return value and forwarded to the caller of this method. If there are
605 // multiple, a nullptr is returned indicating there cannot be a unique
606 // returned value.
607 Optional<Value *> UniqueRV;
608
Johannes Doerfert14a04932019-08-07 22:27:24 +0000609 auto Pred = [&](Value &RV) -> bool {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000610 // If we found a second returned value and neither the current nor the saved
611 // one is an undef, there is no unique returned value. Undefs are special
612 // since we can pretend they have any value.
613 if (UniqueRV.hasValue() && UniqueRV != &RV &&
614 !(isa<UndefValue>(RV) || isa<UndefValue>(UniqueRV.getValue()))) {
615 UniqueRV = nullptr;
616 return false;
617 }
618
619 // Do not overwrite a value with an undef.
620 if (!UniqueRV.hasValue() || !isa<UndefValue>(RV))
621 UniqueRV = &RV;
622
623 return true;
624 };
625
Johannes Doerfert14a04932019-08-07 22:27:24 +0000626 if (!A.checkForAllReturnedValues(getAnchorScope(), Pred, *this))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000627 UniqueRV = nullptr;
628
629 return UniqueRV;
630}
631
Johannes Doerfert14a04932019-08-07 22:27:24 +0000632bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
633 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
634 &Pred) const {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000635 if (!isValidState())
636 return false;
637
638 // Check all returned values but ignore call sites as long as we have not
639 // encountered an overdefined one during an update.
640 for (auto &It : ReturnedValues) {
641 Value *RV = It.first;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000642 const SmallPtrSetImpl<ReturnInst *> &RetInsts = It.second;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000643
644 ImmutableCallSite ICS(RV);
645 if (ICS && !HasOverdefinedReturnedCalls)
646 continue;
647
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000648 if (!Pred(*RV, RetInsts))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000649 return false;
650 }
651
652 return true;
653}
654
Johannes Doerfert007153e2019-08-05 23:26:06 +0000655ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A,
656 InformationCache &InfoCache) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000657
658 // Check if we know of any values returned by the associated function,
659 // if not, we are done.
660 if (getNumReturnValues() == 0) {
661 indicateOptimisticFixpoint();
662 return ChangeStatus::UNCHANGED;
663 }
664
665 // Check if any of the returned values is a call site we can refine.
666 decltype(ReturnedValues) AddRVs;
667 bool HasCallSite = false;
668
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000669 // Keep track of any change to trigger updates on dependent attributes.
670 ChangeStatus Changed = ChangeStatus::UNCHANGED;
671
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000672 auto *LivenessAA = A.getAAFor<AAIsDead>(*this, getAnchorScope());
673
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000674 // Look at all returned call sites.
675 for (auto &It : ReturnedValues) {
676 SmallPtrSet<ReturnInst *, 2> &ReturnInsts = It.second;
677 Value *RV = It.first;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000678
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000679 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Potentially returned value " << *RV
680 << "\n");
681
682 // Only call sites can change during an update, ignore the rest.
683 CallSite RetCS(RV);
684 if (!RetCS)
685 continue;
686
687 // For now, any call site we see will prevent us from directly fixing the
688 // state. However, if the information on the callees is fixed, the call
689 // sites will be removed and we will fix the information for this state.
690 HasCallSite = true;
691
Johannes Doerfert4361da22019-08-04 18:38:53 +0000692 // Ignore dead ReturnValues.
693 if (LivenessAA &&
694 !LivenessAA->isLiveInstSet(ReturnInsts.begin(), ReturnInsts.end())) {
695 LLVM_DEBUG(dbgs() << "[AAReturnedValues] all returns are assumed dead, "
696 "skip it for now\n");
697 continue;
698 }
699
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000700 // Try to find a assumed unique return value for the called function.
701 auto *RetCSAA = A.getAAFor<AAReturnedValuesImpl>(*this, *RV);
Johannes Doerfert0a7f4cd2019-07-13 01:09:21 +0000702 if (!RetCSAA) {
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000703 if (!HasOverdefinedReturnedCalls)
704 Changed = ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000705 HasOverdefinedReturnedCalls = true;
706 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned call site (" << *RV
707 << ") with " << (RetCSAA ? "invalid" : "no")
708 << " associated state\n");
709 continue;
710 }
711
712 // Try to find a assumed unique return value for the called function.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000713 Optional<Value *> AssumedUniqueRV = RetCSAA->getAssumedUniqueReturnValue(A);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000714
715 // If no assumed unique return value was found due to the lack of
716 // candidates, we may need to resolve more calls (through more update
717 // iterations) or the called function will not return. Either way, we simply
718 // stick with the call sites as return values. Because there were not
719 // multiple possibilities, we do not treat it as overdefined.
720 if (!AssumedUniqueRV.hasValue())
721 continue;
722
723 // If multiple, non-refinable values were found, there cannot be a unique
724 // return value for the called function. The returned call is overdefined!
725 if (!AssumedUniqueRV.getValue()) {
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000726 if (!HasOverdefinedReturnedCalls)
727 Changed = ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000728 HasOverdefinedReturnedCalls = true;
729 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned call site has multiple "
730 "potentially returned values\n");
731 continue;
732 }
733
734 LLVM_DEBUG({
735 bool UniqueRVIsKnown = RetCSAA->isAtFixpoint();
736 dbgs() << "[AAReturnedValues] Returned call site "
737 << (UniqueRVIsKnown ? "known" : "assumed")
738 << " unique return value: " << *AssumedUniqueRV << "\n";
739 });
740
741 // The assumed unique return value.
742 Value *AssumedRetVal = AssumedUniqueRV.getValue();
743
744 // If the assumed unique return value is an argument, lookup the matching
745 // call site operand and recursively collect new returned values.
746 // If it is not an argument, it is just put into the set of returned values
747 // as we would have already looked through casts, phis, and similar values.
748 if (Argument *AssumedRetArg = dyn_cast<Argument>(AssumedRetVal))
749 collectValuesRecursively(A,
750 RetCS.getArgOperand(AssumedRetArg->getArgNo()),
751 ReturnInsts, AddRVs);
752 else
753 AddRVs[AssumedRetVal].insert(ReturnInsts.begin(), ReturnInsts.end());
754 }
755
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000756 for (auto &It : AddRVs) {
757 assert(!It.second.empty() && "Entry does not add anything.");
758 auto &ReturnInsts = ReturnedValues[It.first];
759 for (ReturnInst *RI : It.second)
760 if (ReturnInsts.insert(RI).second) {
761 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Add new returned value "
762 << *It.first << " => " << *RI << "\n");
763 Changed = ChangeStatus::CHANGED;
764 }
765 }
766
767 // If there is no call site in the returned values we are done.
768 if (!HasCallSite) {
769 indicateOptimisticFixpoint();
770 return ChangeStatus::CHANGED;
771 }
772
773 return Changed;
774}
775
Stefan Stipanovic06263672019-07-11 21:37:40 +0000776/// ------------------------ NoSync Function Attribute -------------------------
777
Johannes Doerfert344d0382019-08-07 22:34:26 +0000778struct AANoSyncImpl : AANoSync {
Johannes Doerferteccdf082019-08-05 23:35:12 +0000779 IRPositionConstructorForward(AANoSyncImpl, AANoSync);
Stefan Stipanovic06263672019-07-11 21:37:40 +0000780
Stefan Stipanoviccb5ecae2019-07-12 18:34:06 +0000781 const std::string getAsStr() const override {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000782 return getAssumed() ? "nosync" : "may-sync";
783 }
784
785 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000786 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000787
Stefan Stipanovic06263672019-07-11 21:37:40 +0000788 /// Helper function used to determine whether an instruction is non-relaxed
789 /// atomic. In other words, if an atomic instruction does not have unordered
790 /// or monotonic ordering
791 static bool isNonRelaxedAtomic(Instruction *I);
792
793 /// Helper function used to determine whether an instruction is volatile.
794 static bool isVolatile(Instruction *I);
795
Johannes Doerfertc7a1db32019-07-13 01:09:27 +0000796 /// Helper function uset to check if intrinsic is volatile (memcpy, memmove,
797 /// memset).
Stefan Stipanovic06263672019-07-11 21:37:40 +0000798 static bool isNoSyncIntrinsic(Instruction *I);
799};
800
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000801struct AANoSyncFunction final : public AANoSyncImpl {
802 AANoSyncFunction(Function &F) : AANoSyncImpl(F, IRP_FUNCTION) {}
803};
804
805bool AANoSyncImpl::isNonRelaxedAtomic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000806 if (!I->isAtomic())
807 return false;
808
809 AtomicOrdering Ordering;
810 switch (I->getOpcode()) {
811 case Instruction::AtomicRMW:
812 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
813 break;
814 case Instruction::Store:
815 Ordering = cast<StoreInst>(I)->getOrdering();
816 break;
817 case Instruction::Load:
818 Ordering = cast<LoadInst>(I)->getOrdering();
819 break;
820 case Instruction::Fence: {
821 auto *FI = cast<FenceInst>(I);
822 if (FI->getSyncScopeID() == SyncScope::SingleThread)
823 return false;
824 Ordering = FI->getOrdering();
825 break;
826 }
827 case Instruction::AtomicCmpXchg: {
828 AtomicOrdering Success = cast<AtomicCmpXchgInst>(I)->getSuccessOrdering();
829 AtomicOrdering Failure = cast<AtomicCmpXchgInst>(I)->getFailureOrdering();
830 // Only if both are relaxed, than it can be treated as relaxed.
831 // Otherwise it is non-relaxed.
832 if (Success != AtomicOrdering::Unordered &&
833 Success != AtomicOrdering::Monotonic)
834 return true;
835 if (Failure != AtomicOrdering::Unordered &&
836 Failure != AtomicOrdering::Monotonic)
837 return true;
838 return false;
839 }
840 default:
841 llvm_unreachable(
842 "New atomic operations need to be known in the attributor.");
843 }
844
845 // Relaxed.
846 if (Ordering == AtomicOrdering::Unordered ||
847 Ordering == AtomicOrdering::Monotonic)
848 return false;
849 return true;
850}
851
852/// Checks if an intrinsic is nosync. Currently only checks mem* intrinsics.
853/// FIXME: We should ipmrove the handling of intrinsics.
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000854bool AANoSyncImpl::isNoSyncIntrinsic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000855 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
856 switch (II->getIntrinsicID()) {
857 /// Element wise atomic memory intrinsics are can only be unordered,
858 /// therefore nosync.
859 case Intrinsic::memset_element_unordered_atomic:
860 case Intrinsic::memmove_element_unordered_atomic:
861 case Intrinsic::memcpy_element_unordered_atomic:
862 return true;
863 case Intrinsic::memset:
864 case Intrinsic::memmove:
865 case Intrinsic::memcpy:
866 if (!cast<MemIntrinsic>(II)->isVolatile())
867 return true;
868 return false;
869 default:
870 return false;
871 }
872 }
873 return false;
874}
875
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000876bool AANoSyncImpl::isVolatile(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000877 assert(!ImmutableCallSite(I) && !isa<CallBase>(I) &&
878 "Calls should not be checked here");
879
880 switch (I->getOpcode()) {
881 case Instruction::AtomicRMW:
882 return cast<AtomicRMWInst>(I)->isVolatile();
883 case Instruction::Store:
884 return cast<StoreInst>(I)->isVolatile();
885 case Instruction::Load:
886 return cast<LoadInst>(I)->isVolatile();
887 case Instruction::AtomicCmpXchg:
888 return cast<AtomicCmpXchgInst>(I)->isVolatile();
889 default:
890 return false;
891 }
892}
893
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000894ChangeStatus AANoSyncImpl::updateImpl(Attributor &A,
895 InformationCache &InfoCache) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000896 Function &F = getAnchorScope();
897
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000898 auto CheckRWInstForNoSync = [&](Instruction &I) {
899 /// We are looking for volatile instructions or Non-Relaxed atomics.
900 /// FIXME: We should ipmrove the handling of intrinsics.
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000901
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000902 ImmutableCallSite ICS(&I);
903 auto *NoSyncAA = A.getAAFor<AANoSyncImpl>(*this, I);
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000904
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000905 if (isa<IntrinsicInst>(&I) && isNoSyncIntrinsic(&I))
906 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000907
908 if (ICS && (!NoSyncAA || !NoSyncAA->isAssumedNoSync()) &&
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000909 !ICS.hasFnAttr(Attribute::NoSync))
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000910 return false;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000911
Johannes Doerfertc7a1db32019-07-13 01:09:27 +0000912 if (ICS)
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000913 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000914
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000915 if (!isVolatile(&I) && !isNonRelaxedAtomic(&I))
916 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000917
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000918 return false;
919 };
Stefan Stipanovic06263672019-07-11 21:37:40 +0000920
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000921 auto CheckForNoSync = [&](Instruction &I) {
922 // At this point we handled all read/write effects and they are all
923 // nosync, so they can be skipped.
924 if (I.mayReadOrWriteMemory())
925 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000926
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000927 // non-convergent and readnone imply nosync.
928 return !ImmutableCallSite(&I).isConvergent();
929 };
Stefan Stipanovic06263672019-07-11 21:37:40 +0000930
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000931 if (!A.checkForAllReadWriteInstructions(F, CheckRWInstForNoSync, *this,
932 InfoCache) ||
933 !A.checkForAllCallLikeInstructions(F, CheckForNoSync, *this, InfoCache))
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000934 return indicatePessimisticFixpoint();
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000935
Stefan Stipanovic06263672019-07-11 21:37:40 +0000936 return ChangeStatus::UNCHANGED;
937}
938
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000939/// ------------------------ No-Free Attributes ----------------------------
940
Johannes Doerfert344d0382019-08-07 22:34:26 +0000941struct AANoFreeImpl : public AANoFree {
Johannes Doerferteccdf082019-08-05 23:35:12 +0000942 IRPositionConstructorForward(AANoFreeImpl, AANoFree);
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000943
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000944 /// See AbstractAttribute::getAsStr().
945 const std::string getAsStr() const override {
946 return getAssumed() ? "nofree" : "may-free";
947 }
948
949 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000950 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000951};
952
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000953struct AANoFreeFunction final : public AANoFreeImpl {
954 AANoFreeFunction(Function &F) : AANoFreeImpl(F, IRP_FUNCTION) {}
955};
956
957ChangeStatus AANoFreeImpl::updateImpl(Attributor &A,
958 InformationCache &InfoCache) {
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000959 Function &F = getAnchorScope();
960
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000961 auto CheckForNoFree = [&](Instruction &I) {
962 if (ImmutableCallSite(&I).hasFnAttr(Attribute::NoFree))
963 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000964
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000965 auto *NoFreeAA = A.getAAFor<AANoFreeImpl>(*this, I);
966 return NoFreeAA && NoFreeAA->isAssumedNoFree();
967 };
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000968
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000969 if (!A.checkForAllCallLikeInstructions(F, CheckForNoFree, *this, InfoCache))
970 return indicatePessimisticFixpoint();
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000971 return ChangeStatus::UNCHANGED;
972}
973
Hideto Ueno54869ec2019-07-15 06:49:04 +0000974/// ------------------------ NonNull Argument Attribute ------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +0000975struct AANonNullImpl : AANonNull {
Johannes Doerferteccdf082019-08-05 23:35:12 +0000976 IRPositionConstructorForward(AANonNullImpl, AANonNull);
Hideto Ueno54869ec2019-07-15 06:49:04 +0000977
Hideto Ueno54869ec2019-07-15 06:49:04 +0000978
979 /// See AbstractAttribute::getAsStr().
980 const std::string getAsStr() const override {
981 return getAssumed() ? "nonnull" : "may-null";
982 }
983
Hideto Ueno54869ec2019-07-15 06:49:04 +0000984 /// Generate a predicate that checks if a given value is assumed nonnull.
985 /// The generated function returns true if a value satisfies any of
986 /// following conditions.
987 /// (i) A value is known nonZero(=nonnull).
988 /// (ii) A value is associated with AANonNull and its isAssumedNonNull() is
989 /// true.
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000990 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
991 generatePredicate(Attributor &);
Hideto Ueno54869ec2019-07-15 06:49:04 +0000992};
993
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000994std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
995AANonNullImpl::generatePredicate(Attributor &A) {
Hideto Ueno54869ec2019-07-15 06:49:04 +0000996 // FIXME: The `AAReturnedValues` should provide the predicate with the
997 // `ReturnInst` vector as well such that we can use the control flow sensitive
998 // version of `isKnownNonZero`. This should fix `test11` in
999 // `test/Transforms/FunctionAttrs/nonnull.ll`
1000
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001001 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
1002 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &RetInsts) -> bool {
1003 Function &F = getAnchorScope();
1004
1005 if (isKnownNonZero(&RV, F.getParent()->getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001006 return true;
1007
1008 auto *NonNullAA = A.getAAFor<AANonNull>(*this, RV);
1009
1010 ImmutableCallSite ICS(&RV);
1011
1012 if ((!NonNullAA || !NonNullAA->isAssumedNonNull()) &&
1013 (!ICS || !ICS.hasRetAttr(Attribute::NonNull)))
1014 return false;
1015
1016 return true;
1017 };
1018
1019 return Pred;
1020}
1021
1022/// NonNull attribute for function return value.
1023struct AANonNullReturned : AANonNullImpl {
1024
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001025 AANonNullReturned(Function &F) : AANonNullImpl(F, IRP_RETURNED) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001026
1027 /// See AbstractAttriubute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001028 void initialize(Attributor &A, InformationCache &InfoCache) override {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001029 Function &F = getAnchorScope();
1030
1031 // Already nonnull.
1032 if (F.getAttributes().hasAttribute(AttributeList::ReturnIndex,
Hideto Ueno19c07af2019-07-23 08:16:17 +00001033 Attribute::NonNull) ||
1034 F.getAttributes().hasAttribute(AttributeList::ReturnIndex,
1035 Attribute::Dereferenceable))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001036 indicateOptimisticFixpoint();
1037 }
1038
1039 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001040 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Hideto Ueno54869ec2019-07-15 06:49:04 +00001041};
1042
Johannes Doerfert007153e2019-08-05 23:26:06 +00001043ChangeStatus AANonNullReturned::updateImpl(Attributor &A,
1044 InformationCache &InfoCache) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001045 Function &F = getAnchorScope();
1046
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001047 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
1048 this->generatePredicate(A);
1049
Johannes Doerfert14a04932019-08-07 22:27:24 +00001050 if (!A.checkForAllReturnedValuesAndReturnInsts(F, Pred, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001051 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001052 return ChangeStatus::UNCHANGED;
1053}
1054
1055/// NonNull attribute for function argument.
1056struct AANonNullArgument : AANonNullImpl {
1057
Johannes Doerfert007153e2019-08-05 23:26:06 +00001058 AANonNullArgument(Argument &A) : AANonNullImpl(A) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001059
Hideto Ueno54869ec2019-07-15 06:49:04 +00001060 /// See AbstractAttriubute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001061 void initialize(Attributor &A, InformationCache &InfoCache) override {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001062 Argument *Arg = cast<Argument>(getAssociatedValue());
1063 if (Arg->hasNonNullAttr())
1064 indicateOptimisticFixpoint();
1065 }
1066
1067 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001068 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Hideto Ueno54869ec2019-07-15 06:49:04 +00001069};
1070
1071/// NonNull attribute for a call site argument.
1072struct AANonNullCallSiteArgument : AANonNullImpl {
1073
1074 /// See AANonNullImpl::AANonNullImpl(...).
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00001075 AANonNullCallSiteArgument(Instruction &I, unsigned ArgNo)
1076 : AANonNullImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001077
1078 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001079 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001080 CallSite CS(&getAnchorValue());
1081 if (CS.paramHasAttr(getArgNo(), getAttrKind()) ||
1082 CS.paramHasAttr(getArgNo(), Attribute::Dereferenceable) ||
Hideto Ueno19c07af2019-07-23 08:16:17 +00001083 isKnownNonZero(getAssociatedValue(),
1084 getAnchorScope().getParent()->getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001085 indicateOptimisticFixpoint();
1086 }
1087
1088 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001089 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Hideto Ueno54869ec2019-07-15 06:49:04 +00001090};
Johannes Doerfert007153e2019-08-05 23:26:06 +00001091
1092ChangeStatus AANonNullArgument::updateImpl(Attributor &A,
1093 InformationCache &InfoCache) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001094 Function &F = getAnchorScope();
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001095 Argument &Arg = cast<Argument>(getAnchorValue());
Hideto Ueno54869ec2019-07-15 06:49:04 +00001096
1097 unsigned ArgNo = Arg.getArgNo();
1098
1099 // Callback function
1100 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) {
1101 assert(CS && "Sanity check: Call site was not initialized properly!");
1102
1103 auto *NonNullAA = A.getAAFor<AANonNull>(*this, *CS.getInstruction(), ArgNo);
1104
1105 // Check that NonNullAA is AANonNullCallSiteArgument.
1106 if (NonNullAA) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001107 ImmutableCallSite ICS(&NonNullAA->getIRPosition().getAnchorValue());
Hideto Ueno54869ec2019-07-15 06:49:04 +00001108 if (ICS && CS.getInstruction() == ICS.getInstruction())
1109 return NonNullAA->isAssumedNonNull();
1110 return false;
1111 }
1112
1113 if (CS.paramHasAttr(ArgNo, Attribute::NonNull))
1114 return true;
1115
1116 Value *V = CS.getArgOperand(ArgNo);
1117 if (isKnownNonZero(V, getAnchorScope().getParent()->getDataLayout()))
1118 return true;
1119
1120 return false;
1121 };
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001122 if (!A.checkForAllCallSites(F, CallSiteCheck, *this, true))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001123 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001124 return ChangeStatus::UNCHANGED;
1125}
1126
Johannes Doerfert007153e2019-08-05 23:26:06 +00001127ChangeStatus
1128AANonNullCallSiteArgument::updateImpl(Attributor &A,
1129 InformationCache &InfoCache) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001130 // NOTE: Never look at the argument of the callee in this method.
1131 // If we do this, "nonnull" is always deduced because of the assumption.
1132
1133 Value &V = *getAssociatedValue();
1134
1135 auto *NonNullAA = A.getAAFor<AANonNull>(*this, V);
1136
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001137 if (!NonNullAA || !NonNullAA->isAssumedNonNull())
1138 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001139
1140 return ChangeStatus::UNCHANGED;
1141}
1142
Hideto Ueno11d37102019-07-17 15:15:43 +00001143/// ------------------------ Will-Return Attributes ----------------------------
1144
Johannes Doerfert344d0382019-08-07 22:34:26 +00001145struct AAWillReturnImpl : public AAWillReturn {
Johannes Doerferteccdf082019-08-05 23:35:12 +00001146 IRPositionConstructorForward(AAWillReturnImpl, AAWillReturn);
Hideto Ueno11d37102019-07-17 15:15:43 +00001147
Hideto Ueno11d37102019-07-17 15:15:43 +00001148 /// See AbstractAttribute::getAsStr()
1149 const std::string getAsStr() const override {
1150 return getAssumed() ? "willreturn" : "may-noreturn";
1151 }
1152};
1153
1154struct AAWillReturnFunction final : AAWillReturnImpl {
1155
1156 /// See AbstractAttribute::AbstractAttribute(...).
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001157 AAWillReturnFunction(Function &F) : AAWillReturnImpl(F, IRP_FUNCTION) {}
Hideto Ueno11d37102019-07-17 15:15:43 +00001158
1159 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001160 void initialize(Attributor &A, InformationCache &InfoCache) override;
Hideto Ueno11d37102019-07-17 15:15:43 +00001161
1162 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001163 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Hideto Ueno11d37102019-07-17 15:15:43 +00001164};
1165
1166// Helper function that checks whether a function has any cycle.
1167// TODO: Replace with more efficent code
1168bool containsCycle(Function &F) {
1169 SmallPtrSet<BasicBlock *, 32> Visited;
1170
1171 // Traverse BB by dfs and check whether successor is already visited.
1172 for (BasicBlock *BB : depth_first(&F)) {
1173 Visited.insert(BB);
1174 for (auto *SuccBB : successors(BB)) {
1175 if (Visited.count(SuccBB))
1176 return true;
1177 }
1178 }
1179 return false;
1180}
1181
1182// Helper function that checks the function have a loop which might become an
1183// endless loop
1184// FIXME: Any cycle is regarded as endless loop for now.
1185// We have to allow some patterns.
1186bool containsPossiblyEndlessLoop(Function &F) { return containsCycle(F); }
1187
Johannes Doerfert007153e2019-08-05 23:26:06 +00001188void AAWillReturnFunction::initialize(Attributor &A,
1189 InformationCache &InfoCache) {
Hideto Ueno11d37102019-07-17 15:15:43 +00001190 Function &F = getAnchorScope();
1191
1192 if (containsPossiblyEndlessLoop(F))
1193 indicatePessimisticFixpoint();
1194}
1195
Johannes Doerfert007153e2019-08-05 23:26:06 +00001196ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A,
1197 InformationCache &InfoCache) {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001198 const Function &F = getAnchorScope();
Hideto Ueno11d37102019-07-17 15:15:43 +00001199 // The map from instruction opcodes to those instructions in the function.
Hideto Ueno11d37102019-07-17 15:15:43 +00001200
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001201 auto CheckForWillReturn = [&](Instruction &I) {
1202 ImmutableCallSite ICS(&I);
1203 if (ICS.hasFnAttr(Attribute::WillReturn))
1204 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001205
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001206 auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, I);
1207 if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn())
1208 return false;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001209
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001210 // FIXME: Prohibit any recursion for now.
1211 if (ICS.hasFnAttr(Attribute::NoRecurse))
1212 return true;
Hideto Ueno11d37102019-07-17 15:15:43 +00001213
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001214 auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, I);
1215 return NoRecurseAA && NoRecurseAA->isAssumedNoRecurse();
1216 };
Hideto Ueno11d37102019-07-17 15:15:43 +00001217
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001218 if (!A.checkForAllCallLikeInstructions(F, CheckForWillReturn, *this,
1219 InfoCache))
1220 return indicatePessimisticFixpoint();
Hideto Ueno11d37102019-07-17 15:15:43 +00001221
1222 return ChangeStatus::UNCHANGED;
1223}
1224
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001225/// ------------------------ NoAlias Argument Attribute ------------------------
1226
Johannes Doerfert344d0382019-08-07 22:34:26 +00001227struct AANoAliasImpl : AANoAlias {
Johannes Doerferteccdf082019-08-05 23:35:12 +00001228 IRPositionConstructorForward(AANoAliasImpl, AANoAlias);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001229
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001230 const std::string getAsStr() const override {
1231 return getAssumed() ? "noalias" : "may-alias";
1232 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001233};
1234
1235/// NoAlias attribute for function return value.
1236struct AANoAliasReturned : AANoAliasImpl {
1237
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001238 AANoAliasReturned(Function &F) : AANoAliasImpl(F, IRP_RETURNED) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001239
1240 /// See AbstractAttriubute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001241 void initialize(Attributor &A, InformationCache &InfoCache) override {
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001242 Function &F = getAnchorScope();
1243
1244 // Already noalias.
1245 if (F.returnDoesNotAlias()) {
1246 indicateOptimisticFixpoint();
1247 return;
1248 }
1249 }
1250
1251 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001252 virtual ChangeStatus updateImpl(Attributor &A,
1253 InformationCache &InfoCache) override;
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001254};
1255
Johannes Doerfert007153e2019-08-05 23:26:06 +00001256ChangeStatus AANoAliasReturned::updateImpl(Attributor &A,
1257 InformationCache &InfoCache) {
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001258 Function &F = getAnchorScope();
1259
Johannes Doerfert14a04932019-08-07 22:27:24 +00001260 auto CheckReturnValue = [&](Value &RV) -> bool {
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001261 if (Constant *C = dyn_cast<Constant>(&RV))
1262 if (C->isNullValue() || isa<UndefValue>(C))
1263 return true;
1264
1265 /// For now, we can only deduce noalias if we have call sites.
1266 /// FIXME: add more support.
1267 ImmutableCallSite ICS(&RV);
1268 if (!ICS)
1269 return false;
1270
Johannes Doerfert14a04932019-08-07 22:27:24 +00001271 if (!ICS.returnDoesNotAlias()) {
1272 auto *NoAliasAA = A.getAAFor<AANoAlias>(*this, RV);
1273 if (!NoAliasAA || !NoAliasAA->isAssumedNoAlias())
1274 return false;
1275 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001276
1277 /// FIXME: We can improve capture check in two ways:
1278 /// 1. Use the AANoCapture facilities.
1279 /// 2. Use the location of return insts for escape queries.
1280 if (PointerMayBeCaptured(&RV, /* ReturnCaptures */ false,
1281 /* StoreCaptures */ true))
1282 return false;
1283
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001284 return true;
1285 };
1286
Johannes Doerfert14a04932019-08-07 22:27:24 +00001287 if (!A.checkForAllReturnedValues(F, CheckReturnValue, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001288 return indicatePessimisticFixpoint();
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001289
1290 return ChangeStatus::UNCHANGED;
1291}
1292
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001293/// -------------------AAIsDead Function Attribute-----------------------
1294
Johannes Doerfert344d0382019-08-07 22:34:26 +00001295struct AAIsDeadImpl : public AAIsDead {
Johannes Doerferteccdf082019-08-05 23:35:12 +00001296 IRPositionConstructorForward(AAIsDeadImpl, AAIsDead);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001297
Johannes Doerfert007153e2019-08-05 23:26:06 +00001298 void initialize(Attributor &A, InformationCache &InfoCache) override {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001299 Function &F = getAnchorScope();
1300
1301 ToBeExploredPaths.insert(&(F.getEntryBlock().front()));
1302 AssumedLiveBlocks.insert(&(F.getEntryBlock()));
1303 for (size_t i = 0; i < ToBeExploredPaths.size(); ++i)
Johannes Doerfert4361da22019-08-04 18:38:53 +00001304 if (const Instruction *NextNoReturnI =
1305 findNextNoReturn(A, ToBeExploredPaths[i]))
1306 NoReturnCalls.insert(NextNoReturnI);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001307 }
1308
Johannes Doerfert4361da22019-08-04 18:38:53 +00001309 /// Find the next assumed noreturn instruction in the block of \p I starting
1310 /// from, thus including, \p I.
1311 ///
1312 /// The caller is responsible to monitor the ToBeExploredPaths set as new
1313 /// instructions discovered in other basic block will be placed in there.
1314 ///
1315 /// \returns The next assumed noreturn instructions in the block of \p I
1316 /// starting from, thus including, \p I.
1317 const Instruction *findNextNoReturn(Attributor &A, const Instruction *I);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001318
1319 const std::string getAsStr() const override {
1320 return "LiveBBs(" + std::to_string(AssumedLiveBlocks.size()) + "/" +
1321 std::to_string(getAnchorScope().size()) + ")";
1322 }
1323
1324 /// See AbstractAttribute::manifest(...).
1325 ChangeStatus manifest(Attributor &A) override {
1326 assert(getState().isValidState() &&
1327 "Attempted to manifest an invalid state!");
1328
1329 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Johannes Doerfert924d2132019-08-05 21:34:45 +00001330 const Function &F = getAnchorScope();
1331
1332 // Flag to determine if we can change an invoke to a call assuming the callee
1333 // is nounwind. This is not possible if the personality of the function allows
1334 // to catch asynchronous exceptions.
1335 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001336
Johannes Doerfert4361da22019-08-04 18:38:53 +00001337 for (const Instruction *NRC : NoReturnCalls) {
1338 Instruction *I = const_cast<Instruction *>(NRC);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001339 BasicBlock *BB = I->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001340 Instruction *SplitPos = I->getNextNode();
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001341
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001342 if (auto *II = dyn_cast<InvokeInst>(I)) {
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001343 // If we keep the invoke the split position is at the beginning of the
1344 // normal desitination block (it invokes a noreturn function after all).
1345 BasicBlock *NormalDestBB = II->getNormalDest();
1346 SplitPos = &NormalDestBB->front();
1347
Johannes Doerfert4361da22019-08-04 18:38:53 +00001348 /// Invoke is replaced with a call and unreachable is placed after it if
1349 /// the callee is nounwind and noreturn. Otherwise, we keep the invoke
1350 /// and only place an unreachable in the normal successor.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001351 if (Invoke2CallAllowed) {
1352 if (Function *Callee = II->getCalledFunction()) {
1353 auto *AANoUnw = A.getAAFor<AANoUnwind>(*this, *Callee);
1354 if (Callee->hasFnAttribute(Attribute::NoUnwind) ||
1355 (AANoUnw && AANoUnw->isAssumedNoUnwind())) {
1356 LLVM_DEBUG(dbgs()
1357 << "[AAIsDead] Replace invoke with call inst\n");
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001358 // We do not need an invoke (II) but instead want a call followed
1359 // by an unreachable. However, we do not remove II as other
1360 // abstract attributes might have it cached as part of their
1361 // results. Given that we modify the CFG anyway, we simply keep II
1362 // around but in a new dead block. To avoid II being live through
1363 // a different edge we have to ensure the block we place it in is
1364 // only reached from the current block of II and then not reached
1365 // at all when we insert the unreachable.
1366 SplitBlockPredecessors(NormalDestBB, {BB}, ".i2c");
1367 CallInst *CI = createCallMatchingInvoke(II);
1368 CI->insertBefore(II);
1369 CI->takeName(II);
1370 II->replaceAllUsesWith(CI);
1371 SplitPos = CI->getNextNode();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001372 }
Johannes Doerfert4361da22019-08-04 18:38:53 +00001373 }
1374 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001375 }
1376
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001377 BB = SplitPos->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001378 SplitBlock(BB, SplitPos);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001379 changeToUnreachable(BB->getTerminator(), /* UseLLVMTrap */ false);
1380 HasChanged = ChangeStatus::CHANGED;
1381 }
1382
1383 return HasChanged;
1384 }
1385
1386 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001387 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001388
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001389 /// See AAIsDead::isAssumedDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001390 bool isAssumedDead(const BasicBlock *BB) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001391 assert(BB->getParent() == &getAnchorScope() &&
1392 "BB must be in the same anchor scope function.");
1393
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001394 if (!getAssumed())
1395 return false;
1396 return !AssumedLiveBlocks.count(BB);
1397 }
1398
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001399 /// See AAIsDead::isKnownDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001400 bool isKnownDead(const BasicBlock *BB) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001401 return getKnown() && isAssumedDead(BB);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001402 }
1403
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001404 /// See AAIsDead::isAssumed(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001405 bool isAssumedDead(const Instruction *I) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001406 assert(I->getParent()->getParent() == &getAnchorScope() &&
1407 "Instruction must be in the same anchor scope function.");
1408
Stefan Stipanovic7849e412019-08-03 15:27:41 +00001409 if (!getAssumed())
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001410 return false;
1411
1412 // If it is not in AssumedLiveBlocks then it for sure dead.
1413 // Otherwise, it can still be after noreturn call in a live block.
1414 if (!AssumedLiveBlocks.count(I->getParent()))
1415 return true;
1416
1417 // If it is not after a noreturn call, than it is live.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001418 return isAfterNoReturn(I);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001419 }
1420
1421 /// See AAIsDead::isKnownDead(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001422 bool isKnownDead(const Instruction *I) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001423 return getKnown() && isAssumedDead(I);
1424 }
1425
1426 /// Check if instruction is after noreturn call, in other words, assumed dead.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001427 bool isAfterNoReturn(const Instruction *I) const;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001428
Johannes Doerfert924d2132019-08-05 21:34:45 +00001429 /// Determine if \p F might catch asynchronous exceptions.
1430 static bool mayCatchAsynchronousExceptions(const Function &F) {
1431 return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F);
1432 }
1433
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001434 /// Collection of to be explored paths.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001435 SmallSetVector<const Instruction *, 8> ToBeExploredPaths;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001436
1437 /// Collection of all assumed live BasicBlocks.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001438 DenseSet<const BasicBlock *> AssumedLiveBlocks;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001439
1440 /// Collection of calls with noreturn attribute, assumed or knwon.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001441 SmallSetVector<const Instruction *, 4> NoReturnCalls;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001442};
1443
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001444struct AAIsDeadFunction final : public AAIsDeadImpl {
1445 AAIsDeadFunction(Function &F) : AAIsDeadImpl(F, IRP_FUNCTION) {}
1446};
1447
1448bool AAIsDeadImpl::isAfterNoReturn(const Instruction *I) const {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001449 const Instruction *PrevI = I->getPrevNode();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001450 while (PrevI) {
1451 if (NoReturnCalls.count(PrevI))
1452 return true;
1453 PrevI = PrevI->getPrevNode();
1454 }
1455 return false;
1456}
1457
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001458const Instruction *AAIsDeadImpl::findNextNoReturn(Attributor &A,
1459 const Instruction *I) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001460 const BasicBlock *BB = I->getParent();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001461 const Function &F = *BB->getParent();
1462
1463 // Flag to determine if we can change an invoke to a call assuming the callee
1464 // is nounwind. This is not possible if the personality of the function allows
1465 // to catch asynchronous exceptions.
1466 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001467
1468 // TODO: We should have a function that determines if an "edge" is dead.
1469 // Edges could be from an instruction to the next or from a terminator
1470 // to the successor. For now, we need to special case the unwind block
1471 // of InvokeInst below.
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001472
1473 while (I) {
1474 ImmutableCallSite ICS(I);
1475
1476 if (ICS) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001477 // Regarless of the no-return property of an invoke instruction we only
1478 // learn that the regular successor is not reachable through this
1479 // instruction but the unwind block might still be.
1480 if (auto *Invoke = dyn_cast<InvokeInst>(I)) {
1481 // Use nounwind to justify the unwind block is dead as well.
1482 auto *AANoUnw = A.getAAFor<AANoUnwind>(*this, *Invoke);
Johannes Doerfert924d2132019-08-05 21:34:45 +00001483 if (!Invoke2CallAllowed ||
1484 (!AANoUnw || !AANoUnw->isAssumedNoUnwind())) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001485 AssumedLiveBlocks.insert(Invoke->getUnwindDest());
1486 ToBeExploredPaths.insert(&Invoke->getUnwindDest()->front());
1487 }
1488 }
1489
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001490 auto *NoReturnAA = A.getAAFor<AANoReturn>(*this, *I);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001491 if (ICS.hasFnAttr(Attribute::NoReturn) ||
1492 (NoReturnAA && NoReturnAA->isAssumedNoReturn()))
1493 return I;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001494 }
1495
1496 I = I->getNextNode();
1497 }
1498
1499 // get new paths (reachable blocks).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001500 for (const BasicBlock *SuccBB : successors(BB)) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001501 AssumedLiveBlocks.insert(SuccBB);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001502 ToBeExploredPaths.insert(&SuccBB->front());
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001503 }
1504
Johannes Doerfert4361da22019-08-04 18:38:53 +00001505 // No noreturn instruction found.
1506 return nullptr;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001507}
1508
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001509ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A,
1510 InformationCache &InfoCache) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001511 // Temporary collection to iterate over existing noreturn instructions. This
1512 // will alow easier modification of NoReturnCalls collection
Johannes Doerfert4361da22019-08-04 18:38:53 +00001513 SmallVector<const Instruction *, 8> NoReturnChanged;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001514 ChangeStatus Status = ChangeStatus::UNCHANGED;
1515
Johannes Doerfert4361da22019-08-04 18:38:53 +00001516 for (const Instruction *I : NoReturnCalls)
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001517 NoReturnChanged.push_back(I);
1518
Johannes Doerfert4361da22019-08-04 18:38:53 +00001519 for (const Instruction *I : NoReturnChanged) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001520 size_t Size = ToBeExploredPaths.size();
1521
Johannes Doerfert4361da22019-08-04 18:38:53 +00001522 const Instruction *NextNoReturnI = findNextNoReturn(A, I);
1523 if (NextNoReturnI != I) {
1524 Status = ChangeStatus::CHANGED;
1525 NoReturnCalls.remove(I);
1526 if (NextNoReturnI)
1527 NoReturnCalls.insert(NextNoReturnI);
1528 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001529
Johannes Doerfert4361da22019-08-04 18:38:53 +00001530 // Explore new paths.
1531 while (Size != ToBeExploredPaths.size()) {
1532 Status = ChangeStatus::CHANGED;
1533 if (const Instruction *NextNoReturnI =
1534 findNextNoReturn(A, ToBeExploredPaths[Size++]))
1535 NoReturnCalls.insert(NextNoReturnI);
1536 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001537 }
1538
Hideto Ueno19c07af2019-07-23 08:16:17 +00001539 LLVM_DEBUG(
1540 dbgs() << "[AAIsDead] AssumedLiveBlocks: " << AssumedLiveBlocks.size()
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001541 << " Total number of blocks: " << getAnchorScope().size() << "\n");
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001542
Johannes Doerfertd6207812019-08-07 22:32:38 +00001543 // If we know everything is live there is no need to query for liveness.
1544 if (NoReturnCalls.empty() &&
1545 getAnchorScope().size() == AssumedLiveBlocks.size()) {
1546 // Indicating a pessimistic fixpoint will cause the state to be "invalid"
1547 // which will cause the Attributor to not return the AAIsDead on request,
1548 // which will prevent us from querying isAssumedDead().
1549 indicatePessimisticFixpoint();
1550 assert(!isValidState() && "Expected an invalid state!");
1551 }
1552
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001553 return Status;
1554}
1555
Hideto Ueno19c07af2019-07-23 08:16:17 +00001556/// -------------------- Dereferenceable Argument Attribute --------------------
1557
1558struct DerefState : AbstractState {
1559
1560 /// State representing for dereferenceable bytes.
1561 IntegerState DerefBytesState;
1562
1563 /// State representing that whether the value is nonnull or global.
1564 IntegerState NonNullGlobalState;
1565
1566 /// Bits encoding for NonNullGlobalState.
1567 enum {
1568 DEREF_NONNULL = 1 << 0,
1569 DEREF_GLOBAL = 1 << 1,
1570 };
1571
1572 /// See AbstractState::isValidState()
1573 bool isValidState() const override { return DerefBytesState.isValidState(); }
1574
Johannes Doerfertb6acee52019-08-04 17:55:15 +00001575 /// See AbstractState::isAtFixpoint()
Hideto Ueno19c07af2019-07-23 08:16:17 +00001576 bool isAtFixpoint() const override {
Johannes Doerfertb6acee52019-08-04 17:55:15 +00001577 return !isValidState() || (DerefBytesState.isAtFixpoint() &&
1578 NonNullGlobalState.isAtFixpoint());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001579 }
1580
1581 /// See AbstractState::indicateOptimisticFixpoint(...)
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001582 ChangeStatus indicateOptimisticFixpoint() override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001583 DerefBytesState.indicateOptimisticFixpoint();
1584 NonNullGlobalState.indicateOptimisticFixpoint();
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001585 return ChangeStatus::UNCHANGED;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001586 }
1587
1588 /// See AbstractState::indicatePessimisticFixpoint(...)
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001589 ChangeStatus indicatePessimisticFixpoint() override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001590 DerefBytesState.indicatePessimisticFixpoint();
1591 NonNullGlobalState.indicatePessimisticFixpoint();
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001592 return ChangeStatus::CHANGED;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001593 }
1594
1595 /// Update known dereferenceable bytes.
1596 void takeKnownDerefBytesMaximum(uint64_t Bytes) {
1597 DerefBytesState.takeKnownMaximum(Bytes);
1598 }
1599
1600 /// Update assumed dereferenceable bytes.
1601 void takeAssumedDerefBytesMinimum(uint64_t Bytes) {
1602 DerefBytesState.takeAssumedMinimum(Bytes);
1603 }
1604
1605 /// Update assumed NonNullGlobalState
1606 void updateAssumedNonNullGlobalState(bool IsNonNull, bool IsGlobal) {
1607 if (!IsNonNull)
1608 NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
1609 if (!IsGlobal)
1610 NonNullGlobalState.removeAssumedBits(DEREF_GLOBAL);
1611 }
1612
1613 /// Equality for DerefState.
1614 bool operator==(const DerefState &R) {
1615 return this->DerefBytesState == R.DerefBytesState &&
1616 this->NonNullGlobalState == R.NonNullGlobalState;
1617 }
1618};
Hideto Ueno19c07af2019-07-23 08:16:17 +00001619
Johannes Doerferteccdf082019-08-05 23:35:12 +00001620struct AADereferenceableImpl : AADereferenceable, DerefState {
1621 IRPositionConstructorForward(AADereferenceableImpl, AADereferenceable);
Johannes Doerfert344d0382019-08-07 22:34:26 +00001622 using StateType = DerefState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001623
1624 /// See AbstractAttribute::getState()
1625 /// {
Johannes Doerfert344d0382019-08-07 22:34:26 +00001626 StateType &getState() override { return *this; }
1627 const StateType &getState() const override { return *this; }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001628 /// }
1629
1630 /// See AADereferenceable::getAssumedDereferenceableBytes().
1631 uint32_t getAssumedDereferenceableBytes() const override {
1632 return DerefBytesState.getAssumed();
1633 }
1634
1635 /// See AADereferenceable::getKnownDereferenceableBytes().
1636 uint32_t getKnownDereferenceableBytes() const override {
1637 return DerefBytesState.getKnown();
1638 }
1639
1640 // Helper function for syncing nonnull state.
1641 void syncNonNull(const AANonNull *NonNullAA) {
1642 if (!NonNullAA) {
1643 NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
1644 return;
1645 }
1646
1647 if (NonNullAA->isKnownNonNull())
1648 NonNullGlobalState.addKnownBits(DEREF_NONNULL);
1649
1650 if (!NonNullAA->isAssumedNonNull())
1651 NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
1652 }
1653
1654 /// See AADereferenceable::isAssumedGlobal().
1655 bool isAssumedGlobal() const override {
1656 return NonNullGlobalState.isAssumed(DEREF_GLOBAL);
1657 }
1658
1659 /// See AADereferenceable::isKnownGlobal().
1660 bool isKnownGlobal() const override {
1661 return NonNullGlobalState.isKnown(DEREF_GLOBAL);
1662 }
1663
1664 /// See AADereferenceable::isAssumedNonNull().
1665 bool isAssumedNonNull() const override {
1666 return NonNullGlobalState.isAssumed(DEREF_NONNULL);
1667 }
1668
1669 /// See AADereferenceable::isKnownNonNull().
1670 bool isKnownNonNull() const override {
1671 return NonNullGlobalState.isKnown(DEREF_NONNULL);
1672 }
1673
Johannes Doerferteccdf082019-08-05 23:35:12 +00001674 void getDeducedAttributes(LLVMContext &Ctx,
1675 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001676 // TODO: Add *_globally support
1677 if (isAssumedNonNull())
1678 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
1679 Ctx, getAssumedDereferenceableBytes()));
1680 else
1681 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
1682 Ctx, getAssumedDereferenceableBytes()));
1683 }
1684 uint64_t computeAssumedDerefenceableBytes(Attributor &A, Value &V,
1685 bool &IsNonNull, bool &IsGlobal);
1686
Johannes Doerfert007153e2019-08-05 23:26:06 +00001687 void initialize(Attributor &A, InformationCache &InfoCache) override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001688 Function &F = getAnchorScope();
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001689 unsigned AttrIdx = getIRPosition().getAttrIdx();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001690
1691 for (Attribute::AttrKind AK :
1692 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull})
1693 if (F.getAttributes().hasAttribute(AttrIdx, AK))
1694 takeKnownDerefBytesMaximum(F.getAttribute(AttrIdx, AK).getValueAsInt());
1695 }
1696
1697 /// See AbstractAttribute::getAsStr().
1698 const std::string getAsStr() const override {
1699 if (!getAssumedDereferenceableBytes())
1700 return "unknown-dereferenceable";
1701 return std::string("dereferenceable") +
1702 (isAssumedNonNull() ? "" : "_or_null") +
1703 (isAssumedGlobal() ? "_globally" : "") + "<" +
1704 std::to_string(getKnownDereferenceableBytes()) + "-" +
1705 std::to_string(getAssumedDereferenceableBytes()) + ">";
1706 }
1707};
1708
1709struct AADereferenceableReturned : AADereferenceableImpl {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001710 AADereferenceableReturned(Function &F)
1711 : AADereferenceableImpl(F, IRP_RETURNED) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001712
1713 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001714 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001715};
1716
1717// Helper function that returns dereferenceable bytes.
1718static uint64_t calcDifferenceIfBaseIsNonNull(int64_t DerefBytes,
1719 int64_t Offset, bool IsNonNull) {
1720 if (!IsNonNull)
1721 return 0;
1722 return std::max((int64_t)0, DerefBytes - Offset);
1723}
1724
1725uint64_t AADereferenceableImpl::computeAssumedDerefenceableBytes(
1726 Attributor &A, Value &V, bool &IsNonNull, bool &IsGlobal) {
1727 // TODO: Tracking the globally flag.
1728 IsGlobal = false;
1729
1730 // First, we try to get information about V from Attributor.
1731 if (auto *DerefAA = A.getAAFor<AADereferenceable>(*this, V)) {
1732 IsNonNull &= DerefAA->isAssumedNonNull();
1733 return DerefAA->getAssumedDereferenceableBytes();
1734 }
1735
1736 // Otherwise, we try to compute assumed bytes from base pointer.
1737 const DataLayout &DL = getAnchorScope().getParent()->getDataLayout();
1738 unsigned IdxWidth =
1739 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
1740 APInt Offset(IdxWidth, 0);
1741 Value *Base = V.stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
1742
1743 if (auto *BaseDerefAA = A.getAAFor<AADereferenceable>(*this, *Base)) {
1744 IsNonNull &= Offset != 0;
1745 return calcDifferenceIfBaseIsNonNull(
1746 BaseDerefAA->getAssumedDereferenceableBytes(), Offset.getSExtValue(),
1747 Offset != 0 || BaseDerefAA->isAssumedNonNull());
1748 }
1749
1750 // Then, use IR information.
1751
1752 if (isDereferenceablePointer(Base, Base->getType(), DL))
1753 return calcDifferenceIfBaseIsNonNull(
1754 DL.getTypeStoreSize(Base->getType()->getPointerElementType()),
1755 Offset.getSExtValue(),
1756 !NullPointerIsDefined(&getAnchorScope(),
1757 V.getType()->getPointerAddressSpace()));
1758
1759 IsNonNull = false;
1760 return 0;
1761}
Johannes Doerfert007153e2019-08-05 23:26:06 +00001762
1763ChangeStatus
1764AADereferenceableReturned::updateImpl(Attributor &A,
1765 InformationCache &InfoCache) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001766 Function &F = getAnchorScope();
1767 auto BeforeState = static_cast<DerefState>(*this);
1768
1769 syncNonNull(A.getAAFor<AANonNull>(*this, F));
1770
Hideto Ueno19c07af2019-07-23 08:16:17 +00001771 bool IsNonNull = isAssumedNonNull();
1772 bool IsGlobal = isAssumedGlobal();
1773
Johannes Doerfert14a04932019-08-07 22:27:24 +00001774 auto CheckReturnValue = [&](Value &RV) -> bool {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001775 takeAssumedDerefBytesMinimum(
1776 computeAssumedDerefenceableBytes(A, RV, IsNonNull, IsGlobal));
1777 return isValidState();
1778 };
1779
Johannes Doerfert14a04932019-08-07 22:27:24 +00001780 if (A.checkForAllReturnedValues(F, CheckReturnValue, *this)) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001781 updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
1782 return BeforeState == static_cast<DerefState>(*this)
1783 ? ChangeStatus::UNCHANGED
1784 : ChangeStatus::CHANGED;
1785 }
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001786 return indicatePessimisticFixpoint();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001787}
1788
1789struct AADereferenceableArgument : AADereferenceableImpl {
Johannes Doerfert007153e2019-08-05 23:26:06 +00001790 AADereferenceableArgument(Argument &A) : AADereferenceableImpl(A) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001791
Hideto Ueno19c07af2019-07-23 08:16:17 +00001792 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001793 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001794};
1795
Johannes Doerfert007153e2019-08-05 23:26:06 +00001796ChangeStatus
1797AADereferenceableArgument::updateImpl(Attributor &A,
1798 InformationCache &InfoCache) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001799 Function &F = getAnchorScope();
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001800 Argument &Arg = cast<Argument>(getAnchorValue());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001801
1802 auto BeforeState = static_cast<DerefState>(*this);
1803
1804 unsigned ArgNo = Arg.getArgNo();
1805
1806 syncNonNull(A.getAAFor<AANonNull>(*this, F, ArgNo));
1807
1808 bool IsNonNull = isAssumedNonNull();
1809 bool IsGlobal = isAssumedGlobal();
1810
1811 // Callback function
1812 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) -> bool {
1813 assert(CS && "Sanity check: Call site was not initialized properly!");
1814
1815 // Check that DereferenceableAA is AADereferenceableCallSiteArgument.
1816 if (auto *DereferenceableAA =
1817 A.getAAFor<AADereferenceable>(*this, *CS.getInstruction(), ArgNo)) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001818 ImmutableCallSite ICS(
1819 &DereferenceableAA->getIRPosition().getAnchorValue());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001820 if (ICS && CS.getInstruction() == ICS.getInstruction()) {
1821 takeAssumedDerefBytesMinimum(
1822 DereferenceableAA->getAssumedDereferenceableBytes());
1823 IsNonNull &= DereferenceableAA->isAssumedNonNull();
1824 IsGlobal &= DereferenceableAA->isAssumedGlobal();
1825 return isValidState();
1826 }
1827 }
1828
1829 takeAssumedDerefBytesMinimum(computeAssumedDerefenceableBytes(
1830 A, *CS.getArgOperand(ArgNo), IsNonNull, IsGlobal));
1831
1832 return isValidState();
1833 };
1834
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001835 if (!A.checkForAllCallSites(F, CallSiteCheck, *this, true))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001836 return indicatePessimisticFixpoint();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001837
1838 updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
1839
1840 return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
1841 : ChangeStatus::CHANGED;
1842}
1843
1844/// Dereferenceable attribute for a call site argument.
1845struct AADereferenceableCallSiteArgument : AADereferenceableImpl {
1846
1847 /// See AADereferenceableImpl::AADereferenceableImpl(...).
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00001848 AADereferenceableCallSiteArgument(Instruction &I, unsigned ArgNo)
1849 : AADereferenceableImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001850
1851 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001852 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001853 CallSite CS(&getAnchorValue());
1854 if (CS.paramHasAttr(getArgNo(), Attribute::Dereferenceable))
1855 takeKnownDerefBytesMaximum(CS.getDereferenceableBytes(getArgNo()));
Hideto Ueno19c07af2019-07-23 08:16:17 +00001856
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001857 if (CS.paramHasAttr(getArgNo(), Attribute::DereferenceableOrNull))
1858 takeKnownDerefBytesMaximum(CS.getDereferenceableOrNullBytes(getArgNo()));
Hideto Ueno19c07af2019-07-23 08:16:17 +00001859 }
1860
1861 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001862 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001863};
1864
Johannes Doerfert007153e2019-08-05 23:26:06 +00001865ChangeStatus
1866AADereferenceableCallSiteArgument::updateImpl(Attributor &A,
1867 InformationCache &InfoCache) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001868 // NOTE: Never look at the argument of the callee in this method.
1869 // If we do this, "dereferenceable" is always deduced because of the
1870 // assumption.
1871
1872 Value &V = *getAssociatedValue();
1873
1874 auto BeforeState = static_cast<DerefState>(*this);
1875
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001876 syncNonNull(A.getAAFor<AANonNull>(*this, getAnchorValue(), getArgNo()));
Hideto Ueno19c07af2019-07-23 08:16:17 +00001877 bool IsNonNull = isAssumedNonNull();
1878 bool IsGlobal = isKnownGlobal();
1879
1880 takeAssumedDerefBytesMinimum(
1881 computeAssumedDerefenceableBytes(A, V, IsNonNull, IsGlobal));
1882 updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
1883
1884 return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
1885 : ChangeStatus::CHANGED;
1886}
1887
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001888// ------------------------ Align Argument Attribute ------------------------
1889
Johannes Doerfert344d0382019-08-07 22:34:26 +00001890struct AAAlignImpl : AAAlign {
Johannes Doerferteccdf082019-08-05 23:35:12 +00001891 IRPositionConstructorForward(AAAlignImpl, AAAlign);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001892
1893 // Max alignemnt value allowed in IR
1894 static const unsigned MAX_ALIGN = 1U << 29;
1895
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001896 virtual const std::string getAsStr() const override {
1897 return getAssumedAlign() ? ("align<" + std::to_string(getKnownAlign()) +
1898 "-" + std::to_string(getAssumedAlign()) + ">")
1899 : "unknown-align";
1900 }
1901
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001902 /// See AbstractAttriubute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001903 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001904 takeAssumedMinimum(MAX_ALIGN);
1905
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001906 Function &F = getAnchorScope();
1907
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001908 unsigned AttrIdx = getIRPosition().getAttrIdx();
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001909
1910 // Already the function has align attribute on return value or argument.
Johannes Doerfert24020622019-08-05 23:30:01 +00001911 if (F.getAttributes().hasAttribute(AttrIdx, Attribute::Alignment))
1912 addKnownBits(
1913 F.getAttribute(AttrIdx, Attribute::Alignment).getAlignment());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001914 }
1915
1916 /// See AbstractAttribute::getDeducedAttributes
1917 virtual void
Johannes Doerferteccdf082019-08-05 23:35:12 +00001918 getDeducedAttributes(LLVMContext &Ctx,
1919 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001920 Attrs.emplace_back(Attribute::getWithAlignment(Ctx, getAssumedAlign()));
1921 }
1922};
1923
1924/// Align attribute for function return value.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001925struct AAAlignReturned final : AAAlignImpl {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001926
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001927 AAAlignReturned(Function &F) : AAAlignImpl(F, IRP_RETURNED) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001928
1929 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001930 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001931};
1932
Johannes Doerfert007153e2019-08-05 23:26:06 +00001933ChangeStatus AAAlignReturned::updateImpl(Attributor &A,
1934 InformationCache &InfoCache) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001935 Function &F = getAnchorScope();
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001936
1937 // Currently, align<n> is deduced if alignments in return values are assumed
1938 // as greater than n. We reach pessimistic fixpoint if any of the return value
1939 // wouldn't have align. If no assumed state was used for reasoning, an
1940 // optimistic fixpoint is reached earlier.
1941
1942 base_t BeforeState = getAssumed();
Johannes Doerfert14a04932019-08-07 22:27:24 +00001943 auto CheckReturnValue =
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001944 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &RetInsts) -> bool {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001945 auto *AlignAA = A.getAAFor<AAAlign>(*this, RV);
1946
1947 if (AlignAA)
1948 takeAssumedMinimum(AlignAA->getAssumedAlign());
1949 else
1950 // Use IR information.
1951 takeAssumedMinimum(RV.getPointerAlignment(
1952 getAnchorScope().getParent()->getDataLayout()));
1953
1954 return isValidState();
1955 };
1956
Johannes Doerfert14a04932019-08-07 22:27:24 +00001957 if (!A.checkForAllReturnedValuesAndReturnInsts(F, CheckReturnValue, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001958 return indicatePessimisticFixpoint();
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001959
1960 return (getAssumed() != BeforeState) ? ChangeStatus::CHANGED
1961 : ChangeStatus::UNCHANGED;
1962}
1963
1964/// Align attribute for function argument.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001965struct AAAlignArgument final : AAAlignImpl {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001966
Johannes Doerfert007153e2019-08-05 23:26:06 +00001967 AAAlignArgument(Argument &A) : AAAlignImpl(A) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001968
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001969 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001970 virtual ChangeStatus updateImpl(Attributor &A,
1971 InformationCache &InfoCache) override;
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001972};
1973
Johannes Doerfert007153e2019-08-05 23:26:06 +00001974ChangeStatus AAAlignArgument::updateImpl(Attributor &A,
1975 InformationCache &InfoCache) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001976
1977 Function &F = getAnchorScope();
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001978 Argument &Arg = cast<Argument>(getAnchorValue());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001979
1980 unsigned ArgNo = Arg.getArgNo();
1981 const DataLayout &DL = F.getParent()->getDataLayout();
1982
1983 auto BeforeState = getAssumed();
1984
1985 // Callback function
1986 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) {
1987 assert(CS && "Sanity check: Call site was not initialized properly!");
1988
1989 auto *AlignAA = A.getAAFor<AAAlign>(*this, *CS.getInstruction(), ArgNo);
1990
1991 // Check that AlignAA is AAAlignCallSiteArgument.
1992 if (AlignAA) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001993 ImmutableCallSite ICS(&AlignAA->getIRPosition().getAnchorValue());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001994 if (ICS && CS.getInstruction() == ICS.getInstruction()) {
1995 takeAssumedMinimum(AlignAA->getAssumedAlign());
1996 return isValidState();
1997 }
1998 }
1999
2000 Value *V = CS.getArgOperand(ArgNo);
2001 takeAssumedMinimum(V->getPointerAlignment(DL));
2002 return isValidState();
2003 };
2004
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002005 if (!A.checkForAllCallSites(F, CallSiteCheck, *this, true))
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002006 indicatePessimisticFixpoint();
2007
2008 return BeforeState == getAssumed() ? ChangeStatus::UNCHANGED
2009 : ChangeStatus ::CHANGED;
2010}
2011
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002012struct AAAlignCallSiteArgument final : AAAlignImpl {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002013
2014 /// See AANonNullImpl::AANonNullImpl(...).
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002015 AAAlignCallSiteArgument(Instruction &I, unsigned ArgNo)
2016 : AAAlignImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002017
2018 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00002019 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002020 CallSite CS(&getAnchorValue());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002021 takeKnownMaximum(getAssociatedValue()->getPointerAlignment(
2022 getAnchorScope().getParent()->getDataLayout()));
2023 }
2024
2025 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfert007153e2019-08-05 23:26:06 +00002026 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002027};
2028
Johannes Doerfert007153e2019-08-05 23:26:06 +00002029ChangeStatus AAAlignCallSiteArgument::updateImpl(Attributor &A,
2030 InformationCache &InfoCache) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002031 // NOTE: Never look at the argument of the callee in this method.
2032 // If we do this, "align" is always deduced because of the assumption.
2033
2034 auto BeforeState = getAssumed();
2035
2036 Value &V = *getAssociatedValue();
2037
2038 auto *AlignAA = A.getAAFor<AAAlign>(*this, V);
2039
2040 if (AlignAA)
2041 takeAssumedMinimum(AlignAA->getAssumedAlign());
2042 else
2043 indicatePessimisticFixpoint();
2044
2045 return BeforeState == getAssumed() ? ChangeStatus::UNCHANGED
2046 : ChangeStatus::CHANGED;
2047}
2048
Johannes Doerferte83f3032019-08-05 23:22:05 +00002049/// ------------------ Function No-Return Attribute ----------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00002050struct AANoReturnImpl : public AANoReturn {
Johannes Doerferteccdf082019-08-05 23:35:12 +00002051 IRPositionConstructorForward(AANoReturnImpl, AANoReturn);
Johannes Doerferte83f3032019-08-05 23:22:05 +00002052
Johannes Doerferte83f3032019-08-05 23:22:05 +00002053 /// See AbstractAttribute::getAsStr().
2054 const std::string getAsStr() const override {
2055 return getAssumed() ? "noreturn" : "may-return";
2056 }
2057
2058 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00002059 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerferte83f3032019-08-05 23:22:05 +00002060 Function &F = getAnchorScope();
2061 if (F.hasFnAttribute(getAttrKind()))
2062 indicateOptimisticFixpoint();
2063 }
2064
2065 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfert007153e2019-08-05 23:26:06 +00002066 virtual ChangeStatus updateImpl(Attributor &A,
2067 InformationCache &InfoCache) override {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002068 const Function &F = getAnchorScope();
2069 auto CheckForNoReturn = [](Instruction &) { return false; };
2070 if (!A.checkForAllInstructions(F, CheckForNoReturn, *this, InfoCache,
2071 {(unsigned)Instruction::Ret}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002072 return indicatePessimisticFixpoint();
Johannes Doerferte83f3032019-08-05 23:22:05 +00002073 return ChangeStatus::UNCHANGED;
2074 }
2075};
2076
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002077struct AANoReturnFunction final : AANoReturnImpl {
2078 AANoReturnFunction(Function &F) : AANoReturnImpl(F, IRP_FUNCTION) {}
2079};
2080
Johannes Doerfertaade7822019-06-05 03:02:24 +00002081/// ----------------------------------------------------------------------------
2082/// Attributor
2083/// ----------------------------------------------------------------------------
2084
Hideto Ueno54869ec2019-07-15 06:49:04 +00002085bool Attributor::checkForAllCallSites(Function &F,
2086 std::function<bool(CallSite)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002087 const AbstractAttribute &QueryingAA,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002088 bool RequireAllCallSites) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002089 // We can try to determine information from
2090 // the call sites. However, this is only possible all call sites are known,
2091 // hence the function has internal linkage.
2092 if (RequireAllCallSites && !F.hasInternalLinkage()) {
2093 LLVM_DEBUG(
2094 dbgs()
2095 << "Attributor: Function " << F.getName()
2096 << " has no internal linkage, hence not all call sites are known\n");
2097 return false;
2098 }
2099
2100 for (const Use &U : F.uses()) {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002101 Instruction *I = cast<Instruction>(U.getUser());
2102 Function *AnchorValue = I->getParent()->getParent();
2103
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002104 auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, *AnchorValue);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002105
2106 // Skip dead calls.
2107 if (LivenessAA && LivenessAA->isAssumedDead(I))
2108 continue;
Hideto Ueno54869ec2019-07-15 06:49:04 +00002109
2110 CallSite CS(U.getUser());
Hideto Ueno54869ec2019-07-15 06:49:04 +00002111 if (!CS || !CS.isCallee(&U) || !CS.getCaller()->hasExactDefinition()) {
2112 if (!RequireAllCallSites)
2113 continue;
2114
2115 LLVM_DEBUG(dbgs() << "Attributor: User " << *U.getUser()
2116 << " is an invalid use of " << F.getName() << "\n");
2117 return false;
2118 }
2119
2120 if (Pred(CS))
2121 continue;
2122
2123 LLVM_DEBUG(dbgs() << "Attributor: Call site callback failed for "
2124 << *CS.getInstruction() << "\n");
2125 return false;
2126 }
2127
2128 return true;
2129}
2130
Johannes Doerfert14a04932019-08-07 22:27:24 +00002131bool Attributor::checkForAllReturnedValuesAndReturnInsts(
2132 const Function &F,
2133 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
2134 &Pred,
2135 const AbstractAttribute &QueryingAA) {
2136
2137 auto *AARetVal = getAAFor<AAReturnedValues>(QueryingAA, F);
2138 if (!AARetVal)
2139 return false;
2140
2141 auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
2142 if (!LivenessAA)
2143 return AARetVal->checkForAllReturnedValuesAndReturnInsts(Pred);
2144
2145 auto LivenessFilter = [&](Value &RV,
2146 const SmallPtrSetImpl<ReturnInst *> &ReturnInsts) {
2147 SmallPtrSet<ReturnInst *, 4> FilteredReturnInsts;
2148 for (ReturnInst *RI : ReturnInsts)
2149 if (!LivenessAA->isAssumedDead(RI))
2150 FilteredReturnInsts.insert(RI);
2151 if (!FilteredReturnInsts.empty())
2152 return Pred(RV, FilteredReturnInsts);
2153 return true;
2154 };
2155
2156 return AARetVal->checkForAllReturnedValuesAndReturnInsts(LivenessFilter);
2157}
2158
2159bool Attributor::checkForAllReturnedValues(
2160 const Function &F, const function_ref<bool(Value &)> &Pred,
2161 const AbstractAttribute &QueryingAA) {
2162
2163 auto *AARetVal = getAAFor<AAReturnedValues>(QueryingAA, F);
2164 if (!AARetVal)
2165 return false;
2166
2167 auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
2168 if (!LivenessAA)
2169 return AARetVal->checkForAllReturnedValuesAndReturnInsts(
2170 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &) {
2171 return Pred(RV);
2172 });
2173
2174 auto LivenessFilter = [&](Value &RV,
2175 const SmallPtrSetImpl<ReturnInst *> &ReturnInsts) {
2176 if (LivenessAA->isLiveInstSet(ReturnInsts.begin(), ReturnInsts.end()))
2177 return Pred(RV);
2178 return true;
2179 };
2180
2181 return AARetVal->checkForAllReturnedValuesAndReturnInsts(LivenessFilter);
2182}
2183
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002184bool Attributor::checkForAllInstructions(
2185 const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002186 const AbstractAttribute &QueryingAA, InformationCache &InfoCache,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002187 const ArrayRef<unsigned> &Opcodes) {
2188
2189 auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
2190
2191 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
2192 for (unsigned Opcode : Opcodes) {
2193 for (Instruction *I : OpcodeInstMap[Opcode]) {
2194 // Skip dead instructions.
2195 if (LivenessAA && LivenessAA->isAssumedDead(I))
2196 continue;
2197
2198 if (!Pred(*I))
2199 return false;
2200 }
2201 }
2202
2203 return true;
2204}
2205
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002206bool Attributor::checkForAllReadWriteInstructions(
2207 const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
2208 AbstractAttribute &QueryingAA, InformationCache &InfoCache) {
2209
2210 auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
2211
2212 for (Instruction *I : InfoCache.getReadOrWriteInstsForFunction(F)) {
2213 // Skip dead instructions.
2214 if (LivenessAA && LivenessAA->isAssumedDead(I))
2215 continue;
2216
2217 if (!Pred(*I))
2218 return false;
2219 }
2220
2221 return true;
2222}
2223
Johannes Doerfert007153e2019-08-05 23:26:06 +00002224ChangeStatus Attributor::run(InformationCache &InfoCache) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002225 // Initialize all abstract attributes.
2226 for (AbstractAttribute *AA : AllAbstractAttributes)
Johannes Doerfert007153e2019-08-05 23:26:06 +00002227 AA->initialize(*this, InfoCache);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002228
2229 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
2230 << AllAbstractAttributes.size()
2231 << " abstract attributes.\n");
2232
Stefan Stipanovic53605892019-06-27 11:27:54 +00002233 // Now that all abstract attributes are collected and initialized we start
2234 // the abstract analysis.
Johannes Doerfertaade7822019-06-05 03:02:24 +00002235
2236 unsigned IterationCounter = 1;
2237
2238 SmallVector<AbstractAttribute *, 64> ChangedAAs;
2239 SetVector<AbstractAttribute *> Worklist;
2240 Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
2241
2242 do {
2243 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
2244 << ", Worklist size: " << Worklist.size() << "\n");
2245
2246 // Add all abstract attributes that are potentially dependent on one that
2247 // changed to the work list.
2248 for (AbstractAttribute *ChangedAA : ChangedAAs) {
2249 auto &QuerriedAAs = QueryMap[ChangedAA];
2250 Worklist.insert(QuerriedAAs.begin(), QuerriedAAs.end());
2251 }
2252
2253 // Reset the changed set.
2254 ChangedAAs.clear();
2255
2256 // Update all abstract attribute in the work list and record the ones that
2257 // changed.
2258 for (AbstractAttribute *AA : Worklist)
Johannes Doerfert007153e2019-08-05 23:26:06 +00002259 if (AA->update(*this, InfoCache) == ChangeStatus::CHANGED)
Johannes Doerfertaade7822019-06-05 03:02:24 +00002260 ChangedAAs.push_back(AA);
2261
2262 // Reset the work list and repopulate with the changed abstract attributes.
2263 // Note that dependent ones are added above.
2264 Worklist.clear();
2265 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2266
2267 } while (!Worklist.empty() && ++IterationCounter < MaxFixpointIterations);
2268
2269 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
2270 << IterationCounter << "/" << MaxFixpointIterations
2271 << " iterations\n");
2272
2273 bool FinishedAtFixpoint = Worklist.empty();
2274
2275 // Reset abstract arguments not settled in a sound fixpoint by now. This
2276 // happens when we stopped the fixpoint iteration early. Note that only the
2277 // ones marked as "changed" *and* the ones transitively depending on them
2278 // need to be reverted to a pessimistic state. Others might not be in a
2279 // fixpoint state but we can use the optimistic results for them anyway.
2280 SmallPtrSet<AbstractAttribute *, 32> Visited;
2281 for (unsigned u = 0; u < ChangedAAs.size(); u++) {
2282 AbstractAttribute *ChangedAA = ChangedAAs[u];
2283 if (!Visited.insert(ChangedAA).second)
2284 continue;
2285
2286 AbstractState &State = ChangedAA->getState();
2287 if (!State.isAtFixpoint()) {
2288 State.indicatePessimisticFixpoint();
2289
2290 NumAttributesTimedOut++;
2291 }
2292
2293 auto &QuerriedAAs = QueryMap[ChangedAA];
2294 ChangedAAs.append(QuerriedAAs.begin(), QuerriedAAs.end());
2295 }
2296
2297 LLVM_DEBUG({
2298 if (!Visited.empty())
2299 dbgs() << "\n[Attributor] Finalized " << Visited.size()
2300 << " abstract attributes.\n";
2301 });
2302
2303 unsigned NumManifested = 0;
2304 unsigned NumAtFixpoint = 0;
2305 ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
2306 for (AbstractAttribute *AA : AllAbstractAttributes) {
2307 AbstractState &State = AA->getState();
2308
2309 // If there is not already a fixpoint reached, we can now take the
2310 // optimistic state. This is correct because we enforced a pessimistic one
2311 // on abstract attributes that were transitively dependent on a changed one
2312 // already above.
2313 if (!State.isAtFixpoint())
2314 State.indicateOptimisticFixpoint();
2315
2316 // If the state is invalid, we do not try to manifest it.
2317 if (!State.isValidState())
2318 continue;
2319
2320 // Manifest the state and record if we changed the IR.
2321 ChangeStatus LocalChange = AA->manifest(*this);
2322 ManifestChange = ManifestChange | LocalChange;
2323
2324 NumAtFixpoint++;
2325 NumManifested += (LocalChange == ChangeStatus::CHANGED);
2326 }
2327
2328 (void)NumManifested;
2329 (void)NumAtFixpoint;
2330 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
2331 << " arguments while " << NumAtFixpoint
2332 << " were in a valid fixpoint state\n");
2333
2334 // If verification is requested, we finished this run at a fixpoint, and the
2335 // IR was changed, we re-run the whole fixpoint analysis, starting at
2336 // re-initialization of the arguments. This re-run should not result in an IR
2337 // change. Though, the (virtual) state of attributes at the end of the re-run
2338 // might be more optimistic than the known state or the IR state if the better
2339 // state cannot be manifested.
2340 if (VerifyAttributor && FinishedAtFixpoint &&
2341 ManifestChange == ChangeStatus::CHANGED) {
2342 VerifyAttributor = false;
Johannes Doerfert007153e2019-08-05 23:26:06 +00002343 ChangeStatus VerifyStatus = run(InfoCache);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002344 if (VerifyStatus != ChangeStatus::UNCHANGED)
2345 llvm_unreachable(
2346 "Attributor verification failed, re-run did result in an IR change "
2347 "even after a fixpoint was reached in the original run. (False "
2348 "positives possible!)");
2349 VerifyAttributor = true;
2350 }
2351
2352 NumAttributesManifested += NumManifested;
2353 NumAttributesValidFixpoint += NumAtFixpoint;
2354
2355 return ManifestChange;
2356}
2357
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002358/// Helper function that checks if an abstract attribute of type \p AAType
2359/// should be created for \p V (with argument number \p ArgNo) and if so creates
2360/// and registers it with the Attributor \p A.
2361///
2362/// This method will look at the provided whitelist. If one is given and the
2363/// kind \p AAType::ID is not contained, no abstract attribute is created.
2364///
2365/// \returns The created abstract argument, or nullptr if none was created.
2366template <typename AAType, typename ValueType, typename... ArgsTy>
2367static AAType *checkAndRegisterAA(const Function &F, Attributor &A,
2368 DenseSet<const char *> *Whitelist,
2369 ValueType &V, int ArgNo, ArgsTy... Args) {
2370 if (Whitelist && !Whitelist->count(&AAType::ID))
2371 return nullptr;
2372
2373 return &A.registerAA<AAType>(*new AAType(V, Args...), ArgNo);
2374}
2375
Johannes Doerfertaade7822019-06-05 03:02:24 +00002376void Attributor::identifyDefaultAbstractAttributes(
2377 Function &F, InformationCache &InfoCache,
Johannes Doerfert24020622019-08-05 23:30:01 +00002378 DenseSet<const char *> *Whitelist) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002379
Johannes Doerfert305b9612019-08-04 18:40:01 +00002380 // Check for dead BasicBlocks in every function.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002381 // We need dead instruction detection because we do not want to deal with
2382 // broken IR in which SSA rules do not apply.
2383 checkAndRegisterAA<AAIsDeadFunction>(F, *this, /* Whitelist */ nullptr, F,
2384 -1);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002385
2386 // Every function might be "will-return".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002387 checkAndRegisterAA<AAWillReturnFunction>(F, *this, Whitelist, F, -1);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002388
Stefan Stipanovic53605892019-06-27 11:27:54 +00002389 // Every function can be nounwind.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002390 checkAndRegisterAA<AANoUnwindFunction>(F, *this, Whitelist, F, -1);
Stefan Stipanovic53605892019-06-27 11:27:54 +00002391
Stefan Stipanovic06263672019-07-11 21:37:40 +00002392 // Every function might be marked "nosync"
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002393 checkAndRegisterAA<AANoSyncFunction>(F, *this, Whitelist, F, -1);
Stefan Stipanovic06263672019-07-11 21:37:40 +00002394
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002395 // Every function might be "no-free".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002396 checkAndRegisterAA<AANoFreeFunction>(F, *this, Whitelist, F, -1);
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002397
Johannes Doerferte83f3032019-08-05 23:22:05 +00002398 // Every function might be "no-return".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002399 checkAndRegisterAA<AANoReturnFunction>(F, *this, Whitelist, F, -1);
Johannes Doerferte83f3032019-08-05 23:22:05 +00002400
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002401 // Return attributes are only appropriate if the return type is non void.
2402 Type *ReturnType = F.getReturnType();
2403 if (!ReturnType->isVoidTy()) {
2404 // Argument attribute "returned" --- Create only one per function even
2405 // though it is an argument attribute.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002406 checkAndRegisterAA<AAReturnedValuesFunction>(F, *this, Whitelist, F, -1);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002407
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002408 if (ReturnType->isPointerTy()) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002409 // Every function with pointer return type might be marked align.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002410 checkAndRegisterAA<AAAlignReturned>(F, *this, Whitelist, F, -1);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002411
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002412 // Every function with pointer return type might be marked nonnull.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002413 checkAndRegisterAA<AANonNullReturned>(F, *this, Whitelist, F, -1);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002414
2415 // Every function with pointer return type might be marked noalias.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002416 checkAndRegisterAA<AANoAliasReturned>(F, *this, Whitelist, F, -1);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002417
2418 // Every function with pointer return type might be marked
2419 // dereferenceable.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002420 checkAndRegisterAA<AADereferenceableReturned>(F, *this, Whitelist, F, -1);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002421 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00002422 }
2423
Hideto Ueno54869ec2019-07-15 06:49:04 +00002424 for (Argument &Arg : F.args()) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002425 if (Arg.getType()->isPointerTy()) {
2426 // Every argument with pointer type might be marked nonnull.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002427 checkAndRegisterAA<AANonNullArgument>(F, *this, Whitelist, Arg,
2428 Arg.getArgNo());
Hideto Ueno19c07af2019-07-23 08:16:17 +00002429
2430 // Every argument with pointer type might be marked dereferenceable.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002431 checkAndRegisterAA<AADereferenceableArgument>(F, *this, Whitelist, Arg,
2432 Arg.getArgNo());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002433
2434 // Every argument with pointer type might be marked align.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002435 checkAndRegisterAA<AAAlignArgument>(F, *this, Whitelist, Arg,
2436 Arg.getArgNo());
Hideto Ueno19c07af2019-07-23 08:16:17 +00002437 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002438 }
2439
Johannes Doerfertaade7822019-06-05 03:02:24 +00002440 // Walk all instructions to find more attribute opportunities and also
2441 // interesting instructions that might be queried by abstract attributes
2442 // during their initialization or update.
2443 auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
2444 auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
2445
2446 for (Instruction &I : instructions(&F)) {
2447 bool IsInterestingOpcode = false;
2448
2449 // To allow easy access to all instructions in a function with a given
2450 // opcode we store them in the InfoCache. As not all opcodes are interesting
2451 // to concrete attributes we only cache the ones that are as identified in
2452 // the following switch.
2453 // Note: There are no concrete attributes now so this is initially empty.
Stefan Stipanovic53605892019-06-27 11:27:54 +00002454 switch (I.getOpcode()) {
2455 default:
2456 assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) &&
2457 "New call site/base instruction type needs to be known int the "
2458 "attributor.");
2459 break;
2460 case Instruction::Call:
2461 case Instruction::CallBr:
2462 case Instruction::Invoke:
2463 case Instruction::CleanupRet:
2464 case Instruction::CatchSwitch:
2465 case Instruction::Resume:
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002466 case Instruction::Ret:
Stefan Stipanovic53605892019-06-27 11:27:54 +00002467 IsInterestingOpcode = true;
2468 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002469 if (IsInterestingOpcode)
2470 InstOpcodeMap[I.getOpcode()].push_back(&I);
2471 if (I.mayReadOrWriteMemory())
2472 ReadOrWriteInsts.push_back(&I);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002473
2474 CallSite CS(&I);
2475 if (CS && CS.getCalledFunction()) {
2476 for (int i = 0, e = CS.getCalledFunction()->arg_size(); i < e; i++) {
2477 if (!CS.getArgument(i)->getType()->isPointerTy())
2478 continue;
2479
2480 // Call site argument attribute "non-null".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002481 checkAndRegisterAA<AANonNullCallSiteArgument>(F, *this, Whitelist, I, i,
2482 i);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002483
2484 // Call site argument attribute "dereferenceable".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002485 checkAndRegisterAA<AADereferenceableCallSiteArgument>(
2486 F, *this, Whitelist, I, i, i);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002487
2488 // Call site argument attribute "align".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002489 checkAndRegisterAA<AAAlignCallSiteArgument>(F, *this, Whitelist, I, i,
2490 i);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002491 }
2492 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002493 }
2494}
2495
2496/// Helpers to ease debugging through output streams and print calls.
2497///
2498///{
2499raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
2500 return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
2501}
2502
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002503raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002504 switch (AP) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002505 case IRPosition::IRP_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002506 return OS << "arg";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002507 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002508 return OS << "cs_arg";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002509 case IRPosition::IRP_FUNCTION:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002510 return OS << "fn";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002511 case IRPosition::IRP_RETURNED:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002512 return OS << "fn_ret";
2513 }
2514 llvm_unreachable("Unknown attribute position!");
2515}
2516
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002517raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) {
2518 const Value *AV = Pos.getAssociatedValue();
2519 return OS << "{" << Pos.getPositionKind() << ":"
2520 << (AV ? AV->getName() : "n/a") << " ["
2521 << Pos.getAnchorValue().getName() << "@" << Pos.getArgNo() << "]}";
2522}
2523
Johannes Doerfertaade7822019-06-05 03:02:24 +00002524raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
2525 return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
2526}
2527
2528raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
2529 AA.print(OS);
2530 return OS;
2531}
2532
2533void AbstractAttribute::print(raw_ostream &OS) const {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002534 OS << "[P: " << getIRPosition() << "][" << getAsStr() << "][S: " << getState()
2535 << "]";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002536}
2537///}
2538
2539/// ----------------------------------------------------------------------------
2540/// Pass (Manager) Boilerplate
2541/// ----------------------------------------------------------------------------
2542
2543static bool runAttributorOnModule(Module &M) {
2544 if (DisableAttributor)
2545 return false;
2546
2547 LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << M.size()
2548 << " functions.\n");
2549
2550 // Create an Attributor and initially empty information cache that is filled
2551 // while we identify default attribute opportunities.
2552 Attributor A;
2553 InformationCache InfoCache;
2554
2555 for (Function &F : M) {
2556 // TODO: Not all attributes require an exact definition. Find a way to
2557 // enable deduction for some but not all attributes in case the
2558 // definition might be changed at runtime, see also
2559 // http://lists.llvm.org/pipermail/llvm-dev/2018-February/121275.html.
2560 // TODO: We could always determine abstract attributes and if sufficient
2561 // information was found we could duplicate the functions that do not
2562 // have an exact definition.
2563 if (!F.hasExactDefinition()) {
2564 NumFnWithoutExactDefinition++;
2565 continue;
2566 }
2567
2568 // For now we ignore naked and optnone functions.
2569 if (F.hasFnAttribute(Attribute::Naked) ||
2570 F.hasFnAttribute(Attribute::OptimizeNone))
2571 continue;
2572
2573 NumFnWithExactDefinition++;
2574
2575 // Populate the Attributor with abstract attribute opportunities in the
2576 // function and the information cache with IR information.
2577 A.identifyDefaultAbstractAttributes(F, InfoCache);
2578 }
2579
Johannes Doerfert007153e2019-08-05 23:26:06 +00002580 return A.run(InfoCache) == ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002581}
2582
2583PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
2584 if (runAttributorOnModule(M)) {
2585 // FIXME: Think about passes we will preserve and add them here.
2586 return PreservedAnalyses::none();
2587 }
2588 return PreservedAnalyses::all();
2589}
2590
2591namespace {
2592
2593struct AttributorLegacyPass : public ModulePass {
2594 static char ID;
2595
2596 AttributorLegacyPass() : ModulePass(ID) {
2597 initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry());
2598 }
2599
2600 bool runOnModule(Module &M) override {
2601 if (skipModule(M))
2602 return false;
2603 return runAttributorOnModule(M);
2604 }
2605
2606 void getAnalysisUsage(AnalysisUsage &AU) const override {
2607 // FIXME: Think about passes we will preserve and add them here.
2608 AU.setPreservesCFG();
2609 }
2610};
2611
2612} // end anonymous namespace
2613
2614Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); }
2615
2616char AttributorLegacyPass::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002617
2618const char AAReturnedValues::ID = 0;
2619const char AANoUnwind::ID = 0;
2620const char AANoSync::ID = 0;
Johannes Doerferteccdf082019-08-05 23:35:12 +00002621const char AANoFree::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002622const char AANonNull::ID = 0;
2623const char AANoRecurse::ID = 0;
2624const char AAWillReturn::ID = 0;
2625const char AANoAlias::ID = 0;
2626const char AANoReturn::ID = 0;
2627const char AAIsDead::ID = 0;
2628const char AADereferenceable::ID = 0;
2629const char AAAlign::ID = 0;
2630
Johannes Doerfertaade7822019-06-05 03:02:24 +00002631INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor",
2632 "Deduce and propagate attributes", false, false)
2633INITIALIZE_PASS_END(AttributorLegacyPass, "attributor",
2634 "Deduce and propagate attributes", false, false)