blob: d5b158bf8850b88442f3917f9c8f4d0913e0c4e5 [file] [log] [blame]
Johannes Doerfertaade7822019-06-05 03:02:24 +00001//===- Attributor.cpp - Module-wide attribute deduction -------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements an inter procedural pass that deduces and/or propagating
10// attributes. This is done in an abstract interpretation style fixpoint
11// iteration. See the Attributor.h file comment and the class descriptions in
12// that file for more information.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/Transforms/IPO/Attributor.h"
17
Hideto Ueno11d37102019-07-17 15:15:43 +000018#include "llvm/ADT/DepthFirstIterator.h"
Stefan Stipanovic6058b862019-07-22 23:58:23 +000019#include "llvm/ADT/STLExtras.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000020#include "llvm/ADT/SetVector.h"
21#include "llvm/ADT/SmallPtrSet.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/Statistic.h"
Stefan Stipanovic69ebb022019-07-22 19:36:27 +000024#include "llvm/Analysis/CaptureTracking.h"
Johannes Doerfert924d2132019-08-05 21:34:45 +000025#include "llvm/Analysis/EHPersonalities.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000026#include "llvm/Analysis/GlobalsModRef.h"
Hideto Ueno19c07af2019-07-23 08:16:17 +000027#include "llvm/Analysis/Loads.h"
Hideto Ueno54869ec2019-07-15 06:49:04 +000028#include "llvm/Analysis/ValueTracking.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000029#include "llvm/IR/Argument.h"
30#include "llvm/IR/Attributes.h"
Hideto Ueno11d37102019-07-17 15:15:43 +000031#include "llvm/IR/CFG.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000032#include "llvm/IR/InstIterator.h"
Stefan Stipanovic06263672019-07-11 21:37:40 +000033#include "llvm/IR/IntrinsicInst.h"
Johannes Doerfertaade7822019-06-05 03:02:24 +000034#include "llvm/Support/CommandLine.h"
35#include "llvm/Support/Debug.h"
36#include "llvm/Support/raw_ostream.h"
Stefan Stipanovic6058b862019-07-22 23:58:23 +000037#include "llvm/Transforms/Utils/BasicBlockUtils.h"
38#include "llvm/Transforms/Utils/Local.h"
39
Johannes Doerfertaade7822019-06-05 03:02:24 +000040#include <cassert>
41
42using namespace llvm;
43
44#define DEBUG_TYPE "attributor"
45
46STATISTIC(NumFnWithExactDefinition,
47 "Number of function with exact definitions");
48STATISTIC(NumFnWithoutExactDefinition,
49 "Number of function without exact definitions");
50STATISTIC(NumAttributesTimedOut,
51 "Number of abstract attributes timed out before fixpoint");
52STATISTIC(NumAttributesValidFixpoint,
53 "Number of abstract attributes in a valid fixpoint state");
54STATISTIC(NumAttributesManifested,
55 "Number of abstract attributes manifested in IR");
56
Johannes Doerfertd1b79e02019-08-07 22:46:11 +000057// Some helper macros to deal with statistics tracking.
58//
59// Usage:
60// For simple IR attribute tracking overload trackStatistics in the abstract
61// attribute and choose the right STATS_DECL_AND_TRACK_********* macro,
62// e.g.,:
63// void trackStatistics() const override {
64// STATS_DECL_AND_TRACK_ARG_ATTR(returned)
65// }
66// If there is a single "increment" side one can use the macro
67// STATS_DECL_AND_TRACK with a custom message. If there are multiple increment
68// sides, STATS_DECL and STATS_TRACK can also be used separatly.
69//
70#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
71 ("Number of " #TYPE " marked '" #NAME "'")
72#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
73#define STATS_DECL(NAME, TYPE, MSG) STATISTIC(BUILD_STAT_NAME(NAME, TYPE), MSG);
74#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
75#define STATS_DECL_AND_TRACK(NAME, TYPE, MSG) \
76 STATS_DECL(NAME, TYPE, MSG) \
77 STATS_TRACK(NAME, TYPE)
78#define STATS_DECL_AND_TRACK_ARG_ATTR(NAME) \
79 STATS_DECL_AND_TRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
80#define STATS_DECL_AND_TRACK_CSARG_ATTR(NAME) \
81 STATS_DECL_AND_TRACK(NAME, CSArguments, \
82 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
83#define STATS_DECL_AND_TRACK_FN_ATTR(NAME) \
84 STATS_DECL_AND_TRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
85#define STATS_DECL_AND_TRACK_FNRET_ATTR(NAME) \
86 STATS_DECL_AND_TRACK(NAME, FunctionReturn, \
87 BUILD_STAT_MSG_IR_ATTR(function returns, NAME));
Johannes Doerfertaccd3e82019-07-08 23:27:20 +000088
Johannes Doerfertaade7822019-06-05 03:02:24 +000089// TODO: Determine a good default value.
90//
91// In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads
92// (when run with the first 5 abstract attributes). The results also indicate
93// that we never reach 32 iterations but always find a fixpoint sooner.
94//
95// This will become more evolved once we perform two interleaved fixpoint
96// iterations: bottom-up and top-down.
97static cl::opt<unsigned>
98 MaxFixpointIterations("attributor-max-iterations", cl::Hidden,
99 cl::desc("Maximal number of fixpoint iterations."),
100 cl::init(32));
101
102static cl::opt<bool> DisableAttributor(
103 "attributor-disable", cl::Hidden,
104 cl::desc("Disable the attributor inter-procedural deduction pass."),
Johannes Doerfert282d34e2019-06-14 14:53:41 +0000105 cl::init(true));
Johannes Doerfertaade7822019-06-05 03:02:24 +0000106
107static cl::opt<bool> VerifyAttributor(
108 "attributor-verify", cl::Hidden,
109 cl::desc("Verify the Attributor deduction and "
110 "manifestation of attributes -- may issue false-positive errors"),
111 cl::init(false));
112
113/// Logic operators for the change status enum class.
114///
115///{
116ChangeStatus llvm::operator|(ChangeStatus l, ChangeStatus r) {
117 return l == ChangeStatus::CHANGED ? l : r;
118}
119ChangeStatus llvm::operator&(ChangeStatus l, ChangeStatus r) {
120 return l == ChangeStatus::UNCHANGED ? l : r;
121}
122///}
123
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000124template <typename StateTy>
125using followValueCB_t = std::function<bool(Value *, StateTy &State)>;
126template <typename StateTy>
127using visitValueCB_t = std::function<void(Value *, StateTy &State)>;
128
129/// Recursively visit all values that might become \p InitV at some point. This
130/// will be done by looking through cast instructions, selects, phis, and calls
131/// with the "returned" attribute. The callback \p FollowValueCB is asked before
132/// a potential origin value is looked at. If no \p FollowValueCB is passed, a
133/// default one is used that will make sure we visit every value only once. Once
134/// we cannot look through the value any further, the callback \p VisitValueCB
135/// is invoked and passed the current value and the \p State. To limit how much
136/// effort is invested, we will never visit more than \p MaxValues values.
137template <typename StateTy>
138static bool genericValueTraversal(
139 Value *InitV, StateTy &State, visitValueCB_t<StateTy> &VisitValueCB,
140 followValueCB_t<StateTy> *FollowValueCB = nullptr, int MaxValues = 8) {
141
142 SmallPtrSet<Value *, 16> Visited;
143 followValueCB_t<bool> DefaultFollowValueCB = [&](Value *Val, bool &) {
144 return Visited.insert(Val).second;
145 };
146
147 if (!FollowValueCB)
148 FollowValueCB = &DefaultFollowValueCB;
149
150 SmallVector<Value *, 16> Worklist;
151 Worklist.push_back(InitV);
152
153 int Iteration = 0;
154 do {
155 Value *V = Worklist.pop_back_val();
156
157 // Check if we should process the current value. To prevent endless
158 // recursion keep a record of the values we followed!
159 if (!(*FollowValueCB)(V, State))
160 continue;
161
162 // Make sure we limit the compile time for complex expressions.
163 if (Iteration++ >= MaxValues)
164 return false;
165
166 // Explicitly look through calls with a "returned" attribute if we do
167 // not have a pointer as stripPointerCasts only works on them.
168 if (V->getType()->isPointerTy()) {
169 V = V->stripPointerCasts();
170 } else {
171 CallSite CS(V);
172 if (CS && CS.getCalledFunction()) {
173 Value *NewV = nullptr;
174 for (Argument &Arg : CS.getCalledFunction()->args())
175 if (Arg.hasReturnedAttr()) {
176 NewV = CS.getArgOperand(Arg.getArgNo());
177 break;
178 }
179 if (NewV) {
180 Worklist.push_back(NewV);
181 continue;
182 }
183 }
184 }
185
186 // Look through select instructions, visit both potential values.
187 if (auto *SI = dyn_cast<SelectInst>(V)) {
188 Worklist.push_back(SI->getTrueValue());
189 Worklist.push_back(SI->getFalseValue());
190 continue;
191 }
192
193 // Look through phi nodes, visit all operands.
194 if (auto *PHI = dyn_cast<PHINode>(V)) {
195 Worklist.append(PHI->op_begin(), PHI->op_end());
196 continue;
197 }
198
199 // Once a leaf is reached we inform the user through the callback.
200 VisitValueCB(V, State);
201 } while (!Worklist.empty());
202
203 // All values have been visited.
204 return true;
205}
206
Johannes Doerfertaade7822019-06-05 03:02:24 +0000207/// Return true if \p New is equal or worse than \p Old.
208static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) {
209 if (!Old.isIntAttribute())
210 return true;
211
212 return Old.getValueAsInt() >= New.getValueAsInt();
213}
214
215/// Return true if the information provided by \p Attr was added to the
216/// attribute list \p Attrs. This is only the case if it was not already present
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000217/// in \p Attrs at the position describe by \p PK and \p AttrIdx.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000218static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000219 AttributeList &Attrs, int AttrIdx) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000220
221 if (Attr.isEnumAttribute()) {
222 Attribute::AttrKind Kind = Attr.getKindAsEnum();
223 if (Attrs.hasAttribute(AttrIdx, Kind))
224 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
225 return false;
226 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
227 return true;
228 }
229 if (Attr.isStringAttribute()) {
230 StringRef Kind = Attr.getKindAsString();
231 if (Attrs.hasAttribute(AttrIdx, Kind))
232 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
233 return false;
234 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
235 return true;
236 }
Hideto Ueno19c07af2019-07-23 08:16:17 +0000237 if (Attr.isIntAttribute()) {
238 Attribute::AttrKind Kind = Attr.getKindAsEnum();
239 if (Attrs.hasAttribute(AttrIdx, Kind))
240 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind)))
241 return false;
242 Attrs = Attrs.removeAttribute(Ctx, AttrIdx, Kind);
243 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr);
244 return true;
245 }
Johannes Doerfertaade7822019-06-05 03:02:24 +0000246
247 llvm_unreachable("Expected enum or string attribute!");
248}
249
Johannes Doerfert007153e2019-08-05 23:26:06 +0000250ChangeStatus AbstractAttribute::update(Attributor &A,
251 InformationCache &InfoCache) {
Johannes Doerfertaade7822019-06-05 03:02:24 +0000252 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
253 if (getState().isAtFixpoint())
254 return HasChanged;
255
256 LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");
257
Johannes Doerfert007153e2019-08-05 23:26:06 +0000258 HasChanged = updateImpl(A, InfoCache);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000259
260 LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
261 << "\n");
262
263 return HasChanged;
264}
265
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000266ChangeStatus
267IRAttributeManifest::manifestAttrs(Attributor &A, IRPosition &IRP,
268 const ArrayRef<Attribute> &DeducedAttrs) {
Kristina Brooks26e60f02019-08-06 19:53:19 +0000269 assert(IRP.getAssociatedValue() &&
Johannes Doerfertaade7822019-06-05 03:02:24 +0000270 "Attempted to manifest an attribute without associated value!");
271
272 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000273
Kristina Brooks26e60f02019-08-06 19:53:19 +0000274 Function &ScopeFn = IRP.getAnchorScope();
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000275 LLVMContext &Ctx = ScopeFn.getContext();
Kristina Brooks26e60f02019-08-06 19:53:19 +0000276 IRPosition::Kind PK = IRP.getPositionKind();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000277
Johannes Doerfertaade7822019-06-05 03:02:24 +0000278 // In the following some generic code that will manifest attributes in
279 // DeducedAttrs if they improve the current IR. Due to the different
280 // annotation positions we use the underlying AttributeList interface.
Johannes Doerfertaade7822019-06-05 03:02:24 +0000281
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000282 AttributeList Attrs;
283 switch (PK) {
284 case IRPosition::IRP_ARGUMENT:
285 case IRPosition::IRP_FUNCTION:
286 case IRPosition::IRP_RETURNED:
Johannes Doerfertaade7822019-06-05 03:02:24 +0000287 Attrs = ScopeFn.getAttributes();
288 break;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000289 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000290 Attrs = ImmutableCallSite(&IRP.getAnchorValue()).getAttributes();
Johannes Doerfertaade7822019-06-05 03:02:24 +0000291 break;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000292 }
293
294 for (const Attribute &Attr : DeducedAttrs) {
Kristina Brooks26e60f02019-08-06 19:53:19 +0000295 if (!addIfNotExistent(Ctx, Attr, Attrs, IRP.getAttrIdx()))
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000296 continue;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000297
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000298 HasChanged = ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +0000299 }
300
301 if (HasChanged == ChangeStatus::UNCHANGED)
302 return HasChanged;
303
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000304 switch (PK) {
305 case IRPosition::IRP_ARGUMENT:
306 case IRPosition::IRP_FUNCTION:
307 case IRPosition::IRP_RETURNED:
Johannes Doerfertaade7822019-06-05 03:02:24 +0000308 ScopeFn.setAttributes(Attrs);
309 break;
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000310 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Kristina Brooks26e60f02019-08-06 19:53:19 +0000311 CallSite(&IRP.getAnchorValue()).setAttributes(Attrs);
Johannes Doerfertaade7822019-06-05 03:02:24 +0000312 }
313
314 return HasChanged;
315}
316
Stefan Stipanovic53605892019-06-27 11:27:54 +0000317/// -----------------------NoUnwind Function Attribute--------------------------
318
Johannes Doerfert344d0382019-08-07 22:34:26 +0000319struct AANoUnwindImpl : AANoUnwind {
Johannes Doerferteccdf082019-08-05 23:35:12 +0000320 IRPositionConstructorForward(AANoUnwindImpl, AANoUnwind);
Stefan Stipanovic53605892019-06-27 11:27:54 +0000321
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000322 const std::string getAsStr() const override {
Stefan Stipanovic53605892019-06-27 11:27:54 +0000323 return getAssumed() ? "nounwind" : "may-unwind";
324 }
325
326 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000327 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Stefan Stipanovic53605892019-06-27 11:27:54 +0000328};
329
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000330struct AANoUnwindFunction final : public AANoUnwindImpl {
331 AANoUnwindFunction(Function &F) : AANoUnwindImpl(F, IRP_FUNCTION) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000332
333 /// See AbstractAttribute::trackStatistics()
334 void trackStatistics() const override {
335 STATS_DECL_AND_TRACK_FN_ATTR(nounwind)
336 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000337};
338
339ChangeStatus AANoUnwindImpl::updateImpl(Attributor &A,
340 InformationCache &InfoCache) {
Stefan Stipanovic53605892019-06-27 11:27:54 +0000341 Function &F = getAnchorScope();
342
343 // The map from instruction opcodes to those instructions in the function.
Stefan Stipanovic53605892019-06-27 11:27:54 +0000344 auto Opcodes = {
345 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
346 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
347 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
348
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000349 auto CheckForNoUnwind = [&](Instruction &I) {
350 if (!I.mayThrow())
351 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000352
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000353 auto *NoUnwindAA = A.getAAFor<AANoUnwind>(*this, I);
354 return NoUnwindAA && NoUnwindAA->isAssumedNoUnwind();
355 };
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000356
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000357 if (!A.checkForAllInstructions(F, CheckForNoUnwind, *this, InfoCache,
358 Opcodes))
359 return indicatePessimisticFixpoint();
Stefan Stipanovic53605892019-06-27 11:27:54 +0000360
Stefan Stipanovic53605892019-06-27 11:27:54 +0000361 return ChangeStatus::UNCHANGED;
362}
363
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000364/// --------------------- Function Return Values -------------------------------
365
366/// "Attribute" that collects all potential returned values and the return
367/// instructions that they arise from.
368///
369/// If there is a unique returned value R, the manifest method will:
370/// - mark R with the "returned" attribute, if R is an argument.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000371///
372/// TODO: We should use liveness during construction of the returned values map
373/// and before we set HasOverdefinedReturnedCalls.
Johannes Doerferteccdf082019-08-05 23:35:12 +0000374class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000375
376 /// Mapping of values potentially returned by the associated function to the
377 /// return instructions that might return them.
378 DenseMap<Value *, SmallPtrSet<ReturnInst *, 2>> ReturnedValues;
379
380 /// State flags
381 ///
382 ///{
383 bool IsFixed;
384 bool IsValidState;
385 bool HasOverdefinedReturnedCalls;
386 ///}
387
388 /// Collect values that could become \p V in the set \p Values, each mapped to
389 /// \p ReturnInsts.
390 void collectValuesRecursively(
391 Attributor &A, Value *V, SmallPtrSetImpl<ReturnInst *> &ReturnInsts,
392 DenseMap<Value *, SmallPtrSet<ReturnInst *, 2>> &Values) {
393
394 visitValueCB_t<bool> VisitValueCB = [&](Value *Val, bool &) {
395 assert(!isa<Instruction>(Val) ||
396 &getAnchorScope() == cast<Instruction>(Val)->getFunction());
397 Values[Val].insert(ReturnInsts.begin(), ReturnInsts.end());
398 };
399
400 bool UnusedBool;
401 bool Success = genericValueTraversal(V, UnusedBool, VisitValueCB);
402
403 // If we did abort the above traversal we haven't see all the values.
404 // Consequently, we cannot know if the information we would derive is
405 // accurate so we give up early.
406 if (!Success)
407 indicatePessimisticFixpoint();
408 }
409
410public:
Johannes Doerferteccdf082019-08-05 23:35:12 +0000411 IRPositionConstructorForward(AAReturnedValuesImpl, AAReturnedValues);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000412
413 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000414 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000415 // Reset the state.
Johannes Doerfertbeb51502019-08-07 22:36:15 +0000416 setAssociatedValue(nullptr);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000417 IsFixed = false;
418 IsValidState = true;
419 HasOverdefinedReturnedCalls = false;
420 ReturnedValues.clear();
421
Johannes Doerfertbeb51502019-08-07 22:36:15 +0000422 Function &F = getAnchorScope();
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000423
424 // The map from instruction opcodes to those instructions in the function.
425 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
426
427 // Look through all arguments, if one is marked as returned we are done.
428 for (Argument &Arg : F.args()) {
429 if (Arg.hasReturnedAttr()) {
430
431 auto &ReturnInstSet = ReturnedValues[&Arg];
432 for (Instruction *RI : OpcodeInstMap[Instruction::Ret])
433 ReturnInstSet.insert(cast<ReturnInst>(RI));
434
435 indicateOptimisticFixpoint();
436 return;
437 }
438 }
439
440 // If no argument was marked as returned we look at all return instructions
441 // and collect potentially returned values.
442 for (Instruction *RI : OpcodeInstMap[Instruction::Ret]) {
443 SmallPtrSet<ReturnInst *, 1> RISet({cast<ReturnInst>(RI)});
444 collectValuesRecursively(A, cast<ReturnInst>(RI)->getReturnValue(), RISet,
445 ReturnedValues);
446 }
447 }
448
449 /// See AbstractAttribute::manifest(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000450 ChangeStatus manifest(Attributor &A) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000451
452 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000453 AbstractState &getState() override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000454
455 /// See AbstractAttribute::getState(...).
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000456 const AbstractState &getState() const override { return *this; }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000457
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000458 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000459 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000460
461 /// Return the number of potential return values, -1 if unknown.
462 size_t getNumReturnValues() const {
463 return isValidState() ? ReturnedValues.size() : -1;
464 }
465
466 /// Return an assumed unique return value if a single candidate is found. If
467 /// there cannot be one, return a nullptr. If it is not clear yet, return the
468 /// Optional::NoneType.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000469 Optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000470
Johannes Doerfert14a04932019-08-07 22:27:24 +0000471 /// See AbstractState::checkForAllReturnedValues(...).
472 bool checkForAllReturnedValuesAndReturnInsts(
473 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
474 &Pred) const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000475
476 /// Pretty print the attribute similar to the IR representation.
Stefan Stipanovic15e86f72019-07-12 17:42:14 +0000477 const std::string getAsStr() const override;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000478
479 /// See AbstractState::isAtFixpoint().
480 bool isAtFixpoint() const override { return IsFixed; }
481
482 /// See AbstractState::isValidState().
483 bool isValidState() const override { return IsValidState; }
484
485 /// See AbstractState::indicateOptimisticFixpoint(...).
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000486 ChangeStatus indicateOptimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000487 IsFixed = true;
488 IsValidState &= true;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000489 return ChangeStatus::UNCHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000490 }
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000491
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000492 ChangeStatus indicatePessimisticFixpoint() override {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000493 IsFixed = true;
494 IsValidState = false;
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000495 return ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000496 }
497};
498
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000499struct AAReturnedValuesFunction final : public AAReturnedValuesImpl {
500 AAReturnedValuesFunction(Function &F)
501 : AAReturnedValuesImpl(F, IRP_FUNCTION) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000502
503 /// See AbstractAttribute::trackStatistics()
504 void trackStatistics() const override {
505 STATS_DECL_AND_TRACK_ARG_ATTR(returned)
506 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000507};
508
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000509ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) {
510 ChangeStatus Changed = ChangeStatus::UNCHANGED;
511
512 // Bookkeeping.
513 assert(isValidState());
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000514 STATS_DECL_AND_TRACK(KnownReturnValues, FunctionReturn,
515 "Number of function with known return values");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000516
517 // Check if we have an assumed unique return value that we could manifest.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000518 Optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000519
520 if (!UniqueRV.hasValue() || !UniqueRV.getValue())
521 return Changed;
522
523 // Bookkeeping.
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000524 STATS_DECL_AND_TRACK(UniqueReturnValue, FunctionReturn,
525 "Number of function with unique return");
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000526
527 // If the assumed unique return value is an argument, annotate it.
528 if (auto *UniqueRVArg = dyn_cast<Argument>(UniqueRV.getValue())) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000529 setAssociatedValue(UniqueRVArg);
530 setAttributeIdx(UniqueRVArg->getArgNo() + AttributeList::FirstArgIndex);
Johannes Doerferteccdf082019-08-05 23:35:12 +0000531 Changed = IRAttribute::manifest(A) | Changed;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000532 }
533
534 return Changed;
535}
536
537const std::string AAReturnedValuesImpl::getAsStr() const {
538 return (isAtFixpoint() ? "returns(#" : "may-return(#") +
Johannes Doerfert6471bb62019-08-04 18:39:28 +0000539 (isValidState() ? std::to_string(getNumReturnValues()) : "?") +
540 ")[OD: " + std::to_string(HasOverdefinedReturnedCalls) + "]";
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000541}
542
Johannes Doerfert14a04932019-08-07 22:27:24 +0000543Optional<Value *>
544AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const {
545 // If checkForAllReturnedValues provides a unique value, ignoring potential
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000546 // undef values that can also be present, it is assumed to be the actual
547 // return value and forwarded to the caller of this method. If there are
548 // multiple, a nullptr is returned indicating there cannot be a unique
549 // returned value.
550 Optional<Value *> UniqueRV;
551
Johannes Doerfert14a04932019-08-07 22:27:24 +0000552 auto Pred = [&](Value &RV) -> bool {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000553 // If we found a second returned value and neither the current nor the saved
554 // one is an undef, there is no unique returned value. Undefs are special
555 // since we can pretend they have any value.
556 if (UniqueRV.hasValue() && UniqueRV != &RV &&
557 !(isa<UndefValue>(RV) || isa<UndefValue>(UniqueRV.getValue()))) {
558 UniqueRV = nullptr;
559 return false;
560 }
561
562 // Do not overwrite a value with an undef.
563 if (!UniqueRV.hasValue() || !isa<UndefValue>(RV))
564 UniqueRV = &RV;
565
566 return true;
567 };
568
Johannes Doerfert14a04932019-08-07 22:27:24 +0000569 if (!A.checkForAllReturnedValues(getAnchorScope(), Pred, *this))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000570 UniqueRV = nullptr;
571
572 return UniqueRV;
573}
574
Johannes Doerfert14a04932019-08-07 22:27:24 +0000575bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts(
576 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
577 &Pred) const {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000578 if (!isValidState())
579 return false;
580
581 // Check all returned values but ignore call sites as long as we have not
582 // encountered an overdefined one during an update.
583 for (auto &It : ReturnedValues) {
584 Value *RV = It.first;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000585 const SmallPtrSetImpl<ReturnInst *> &RetInsts = It.second;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000586
587 ImmutableCallSite ICS(RV);
588 if (ICS && !HasOverdefinedReturnedCalls)
589 continue;
590
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000591 if (!Pred(*RV, RetInsts))
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000592 return false;
593 }
594
595 return true;
596}
597
Johannes Doerfert007153e2019-08-05 23:26:06 +0000598ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A,
599 InformationCache &InfoCache) {
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000600
601 // Check if we know of any values returned by the associated function,
602 // if not, we are done.
603 if (getNumReturnValues() == 0) {
604 indicateOptimisticFixpoint();
605 return ChangeStatus::UNCHANGED;
606 }
607
608 // Check if any of the returned values is a call site we can refine.
609 decltype(ReturnedValues) AddRVs;
610 bool HasCallSite = false;
611
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000612 // Keep track of any change to trigger updates on dependent attributes.
613 ChangeStatus Changed = ChangeStatus::UNCHANGED;
614
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000615 auto *LivenessAA = A.getAAFor<AAIsDead>(*this, getAnchorScope());
616
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000617 // Look at all returned call sites.
618 for (auto &It : ReturnedValues) {
619 SmallPtrSet<ReturnInst *, 2> &ReturnInsts = It.second;
620 Value *RV = It.first;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000621
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000622 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Potentially returned value " << *RV
623 << "\n");
624
625 // Only call sites can change during an update, ignore the rest.
626 CallSite RetCS(RV);
627 if (!RetCS)
628 continue;
629
630 // For now, any call site we see will prevent us from directly fixing the
631 // state. However, if the information on the callees is fixed, the call
632 // sites will be removed and we will fix the information for this state.
633 HasCallSite = true;
634
Johannes Doerfert4361da22019-08-04 18:38:53 +0000635 // Ignore dead ReturnValues.
636 if (LivenessAA &&
637 !LivenessAA->isLiveInstSet(ReturnInsts.begin(), ReturnInsts.end())) {
638 LLVM_DEBUG(dbgs() << "[AAReturnedValues] all returns are assumed dead, "
639 "skip it for now\n");
640 continue;
641 }
642
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000643 // Try to find a assumed unique return value for the called function.
644 auto *RetCSAA = A.getAAFor<AAReturnedValuesImpl>(*this, *RV);
Johannes Doerfert0a7f4cd2019-07-13 01:09:21 +0000645 if (!RetCSAA) {
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000646 if (!HasOverdefinedReturnedCalls)
647 Changed = ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000648 HasOverdefinedReturnedCalls = true;
649 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned call site (" << *RV
650 << ") with " << (RetCSAA ? "invalid" : "no")
651 << " associated state\n");
652 continue;
653 }
654
655 // Try to find a assumed unique return value for the called function.
Johannes Doerfert14a04932019-08-07 22:27:24 +0000656 Optional<Value *> AssumedUniqueRV = RetCSAA->getAssumedUniqueReturnValue(A);
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000657
658 // If no assumed unique return value was found due to the lack of
659 // candidates, we may need to resolve more calls (through more update
660 // iterations) or the called function will not return. Either way, we simply
661 // stick with the call sites as return values. Because there were not
662 // multiple possibilities, we do not treat it as overdefined.
663 if (!AssumedUniqueRV.hasValue())
664 continue;
665
666 // If multiple, non-refinable values were found, there cannot be a unique
667 // return value for the called function. The returned call is overdefined!
668 if (!AssumedUniqueRV.getValue()) {
Johannes Doerfertda4d8112019-08-01 16:21:54 +0000669 if (!HasOverdefinedReturnedCalls)
670 Changed = ChangeStatus::CHANGED;
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000671 HasOverdefinedReturnedCalls = true;
672 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned call site has multiple "
673 "potentially returned values\n");
674 continue;
675 }
676
677 LLVM_DEBUG({
678 bool UniqueRVIsKnown = RetCSAA->isAtFixpoint();
679 dbgs() << "[AAReturnedValues] Returned call site "
680 << (UniqueRVIsKnown ? "known" : "assumed")
681 << " unique return value: " << *AssumedUniqueRV << "\n";
682 });
683
684 // The assumed unique return value.
685 Value *AssumedRetVal = AssumedUniqueRV.getValue();
686
687 // If the assumed unique return value is an argument, lookup the matching
688 // call site operand and recursively collect new returned values.
689 // If it is not an argument, it is just put into the set of returned values
690 // as we would have already looked through casts, phis, and similar values.
691 if (Argument *AssumedRetArg = dyn_cast<Argument>(AssumedRetVal))
692 collectValuesRecursively(A,
693 RetCS.getArgOperand(AssumedRetArg->getArgNo()),
694 ReturnInsts, AddRVs);
695 else
696 AddRVs[AssumedRetVal].insert(ReturnInsts.begin(), ReturnInsts.end());
697 }
698
Johannes Doerfertaccd3e82019-07-08 23:27:20 +0000699 for (auto &It : AddRVs) {
700 assert(!It.second.empty() && "Entry does not add anything.");
701 auto &ReturnInsts = ReturnedValues[It.first];
702 for (ReturnInst *RI : It.second)
703 if (ReturnInsts.insert(RI).second) {
704 LLVM_DEBUG(dbgs() << "[AAReturnedValues] Add new returned value "
705 << *It.first << " => " << *RI << "\n");
706 Changed = ChangeStatus::CHANGED;
707 }
708 }
709
710 // If there is no call site in the returned values we are done.
711 if (!HasCallSite) {
712 indicateOptimisticFixpoint();
713 return ChangeStatus::CHANGED;
714 }
715
716 return Changed;
717}
718
Stefan Stipanovic06263672019-07-11 21:37:40 +0000719/// ------------------------ NoSync Function Attribute -------------------------
720
Johannes Doerfert344d0382019-08-07 22:34:26 +0000721struct AANoSyncImpl : AANoSync {
Johannes Doerferteccdf082019-08-05 23:35:12 +0000722 IRPositionConstructorForward(AANoSyncImpl, AANoSync);
Stefan Stipanovic06263672019-07-11 21:37:40 +0000723
Stefan Stipanoviccb5ecae2019-07-12 18:34:06 +0000724 const std::string getAsStr() const override {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000725 return getAssumed() ? "nosync" : "may-sync";
726 }
727
728 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000729 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000730
Stefan Stipanovic06263672019-07-11 21:37:40 +0000731 /// Helper function used to determine whether an instruction is non-relaxed
732 /// atomic. In other words, if an atomic instruction does not have unordered
733 /// or monotonic ordering
734 static bool isNonRelaxedAtomic(Instruction *I);
735
736 /// Helper function used to determine whether an instruction is volatile.
737 static bool isVolatile(Instruction *I);
738
Johannes Doerfertc7a1db32019-07-13 01:09:27 +0000739 /// Helper function uset to check if intrinsic is volatile (memcpy, memmove,
740 /// memset).
Stefan Stipanovic06263672019-07-11 21:37:40 +0000741 static bool isNoSyncIntrinsic(Instruction *I);
742};
743
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000744struct AANoSyncFunction final : public AANoSyncImpl {
745 AANoSyncFunction(Function &F) : AANoSyncImpl(F, IRP_FUNCTION) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000746
747 /// See AbstractAttribute::trackStatistics()
748 void trackStatistics() const override { STATS_DECL_AND_TRACK_FN_ATTR(nosync) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000749};
750
751bool AANoSyncImpl::isNonRelaxedAtomic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000752 if (!I->isAtomic())
753 return false;
754
755 AtomicOrdering Ordering;
756 switch (I->getOpcode()) {
757 case Instruction::AtomicRMW:
758 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
759 break;
760 case Instruction::Store:
761 Ordering = cast<StoreInst>(I)->getOrdering();
762 break;
763 case Instruction::Load:
764 Ordering = cast<LoadInst>(I)->getOrdering();
765 break;
766 case Instruction::Fence: {
767 auto *FI = cast<FenceInst>(I);
768 if (FI->getSyncScopeID() == SyncScope::SingleThread)
769 return false;
770 Ordering = FI->getOrdering();
771 break;
772 }
773 case Instruction::AtomicCmpXchg: {
774 AtomicOrdering Success = cast<AtomicCmpXchgInst>(I)->getSuccessOrdering();
775 AtomicOrdering Failure = cast<AtomicCmpXchgInst>(I)->getFailureOrdering();
776 // Only if both are relaxed, than it can be treated as relaxed.
777 // Otherwise it is non-relaxed.
778 if (Success != AtomicOrdering::Unordered &&
779 Success != AtomicOrdering::Monotonic)
780 return true;
781 if (Failure != AtomicOrdering::Unordered &&
782 Failure != AtomicOrdering::Monotonic)
783 return true;
784 return false;
785 }
786 default:
787 llvm_unreachable(
788 "New atomic operations need to be known in the attributor.");
789 }
790
791 // Relaxed.
792 if (Ordering == AtomicOrdering::Unordered ||
793 Ordering == AtomicOrdering::Monotonic)
794 return false;
795 return true;
796}
797
798/// Checks if an intrinsic is nosync. Currently only checks mem* intrinsics.
799/// FIXME: We should ipmrove the handling of intrinsics.
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000800bool AANoSyncImpl::isNoSyncIntrinsic(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000801 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
802 switch (II->getIntrinsicID()) {
803 /// Element wise atomic memory intrinsics are can only be unordered,
804 /// therefore nosync.
805 case Intrinsic::memset_element_unordered_atomic:
806 case Intrinsic::memmove_element_unordered_atomic:
807 case Intrinsic::memcpy_element_unordered_atomic:
808 return true;
809 case Intrinsic::memset:
810 case Intrinsic::memmove:
811 case Intrinsic::memcpy:
812 if (!cast<MemIntrinsic>(II)->isVolatile())
813 return true;
814 return false;
815 default:
816 return false;
817 }
818 }
819 return false;
820}
821
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000822bool AANoSyncImpl::isVolatile(Instruction *I) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000823 assert(!ImmutableCallSite(I) && !isa<CallBase>(I) &&
824 "Calls should not be checked here");
825
826 switch (I->getOpcode()) {
827 case Instruction::AtomicRMW:
828 return cast<AtomicRMWInst>(I)->isVolatile();
829 case Instruction::Store:
830 return cast<StoreInst>(I)->isVolatile();
831 case Instruction::Load:
832 return cast<LoadInst>(I)->isVolatile();
833 case Instruction::AtomicCmpXchg:
834 return cast<AtomicCmpXchgInst>(I)->isVolatile();
835 default:
836 return false;
837 }
838}
839
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000840ChangeStatus AANoSyncImpl::updateImpl(Attributor &A,
841 InformationCache &InfoCache) {
Stefan Stipanovic06263672019-07-11 21:37:40 +0000842 Function &F = getAnchorScope();
843
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000844 auto CheckRWInstForNoSync = [&](Instruction &I) {
845 /// We are looking for volatile instructions or Non-Relaxed atomics.
846 /// FIXME: We should ipmrove the handling of intrinsics.
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000847
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000848 ImmutableCallSite ICS(&I);
849 auto *NoSyncAA = A.getAAFor<AANoSyncImpl>(*this, I);
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000850
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000851 if (isa<IntrinsicInst>(&I) && isNoSyncIntrinsic(&I))
852 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000853
854 if (ICS && (!NoSyncAA || !NoSyncAA->isAssumedNoSync()) &&
Johannes Doerfertd1c37932019-08-04 18:37:38 +0000855 !ICS.hasFnAttr(Attribute::NoSync))
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000856 return false;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000857
Johannes Doerfertc7a1db32019-07-13 01:09:27 +0000858 if (ICS)
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000859 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000860
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000861 if (!isVolatile(&I) && !isNonRelaxedAtomic(&I))
862 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000863
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000864 return false;
865 };
Stefan Stipanovic06263672019-07-11 21:37:40 +0000866
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000867 auto CheckForNoSync = [&](Instruction &I) {
868 // At this point we handled all read/write effects and they are all
869 // nosync, so they can be skipped.
870 if (I.mayReadOrWriteMemory())
871 return true;
Stefan Stipanovic06263672019-07-11 21:37:40 +0000872
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000873 // non-convergent and readnone imply nosync.
874 return !ImmutableCallSite(&I).isConvergent();
875 };
Stefan Stipanovic06263672019-07-11 21:37:40 +0000876
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000877 if (!A.checkForAllReadWriteInstructions(F, CheckRWInstForNoSync, *this,
878 InfoCache) ||
879 !A.checkForAllCallLikeInstructions(F, CheckForNoSync, *this, InfoCache))
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000880 return indicatePessimisticFixpoint();
Stefan Stipanovicaaa52702019-08-07 18:26:02 +0000881
Stefan Stipanovic06263672019-07-11 21:37:40 +0000882 return ChangeStatus::UNCHANGED;
883}
884
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000885/// ------------------------ No-Free Attributes ----------------------------
886
Johannes Doerfert344d0382019-08-07 22:34:26 +0000887struct AANoFreeImpl : public AANoFree {
Johannes Doerferteccdf082019-08-05 23:35:12 +0000888 IRPositionConstructorForward(AANoFreeImpl, AANoFree);
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000889
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000890 /// See AbstractAttribute::getAsStr().
891 const std::string getAsStr() const override {
892 return getAssumed() ? "nofree" : "may-free";
893 }
894
895 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000896 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000897};
898
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000899struct AANoFreeFunction final : public AANoFreeImpl {
900 AANoFreeFunction(Function &F) : AANoFreeImpl(F, IRP_FUNCTION) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000901
902 /// See AbstractAttribute::trackStatistics()
903 void trackStatistics() const override { STATS_DECL_AND_TRACK_FN_ATTR(nofree) }
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000904};
905
906ChangeStatus AANoFreeImpl::updateImpl(Attributor &A,
907 InformationCache &InfoCache) {
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000908 Function &F = getAnchorScope();
909
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000910 auto CheckForNoFree = [&](Instruction &I) {
911 if (ImmutableCallSite(&I).hasFnAttr(Attribute::NoFree))
912 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000913
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000914 auto *NoFreeAA = A.getAAFor<AANoFreeImpl>(*this, I);
915 return NoFreeAA && NoFreeAA->isAssumedNoFree();
916 };
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000917
Johannes Doerfertd0f64002019-08-06 00:32:43 +0000918 if (!A.checkForAllCallLikeInstructions(F, CheckForNoFree, *this, InfoCache))
919 return indicatePessimisticFixpoint();
Hideto Ueno65bbaf92019-07-12 17:38:51 +0000920 return ChangeStatus::UNCHANGED;
921}
922
Hideto Ueno54869ec2019-07-15 06:49:04 +0000923/// ------------------------ NonNull Argument Attribute ------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +0000924struct AANonNullImpl : AANonNull {
Johannes Doerferteccdf082019-08-05 23:35:12 +0000925 IRPositionConstructorForward(AANonNullImpl, AANonNull);
Hideto Ueno54869ec2019-07-15 06:49:04 +0000926
Hideto Ueno54869ec2019-07-15 06:49:04 +0000927 /// See AbstractAttribute::getAsStr().
928 const std::string getAsStr() const override {
929 return getAssumed() ? "nonnull" : "may-null";
930 }
931
Hideto Ueno54869ec2019-07-15 06:49:04 +0000932 /// Generate a predicate that checks if a given value is assumed nonnull.
933 /// The generated function returns true if a value satisfies any of
934 /// following conditions.
935 /// (i) A value is known nonZero(=nonnull).
936 /// (ii) A value is associated with AANonNull and its isAssumedNonNull() is
937 /// true.
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000938 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
939 generatePredicate(Attributor &);
Hideto Ueno54869ec2019-07-15 06:49:04 +0000940};
941
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000942std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
943AANonNullImpl::generatePredicate(Attributor &A) {
Hideto Ueno54869ec2019-07-15 06:49:04 +0000944 // FIXME: The `AAReturnedValues` should provide the predicate with the
945 // `ReturnInst` vector as well such that we can use the control flow sensitive
946 // version of `isKnownNonZero`. This should fix `test11` in
947 // `test/Transforms/FunctionAttrs/nonnull.ll`
948
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000949 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
950 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &RetInsts) -> bool {
951 Function &F = getAnchorScope();
952
953 if (isKnownNonZero(&RV, F.getParent()->getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +0000954 return true;
955
956 auto *NonNullAA = A.getAAFor<AANonNull>(*this, RV);
957
958 ImmutableCallSite ICS(&RV);
959
960 if ((!NonNullAA || !NonNullAA->isAssumedNonNull()) &&
961 (!ICS || !ICS.hasRetAttr(Attribute::NonNull)))
962 return false;
963
964 return true;
965 };
966
967 return Pred;
968}
969
970/// NonNull attribute for function return value.
Johannes Doerfertbeb51502019-08-07 22:36:15 +0000971struct AANonNullReturned final : AANonNullImpl {
Johannes Doerfertfb69f762019-08-05 23:32:31 +0000972 AANonNullReturned(Function &F) : AANonNullImpl(F, IRP_RETURNED) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +0000973
Johannes Doerfertbeb51502019-08-07 22:36:15 +0000974 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000975 void initialize(Attributor &A, InformationCache &InfoCache) override {
Hideto Ueno54869ec2019-07-15 06:49:04 +0000976 Function &F = getAnchorScope();
977
978 // Already nonnull.
979 if (F.getAttributes().hasAttribute(AttributeList::ReturnIndex,
Hideto Ueno19c07af2019-07-23 08:16:17 +0000980 Attribute::NonNull) ||
981 F.getAttributes().hasAttribute(AttributeList::ReturnIndex,
982 Attribute::Dereferenceable))
Hideto Ueno54869ec2019-07-15 06:49:04 +0000983 indicateOptimisticFixpoint();
984 }
985
986 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +0000987 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +0000988
989 /// See AbstractAttribute::trackStatistics()
990 void trackStatistics() const override {
991 STATS_DECL_AND_TRACK_FNRET_ATTR(nonnull)
992 }
Hideto Ueno54869ec2019-07-15 06:49:04 +0000993};
994
Johannes Doerfert007153e2019-08-05 23:26:06 +0000995ChangeStatus AANonNullReturned::updateImpl(Attributor &A,
996 InformationCache &InfoCache) {
Hideto Ueno54869ec2019-07-15 06:49:04 +0000997 Function &F = getAnchorScope();
998
Stefan Stipanovicd0216172019-08-02 21:31:22 +0000999 std::function<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)> Pred =
1000 this->generatePredicate(A);
1001
Johannes Doerfert14a04932019-08-07 22:27:24 +00001002 if (!A.checkForAllReturnedValuesAndReturnInsts(F, Pred, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001003 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001004 return ChangeStatus::UNCHANGED;
1005}
1006
1007/// NonNull attribute for function argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001008struct AANonNullArgument final : AANonNullImpl {
Johannes Doerfert007153e2019-08-05 23:26:06 +00001009 AANonNullArgument(Argument &A) : AANonNullImpl(A) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001010
Hideto Ueno54869ec2019-07-15 06:49:04 +00001011 /// See AbstractAttriubute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001012 void initialize(Attributor &A, InformationCache &InfoCache) override {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001013 Argument *Arg = cast<Argument>(getAssociatedValue());
1014 if (Arg->hasNonNullAttr())
1015 indicateOptimisticFixpoint();
1016 }
1017
1018 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001019 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001020
1021 /// See AbstractAttribute::trackStatistics()
1022 void trackStatistics() const override {
1023 STATS_DECL_AND_TRACK_ARG_ATTR(nonnull)
1024 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001025};
1026
1027/// NonNull attribute for a call site argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001028struct AANonNullCallSiteArgument final : AANonNullImpl {
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00001029 AANonNullCallSiteArgument(Instruction &I, unsigned ArgNo)
1030 : AANonNullImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
Hideto Ueno54869ec2019-07-15 06:49:04 +00001031
1032 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001033 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001034 CallSite CS(&getAnchorValue());
1035 if (CS.paramHasAttr(getArgNo(), getAttrKind()) ||
1036 CS.paramHasAttr(getArgNo(), Attribute::Dereferenceable) ||
Hideto Ueno19c07af2019-07-23 08:16:17 +00001037 isKnownNonZero(getAssociatedValue(),
1038 getAnchorScope().getParent()->getDataLayout()))
Hideto Ueno54869ec2019-07-15 06:49:04 +00001039 indicateOptimisticFixpoint();
1040 }
1041
1042 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001043 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001044
1045 /// See AbstractAttribute::trackStatistics()
1046 void trackStatistics() const override {
1047 STATS_DECL_AND_TRACK_CSARG_ATTR(nonnull)
1048 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00001049};
Johannes Doerfert007153e2019-08-05 23:26:06 +00001050
1051ChangeStatus AANonNullArgument::updateImpl(Attributor &A,
1052 InformationCache &InfoCache) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001053 Function &F = getAnchorScope();
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001054 unsigned ArgNo = getArgNo();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001055
1056 // Callback function
1057 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) {
1058 assert(CS && "Sanity check: Call site was not initialized properly!");
1059
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001060 auto *NonNullAA =
1061 A.getAAFor<AANonNullImpl>(*this, *CS.getInstruction(), ArgNo);
Hideto Ueno54869ec2019-07-15 06:49:04 +00001062
1063 // Check that NonNullAA is AANonNullCallSiteArgument.
1064 if (NonNullAA) {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001065 ImmutableCallSite ICS(&NonNullAA->getAnchorValue());
Hideto Ueno54869ec2019-07-15 06:49:04 +00001066 if (ICS && CS.getInstruction() == ICS.getInstruction())
1067 return NonNullAA->isAssumedNonNull();
1068 return false;
1069 }
1070
1071 if (CS.paramHasAttr(ArgNo, Attribute::NonNull))
1072 return true;
1073
1074 Value *V = CS.getArgOperand(ArgNo);
1075 if (isKnownNonZero(V, getAnchorScope().getParent()->getDataLayout()))
1076 return true;
1077
1078 return false;
1079 };
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001080 if (!A.checkForAllCallSites(F, CallSiteCheck, *this, true))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001081 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001082 return ChangeStatus::UNCHANGED;
1083}
1084
Johannes Doerfert007153e2019-08-05 23:26:06 +00001085ChangeStatus
1086AANonNullCallSiteArgument::updateImpl(Attributor &A,
1087 InformationCache &InfoCache) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00001088 // NOTE: Never look at the argument of the callee in this method.
1089 // If we do this, "nonnull" is always deduced because of the assumption.
1090
1091 Value &V = *getAssociatedValue();
1092
1093 auto *NonNullAA = A.getAAFor<AANonNull>(*this, V);
1094
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001095 if (!NonNullAA || !NonNullAA->isAssumedNonNull())
1096 return indicatePessimisticFixpoint();
Hideto Ueno54869ec2019-07-15 06:49:04 +00001097
1098 return ChangeStatus::UNCHANGED;
1099}
1100
Hideto Ueno11d37102019-07-17 15:15:43 +00001101/// ------------------------ Will-Return Attributes ----------------------------
1102
Johannes Doerfert344d0382019-08-07 22:34:26 +00001103struct AAWillReturnImpl : public AAWillReturn {
Johannes Doerferteccdf082019-08-05 23:35:12 +00001104 IRPositionConstructorForward(AAWillReturnImpl, AAWillReturn);
Hideto Ueno11d37102019-07-17 15:15:43 +00001105
Hideto Ueno11d37102019-07-17 15:15:43 +00001106 /// See AbstractAttribute::getAsStr()
1107 const std::string getAsStr() const override {
1108 return getAssumed() ? "willreturn" : "may-noreturn";
1109 }
1110};
1111
1112struct AAWillReturnFunction final : AAWillReturnImpl {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001113 AAWillReturnFunction(Function &F) : AAWillReturnImpl(F, IRP_FUNCTION) {}
Hideto Ueno11d37102019-07-17 15:15:43 +00001114
1115 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001116 void initialize(Attributor &A, InformationCache &InfoCache) override;
Hideto Ueno11d37102019-07-17 15:15:43 +00001117
1118 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001119 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001120
1121 /// See AbstractAttribute::trackStatistics()
1122 void trackStatistics() const override {
1123 STATS_DECL_AND_TRACK_FN_ATTR(willreturn)
1124 }
Hideto Ueno11d37102019-07-17 15:15:43 +00001125};
1126
1127// Helper function that checks whether a function has any cycle.
1128// TODO: Replace with more efficent code
1129bool containsCycle(Function &F) {
1130 SmallPtrSet<BasicBlock *, 32> Visited;
1131
1132 // Traverse BB by dfs and check whether successor is already visited.
1133 for (BasicBlock *BB : depth_first(&F)) {
1134 Visited.insert(BB);
1135 for (auto *SuccBB : successors(BB)) {
1136 if (Visited.count(SuccBB))
1137 return true;
1138 }
1139 }
1140 return false;
1141}
1142
1143// Helper function that checks the function have a loop which might become an
1144// endless loop
1145// FIXME: Any cycle is regarded as endless loop for now.
1146// We have to allow some patterns.
1147bool containsPossiblyEndlessLoop(Function &F) { return containsCycle(F); }
1148
Johannes Doerfert007153e2019-08-05 23:26:06 +00001149void AAWillReturnFunction::initialize(Attributor &A,
1150 InformationCache &InfoCache) {
Hideto Ueno11d37102019-07-17 15:15:43 +00001151 Function &F = getAnchorScope();
1152
1153 if (containsPossiblyEndlessLoop(F))
1154 indicatePessimisticFixpoint();
1155}
1156
Johannes Doerfert007153e2019-08-05 23:26:06 +00001157ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A,
1158 InformationCache &InfoCache) {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001159 const Function &F = getAnchorScope();
Hideto Ueno11d37102019-07-17 15:15:43 +00001160 // The map from instruction opcodes to those instructions in the function.
Hideto Ueno11d37102019-07-17 15:15:43 +00001161
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001162 auto CheckForWillReturn = [&](Instruction &I) {
1163 ImmutableCallSite ICS(&I);
1164 if (ICS.hasFnAttr(Attribute::WillReturn))
1165 return true;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001166
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001167 auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, I);
1168 if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn())
1169 return false;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001170
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001171 // FIXME: Prohibit any recursion for now.
1172 if (ICS.hasFnAttr(Attribute::NoRecurse))
1173 return true;
Hideto Ueno11d37102019-07-17 15:15:43 +00001174
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001175 auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, I);
1176 return NoRecurseAA && NoRecurseAA->isAssumedNoRecurse();
1177 };
Hideto Ueno11d37102019-07-17 15:15:43 +00001178
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001179 if (!A.checkForAllCallLikeInstructions(F, CheckForWillReturn, *this,
1180 InfoCache))
1181 return indicatePessimisticFixpoint();
Hideto Ueno11d37102019-07-17 15:15:43 +00001182
1183 return ChangeStatus::UNCHANGED;
1184}
1185
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001186/// ------------------------ NoAlias Argument Attribute ------------------------
1187
Johannes Doerfert344d0382019-08-07 22:34:26 +00001188struct AANoAliasImpl : AANoAlias {
Johannes Doerferteccdf082019-08-05 23:35:12 +00001189 IRPositionConstructorForward(AANoAliasImpl, AANoAlias);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001190
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001191 const std::string getAsStr() const override {
1192 return getAssumed() ? "noalias" : "may-alias";
1193 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001194};
1195
1196/// NoAlias attribute for function return value.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001197struct AANoAliasReturned final : AANoAliasImpl {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001198 AANoAliasReturned(Function &F) : AANoAliasImpl(F, IRP_RETURNED) {}
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001199
1200 /// See AbstractAttriubute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001201 void initialize(Attributor &A, InformationCache &InfoCache) override {
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001202 Function &F = getAnchorScope();
1203
1204 // Already noalias.
1205 if (F.returnDoesNotAlias()) {
1206 indicateOptimisticFixpoint();
1207 return;
1208 }
1209 }
1210
1211 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001212 virtual ChangeStatus updateImpl(Attributor &A,
1213 InformationCache &InfoCache) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001214
1215 /// See AbstractAttribute::trackStatistics()
1216 void trackStatistics() const override {
1217 STATS_DECL_AND_TRACK_FNRET_ATTR(noalias)
1218 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001219};
1220
Johannes Doerfert007153e2019-08-05 23:26:06 +00001221ChangeStatus AANoAliasReturned::updateImpl(Attributor &A,
1222 InformationCache &InfoCache) {
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001223 Function &F = getAnchorScope();
1224
Johannes Doerfert14a04932019-08-07 22:27:24 +00001225 auto CheckReturnValue = [&](Value &RV) -> bool {
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001226 if (Constant *C = dyn_cast<Constant>(&RV))
1227 if (C->isNullValue() || isa<UndefValue>(C))
1228 return true;
1229
1230 /// For now, we can only deduce noalias if we have call sites.
1231 /// FIXME: add more support.
1232 ImmutableCallSite ICS(&RV);
1233 if (!ICS)
1234 return false;
1235
Johannes Doerfert14a04932019-08-07 22:27:24 +00001236 if (!ICS.returnDoesNotAlias()) {
1237 auto *NoAliasAA = A.getAAFor<AANoAlias>(*this, RV);
1238 if (!NoAliasAA || !NoAliasAA->isAssumedNoAlias())
1239 return false;
1240 }
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001241
1242 /// FIXME: We can improve capture check in two ways:
1243 /// 1. Use the AANoCapture facilities.
1244 /// 2. Use the location of return insts for escape queries.
1245 if (PointerMayBeCaptured(&RV, /* ReturnCaptures */ false,
1246 /* StoreCaptures */ true))
1247 return false;
1248
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001249 return true;
1250 };
1251
Johannes Doerfert14a04932019-08-07 22:27:24 +00001252 if (!A.checkForAllReturnedValues(F, CheckReturnValue, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001253 return indicatePessimisticFixpoint();
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00001254
1255 return ChangeStatus::UNCHANGED;
1256}
1257
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001258/// -------------------AAIsDead Function Attribute-----------------------
1259
Johannes Doerfert344d0382019-08-07 22:34:26 +00001260struct AAIsDeadImpl : public AAIsDead {
Johannes Doerferteccdf082019-08-05 23:35:12 +00001261 IRPositionConstructorForward(AAIsDeadImpl, AAIsDead);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001262
Johannes Doerfert007153e2019-08-05 23:26:06 +00001263 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001264 const Function &F = getAnchorScope();
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001265
1266 ToBeExploredPaths.insert(&(F.getEntryBlock().front()));
1267 AssumedLiveBlocks.insert(&(F.getEntryBlock()));
1268 for (size_t i = 0; i < ToBeExploredPaths.size(); ++i)
Johannes Doerfert4361da22019-08-04 18:38:53 +00001269 if (const Instruction *NextNoReturnI =
1270 findNextNoReturn(A, ToBeExploredPaths[i]))
1271 NoReturnCalls.insert(NextNoReturnI);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001272 }
1273
Johannes Doerfert4361da22019-08-04 18:38:53 +00001274 /// Find the next assumed noreturn instruction in the block of \p I starting
1275 /// from, thus including, \p I.
1276 ///
1277 /// The caller is responsible to monitor the ToBeExploredPaths set as new
1278 /// instructions discovered in other basic block will be placed in there.
1279 ///
1280 /// \returns The next assumed noreturn instructions in the block of \p I
1281 /// starting from, thus including, \p I.
1282 const Instruction *findNextNoReturn(Attributor &A, const Instruction *I);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001283
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001284 /// See AbstractAttribute::getAsStr().
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001285 const std::string getAsStr() const override {
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001286 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
1287 std::to_string(getAnchorScope().size()) + "][#NRI " +
1288 std::to_string(NoReturnCalls.size()) + "]";
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001289 }
1290
1291 /// See AbstractAttribute::manifest(...).
1292 ChangeStatus manifest(Attributor &A) override {
1293 assert(getState().isValidState() &&
1294 "Attempted to manifest an invalid state!");
1295
1296 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
Johannes Doerfert924d2132019-08-05 21:34:45 +00001297 const Function &F = getAnchorScope();
1298
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001299 // Flag to determine if we can change an invoke to a call assuming the
1300 // callee is nounwind. This is not possible if the personality of the
1301 // function allows to catch asynchronous exceptions.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001302 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001303
Johannes Doerfert4361da22019-08-04 18:38:53 +00001304 for (const Instruction *NRC : NoReturnCalls) {
1305 Instruction *I = const_cast<Instruction *>(NRC);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001306 BasicBlock *BB = I->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001307 Instruction *SplitPos = I->getNextNode();
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001308
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001309 if (auto *II = dyn_cast<InvokeInst>(I)) {
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001310 // If we keep the invoke the split position is at the beginning of the
1311 // normal desitination block (it invokes a noreturn function after all).
1312 BasicBlock *NormalDestBB = II->getNormalDest();
1313 SplitPos = &NormalDestBB->front();
1314
Johannes Doerfert4361da22019-08-04 18:38:53 +00001315 /// Invoke is replaced with a call and unreachable is placed after it if
1316 /// the callee is nounwind and noreturn. Otherwise, we keep the invoke
1317 /// and only place an unreachable in the normal successor.
Johannes Doerfert924d2132019-08-05 21:34:45 +00001318 if (Invoke2CallAllowed) {
1319 if (Function *Callee = II->getCalledFunction()) {
1320 auto *AANoUnw = A.getAAFor<AANoUnwind>(*this, *Callee);
1321 if (Callee->hasFnAttribute(Attribute::NoUnwind) ||
1322 (AANoUnw && AANoUnw->isAssumedNoUnwind())) {
1323 LLVM_DEBUG(dbgs()
1324 << "[AAIsDead] Replace invoke with call inst\n");
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001325 // We do not need an invoke (II) but instead want a call followed
1326 // by an unreachable. However, we do not remove II as other
1327 // abstract attributes might have it cached as part of their
1328 // results. Given that we modify the CFG anyway, we simply keep II
1329 // around but in a new dead block. To avoid II being live through
1330 // a different edge we have to ensure the block we place it in is
1331 // only reached from the current block of II and then not reached
1332 // at all when we insert the unreachable.
1333 SplitBlockPredecessors(NormalDestBB, {BB}, ".i2c");
1334 CallInst *CI = createCallMatchingInvoke(II);
1335 CI->insertBefore(II);
1336 CI->takeName(II);
1337 II->replaceAllUsesWith(CI);
1338 SplitPos = CI->getNextNode();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001339 }
Johannes Doerfert4361da22019-08-04 18:38:53 +00001340 }
1341 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001342 }
1343
Johannes Doerfert3d7bbc62019-08-05 21:35:02 +00001344 BB = SplitPos->getParent();
Johannes Doerfert4361da22019-08-04 18:38:53 +00001345 SplitBlock(BB, SplitPos);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001346 changeToUnreachable(BB->getTerminator(), /* UseLLVMTrap */ false);
1347 HasChanged = ChangeStatus::CHANGED;
1348 }
1349
1350 return HasChanged;
1351 }
1352
1353 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001354 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001355
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001356 /// See AAIsDead::isAssumedDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001357 bool isAssumedDead(const BasicBlock *BB) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001358 assert(BB->getParent() == &getAnchorScope() &&
1359 "BB must be in the same anchor scope function.");
1360
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001361 if (!getAssumed())
1362 return false;
1363 return !AssumedLiveBlocks.count(BB);
1364 }
1365
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001366 /// See AAIsDead::isKnownDead(BasicBlock *).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001367 bool isKnownDead(const BasicBlock *BB) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001368 return getKnown() && isAssumedDead(BB);
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001369 }
1370
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001371 /// See AAIsDead::isAssumed(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001372 bool isAssumedDead(const Instruction *I) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001373 assert(I->getParent()->getParent() == &getAnchorScope() &&
1374 "Instruction must be in the same anchor scope function.");
1375
Stefan Stipanovic7849e412019-08-03 15:27:41 +00001376 if (!getAssumed())
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001377 return false;
1378
1379 // If it is not in AssumedLiveBlocks then it for sure dead.
1380 // Otherwise, it can still be after noreturn call in a live block.
1381 if (!AssumedLiveBlocks.count(I->getParent()))
1382 return true;
1383
1384 // If it is not after a noreturn call, than it is live.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001385 return isAfterNoReturn(I);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001386 }
1387
1388 /// See AAIsDead::isKnownDead(Instruction *I).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001389 bool isKnownDead(const Instruction *I) const override {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001390 return getKnown() && isAssumedDead(I);
1391 }
1392
1393 /// Check if instruction is after noreturn call, in other words, assumed dead.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001394 bool isAfterNoReturn(const Instruction *I) const;
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001395
Johannes Doerfert924d2132019-08-05 21:34:45 +00001396 /// Determine if \p F might catch asynchronous exceptions.
1397 static bool mayCatchAsynchronousExceptions(const Function &F) {
1398 return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F);
1399 }
1400
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001401 /// Collection of to be explored paths.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001402 SmallSetVector<const Instruction *, 8> ToBeExploredPaths;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001403
1404 /// Collection of all assumed live BasicBlocks.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001405 DenseSet<const BasicBlock *> AssumedLiveBlocks;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001406
1407 /// Collection of calls with noreturn attribute, assumed or knwon.
Johannes Doerfert4361da22019-08-04 18:38:53 +00001408 SmallSetVector<const Instruction *, 4> NoReturnCalls;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001409};
1410
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001411struct AAIsDeadFunction final : public AAIsDeadImpl {
1412 AAIsDeadFunction(Function &F) : AAIsDeadImpl(F, IRP_FUNCTION) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001413
1414 /// See AbstractAttribute::trackStatistics()
1415 void trackStatistics() const override {
1416 STATS_DECL(DeadBlocks, Function,
1417 "Number of basic blocks classified as dead");
1418 BUILD_STAT_NAME(DeadBlocks, Function) +=
1419 getAnchorScope().size() - AssumedLiveBlocks.size();
1420 STATS_DECL(PartiallyDeadBlocks, Function,
1421 "Number of basic blocks classified as partially dead");
1422 BUILD_STAT_NAME(PartiallyDeadBlocks, Function) += NoReturnCalls.size();
1423 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001424};
1425
1426bool AAIsDeadImpl::isAfterNoReturn(const Instruction *I) const {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001427 const Instruction *PrevI = I->getPrevNode();
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001428 while (PrevI) {
1429 if (NoReturnCalls.count(PrevI))
1430 return true;
1431 PrevI = PrevI->getPrevNode();
1432 }
1433 return false;
1434}
1435
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001436const Instruction *AAIsDeadImpl::findNextNoReturn(Attributor &A,
1437 const Instruction *I) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001438 const BasicBlock *BB = I->getParent();
Johannes Doerfert924d2132019-08-05 21:34:45 +00001439 const Function &F = *BB->getParent();
1440
1441 // Flag to determine if we can change an invoke to a call assuming the callee
1442 // is nounwind. This is not possible if the personality of the function allows
1443 // to catch asynchronous exceptions.
1444 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001445
1446 // TODO: We should have a function that determines if an "edge" is dead.
1447 // Edges could be from an instruction to the next or from a terminator
1448 // to the successor. For now, we need to special case the unwind block
1449 // of InvokeInst below.
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001450
1451 while (I) {
1452 ImmutableCallSite ICS(I);
1453
1454 if (ICS) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001455 // Regarless of the no-return property of an invoke instruction we only
1456 // learn that the regular successor is not reachable through this
1457 // instruction but the unwind block might still be.
1458 if (auto *Invoke = dyn_cast<InvokeInst>(I)) {
1459 // Use nounwind to justify the unwind block is dead as well.
1460 auto *AANoUnw = A.getAAFor<AANoUnwind>(*this, *Invoke);
Johannes Doerfert924d2132019-08-05 21:34:45 +00001461 if (!Invoke2CallAllowed ||
1462 (!AANoUnw || !AANoUnw->isAssumedNoUnwind())) {
Johannes Doerfert4361da22019-08-04 18:38:53 +00001463 AssumedLiveBlocks.insert(Invoke->getUnwindDest());
1464 ToBeExploredPaths.insert(&Invoke->getUnwindDest()->front());
1465 }
1466 }
1467
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001468 auto *NoReturnAA = A.getAAFor<AANoReturn>(*this, *I);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001469 if (ICS.hasFnAttr(Attribute::NoReturn) ||
1470 (NoReturnAA && NoReturnAA->isAssumedNoReturn()))
1471 return I;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001472 }
1473
1474 I = I->getNextNode();
1475 }
1476
1477 // get new paths (reachable blocks).
Johannes Doerfert4361da22019-08-04 18:38:53 +00001478 for (const BasicBlock *SuccBB : successors(BB)) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001479 AssumedLiveBlocks.insert(SuccBB);
Johannes Doerfert4361da22019-08-04 18:38:53 +00001480 ToBeExploredPaths.insert(&SuccBB->front());
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001481 }
1482
Johannes Doerfert4361da22019-08-04 18:38:53 +00001483 // No noreturn instruction found.
1484 return nullptr;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001485}
1486
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001487ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A,
1488 InformationCache &InfoCache) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001489 // Temporary collection to iterate over existing noreturn instructions. This
1490 // will alow easier modification of NoReturnCalls collection
Johannes Doerfert4361da22019-08-04 18:38:53 +00001491 SmallVector<const Instruction *, 8> NoReturnChanged;
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001492 ChangeStatus Status = ChangeStatus::UNCHANGED;
1493
Johannes Doerfert4361da22019-08-04 18:38:53 +00001494 for (const Instruction *I : NoReturnCalls)
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001495 NoReturnChanged.push_back(I);
1496
Johannes Doerfert4361da22019-08-04 18:38:53 +00001497 for (const Instruction *I : NoReturnChanged) {
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001498 size_t Size = ToBeExploredPaths.size();
1499
Johannes Doerfert4361da22019-08-04 18:38:53 +00001500 const Instruction *NextNoReturnI = findNextNoReturn(A, I);
1501 if (NextNoReturnI != I) {
1502 Status = ChangeStatus::CHANGED;
1503 NoReturnCalls.remove(I);
1504 if (NextNoReturnI)
1505 NoReturnCalls.insert(NextNoReturnI);
1506 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001507
Johannes Doerfert4361da22019-08-04 18:38:53 +00001508 // Explore new paths.
1509 while (Size != ToBeExploredPaths.size()) {
1510 Status = ChangeStatus::CHANGED;
1511 if (const Instruction *NextNoReturnI =
1512 findNextNoReturn(A, ToBeExploredPaths[Size++]))
1513 NoReturnCalls.insert(NextNoReturnI);
1514 }
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001515 }
1516
Hideto Ueno19c07af2019-07-23 08:16:17 +00001517 LLVM_DEBUG(
1518 dbgs() << "[AAIsDead] AssumedLiveBlocks: " << AssumedLiveBlocks.size()
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001519 << " Total number of blocks: " << getAnchorScope().size() << "\n");
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001520
Johannes Doerfertd6207812019-08-07 22:32:38 +00001521 // If we know everything is live there is no need to query for liveness.
1522 if (NoReturnCalls.empty() &&
1523 getAnchorScope().size() == AssumedLiveBlocks.size()) {
1524 // Indicating a pessimistic fixpoint will cause the state to be "invalid"
1525 // which will cause the Attributor to not return the AAIsDead on request,
1526 // which will prevent us from querying isAssumedDead().
1527 indicatePessimisticFixpoint();
1528 assert(!isValidState() && "Expected an invalid state!");
1529 }
1530
Stefan Stipanovic6058b862019-07-22 23:58:23 +00001531 return Status;
1532}
1533
Hideto Ueno19c07af2019-07-23 08:16:17 +00001534/// -------------------- Dereferenceable Argument Attribute --------------------
1535
1536struct DerefState : AbstractState {
1537
1538 /// State representing for dereferenceable bytes.
1539 IntegerState DerefBytesState;
1540
1541 /// State representing that whether the value is nonnull or global.
1542 IntegerState NonNullGlobalState;
1543
1544 /// Bits encoding for NonNullGlobalState.
1545 enum {
1546 DEREF_NONNULL = 1 << 0,
1547 DEREF_GLOBAL = 1 << 1,
1548 };
1549
1550 /// See AbstractState::isValidState()
1551 bool isValidState() const override { return DerefBytesState.isValidState(); }
1552
Johannes Doerfertb6acee52019-08-04 17:55:15 +00001553 /// See AbstractState::isAtFixpoint()
Hideto Ueno19c07af2019-07-23 08:16:17 +00001554 bool isAtFixpoint() const override {
Johannes Doerfertb6acee52019-08-04 17:55:15 +00001555 return !isValidState() || (DerefBytesState.isAtFixpoint() &&
1556 NonNullGlobalState.isAtFixpoint());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001557 }
1558
1559 /// See AbstractState::indicateOptimisticFixpoint(...)
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001560 ChangeStatus indicateOptimisticFixpoint() override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001561 DerefBytesState.indicateOptimisticFixpoint();
1562 NonNullGlobalState.indicateOptimisticFixpoint();
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001563 return ChangeStatus::UNCHANGED;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001564 }
1565
1566 /// See AbstractState::indicatePessimisticFixpoint(...)
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001567 ChangeStatus indicatePessimisticFixpoint() override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001568 DerefBytesState.indicatePessimisticFixpoint();
1569 NonNullGlobalState.indicatePessimisticFixpoint();
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001570 return ChangeStatus::CHANGED;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001571 }
1572
1573 /// Update known dereferenceable bytes.
1574 void takeKnownDerefBytesMaximum(uint64_t Bytes) {
1575 DerefBytesState.takeKnownMaximum(Bytes);
1576 }
1577
1578 /// Update assumed dereferenceable bytes.
1579 void takeAssumedDerefBytesMinimum(uint64_t Bytes) {
1580 DerefBytesState.takeAssumedMinimum(Bytes);
1581 }
1582
1583 /// Update assumed NonNullGlobalState
1584 void updateAssumedNonNullGlobalState(bool IsNonNull, bool IsGlobal) {
1585 if (!IsNonNull)
1586 NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
1587 if (!IsGlobal)
1588 NonNullGlobalState.removeAssumedBits(DEREF_GLOBAL);
1589 }
1590
1591 /// Equality for DerefState.
1592 bool operator==(const DerefState &R) {
1593 return this->DerefBytesState == R.DerefBytesState &&
1594 this->NonNullGlobalState == R.NonNullGlobalState;
1595 }
1596};
Hideto Ueno19c07af2019-07-23 08:16:17 +00001597
Johannes Doerferteccdf082019-08-05 23:35:12 +00001598struct AADereferenceableImpl : AADereferenceable, DerefState {
1599 IRPositionConstructorForward(AADereferenceableImpl, AADereferenceable);
Johannes Doerfert344d0382019-08-07 22:34:26 +00001600 using StateType = DerefState;
Hideto Ueno19c07af2019-07-23 08:16:17 +00001601
1602 /// See AbstractAttribute::getState()
1603 /// {
Johannes Doerfert344d0382019-08-07 22:34:26 +00001604 StateType &getState() override { return *this; }
1605 const StateType &getState() const override { return *this; }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001606 /// }
1607
1608 /// See AADereferenceable::getAssumedDereferenceableBytes().
1609 uint32_t getAssumedDereferenceableBytes() const override {
1610 return DerefBytesState.getAssumed();
1611 }
1612
1613 /// See AADereferenceable::getKnownDereferenceableBytes().
1614 uint32_t getKnownDereferenceableBytes() const override {
1615 return DerefBytesState.getKnown();
1616 }
1617
1618 // Helper function for syncing nonnull state.
1619 void syncNonNull(const AANonNull *NonNullAA) {
1620 if (!NonNullAA) {
1621 NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
1622 return;
1623 }
1624
1625 if (NonNullAA->isKnownNonNull())
1626 NonNullGlobalState.addKnownBits(DEREF_NONNULL);
1627
1628 if (!NonNullAA->isAssumedNonNull())
1629 NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
1630 }
1631
1632 /// See AADereferenceable::isAssumedGlobal().
1633 bool isAssumedGlobal() const override {
1634 return NonNullGlobalState.isAssumed(DEREF_GLOBAL);
1635 }
1636
1637 /// See AADereferenceable::isKnownGlobal().
1638 bool isKnownGlobal() const override {
1639 return NonNullGlobalState.isKnown(DEREF_GLOBAL);
1640 }
1641
1642 /// See AADereferenceable::isAssumedNonNull().
1643 bool isAssumedNonNull() const override {
1644 return NonNullGlobalState.isAssumed(DEREF_NONNULL);
1645 }
1646
1647 /// See AADereferenceable::isKnownNonNull().
1648 bool isKnownNonNull() const override {
1649 return NonNullGlobalState.isKnown(DEREF_NONNULL);
1650 }
1651
Johannes Doerferteccdf082019-08-05 23:35:12 +00001652 void getDeducedAttributes(LLVMContext &Ctx,
1653 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001654 // TODO: Add *_globally support
1655 if (isAssumedNonNull())
1656 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
1657 Ctx, getAssumedDereferenceableBytes()));
1658 else
1659 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
1660 Ctx, getAssumedDereferenceableBytes()));
1661 }
1662 uint64_t computeAssumedDerefenceableBytes(Attributor &A, Value &V,
1663 bool &IsNonNull, bool &IsGlobal);
1664
Johannes Doerfert007153e2019-08-05 23:26:06 +00001665 void initialize(Attributor &A, InformationCache &InfoCache) override {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001666 Function &F = getAnchorScope();
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001667 unsigned AttrIdx = getIRPosition().getAttrIdx();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001668
1669 for (Attribute::AttrKind AK :
1670 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull})
1671 if (F.getAttributes().hasAttribute(AttrIdx, AK))
1672 takeKnownDerefBytesMaximum(F.getAttribute(AttrIdx, AK).getValueAsInt());
1673 }
1674
1675 /// See AbstractAttribute::getAsStr().
1676 const std::string getAsStr() const override {
1677 if (!getAssumedDereferenceableBytes())
1678 return "unknown-dereferenceable";
1679 return std::string("dereferenceable") +
1680 (isAssumedNonNull() ? "" : "_or_null") +
1681 (isAssumedGlobal() ? "_globally" : "") + "<" +
1682 std::to_string(getKnownDereferenceableBytes()) + "-" +
1683 std::to_string(getAssumedDereferenceableBytes()) + ">";
1684 }
1685};
1686
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001687struct AADereferenceableReturned final : AADereferenceableImpl {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001688 AADereferenceableReturned(Function &F)
1689 : AADereferenceableImpl(F, IRP_RETURNED) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001690
1691 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001692 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001693
1694 /// See AbstractAttribute::trackStatistics()
1695 void trackStatistics() const override {
1696 STATS_DECL_AND_TRACK_FNRET_ATTR(dereferenceable)
1697 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001698};
1699
1700// Helper function that returns dereferenceable bytes.
1701static uint64_t calcDifferenceIfBaseIsNonNull(int64_t DerefBytes,
1702 int64_t Offset, bool IsNonNull) {
1703 if (!IsNonNull)
1704 return 0;
1705 return std::max((int64_t)0, DerefBytes - Offset);
1706}
1707
1708uint64_t AADereferenceableImpl::computeAssumedDerefenceableBytes(
1709 Attributor &A, Value &V, bool &IsNonNull, bool &IsGlobal) {
1710 // TODO: Tracking the globally flag.
1711 IsGlobal = false;
1712
1713 // First, we try to get information about V from Attributor.
1714 if (auto *DerefAA = A.getAAFor<AADereferenceable>(*this, V)) {
1715 IsNonNull &= DerefAA->isAssumedNonNull();
1716 return DerefAA->getAssumedDereferenceableBytes();
1717 }
1718
1719 // Otherwise, we try to compute assumed bytes from base pointer.
1720 const DataLayout &DL = getAnchorScope().getParent()->getDataLayout();
1721 unsigned IdxWidth =
1722 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
1723 APInt Offset(IdxWidth, 0);
1724 Value *Base = V.stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
1725
1726 if (auto *BaseDerefAA = A.getAAFor<AADereferenceable>(*this, *Base)) {
1727 IsNonNull &= Offset != 0;
1728 return calcDifferenceIfBaseIsNonNull(
1729 BaseDerefAA->getAssumedDereferenceableBytes(), Offset.getSExtValue(),
1730 Offset != 0 || BaseDerefAA->isAssumedNonNull());
1731 }
1732
1733 // Then, use IR information.
1734
1735 if (isDereferenceablePointer(Base, Base->getType(), DL))
1736 return calcDifferenceIfBaseIsNonNull(
1737 DL.getTypeStoreSize(Base->getType()->getPointerElementType()),
1738 Offset.getSExtValue(),
1739 !NullPointerIsDefined(&getAnchorScope(),
1740 V.getType()->getPointerAddressSpace()));
1741
1742 IsNonNull = false;
1743 return 0;
1744}
Johannes Doerfert007153e2019-08-05 23:26:06 +00001745
1746ChangeStatus
1747AADereferenceableReturned::updateImpl(Attributor &A,
1748 InformationCache &InfoCache) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001749 Function &F = getAnchorScope();
1750 auto BeforeState = static_cast<DerefState>(*this);
1751
1752 syncNonNull(A.getAAFor<AANonNull>(*this, F));
1753
Hideto Ueno19c07af2019-07-23 08:16:17 +00001754 bool IsNonNull = isAssumedNonNull();
1755 bool IsGlobal = isAssumedGlobal();
1756
Johannes Doerfert14a04932019-08-07 22:27:24 +00001757 auto CheckReturnValue = [&](Value &RV) -> bool {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001758 takeAssumedDerefBytesMinimum(
1759 computeAssumedDerefenceableBytes(A, RV, IsNonNull, IsGlobal));
1760 return isValidState();
1761 };
1762
Johannes Doerfert14a04932019-08-07 22:27:24 +00001763 if (A.checkForAllReturnedValues(F, CheckReturnValue, *this)) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001764 updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
1765 return BeforeState == static_cast<DerefState>(*this)
1766 ? ChangeStatus::UNCHANGED
1767 : ChangeStatus::CHANGED;
1768 }
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001769 return indicatePessimisticFixpoint();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001770}
1771
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001772struct AADereferenceableArgument final : AADereferenceableImpl {
Johannes Doerfert007153e2019-08-05 23:26:06 +00001773 AADereferenceableArgument(Argument &A) : AADereferenceableImpl(A) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001774
Hideto Ueno19c07af2019-07-23 08:16:17 +00001775 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001776 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001777
1778 /// See AbstractAttribute::trackStatistics()
1779 void trackStatistics() const override {
1780 STATS_DECL_AND_TRACK_ARG_ATTR(dereferenceable)
1781 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001782};
1783
Johannes Doerfert007153e2019-08-05 23:26:06 +00001784ChangeStatus
1785AADereferenceableArgument::updateImpl(Attributor &A,
1786 InformationCache &InfoCache) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001787 Function &F = getAnchorScope();
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001788 Argument &Arg = cast<Argument>(getAnchorValue());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001789
1790 auto BeforeState = static_cast<DerefState>(*this);
1791
1792 unsigned ArgNo = Arg.getArgNo();
1793
1794 syncNonNull(A.getAAFor<AANonNull>(*this, F, ArgNo));
1795
1796 bool IsNonNull = isAssumedNonNull();
1797 bool IsGlobal = isAssumedGlobal();
1798
1799 // Callback function
1800 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) -> bool {
1801 assert(CS && "Sanity check: Call site was not initialized properly!");
1802
1803 // Check that DereferenceableAA is AADereferenceableCallSiteArgument.
1804 if (auto *DereferenceableAA =
1805 A.getAAFor<AADereferenceable>(*this, *CS.getInstruction(), ArgNo)) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001806 ImmutableCallSite ICS(
1807 &DereferenceableAA->getIRPosition().getAnchorValue());
Hideto Ueno19c07af2019-07-23 08:16:17 +00001808 if (ICS && CS.getInstruction() == ICS.getInstruction()) {
1809 takeAssumedDerefBytesMinimum(
1810 DereferenceableAA->getAssumedDereferenceableBytes());
1811 IsNonNull &= DereferenceableAA->isAssumedNonNull();
1812 IsGlobal &= DereferenceableAA->isAssumedGlobal();
1813 return isValidState();
1814 }
1815 }
1816
1817 takeAssumedDerefBytesMinimum(computeAssumedDerefenceableBytes(
1818 A, *CS.getArgOperand(ArgNo), IsNonNull, IsGlobal));
1819
1820 return isValidState();
1821 };
1822
Johannes Doerfertd0f64002019-08-06 00:32:43 +00001823 if (!A.checkForAllCallSites(F, CallSiteCheck, *this, true))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001824 return indicatePessimisticFixpoint();
Hideto Ueno19c07af2019-07-23 08:16:17 +00001825
1826 updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
1827
1828 return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
1829 : ChangeStatus::CHANGED;
1830}
1831
1832/// Dereferenceable attribute for a call site argument.
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001833struct AADereferenceableCallSiteArgument final : AADereferenceableImpl {
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00001834 AADereferenceableCallSiteArgument(Instruction &I, unsigned ArgNo)
1835 : AADereferenceableImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
Hideto Ueno19c07af2019-07-23 08:16:17 +00001836
1837 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001838 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001839 CallSite CS(&getAnchorValue());
1840 if (CS.paramHasAttr(getArgNo(), Attribute::Dereferenceable))
1841 takeKnownDerefBytesMaximum(CS.getDereferenceableBytes(getArgNo()));
Hideto Ueno19c07af2019-07-23 08:16:17 +00001842
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001843 if (CS.paramHasAttr(getArgNo(), Attribute::DereferenceableOrNull))
1844 takeKnownDerefBytesMaximum(CS.getDereferenceableOrNullBytes(getArgNo()));
Hideto Ueno19c07af2019-07-23 08:16:17 +00001845 }
1846
1847 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001848 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001849
1850 /// See AbstractAttribute::trackStatistics()
1851 void trackStatistics() const override {
1852 STATS_DECL_AND_TRACK_CSARG_ATTR(dereferenceable)
1853 }
Hideto Ueno19c07af2019-07-23 08:16:17 +00001854};
1855
Johannes Doerfert007153e2019-08-05 23:26:06 +00001856ChangeStatus
1857AADereferenceableCallSiteArgument::updateImpl(Attributor &A,
1858 InformationCache &InfoCache) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00001859 // NOTE: Never look at the argument of the callee in this method.
1860 // If we do this, "dereferenceable" is always deduced because of the
1861 // assumption.
1862
1863 Value &V = *getAssociatedValue();
1864
1865 auto BeforeState = static_cast<DerefState>(*this);
1866
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001867 syncNonNull(A.getAAFor<AANonNull>(*this, getAnchorValue(), getArgNo()));
Hideto Ueno19c07af2019-07-23 08:16:17 +00001868 bool IsNonNull = isAssumedNonNull();
1869 bool IsGlobal = isKnownGlobal();
1870
1871 takeAssumedDerefBytesMinimum(
1872 computeAssumedDerefenceableBytes(A, V, IsNonNull, IsGlobal));
1873 updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
1874
1875 return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
1876 : ChangeStatus::CHANGED;
1877}
1878
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001879// ------------------------ Align Argument Attribute ------------------------
1880
Johannes Doerfert344d0382019-08-07 22:34:26 +00001881struct AAAlignImpl : AAAlign {
Johannes Doerferteccdf082019-08-05 23:35:12 +00001882 IRPositionConstructorForward(AAAlignImpl, AAAlign);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001883
1884 // Max alignemnt value allowed in IR
1885 static const unsigned MAX_ALIGN = 1U << 29;
1886
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001887 const std::string getAsStr() const override {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001888 return getAssumedAlign() ? ("align<" + std::to_string(getKnownAlign()) +
1889 "-" + std::to_string(getAssumedAlign()) + ">")
1890 : "unknown-align";
1891 }
1892
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001893 /// See AbstractAttriubute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001894 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001895 takeAssumedMinimum(MAX_ALIGN);
1896
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001897 Function &F = getAnchorScope();
1898
Johannes Doerfertbeb51502019-08-07 22:36:15 +00001899 unsigned AttrIdx = getAttrIdx();
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001900 // Already the function has align attribute on return value or argument.
Johannes Doerfert24020622019-08-05 23:30:01 +00001901 if (F.getAttributes().hasAttribute(AttrIdx, Attribute::Alignment))
1902 addKnownBits(
1903 F.getAttribute(AttrIdx, Attribute::Alignment).getAlignment());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001904 }
1905
1906 /// See AbstractAttribute::getDeducedAttributes
1907 virtual void
Johannes Doerferteccdf082019-08-05 23:35:12 +00001908 getDeducedAttributes(LLVMContext &Ctx,
1909 SmallVectorImpl<Attribute> &Attrs) const override {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001910 Attrs.emplace_back(Attribute::getWithAlignment(Ctx, getAssumedAlign()));
1911 }
1912};
1913
1914/// Align attribute for function return value.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001915struct AAAlignReturned final : AAAlignImpl {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001916 AAAlignReturned(Function &F) : AAAlignImpl(F, IRP_RETURNED) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001917
1918 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001919 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001920
1921 /// See AbstractAttribute::trackStatistics()
1922 void trackStatistics() const override {
1923 STATS_DECL_AND_TRACK_FNRET_ATTR(aligned)
1924 }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001925};
1926
Johannes Doerfert007153e2019-08-05 23:26:06 +00001927ChangeStatus AAAlignReturned::updateImpl(Attributor &A,
1928 InformationCache &InfoCache) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001929 Function &F = getAnchorScope();
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001930
1931 // Currently, align<n> is deduced if alignments in return values are assumed
1932 // as greater than n. We reach pessimistic fixpoint if any of the return value
1933 // wouldn't have align. If no assumed state was used for reasoning, an
1934 // optimistic fixpoint is reached earlier.
1935
1936 base_t BeforeState = getAssumed();
Johannes Doerfert14a04932019-08-07 22:27:24 +00001937 auto CheckReturnValue =
Stefan Stipanovicd0216172019-08-02 21:31:22 +00001938 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &RetInsts) -> bool {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001939 auto *AlignAA = A.getAAFor<AAAlign>(*this, RV);
1940
1941 if (AlignAA)
1942 takeAssumedMinimum(AlignAA->getAssumedAlign());
1943 else
1944 // Use IR information.
1945 takeAssumedMinimum(RV.getPointerAlignment(
1946 getAnchorScope().getParent()->getDataLayout()));
1947
1948 return isValidState();
1949 };
1950
Johannes Doerfert14a04932019-08-07 22:27:24 +00001951 if (!A.checkForAllReturnedValuesAndReturnInsts(F, CheckReturnValue, *this))
Johannes Doerfertd1c37932019-08-04 18:37:38 +00001952 return indicatePessimisticFixpoint();
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001953
1954 return (getAssumed() != BeforeState) ? ChangeStatus::CHANGED
1955 : ChangeStatus::UNCHANGED;
1956}
1957
1958/// Align attribute for function argument.
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001959struct AAAlignArgument final : AAAlignImpl {
Johannes Doerfert007153e2019-08-05 23:26:06 +00001960 AAAlignArgument(Argument &A) : AAAlignImpl(A) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001961
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001962 /// See AbstractAttribute::updateImpl(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00001963 virtual ChangeStatus updateImpl(Attributor &A,
1964 InformationCache &InfoCache) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00001965
1966 /// See AbstractAttribute::trackStatistics()
1967 void trackStatistics() const override{STATS_DECL_AND_TRACK_ARG_ATTR(aligned)};
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001968};
1969
Johannes Doerfert007153e2019-08-05 23:26:06 +00001970ChangeStatus AAAlignArgument::updateImpl(Attributor &A,
1971 InformationCache &InfoCache) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001972
1973 Function &F = getAnchorScope();
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001974 Argument &Arg = cast<Argument>(getAnchorValue());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001975
1976 unsigned ArgNo = Arg.getArgNo();
1977 const DataLayout &DL = F.getParent()->getDataLayout();
1978
1979 auto BeforeState = getAssumed();
1980
1981 // Callback function
1982 std::function<bool(CallSite)> CallSiteCheck = [&](CallSite CS) {
1983 assert(CS && "Sanity check: Call site was not initialized properly!");
1984
1985 auto *AlignAA = A.getAAFor<AAAlign>(*this, *CS.getInstruction(), ArgNo);
1986
1987 // Check that AlignAA is AAAlignCallSiteArgument.
1988 if (AlignAA) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00001989 ImmutableCallSite ICS(&AlignAA->getIRPosition().getAnchorValue());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00001990 if (ICS && CS.getInstruction() == ICS.getInstruction()) {
1991 takeAssumedMinimum(AlignAA->getAssumedAlign());
1992 return isValidState();
1993 }
1994 }
1995
1996 Value *V = CS.getArgOperand(ArgNo);
1997 takeAssumedMinimum(V->getPointerAlignment(DL));
1998 return isValidState();
1999 };
2000
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002001 if (!A.checkForAllCallSites(F, CallSiteCheck, *this, true))
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002002 indicatePessimisticFixpoint();
2003
2004 return BeforeState == getAssumed() ? ChangeStatus::UNCHANGED
2005 : ChangeStatus ::CHANGED;
2006}
2007
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002008struct AAAlignCallSiteArgument final : AAAlignImpl {
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002009 AAAlignCallSiteArgument(Instruction &I, unsigned ArgNo)
2010 : AAAlignImpl(CallSite(&I).getArgOperand(ArgNo), I, ArgNo) {}
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002011
2012 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00002013 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002014 CallSite CS(&getAnchorValue());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002015 takeKnownMaximum(getAssociatedValue()->getPointerAlignment(
2016 getAnchorScope().getParent()->getDataLayout()));
2017 }
2018
2019 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfert007153e2019-08-05 23:26:06 +00002020 ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override;
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002021
2022 /// See AbstractAttribute::trackStatistics()
2023 void trackStatistics() const override {
2024 STATS_DECL_AND_TRACK_CSARG_ATTR(aligned)
2025 }
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002026};
2027
Johannes Doerfert007153e2019-08-05 23:26:06 +00002028ChangeStatus AAAlignCallSiteArgument::updateImpl(Attributor &A,
2029 InformationCache &InfoCache) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002030 // NOTE: Never look at the argument of the callee in this method.
2031 // If we do this, "align" is always deduced because of the assumption.
2032
2033 auto BeforeState = getAssumed();
2034
2035 Value &V = *getAssociatedValue();
2036
2037 auto *AlignAA = A.getAAFor<AAAlign>(*this, V);
2038
2039 if (AlignAA)
2040 takeAssumedMinimum(AlignAA->getAssumedAlign());
2041 else
2042 indicatePessimisticFixpoint();
2043
2044 return BeforeState == getAssumed() ? ChangeStatus::UNCHANGED
2045 : ChangeStatus::CHANGED;
2046}
2047
Johannes Doerferte83f3032019-08-05 23:22:05 +00002048/// ------------------ Function No-Return Attribute ----------------------------
Johannes Doerfert344d0382019-08-07 22:34:26 +00002049struct AANoReturnImpl : public AANoReturn {
Johannes Doerferteccdf082019-08-05 23:35:12 +00002050 IRPositionConstructorForward(AANoReturnImpl, AANoReturn);
Johannes Doerferte83f3032019-08-05 23:22:05 +00002051
Johannes Doerferte83f3032019-08-05 23:22:05 +00002052 /// See AbstractAttribute::getAsStr().
2053 const std::string getAsStr() const override {
2054 return getAssumed() ? "noreturn" : "may-return";
2055 }
2056
2057 /// See AbstractAttribute::initialize(...).
Johannes Doerfert007153e2019-08-05 23:26:06 +00002058 void initialize(Attributor &A, InformationCache &InfoCache) override {
Johannes Doerferte83f3032019-08-05 23:22:05 +00002059 Function &F = getAnchorScope();
2060 if (F.hasFnAttribute(getAttrKind()))
2061 indicateOptimisticFixpoint();
2062 }
2063
2064 /// See AbstractAttribute::updateImpl(Attributor &A).
Johannes Doerfert007153e2019-08-05 23:26:06 +00002065 virtual ChangeStatus updateImpl(Attributor &A,
2066 InformationCache &InfoCache) override {
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002067 const Function &F = getAnchorScope();
2068 auto CheckForNoReturn = [](Instruction &) { return false; };
2069 if (!A.checkForAllInstructions(F, CheckForNoReturn, *this, InfoCache,
2070 {(unsigned)Instruction::Ret}))
Johannes Doerferte83f3032019-08-05 23:22:05 +00002071 return indicatePessimisticFixpoint();
Johannes Doerferte83f3032019-08-05 23:22:05 +00002072 return ChangeStatus::UNCHANGED;
2073 }
2074};
2075
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002076struct AANoReturnFunction final : AANoReturnImpl {
2077 AANoReturnFunction(Function &F) : AANoReturnImpl(F, IRP_FUNCTION) {}
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002078
2079 /// See AbstractAttribute::trackStatistics()
2080 void trackStatistics() const override {
2081 STATS_DECL_AND_TRACK_FN_ATTR(noreturn)
2082 }
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002083};
2084
Johannes Doerfertaade7822019-06-05 03:02:24 +00002085/// ----------------------------------------------------------------------------
2086/// Attributor
2087/// ----------------------------------------------------------------------------
2088
Hideto Ueno54869ec2019-07-15 06:49:04 +00002089bool Attributor::checkForAllCallSites(Function &F,
2090 std::function<bool(CallSite)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002091 const AbstractAttribute &QueryingAA,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002092 bool RequireAllCallSites) {
Hideto Ueno54869ec2019-07-15 06:49:04 +00002093 // We can try to determine information from
2094 // the call sites. However, this is only possible all call sites are known,
2095 // hence the function has internal linkage.
2096 if (RequireAllCallSites && !F.hasInternalLinkage()) {
2097 LLVM_DEBUG(
2098 dbgs()
2099 << "Attributor: Function " << F.getName()
2100 << " has no internal linkage, hence not all call sites are known\n");
2101 return false;
2102 }
2103
2104 for (const Use &U : F.uses()) {
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002105 Instruction *I = cast<Instruction>(U.getUser());
2106 Function *AnchorValue = I->getParent()->getParent();
2107
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002108 auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, *AnchorValue);
Stefan Stipanovicd0216172019-08-02 21:31:22 +00002109
2110 // Skip dead calls.
2111 if (LivenessAA && LivenessAA->isAssumedDead(I))
2112 continue;
Hideto Ueno54869ec2019-07-15 06:49:04 +00002113
2114 CallSite CS(U.getUser());
Hideto Ueno54869ec2019-07-15 06:49:04 +00002115 if (!CS || !CS.isCallee(&U) || !CS.getCaller()->hasExactDefinition()) {
2116 if (!RequireAllCallSites)
2117 continue;
2118
2119 LLVM_DEBUG(dbgs() << "Attributor: User " << *U.getUser()
2120 << " is an invalid use of " << F.getName() << "\n");
2121 return false;
2122 }
2123
2124 if (Pred(CS))
2125 continue;
2126
2127 LLVM_DEBUG(dbgs() << "Attributor: Call site callback failed for "
2128 << *CS.getInstruction() << "\n");
2129 return false;
2130 }
2131
2132 return true;
2133}
2134
Johannes Doerfert14a04932019-08-07 22:27:24 +00002135bool Attributor::checkForAllReturnedValuesAndReturnInsts(
2136 const Function &F,
2137 const function_ref<bool(Value &, const SmallPtrSetImpl<ReturnInst *> &)>
2138 &Pred,
2139 const AbstractAttribute &QueryingAA) {
2140
2141 auto *AARetVal = getAAFor<AAReturnedValues>(QueryingAA, F);
2142 if (!AARetVal)
2143 return false;
2144
2145 auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
2146 if (!LivenessAA)
2147 return AARetVal->checkForAllReturnedValuesAndReturnInsts(Pred);
2148
2149 auto LivenessFilter = [&](Value &RV,
2150 const SmallPtrSetImpl<ReturnInst *> &ReturnInsts) {
2151 SmallPtrSet<ReturnInst *, 4> FilteredReturnInsts;
2152 for (ReturnInst *RI : ReturnInsts)
2153 if (!LivenessAA->isAssumedDead(RI))
2154 FilteredReturnInsts.insert(RI);
2155 if (!FilteredReturnInsts.empty())
2156 return Pred(RV, FilteredReturnInsts);
2157 return true;
2158 };
2159
2160 return AARetVal->checkForAllReturnedValuesAndReturnInsts(LivenessFilter);
2161}
2162
2163bool Attributor::checkForAllReturnedValues(
2164 const Function &F, const function_ref<bool(Value &)> &Pred,
2165 const AbstractAttribute &QueryingAA) {
2166
2167 auto *AARetVal = getAAFor<AAReturnedValues>(QueryingAA, F);
2168 if (!AARetVal)
2169 return false;
2170
2171 auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
2172 if (!LivenessAA)
2173 return AARetVal->checkForAllReturnedValuesAndReturnInsts(
2174 [&](Value &RV, const SmallPtrSetImpl<ReturnInst *> &) {
2175 return Pred(RV);
2176 });
2177
2178 auto LivenessFilter = [&](Value &RV,
2179 const SmallPtrSetImpl<ReturnInst *> &ReturnInsts) {
2180 if (LivenessAA->isLiveInstSet(ReturnInsts.begin(), ReturnInsts.end()))
2181 return Pred(RV);
2182 return true;
2183 };
2184
2185 return AARetVal->checkForAllReturnedValuesAndReturnInsts(LivenessFilter);
2186}
2187
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002188bool Attributor::checkForAllInstructions(
2189 const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
Johannes Doerfert14a04932019-08-07 22:27:24 +00002190 const AbstractAttribute &QueryingAA, InformationCache &InfoCache,
Johannes Doerfertd0f64002019-08-06 00:32:43 +00002191 const ArrayRef<unsigned> &Opcodes) {
2192
2193 auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
2194
2195 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
2196 for (unsigned Opcode : Opcodes) {
2197 for (Instruction *I : OpcodeInstMap[Opcode]) {
2198 // Skip dead instructions.
2199 if (LivenessAA && LivenessAA->isAssumedDead(I))
2200 continue;
2201
2202 if (!Pred(*I))
2203 return false;
2204 }
2205 }
2206
2207 return true;
2208}
2209
Stefan Stipanovicaaa52702019-08-07 18:26:02 +00002210bool Attributor::checkForAllReadWriteInstructions(
2211 const Function &F, const llvm::function_ref<bool(Instruction &)> &Pred,
2212 AbstractAttribute &QueryingAA, InformationCache &InfoCache) {
2213
2214 auto *LivenessAA = getAAFor<AAIsDead>(QueryingAA, F);
2215
2216 for (Instruction *I : InfoCache.getReadOrWriteInstsForFunction(F)) {
2217 // Skip dead instructions.
2218 if (LivenessAA && LivenessAA->isAssumedDead(I))
2219 continue;
2220
2221 if (!Pred(*I))
2222 return false;
2223 }
2224
2225 return true;
2226}
2227
Johannes Doerfert007153e2019-08-05 23:26:06 +00002228ChangeStatus Attributor::run(InformationCache &InfoCache) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002229 // Initialize all abstract attributes.
2230 for (AbstractAttribute *AA : AllAbstractAttributes)
Johannes Doerfert007153e2019-08-05 23:26:06 +00002231 AA->initialize(*this, InfoCache);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002232
2233 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
2234 << AllAbstractAttributes.size()
2235 << " abstract attributes.\n");
2236
Stefan Stipanovic53605892019-06-27 11:27:54 +00002237 // Now that all abstract attributes are collected and initialized we start
2238 // the abstract analysis.
Johannes Doerfertaade7822019-06-05 03:02:24 +00002239
2240 unsigned IterationCounter = 1;
2241
2242 SmallVector<AbstractAttribute *, 64> ChangedAAs;
2243 SetVector<AbstractAttribute *> Worklist;
2244 Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
2245
2246 do {
2247 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
2248 << ", Worklist size: " << Worklist.size() << "\n");
2249
2250 // Add all abstract attributes that are potentially dependent on one that
2251 // changed to the work list.
2252 for (AbstractAttribute *ChangedAA : ChangedAAs) {
2253 auto &QuerriedAAs = QueryMap[ChangedAA];
2254 Worklist.insert(QuerriedAAs.begin(), QuerriedAAs.end());
2255 }
2256
2257 // Reset the changed set.
2258 ChangedAAs.clear();
2259
2260 // Update all abstract attribute in the work list and record the ones that
2261 // changed.
2262 for (AbstractAttribute *AA : Worklist)
Johannes Doerfert007153e2019-08-05 23:26:06 +00002263 if (AA->update(*this, InfoCache) == ChangeStatus::CHANGED)
Johannes Doerfertaade7822019-06-05 03:02:24 +00002264 ChangedAAs.push_back(AA);
2265
2266 // Reset the work list and repopulate with the changed abstract attributes.
2267 // Note that dependent ones are added above.
2268 Worklist.clear();
2269 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end());
2270
2271 } while (!Worklist.empty() && ++IterationCounter < MaxFixpointIterations);
2272
2273 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
2274 << IterationCounter << "/" << MaxFixpointIterations
2275 << " iterations\n");
2276
2277 bool FinishedAtFixpoint = Worklist.empty();
2278
2279 // Reset abstract arguments not settled in a sound fixpoint by now. This
2280 // happens when we stopped the fixpoint iteration early. Note that only the
2281 // ones marked as "changed" *and* the ones transitively depending on them
2282 // need to be reverted to a pessimistic state. Others might not be in a
2283 // fixpoint state but we can use the optimistic results for them anyway.
2284 SmallPtrSet<AbstractAttribute *, 32> Visited;
2285 for (unsigned u = 0; u < ChangedAAs.size(); u++) {
2286 AbstractAttribute *ChangedAA = ChangedAAs[u];
2287 if (!Visited.insert(ChangedAA).second)
2288 continue;
2289
2290 AbstractState &State = ChangedAA->getState();
2291 if (!State.isAtFixpoint()) {
2292 State.indicatePessimisticFixpoint();
2293
2294 NumAttributesTimedOut++;
2295 }
2296
2297 auto &QuerriedAAs = QueryMap[ChangedAA];
2298 ChangedAAs.append(QuerriedAAs.begin(), QuerriedAAs.end());
2299 }
2300
2301 LLVM_DEBUG({
2302 if (!Visited.empty())
2303 dbgs() << "\n[Attributor] Finalized " << Visited.size()
2304 << " abstract attributes.\n";
2305 });
2306
2307 unsigned NumManifested = 0;
2308 unsigned NumAtFixpoint = 0;
2309 ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
2310 for (AbstractAttribute *AA : AllAbstractAttributes) {
2311 AbstractState &State = AA->getState();
2312
2313 // If there is not already a fixpoint reached, we can now take the
2314 // optimistic state. This is correct because we enforced a pessimistic one
2315 // on abstract attributes that were transitively dependent on a changed one
2316 // already above.
2317 if (!State.isAtFixpoint())
2318 State.indicateOptimisticFixpoint();
2319
2320 // If the state is invalid, we do not try to manifest it.
2321 if (!State.isValidState())
2322 continue;
2323
2324 // Manifest the state and record if we changed the IR.
2325 ChangeStatus LocalChange = AA->manifest(*this);
Johannes Doerfertd1b79e02019-08-07 22:46:11 +00002326 if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled())
2327 AA->trackStatistics();
2328
Johannes Doerfertaade7822019-06-05 03:02:24 +00002329 ManifestChange = ManifestChange | LocalChange;
2330
2331 NumAtFixpoint++;
2332 NumManifested += (LocalChange == ChangeStatus::CHANGED);
2333 }
2334
2335 (void)NumManifested;
2336 (void)NumAtFixpoint;
2337 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
2338 << " arguments while " << NumAtFixpoint
2339 << " were in a valid fixpoint state\n");
2340
2341 // If verification is requested, we finished this run at a fixpoint, and the
2342 // IR was changed, we re-run the whole fixpoint analysis, starting at
2343 // re-initialization of the arguments. This re-run should not result in an IR
2344 // change. Though, the (virtual) state of attributes at the end of the re-run
2345 // might be more optimistic than the known state or the IR state if the better
2346 // state cannot be manifested.
2347 if (VerifyAttributor && FinishedAtFixpoint &&
2348 ManifestChange == ChangeStatus::CHANGED) {
2349 VerifyAttributor = false;
Johannes Doerfert007153e2019-08-05 23:26:06 +00002350 ChangeStatus VerifyStatus = run(InfoCache);
Johannes Doerfertaade7822019-06-05 03:02:24 +00002351 if (VerifyStatus != ChangeStatus::UNCHANGED)
2352 llvm_unreachable(
2353 "Attributor verification failed, re-run did result in an IR change "
2354 "even after a fixpoint was reached in the original run. (False "
2355 "positives possible!)");
2356 VerifyAttributor = true;
2357 }
2358
2359 NumAttributesManifested += NumManifested;
2360 NumAttributesValidFixpoint += NumAtFixpoint;
2361
2362 return ManifestChange;
2363}
2364
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002365/// Helper function that checks if an abstract attribute of type \p AAType
2366/// should be created for \p V (with argument number \p ArgNo) and if so creates
2367/// and registers it with the Attributor \p A.
2368///
2369/// This method will look at the provided whitelist. If one is given and the
2370/// kind \p AAType::ID is not contained, no abstract attribute is created.
2371///
2372/// \returns The created abstract argument, or nullptr if none was created.
2373template <typename AAType, typename ValueType, typename... ArgsTy>
2374static AAType *checkAndRegisterAA(const Function &F, Attributor &A,
2375 DenseSet<const char *> *Whitelist,
2376 ValueType &V, int ArgNo, ArgsTy... Args) {
2377 if (Whitelist && !Whitelist->count(&AAType::ID))
2378 return nullptr;
2379
2380 return &A.registerAA<AAType>(*new AAType(V, Args...), ArgNo);
2381}
2382
Johannes Doerfertaade7822019-06-05 03:02:24 +00002383void Attributor::identifyDefaultAbstractAttributes(
2384 Function &F, InformationCache &InfoCache,
Johannes Doerfert24020622019-08-05 23:30:01 +00002385 DenseSet<const char *> *Whitelist) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002386
Johannes Doerfert305b9612019-08-04 18:40:01 +00002387 // Check for dead BasicBlocks in every function.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002388 // We need dead instruction detection because we do not want to deal with
2389 // broken IR in which SSA rules do not apply.
2390 checkAndRegisterAA<AAIsDeadFunction>(F, *this, /* Whitelist */ nullptr, F,
2391 -1);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002392
2393 // Every function might be "will-return".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002394 checkAndRegisterAA<AAWillReturnFunction>(F, *this, Whitelist, F, -1);
Johannes Doerfert305b9612019-08-04 18:40:01 +00002395
Stefan Stipanovic53605892019-06-27 11:27:54 +00002396 // Every function can be nounwind.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002397 checkAndRegisterAA<AANoUnwindFunction>(F, *this, Whitelist, F, -1);
Stefan Stipanovic53605892019-06-27 11:27:54 +00002398
Stefan Stipanovic06263672019-07-11 21:37:40 +00002399 // Every function might be marked "nosync"
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002400 checkAndRegisterAA<AANoSyncFunction>(F, *this, Whitelist, F, -1);
Stefan Stipanovic06263672019-07-11 21:37:40 +00002401
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002402 // Every function might be "no-free".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002403 checkAndRegisterAA<AANoFreeFunction>(F, *this, Whitelist, F, -1);
Hideto Ueno65bbaf92019-07-12 17:38:51 +00002404
Johannes Doerferte83f3032019-08-05 23:22:05 +00002405 // Every function might be "no-return".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002406 checkAndRegisterAA<AANoReturnFunction>(F, *this, Whitelist, F, -1);
Johannes Doerferte83f3032019-08-05 23:22:05 +00002407
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002408 // Return attributes are only appropriate if the return type is non void.
2409 Type *ReturnType = F.getReturnType();
2410 if (!ReturnType->isVoidTy()) {
2411 // Argument attribute "returned" --- Create only one per function even
2412 // though it is an argument attribute.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002413 checkAndRegisterAA<AAReturnedValuesFunction>(F, *this, Whitelist, F, -1);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002414
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002415 if (ReturnType->isPointerTy()) {
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002416 // Every function with pointer return type might be marked align.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002417 checkAndRegisterAA<AAAlignReturned>(F, *this, Whitelist, F, -1);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002418
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002419 // Every function with pointer return type might be marked nonnull.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002420 checkAndRegisterAA<AANonNullReturned>(F, *this, Whitelist, F, -1);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002421
2422 // Every function with pointer return type might be marked noalias.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002423 checkAndRegisterAA<AANoAliasReturned>(F, *this, Whitelist, F, -1);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002424
2425 // Every function with pointer return type might be marked
2426 // dereferenceable.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002427 checkAndRegisterAA<AADereferenceableReturned>(F, *this, Whitelist, F, -1);
Stefan Stipanovic69ebb022019-07-22 19:36:27 +00002428 }
Hideto Ueno54869ec2019-07-15 06:49:04 +00002429 }
2430
Hideto Ueno54869ec2019-07-15 06:49:04 +00002431 for (Argument &Arg : F.args()) {
Hideto Ueno19c07af2019-07-23 08:16:17 +00002432 if (Arg.getType()->isPointerTy()) {
2433 // Every argument with pointer type might be marked nonnull.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002434 checkAndRegisterAA<AANonNullArgument>(F, *this, Whitelist, Arg,
2435 Arg.getArgNo());
Hideto Ueno19c07af2019-07-23 08:16:17 +00002436
2437 // Every argument with pointer type might be marked dereferenceable.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002438 checkAndRegisterAA<AADereferenceableArgument>(F, *this, Whitelist, Arg,
2439 Arg.getArgNo());
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002440
2441 // Every argument with pointer type might be marked align.
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002442 checkAndRegisterAA<AAAlignArgument>(F, *this, Whitelist, Arg,
2443 Arg.getArgNo());
Hideto Ueno19c07af2019-07-23 08:16:17 +00002444 }
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002445 }
2446
Johannes Doerfertaade7822019-06-05 03:02:24 +00002447 // Walk all instructions to find more attribute opportunities and also
2448 // interesting instructions that might be queried by abstract attributes
2449 // during their initialization or update.
2450 auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
2451 auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
2452
2453 for (Instruction &I : instructions(&F)) {
2454 bool IsInterestingOpcode = false;
2455
2456 // To allow easy access to all instructions in a function with a given
2457 // opcode we store them in the InfoCache. As not all opcodes are interesting
2458 // to concrete attributes we only cache the ones that are as identified in
2459 // the following switch.
2460 // Note: There are no concrete attributes now so this is initially empty.
Stefan Stipanovic53605892019-06-27 11:27:54 +00002461 switch (I.getOpcode()) {
2462 default:
2463 assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) &&
2464 "New call site/base instruction type needs to be known int the "
2465 "attributor.");
2466 break;
2467 case Instruction::Call:
2468 case Instruction::CallBr:
2469 case Instruction::Invoke:
2470 case Instruction::CleanupRet:
2471 case Instruction::CatchSwitch:
2472 case Instruction::Resume:
Johannes Doerfertaccd3e82019-07-08 23:27:20 +00002473 case Instruction::Ret:
Stefan Stipanovic53605892019-06-27 11:27:54 +00002474 IsInterestingOpcode = true;
2475 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002476 if (IsInterestingOpcode)
2477 InstOpcodeMap[I.getOpcode()].push_back(&I);
2478 if (I.mayReadOrWriteMemory())
2479 ReadOrWriteInsts.push_back(&I);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002480
2481 CallSite CS(&I);
2482 if (CS && CS.getCalledFunction()) {
2483 for (int i = 0, e = CS.getCalledFunction()->arg_size(); i < e; i++) {
2484 if (!CS.getArgument(i)->getType()->isPointerTy())
2485 continue;
2486
2487 // Call site argument attribute "non-null".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002488 checkAndRegisterAA<AANonNullCallSiteArgument>(F, *this, Whitelist, I, i,
2489 i);
Hideto Ueno19c07af2019-07-23 08:16:17 +00002490
2491 // Call site argument attribute "dereferenceable".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002492 checkAndRegisterAA<AADereferenceableCallSiteArgument>(
2493 F, *this, Whitelist, I, i, i);
Hideto Uenoe7bea9b2019-07-28 07:04:01 +00002494
2495 // Call site argument attribute "align".
Johannes Doerfert21fe0a32019-08-06 00:55:11 +00002496 checkAndRegisterAA<AAAlignCallSiteArgument>(F, *this, Whitelist, I, i,
2497 i);
Hideto Ueno54869ec2019-07-15 06:49:04 +00002498 }
2499 }
Johannes Doerfertaade7822019-06-05 03:02:24 +00002500 }
2501}
2502
2503/// Helpers to ease debugging through output streams and print calls.
2504///
2505///{
2506raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
2507 return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
2508}
2509
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002510raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) {
Johannes Doerfertaade7822019-06-05 03:02:24 +00002511 switch (AP) {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002512 case IRPosition::IRP_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002513 return OS << "arg";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002514 case IRPosition::IRP_CALL_SITE_ARGUMENT:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002515 return OS << "cs_arg";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002516 case IRPosition::IRP_FUNCTION:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002517 return OS << "fn";
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002518 case IRPosition::IRP_RETURNED:
Johannes Doerfertaade7822019-06-05 03:02:24 +00002519 return OS << "fn_ret";
2520 }
2521 llvm_unreachable("Unknown attribute position!");
2522}
2523
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002524raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) {
2525 const Value *AV = Pos.getAssociatedValue();
2526 return OS << "{" << Pos.getPositionKind() << ":"
2527 << (AV ? AV->getName() : "n/a") << " ["
2528 << Pos.getAnchorValue().getName() << "@" << Pos.getArgNo() << "]}";
2529}
2530
Johannes Doerfertaade7822019-06-05 03:02:24 +00002531raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
2532 return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
2533}
2534
2535raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
2536 AA.print(OS);
2537 return OS;
2538}
2539
2540void AbstractAttribute::print(raw_ostream &OS) const {
Johannes Doerfertfb69f762019-08-05 23:32:31 +00002541 OS << "[P: " << getIRPosition() << "][" << getAsStr() << "][S: " << getState()
2542 << "]";
Johannes Doerfertaade7822019-06-05 03:02:24 +00002543}
2544///}
2545
2546/// ----------------------------------------------------------------------------
2547/// Pass (Manager) Boilerplate
2548/// ----------------------------------------------------------------------------
2549
2550static bool runAttributorOnModule(Module &M) {
2551 if (DisableAttributor)
2552 return false;
2553
2554 LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << M.size()
2555 << " functions.\n");
2556
2557 // Create an Attributor and initially empty information cache that is filled
2558 // while we identify default attribute opportunities.
2559 Attributor A;
2560 InformationCache InfoCache;
2561
2562 for (Function &F : M) {
2563 // TODO: Not all attributes require an exact definition. Find a way to
2564 // enable deduction for some but not all attributes in case the
2565 // definition might be changed at runtime, see also
2566 // http://lists.llvm.org/pipermail/llvm-dev/2018-February/121275.html.
2567 // TODO: We could always determine abstract attributes and if sufficient
2568 // information was found we could duplicate the functions that do not
2569 // have an exact definition.
2570 if (!F.hasExactDefinition()) {
2571 NumFnWithoutExactDefinition++;
2572 continue;
2573 }
2574
2575 // For now we ignore naked and optnone functions.
2576 if (F.hasFnAttribute(Attribute::Naked) ||
2577 F.hasFnAttribute(Attribute::OptimizeNone))
2578 continue;
2579
2580 NumFnWithExactDefinition++;
2581
2582 // Populate the Attributor with abstract attribute opportunities in the
2583 // function and the information cache with IR information.
2584 A.identifyDefaultAbstractAttributes(F, InfoCache);
2585 }
2586
Johannes Doerfert007153e2019-08-05 23:26:06 +00002587 return A.run(InfoCache) == ChangeStatus::CHANGED;
Johannes Doerfertaade7822019-06-05 03:02:24 +00002588}
2589
2590PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
2591 if (runAttributorOnModule(M)) {
2592 // FIXME: Think about passes we will preserve and add them here.
2593 return PreservedAnalyses::none();
2594 }
2595 return PreservedAnalyses::all();
2596}
2597
2598namespace {
2599
2600struct AttributorLegacyPass : public ModulePass {
2601 static char ID;
2602
2603 AttributorLegacyPass() : ModulePass(ID) {
2604 initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry());
2605 }
2606
2607 bool runOnModule(Module &M) override {
2608 if (skipModule(M))
2609 return false;
2610 return runAttributorOnModule(M);
2611 }
2612
2613 void getAnalysisUsage(AnalysisUsage &AU) const override {
2614 // FIXME: Think about passes we will preserve and add them here.
2615 AU.setPreservesCFG();
2616 }
2617};
2618
2619} // end anonymous namespace
2620
2621Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); }
2622
2623char AttributorLegacyPass::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002624
2625const char AAReturnedValues::ID = 0;
2626const char AANoUnwind::ID = 0;
2627const char AANoSync::ID = 0;
Johannes Doerferteccdf082019-08-05 23:35:12 +00002628const char AANoFree::ID = 0;
Johannes Doerfert24020622019-08-05 23:30:01 +00002629const char AANonNull::ID = 0;
2630const char AANoRecurse::ID = 0;
2631const char AAWillReturn::ID = 0;
2632const char AANoAlias::ID = 0;
2633const char AANoReturn::ID = 0;
2634const char AAIsDead::ID = 0;
2635const char AADereferenceable::ID = 0;
2636const char AAAlign::ID = 0;
2637
Johannes Doerfertaade7822019-06-05 03:02:24 +00002638INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor",
2639 "Deduce and propagate attributes", false, false)
2640INITIALIZE_PASS_END(AttributorLegacyPass, "attributor",
2641 "Deduce and propagate attributes", false, false)