| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 1 | //===- 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 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 16 | #include "llvm/Transforms/IPO/Attributor.h" | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 17 |  | 
| Hideto Ueno | 11d3710 | 2019-07-17 15:15:43 +0000 | [diff] [blame] | 18 | #include "llvm/ADT/DepthFirstIterator.h" | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 19 | #include "llvm/ADT/STLExtras.h" | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 20 | #include "llvm/ADT/SmallPtrSet.h" | 
|  | 21 | #include "llvm/ADT/SmallVector.h" | 
|  | 22 | #include "llvm/ADT/Statistic.h" | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 23 | #include "llvm/Analysis/CallGraph.h" | 
|  | 24 | #include "llvm/Analysis/CallGraphSCCPass.h" | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 25 | #include "llvm/Analysis/CaptureTracking.h" | 
| Johannes Doerfert | 924d213 | 2019-08-05 21:34:45 +0000 | [diff] [blame] | 26 | #include "llvm/Analysis/EHPersonalities.h" | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 27 | #include "llvm/Analysis/GlobalsModRef.h" | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 28 | #include "llvm/Analysis/LazyValueInfo.h" | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 29 | #include "llvm/Analysis/Loads.h" | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 30 | #include "llvm/Analysis/MemoryBuiltins.h" | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 31 | #include "llvm/Analysis/ScalarEvolution.h" | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 32 | #include "llvm/Analysis/ValueTracking.h" | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 33 | #include "llvm/IR/Argument.h" | 
|  | 34 | #include "llvm/IR/Attributes.h" | 
| Hideto Ueno | 11d3710 | 2019-07-17 15:15:43 +0000 | [diff] [blame] | 35 | #include "llvm/IR/CFG.h" | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 36 | #include "llvm/IR/IRBuilder.h" | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 37 | #include "llvm/IR/InstIterator.h" | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 38 | #include "llvm/IR/IntrinsicInst.h" | 
| Johannes Doerfert | a4088c7 | 2020-01-07 16:01:57 -0600 | [diff] [blame] | 39 | #include "llvm/IR/Verifier.h" | 
| Reid Kleckner | 05da2fe | 2019-11-13 13:15:01 -0800 | [diff] [blame] | 40 | #include "llvm/InitializePasses.h" | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 41 | #include "llvm/IR/NoFolder.h" | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 42 | #include "llvm/Support/CommandLine.h" | 
|  | 43 | #include "llvm/Support/Debug.h" | 
|  | 44 | #include "llvm/Support/raw_ostream.h" | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 45 | #include "llvm/Transforms/IPO/ArgumentPromotion.h" | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 46 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" | 
|  | 47 | #include "llvm/Transforms/Utils/Local.h" | 
|  | 48 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 49 | #include <cassert> | 
|  | 50 |  | 
|  | 51 | using namespace llvm; | 
|  | 52 |  | 
|  | 53 | #define DEBUG_TYPE "attributor" | 
|  | 54 |  | 
|  | 55 | STATISTIC(NumFnWithExactDefinition, | 
|  | 56 | "Number of function with exact definitions"); | 
|  | 57 | STATISTIC(NumFnWithoutExactDefinition, | 
|  | 58 | "Number of function without exact definitions"); | 
|  | 59 | STATISTIC(NumAttributesTimedOut, | 
|  | 60 | "Number of abstract attributes timed out before fixpoint"); | 
|  | 61 | STATISTIC(NumAttributesValidFixpoint, | 
|  | 62 | "Number of abstract attributes in a valid fixpoint state"); | 
|  | 63 | STATISTIC(NumAttributesManifested, | 
|  | 64 | "Number of abstract attributes manifested in IR"); | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 65 | STATISTIC(NumAttributesFixedDueToRequiredDependences, | 
|  | 66 | "Number of abstract attributes fixed due to required dependences"); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 67 |  | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 68 | // Some helper macros to deal with statistics tracking. | 
|  | 69 | // | 
|  | 70 | // Usage: | 
|  | 71 | // For simple IR attribute tracking overload trackStatistics in the abstract | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 72 | // attribute and choose the right STATS_DECLTRACK_********* macro, | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 73 | // e.g.,: | 
|  | 74 | //  void trackStatistics() const override { | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 75 | //    STATS_DECLTRACK_ARG_ATTR(returned) | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 76 | //  } | 
|  | 77 | // If there is a single "increment" side one can use the macro | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 78 | // STATS_DECLTRACK with a custom message. If there are multiple increment | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 79 | // sides, STATS_DECL and STATS_TRACK can also be used separatly. | 
|  | 80 | // | 
|  | 81 | #define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME)                                     \ | 
|  | 82 | ("Number of " #TYPE " marked '" #NAME "'") | 
|  | 83 | #define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME | 
| Johannes Doerfert | a7a3b3a | 2019-09-04 19:01:08 +0000 | [diff] [blame] | 84 | #define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG); | 
|  | 85 | #define STATS_DECL(NAME, TYPE, MSG)                                            \ | 
|  | 86 | STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG); | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 87 | #define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE)); | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 88 | #define STATS_DECLTRACK(NAME, TYPE, MSG)                                       \ | 
| Johannes Doerfert | 169af99 | 2019-08-20 06:09:56 +0000 | [diff] [blame] | 89 | {                                                                            \ | 
|  | 90 | STATS_DECL(NAME, TYPE, MSG)                                                \ | 
|  | 91 | STATS_TRACK(NAME, TYPE)                                                    \ | 
|  | 92 | } | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 93 | #define STATS_DECLTRACK_ARG_ATTR(NAME)                                         \ | 
|  | 94 | STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME)) | 
|  | 95 | #define STATS_DECLTRACK_CSARG_ATTR(NAME)                                       \ | 
|  | 96 | STATS_DECLTRACK(NAME, CSArguments,                                           \ | 
|  | 97 | BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME)) | 
|  | 98 | #define STATS_DECLTRACK_FN_ATTR(NAME)                                          \ | 
|  | 99 | STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME)) | 
|  | 100 | #define STATS_DECLTRACK_CS_ATTR(NAME)                                          \ | 
|  | 101 | STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME)) | 
|  | 102 | #define STATS_DECLTRACK_FNRET_ATTR(NAME)                                       \ | 
|  | 103 | STATS_DECLTRACK(NAME, FunctionReturn,                                        \ | 
| Johannes Doerfert | 2db8528 | 2019-08-21 20:56:56 +0000 | [diff] [blame] | 104 | BUILD_STAT_MSG_IR_ATTR(function returns, NAME)) | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 105 | #define STATS_DECLTRACK_CSRET_ATTR(NAME)                                       \ | 
|  | 106 | STATS_DECLTRACK(NAME, CSReturn,                                              \ | 
|  | 107 | BUILD_STAT_MSG_IR_ATTR(call site returns, NAME)) | 
|  | 108 | #define STATS_DECLTRACK_FLOATING_ATTR(NAME)                                    \ | 
|  | 109 | STATS_DECLTRACK(NAME, Floating,                                              \ | 
|  | 110 | ("Number of floating values known to be '" #NAME "'")) | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 111 |  | 
| Johannes Doerfert | 3d347e2 | 2019-12-13 23:35:45 -0600 | [diff] [blame] | 112 | // Specialization of the operator<< for abstract attributes subclasses. This | 
|  | 113 | // disambiguates situations where multiple operators are applicable. | 
|  | 114 | namespace llvm { | 
|  | 115 | #define PIPE_OPERATOR(CLASS)                                                   \ | 
|  | 116 | raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) {                  \ | 
|  | 117 | return OS << static_cast<const AbstractAttribute &>(AA);                   \ | 
|  | 118 | } | 
|  | 119 |  | 
|  | 120 | PIPE_OPERATOR(AAIsDead) | 
|  | 121 | PIPE_OPERATOR(AANoUnwind) | 
|  | 122 | PIPE_OPERATOR(AANoSync) | 
|  | 123 | PIPE_OPERATOR(AANoRecurse) | 
|  | 124 | PIPE_OPERATOR(AAWillReturn) | 
|  | 125 | PIPE_OPERATOR(AANoReturn) | 
|  | 126 | PIPE_OPERATOR(AAReturnedValues) | 
|  | 127 | PIPE_OPERATOR(AANonNull) | 
|  | 128 | PIPE_OPERATOR(AANoAlias) | 
|  | 129 | PIPE_OPERATOR(AADereferenceable) | 
|  | 130 | PIPE_OPERATOR(AAAlign) | 
|  | 131 | PIPE_OPERATOR(AANoCapture) | 
|  | 132 | PIPE_OPERATOR(AAValueSimplify) | 
|  | 133 | PIPE_OPERATOR(AANoFree) | 
|  | 134 | PIPE_OPERATOR(AAHeapToStack) | 
|  | 135 | PIPE_OPERATOR(AAReachability) | 
|  | 136 | PIPE_OPERATOR(AAMemoryBehavior) | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 137 | PIPE_OPERATOR(AAValueConstantRange) | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 138 | PIPE_OPERATOR(AAPrivatizablePtr) | 
| Johannes Doerfert | 3d347e2 | 2019-12-13 23:35:45 -0600 | [diff] [blame] | 139 |  | 
|  | 140 | #undef PIPE_OPERATOR | 
|  | 141 | } // namespace llvm | 
|  | 142 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 143 | // TODO: Determine a good default value. | 
|  | 144 | // | 
|  | 145 | // In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads | 
|  | 146 | // (when run with the first 5 abstract attributes). The results also indicate | 
|  | 147 | // that we never reach 32 iterations but always find a fixpoint sooner. | 
|  | 148 | // | 
|  | 149 | // This will become more evolved once we perform two interleaved fixpoint | 
|  | 150 | // iterations: bottom-up and top-down. | 
|  | 151 | static cl::opt<unsigned> | 
|  | 152 | MaxFixpointIterations("attributor-max-iterations", cl::Hidden, | 
|  | 153 | cl::desc("Maximal number of fixpoint iterations."), | 
|  | 154 | cl::init(32)); | 
| Johannes Doerfert | b504eb8 | 2019-08-26 18:55:47 +0000 | [diff] [blame] | 155 | static cl::opt<bool> VerifyMaxFixpointIterations( | 
|  | 156 | "attributor-max-iterations-verify", cl::Hidden, | 
|  | 157 | cl::desc("Verify that max-iterations is a tight bound for a fixpoint"), | 
|  | 158 | cl::init(false)); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 159 |  | 
|  | 160 | static cl::opt<bool> DisableAttributor( | 
|  | 161 | "attributor-disable", cl::Hidden, | 
|  | 162 | cl::desc("Disable the attributor inter-procedural deduction pass."), | 
| Johannes Doerfert | 282d34e | 2019-06-14 14:53:41 +0000 | [diff] [blame] | 163 | cl::init(true)); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 164 |  | 
| Johannes Doerfert | c36e2eb | 2019-10-31 20:15:02 -0500 | [diff] [blame] | 165 | static cl::opt<bool> AnnotateDeclarationCallSites( | 
|  | 166 | "attributor-annotate-decl-cs", cl::Hidden, | 
| James Henderson | d68904f | 2020-01-06 10:15:44 +0000 | [diff] [blame] | 167 | cl::desc("Annotate call sites of function declarations."), cl::init(false)); | 
| Johannes Doerfert | c36e2eb | 2019-10-31 20:15:02 -0500 | [diff] [blame] | 168 |  | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 169 | static cl::opt<bool> ManifestInternal( | 
|  | 170 | "attributor-manifest-internal", cl::Hidden, | 
|  | 171 | cl::desc("Manifest Attributor internal string attributes."), | 
|  | 172 | cl::init(false)); | 
|  | 173 |  | 
| Johannes Doerfert | f7ca0fe | 2019-08-28 16:58:52 +0000 | [diff] [blame] | 174 | static cl::opt<unsigned> DepRecInterval( | 
|  | 175 | "attributor-dependence-recompute-interval", cl::Hidden, | 
|  | 176 | cl::desc("Number of iterations until dependences are recomputed."), | 
|  | 177 | cl::init(4)); | 
|  | 178 |  | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 179 | static cl::opt<bool> EnableHeapToStack("enable-heap-to-stack-conversion", | 
|  | 180 | cl::init(true), cl::Hidden); | 
|  | 181 |  | 
| Johannes Doerfert | 1c2afae | 2019-10-10 05:34:21 +0000 | [diff] [blame] | 182 | static cl::opt<int> MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128), | 
|  | 183 | cl::Hidden); | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 184 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 185 | /// Logic operators for the change status enum class. | 
|  | 186 | /// | 
|  | 187 | ///{ | 
|  | 188 | ChangeStatus llvm::operator|(ChangeStatus l, ChangeStatus r) { | 
|  | 189 | return l == ChangeStatus::CHANGED ? l : r; | 
|  | 190 | } | 
|  | 191 | ChangeStatus llvm::operator&(ChangeStatus l, ChangeStatus r) { | 
|  | 192 | return l == ChangeStatus::UNCHANGED ? l : r; | 
|  | 193 | } | 
|  | 194 | ///} | 
|  | 195 |  | 
| Johannes Doerfert | b1b441d | 2019-10-10 01:19:57 -0500 | [diff] [blame] | 196 | Argument *IRPosition::getAssociatedArgument() const { | 
|  | 197 | if (getPositionKind() == IRP_ARGUMENT) | 
|  | 198 | return cast<Argument>(&getAnchorValue()); | 
|  | 199 |  | 
|  | 200 | // Not an Argument and no argument number means this is not a call site | 
|  | 201 | // argument, thus we cannot find a callback argument to return. | 
|  | 202 | int ArgNo = getArgNo(); | 
|  | 203 | if (ArgNo < 0) | 
|  | 204 | return nullptr; | 
|  | 205 |  | 
|  | 206 | // Use abstract call sites to make the connection between the call site | 
|  | 207 | // values and the ones in callbacks. If a callback was found that makes use | 
|  | 208 | // of the underlying call site operand, we want the corresponding callback | 
|  | 209 | // callee argument and not the direct callee argument. | 
|  | 210 | Optional<Argument *> CBCandidateArg; | 
|  | 211 | SmallVector<const Use *, 4> CBUses; | 
|  | 212 | ImmutableCallSite ICS(&getAnchorValue()); | 
|  | 213 | AbstractCallSite::getCallbackUses(ICS, CBUses); | 
|  | 214 | for (const Use *U : CBUses) { | 
|  | 215 | AbstractCallSite ACS(U); | 
|  | 216 | assert(ACS && ACS.isCallbackCall()); | 
|  | 217 | if (!ACS.getCalledFunction()) | 
|  | 218 | continue; | 
|  | 219 |  | 
|  | 220 | for (unsigned u = 0, e = ACS.getNumArgOperands(); u < e; u++) { | 
|  | 221 |  | 
|  | 222 | // Test if the underlying call site operand is argument number u of the | 
|  | 223 | // callback callee. | 
|  | 224 | if (ACS.getCallArgOperandNo(u) != ArgNo) | 
|  | 225 | continue; | 
|  | 226 |  | 
|  | 227 | assert(ACS.getCalledFunction()->arg_size() > u && | 
|  | 228 | "ACS mapped into var-args arguments!"); | 
|  | 229 | if (CBCandidateArg.hasValue()) { | 
|  | 230 | CBCandidateArg = nullptr; | 
|  | 231 | break; | 
|  | 232 | } | 
|  | 233 | CBCandidateArg = ACS.getCalledFunction()->getArg(u); | 
|  | 234 | } | 
|  | 235 | } | 
|  | 236 |  | 
|  | 237 | // If we found a unique callback candidate argument, return it. | 
|  | 238 | if (CBCandidateArg.hasValue() && CBCandidateArg.getValue()) | 
|  | 239 | return CBCandidateArg.getValue(); | 
|  | 240 |  | 
|  | 241 | // If no callbacks were found, or none used the underlying call site operand | 
|  | 242 | // exclusively, use the direct callee argument if available. | 
|  | 243 | const Function *Callee = ICS.getCalledFunction(); | 
|  | 244 | if (Callee && Callee->arg_size() > unsigned(ArgNo)) | 
|  | 245 | return Callee->getArg(ArgNo); | 
|  | 246 |  | 
|  | 247 | return nullptr; | 
|  | 248 | } | 
|  | 249 |  | 
| Johannes Doerfert | 214ed3f | 2020-01-11 23:35:45 -0600 | [diff] [blame] | 250 | static Optional<ConstantInt *> | 
|  | 251 | getAssumedConstant(Attributor &A, const Value &V, const AbstractAttribute &AA, | 
|  | 252 | bool &UsedAssumedInformation) { | 
|  | 253 | const auto &ValueSimplifyAA = A.getAAFor<AAValueSimplify>( | 
|  | 254 | AA, IRPosition::value(V), /* TrackDependence */ false); | 
|  | 255 | Optional<Value *> SimplifiedV = ValueSimplifyAA.getAssumedSimplifiedValue(A); | 
|  | 256 | bool IsKnown = ValueSimplifyAA.isKnown(); | 
|  | 257 | UsedAssumedInformation |= !IsKnown; | 
|  | 258 | if (!SimplifiedV.hasValue()) { | 
|  | 259 | A.recordDependence(ValueSimplifyAA, AA, DepClassTy::OPTIONAL); | 
|  | 260 | return llvm::None; | 
|  | 261 | } | 
|  | 262 | if (isa_and_nonnull<UndefValue>(SimplifiedV.getValue())) { | 
|  | 263 | A.recordDependence(ValueSimplifyAA, AA, DepClassTy::OPTIONAL); | 
|  | 264 | return llvm::None; | 
|  | 265 | } | 
|  | 266 | ConstantInt *CI = dyn_cast_or_null<ConstantInt>(SimplifiedV.getValue()); | 
|  | 267 | if (CI) | 
|  | 268 | A.recordDependence(ValueSimplifyAA, AA, DepClassTy::OPTIONAL); | 
|  | 269 | return CI; | 
|  | 270 | } | 
|  | 271 |  | 
| Johannes Doerfert | b6dbd0f | 2020-01-26 02:49:58 -0600 | [diff] [blame] | 272 | /// Get pointer operand of memory accessing instruction. If \p I is | 
|  | 273 | /// not a memory accessing instruction, return nullptr. If \p AllowVolatile, | 
|  | 274 | /// is set to false and the instruction is volatile, return nullptr. | 
|  | 275 | static const Value *getPointerOperand(const Instruction *I, | 
|  | 276 | bool AllowVolatile) { | 
|  | 277 | if (auto *LI = dyn_cast<LoadInst>(I)) { | 
|  | 278 | if (!AllowVolatile && LI->isVolatile()) | 
|  | 279 | return nullptr; | 
|  | 280 | return LI->getPointerOperand(); | 
|  | 281 | } | 
|  | 282 |  | 
|  | 283 | if (auto *SI = dyn_cast<StoreInst>(I)) { | 
|  | 284 | if (!AllowVolatile && SI->isVolatile()) | 
|  | 285 | return nullptr; | 
|  | 286 | return SI->getPointerOperand(); | 
|  | 287 | } | 
|  | 288 |  | 
|  | 289 | if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(I)) { | 
|  | 290 | if (!AllowVolatile && CXI->isVolatile()) | 
|  | 291 | return nullptr; | 
|  | 292 | return CXI->getPointerOperand(); | 
|  | 293 | } | 
|  | 294 |  | 
|  | 295 | if (auto *RMWI = dyn_cast<AtomicRMWInst>(I)) { | 
|  | 296 | if (!AllowVolatile && RMWI->isVolatile()) | 
|  | 297 | return nullptr; | 
|  | 298 | return RMWI->getPointerOperand(); | 
|  | 299 | } | 
|  | 300 |  | 
|  | 301 | return nullptr; | 
|  | 302 | } | 
|  | 303 |  | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 304 | /// Helper function to create a pointer of type \p ResTy, based on \p Ptr, and | 
|  | 305 | /// advanced by \p Offset bytes. To aid later analysis the method tries to build | 
|  | 306 | /// getelement pointer instructions that traverse the natural type of \p Ptr if | 
|  | 307 | /// possible. If that fails, the remaining offset is adjusted byte-wise, hence | 
|  | 308 | /// through a cast to i8*. | 
|  | 309 | /// | 
|  | 310 | /// TODO: This could probably live somewhere more prominantly if it doesn't | 
|  | 311 | ///       already exist. | 
|  | 312 | static Value *constructPointer(Type *ResTy, Value *Ptr, int64_t Offset, | 
|  | 313 | IRBuilder<NoFolder> &IRB, const DataLayout &DL) { | 
|  | 314 | assert(Offset >= 0 && "Negative offset not supported yet!"); | 
|  | 315 | LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offset | 
|  | 316 | << "-bytes as " << *ResTy << "\n"); | 
|  | 317 |  | 
|  | 318 | // The initial type we are trying to traverse to get nice GEPs. | 
|  | 319 | Type *Ty = Ptr->getType(); | 
|  | 320 |  | 
|  | 321 | SmallVector<Value *, 4> Indices; | 
|  | 322 | std::string GEPName = Ptr->getName().str(); | 
|  | 323 | while (Offset) { | 
|  | 324 | uint64_t Idx, Rem; | 
|  | 325 |  | 
|  | 326 | if (auto *STy = dyn_cast<StructType>(Ty)) { | 
|  | 327 | const StructLayout *SL = DL.getStructLayout(STy); | 
|  | 328 | if (int64_t(SL->getSizeInBytes()) < Offset) | 
|  | 329 | break; | 
|  | 330 | Idx = SL->getElementContainingOffset(Offset); | 
|  | 331 | assert(Idx < STy->getNumElements() && "Offset calculation error!"); | 
|  | 332 | Rem = Offset - SL->getElementOffset(Idx); | 
|  | 333 | Ty = STy->getElementType(Idx); | 
|  | 334 | } else if (auto *PTy = dyn_cast<PointerType>(Ty)) { | 
|  | 335 | Ty = PTy->getElementType(); | 
|  | 336 | if (!Ty->isSized()) | 
|  | 337 | break; | 
|  | 338 | uint64_t ElementSize = DL.getTypeAllocSize(Ty); | 
|  | 339 | assert(ElementSize && "Expected type with size!"); | 
|  | 340 | Idx = Offset / ElementSize; | 
|  | 341 | Rem = Offset % ElementSize; | 
|  | 342 | } else { | 
|  | 343 | // Non-aggregate type, we cast and make byte-wise progress now. | 
|  | 344 | break; | 
|  | 345 | } | 
|  | 346 |  | 
|  | 347 | LLVM_DEBUG(errs() << "Ty: " << *Ty << " Offset: " << Offset | 
|  | 348 | << " Idx: " << Idx << " Rem: " << Rem << "\n"); | 
|  | 349 |  | 
|  | 350 | GEPName += "." + std::to_string(Idx); | 
|  | 351 | Indices.push_back(ConstantInt::get(IRB.getInt32Ty(), Idx)); | 
|  | 352 | Offset = Rem; | 
|  | 353 | } | 
|  | 354 |  | 
|  | 355 | // Create a GEP if we collected indices above. | 
|  | 356 | if (Indices.size()) | 
|  | 357 | Ptr = IRB.CreateGEP(Ptr, Indices, GEPName); | 
|  | 358 |  | 
|  | 359 | // If an offset is left we use byte-wise adjustment. | 
|  | 360 | if (Offset) { | 
|  | 361 | Ptr = IRB.CreateBitCast(Ptr, IRB.getInt8PtrTy()); | 
|  | 362 | Ptr = IRB.CreateGEP(Ptr, IRB.getInt32(Offset), | 
|  | 363 | GEPName + ".b" + Twine(Offset)); | 
|  | 364 | } | 
|  | 365 |  | 
|  | 366 | // Ensure the result has the requested type. | 
|  | 367 | Ptr = IRB.CreateBitOrPointerCast(Ptr, ResTy, Ptr->getName() + ".cast"); | 
|  | 368 |  | 
|  | 369 | LLVM_DEBUG(dbgs() << "Constructed pointer: " << *Ptr << "\n"); | 
|  | 370 | return Ptr; | 
|  | 371 | } | 
|  | 372 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 373 | /// Recursively visit all values that might become \p IRP at some point. This | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 374 | /// will be done by looking through cast instructions, selects, phis, and calls | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 375 | /// with the "returned" attribute. Once we cannot look through the value any | 
|  | 376 | /// further, the callback \p VisitValueCB is invoked and passed the current | 
| Johannes Doerfert | 52aec32 | 2020-02-11 15:11:32 -0600 | [diff] [blame] | 377 | /// value, the \p State, and a flag to indicate if we stripped anything. | 
|  | 378 | /// Stripped means that we unpacked the value associated with \p IRP at least | 
|  | 379 | /// once. Note that the value used for the callback may still be the value | 
|  | 380 | /// associated with \p IRP (due to PHIs). To limit how much effort is invested, | 
|  | 381 | /// we will never visit more values than specified by \p MaxValues. | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 382 | template <typename AAType, typename StateTy> | 
| Benjamin Kramer | df4b9a3 | 2019-09-17 12:56:29 +0000 | [diff] [blame] | 383 | static bool genericValueTraversal( | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 384 | Attributor &A, IRPosition IRP, const AAType &QueryingAA, StateTy &State, | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 385 | const function_ref<bool(Value &, StateTy &, bool)> &VisitValueCB, | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 386 | int MaxValues = 8) { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 387 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 388 | const AAIsDead *LivenessAA = nullptr; | 
|  | 389 | if (IRP.getAnchorScope()) | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 390 | LivenessAA = &A.getAAFor<AAIsDead>( | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 391 | QueryingAA, IRPosition::function(*IRP.getAnchorScope()), | 
|  | 392 | /* TrackDependence */ false); | 
|  | 393 | bool AnyDead = false; | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 394 |  | 
|  | 395 | // TODO: Use Positions here to allow context sensitivity in VisitValueCB | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 396 | SmallPtrSet<Value *, 16> Visited; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 397 | SmallVector<Value *, 16> Worklist; | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 398 | Worklist.push_back(&IRP.getAssociatedValue()); | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 399 |  | 
|  | 400 | int Iteration = 0; | 
|  | 401 | do { | 
|  | 402 | Value *V = Worklist.pop_back_val(); | 
|  | 403 |  | 
|  | 404 | // Check if we should process the current value. To prevent endless | 
|  | 405 | // recursion keep a record of the values we followed! | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 406 | if (!Visited.insert(V).second) | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 407 | continue; | 
|  | 408 |  | 
|  | 409 | // Make sure we limit the compile time for complex expressions. | 
|  | 410 | if (Iteration++ >= MaxValues) | 
|  | 411 | return false; | 
|  | 412 |  | 
|  | 413 | // Explicitly look through calls with a "returned" attribute if we do | 
|  | 414 | // not have a pointer as stripPointerCasts only works on them. | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 415 | Value *NewV = nullptr; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 416 | if (V->getType()->isPointerTy()) { | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 417 | NewV = V->stripPointerCasts(); | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 418 | } else { | 
|  | 419 | CallSite CS(V); | 
|  | 420 | if (CS && CS.getCalledFunction()) { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 421 | for (Argument &Arg : CS.getCalledFunction()->args()) | 
|  | 422 | if (Arg.hasReturnedAttr()) { | 
|  | 423 | NewV = CS.getArgOperand(Arg.getArgNo()); | 
|  | 424 | break; | 
|  | 425 | } | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 426 | } | 
|  | 427 | } | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 428 | if (NewV && NewV != V) { | 
|  | 429 | Worklist.push_back(NewV); | 
|  | 430 | continue; | 
|  | 431 | } | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 432 |  | 
|  | 433 | // Look through select instructions, visit both potential values. | 
|  | 434 | if (auto *SI = dyn_cast<SelectInst>(V)) { | 
|  | 435 | Worklist.push_back(SI->getTrueValue()); | 
|  | 436 | Worklist.push_back(SI->getFalseValue()); | 
|  | 437 | continue; | 
|  | 438 | } | 
|  | 439 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 440 | // Look through phi nodes, visit all live operands. | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 441 | if (auto *PHI = dyn_cast<PHINode>(V)) { | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 442 | assert(LivenessAA && | 
|  | 443 | "Expected liveness in the presence of instructions!"); | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 444 | for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) { | 
|  | 445 | const BasicBlock *IncomingBB = PHI->getIncomingBlock(u); | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 446 | if (LivenessAA->isAssumedDead(IncomingBB->getTerminator())) { | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 447 | AnyDead = true; | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 448 | continue; | 
|  | 449 | } | 
|  | 450 | Worklist.push_back(PHI->getIncomingValue(u)); | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 451 | } | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 452 | continue; | 
|  | 453 | } | 
|  | 454 |  | 
|  | 455 | // Once a leaf is reached we inform the user through the callback. | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 456 | if (!VisitValueCB(*V, State, Iteration > 1)) | 
|  | 457 | return false; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 458 | } while (!Worklist.empty()); | 
|  | 459 |  | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 460 | // If we actually used liveness information so we have to record a dependence. | 
|  | 461 | if (AnyDead) | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 462 | A.recordDependence(*LivenessAA, QueryingAA, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 463 |  | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 464 | // All values have been visited. | 
|  | 465 | return true; | 
|  | 466 | } | 
|  | 467 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 468 | /// Return true if \p New is equal or worse than \p Old. | 
|  | 469 | static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) { | 
|  | 470 | if (!Old.isIntAttribute()) | 
|  | 471 | return true; | 
|  | 472 |  | 
|  | 473 | return Old.getValueAsInt() >= New.getValueAsInt(); | 
|  | 474 | } | 
|  | 475 |  | 
|  | 476 | /// Return true if the information provided by \p Attr was added to the | 
|  | 477 | /// attribute list \p Attrs. This is only the case if it was not already present | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 478 | /// in \p Attrs at the position describe by \p PK and \p AttrIdx. | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 479 | static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr, | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 480 | AttributeList &Attrs, int AttrIdx) { | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 481 |  | 
|  | 482 | if (Attr.isEnumAttribute()) { | 
|  | 483 | Attribute::AttrKind Kind = Attr.getKindAsEnum(); | 
|  | 484 | if (Attrs.hasAttribute(AttrIdx, Kind)) | 
|  | 485 | if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind))) | 
|  | 486 | return false; | 
|  | 487 | Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr); | 
|  | 488 | return true; | 
|  | 489 | } | 
|  | 490 | if (Attr.isStringAttribute()) { | 
|  | 491 | StringRef Kind = Attr.getKindAsString(); | 
|  | 492 | if (Attrs.hasAttribute(AttrIdx, Kind)) | 
|  | 493 | if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind))) | 
|  | 494 | return false; | 
|  | 495 | Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr); | 
|  | 496 | return true; | 
|  | 497 | } | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 498 | if (Attr.isIntAttribute()) { | 
|  | 499 | Attribute::AttrKind Kind = Attr.getKindAsEnum(); | 
|  | 500 | if (Attrs.hasAttribute(AttrIdx, Kind)) | 
|  | 501 | if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind))) | 
|  | 502 | return false; | 
|  | 503 | Attrs = Attrs.removeAttribute(Ctx, AttrIdx, Kind); | 
|  | 504 | Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr); | 
|  | 505 | return true; | 
|  | 506 | } | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 507 |  | 
|  | 508 | llvm_unreachable("Expected enum or string attribute!"); | 
|  | 509 | } | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 510 |  | 
| Hideto Ueno | 0f4383f | 2019-11-27 14:41:12 +0000 | [diff] [blame] | 511 | static const Value * | 
|  | 512 | getBasePointerOfAccessPointerOperand(const Instruction *I, int64_t &BytesOffset, | 
|  | 513 | const DataLayout &DL, | 
|  | 514 | bool AllowNonInbounds = false) { | 
| Johannes Doerfert | b6dbd0f | 2020-01-26 02:49:58 -0600 | [diff] [blame] | 515 | const Value *Ptr = getPointerOperand(I, /* AllowVolatile */ false); | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 516 | if (!Ptr) | 
|  | 517 | return nullptr; | 
|  | 518 |  | 
|  | 519 | return GetPointerBaseWithConstantOffset(Ptr, BytesOffset, DL, | 
| Hideto Ueno | 0f4383f | 2019-11-27 14:41:12 +0000 | [diff] [blame] | 520 | AllowNonInbounds); | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 521 | } | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 522 |  | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 523 | ChangeStatus AbstractAttribute::update(Attributor &A) { | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 524 | ChangeStatus HasChanged = ChangeStatus::UNCHANGED; | 
|  | 525 | if (getState().isAtFixpoint()) | 
|  | 526 | return HasChanged; | 
|  | 527 |  | 
|  | 528 | LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n"); | 
|  | 529 |  | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 530 | HasChanged = updateImpl(A); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 531 |  | 
|  | 532 | LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this | 
|  | 533 | << "\n"); | 
|  | 534 |  | 
|  | 535 | return HasChanged; | 
|  | 536 | } | 
|  | 537 |  | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 538 | ChangeStatus | 
| Johannes Doerfert | b2083c5 | 2019-10-20 22:46:48 -0500 | [diff] [blame] | 539 | IRAttributeManifest::manifestAttrs(Attributor &A, const IRPosition &IRP, | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 540 | const ArrayRef<Attribute> &DeducedAttrs) { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 541 | Function *ScopeFn = IRP.getAssociatedFunction(); | 
| Kristina Brooks | 26e60f0 | 2019-08-06 19:53:19 +0000 | [diff] [blame] | 542 | IRPosition::Kind PK = IRP.getPositionKind(); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 543 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 544 | // In the following some generic code that will manifest attributes in | 
|  | 545 | // DeducedAttrs if they improve the current IR. Due to the different | 
|  | 546 | // annotation positions we use the underlying AttributeList interface. | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 547 |  | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 548 | AttributeList Attrs; | 
|  | 549 | switch (PK) { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 550 | case IRPosition::IRP_INVALID: | 
|  | 551 | case IRPosition::IRP_FLOAT: | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 552 | return ChangeStatus::UNCHANGED; | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 553 | case IRPosition::IRP_ARGUMENT: | 
|  | 554 | case IRPosition::IRP_FUNCTION: | 
|  | 555 | case IRPosition::IRP_RETURNED: | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 556 | Attrs = ScopeFn->getAttributes(); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 557 | break; | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 558 | case IRPosition::IRP_CALL_SITE: | 
|  | 559 | case IRPosition::IRP_CALL_SITE_RETURNED: | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 560 | case IRPosition::IRP_CALL_SITE_ARGUMENT: | 
| Kristina Brooks | 26e60f0 | 2019-08-06 19:53:19 +0000 | [diff] [blame] | 561 | Attrs = ImmutableCallSite(&IRP.getAnchorValue()).getAttributes(); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 562 | break; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 563 | } | 
|  | 564 |  | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 565 | ChangeStatus HasChanged = ChangeStatus::UNCHANGED; | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 566 | LLVMContext &Ctx = IRP.getAnchorValue().getContext(); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 567 | for (const Attribute &Attr : DeducedAttrs) { | 
| Kristina Brooks | 26e60f0 | 2019-08-06 19:53:19 +0000 | [diff] [blame] | 568 | if (!addIfNotExistent(Ctx, Attr, Attrs, IRP.getAttrIdx())) | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 569 | continue; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 570 |  | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 571 | HasChanged = ChangeStatus::CHANGED; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 572 | } | 
|  | 573 |  | 
|  | 574 | if (HasChanged == ChangeStatus::UNCHANGED) | 
|  | 575 | return HasChanged; | 
|  | 576 |  | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 577 | switch (PK) { | 
|  | 578 | case IRPosition::IRP_ARGUMENT: | 
|  | 579 | case IRPosition::IRP_FUNCTION: | 
|  | 580 | case IRPosition::IRP_RETURNED: | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 581 | ScopeFn->setAttributes(Attrs); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 582 | break; | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 583 | case IRPosition::IRP_CALL_SITE: | 
|  | 584 | case IRPosition::IRP_CALL_SITE_RETURNED: | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 585 | case IRPosition::IRP_CALL_SITE_ARGUMENT: | 
| Kristina Brooks | 26e60f0 | 2019-08-06 19:53:19 +0000 | [diff] [blame] | 586 | CallSite(&IRP.getAnchorValue()).setAttributes(Attrs); | 
| Johannes Doerfert | 4395b31 | 2019-08-14 21:46:28 +0000 | [diff] [blame] | 587 | break; | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 588 | case IRPosition::IRP_INVALID: | 
| Johannes Doerfert | 4395b31 | 2019-08-14 21:46:28 +0000 | [diff] [blame] | 589 | case IRPosition::IRP_FLOAT: | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 590 | break; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 591 | } | 
|  | 592 |  | 
|  | 593 | return HasChanged; | 
|  | 594 | } | 
|  | 595 |  | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 596 | const IRPosition IRPosition::EmptyKey(255); | 
|  | 597 | const IRPosition IRPosition::TombstoneKey(256); | 
|  | 598 |  | 
|  | 599 | SubsumingPositionIterator::SubsumingPositionIterator(const IRPosition &IRP) { | 
|  | 600 | IRPositions.emplace_back(IRP); | 
|  | 601 |  | 
|  | 602 | ImmutableCallSite ICS(&IRP.getAnchorValue()); | 
|  | 603 | switch (IRP.getPositionKind()) { | 
|  | 604 | case IRPosition::IRP_INVALID: | 
|  | 605 | case IRPosition::IRP_FLOAT: | 
|  | 606 | case IRPosition::IRP_FUNCTION: | 
|  | 607 | return; | 
|  | 608 | case IRPosition::IRP_ARGUMENT: | 
|  | 609 | case IRPosition::IRP_RETURNED: | 
|  | 610 | IRPositions.emplace_back( | 
|  | 611 | IRPosition::function(*IRP.getAssociatedFunction())); | 
|  | 612 | return; | 
|  | 613 | case IRPosition::IRP_CALL_SITE: | 
|  | 614 | assert(ICS && "Expected call site!"); | 
|  | 615 | // TODO: We need to look at the operand bundles similar to the redirection | 
|  | 616 | //       in CallBase. | 
|  | 617 | if (!ICS.hasOperandBundles()) | 
|  | 618 | if (const Function *Callee = ICS.getCalledFunction()) | 
|  | 619 | IRPositions.emplace_back(IRPosition::function(*Callee)); | 
|  | 620 | return; | 
|  | 621 | case IRPosition::IRP_CALL_SITE_RETURNED: | 
|  | 622 | assert(ICS && "Expected call site!"); | 
|  | 623 | // TODO: We need to look at the operand bundles similar to the redirection | 
|  | 624 | //       in CallBase. | 
|  | 625 | if (!ICS.hasOperandBundles()) { | 
|  | 626 | if (const Function *Callee = ICS.getCalledFunction()) { | 
|  | 627 | IRPositions.emplace_back(IRPosition::returned(*Callee)); | 
|  | 628 | IRPositions.emplace_back(IRPosition::function(*Callee)); | 
|  | 629 | } | 
|  | 630 | } | 
|  | 631 | IRPositions.emplace_back( | 
|  | 632 | IRPosition::callsite_function(cast<CallBase>(*ICS.getInstruction()))); | 
|  | 633 | return; | 
|  | 634 | case IRPosition::IRP_CALL_SITE_ARGUMENT: { | 
|  | 635 | int ArgNo = IRP.getArgNo(); | 
|  | 636 | assert(ICS && ArgNo >= 0 && "Expected call site!"); | 
|  | 637 | // TODO: We need to look at the operand bundles similar to the redirection | 
|  | 638 | //       in CallBase. | 
|  | 639 | if (!ICS.hasOperandBundles()) { | 
|  | 640 | const Function *Callee = ICS.getCalledFunction(); | 
|  | 641 | if (Callee && Callee->arg_size() > unsigned(ArgNo)) | 
|  | 642 | IRPositions.emplace_back(IRPosition::argument(*Callee->getArg(ArgNo))); | 
|  | 643 | if (Callee) | 
|  | 644 | IRPositions.emplace_back(IRPosition::function(*Callee)); | 
|  | 645 | } | 
|  | 646 | IRPositions.emplace_back(IRPosition::value(IRP.getAssociatedValue())); | 
|  | 647 | return; | 
|  | 648 | } | 
|  | 649 | } | 
|  | 650 | } | 
|  | 651 |  | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 652 | bool IRPosition::hasAttr(ArrayRef<Attribute::AttrKind> AKs, | 
|  | 653 | bool IgnoreSubsumingPositions) const { | 
|  | 654 | for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this)) { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 655 | for (Attribute::AttrKind AK : AKs) | 
|  | 656 | if (EquivIRP.getAttr(AK).getKindAsEnum() == AK) | 
|  | 657 | return true; | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 658 | // The first position returned by the SubsumingPositionIterator is | 
|  | 659 | // always the position itself. If we ignore subsuming positions we | 
|  | 660 | // are done after the first iteration. | 
|  | 661 | if (IgnoreSubsumingPositions) | 
|  | 662 | break; | 
|  | 663 | } | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 664 | return false; | 
|  | 665 | } | 
|  | 666 |  | 
|  | 667 | void IRPosition::getAttrs(ArrayRef<Attribute::AttrKind> AKs, | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 668 | SmallVectorImpl<Attribute> &Attrs, | 
|  | 669 | bool IgnoreSubsumingPositions) const { | 
|  | 670 | for (const IRPosition &EquivIRP : SubsumingPositionIterator(*this)) { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 671 | for (Attribute::AttrKind AK : AKs) { | 
|  | 672 | const Attribute &Attr = EquivIRP.getAttr(AK); | 
|  | 673 | if (Attr.getKindAsEnum() == AK) | 
|  | 674 | Attrs.push_back(Attr); | 
|  | 675 | } | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 676 | // The first position returned by the SubsumingPositionIterator is | 
|  | 677 | // always the position itself. If we ignore subsuming positions we | 
|  | 678 | // are done after the first iteration. | 
|  | 679 | if (IgnoreSubsumingPositions) | 
|  | 680 | break; | 
|  | 681 | } | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 682 | } | 
|  | 683 |  | 
|  | 684 | void IRPosition::verify() { | 
|  | 685 | switch (KindOrArgNo) { | 
|  | 686 | default: | 
|  | 687 | assert(KindOrArgNo >= 0 && "Expected argument or call site argument!"); | 
|  | 688 | assert((isa<CallBase>(AnchorVal) || isa<Argument>(AnchorVal)) && | 
|  | 689 | "Expected call base or argument for positive attribute index!"); | 
| Simon Pilgrim | 920b040 | 2019-08-29 10:08:45 +0000 | [diff] [blame] | 690 | if (isa<Argument>(AnchorVal)) { | 
|  | 691 | assert(cast<Argument>(AnchorVal)->getArgNo() == unsigned(getArgNo()) && | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 692 | "Argument number mismatch!"); | 
| Simon Pilgrim | 920b040 | 2019-08-29 10:08:45 +0000 | [diff] [blame] | 693 | assert(cast<Argument>(AnchorVal) == &getAssociatedValue() && | 
|  | 694 | "Associated value mismatch!"); | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 695 | } else { | 
| Simon Pilgrim | 920b040 | 2019-08-29 10:08:45 +0000 | [diff] [blame] | 696 | assert(cast<CallBase>(*AnchorVal).arg_size() > unsigned(getArgNo()) && | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 697 | "Call site argument number mismatch!"); | 
| Simon Pilgrim | 920b040 | 2019-08-29 10:08:45 +0000 | [diff] [blame] | 698 | assert(cast<CallBase>(*AnchorVal).getArgOperand(getArgNo()) == | 
|  | 699 | &getAssociatedValue() && | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 700 | "Associated value mismatch!"); | 
|  | 701 | } | 
|  | 702 | break; | 
|  | 703 | case IRP_INVALID: | 
|  | 704 | assert(!AnchorVal && "Expected no value for an invalid position!"); | 
|  | 705 | break; | 
|  | 706 | case IRP_FLOAT: | 
|  | 707 | assert((!isa<CallBase>(&getAssociatedValue()) && | 
|  | 708 | !isa<Argument>(&getAssociatedValue())) && | 
|  | 709 | "Expected specialized kind for call base and argument values!"); | 
|  | 710 | break; | 
|  | 711 | case IRP_RETURNED: | 
|  | 712 | assert(isa<Function>(AnchorVal) && | 
|  | 713 | "Expected function for a 'returned' position!"); | 
|  | 714 | assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!"); | 
|  | 715 | break; | 
|  | 716 | case IRP_CALL_SITE_RETURNED: | 
|  | 717 | assert((isa<CallBase>(AnchorVal)) && | 
|  | 718 | "Expected call base for 'call site returned' position!"); | 
|  | 719 | assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!"); | 
|  | 720 | break; | 
|  | 721 | case IRP_CALL_SITE: | 
|  | 722 | assert((isa<CallBase>(AnchorVal)) && | 
|  | 723 | "Expected call base for 'call site function' position!"); | 
|  | 724 | assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!"); | 
|  | 725 | break; | 
|  | 726 | case IRP_FUNCTION: | 
|  | 727 | assert(isa<Function>(AnchorVal) && | 
|  | 728 | "Expected function for a 'function' position!"); | 
|  | 729 | assert(AnchorVal == &getAssociatedValue() && "Associated value mismatch!"); | 
|  | 730 | break; | 
|  | 731 | } | 
|  | 732 | } | 
|  | 733 |  | 
| Benjamin Kramer | df4b9a3 | 2019-09-17 12:56:29 +0000 | [diff] [blame] | 734 | namespace { | 
| Johannes Doerfert | 1a74645 | 2019-10-20 22:28:49 -0500 | [diff] [blame] | 735 | /// Helper function to clamp a state \p S of type \p StateType with the | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 736 | /// information in \p R and indicate/return if \p S did change (as-in update is | 
|  | 737 | /// required to be run again). | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 738 | template <typename StateType> | 
| Johannes Doerfert | 1a74645 | 2019-10-20 22:28:49 -0500 | [diff] [blame] | 739 | ChangeStatus clampStateAndIndicateChange(StateType &S, const StateType &R) { | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 740 | auto Assumed = S.getAssumed(); | 
|  | 741 | S ^= R; | 
|  | 742 | return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED | 
|  | 743 | : ChangeStatus::CHANGED; | 
|  | 744 | } | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 745 |  | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 746 | /// Clamp the information known for all returned values of a function | 
|  | 747 | /// (identified by \p QueryingAA) into \p S. | 
|  | 748 | template <typename AAType, typename StateType = typename AAType::StateType> | 
|  | 749 | static void clampReturnedValueStates(Attributor &A, const AAType &QueryingAA, | 
|  | 750 | StateType &S) { | 
|  | 751 | LLVM_DEBUG(dbgs() << "[Attributor] Clamp return value states for " | 
| Johannes Doerfert | 3d347e2 | 2019-12-13 23:35:45 -0600 | [diff] [blame] | 752 | << QueryingAA << " into " << S << "\n"); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 753 |  | 
|  | 754 | assert((QueryingAA.getIRPosition().getPositionKind() == | 
|  | 755 | IRPosition::IRP_RETURNED || | 
|  | 756 | QueryingAA.getIRPosition().getPositionKind() == | 
|  | 757 | IRPosition::IRP_CALL_SITE_RETURNED) && | 
|  | 758 | "Can only clamp returned value states for a function returned or call " | 
|  | 759 | "site returned position!"); | 
|  | 760 |  | 
|  | 761 | // Use an optional state as there might not be any return values and we want | 
|  | 762 | // to join (IntegerState::operator&) the state of all there are. | 
|  | 763 | Optional<StateType> T; | 
|  | 764 |  | 
|  | 765 | // Callback for each possibly returned value. | 
|  | 766 | auto CheckReturnValue = [&](Value &RV) -> bool { | 
|  | 767 | const IRPosition &RVPos = IRPosition::value(RV); | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 768 | const AAType &AA = A.getAAFor<AAType>(QueryingAA, RVPos); | 
|  | 769 | LLVM_DEBUG(dbgs() << "[Attributor] RV: " << RV << " AA: " << AA.getAsStr() | 
|  | 770 | << " @ " << RVPos << "\n"); | 
|  | 771 | const StateType &AAS = static_cast<const StateType &>(AA.getState()); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 772 | if (T.hasValue()) | 
|  | 773 | *T &= AAS; | 
|  | 774 | else | 
|  | 775 | T = AAS; | 
|  | 776 | LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " RV State: " << T | 
|  | 777 | << "\n"); | 
|  | 778 | return T->isValidState(); | 
|  | 779 | }; | 
|  | 780 |  | 
|  | 781 | if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA)) | 
|  | 782 | S.indicatePessimisticFixpoint(); | 
|  | 783 | else if (T.hasValue()) | 
|  | 784 | S ^= *T; | 
|  | 785 | } | 
|  | 786 |  | 
| Hideto Ueno | 08daf8c | 2019-10-08 15:20:19 +0000 | [diff] [blame] | 787 | /// Helper class to compose two generic deduction | 
|  | 788 | template <typename AAType, typename Base, typename StateType, | 
|  | 789 | template <typename...> class F, template <typename...> class G> | 
|  | 790 | struct AAComposeTwoGenericDeduction | 
|  | 791 | : public F<AAType, G<AAType, Base, StateType>, StateType> { | 
|  | 792 | AAComposeTwoGenericDeduction(const IRPosition &IRP) | 
|  | 793 | : F<AAType, G<AAType, Base, StateType>, StateType>(IRP) {} | 
|  | 794 |  | 
|  | 795 | /// See AbstractAttribute::updateImpl(...). | 
|  | 796 | ChangeStatus updateImpl(Attributor &A) override { | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 797 | ChangeStatus ChangedF = | 
|  | 798 | F<AAType, G<AAType, Base, StateType>, StateType>::updateImpl(A); | 
| Johannes Doerfert | db6efb0 | 2019-10-13 20:40:10 +0000 | [diff] [blame] | 799 | ChangeStatus ChangedG = G<AAType, Base, StateType>::updateImpl(A); | 
|  | 800 | return ChangedF | ChangedG; | 
| Hideto Ueno | 08daf8c | 2019-10-08 15:20:19 +0000 | [diff] [blame] | 801 | } | 
|  | 802 | }; | 
|  | 803 |  | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 804 | /// Helper class for generic deduction: return value -> returned position. | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 805 | template <typename AAType, typename Base, | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 806 | typename StateType = typename Base::StateType> | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 807 | struct AAReturnedFromReturnedValues : public Base { | 
|  | 808 | AAReturnedFromReturnedValues(const IRPosition &IRP) : Base(IRP) {} | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 809 |  | 
|  | 810 | /// See AbstractAttribute::updateImpl(...). | 
|  | 811 | ChangeStatus updateImpl(Attributor &A) override { | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 812 | StateType S(StateType::getBestState(this->getState())); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 813 | clampReturnedValueStates<AAType, StateType>(A, *this, S); | 
| Johannes Doerfert | 028b2aa | 2019-08-20 05:57:01 +0000 | [diff] [blame] | 814 | // TODO: If we know we visited all returned values, thus no are assumed | 
|  | 815 | // dead, we can take the known information from the state T. | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 816 | return clampStateAndIndicateChange<StateType>(this->getState(), S); | 
|  | 817 | } | 
|  | 818 | }; | 
|  | 819 |  | 
|  | 820 | /// Clamp the information known at all call sites for a given argument | 
|  | 821 | /// (identified by \p QueryingAA) into \p S. | 
|  | 822 | template <typename AAType, typename StateType = typename AAType::StateType> | 
|  | 823 | static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA, | 
|  | 824 | StateType &S) { | 
|  | 825 | LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for " | 
| Johannes Doerfert | 3d347e2 | 2019-12-13 23:35:45 -0600 | [diff] [blame] | 826 | << QueryingAA << " into " << S << "\n"); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 827 |  | 
|  | 828 | assert(QueryingAA.getIRPosition().getPositionKind() == | 
|  | 829 | IRPosition::IRP_ARGUMENT && | 
|  | 830 | "Can only clamp call site argument states for an argument position!"); | 
|  | 831 |  | 
|  | 832 | // Use an optional state as there might not be any return values and we want | 
|  | 833 | // to join (IntegerState::operator&) the state of all there are. | 
|  | 834 | Optional<StateType> T; | 
|  | 835 |  | 
|  | 836 | // The argument number which is also the call site argument number. | 
|  | 837 | unsigned ArgNo = QueryingAA.getIRPosition().getArgNo(); | 
|  | 838 |  | 
| Johannes Doerfert | 661db04 | 2019-10-07 23:14:58 +0000 | [diff] [blame] | 839 | auto CallSiteCheck = [&](AbstractCallSite ACS) { | 
|  | 840 | const IRPosition &ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo); | 
|  | 841 | // Check if a coresponding argument was found or if it is on not associated | 
|  | 842 | // (which can happen for callback calls). | 
|  | 843 | if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID) | 
|  | 844 | return false; | 
|  | 845 |  | 
|  | 846 | const AAType &AA = A.getAAFor<AAType>(QueryingAA, ACSArgPos); | 
|  | 847 | LLVM_DEBUG(dbgs() << "[Attributor] ACS: " << *ACS.getInstruction() | 
|  | 848 | << " AA: " << AA.getAsStr() << " @" << ACSArgPos << "\n"); | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 849 | const StateType &AAS = static_cast<const StateType &>(AA.getState()); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 850 | if (T.hasValue()) | 
|  | 851 | *T &= AAS; | 
|  | 852 | else | 
|  | 853 | T = AAS; | 
|  | 854 | LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " CSA State: " << T | 
|  | 855 | << "\n"); | 
|  | 856 | return T->isValidState(); | 
|  | 857 | }; | 
|  | 858 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 859 | bool AllCallSitesKnown; | 
|  | 860 | if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true, | 
|  | 861 | AllCallSitesKnown)) | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 862 | S.indicatePessimisticFixpoint(); | 
|  | 863 | else if (T.hasValue()) | 
|  | 864 | S ^= *T; | 
|  | 865 | } | 
|  | 866 |  | 
|  | 867 | /// Helper class for generic deduction: call site argument -> argument position. | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 868 | template <typename AAType, typename Base, | 
|  | 869 | typename StateType = typename AAType::StateType> | 
|  | 870 | struct AAArgumentFromCallSiteArguments : public Base { | 
|  | 871 | AAArgumentFromCallSiteArguments(const IRPosition &IRP) : Base(IRP) {} | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 872 |  | 
|  | 873 | /// See AbstractAttribute::updateImpl(...). | 
|  | 874 | ChangeStatus updateImpl(Attributor &A) override { | 
| Johannes Doerfert | ea5fabe | 2020-01-28 09:46:15 -0600 | [diff] [blame] | 875 | StateType S(StateType::getBestState(this->getState())); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 876 | clampCallSiteArgumentStates<AAType, StateType>(A, *this, S); | 
| Johannes Doerfert | 028b2aa | 2019-08-20 05:57:01 +0000 | [diff] [blame] | 877 | // TODO: If we know we visited all incoming values, thus no are assumed | 
|  | 878 | // dead, we can take the known information from the state T. | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 879 | return clampStateAndIndicateChange<StateType>(this->getState(), S); | 
|  | 880 | } | 
|  | 881 | }; | 
|  | 882 |  | 
|  | 883 | /// Helper class for generic replication: function returned -> cs returned. | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 884 | template <typename AAType, typename Base, | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 885 | typename StateType = typename Base::StateType> | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 886 | struct AACallSiteReturnedFromReturned : public Base { | 
|  | 887 | AACallSiteReturnedFromReturned(const IRPosition &IRP) : Base(IRP) {} | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 888 |  | 
|  | 889 | /// See AbstractAttribute::updateImpl(...). | 
|  | 890 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 891 | assert(this->getIRPosition().getPositionKind() == | 
|  | 892 | IRPosition::IRP_CALL_SITE_RETURNED && | 
|  | 893 | "Can only wrap function returned positions for call site returned " | 
|  | 894 | "positions!"); | 
|  | 895 | auto &S = this->getState(); | 
|  | 896 |  | 
|  | 897 | const Function *AssociatedFunction = | 
|  | 898 | this->getIRPosition().getAssociatedFunction(); | 
|  | 899 | if (!AssociatedFunction) | 
|  | 900 | return S.indicatePessimisticFixpoint(); | 
|  | 901 |  | 
|  | 902 | IRPosition FnPos = IRPosition::returned(*AssociatedFunction); | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 903 | const AAType &AA = A.getAAFor<AAType>(*this, FnPos); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 904 | return clampStateAndIndicateChange( | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 905 | S, static_cast<const StateType &>(AA.getState())); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 906 | } | 
|  | 907 | }; | 
|  | 908 |  | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 909 | /// Helper class for generic deduction using must-be-executed-context | 
|  | 910 | /// Base class is required to have `followUse` method. | 
|  | 911 |  | 
|  | 912 | /// bool followUse(Attributor &A, const Use *U, const Instruction *I) | 
| Simon Pilgrim | f7aee61 | 2019-10-10 15:25:16 +0000 | [diff] [blame] | 913 | /// U - Underlying use. | 
|  | 914 | /// I - The user of the \p U. | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 915 | /// `followUse` returns true if the value should be tracked transitively. | 
|  | 916 |  | 
|  | 917 | template <typename AAType, typename Base, | 
|  | 918 | typename StateType = typename AAType::StateType> | 
|  | 919 | struct AAFromMustBeExecutedContext : public Base { | 
|  | 920 | AAFromMustBeExecutedContext(const IRPosition &IRP) : Base(IRP) {} | 
|  | 921 |  | 
|  | 922 | void initialize(Attributor &A) override { | 
|  | 923 | Base::initialize(A); | 
| Johannes Doerfert | b2083c5 | 2019-10-20 22:46:48 -0500 | [diff] [blame] | 924 | const IRPosition &IRP = this->getIRPosition(); | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 925 | Instruction *CtxI = IRP.getCtxI(); | 
|  | 926 |  | 
|  | 927 | if (!CtxI) | 
|  | 928 | return; | 
|  | 929 |  | 
|  | 930 | for (const Use &U : IRP.getAssociatedValue().uses()) | 
|  | 931 | Uses.insert(&U); | 
|  | 932 | } | 
|  | 933 |  | 
|  | 934 | /// See AbstractAttribute::updateImpl(...). | 
|  | 935 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 936 | auto BeforeState = this->getState(); | 
|  | 937 | auto &S = this->getState(); | 
|  | 938 | Instruction *CtxI = this->getIRPosition().getCtxI(); | 
|  | 939 | if (!CtxI) | 
|  | 940 | return ChangeStatus::UNCHANGED; | 
|  | 941 |  | 
|  | 942 | MustBeExecutedContextExplorer &Explorer = | 
|  | 943 | A.getInfoCache().getMustBeExecutedContextExplorer(); | 
|  | 944 |  | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 945 | auto EIt = Explorer.begin(CtxI), EEnd = Explorer.end(CtxI); | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 946 | for (unsigned u = 0; u < Uses.size(); ++u) { | 
| Johannes Doerfert | eb4f41d | 2019-10-30 17:21:53 -0500 | [diff] [blame] | 947 | const Use *U = Uses[u]; | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 948 | if (const Instruction *UserI = dyn_cast<Instruction>(U->getUser())) { | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 949 | bool Found = Explorer.findInContextOf(UserI, EIt, EEnd); | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 950 | if (Found && Base::followUse(A, U, UserI)) | 
|  | 951 | for (const Use &Us : UserI->uses()) | 
| Johannes Doerfert | eb4f41d | 2019-10-30 17:21:53 -0500 | [diff] [blame] | 952 | Uses.insert(&Us); | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 953 | } | 
|  | 954 | } | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 955 |  | 
|  | 956 | return BeforeState == S ? ChangeStatus::UNCHANGED : ChangeStatus::CHANGED; | 
|  | 957 | } | 
|  | 958 |  | 
|  | 959 | private: | 
|  | 960 | /// Container for (transitive) uses of the associated value. | 
|  | 961 | SetVector<const Use *> Uses; | 
|  | 962 | }; | 
|  | 963 |  | 
|  | 964 | template <typename AAType, typename Base, | 
|  | 965 | typename StateType = typename AAType::StateType> | 
|  | 966 | using AAArgumentFromCallSiteArgumentsAndMustBeExecutedContext = | 
|  | 967 | AAComposeTwoGenericDeduction<AAType, Base, StateType, | 
|  | 968 | AAFromMustBeExecutedContext, | 
|  | 969 | AAArgumentFromCallSiteArguments>; | 
|  | 970 |  | 
|  | 971 | template <typename AAType, typename Base, | 
|  | 972 | typename StateType = typename AAType::StateType> | 
|  | 973 | using AACallSiteReturnedFromReturnedAndMustBeExecutedContext = | 
|  | 974 | AAComposeTwoGenericDeduction<AAType, Base, StateType, | 
|  | 975 | AAFromMustBeExecutedContext, | 
|  | 976 | AACallSiteReturnedFromReturned>; | 
|  | 977 |  | 
| Stefan Stipanovic | 5360589 | 2019-06-27 11:27:54 +0000 | [diff] [blame] | 978 | /// -----------------------NoUnwind Function Attribute-------------------------- | 
|  | 979 |  | 
| Johannes Doerfert | 344d038 | 2019-08-07 22:34:26 +0000 | [diff] [blame] | 980 | struct AANoUnwindImpl : AANoUnwind { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 981 | AANoUnwindImpl(const IRPosition &IRP) : AANoUnwind(IRP) {} | 
| Stefan Stipanovic | 5360589 | 2019-06-27 11:27:54 +0000 | [diff] [blame] | 982 |  | 
| Stefan Stipanovic | 15e86f7 | 2019-07-12 17:42:14 +0000 | [diff] [blame] | 983 | const std::string getAsStr() const override { | 
| Stefan Stipanovic | 5360589 | 2019-06-27 11:27:54 +0000 | [diff] [blame] | 984 | return getAssumed() ? "nounwind" : "may-unwind"; | 
|  | 985 | } | 
|  | 986 |  | 
|  | 987 | /// See AbstractAttribute::updateImpl(...). | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 988 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 989 | auto Opcodes = { | 
|  | 990 | (unsigned)Instruction::Invoke,      (unsigned)Instruction::CallBr, | 
|  | 991 | (unsigned)Instruction::Call,        (unsigned)Instruction::CleanupRet, | 
|  | 992 | (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume}; | 
|  | 993 |  | 
|  | 994 | auto CheckForNoUnwind = [&](Instruction &I) { | 
|  | 995 | if (!I.mayThrow()) | 
|  | 996 | return true; | 
|  | 997 |  | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 998 | if (ImmutableCallSite ICS = ImmutableCallSite(&I)) { | 
|  | 999 | const auto &NoUnwindAA = | 
|  | 1000 | A.getAAFor<AANoUnwind>(*this, IRPosition::callsite_function(ICS)); | 
|  | 1001 | return NoUnwindAA.isAssumedNoUnwind(); | 
|  | 1002 | } | 
|  | 1003 | return false; | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 1004 | }; | 
|  | 1005 |  | 
|  | 1006 | if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes)) | 
|  | 1007 | return indicatePessimisticFixpoint(); | 
|  | 1008 |  | 
|  | 1009 | return ChangeStatus::UNCHANGED; | 
|  | 1010 | } | 
| Stefan Stipanovic | 5360589 | 2019-06-27 11:27:54 +0000 | [diff] [blame] | 1011 | }; | 
|  | 1012 |  | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 1013 | struct AANoUnwindFunction final : public AANoUnwindImpl { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1014 | AANoUnwindFunction(const IRPosition &IRP) : AANoUnwindImpl(IRP) {} | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 1015 |  | 
|  | 1016 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 1017 | void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) } | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 1018 | }; | 
|  | 1019 |  | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 1020 | /// NoUnwind attribute deduction for a call sites. | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 1021 | struct AANoUnwindCallSite final : AANoUnwindImpl { | 
|  | 1022 | AANoUnwindCallSite(const IRPosition &IRP) : AANoUnwindImpl(IRP) {} | 
|  | 1023 |  | 
|  | 1024 | /// See AbstractAttribute::initialize(...). | 
|  | 1025 | void initialize(Attributor &A) override { | 
|  | 1026 | AANoUnwindImpl::initialize(A); | 
|  | 1027 | Function *F = getAssociatedFunction(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 1028 | if (!F) | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 1029 | indicatePessimisticFixpoint(); | 
|  | 1030 | } | 
|  | 1031 |  | 
|  | 1032 | /// See AbstractAttribute::updateImpl(...). | 
|  | 1033 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 1034 | // TODO: Once we have call site specific value information we can provide | 
|  | 1035 | //       call site specific liveness information and then it makes | 
|  | 1036 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 1037 | //       redirecting requests to the callee argument. | 
|  | 1038 | Function *F = getAssociatedFunction(); | 
|  | 1039 | const IRPosition &FnPos = IRPosition::function(*F); | 
|  | 1040 | auto &FnAA = A.getAAFor<AANoUnwind>(*this, FnPos); | 
|  | 1041 | return clampStateAndIndicateChange( | 
|  | 1042 | getState(), | 
|  | 1043 | static_cast<const AANoUnwind::StateType &>(FnAA.getState())); | 
|  | 1044 | } | 
|  | 1045 |  | 
|  | 1046 | /// See AbstractAttribute::trackStatistics() | 
|  | 1047 | void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nounwind); } | 
|  | 1048 | }; | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 1049 |  | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1050 | /// --------------------- Function Return Values ------------------------------- | 
|  | 1051 |  | 
|  | 1052 | /// "Attribute" that collects all potential returned values and the return | 
|  | 1053 | /// instructions that they arise from. | 
|  | 1054 | /// | 
|  | 1055 | /// If there is a unique returned value R, the manifest method will: | 
|  | 1056 | ///   - mark R with the "returned" attribute, if R is an argument. | 
| Johannes Doerfert | eccdf08 | 2019-08-05 23:35:12 +0000 | [diff] [blame] | 1057 | class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1058 |  | 
|  | 1059 | /// Mapping of values potentially returned by the associated function to the | 
|  | 1060 | /// return instructions that might return them. | 
| Johannes Doerfert | a4a308c | 2019-08-26 17:51:23 +0000 | [diff] [blame] | 1061 | MapVector<Value *, SmallSetVector<ReturnInst *, 4>> ReturnedValues; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1062 |  | 
| Johannes Doerfert | deb9ea3 | 2019-08-23 15:42:19 +0000 | [diff] [blame] | 1063 | /// Mapping to remember the number of returned values for a call site such | 
|  | 1064 | /// that we can avoid updates if nothing changed. | 
|  | 1065 | DenseMap<const CallBase *, unsigned> NumReturnedValuesPerKnownAA; | 
|  | 1066 |  | 
|  | 1067 | /// Set of unresolved calls returned by the associated function. | 
| Johannes Doerfert | 695089e | 2019-08-23 15:23:49 +0000 | [diff] [blame] | 1068 | SmallSetVector<CallBase *, 4> UnresolvedCalls; | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1069 |  | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1070 | /// State flags | 
|  | 1071 | /// | 
|  | 1072 | ///{ | 
| Johannes Doerfert | deb9ea3 | 2019-08-23 15:42:19 +0000 | [diff] [blame] | 1073 | bool IsFixed = false; | 
|  | 1074 | bool IsValidState = true; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1075 | ///} | 
|  | 1076 |  | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1077 | public: | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1078 | AAReturnedValuesImpl(const IRPosition &IRP) : AAReturnedValues(IRP) {} | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1079 |  | 
|  | 1080 | /// See AbstractAttribute::initialize(...). | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 1081 | void initialize(Attributor &A) override { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1082 | // Reset the state. | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1083 | IsFixed = false; | 
|  | 1084 | IsValidState = true; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1085 | ReturnedValues.clear(); | 
|  | 1086 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1087 | Function *F = getAssociatedFunction(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 1088 | if (!F) { | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1089 | indicatePessimisticFixpoint(); | 
|  | 1090 | return; | 
|  | 1091 | } | 
| Johannes Doerfert | e273ac4 | 2020-01-12 00:13:03 -0600 | [diff] [blame] | 1092 | assert(!F->getReturnType()->isVoidTy() && | 
|  | 1093 | "Did not expect a void return type!"); | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1094 |  | 
|  | 1095 | // The map from instruction opcodes to those instructions in the function. | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1096 | auto &OpcodeInstMap = A.getInfoCache().getOpcodeInstMapForFunction(*F); | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1097 |  | 
|  | 1098 | // Look through all arguments, if one is marked as returned we are done. | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1099 | for (Argument &Arg : F->args()) { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1100 | if (Arg.hasReturnedAttr()) { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1101 | auto &ReturnInstSet = ReturnedValues[&Arg]; | 
|  | 1102 | for (Instruction *RI : OpcodeInstMap[Instruction::Ret]) | 
|  | 1103 | ReturnInstSet.insert(cast<ReturnInst>(RI)); | 
|  | 1104 |  | 
|  | 1105 | indicateOptimisticFixpoint(); | 
|  | 1106 | return; | 
|  | 1107 | } | 
|  | 1108 | } | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 1109 |  | 
|  | 1110 | if (!F->hasExactDefinition()) | 
|  | 1111 | indicatePessimisticFixpoint(); | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1112 | } | 
|  | 1113 |  | 
|  | 1114 | /// See AbstractAttribute::manifest(...). | 
| Stefan Stipanovic | 15e86f7 | 2019-07-12 17:42:14 +0000 | [diff] [blame] | 1115 | ChangeStatus manifest(Attributor &A) override; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1116 |  | 
|  | 1117 | /// See AbstractAttribute::getState(...). | 
| Stefan Stipanovic | 15e86f7 | 2019-07-12 17:42:14 +0000 | [diff] [blame] | 1118 | AbstractState &getState() override { return *this; } | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1119 |  | 
|  | 1120 | /// See AbstractAttribute::getState(...). | 
| Stefan Stipanovic | 15e86f7 | 2019-07-12 17:42:14 +0000 | [diff] [blame] | 1121 | const AbstractState &getState() const override { return *this; } | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1122 |  | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1123 | /// See AbstractAttribute::updateImpl(Attributor &A). | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 1124 | ChangeStatus updateImpl(Attributor &A) override; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1125 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1126 | llvm::iterator_range<iterator> returned_values() override { | 
|  | 1127 | return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end()); | 
|  | 1128 | } | 
|  | 1129 |  | 
|  | 1130 | llvm::iterator_range<const_iterator> returned_values() const override { | 
|  | 1131 | return llvm::make_range(ReturnedValues.begin(), ReturnedValues.end()); | 
|  | 1132 | } | 
|  | 1133 |  | 
| Johannes Doerfert | 695089e | 2019-08-23 15:23:49 +0000 | [diff] [blame] | 1134 | const SmallSetVector<CallBase *, 4> &getUnresolvedCalls() const override { | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1135 | return UnresolvedCalls; | 
|  | 1136 | } | 
|  | 1137 |  | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1138 | /// Return the number of potential return values, -1 if unknown. | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1139 | size_t getNumReturnValues() const override { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1140 | return isValidState() ? ReturnedValues.size() : -1; | 
|  | 1141 | } | 
|  | 1142 |  | 
|  | 1143 | /// Return an assumed unique return value if a single candidate is found. If | 
|  | 1144 | /// there cannot be one, return a nullptr. If it is not clear yet, return the | 
|  | 1145 | /// Optional::NoneType. | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 1146 | Optional<Value *> getAssumedUniqueReturnValue(Attributor &A) const; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1147 |  | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 1148 | /// See AbstractState::checkForAllReturnedValues(...). | 
|  | 1149 | bool checkForAllReturnedValuesAndReturnInsts( | 
| Johannes Doerfert | 695089e | 2019-08-23 15:23:49 +0000 | [diff] [blame] | 1150 | const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)> | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 1151 | &Pred) const override; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1152 |  | 
|  | 1153 | /// Pretty print the attribute similar to the IR representation. | 
| Stefan Stipanovic | 15e86f7 | 2019-07-12 17:42:14 +0000 | [diff] [blame] | 1154 | const std::string getAsStr() const override; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1155 |  | 
|  | 1156 | /// See AbstractState::isAtFixpoint(). | 
|  | 1157 | bool isAtFixpoint() const override { return IsFixed; } | 
|  | 1158 |  | 
|  | 1159 | /// See AbstractState::isValidState(). | 
|  | 1160 | bool isValidState() const override { return IsValidState; } | 
|  | 1161 |  | 
|  | 1162 | /// See AbstractState::indicateOptimisticFixpoint(...). | 
| Johannes Doerfert | d1c3793 | 2019-08-04 18:37:38 +0000 | [diff] [blame] | 1163 | ChangeStatus indicateOptimisticFixpoint() override { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1164 | IsFixed = true; | 
| Johannes Doerfert | d1c3793 | 2019-08-04 18:37:38 +0000 | [diff] [blame] | 1165 | return ChangeStatus::UNCHANGED; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1166 | } | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 1167 |  | 
| Johannes Doerfert | d1c3793 | 2019-08-04 18:37:38 +0000 | [diff] [blame] | 1168 | ChangeStatus indicatePessimisticFixpoint() override { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1169 | IsFixed = true; | 
|  | 1170 | IsValidState = false; | 
| Johannes Doerfert | d1c3793 | 2019-08-04 18:37:38 +0000 | [diff] [blame] | 1171 | return ChangeStatus::CHANGED; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1172 | } | 
|  | 1173 | }; | 
|  | 1174 |  | 
|  | 1175 | ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) { | 
|  | 1176 | ChangeStatus Changed = ChangeStatus::UNCHANGED; | 
|  | 1177 |  | 
|  | 1178 | // Bookkeeping. | 
|  | 1179 | assert(isValidState()); | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 1180 | STATS_DECLTRACK(KnownReturnValues, FunctionReturn, | 
|  | 1181 | "Number of function with known return values"); | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1182 |  | 
|  | 1183 | // Check if we have an assumed unique return value that we could manifest. | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 1184 | Optional<Value *> UniqueRV = getAssumedUniqueReturnValue(A); | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1185 |  | 
|  | 1186 | if (!UniqueRV.hasValue() || !UniqueRV.getValue()) | 
|  | 1187 | return Changed; | 
|  | 1188 |  | 
|  | 1189 | // Bookkeeping. | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 1190 | STATS_DECLTRACK(UniqueReturnValue, FunctionReturn, | 
|  | 1191 | "Number of function with unique return"); | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1192 |  | 
| Johannes Doerfert | 23400e61 | 2019-08-23 17:41:37 +0000 | [diff] [blame] | 1193 | // Callback to replace the uses of CB with the constant C. | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 1194 | auto ReplaceCallSiteUsersWith = [&A](CallBase &CB, Constant &C) { | 
| Johannes Doerfert | 8fa56c4 | 2019-10-11 01:45:32 +0000 | [diff] [blame] | 1195 | if (CB.getNumUses() == 0 || CB.isMustTailCall()) | 
| Johannes Doerfert | 23400e61 | 2019-08-23 17:41:37 +0000 | [diff] [blame] | 1196 | return ChangeStatus::UNCHANGED; | 
| Johannes Doerfert | 4c62a35 | 2020-01-12 00:17:08 -0600 | [diff] [blame] | 1197 | if (A.changeValueAfterManifest(CB, C)) | 
|  | 1198 | return ChangeStatus::CHANGED; | 
|  | 1199 | return ChangeStatus::UNCHANGED; | 
| Johannes Doerfert | 23400e61 | 2019-08-23 17:41:37 +0000 | [diff] [blame] | 1200 | }; | 
|  | 1201 |  | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1202 | // If the assumed unique return value is an argument, annotate it. | 
|  | 1203 | if (auto *UniqueRVArg = dyn_cast<Argument>(UniqueRV.getValue())) { | 
| Johannes Doerfert | b2083c5 | 2019-10-20 22:46:48 -0500 | [diff] [blame] | 1204 | // TODO: This should be handled differently! | 
|  | 1205 | this->AnchorVal = UniqueRVArg; | 
|  | 1206 | this->KindOrArgNo = UniqueRVArg->getArgNo(); | 
| Johannes Doerfert | 23400e61 | 2019-08-23 17:41:37 +0000 | [diff] [blame] | 1207 | Changed = IRAttribute::manifest(A); | 
|  | 1208 | } else if (auto *RVC = dyn_cast<Constant>(UniqueRV.getValue())) { | 
|  | 1209 | // We can replace the returned value with the unique returned constant. | 
|  | 1210 | Value &AnchorValue = getAnchorValue(); | 
|  | 1211 | if (Function *F = dyn_cast<Function>(&AnchorValue)) { | 
|  | 1212 | for (const Use &U : F->uses()) | 
|  | 1213 | if (CallBase *CB = dyn_cast<CallBase>(U.getUser())) | 
| Johannes Doerfert | e7c6f97 | 2019-09-14 02:57:50 +0000 | [diff] [blame] | 1214 | if (CB->isCallee(&U)) { | 
|  | 1215 | Constant *RVCCast = | 
| Johannes Doerfert | 07d1642 | 2019-11-01 23:03:35 -0500 | [diff] [blame] | 1216 | CB->getType() == RVC->getType() | 
|  | 1217 | ? RVC | 
|  | 1218 | : ConstantExpr::getTruncOrBitCast(RVC, CB->getType()); | 
| Johannes Doerfert | e7c6f97 | 2019-09-14 02:57:50 +0000 | [diff] [blame] | 1219 | Changed = ReplaceCallSiteUsersWith(*CB, *RVCCast) | Changed; | 
|  | 1220 | } | 
| Johannes Doerfert | 23400e61 | 2019-08-23 17:41:37 +0000 | [diff] [blame] | 1221 | } else { | 
|  | 1222 | assert(isa<CallBase>(AnchorValue) && | 
|  | 1223 | "Expcected a function or call base anchor!"); | 
| Johannes Doerfert | e7c6f97 | 2019-09-14 02:57:50 +0000 | [diff] [blame] | 1224 | Constant *RVCCast = | 
| Johannes Doerfert | 07d1642 | 2019-11-01 23:03:35 -0500 | [diff] [blame] | 1225 | AnchorValue.getType() == RVC->getType() | 
|  | 1226 | ? RVC | 
|  | 1227 | : ConstantExpr::getTruncOrBitCast(RVC, AnchorValue.getType()); | 
| Johannes Doerfert | e7c6f97 | 2019-09-14 02:57:50 +0000 | [diff] [blame] | 1228 | Changed = ReplaceCallSiteUsersWith(cast<CallBase>(AnchorValue), *RVCCast); | 
| Johannes Doerfert | 23400e61 | 2019-08-23 17:41:37 +0000 | [diff] [blame] | 1229 | } | 
|  | 1230 | if (Changed == ChangeStatus::CHANGED) | 
|  | 1231 | STATS_DECLTRACK(UniqueConstantReturnValue, FunctionReturn, | 
|  | 1232 | "Number of function returns replaced by constant return"); | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1233 | } | 
|  | 1234 |  | 
|  | 1235 | return Changed; | 
|  | 1236 | } | 
|  | 1237 |  | 
|  | 1238 | const std::string AAReturnedValuesImpl::getAsStr() const { | 
|  | 1239 | return (isAtFixpoint() ? "returns(#" : "may-return(#") + | 
| Johannes Doerfert | 6471bb6 | 2019-08-04 18:39:28 +0000 | [diff] [blame] | 1240 | (isValidState() ? std::to_string(getNumReturnValues()) : "?") + | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1241 | ")[#UC: " + std::to_string(UnresolvedCalls.size()) + "]"; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1242 | } | 
|  | 1243 |  | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 1244 | Optional<Value *> | 
|  | 1245 | AAReturnedValuesImpl::getAssumedUniqueReturnValue(Attributor &A) const { | 
|  | 1246 | // If checkForAllReturnedValues provides a unique value, ignoring potential | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1247 | // undef values that can also be present, it is assumed to be the actual | 
|  | 1248 | // return value and forwarded to the caller of this method. If there are | 
|  | 1249 | // multiple, a nullptr is returned indicating there cannot be a unique | 
|  | 1250 | // returned value. | 
|  | 1251 | Optional<Value *> UniqueRV; | 
|  | 1252 |  | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 1253 | auto Pred = [&](Value &RV) -> bool { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1254 | // If we found a second returned value and neither the current nor the saved | 
|  | 1255 | // one is an undef, there is no unique returned value. Undefs are special | 
|  | 1256 | // since we can pretend they have any value. | 
|  | 1257 | if (UniqueRV.hasValue() && UniqueRV != &RV && | 
|  | 1258 | !(isa<UndefValue>(RV) || isa<UndefValue>(UniqueRV.getValue()))) { | 
|  | 1259 | UniqueRV = nullptr; | 
|  | 1260 | return false; | 
|  | 1261 | } | 
|  | 1262 |  | 
|  | 1263 | // Do not overwrite a value with an undef. | 
|  | 1264 | if (!UniqueRV.hasValue() || !isa<UndefValue>(RV)) | 
|  | 1265 | UniqueRV = &RV; | 
|  | 1266 |  | 
|  | 1267 | return true; | 
|  | 1268 | }; | 
|  | 1269 |  | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1270 | if (!A.checkForAllReturnedValues(Pred, *this)) | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1271 | UniqueRV = nullptr; | 
|  | 1272 |  | 
|  | 1273 | return UniqueRV; | 
|  | 1274 | } | 
|  | 1275 |  | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 1276 | bool AAReturnedValuesImpl::checkForAllReturnedValuesAndReturnInsts( | 
| Johannes Doerfert | 695089e | 2019-08-23 15:23:49 +0000 | [diff] [blame] | 1277 | const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)> | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 1278 | &Pred) const { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1279 | if (!isValidState()) | 
|  | 1280 | return false; | 
|  | 1281 |  | 
|  | 1282 | // Check all returned values but ignore call sites as long as we have not | 
|  | 1283 | // encountered an overdefined one during an update. | 
|  | 1284 | for (auto &It : ReturnedValues) { | 
|  | 1285 | Value *RV = It.first; | 
|  | 1286 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1287 | CallBase *CB = dyn_cast<CallBase>(RV); | 
|  | 1288 | if (CB && !UnresolvedCalls.count(CB)) | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1289 | continue; | 
|  | 1290 |  | 
| Johannes Doerfert | 695089e | 2019-08-23 15:23:49 +0000 | [diff] [blame] | 1291 | if (!Pred(*RV, It.second)) | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1292 | return false; | 
|  | 1293 | } | 
|  | 1294 |  | 
|  | 1295 | return true; | 
|  | 1296 | } | 
|  | 1297 |  | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 1298 | ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) { | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1299 | size_t NumUnresolvedCalls = UnresolvedCalls.size(); | 
|  | 1300 | bool Changed = false; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1301 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1302 | // State used in the value traversals starting in returned values. | 
|  | 1303 | struct RVState { | 
|  | 1304 | // The map in which we collect return values -> return instrs. | 
|  | 1305 | decltype(ReturnedValues) &RetValsMap; | 
|  | 1306 | // The flag to indicate a change. | 
| Johannes Doerfert | 056f1b5 | 2019-08-19 19:14:10 +0000 | [diff] [blame] | 1307 | bool &Changed; | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1308 | // The return instrs we come from. | 
| Johannes Doerfert | 695089e | 2019-08-23 15:23:49 +0000 | [diff] [blame] | 1309 | SmallSetVector<ReturnInst *, 4> RetInsts; | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1310 | }; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1311 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1312 | // Callback for a leaf value returned by the associated function. | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 1313 | auto VisitValueCB = [](Value &Val, RVState &RVS, bool) -> bool { | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1314 | auto Size = RVS.RetValsMap[&Val].size(); | 
|  | 1315 | RVS.RetValsMap[&Val].insert(RVS.RetInsts.begin(), RVS.RetInsts.end()); | 
|  | 1316 | bool Inserted = RVS.RetValsMap[&Val].size() != Size; | 
|  | 1317 | RVS.Changed |= Inserted; | 
|  | 1318 | LLVM_DEBUG({ | 
|  | 1319 | if (Inserted) | 
|  | 1320 | dbgs() << "[AAReturnedValues] 1 Add new returned value " << Val | 
|  | 1321 | << " => " << RVS.RetInsts.size() << "\n"; | 
|  | 1322 | }); | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 1323 | return true; | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1324 | }; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1325 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1326 | // Helper method to invoke the generic value traversal. | 
|  | 1327 | auto VisitReturnedValue = [&](Value &RV, RVState &RVS) { | 
|  | 1328 | IRPosition RetValPos = IRPosition::value(RV); | 
|  | 1329 | return genericValueTraversal<AAReturnedValues, RVState>(A, RetValPos, *this, | 
|  | 1330 | RVS, VisitValueCB); | 
|  | 1331 | }; | 
| Johannes Doerfert | da4d811 | 2019-08-01 16:21:54 +0000 | [diff] [blame] | 1332 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1333 | // Callback for all "return intructions" live in the associated function. | 
|  | 1334 | auto CheckReturnInst = [this, &VisitReturnedValue, &Changed](Instruction &I) { | 
|  | 1335 | ReturnInst &Ret = cast<ReturnInst>(I); | 
| Johannes Doerfert | 056f1b5 | 2019-08-19 19:14:10 +0000 | [diff] [blame] | 1336 | RVState RVS({ReturnedValues, Changed, {}}); | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1337 | RVS.RetInsts.insert(&Ret); | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1338 | return VisitReturnedValue(*Ret.getReturnValue(), RVS); | 
|  | 1339 | }; | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 1340 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1341 | // Start by discovering returned values from all live returned instructions in | 
|  | 1342 | // the associated function. | 
|  | 1343 | if (!A.checkForAllInstructions(CheckReturnInst, *this, {Instruction::Ret})) | 
|  | 1344 | return indicatePessimisticFixpoint(); | 
|  | 1345 |  | 
|  | 1346 | // Once returned values "directly" present in the code are handled we try to | 
|  | 1347 | // resolve returned calls. | 
|  | 1348 | decltype(ReturnedValues) NewRVsMap; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1349 | for (auto &It : ReturnedValues) { | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1350 | LLVM_DEBUG(dbgs() << "[AAReturnedValues] Returned value: " << *It.first | 
|  | 1351 | << " by #" << It.second.size() << " RIs\n"); | 
|  | 1352 | CallBase *CB = dyn_cast<CallBase>(It.first); | 
|  | 1353 | if (!CB || UnresolvedCalls.count(CB)) | 
|  | 1354 | continue; | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 1355 |  | 
| Johannes Doerfert | 07a5c12 | 2019-08-28 14:09:14 +0000 | [diff] [blame] | 1356 | if (!CB->getCalledFunction()) { | 
|  | 1357 | LLVM_DEBUG(dbgs() << "[AAReturnedValues] Unresolved call: " << *CB | 
|  | 1358 | << "\n"); | 
|  | 1359 | UnresolvedCalls.insert(CB); | 
|  | 1360 | continue; | 
|  | 1361 | } | 
|  | 1362 |  | 
|  | 1363 | // TODO: use the function scope once we have call site AAReturnedValues. | 
|  | 1364 | const auto &RetValAA = A.getAAFor<AAReturnedValues>( | 
|  | 1365 | *this, IRPosition::function(*CB->getCalledFunction())); | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 1366 | LLVM_DEBUG(dbgs() << "[AAReturnedValues] Found another AAReturnedValues: " | 
| Johannes Doerfert | 3d347e2 | 2019-12-13 23:35:45 -0600 | [diff] [blame] | 1367 | << RetValAA << "\n"); | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1368 |  | 
|  | 1369 | // Skip dead ends, thus if we do not know anything about the returned | 
|  | 1370 | // call we mark it as unresolved and it will stay that way. | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 1371 | if (!RetValAA.getState().isValidState()) { | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1372 | LLVM_DEBUG(dbgs() << "[AAReturnedValues] Unresolved call: " << *CB | 
|  | 1373 | << "\n"); | 
|  | 1374 | UnresolvedCalls.insert(CB); | 
|  | 1375 | continue; | 
|  | 1376 | } | 
|  | 1377 |  | 
| Johannes Doerfert | de7674c | 2019-08-19 21:35:31 +0000 | [diff] [blame] | 1378 | // Do not try to learn partial information. If the callee has unresolved | 
|  | 1379 | // return values we will treat the call as unresolved/opaque. | 
|  | 1380 | auto &RetValAAUnresolvedCalls = RetValAA.getUnresolvedCalls(); | 
|  | 1381 | if (!RetValAAUnresolvedCalls.empty()) { | 
|  | 1382 | UnresolvedCalls.insert(CB); | 
|  | 1383 | continue; | 
|  | 1384 | } | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1385 |  | 
| Johannes Doerfert | de7674c | 2019-08-19 21:35:31 +0000 | [diff] [blame] | 1386 | // Now check if we can track transitively returned values. If possible, thus | 
|  | 1387 | // if all return value can be represented in the current scope, do so. | 
|  | 1388 | bool Unresolved = false; | 
|  | 1389 | for (auto &RetValAAIt : RetValAA.returned_values()) { | 
|  | 1390 | Value *RetVal = RetValAAIt.first; | 
|  | 1391 | if (isa<Argument>(RetVal) || isa<CallBase>(RetVal) || | 
|  | 1392 | isa<Constant>(RetVal)) | 
|  | 1393 | continue; | 
|  | 1394 | // Anything that did not fit in the above categories cannot be resolved, | 
|  | 1395 | // mark the call as unresolved. | 
|  | 1396 | LLVM_DEBUG(dbgs() << "[AAReturnedValues] transitively returned value " | 
|  | 1397 | "cannot be translated: " | 
|  | 1398 | << *RetVal << "\n"); | 
|  | 1399 | UnresolvedCalls.insert(CB); | 
|  | 1400 | Unresolved = true; | 
|  | 1401 | break; | 
|  | 1402 | } | 
|  | 1403 |  | 
|  | 1404 | if (Unresolved) | 
|  | 1405 | continue; | 
|  | 1406 |  | 
| Johannes Doerfert | deb9ea3 | 2019-08-23 15:42:19 +0000 | [diff] [blame] | 1407 | // Now track transitively returned values. | 
|  | 1408 | unsigned &NumRetAA = NumReturnedValuesPerKnownAA[CB]; | 
|  | 1409 | if (NumRetAA == RetValAA.getNumReturnValues()) { | 
|  | 1410 | LLVM_DEBUG(dbgs() << "[AAReturnedValues] Skip call as it has not " | 
|  | 1411 | "changed since it was seen last\n"); | 
|  | 1412 | continue; | 
|  | 1413 | } | 
|  | 1414 | NumRetAA = RetValAA.getNumReturnValues(); | 
|  | 1415 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1416 | for (auto &RetValAAIt : RetValAA.returned_values()) { | 
|  | 1417 | Value *RetVal = RetValAAIt.first; | 
|  | 1418 | if (Argument *Arg = dyn_cast<Argument>(RetVal)) { | 
|  | 1419 | // Arguments are mapped to call site operands and we begin the traversal | 
|  | 1420 | // again. | 
| Johannes Doerfert | 056f1b5 | 2019-08-19 19:14:10 +0000 | [diff] [blame] | 1421 | bool Unused = false; | 
|  | 1422 | RVState RVS({NewRVsMap, Unused, RetValAAIt.second}); | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1423 | VisitReturnedValue(*CB->getArgOperand(Arg->getArgNo()), RVS); | 
|  | 1424 | continue; | 
|  | 1425 | } else if (isa<CallBase>(RetVal)) { | 
|  | 1426 | // Call sites are resolved by the callee attribute over time, no need to | 
|  | 1427 | // do anything for us. | 
|  | 1428 | continue; | 
|  | 1429 | } else if (isa<Constant>(RetVal)) { | 
|  | 1430 | // Constants are valid everywhere, we can simply take them. | 
|  | 1431 | NewRVsMap[RetVal].insert(It.second.begin(), It.second.end()); | 
|  | 1432 | continue; | 
|  | 1433 | } | 
| Johannes Doerfert | 4361da2 | 2019-08-04 18:38:53 +0000 | [diff] [blame] | 1434 | } | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1435 | } | 
|  | 1436 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1437 | // To avoid modifications to the ReturnedValues map while we iterate over it | 
|  | 1438 | // we kept record of potential new entries in a copy map, NewRVsMap. | 
|  | 1439 | for (auto &It : NewRVsMap) { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1440 | assert(!It.second.empty() && "Entry does not add anything."); | 
|  | 1441 | auto &ReturnInsts = ReturnedValues[It.first]; | 
|  | 1442 | for (ReturnInst *RI : It.second) | 
| Johannes Doerfert | 695089e | 2019-08-23 15:23:49 +0000 | [diff] [blame] | 1443 | if (ReturnInsts.insert(RI)) { | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1444 | LLVM_DEBUG(dbgs() << "[AAReturnedValues] Add new returned value " | 
|  | 1445 | << *It.first << " => " << *RI << "\n"); | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1446 | Changed = true; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1447 | } | 
|  | 1448 | } | 
|  | 1449 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1450 | Changed |= (NumUnresolvedCalls != UnresolvedCalls.size()); | 
|  | 1451 | return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED; | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 1452 | } | 
|  | 1453 |  | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1454 | struct AAReturnedValuesFunction final : public AAReturnedValuesImpl { | 
|  | 1455 | AAReturnedValuesFunction(const IRPosition &IRP) : AAReturnedValuesImpl(IRP) {} | 
|  | 1456 |  | 
|  | 1457 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 1458 | void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(returned) } | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 1459 | }; | 
|  | 1460 |  | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 1461 | /// Returned values information for a call sites. | 
| Johannes Doerfert | 07a5c12 | 2019-08-28 14:09:14 +0000 | [diff] [blame] | 1462 | struct AAReturnedValuesCallSite final : AAReturnedValuesImpl { | 
|  | 1463 | AAReturnedValuesCallSite(const IRPosition &IRP) : AAReturnedValuesImpl(IRP) {} | 
|  | 1464 |  | 
|  | 1465 | /// See AbstractAttribute::initialize(...). | 
|  | 1466 | void initialize(Attributor &A) override { | 
|  | 1467 | // TODO: Once we have call site specific value information we can provide | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 1468 | //       call site specific liveness information and then it makes | 
| Johannes Doerfert | 07a5c12 | 2019-08-28 14:09:14 +0000 | [diff] [blame] | 1469 | //       sense to specialize attributes for call sites instead of | 
|  | 1470 | //       redirecting requests to the callee. | 
|  | 1471 | llvm_unreachable("Abstract attributes for returned values are not " | 
|  | 1472 | "supported for call sites yet!"); | 
|  | 1473 | } | 
|  | 1474 |  | 
|  | 1475 | /// See AbstractAttribute::updateImpl(...). | 
|  | 1476 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 1477 | return indicatePessimisticFixpoint(); | 
|  | 1478 | } | 
|  | 1479 |  | 
|  | 1480 | /// See AbstractAttribute::trackStatistics() | 
|  | 1481 | void trackStatistics() const override {} | 
|  | 1482 | }; | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 1483 |  | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1484 | /// ------------------------ NoSync Function Attribute ------------------------- | 
|  | 1485 |  | 
| Johannes Doerfert | 344d038 | 2019-08-07 22:34:26 +0000 | [diff] [blame] | 1486 | struct AANoSyncImpl : AANoSync { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1487 | AANoSyncImpl(const IRPosition &IRP) : AANoSync(IRP) {} | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1488 |  | 
| Stefan Stipanovic | cb5ecae | 2019-07-12 18:34:06 +0000 | [diff] [blame] | 1489 | const std::string getAsStr() const override { | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1490 | return getAssumed() ? "nosync" : "may-sync"; | 
|  | 1491 | } | 
|  | 1492 |  | 
|  | 1493 | /// See AbstractAttribute::updateImpl(...). | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 1494 | ChangeStatus updateImpl(Attributor &A) override; | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1495 |  | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1496 | /// Helper function used to determine whether an instruction is non-relaxed | 
|  | 1497 | /// atomic. In other words, if an atomic instruction does not have unordered | 
|  | 1498 | /// or monotonic ordering | 
|  | 1499 | static bool isNonRelaxedAtomic(Instruction *I); | 
|  | 1500 |  | 
|  | 1501 | /// Helper function used to determine whether an instruction is volatile. | 
|  | 1502 | static bool isVolatile(Instruction *I); | 
|  | 1503 |  | 
| Johannes Doerfert | c7a1db3 | 2019-07-13 01:09:27 +0000 | [diff] [blame] | 1504 | /// Helper function uset to check if intrinsic is volatile (memcpy, memmove, | 
|  | 1505 | /// memset). | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1506 | static bool isNoSyncIntrinsic(Instruction *I); | 
|  | 1507 | }; | 
|  | 1508 |  | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 1509 | bool AANoSyncImpl::isNonRelaxedAtomic(Instruction *I) { | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1510 | if (!I->isAtomic()) | 
|  | 1511 | return false; | 
|  | 1512 |  | 
|  | 1513 | AtomicOrdering Ordering; | 
|  | 1514 | switch (I->getOpcode()) { | 
|  | 1515 | case Instruction::AtomicRMW: | 
|  | 1516 | Ordering = cast<AtomicRMWInst>(I)->getOrdering(); | 
|  | 1517 | break; | 
|  | 1518 | case Instruction::Store: | 
|  | 1519 | Ordering = cast<StoreInst>(I)->getOrdering(); | 
|  | 1520 | break; | 
|  | 1521 | case Instruction::Load: | 
|  | 1522 | Ordering = cast<LoadInst>(I)->getOrdering(); | 
|  | 1523 | break; | 
|  | 1524 | case Instruction::Fence: { | 
|  | 1525 | auto *FI = cast<FenceInst>(I); | 
|  | 1526 | if (FI->getSyncScopeID() == SyncScope::SingleThread) | 
|  | 1527 | return false; | 
|  | 1528 | Ordering = FI->getOrdering(); | 
|  | 1529 | break; | 
|  | 1530 | } | 
|  | 1531 | case Instruction::AtomicCmpXchg: { | 
|  | 1532 | AtomicOrdering Success = cast<AtomicCmpXchgInst>(I)->getSuccessOrdering(); | 
|  | 1533 | AtomicOrdering Failure = cast<AtomicCmpXchgInst>(I)->getFailureOrdering(); | 
|  | 1534 | // Only if both are relaxed, than it can be treated as relaxed. | 
|  | 1535 | // Otherwise it is non-relaxed. | 
|  | 1536 | if (Success != AtomicOrdering::Unordered && | 
|  | 1537 | Success != AtomicOrdering::Monotonic) | 
|  | 1538 | return true; | 
|  | 1539 | if (Failure != AtomicOrdering::Unordered && | 
|  | 1540 | Failure != AtomicOrdering::Monotonic) | 
|  | 1541 | return true; | 
|  | 1542 | return false; | 
|  | 1543 | } | 
|  | 1544 | default: | 
|  | 1545 | llvm_unreachable( | 
|  | 1546 | "New atomic operations need to be known in the attributor."); | 
|  | 1547 | } | 
|  | 1548 |  | 
|  | 1549 | // Relaxed. | 
|  | 1550 | if (Ordering == AtomicOrdering::Unordered || | 
|  | 1551 | Ordering == AtomicOrdering::Monotonic) | 
|  | 1552 | return false; | 
|  | 1553 | return true; | 
|  | 1554 | } | 
|  | 1555 |  | 
|  | 1556 | /// Checks if an intrinsic is nosync. Currently only checks mem* intrinsics. | 
|  | 1557 | /// FIXME: We should ipmrove the handling of intrinsics. | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 1558 | bool AANoSyncImpl::isNoSyncIntrinsic(Instruction *I) { | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1559 | if (auto *II = dyn_cast<IntrinsicInst>(I)) { | 
|  | 1560 | switch (II->getIntrinsicID()) { | 
|  | 1561 | /// Element wise atomic memory intrinsics are can only be unordered, | 
|  | 1562 | /// therefore nosync. | 
|  | 1563 | case Intrinsic::memset_element_unordered_atomic: | 
|  | 1564 | case Intrinsic::memmove_element_unordered_atomic: | 
|  | 1565 | case Intrinsic::memcpy_element_unordered_atomic: | 
|  | 1566 | return true; | 
|  | 1567 | case Intrinsic::memset: | 
|  | 1568 | case Intrinsic::memmove: | 
|  | 1569 | case Intrinsic::memcpy: | 
|  | 1570 | if (!cast<MemIntrinsic>(II)->isVolatile()) | 
|  | 1571 | return true; | 
|  | 1572 | return false; | 
|  | 1573 | default: | 
|  | 1574 | return false; | 
|  | 1575 | } | 
|  | 1576 | } | 
|  | 1577 | return false; | 
|  | 1578 | } | 
|  | 1579 |  | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 1580 | bool AANoSyncImpl::isVolatile(Instruction *I) { | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1581 | assert(!ImmutableCallSite(I) && !isa<CallBase>(I) && | 
|  | 1582 | "Calls should not be checked here"); | 
|  | 1583 |  | 
|  | 1584 | switch (I->getOpcode()) { | 
|  | 1585 | case Instruction::AtomicRMW: | 
|  | 1586 | return cast<AtomicRMWInst>(I)->isVolatile(); | 
|  | 1587 | case Instruction::Store: | 
|  | 1588 | return cast<StoreInst>(I)->isVolatile(); | 
|  | 1589 | case Instruction::Load: | 
|  | 1590 | return cast<LoadInst>(I)->isVolatile(); | 
|  | 1591 | case Instruction::AtomicCmpXchg: | 
|  | 1592 | return cast<AtomicCmpXchgInst>(I)->isVolatile(); | 
|  | 1593 | default: | 
|  | 1594 | return false; | 
|  | 1595 | } | 
|  | 1596 | } | 
|  | 1597 |  | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 1598 | ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) { | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1599 |  | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 1600 | auto CheckRWInstForNoSync = [&](Instruction &I) { | 
|  | 1601 | /// We are looking for volatile instructions or Non-Relaxed atomics. | 
| Pankaj Gode | b9a26a8 | 2019-11-22 14:46:43 +0530 | [diff] [blame] | 1602 | /// FIXME: We should improve the handling of intrinsics. | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 1603 |  | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 1604 | if (isa<IntrinsicInst>(&I) && isNoSyncIntrinsic(&I)) | 
|  | 1605 | return true; | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1606 |  | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1607 | if (ImmutableCallSite ICS = ImmutableCallSite(&I)) { | 
|  | 1608 | if (ICS.hasFnAttr(Attribute::NoSync)) | 
|  | 1609 | return true; | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1610 |  | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 1611 | const auto &NoSyncAA = | 
|  | 1612 | A.getAAFor<AANoSync>(*this, IRPosition::callsite_function(ICS)); | 
|  | 1613 | if (NoSyncAA.isAssumedNoSync()) | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1614 | return true; | 
|  | 1615 | return false; | 
|  | 1616 | } | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1617 |  | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 1618 | if (!isVolatile(&I) && !isNonRelaxedAtomic(&I)) | 
|  | 1619 | return true; | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1620 |  | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 1621 | return false; | 
|  | 1622 | }; | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1623 |  | 
| Johannes Doerfert | d0f6400 | 2019-08-06 00:32:43 +0000 | [diff] [blame] | 1624 | auto CheckForNoSync = [&](Instruction &I) { | 
|  | 1625 | // At this point we handled all read/write effects and they are all | 
|  | 1626 | // nosync, so they can be skipped. | 
|  | 1627 | if (I.mayReadOrWriteMemory()) | 
|  | 1628 | return true; | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1629 |  | 
| Johannes Doerfert | d0f6400 | 2019-08-06 00:32:43 +0000 | [diff] [blame] | 1630 | // non-convergent and readnone imply nosync. | 
|  | 1631 | return !ImmutableCallSite(&I).isConvergent(); | 
|  | 1632 | }; | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1633 |  | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1634 | if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this) || | 
|  | 1635 | !A.checkForAllCallLikeInstructions(CheckForNoSync, *this)) | 
| Johannes Doerfert | d0f6400 | 2019-08-06 00:32:43 +0000 | [diff] [blame] | 1636 | return indicatePessimisticFixpoint(); | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 1637 |  | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 1638 | return ChangeStatus::UNCHANGED; | 
|  | 1639 | } | 
|  | 1640 |  | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 1641 | struct AANoSyncFunction final : public AANoSyncImpl { | 
|  | 1642 | AANoSyncFunction(const IRPosition &IRP) : AANoSyncImpl(IRP) {} | 
|  | 1643 |  | 
|  | 1644 | /// See AbstractAttribute::trackStatistics() | 
|  | 1645 | void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) } | 
|  | 1646 | }; | 
|  | 1647 |  | 
|  | 1648 | /// NoSync attribute deduction for a call sites. | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 1649 | struct AANoSyncCallSite final : AANoSyncImpl { | 
|  | 1650 | AANoSyncCallSite(const IRPosition &IRP) : AANoSyncImpl(IRP) {} | 
|  | 1651 |  | 
|  | 1652 | /// See AbstractAttribute::initialize(...). | 
|  | 1653 | void initialize(Attributor &A) override { | 
|  | 1654 | AANoSyncImpl::initialize(A); | 
|  | 1655 | Function *F = getAssociatedFunction(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 1656 | if (!F) | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 1657 | indicatePessimisticFixpoint(); | 
|  | 1658 | } | 
|  | 1659 |  | 
|  | 1660 | /// See AbstractAttribute::updateImpl(...). | 
|  | 1661 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 1662 | // TODO: Once we have call site specific value information we can provide | 
|  | 1663 | //       call site specific liveness information and then it makes | 
|  | 1664 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 1665 | //       redirecting requests to the callee argument. | 
|  | 1666 | Function *F = getAssociatedFunction(); | 
|  | 1667 | const IRPosition &FnPos = IRPosition::function(*F); | 
|  | 1668 | auto &FnAA = A.getAAFor<AANoSync>(*this, FnPos); | 
|  | 1669 | return clampStateAndIndicateChange( | 
|  | 1670 | getState(), static_cast<const AANoSync::StateType &>(FnAA.getState())); | 
|  | 1671 | } | 
|  | 1672 |  | 
|  | 1673 | /// See AbstractAttribute::trackStatistics() | 
|  | 1674 | void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nosync); } | 
|  | 1675 | }; | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 1676 |  | 
| Hideto Ueno | 65bbaf9 | 2019-07-12 17:38:51 +0000 | [diff] [blame] | 1677 | /// ------------------------ No-Free Attributes ---------------------------- | 
|  | 1678 |  | 
| Johannes Doerfert | 344d038 | 2019-08-07 22:34:26 +0000 | [diff] [blame] | 1679 | struct AANoFreeImpl : public AANoFree { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1680 | AANoFreeImpl(const IRPosition &IRP) : AANoFree(IRP) {} | 
| Hideto Ueno | 65bbaf9 | 2019-07-12 17:38:51 +0000 | [diff] [blame] | 1681 |  | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 1682 | /// See AbstractAttribute::updateImpl(...). | 
|  | 1683 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 1684 | auto CheckForNoFree = [&](Instruction &I) { | 
|  | 1685 | ImmutableCallSite ICS(&I); | 
|  | 1686 | if (ICS.hasFnAttr(Attribute::NoFree)) | 
|  | 1687 | return true; | 
|  | 1688 |  | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 1689 | const auto &NoFreeAA = | 
|  | 1690 | A.getAAFor<AANoFree>(*this, IRPosition::callsite_function(ICS)); | 
|  | 1691 | return NoFreeAA.isAssumedNoFree(); | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 1692 | }; | 
|  | 1693 |  | 
|  | 1694 | if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this)) | 
|  | 1695 | return indicatePessimisticFixpoint(); | 
|  | 1696 | return ChangeStatus::UNCHANGED; | 
|  | 1697 | } | 
|  | 1698 |  | 
| Hideto Ueno | 65bbaf9 | 2019-07-12 17:38:51 +0000 | [diff] [blame] | 1699 | /// See AbstractAttribute::getAsStr(). | 
|  | 1700 | const std::string getAsStr() const override { | 
|  | 1701 | return getAssumed() ? "nofree" : "may-free"; | 
|  | 1702 | } | 
| Hideto Ueno | 65bbaf9 | 2019-07-12 17:38:51 +0000 | [diff] [blame] | 1703 | }; | 
|  | 1704 |  | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 1705 | struct AANoFreeFunction final : public AANoFreeImpl { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1706 | AANoFreeFunction(const IRPosition &IRP) : AANoFreeImpl(IRP) {} | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 1707 |  | 
|  | 1708 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 1709 | void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) } | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 1710 | }; | 
|  | 1711 |  | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 1712 | /// NoFree attribute deduction for a call sites. | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 1713 | struct AANoFreeCallSite final : AANoFreeImpl { | 
|  | 1714 | AANoFreeCallSite(const IRPosition &IRP) : AANoFreeImpl(IRP) {} | 
|  | 1715 |  | 
|  | 1716 | /// See AbstractAttribute::initialize(...). | 
|  | 1717 | void initialize(Attributor &A) override { | 
|  | 1718 | AANoFreeImpl::initialize(A); | 
|  | 1719 | Function *F = getAssociatedFunction(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 1720 | if (!F) | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 1721 | indicatePessimisticFixpoint(); | 
|  | 1722 | } | 
|  | 1723 |  | 
|  | 1724 | /// See AbstractAttribute::updateImpl(...). | 
|  | 1725 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 1726 | // TODO: Once we have call site specific value information we can provide | 
|  | 1727 | //       call site specific liveness information and then it makes | 
|  | 1728 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 1729 | //       redirecting requests to the callee argument. | 
|  | 1730 | Function *F = getAssociatedFunction(); | 
|  | 1731 | const IRPosition &FnPos = IRPosition::function(*F); | 
|  | 1732 | auto &FnAA = A.getAAFor<AANoFree>(*this, FnPos); | 
|  | 1733 | return clampStateAndIndicateChange( | 
|  | 1734 | getState(), static_cast<const AANoFree::StateType &>(FnAA.getState())); | 
|  | 1735 | } | 
|  | 1736 |  | 
|  | 1737 | /// See AbstractAttribute::trackStatistics() | 
|  | 1738 | void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nofree); } | 
|  | 1739 | }; | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 1740 |  | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 1741 | /// NoFree attribute for floating values. | 
|  | 1742 | struct AANoFreeFloating : AANoFreeImpl { | 
|  | 1743 | AANoFreeFloating(const IRPosition &IRP) : AANoFreeImpl(IRP) {} | 
|  | 1744 |  | 
|  | 1745 | /// See AbstractAttribute::trackStatistics() | 
|  | 1746 | void trackStatistics() const override{STATS_DECLTRACK_FLOATING_ATTR(nofree)} | 
|  | 1747 |  | 
|  | 1748 | /// See Abstract Attribute::updateImpl(...). | 
|  | 1749 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 1750 | const IRPosition &IRP = getIRPosition(); | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 1751 |  | 
|  | 1752 | const auto &NoFreeAA = | 
|  | 1753 | A.getAAFor<AANoFree>(*this, IRPosition::function_scope(IRP)); | 
|  | 1754 | if (NoFreeAA.isAssumedNoFree()) | 
|  | 1755 | return ChangeStatus::UNCHANGED; | 
|  | 1756 |  | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 1757 | Value &AssociatedValue = getIRPosition().getAssociatedValue(); | 
| Hideto Ueno | 63599bd | 2019-12-12 12:26:09 +0000 | [diff] [blame] | 1758 | auto Pred = [&](const Use &U, bool &Follow) -> bool { | 
|  | 1759 | Instruction *UserI = cast<Instruction>(U.getUser()); | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 1760 | if (auto *CB = dyn_cast<CallBase>(UserI)) { | 
| Hideto Ueno | 63599bd | 2019-12-12 12:26:09 +0000 | [diff] [blame] | 1761 | if (CB->isBundleOperand(&U)) | 
|  | 1762 | return false; | 
|  | 1763 | if (!CB->isArgOperand(&U)) | 
|  | 1764 | return true; | 
|  | 1765 | unsigned ArgNo = CB->getArgOperandNo(&U); | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 1766 |  | 
|  | 1767 | const auto &NoFreeArg = A.getAAFor<AANoFree>( | 
|  | 1768 | *this, IRPosition::callsite_argument(*CB, ArgNo)); | 
| Hideto Ueno | 63599bd | 2019-12-12 12:26:09 +0000 | [diff] [blame] | 1769 | return NoFreeArg.isAssumedNoFree(); | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 1770 | } | 
|  | 1771 |  | 
|  | 1772 | if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) || | 
|  | 1773 | isa<PHINode>(UserI) || isa<SelectInst>(UserI)) { | 
| Hideto Ueno | 63599bd | 2019-12-12 12:26:09 +0000 | [diff] [blame] | 1774 | Follow = true; | 
|  | 1775 | return true; | 
| Hideto Ueno | 4ecf255 | 2019-12-12 13:42:40 +0000 | [diff] [blame] | 1776 | } | 
| Johannes Doerfert | f955539 | 2020-01-10 14:49:45 -0600 | [diff] [blame] | 1777 | if (isa<ReturnInst>(UserI)) | 
|  | 1778 | return true; | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 1779 |  | 
|  | 1780 | // Unknown user. | 
| Hideto Ueno | 63599bd | 2019-12-12 12:26:09 +0000 | [diff] [blame] | 1781 | return false; | 
|  | 1782 | }; | 
|  | 1783 | if (!A.checkForAllUses(Pred, *this, AssociatedValue)) | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 1784 | return indicatePessimisticFixpoint(); | 
| Hideto Ueno | 63599bd | 2019-12-12 12:26:09 +0000 | [diff] [blame] | 1785 |  | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 1786 | return ChangeStatus::UNCHANGED; | 
|  | 1787 | } | 
|  | 1788 | }; | 
|  | 1789 |  | 
|  | 1790 | /// NoFree attribute for a call site argument. | 
|  | 1791 | struct AANoFreeArgument final : AANoFreeFloating { | 
|  | 1792 | AANoFreeArgument(const IRPosition &IRP) : AANoFreeFloating(IRP) {} | 
|  | 1793 |  | 
|  | 1794 | /// See AbstractAttribute::trackStatistics() | 
|  | 1795 | void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofree) } | 
|  | 1796 | }; | 
|  | 1797 |  | 
|  | 1798 | /// NoFree attribute for call site arguments. | 
|  | 1799 | struct AANoFreeCallSiteArgument final : AANoFreeFloating { | 
|  | 1800 | AANoFreeCallSiteArgument(const IRPosition &IRP) : AANoFreeFloating(IRP) {} | 
|  | 1801 |  | 
|  | 1802 | /// See AbstractAttribute::updateImpl(...). | 
|  | 1803 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 1804 | // TODO: Once we have call site specific value information we can provide | 
|  | 1805 | //       call site specific liveness information and then it makes | 
|  | 1806 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 1807 | //       redirecting requests to the callee argument. | 
|  | 1808 | Argument *Arg = getAssociatedArgument(); | 
|  | 1809 | if (!Arg) | 
|  | 1810 | return indicatePessimisticFixpoint(); | 
|  | 1811 | const IRPosition &ArgPos = IRPosition::argument(*Arg); | 
|  | 1812 | auto &ArgAA = A.getAAFor<AANoFree>(*this, ArgPos); | 
|  | 1813 | return clampStateAndIndicateChange( | 
|  | 1814 | getState(), static_cast<const AANoFree::StateType &>(ArgAA.getState())); | 
|  | 1815 | } | 
|  | 1816 |  | 
|  | 1817 | /// See AbstractAttribute::trackStatistics() | 
|  | 1818 | void trackStatistics() const override{STATS_DECLTRACK_CSARG_ATTR(nofree)}; | 
|  | 1819 | }; | 
|  | 1820 |  | 
|  | 1821 | /// NoFree attribute for function return value. | 
|  | 1822 | struct AANoFreeReturned final : AANoFreeFloating { | 
|  | 1823 | AANoFreeReturned(const IRPosition &IRP) : AANoFreeFloating(IRP) { | 
|  | 1824 | llvm_unreachable("NoFree is not applicable to function returns!"); | 
|  | 1825 | } | 
|  | 1826 |  | 
|  | 1827 | /// See AbstractAttribute::initialize(...). | 
|  | 1828 | void initialize(Attributor &A) override { | 
|  | 1829 | llvm_unreachable("NoFree is not applicable to function returns!"); | 
|  | 1830 | } | 
|  | 1831 |  | 
|  | 1832 | /// See AbstractAttribute::updateImpl(...). | 
|  | 1833 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 1834 | llvm_unreachable("NoFree is not applicable to function returns!"); | 
|  | 1835 | } | 
|  | 1836 |  | 
|  | 1837 | /// See AbstractAttribute::trackStatistics() | 
|  | 1838 | void trackStatistics() const override {} | 
|  | 1839 | }; | 
|  | 1840 |  | 
|  | 1841 | /// NoFree attribute deduction for a call site return value. | 
|  | 1842 | struct AANoFreeCallSiteReturned final : AANoFreeFloating { | 
|  | 1843 | AANoFreeCallSiteReturned(const IRPosition &IRP) : AANoFreeFloating(IRP) {} | 
|  | 1844 |  | 
|  | 1845 | ChangeStatus manifest(Attributor &A) override { | 
|  | 1846 | return ChangeStatus::UNCHANGED; | 
|  | 1847 | } | 
|  | 1848 | /// See AbstractAttribute::trackStatistics() | 
|  | 1849 | void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nofree) } | 
|  | 1850 | }; | 
|  | 1851 |  | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 1852 | /// ------------------------ NonNull Argument Attribute ------------------------ | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1853 | static int64_t getKnownNonNullAndDerefBytesForUse( | 
|  | 1854 | Attributor &A, AbstractAttribute &QueryingAA, Value &AssociatedValue, | 
|  | 1855 | const Use *U, const Instruction *I, bool &IsNonNull, bool &TrackUse) { | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1856 | TrackUse = false; | 
|  | 1857 |  | 
| Johannes Doerfert | db6efb0 | 2019-10-13 20:40:10 +0000 | [diff] [blame] | 1858 | const Value *UseV = U->get(); | 
|  | 1859 | if (!UseV->getType()->isPointerTy()) | 
|  | 1860 | return 0; | 
|  | 1861 |  | 
|  | 1862 | Type *PtrTy = UseV->getType(); | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1863 | const Function *F = I->getFunction(); | 
| Johannes Doerfert | db6efb0 | 2019-10-13 20:40:10 +0000 | [diff] [blame] | 1864 | bool NullPointerIsDefined = | 
|  | 1865 | F ? llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace()) : true; | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1866 | const DataLayout &DL = A.getInfoCache().getDL(); | 
|  | 1867 | if (ImmutableCallSite ICS = ImmutableCallSite(I)) { | 
|  | 1868 | if (ICS.isBundleOperand(U)) | 
|  | 1869 | return 0; | 
|  | 1870 |  | 
|  | 1871 | if (ICS.isCallee(U)) { | 
|  | 1872 | IsNonNull |= !NullPointerIsDefined; | 
|  | 1873 | return 0; | 
|  | 1874 | } | 
|  | 1875 |  | 
|  | 1876 | unsigned ArgNo = ICS.getArgumentNo(U); | 
|  | 1877 | IRPosition IRP = IRPosition::callsite_argument(ICS, ArgNo); | 
| Johannes Doerfert | 77a6b35 | 2019-11-02 14:47:45 -0500 | [diff] [blame] | 1878 | // As long as we only use known information there is no need to track | 
|  | 1879 | // dependences here. | 
|  | 1880 | auto &DerefAA = A.getAAFor<AADereferenceable>(QueryingAA, IRP, | 
|  | 1881 | /* TrackDependence */ false); | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1882 | IsNonNull |= DerefAA.isKnownNonNull(); | 
|  | 1883 | return DerefAA.getKnownDereferenceableBytes(); | 
|  | 1884 | } | 
|  | 1885 |  | 
| Johannes Doerfert | eb4f41d | 2019-10-30 17:21:53 -0500 | [diff] [blame] | 1886 | // We need to follow common pointer manipulation uses to the accesses they | 
|  | 1887 | // feed into. We can try to be smart to avoid looking through things we do not | 
|  | 1888 | // like for now, e.g., non-inbounds GEPs. | 
|  | 1889 | if (isa<CastInst>(I)) { | 
|  | 1890 | TrackUse = true; | 
|  | 1891 | return 0; | 
|  | 1892 | } | 
|  | 1893 | if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) | 
| Hideto Ueno | 0f4383f | 2019-11-27 14:41:12 +0000 | [diff] [blame] | 1894 | if (GEP->hasAllConstantIndices()) { | 
| Johannes Doerfert | eb4f41d | 2019-10-30 17:21:53 -0500 | [diff] [blame] | 1895 | TrackUse = true; | 
|  | 1896 | return 0; | 
|  | 1897 | } | 
|  | 1898 |  | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1899 | int64_t Offset; | 
|  | 1900 | if (const Value *Base = getBasePointerOfAccessPointerOperand(I, Offset, DL)) { | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 1901 | if (Base == &AssociatedValue && | 
| Johannes Doerfert | b6dbd0f | 2020-01-26 02:49:58 -0600 | [diff] [blame] | 1902 | getPointerOperand(I, /* AllowVolatile */ false) == UseV) { | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1903 | int64_t DerefBytes = | 
| Johannes Doerfert | eb4f41d | 2019-10-30 17:21:53 -0500 | [diff] [blame] | 1904 | (int64_t)DL.getTypeStoreSize(PtrTy->getPointerElementType()) + Offset; | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1905 |  | 
|  | 1906 | IsNonNull |= !NullPointerIsDefined; | 
| Johannes Doerfert | eb4f41d | 2019-10-30 17:21:53 -0500 | [diff] [blame] | 1907 | return std::max(int64_t(0), DerefBytes); | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1908 | } | 
|  | 1909 | } | 
| Hideto Ueno | 0f4383f | 2019-11-27 14:41:12 +0000 | [diff] [blame] | 1910 |  | 
|  | 1911 | /// Corner case when an offset is 0. | 
|  | 1912 | if (const Value *Base = getBasePointerOfAccessPointerOperand( | 
|  | 1913 | I, Offset, DL, /*AllowNonInbounds*/ true)) { | 
|  | 1914 | if (Offset == 0 && Base == &AssociatedValue && | 
| Johannes Doerfert | b6dbd0f | 2020-01-26 02:49:58 -0600 | [diff] [blame] | 1915 | getPointerOperand(I, /* AllowVolatile */ false) == UseV) { | 
| Hideto Ueno | 0f4383f | 2019-11-27 14:41:12 +0000 | [diff] [blame] | 1916 | int64_t DerefBytes = | 
|  | 1917 | (int64_t)DL.getTypeStoreSize(PtrTy->getPointerElementType()); | 
|  | 1918 | IsNonNull |= !NullPointerIsDefined; | 
|  | 1919 | return std::max(int64_t(0), DerefBytes); | 
|  | 1920 | } | 
|  | 1921 | } | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1922 |  | 
|  | 1923 | return 0; | 
|  | 1924 | } | 
| Johannes Doerfert | db6efb0 | 2019-10-13 20:40:10 +0000 | [diff] [blame] | 1925 |  | 
| Johannes Doerfert | 344d038 | 2019-08-07 22:34:26 +0000 | [diff] [blame] | 1926 | struct AANonNullImpl : AANonNull { | 
| Johannes Doerfert | d82385b | 2019-10-13 20:48:26 +0000 | [diff] [blame] | 1927 | AANonNullImpl(const IRPosition &IRP) | 
|  | 1928 | : AANonNull(IRP), | 
|  | 1929 | NullIsDefined(NullPointerIsDefined( | 
|  | 1930 | getAnchorScope(), | 
|  | 1931 | getAssociatedValue().getType()->getPointerAddressSpace())) {} | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 1932 |  | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1933 | /// See AbstractAttribute::initialize(...). | 
|  | 1934 | void initialize(Attributor &A) override { | 
| Johannes Doerfert | d82385b | 2019-10-13 20:48:26 +0000 | [diff] [blame] | 1935 | if (!NullIsDefined && | 
|  | 1936 | hasAttr({Attribute::NonNull, Attribute::Dereferenceable})) | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1937 | indicateOptimisticFixpoint(); | 
| Johannes Doerfert | eb4f41d | 2019-10-30 17:21:53 -0500 | [diff] [blame] | 1938 | else if (isa<ConstantPointerNull>(getAssociatedValue())) | 
|  | 1939 | indicatePessimisticFixpoint(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 1940 | else | 
|  | 1941 | AANonNull::initialize(A); | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 1942 | } | 
|  | 1943 |  | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1944 | /// See AAFromMustBeExecutedContext | 
|  | 1945 | bool followUse(Attributor &A, const Use *U, const Instruction *I) { | 
|  | 1946 | bool IsNonNull = false; | 
|  | 1947 | bool TrackUse = false; | 
|  | 1948 | getKnownNonNullAndDerefBytesForUse(A, *this, getAssociatedValue(), U, I, | 
|  | 1949 | IsNonNull, TrackUse); | 
| Johannes Doerfert | 1a74645 | 2019-10-20 22:28:49 -0500 | [diff] [blame] | 1950 | setKnown(IsNonNull); | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1951 | return TrackUse; | 
|  | 1952 | } | 
|  | 1953 |  | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 1954 | /// See AbstractAttribute::getAsStr(). | 
|  | 1955 | const std::string getAsStr() const override { | 
|  | 1956 | return getAssumed() ? "nonnull" : "may-null"; | 
|  | 1957 | } | 
| Johannes Doerfert | d82385b | 2019-10-13 20:48:26 +0000 | [diff] [blame] | 1958 |  | 
|  | 1959 | /// Flag to determine if the underlying value can be null and still allow | 
|  | 1960 | /// valid accesses. | 
|  | 1961 | const bool NullIsDefined; | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 1962 | }; | 
|  | 1963 |  | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 1964 | /// NonNull attribute for a floating value. | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1965 | struct AANonNullFloating | 
|  | 1966 | : AAFromMustBeExecutedContext<AANonNull, AANonNullImpl> { | 
|  | 1967 | using Base = AAFromMustBeExecutedContext<AANonNull, AANonNullImpl>; | 
|  | 1968 | AANonNullFloating(const IRPosition &IRP) : Base(IRP) {} | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 1969 |  | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 1970 | /// See AbstractAttribute::updateImpl(...). | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 1971 | ChangeStatus updateImpl(Attributor &A) override { | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 1972 | ChangeStatus Change = Base::updateImpl(A); | 
|  | 1973 | if (isKnownNonNull()) | 
|  | 1974 | return Change; | 
|  | 1975 |  | 
| Johannes Doerfert | d82385b | 2019-10-13 20:48:26 +0000 | [diff] [blame] | 1976 | if (!NullIsDefined) { | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 1977 | const auto &DerefAA = | 
|  | 1978 | A.getAAFor<AADereferenceable>(*this, getIRPosition()); | 
| Johannes Doerfert | d82385b | 2019-10-13 20:48:26 +0000 | [diff] [blame] | 1979 | if (DerefAA.getAssumedDereferenceableBytes()) | 
|  | 1980 | return Change; | 
|  | 1981 | } | 
|  | 1982 |  | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 1983 | const DataLayout &DL = A.getDataLayout(); | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 1984 |  | 
| Johannes Doerfert | 2d6d651 | 2019-10-29 11:46:00 -0500 | [diff] [blame] | 1985 | DominatorTree *DT = nullptr; | 
|  | 1986 | InformationCache &InfoCache = A.getInfoCache(); | 
|  | 1987 | if (const Function *Fn = getAnchorScope()) | 
|  | 1988 | DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*Fn); | 
|  | 1989 |  | 
| Johannes Doerfert | 1a74645 | 2019-10-20 22:28:49 -0500 | [diff] [blame] | 1990 | auto VisitValueCB = [&](Value &V, AANonNull::StateType &T, | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 1991 | bool Stripped) -> bool { | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 1992 | const auto &AA = A.getAAFor<AANonNull>(*this, IRPosition::value(V)); | 
|  | 1993 | if (!Stripped && this == &AA) { | 
| Johannes Doerfert | 2d6d651 | 2019-10-29 11:46:00 -0500 | [diff] [blame] | 1994 | if (!isKnownNonZero(&V, DL, 0, /* TODO: AC */ nullptr, getCtxI(), DT)) | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 1995 | T.indicatePessimisticFixpoint(); | 
|  | 1996 | } else { | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 1997 | // Use abstract attribute information. | 
|  | 1998 | const AANonNull::StateType &NS = | 
|  | 1999 | static_cast<const AANonNull::StateType &>(AA.getState()); | 
|  | 2000 | T ^= NS; | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 2001 | } | 
|  | 2002 | return T.isValidState(); | 
|  | 2003 | }; | 
|  | 2004 |  | 
|  | 2005 | StateType T; | 
|  | 2006 | if (!genericValueTraversal<AANonNull, StateType>(A, getIRPosition(), *this, | 
|  | 2007 | T, VisitValueCB)) | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2008 | return indicatePessimisticFixpoint(); | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 2009 |  | 
|  | 2010 | return clampStateAndIndicateChange(getState(), T); | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2011 | } | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 2012 |  | 
|  | 2013 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 2014 | void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) } | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 2015 | }; | 
|  | 2016 |  | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 2017 | /// NonNull attribute for function return value. | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 2018 | struct AANonNullReturned final | 
|  | 2019 | : AAReturnedFromReturnedValues<AANonNull, AANonNullImpl> { | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 2020 | AANonNullReturned(const IRPosition &IRP) | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 2021 | : AAReturnedFromReturnedValues<AANonNull, AANonNullImpl>(IRP) {} | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 2022 |  | 
|  | 2023 | /// See AbstractAttribute::trackStatistics() | 
|  | 2024 | void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) } | 
|  | 2025 | }; | 
|  | 2026 |  | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 2027 | /// NonNull attribute for function argument. | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 2028 | struct AANonNullArgument final | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 2029 | : AAArgumentFromCallSiteArgumentsAndMustBeExecutedContext<AANonNull, | 
|  | 2030 | AANonNullImpl> { | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 2031 | AANonNullArgument(const IRPosition &IRP) | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 2032 | : AAArgumentFromCallSiteArgumentsAndMustBeExecutedContext<AANonNull, | 
|  | 2033 | AANonNullImpl>( | 
|  | 2034 | IRP) {} | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 2035 |  | 
|  | 2036 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 2037 | void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) } | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 2038 | }; | 
|  | 2039 |  | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 2040 | struct AANonNullCallSiteArgument final : AANonNullFloating { | 
|  | 2041 | AANonNullCallSiteArgument(const IRPosition &IRP) : AANonNullFloating(IRP) {} | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 2042 |  | 
|  | 2043 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 1aac182 | 2019-08-29 01:26:09 +0000 | [diff] [blame] | 2044 | void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) } | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 2045 | }; | 
| Johannes Doerfert | 007153e | 2019-08-05 23:26:06 +0000 | [diff] [blame] | 2046 |  | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 2047 | /// NonNull attribute for a call site return position. | 
|  | 2048 | struct AANonNullCallSiteReturned final | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 2049 | : AACallSiteReturnedFromReturnedAndMustBeExecutedContext<AANonNull, | 
|  | 2050 | AANonNullImpl> { | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 2051 | AANonNullCallSiteReturned(const IRPosition &IRP) | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 2052 | : AACallSiteReturnedFromReturnedAndMustBeExecutedContext<AANonNull, | 
|  | 2053 | AANonNullImpl>( | 
|  | 2054 | IRP) {} | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 2055 |  | 
|  | 2056 | /// See AbstractAttribute::trackStatistics() | 
|  | 2057 | void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull) } | 
|  | 2058 | }; | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 2059 |  | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2060 | /// ------------------------ No-Recurse Attributes ---------------------------- | 
|  | 2061 |  | 
|  | 2062 | struct AANoRecurseImpl : public AANoRecurse { | 
|  | 2063 | AANoRecurseImpl(const IRPosition &IRP) : AANoRecurse(IRP) {} | 
|  | 2064 |  | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2065 | /// See AbstractAttribute::getAsStr() | 
|  | 2066 | const std::string getAsStr() const override { | 
|  | 2067 | return getAssumed() ? "norecurse" : "may-recurse"; | 
|  | 2068 | } | 
|  | 2069 | }; | 
|  | 2070 |  | 
|  | 2071 | struct AANoRecurseFunction final : AANoRecurseImpl { | 
|  | 2072 | AANoRecurseFunction(const IRPosition &IRP) : AANoRecurseImpl(IRP) {} | 
|  | 2073 |  | 
| Hideto Ueno | 63f6066 | 2019-09-21 15:13:19 +0000 | [diff] [blame] | 2074 | /// See AbstractAttribute::initialize(...). | 
|  | 2075 | void initialize(Attributor &A) override { | 
|  | 2076 | AANoRecurseImpl::initialize(A); | 
|  | 2077 | if (const Function *F = getAnchorScope()) | 
| Johannes Doerfert | 26d02b0 | 2019-12-30 16:15:38 -0600 | [diff] [blame] | 2078 | if (A.getInfoCache().getSccSize(*F) != 1) | 
|  | 2079 | indicatePessimisticFixpoint(); | 
| Hideto Ueno | 63f6066 | 2019-09-21 15:13:19 +0000 | [diff] [blame] | 2080 | } | 
|  | 2081 |  | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2082 | /// See AbstractAttribute::updateImpl(...). | 
|  | 2083 | ChangeStatus updateImpl(Attributor &A) override { | 
| Hideto Ueno | 63f6066 | 2019-09-21 15:13:19 +0000 | [diff] [blame] | 2084 |  | 
| Johannes Doerfert | 26d02b0 | 2019-12-30 16:15:38 -0600 | [diff] [blame] | 2085 | // If all live call sites are known to be no-recurse, we are as well. | 
|  | 2086 | auto CallSitePred = [&](AbstractCallSite ACS) { | 
|  | 2087 | const auto &NoRecurseAA = A.getAAFor<AANoRecurse>( | 
|  | 2088 | *this, IRPosition::function(*ACS.getInstruction()->getFunction()), | 
|  | 2089 | /* TrackDependence */ false, DepClassTy::OPTIONAL); | 
|  | 2090 | return NoRecurseAA.isKnownNoRecurse(); | 
|  | 2091 | }; | 
|  | 2092 | bool AllCallSitesKnown; | 
|  | 2093 | if (A.checkForAllCallSites(CallSitePred, *this, true, AllCallSitesKnown)) { | 
|  | 2094 | // If we know all call sites and all are known no-recurse, we are done. | 
|  | 2095 | // If all known call sites, which might not be all that exist, are known | 
|  | 2096 | // to be no-recurse, we are not done but we can continue to assume | 
|  | 2097 | // no-recurse. If one of the call sites we have not visited will become | 
|  | 2098 | // live, another update is triggered. | 
|  | 2099 | if (AllCallSitesKnown) | 
|  | 2100 | indicateOptimisticFixpoint(); | 
|  | 2101 | return ChangeStatus::UNCHANGED; | 
|  | 2102 | } | 
|  | 2103 |  | 
|  | 2104 | // If the above check does not hold anymore we look at the calls. | 
| Hideto Ueno | 63f6066 | 2019-09-21 15:13:19 +0000 | [diff] [blame] | 2105 | auto CheckForNoRecurse = [&](Instruction &I) { | 
|  | 2106 | ImmutableCallSite ICS(&I); | 
|  | 2107 | if (ICS.hasFnAttr(Attribute::NoRecurse)) | 
|  | 2108 | return true; | 
|  | 2109 |  | 
|  | 2110 | const auto &NoRecurseAA = | 
|  | 2111 | A.getAAFor<AANoRecurse>(*this, IRPosition::callsite_function(ICS)); | 
|  | 2112 | if (!NoRecurseAA.isAssumedNoRecurse()) | 
|  | 2113 | return false; | 
|  | 2114 |  | 
|  | 2115 | // Recursion to the same function | 
|  | 2116 | if (ICS.getCalledFunction() == getAnchorScope()) | 
|  | 2117 | return false; | 
|  | 2118 |  | 
|  | 2119 | return true; | 
|  | 2120 | }; | 
|  | 2121 |  | 
|  | 2122 | if (!A.checkForAllCallLikeInstructions(CheckForNoRecurse, *this)) | 
|  | 2123 | return indicatePessimisticFixpoint(); | 
|  | 2124 | return ChangeStatus::UNCHANGED; | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2125 | } | 
|  | 2126 |  | 
|  | 2127 | void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) } | 
|  | 2128 | }; | 
|  | 2129 |  | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 2130 | /// NoRecurse attribute deduction for a call sites. | 
|  | 2131 | struct AANoRecurseCallSite final : AANoRecurseImpl { | 
|  | 2132 | AANoRecurseCallSite(const IRPosition &IRP) : AANoRecurseImpl(IRP) {} | 
|  | 2133 |  | 
|  | 2134 | /// See AbstractAttribute::initialize(...). | 
|  | 2135 | void initialize(Attributor &A) override { | 
|  | 2136 | AANoRecurseImpl::initialize(A); | 
|  | 2137 | Function *F = getAssociatedFunction(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 2138 | if (!F) | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 2139 | indicatePessimisticFixpoint(); | 
|  | 2140 | } | 
|  | 2141 |  | 
|  | 2142 | /// See AbstractAttribute::updateImpl(...). | 
|  | 2143 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 2144 | // TODO: Once we have call site specific value information we can provide | 
|  | 2145 | //       call site specific liveness information and then it makes | 
|  | 2146 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 2147 | //       redirecting requests to the callee argument. | 
|  | 2148 | Function *F = getAssociatedFunction(); | 
|  | 2149 | const IRPosition &FnPos = IRPosition::function(*F); | 
|  | 2150 | auto &FnAA = A.getAAFor<AANoRecurse>(*this, FnPos); | 
|  | 2151 | return clampStateAndIndicateChange( | 
|  | 2152 | getState(), | 
|  | 2153 | static_cast<const AANoRecurse::StateType &>(FnAA.getState())); | 
|  | 2154 | } | 
|  | 2155 |  | 
|  | 2156 | /// See AbstractAttribute::trackStatistics() | 
|  | 2157 | void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(norecurse); } | 
|  | 2158 | }; | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2159 |  | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2160 | /// -------------------- Undefined-Behavior Attributes ------------------------ | 
|  | 2161 |  | 
|  | 2162 | struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior { | 
|  | 2163 | AAUndefinedBehaviorImpl(const IRPosition &IRP) : AAUndefinedBehavior(IRP) {} | 
|  | 2164 |  | 
|  | 2165 | /// See AbstractAttribute::updateImpl(...). | 
| Johannes Doerfert | 5732f56 | 2019-12-24 19:25:08 -0600 | [diff] [blame] | 2166 | // through a pointer (i.e. also branches etc.) | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2167 | ChangeStatus updateImpl(Attributor &A) override { | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2168 | const size_t UBPrevSize = KnownUBInsts.size(); | 
|  | 2169 | const size_t NoUBPrevSize = AssumedNoUBInsts.size(); | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2170 |  | 
| Johannes Doerfert | 5732f56 | 2019-12-24 19:25:08 -0600 | [diff] [blame] | 2171 | auto InspectMemAccessInstForUB = [&](Instruction &I) { | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2172 | // Skip instructions that are already saved. | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2173 | if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I)) | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2174 | return true; | 
|  | 2175 |  | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2176 | // If we reach here, we know we have an instruction | 
|  | 2177 | // that accesses memory through a pointer operand, | 
|  | 2178 | // for which getPointerOperand() should give it to us. | 
| Johannes Doerfert | b6dbd0f | 2020-01-26 02:49:58 -0600 | [diff] [blame] | 2179 | const Value *PtrOp = getPointerOperand(&I, /* AllowVolatile */ true); | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2180 | assert(PtrOp && | 
|  | 2181 | "Expected pointer operand of memory accessing instruction"); | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2182 |  | 
| Johannes Doerfert | 5732f56 | 2019-12-24 19:25:08 -0600 | [diff] [blame] | 2183 | // A memory access through a pointer is considered UB | 
|  | 2184 | // only if the pointer has constant null value. | 
|  | 2185 | // TODO: Expand it to not only check constant values. | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2186 | if (!isa<ConstantPointerNull>(PtrOp)) { | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2187 | AssumedNoUBInsts.insert(&I); | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2188 | return true; | 
|  | 2189 | } | 
| Johannes Doerfert | 5732f56 | 2019-12-24 19:25:08 -0600 | [diff] [blame] | 2190 | const Type *PtrTy = PtrOp->getType(); | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2191 |  | 
| Johannes Doerfert | 5732f56 | 2019-12-24 19:25:08 -0600 | [diff] [blame] | 2192 | // Because we only consider instructions inside functions, | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2193 | // assume that a parent function exists. | 
|  | 2194 | const Function *F = I.getFunction(); | 
|  | 2195 |  | 
| Johannes Doerfert | 5732f56 | 2019-12-24 19:25:08 -0600 | [diff] [blame] | 2196 | // A memory access using constant null pointer is only considered UB | 
|  | 2197 | // if null pointer is _not_ defined for the target platform. | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2198 | if (llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace())) | 
|  | 2199 | AssumedNoUBInsts.insert(&I); | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2200 | else | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2201 | KnownUBInsts.insert(&I); | 
|  | 2202 | return true; | 
|  | 2203 | }; | 
|  | 2204 |  | 
|  | 2205 | auto InspectBrInstForUB = [&](Instruction &I) { | 
|  | 2206 | // A conditional branch instruction is considered UB if it has `undef` | 
|  | 2207 | // condition. | 
|  | 2208 |  | 
|  | 2209 | // Skip instructions that are already saved. | 
|  | 2210 | if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I)) | 
|  | 2211 | return true; | 
|  | 2212 |  | 
|  | 2213 | // We know we have a branch instruction. | 
|  | 2214 | auto BrInst = cast<BranchInst>(&I); | 
|  | 2215 |  | 
|  | 2216 | // Unconditional branches are never considered UB. | 
|  | 2217 | if (BrInst->isUnconditional()) | 
|  | 2218 | return true; | 
|  | 2219 |  | 
|  | 2220 | // Either we stopped and the appropriate action was taken, | 
|  | 2221 | // or we got back a simplified value to continue. | 
|  | 2222 | Optional<Value *> SimplifiedCond = | 
|  | 2223 | stopOnUndefOrAssumed(A, BrInst->getCondition(), BrInst); | 
|  | 2224 | if (!SimplifiedCond.hasValue()) | 
|  | 2225 | return true; | 
|  | 2226 | AssumedNoUBInsts.insert(&I); | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2227 | return true; | 
|  | 2228 | }; | 
|  | 2229 |  | 
| Johannes Doerfert | 5732f56 | 2019-12-24 19:25:08 -0600 | [diff] [blame] | 2230 | A.checkForAllInstructions(InspectMemAccessInstForUB, *this, | 
|  | 2231 | {Instruction::Load, Instruction::Store, | 
|  | 2232 | Instruction::AtomicCmpXchg, | 
|  | 2233 | Instruction::AtomicRMW}); | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2234 | A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::Br}); | 
|  | 2235 | if (NoUBPrevSize != AssumedNoUBInsts.size() || | 
|  | 2236 | UBPrevSize != KnownUBInsts.size()) | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2237 | return ChangeStatus::CHANGED; | 
|  | 2238 | return ChangeStatus::UNCHANGED; | 
|  | 2239 | } | 
|  | 2240 |  | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2241 | bool isKnownToCauseUB(Instruction *I) const override { | 
|  | 2242 | return KnownUBInsts.count(I); | 
|  | 2243 | } | 
|  | 2244 |  | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2245 | bool isAssumedToCauseUB(Instruction *I) const override { | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2246 | // In simple words, if an instruction is not in the assumed to _not_ | 
|  | 2247 | // cause UB, then it is assumed UB (that includes those | 
|  | 2248 | // in the KnownUBInsts set). The rest is boilerplate | 
|  | 2249 | // is to ensure that it is one of the instructions we test | 
|  | 2250 | // for UB. | 
|  | 2251 |  | 
|  | 2252 | switch (I->getOpcode()) { | 
|  | 2253 | case Instruction::Load: | 
|  | 2254 | case Instruction::Store: | 
|  | 2255 | case Instruction::AtomicCmpXchg: | 
|  | 2256 | case Instruction::AtomicRMW: | 
|  | 2257 | return !AssumedNoUBInsts.count(I); | 
|  | 2258 | case Instruction::Br: { | 
|  | 2259 | auto BrInst = cast<BranchInst>(I); | 
|  | 2260 | if (BrInst->isUnconditional()) | 
|  | 2261 | return false; | 
|  | 2262 | return !AssumedNoUBInsts.count(I); | 
|  | 2263 | } break; | 
|  | 2264 | default: | 
|  | 2265 | return false; | 
|  | 2266 | } | 
|  | 2267 | return false; | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2268 | } | 
|  | 2269 |  | 
|  | 2270 | ChangeStatus manifest(Attributor &A) override { | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2271 | if (KnownUBInsts.empty()) | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2272 | return ChangeStatus::UNCHANGED; | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2273 | for (Instruction *I : KnownUBInsts) | 
| Hideto Ueno | cb5eb13 | 2019-12-27 02:39:37 +0900 | [diff] [blame] | 2274 | A.changeToUnreachableAfterManifest(I); | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2275 | return ChangeStatus::CHANGED; | 
|  | 2276 | } | 
|  | 2277 |  | 
|  | 2278 | /// See AbstractAttribute::getAsStr() | 
|  | 2279 | const std::string getAsStr() const override { | 
|  | 2280 | return getAssumed() ? "undefined-behavior" : "no-ub"; | 
|  | 2281 | } | 
|  | 2282 |  | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2283 | /// Note: The correctness of this analysis depends on the fact that the | 
|  | 2284 | /// following 2 sets will stop changing after some point. | 
|  | 2285 | /// "Change" here means that their size changes. | 
|  | 2286 | /// The size of each set is monotonically increasing | 
|  | 2287 | /// (we only add items to them) and it is upper bounded by the number of | 
|  | 2288 | /// instructions in the processed function (we can never save more | 
|  | 2289 | /// elements in either set than this number). Hence, at some point, | 
|  | 2290 | /// they will stop increasing. | 
|  | 2291 | /// Consequently, at some point, both sets will have stopped | 
|  | 2292 | /// changing, effectively making the analysis reach a fixpoint. | 
|  | 2293 |  | 
|  | 2294 | /// Note: These 2 sets are disjoint and an instruction can be considered | 
|  | 2295 | /// one of 3 things: | 
|  | 2296 | /// 1) Known to cause UB (AAUndefinedBehavior could prove it) and put it in | 
|  | 2297 | ///    the KnownUBInsts set. | 
|  | 2298 | /// 2) Assumed to cause UB (in every updateImpl, AAUndefinedBehavior | 
|  | 2299 | ///    has a reason to assume it). | 
|  | 2300 | /// 3) Assumed to not cause UB. very other instruction - AAUndefinedBehavior | 
|  | 2301 | ///    could not find a reason to assume or prove that it can cause UB, | 
|  | 2302 | ///    hence it assumes it doesn't. We have a set for these instructions | 
|  | 2303 | ///    so that we don't reprocess them in every update. | 
|  | 2304 | ///    Note however that instructions in this set may cause UB. | 
|  | 2305 |  | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2306 | protected: | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2307 | /// A set of all live instructions _known_ to cause UB. | 
|  | 2308 | SmallPtrSet<Instruction *, 8> KnownUBInsts; | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2309 |  | 
|  | 2310 | private: | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2311 | /// A set of all the (live) instructions that are assumed to _not_ cause UB. | 
|  | 2312 | SmallPtrSet<Instruction *, 8> AssumedNoUBInsts; | 
|  | 2313 |  | 
|  | 2314 | // Should be called on updates in which if we're processing an instruction | 
|  | 2315 | // \p I that depends on a value \p V, one of the following has to happen: | 
|  | 2316 | // - If the value is assumed, then stop. | 
|  | 2317 | // - If the value is known but undef, then consider it UB. | 
|  | 2318 | // - Otherwise, do specific processing with the simplified value. | 
|  | 2319 | // We return None in the first 2 cases to signify that an appropriate | 
|  | 2320 | // action was taken and the caller should stop. | 
|  | 2321 | // Otherwise, we return the simplified value that the caller should | 
|  | 2322 | // use for specific processing. | 
|  | 2323 | Optional<Value *> stopOnUndefOrAssumed(Attributor &A, const Value *V, | 
|  | 2324 | Instruction *I) { | 
|  | 2325 | const auto &ValueSimplifyAA = | 
|  | 2326 | A.getAAFor<AAValueSimplify>(*this, IRPosition::value(*V)); | 
|  | 2327 | Optional<Value *> SimplifiedV = | 
|  | 2328 | ValueSimplifyAA.getAssumedSimplifiedValue(A); | 
|  | 2329 | if (!ValueSimplifyAA.isKnown()) { | 
|  | 2330 | // Don't depend on assumed values. | 
|  | 2331 | return llvm::None; | 
|  | 2332 | } | 
|  | 2333 | if (!SimplifiedV.hasValue()) { | 
|  | 2334 | // If it is known (which we tested above) but it doesn't have a value, | 
|  | 2335 | // then we can assume `undef` and hence the instruction is UB. | 
|  | 2336 | KnownUBInsts.insert(I); | 
|  | 2337 | return llvm::None; | 
|  | 2338 | } | 
|  | 2339 | Value *Val = SimplifiedV.getValue(); | 
|  | 2340 | if (isa<UndefValue>(Val)) { | 
|  | 2341 | KnownUBInsts.insert(I); | 
|  | 2342 | return llvm::None; | 
|  | 2343 | } | 
|  | 2344 | return Val; | 
|  | 2345 | } | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2346 | }; | 
|  | 2347 |  | 
|  | 2348 | struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl { | 
|  | 2349 | AAUndefinedBehaviorFunction(const IRPosition &IRP) | 
|  | 2350 | : AAUndefinedBehaviorImpl(IRP) {} | 
|  | 2351 |  | 
|  | 2352 | /// See AbstractAttribute::trackStatistics() | 
|  | 2353 | void trackStatistics() const override { | 
|  | 2354 | STATS_DECL(UndefinedBehaviorInstruction, Instruction, | 
|  | 2355 | "Number of instructions known to have UB"); | 
|  | 2356 | BUILD_STAT_NAME(UndefinedBehaviorInstruction, Instruction) += | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 2357 | KnownUBInsts.size(); | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 2358 | } | 
|  | 2359 | }; | 
|  | 2360 |  | 
| Hideto Ueno | 11d3710 | 2019-07-17 15:15:43 +0000 | [diff] [blame] | 2361 | /// ------------------------ Will-Return Attributes ---------------------------- | 
|  | 2362 |  | 
| Hideto Ueno | 11d3710 | 2019-07-17 15:15:43 +0000 | [diff] [blame] | 2363 | // Helper function that checks whether a function has any cycle. | 
|  | 2364 | // TODO: Replace with more efficent code | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2365 | static bool containsCycle(Function &F) { | 
| Hideto Ueno | 11d3710 | 2019-07-17 15:15:43 +0000 | [diff] [blame] | 2366 | SmallPtrSet<BasicBlock *, 32> Visited; | 
|  | 2367 |  | 
|  | 2368 | // Traverse BB by dfs and check whether successor is already visited. | 
|  | 2369 | for (BasicBlock *BB : depth_first(&F)) { | 
|  | 2370 | Visited.insert(BB); | 
|  | 2371 | for (auto *SuccBB : successors(BB)) { | 
|  | 2372 | if (Visited.count(SuccBB)) | 
|  | 2373 | return true; | 
|  | 2374 | } | 
|  | 2375 | } | 
|  | 2376 | return false; | 
|  | 2377 | } | 
|  | 2378 |  | 
|  | 2379 | // Helper function that checks the function have a loop which might become an | 
|  | 2380 | // endless loop | 
|  | 2381 | // FIXME: Any cycle is regarded as endless loop for now. | 
|  | 2382 | //        We have to allow some patterns. | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2383 | static bool containsPossiblyEndlessLoop(Function *F) { | 
|  | 2384 | return !F || !F->hasExactDefinition() || containsCycle(*F); | 
| Hideto Ueno | 11d3710 | 2019-07-17 15:15:43 +0000 | [diff] [blame] | 2385 | } | 
|  | 2386 |  | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2387 | struct AAWillReturnImpl : public AAWillReturn { | 
|  | 2388 | AAWillReturnImpl(const IRPosition &IRP) : AAWillReturn(IRP) {} | 
| Hideto Ueno | 11d3710 | 2019-07-17 15:15:43 +0000 | [diff] [blame] | 2389 |  | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2390 | /// See AbstractAttribute::initialize(...). | 
|  | 2391 | void initialize(Attributor &A) override { | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 2392 | AAWillReturn::initialize(A); | 
| Hideto Ueno | 11d3710 | 2019-07-17 15:15:43 +0000 | [diff] [blame] | 2393 |  | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2394 | Function *F = getAssociatedFunction(); | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2395 | if (containsPossiblyEndlessLoop(F)) | 
|  | 2396 | indicatePessimisticFixpoint(); | 
|  | 2397 | } | 
| Hideto Ueno | 11d3710 | 2019-07-17 15:15:43 +0000 | [diff] [blame] | 2398 |  | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2399 | /// See AbstractAttribute::updateImpl(...). | 
|  | 2400 | ChangeStatus updateImpl(Attributor &A) override { | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2401 | auto CheckForWillReturn = [&](Instruction &I) { | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 2402 | IRPosition IPos = IRPosition::callsite_function(ImmutableCallSite(&I)); | 
|  | 2403 | const auto &WillReturnAA = A.getAAFor<AAWillReturn>(*this, IPos); | 
|  | 2404 | if (WillReturnAA.isKnownWillReturn()) | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2405 | return true; | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 2406 | if (!WillReturnAA.isAssumedWillReturn()) | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2407 | return false; | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 2408 | const auto &NoRecurseAA = A.getAAFor<AANoRecurse>(*this, IPos); | 
|  | 2409 | return NoRecurseAA.isAssumedNoRecurse(); | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2410 | }; | 
|  | 2411 |  | 
|  | 2412 | if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this)) | 
|  | 2413 | return indicatePessimisticFixpoint(); | 
|  | 2414 |  | 
|  | 2415 | return ChangeStatus::UNCHANGED; | 
|  | 2416 | } | 
|  | 2417 |  | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2418 | /// See AbstractAttribute::getAsStr() | 
|  | 2419 | const std::string getAsStr() const override { | 
|  | 2420 | return getAssumed() ? "willreturn" : "may-noreturn"; | 
|  | 2421 | } | 
|  | 2422 | }; | 
|  | 2423 |  | 
|  | 2424 | struct AAWillReturnFunction final : AAWillReturnImpl { | 
|  | 2425 | AAWillReturnFunction(const IRPosition &IRP) : AAWillReturnImpl(IRP) {} | 
|  | 2426 |  | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2427 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2428 | void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) } | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2429 | }; | 
| Hideto Ueno | 11d3710 | 2019-07-17 15:15:43 +0000 | [diff] [blame] | 2430 |  | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 2431 | /// WillReturn attribute deduction for a call sites. | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 2432 | struct AAWillReturnCallSite final : AAWillReturnImpl { | 
|  | 2433 | AAWillReturnCallSite(const IRPosition &IRP) : AAWillReturnImpl(IRP) {} | 
|  | 2434 |  | 
|  | 2435 | /// See AbstractAttribute::initialize(...). | 
|  | 2436 | void initialize(Attributor &A) override { | 
|  | 2437 | AAWillReturnImpl::initialize(A); | 
|  | 2438 | Function *F = getAssociatedFunction(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 2439 | if (!F) | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 2440 | indicatePessimisticFixpoint(); | 
|  | 2441 | } | 
|  | 2442 |  | 
|  | 2443 | /// See AbstractAttribute::updateImpl(...). | 
|  | 2444 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 2445 | // TODO: Once we have call site specific value information we can provide | 
|  | 2446 | //       call site specific liveness information and then it makes | 
|  | 2447 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 2448 | //       redirecting requests to the callee argument. | 
|  | 2449 | Function *F = getAssociatedFunction(); | 
|  | 2450 | const IRPosition &FnPos = IRPosition::function(*F); | 
|  | 2451 | auto &FnAA = A.getAAFor<AAWillReturn>(*this, FnPos); | 
|  | 2452 | return clampStateAndIndicateChange( | 
|  | 2453 | getState(), | 
|  | 2454 | static_cast<const AAWillReturn::StateType &>(FnAA.getState())); | 
|  | 2455 | } | 
|  | 2456 |  | 
|  | 2457 | /// See AbstractAttribute::trackStatistics() | 
|  | 2458 | void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(willreturn); } | 
|  | 2459 | }; | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 2460 |  | 
| Pankaj Gode | 04945c9 | 2019-11-22 18:40:47 +0530 | [diff] [blame] | 2461 | /// -------------------AAReachability Attribute-------------------------- | 
|  | 2462 |  | 
|  | 2463 | struct AAReachabilityImpl : AAReachability { | 
|  | 2464 | AAReachabilityImpl(const IRPosition &IRP) : AAReachability(IRP) {} | 
|  | 2465 |  | 
|  | 2466 | const std::string getAsStr() const override { | 
|  | 2467 | // TODO: Return the number of reachable queries. | 
|  | 2468 | return "reachable"; | 
|  | 2469 | } | 
|  | 2470 |  | 
|  | 2471 | /// See AbstractAttribute::initialize(...). | 
| Johannes Doerfert | 0bc3336 | 2019-12-16 21:03:18 -0600 | [diff] [blame] | 2472 | void initialize(Attributor &A) override { indicatePessimisticFixpoint(); } | 
| Pankaj Gode | 04945c9 | 2019-11-22 18:40:47 +0530 | [diff] [blame] | 2473 |  | 
|  | 2474 | /// See AbstractAttribute::updateImpl(...). | 
|  | 2475 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 2476 | return indicatePessimisticFixpoint(); | 
|  | 2477 | } | 
|  | 2478 | }; | 
|  | 2479 |  | 
|  | 2480 | struct AAReachabilityFunction final : public AAReachabilityImpl { | 
|  | 2481 | AAReachabilityFunction(const IRPosition &IRP) : AAReachabilityImpl(IRP) {} | 
|  | 2482 |  | 
|  | 2483 | /// See AbstractAttribute::trackStatistics() | 
|  | 2484 | void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(reachable); } | 
|  | 2485 | }; | 
|  | 2486 |  | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 2487 | /// ------------------------ NoAlias Argument Attribute ------------------------ | 
|  | 2488 |  | 
| Johannes Doerfert | 344d038 | 2019-08-07 22:34:26 +0000 | [diff] [blame] | 2489 | struct AANoAliasImpl : AANoAlias { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 2490 | AANoAliasImpl(const IRPosition &IRP) : AANoAlias(IRP) {} | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 2491 |  | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 2492 | const std::string getAsStr() const override { | 
|  | 2493 | return getAssumed() ? "noalias" : "may-alias"; | 
|  | 2494 | } | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 2495 | }; | 
|  | 2496 |  | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2497 | /// NoAlias attribute for a floating value. | 
|  | 2498 | struct AANoAliasFloating final : AANoAliasImpl { | 
|  | 2499 | AANoAliasFloating(const IRPosition &IRP) : AANoAliasImpl(IRP) {} | 
|  | 2500 |  | 
| Hideto Ueno | cbab334 | 2019-08-29 05:52:00 +0000 | [diff] [blame] | 2501 | /// See AbstractAttribute::initialize(...). | 
|  | 2502 | void initialize(Attributor &A) override { | 
| Hideto Ueno | 1d68ed8 | 2019-09-11 07:00:33 +0000 | [diff] [blame] | 2503 | AANoAliasImpl::initialize(A); | 
| Johannes Doerfert | 87ddf1f | 2020-01-25 20:21:41 -0600 | [diff] [blame] | 2504 | Value *Val = &getAssociatedValue(); | 
|  | 2505 | do { | 
|  | 2506 | CastInst *CI = dyn_cast<CastInst>(Val); | 
|  | 2507 | if (!CI) | 
|  | 2508 | break; | 
|  | 2509 | Value *Base = CI->getOperand(0); | 
|  | 2510 | if (Base->getNumUses() != 1) | 
|  | 2511 | break; | 
|  | 2512 | Val = Base; | 
|  | 2513 | } while (true); | 
|  | 2514 |  | 
| Johannes Doerfert | 72adda1 | 2019-10-10 05:33:21 +0000 | [diff] [blame] | 2515 | if (isa<AllocaInst>(Val)) | 
|  | 2516 | indicateOptimisticFixpoint(); | 
| Johannes Doerfert | 24ae77e | 2020-01-27 22:19:11 -0600 | [diff] [blame] | 2517 | else if (isa<ConstantPointerNull>(Val) && | 
|  | 2518 | !NullPointerIsDefined(getAnchorScope(), | 
| Johannes Doerfert | 87ddf1f | 2020-01-25 20:21:41 -0600 | [diff] [blame] | 2519 | Val->getType()->getPointerAddressSpace())) | 
| Hideto Ueno | 1d68ed8 | 2019-09-11 07:00:33 +0000 | [diff] [blame] | 2520 | indicateOptimisticFixpoint(); | 
| Johannes Doerfert | 87ddf1f | 2020-01-25 20:21:41 -0600 | [diff] [blame] | 2521 | else if (Val != &getAssociatedValue()) { | 
|  | 2522 | const auto &ValNoAliasAA = | 
|  | 2523 | A.getAAFor<AANoAlias>(*this, IRPosition::value(*Val)); | 
|  | 2524 | if (ValNoAliasAA.isKnownNoAlias()) | 
|  | 2525 | indicateOptimisticFixpoint(); | 
|  | 2526 | } | 
| Hideto Ueno | cbab334 | 2019-08-29 05:52:00 +0000 | [diff] [blame] | 2527 | } | 
|  | 2528 |  | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2529 | /// See AbstractAttribute::updateImpl(...). | 
|  | 2530 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 2531 | // TODO: Implement this. | 
|  | 2532 | return indicatePessimisticFixpoint(); | 
|  | 2533 | } | 
|  | 2534 |  | 
|  | 2535 | /// See AbstractAttribute::trackStatistics() | 
|  | 2536 | void trackStatistics() const override { | 
|  | 2537 | STATS_DECLTRACK_FLOATING_ATTR(noalias) | 
|  | 2538 | } | 
|  | 2539 | }; | 
|  | 2540 |  | 
|  | 2541 | /// NoAlias attribute for an argument. | 
| Hideto Ueno | cbab334 | 2019-08-29 05:52:00 +0000 | [diff] [blame] | 2542 | struct AANoAliasArgument final | 
|  | 2543 | : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> { | 
| Johannes Doerfert | b1b441d | 2019-10-10 01:19:57 -0500 | [diff] [blame] | 2544 | using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>; | 
|  | 2545 | AANoAliasArgument(const IRPosition &IRP) : Base(IRP) {} | 
|  | 2546 |  | 
| Johannes Doerfert | 2baf000 | 2020-01-12 00:18:07 -0600 | [diff] [blame] | 2547 | /// See AbstractAttribute::initialize(...). | 
|  | 2548 | void initialize(Attributor &A) override { | 
|  | 2549 | Base::initialize(A); | 
|  | 2550 | // See callsite argument attribute and callee argument attribute. | 
|  | 2551 | if (hasAttr({Attribute::ByVal})) | 
|  | 2552 | indicateOptimisticFixpoint(); | 
|  | 2553 | } | 
|  | 2554 |  | 
| Johannes Doerfert | b1b441d | 2019-10-10 01:19:57 -0500 | [diff] [blame] | 2555 | /// See AbstractAttribute::update(...). | 
|  | 2556 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 2557 | // We have to make sure no-alias on the argument does not break | 
|  | 2558 | // synchronization when this is a callback argument, see also [1] below. | 
|  | 2559 | // If synchronization cannot be affected, we delegate to the base updateImpl | 
|  | 2560 | // function, otherwise we give up for now. | 
|  | 2561 |  | 
|  | 2562 | // If the function is no-sync, no-alias cannot break synchronization. | 
|  | 2563 | const auto &NoSyncAA = A.getAAFor<AANoSync>( | 
|  | 2564 | *this, IRPosition::function_scope(getIRPosition())); | 
|  | 2565 | if (NoSyncAA.isAssumedNoSync()) | 
|  | 2566 | return Base::updateImpl(A); | 
|  | 2567 |  | 
|  | 2568 | // If the argument is read-only, no-alias cannot break synchronization. | 
|  | 2569 | const auto &MemBehaviorAA = | 
|  | 2570 | A.getAAFor<AAMemoryBehavior>(*this, getIRPosition()); | 
|  | 2571 | if (MemBehaviorAA.isAssumedReadOnly()) | 
|  | 2572 | return Base::updateImpl(A); | 
|  | 2573 |  | 
|  | 2574 | // If the argument is never passed through callbacks, no-alias cannot break | 
|  | 2575 | // synchronization. | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 2576 | bool AllCallSitesKnown; | 
| Johannes Doerfert | b1b441d | 2019-10-10 01:19:57 -0500 | [diff] [blame] | 2577 | if (A.checkForAllCallSites( | 
|  | 2578 | [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *this, | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 2579 | true, AllCallSitesKnown)) | 
| Johannes Doerfert | b1b441d | 2019-10-10 01:19:57 -0500 | [diff] [blame] | 2580 | return Base::updateImpl(A); | 
|  | 2581 |  | 
|  | 2582 | // TODO: add no-alias but make sure it doesn't break synchronization by | 
|  | 2583 | // introducing fake uses. See: | 
|  | 2584 | // [1] Compiler Optimizations for OpenMP, J. Doerfert and H. Finkel, | 
|  | 2585 | //     International Workshop on OpenMP 2018, | 
|  | 2586 | //     http://compilers.cs.uni-saarland.de/people/doerfert/par_opt18.pdf | 
|  | 2587 |  | 
|  | 2588 | return indicatePessimisticFixpoint(); | 
|  | 2589 | } | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2590 |  | 
|  | 2591 | /// See AbstractAttribute::trackStatistics() | 
|  | 2592 | void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) } | 
|  | 2593 | }; | 
|  | 2594 |  | 
|  | 2595 | struct AANoAliasCallSiteArgument final : AANoAliasImpl { | 
|  | 2596 | AANoAliasCallSiteArgument(const IRPosition &IRP) : AANoAliasImpl(IRP) {} | 
|  | 2597 |  | 
| Hideto Ueno | cbab334 | 2019-08-29 05:52:00 +0000 | [diff] [blame] | 2598 | /// See AbstractAttribute::initialize(...). | 
|  | 2599 | void initialize(Attributor &A) override { | 
| Hideto Ueno | 6381b14 | 2019-08-30 10:00:32 +0000 | [diff] [blame] | 2600 | // See callsite argument attribute and callee argument attribute. | 
|  | 2601 | ImmutableCallSite ICS(&getAnchorValue()); | 
|  | 2602 | if (ICS.paramHasAttr(getArgNo(), Attribute::NoAlias)) | 
|  | 2603 | indicateOptimisticFixpoint(); | 
| Johannes Doerfert | 24ae77e | 2020-01-27 22:19:11 -0600 | [diff] [blame] | 2604 | Value &Val = getAssociatedValue(); | 
|  | 2605 | if (isa<ConstantPointerNull>(Val) && | 
|  | 2606 | !NullPointerIsDefined(getAnchorScope(), | 
|  | 2607 | Val.getType()->getPointerAddressSpace())) | 
|  | 2608 | indicateOptimisticFixpoint(); | 
| Hideto Ueno | cbab334 | 2019-08-29 05:52:00 +0000 | [diff] [blame] | 2609 | } | 
|  | 2610 |  | 
| Johannes Doerfert | 53992c7 | 2020-01-27 22:24:32 -0600 | [diff] [blame] | 2611 | /// Determine if the underlying value may alias with the call site argument | 
|  | 2612 | /// \p OtherArgNo of \p ICS (= the underlying call site). | 
|  | 2613 | bool mayAliasWithArgument(Attributor &A, AAResults *&AAR, | 
|  | 2614 | const AAMemoryBehavior &MemBehaviorAA, | 
|  | 2615 | ImmutableCallSite ICS, unsigned OtherArgNo) { | 
|  | 2616 | // We do not need to worry about aliasing with the underlying IRP. | 
|  | 2617 | if (this->getArgNo() == (int)OtherArgNo) | 
|  | 2618 | return false; | 
|  | 2619 |  | 
|  | 2620 | // If it is not a pointer or pointer vector we do not alias. | 
|  | 2621 | const Value *ArgOp = ICS.getArgOperand(OtherArgNo); | 
|  | 2622 | if (!ArgOp->getType()->isPtrOrPtrVectorTy()) | 
|  | 2623 | return false; | 
|  | 2624 |  | 
|  | 2625 | auto &ICSArgMemBehaviorAA = A.getAAFor<AAMemoryBehavior>( | 
|  | 2626 | *this, IRPosition::callsite_argument(ICS, OtherArgNo), | 
|  | 2627 | /* TrackDependence */ false); | 
|  | 2628 |  | 
|  | 2629 | // If the argument is readnone, there is no read-write aliasing. | 
|  | 2630 | if (ICSArgMemBehaviorAA.isAssumedReadNone()) { | 
|  | 2631 | A.recordDependence(ICSArgMemBehaviorAA, *this, DepClassTy::OPTIONAL); | 
|  | 2632 | return false; | 
|  | 2633 | } | 
|  | 2634 |  | 
|  | 2635 | // If the argument is readonly and the underlying value is readonly, there | 
|  | 2636 | // is no read-write aliasing. | 
|  | 2637 | bool IsReadOnly = MemBehaviorAA.isAssumedReadOnly(); | 
|  | 2638 | if (ICSArgMemBehaviorAA.isAssumedReadOnly() && IsReadOnly) { | 
|  | 2639 | A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL); | 
|  | 2640 | A.recordDependence(ICSArgMemBehaviorAA, *this, DepClassTy::OPTIONAL); | 
|  | 2641 | return false; | 
|  | 2642 | } | 
|  | 2643 |  | 
|  | 2644 | // We have to utilize actual alias analysis queries so we need the object. | 
|  | 2645 | if (!AAR) | 
|  | 2646 | AAR = A.getInfoCache().getAAResultsForFunction(*getAnchorScope()); | 
|  | 2647 |  | 
|  | 2648 | // Try to rule it out at the call site. | 
|  | 2649 | bool IsAliasing = !AAR || !AAR->isNoAlias(&getAssociatedValue(), ArgOp); | 
|  | 2650 | LLVM_DEBUG(dbgs() << "[NoAliasCSArg] Check alias between " | 
|  | 2651 | "callsite arguments: " | 
|  | 2652 | << getAssociatedValue() << " " << *ArgOp << " => " | 
|  | 2653 | << (IsAliasing ? "" : "no-") << "alias \n"); | 
|  | 2654 |  | 
|  | 2655 | return IsAliasing; | 
|  | 2656 | } | 
|  | 2657 |  | 
|  | 2658 | bool | 
|  | 2659 | isKnownNoAliasDueToNoAliasPreservation(Attributor &A, AAResults *&AAR, | 
|  | 2660 | const AAMemoryBehavior &MemBehaviorAA, | 
|  | 2661 | const AANoAlias &NoAliasAA) { | 
| Hideto Ueno | 1d68ed8 | 2019-09-11 07:00:33 +0000 | [diff] [blame] | 2662 | // We can deduce "noalias" if the following conditions hold. | 
|  | 2663 | // (i)   Associated value is assumed to be noalias in the definition. | 
|  | 2664 | // (ii)  Associated value is assumed to be no-capture in all the uses | 
|  | 2665 | //       possibly executed before this callsite. | 
|  | 2666 | // (iii) There is no other pointer argument which could alias with the | 
|  | 2667 | //       value. | 
|  | 2668 |  | 
| Johannes Doerfert | 53992c7 | 2020-01-27 22:24:32 -0600 | [diff] [blame] | 2669 | bool AssociatedValueIsNoAliasAtDef = NoAliasAA.isAssumedNoAlias(); | 
|  | 2670 | if (!AssociatedValueIsNoAliasAtDef) { | 
|  | 2671 | LLVM_DEBUG(dbgs() << "[AANoAlias] " << getAssociatedValue() | 
|  | 2672 | << " is not no-alias at the definition\n"); | 
|  | 2673 | return false; | 
|  | 2674 | } | 
| Hideto Ueno | 1d68ed8 | 2019-09-11 07:00:33 +0000 | [diff] [blame] | 2675 |  | 
| Johannes Doerfert | 53992c7 | 2020-01-27 22:24:32 -0600 | [diff] [blame] | 2676 | const IRPosition &VIRP = IRPosition::value(getAssociatedValue()); | 
|  | 2677 | auto &NoCaptureAA = | 
|  | 2678 | A.getAAFor<AANoCapture>(*this, VIRP, /* TrackDependence */ false); | 
|  | 2679 | // Check whether the value is captured in the scope using AANoCapture. | 
|  | 2680 | // FIXME: This is conservative though, it is better to look at CFG and | 
|  | 2681 | //        check only uses possibly executed before this callsite. | 
| Johannes Doerfert | 72adda1 | 2019-10-10 05:33:21 +0000 | [diff] [blame] | 2682 | if (!NoCaptureAA.isAssumedNoCaptureMaybeReturned()) { | 
|  | 2683 | LLVM_DEBUG( | 
| Johannes Doerfert | 53992c7 | 2020-01-27 22:24:32 -0600 | [diff] [blame] | 2684 | dbgs() << "[AANoAliasCSArg] " << getAssociatedValue() | 
| Johannes Doerfert | 72adda1 | 2019-10-10 05:33:21 +0000 | [diff] [blame] | 2685 | << " cannot be noalias as it is potentially captured\n"); | 
| Johannes Doerfert | 53992c7 | 2020-01-27 22:24:32 -0600 | [diff] [blame] | 2686 | return false; | 
| Johannes Doerfert | 72adda1 | 2019-10-10 05:33:21 +0000 | [diff] [blame] | 2687 | } | 
| Johannes Doerfert | 53992c7 | 2020-01-27 22:24:32 -0600 | [diff] [blame] | 2688 | A.recordDependence(NoCaptureAA, *this, DepClassTy::OPTIONAL); | 
| Hideto Ueno | 1d68ed8 | 2019-09-11 07:00:33 +0000 | [diff] [blame] | 2689 |  | 
| Johannes Doerfert | 53992c7 | 2020-01-27 22:24:32 -0600 | [diff] [blame] | 2690 | // Check there is no other pointer argument which could alias with the | 
|  | 2691 | // value passed at this call site. | 
| Johannes Doerfert | b1b441d | 2019-10-10 01:19:57 -0500 | [diff] [blame] | 2692 | // TODO: AbstractCallSite | 
| Hideto Ueno | 1d68ed8 | 2019-09-11 07:00:33 +0000 | [diff] [blame] | 2693 | ImmutableCallSite ICS(&getAnchorValue()); | 
| Johannes Doerfert | 53992c7 | 2020-01-27 22:24:32 -0600 | [diff] [blame] | 2694 | for (unsigned OtherArgNo = 0; OtherArgNo < ICS.getNumArgOperands(); | 
|  | 2695 | OtherArgNo++) | 
|  | 2696 | if (mayAliasWithArgument(A, AAR, MemBehaviorAA, ICS, OtherArgNo)) | 
|  | 2697 | return false; | 
| Hideto Ueno | 1d68ed8 | 2019-09-11 07:00:33 +0000 | [diff] [blame] | 2698 |  | 
| Johannes Doerfert | 53992c7 | 2020-01-27 22:24:32 -0600 | [diff] [blame] | 2699 | return true; | 
|  | 2700 | } | 
| Hideto Ueno | 1d68ed8 | 2019-09-11 07:00:33 +0000 | [diff] [blame] | 2701 |  | 
| Johannes Doerfert | 53992c7 | 2020-01-27 22:24:32 -0600 | [diff] [blame] | 2702 | /// See AbstractAttribute::updateImpl(...). | 
|  | 2703 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 2704 | // If the argument is readnone we are done as there are no accesses via the | 
|  | 2705 | // argument. | 
|  | 2706 | auto &MemBehaviorAA = | 
|  | 2707 | A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), | 
|  | 2708 | /* TrackDependence */ false); | 
|  | 2709 | if (MemBehaviorAA.isAssumedReadNone()) { | 
|  | 2710 | A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL); | 
|  | 2711 | return ChangeStatus::UNCHANGED; | 
| Hideto Ueno | 1d68ed8 | 2019-09-11 07:00:33 +0000 | [diff] [blame] | 2712 | } | 
|  | 2713 |  | 
| Johannes Doerfert | 53992c7 | 2020-01-27 22:24:32 -0600 | [diff] [blame] | 2714 | const IRPosition &VIRP = IRPosition::value(getAssociatedValue()); | 
|  | 2715 | const auto &NoAliasAA = A.getAAFor<AANoAlias>(*this, VIRP, | 
|  | 2716 | /* TrackDependence */ false); | 
|  | 2717 |  | 
|  | 2718 | AAResults *AAR = nullptr; | 
|  | 2719 | if (isKnownNoAliasDueToNoAliasPreservation(A, AAR, MemBehaviorAA, | 
|  | 2720 | NoAliasAA)) { | 
|  | 2721 | LLVM_DEBUG( | 
|  | 2722 | dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n"); | 
|  | 2723 | return ChangeStatus::UNCHANGED; | 
|  | 2724 | } | 
|  | 2725 |  | 
|  | 2726 | return indicatePessimisticFixpoint(); | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2727 | } | 
|  | 2728 |  | 
|  | 2729 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 56e9b60 | 2019-09-04 20:34:57 +0000 | [diff] [blame] | 2730 | void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noalias) } | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 2731 | }; | 
|  | 2732 |  | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 2733 | /// NoAlias attribute for function return value. | 
| Johannes Doerfert | beb5150 | 2019-08-07 22:36:15 +0000 | [diff] [blame] | 2734 | struct AANoAliasReturned final : AANoAliasImpl { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 2735 | AANoAliasReturned(const IRPosition &IRP) : AANoAliasImpl(IRP) {} | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 2736 |  | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 2737 | /// See AbstractAttribute::updateImpl(...). | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2738 | virtual ChangeStatus updateImpl(Attributor &A) override { | 
|  | 2739 |  | 
|  | 2740 | auto CheckReturnValue = [&](Value &RV) -> bool { | 
|  | 2741 | if (Constant *C = dyn_cast<Constant>(&RV)) | 
|  | 2742 | if (C->isNullValue() || isa<UndefValue>(C)) | 
|  | 2743 | return true; | 
|  | 2744 |  | 
|  | 2745 | /// For now, we can only deduce noalias if we have call sites. | 
|  | 2746 | /// FIXME: add more support. | 
|  | 2747 | ImmutableCallSite ICS(&RV); | 
|  | 2748 | if (!ICS) | 
|  | 2749 | return false; | 
|  | 2750 |  | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 2751 | const IRPosition &RVPos = IRPosition::value(RV); | 
|  | 2752 | const auto &NoAliasAA = A.getAAFor<AANoAlias>(*this, RVPos); | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 2753 | if (!NoAliasAA.isAssumedNoAlias()) | 
|  | 2754 | return false; | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2755 |  | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 2756 | const auto &NoCaptureAA = A.getAAFor<AANoCapture>(*this, RVPos); | 
|  | 2757 | return NoCaptureAA.isAssumedNoCaptureMaybeReturned(); | 
| Johannes Doerfert | fe6dbad | 2019-08-16 19:36:17 +0000 | [diff] [blame] | 2758 | }; | 
|  | 2759 |  | 
|  | 2760 | if (!A.checkForAllReturnedValues(CheckReturnValue, *this)) | 
|  | 2761 | return indicatePessimisticFixpoint(); | 
|  | 2762 |  | 
|  | 2763 | return ChangeStatus::UNCHANGED; | 
|  | 2764 | } | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 2765 |  | 
|  | 2766 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 2767 | void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) } | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 2768 | }; | 
|  | 2769 |  | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 2770 | /// NoAlias attribute deduction for a call site return value. | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 2771 | struct AANoAliasCallSiteReturned final : AANoAliasImpl { | 
|  | 2772 | AANoAliasCallSiteReturned(const IRPosition &IRP) : AANoAliasImpl(IRP) {} | 
|  | 2773 |  | 
|  | 2774 | /// See AbstractAttribute::initialize(...). | 
|  | 2775 | void initialize(Attributor &A) override { | 
|  | 2776 | AANoAliasImpl::initialize(A); | 
|  | 2777 | Function *F = getAssociatedFunction(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 2778 | if (!F) | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 2779 | indicatePessimisticFixpoint(); | 
|  | 2780 | } | 
|  | 2781 |  | 
|  | 2782 | /// See AbstractAttribute::updateImpl(...). | 
|  | 2783 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 2784 | // TODO: Once we have call site specific value information we can provide | 
|  | 2785 | //       call site specific liveness information and then it makes | 
|  | 2786 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 2787 | //       redirecting requests to the callee argument. | 
|  | 2788 | Function *F = getAssociatedFunction(); | 
|  | 2789 | const IRPosition &FnPos = IRPosition::returned(*F); | 
|  | 2790 | auto &FnAA = A.getAAFor<AANoAlias>(*this, FnPos); | 
|  | 2791 | return clampStateAndIndicateChange( | 
|  | 2792 | getState(), static_cast<const AANoAlias::StateType &>(FnAA.getState())); | 
|  | 2793 | } | 
|  | 2794 |  | 
|  | 2795 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 56e9b60 | 2019-09-04 20:34:57 +0000 | [diff] [blame] | 2796 | void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noalias); } | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 2797 | }; | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 2798 |  | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 2799 | /// -------------------AAIsDead Function Attribute----------------------- | 
|  | 2800 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 2801 | struct AAIsDeadValueImpl : public AAIsDead { | 
|  | 2802 | AAIsDeadValueImpl(const IRPosition &IRP) : AAIsDead(IRP) {} | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 2803 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 2804 | /// See AAIsDead::isAssumedDead(). | 
|  | 2805 | bool isAssumedDead() const override { return getAssumed(); } | 
|  | 2806 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 2807 | /// See AAIsDead::isKnownDead(). | 
|  | 2808 | bool isKnownDead() const override { return getKnown(); } | 
|  | 2809 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 2810 | /// See AAIsDead::isAssumedDead(BasicBlock *). | 
|  | 2811 | bool isAssumedDead(const BasicBlock *BB) const override { return false; } | 
|  | 2812 |  | 
|  | 2813 | /// See AAIsDead::isKnownDead(BasicBlock *). | 
|  | 2814 | bool isKnownDead(const BasicBlock *BB) const override { return false; } | 
|  | 2815 |  | 
|  | 2816 | /// See AAIsDead::isAssumedDead(Instruction *I). | 
|  | 2817 | bool isAssumedDead(const Instruction *I) const override { | 
|  | 2818 | return I == getCtxI() && isAssumedDead(); | 
|  | 2819 | } | 
|  | 2820 |  | 
|  | 2821 | /// See AAIsDead::isKnownDead(Instruction *I). | 
|  | 2822 | bool isKnownDead(const Instruction *I) const override { | 
|  | 2823 | return I == getCtxI() && getKnown(); | 
|  | 2824 | } | 
|  | 2825 |  | 
|  | 2826 | /// See AbstractAttribute::getAsStr(). | 
|  | 2827 | const std::string getAsStr() const override { | 
|  | 2828 | return isAssumedDead() ? "assumed-dead" : "assumed-live"; | 
|  | 2829 | } | 
|  | 2830 | }; | 
|  | 2831 |  | 
|  | 2832 | struct AAIsDeadFloating : public AAIsDeadValueImpl { | 
|  | 2833 | AAIsDeadFloating(const IRPosition &IRP) : AAIsDeadValueImpl(IRP) {} | 
|  | 2834 |  | 
|  | 2835 | /// See AbstractAttribute::initialize(...). | 
|  | 2836 | void initialize(Attributor &A) override { | 
|  | 2837 | if (Instruction *I = dyn_cast<Instruction>(&getAssociatedValue())) | 
|  | 2838 | if (!wouldInstructionBeTriviallyDead(I)) | 
|  | 2839 | indicatePessimisticFixpoint(); | 
|  | 2840 | if (isa<UndefValue>(getAssociatedValue())) | 
|  | 2841 | indicatePessimisticFixpoint(); | 
|  | 2842 | } | 
|  | 2843 |  | 
|  | 2844 | /// See AbstractAttribute::updateImpl(...). | 
|  | 2845 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 2846 | auto UsePred = [&](const Use &U, bool &Follow) { | 
|  | 2847 | Instruction *UserI = cast<Instruction>(U.getUser()); | 
|  | 2848 | if (CallSite CS = CallSite(UserI)) { | 
|  | 2849 | if (!CS.isArgOperand(&U)) | 
|  | 2850 | return false; | 
|  | 2851 | const IRPosition &CSArgPos = | 
|  | 2852 | IRPosition::callsite_argument(CS, CS.getArgumentNo(&U)); | 
|  | 2853 | const auto &CSArgIsDead = A.getAAFor<AAIsDead>(*this, CSArgPos); | 
|  | 2854 | return CSArgIsDead.isAssumedDead(); | 
|  | 2855 | } | 
|  | 2856 | if (ReturnInst *RI = dyn_cast<ReturnInst>(UserI)) { | 
|  | 2857 | const IRPosition &RetPos = IRPosition::returned(*RI->getFunction()); | 
|  | 2858 | const auto &RetIsDeadAA = A.getAAFor<AAIsDead>(*this, RetPos); | 
|  | 2859 | return RetIsDeadAA.isAssumedDead(); | 
|  | 2860 | } | 
|  | 2861 | Follow = true; | 
|  | 2862 | return wouldInstructionBeTriviallyDead(UserI); | 
|  | 2863 | }; | 
|  | 2864 |  | 
|  | 2865 | if (!A.checkForAllUses(UsePred, *this, getAssociatedValue())) | 
|  | 2866 | return indicatePessimisticFixpoint(); | 
|  | 2867 | return ChangeStatus::UNCHANGED; | 
|  | 2868 | } | 
|  | 2869 |  | 
|  | 2870 | /// See AbstractAttribute::manifest(...). | 
|  | 2871 | ChangeStatus manifest(Attributor &A) override { | 
|  | 2872 | Value &V = getAssociatedValue(); | 
|  | 2873 | if (auto *I = dyn_cast<Instruction>(&V)) | 
|  | 2874 | if (wouldInstructionBeTriviallyDead(I)) { | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 2875 | A.deleteAfterManifest(*I); | 
|  | 2876 | return ChangeStatus::CHANGED; | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 2877 | } | 
|  | 2878 |  | 
|  | 2879 | if (V.use_empty()) | 
|  | 2880 | return ChangeStatus::UNCHANGED; | 
|  | 2881 |  | 
|  | 2882 | UndefValue &UV = *UndefValue::get(V.getType()); | 
| Hideto Ueno | 34fe8d0 | 2019-12-30 17:08:48 +0900 | [diff] [blame] | 2883 | bool AnyChange = A.changeValueAfterManifest(V, UV); | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 2884 | return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED; | 
|  | 2885 | } | 
|  | 2886 |  | 
|  | 2887 | /// See AbstractAttribute::trackStatistics() | 
|  | 2888 | void trackStatistics() const override { | 
|  | 2889 | STATS_DECLTRACK_FLOATING_ATTR(IsDead) | 
|  | 2890 | } | 
|  | 2891 | }; | 
|  | 2892 |  | 
|  | 2893 | struct AAIsDeadArgument : public AAIsDeadFloating { | 
|  | 2894 | AAIsDeadArgument(const IRPosition &IRP) : AAIsDeadFloating(IRP) {} | 
|  | 2895 |  | 
|  | 2896 | /// See AbstractAttribute::initialize(...). | 
|  | 2897 | void initialize(Attributor &A) override { | 
|  | 2898 | if (!getAssociatedFunction()->hasExactDefinition()) | 
|  | 2899 | indicatePessimisticFixpoint(); | 
|  | 2900 | } | 
|  | 2901 |  | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 2902 | /// See AbstractAttribute::manifest(...). | 
|  | 2903 | ChangeStatus manifest(Attributor &A) override { | 
|  | 2904 | ChangeStatus Changed = AAIsDeadFloating::manifest(A); | 
|  | 2905 | Argument &Arg = *getAssociatedArgument(); | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 2906 | if (A.isValidFunctionSignatureRewrite(Arg, /* ReplacementTypes */ {})) | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 2907 | if (A.registerFunctionSignatureRewrite( | 
|  | 2908 | Arg, /* ReplacementTypes */ {}, | 
|  | 2909 | Attributor::ArgumentReplacementInfo::CalleeRepairCBTy{}, | 
|  | 2910 | Attributor::ArgumentReplacementInfo::ACSRepairCBTy{})) | 
|  | 2911 | return ChangeStatus::CHANGED; | 
|  | 2912 | return Changed; | 
|  | 2913 | } | 
|  | 2914 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 2915 | /// See AbstractAttribute::trackStatistics() | 
|  | 2916 | void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(IsDead) } | 
|  | 2917 | }; | 
|  | 2918 |  | 
|  | 2919 | struct AAIsDeadCallSiteArgument : public AAIsDeadValueImpl { | 
|  | 2920 | AAIsDeadCallSiteArgument(const IRPosition &IRP) : AAIsDeadValueImpl(IRP) {} | 
|  | 2921 |  | 
|  | 2922 | /// See AbstractAttribute::initialize(...). | 
|  | 2923 | void initialize(Attributor &A) override { | 
|  | 2924 | if (isa<UndefValue>(getAssociatedValue())) | 
|  | 2925 | indicatePessimisticFixpoint(); | 
|  | 2926 | } | 
|  | 2927 |  | 
|  | 2928 | /// See AbstractAttribute::updateImpl(...). | 
|  | 2929 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 2930 | // TODO: Once we have call site specific value information we can provide | 
|  | 2931 | //       call site specific liveness information and then it makes | 
|  | 2932 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 2933 | //       redirecting requests to the callee argument. | 
|  | 2934 | Argument *Arg = getAssociatedArgument(); | 
|  | 2935 | if (!Arg) | 
|  | 2936 | return indicatePessimisticFixpoint(); | 
|  | 2937 | const IRPosition &ArgPos = IRPosition::argument(*Arg); | 
|  | 2938 | auto &ArgAA = A.getAAFor<AAIsDead>(*this, ArgPos); | 
|  | 2939 | return clampStateAndIndicateChange( | 
|  | 2940 | getState(), static_cast<const AAIsDead::StateType &>(ArgAA.getState())); | 
|  | 2941 | } | 
|  | 2942 |  | 
|  | 2943 | /// See AbstractAttribute::manifest(...). | 
|  | 2944 | ChangeStatus manifest(Attributor &A) override { | 
|  | 2945 | CallBase &CB = cast<CallBase>(getAnchorValue()); | 
|  | 2946 | Use &U = CB.getArgOperandUse(getArgNo()); | 
|  | 2947 | assert(!isa<UndefValue>(U.get()) && | 
|  | 2948 | "Expected undef values to be filtered out!"); | 
|  | 2949 | UndefValue &UV = *UndefValue::get(U->getType()); | 
|  | 2950 | if (A.changeUseAfterManifest(U, UV)) | 
|  | 2951 | return ChangeStatus::CHANGED; | 
|  | 2952 | return ChangeStatus::UNCHANGED; | 
|  | 2953 | } | 
|  | 2954 |  | 
|  | 2955 | /// See AbstractAttribute::trackStatistics() | 
|  | 2956 | void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(IsDead) } | 
|  | 2957 | }; | 
|  | 2958 |  | 
|  | 2959 | struct AAIsDeadReturned : public AAIsDeadValueImpl { | 
|  | 2960 | AAIsDeadReturned(const IRPosition &IRP) : AAIsDeadValueImpl(IRP) {} | 
|  | 2961 |  | 
|  | 2962 | /// See AbstractAttribute::updateImpl(...). | 
|  | 2963 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 2964 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 2965 | bool AllKnownDead = true; | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 2966 | auto PredForCallSite = [&](AbstractCallSite ACS) { | 
|  | 2967 | if (ACS.isCallbackCall()) | 
|  | 2968 | return false; | 
|  | 2969 | const IRPosition &CSRetPos = | 
|  | 2970 | IRPosition::callsite_returned(ACS.getCallSite()); | 
|  | 2971 | const auto &RetIsDeadAA = A.getAAFor<AAIsDead>(*this, CSRetPos); | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 2972 | AllKnownDead &= RetIsDeadAA.isKnownDead(); | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 2973 | return RetIsDeadAA.isAssumedDead(); | 
|  | 2974 | }; | 
|  | 2975 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 2976 | bool AllCallSitesKnown; | 
|  | 2977 | if (!A.checkForAllCallSites(PredForCallSite, *this, true, | 
|  | 2978 | AllCallSitesKnown)) | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 2979 | return indicatePessimisticFixpoint(); | 
|  | 2980 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 2981 | if (AllCallSitesKnown && AllKnownDead) | 
|  | 2982 | indicateOptimisticFixpoint(); | 
|  | 2983 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 2984 | return ChangeStatus::UNCHANGED; | 
|  | 2985 | } | 
|  | 2986 |  | 
|  | 2987 | /// See AbstractAttribute::manifest(...). | 
|  | 2988 | ChangeStatus manifest(Attributor &A) override { | 
|  | 2989 | // TODO: Rewrite the signature to return void? | 
|  | 2990 | bool AnyChange = false; | 
|  | 2991 | UndefValue &UV = *UndefValue::get(getAssociatedFunction()->getReturnType()); | 
|  | 2992 | auto RetInstPred = [&](Instruction &I) { | 
|  | 2993 | ReturnInst &RI = cast<ReturnInst>(I); | 
|  | 2994 | if (!isa<UndefValue>(RI.getReturnValue())) | 
|  | 2995 | AnyChange |= A.changeUseAfterManifest(RI.getOperandUse(0), UV); | 
|  | 2996 | return true; | 
|  | 2997 | }; | 
|  | 2998 | A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret}); | 
|  | 2999 | return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED; | 
|  | 3000 | } | 
|  | 3001 |  | 
|  | 3002 | /// See AbstractAttribute::trackStatistics() | 
|  | 3003 | void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(IsDead) } | 
|  | 3004 | }; | 
|  | 3005 |  | 
|  | 3006 | struct AAIsDeadCallSiteReturned : public AAIsDeadFloating { | 
|  | 3007 | AAIsDeadCallSiteReturned(const IRPosition &IRP) : AAIsDeadFloating(IRP) {} | 
|  | 3008 |  | 
|  | 3009 | /// See AbstractAttribute::initialize(...). | 
|  | 3010 | void initialize(Attributor &A) override {} | 
|  | 3011 |  | 
|  | 3012 | /// See AbstractAttribute::trackStatistics() | 
|  | 3013 | void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(IsDead) } | 
|  | 3014 | }; | 
|  | 3015 |  | 
|  | 3016 | struct AAIsDeadFunction : public AAIsDead { | 
|  | 3017 | AAIsDeadFunction(const IRPosition &IRP) : AAIsDead(IRP) {} | 
|  | 3018 |  | 
|  | 3019 | /// See AbstractAttribute::initialize(...). | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 3020 | void initialize(Attributor &A) override { | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 3021 | const Function *F = getAssociatedFunction(); | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3022 | if (F && !F->isDeclaration()) { | 
|  | 3023 | ToBeExploredFrom.insert(&F->getEntryBlock().front()); | 
|  | 3024 | assumeLive(A, F->getEntryBlock()); | 
|  | 3025 | } | 
| Stefan Stipanovic | 26121ae | 2019-08-20 23:16:57 +0000 | [diff] [blame] | 3026 | } | 
|  | 3027 |  | 
| Johannes Doerfert | beb5150 | 2019-08-07 22:36:15 +0000 | [diff] [blame] | 3028 | /// See AbstractAttribute::getAsStr(). | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3029 | const std::string getAsStr() const override { | 
| Johannes Doerfert | beb5150 | 2019-08-07 22:36:15 +0000 | [diff] [blame] | 3030 | return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" + | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3031 | std::to_string(getAssociatedFunction()->size()) + "][#TBEP " + | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3032 | std::to_string(ToBeExploredFrom.size()) + "][#KDE " + | 
|  | 3033 | std::to_string(KnownDeadEnds.size()) + "]"; | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3034 | } | 
|  | 3035 |  | 
|  | 3036 | /// See AbstractAttribute::manifest(...). | 
|  | 3037 | ChangeStatus manifest(Attributor &A) override { | 
|  | 3038 | assert(getState().isValidState() && | 
|  | 3039 | "Attempted to manifest an invalid state!"); | 
|  | 3040 |  | 
|  | 3041 | ChangeStatus HasChanged = ChangeStatus::UNCHANGED; | 
| Stefan Stipanovic | 26121ae | 2019-08-20 23:16:57 +0000 | [diff] [blame] | 3042 | Function &F = *getAssociatedFunction(); | 
|  | 3043 |  | 
|  | 3044 | if (AssumedLiveBlocks.empty()) { | 
| Johannes Doerfert | b19cd27 | 2019-09-03 20:42:16 +0000 | [diff] [blame] | 3045 | A.deleteAfterManifest(F); | 
| Stefan Stipanovic | 26121ae | 2019-08-20 23:16:57 +0000 | [diff] [blame] | 3046 | return ChangeStatus::CHANGED; | 
|  | 3047 | } | 
| Johannes Doerfert | 924d213 | 2019-08-05 21:34:45 +0000 | [diff] [blame] | 3048 |  | 
| Johannes Doerfert | beb5150 | 2019-08-07 22:36:15 +0000 | [diff] [blame] | 3049 | // Flag to determine if we can change an invoke to a call assuming the | 
|  | 3050 | // callee is nounwind. This is not possible if the personality of the | 
|  | 3051 | // function allows to catch asynchronous exceptions. | 
| Johannes Doerfert | 924d213 | 2019-08-05 21:34:45 +0000 | [diff] [blame] | 3052 | bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F); | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3053 |  | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3054 | KnownDeadEnds.set_union(ToBeExploredFrom); | 
|  | 3055 | for (const Instruction *DeadEndI : KnownDeadEnds) { | 
|  | 3056 | auto *CB = dyn_cast<CallBase>(DeadEndI); | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3057 | if (!CB) | 
|  | 3058 | continue; | 
|  | 3059 | const auto &NoReturnAA = | 
|  | 3060 | A.getAAFor<AANoReturn>(*this, IRPosition::callsite_function(*CB)); | 
| Johannes Doerfert | c7ab19d | 2019-11-01 21:59:32 -0500 | [diff] [blame] | 3061 | bool MayReturn = !NoReturnAA.isAssumedNoReturn(); | 
|  | 3062 | if (MayReturn && (!Invoke2CallAllowed || !isa<InvokeInst>(CB))) | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3063 | continue; | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3064 |  | 
| Johannes Doerfert | a4088c7 | 2020-01-07 16:01:57 -0600 | [diff] [blame] | 3065 | if (auto *II = dyn_cast<InvokeInst>(DeadEndI)) | 
|  | 3066 | A.registerInvokeWithDeadSuccessor(const_cast<InvokeInst &>(*II)); | 
|  | 3067 | else | 
|  | 3068 | A.changeToUnreachableAfterManifest( | 
|  | 3069 | const_cast<Instruction *>(DeadEndI->getNextNode())); | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3070 | HasChanged = ChangeStatus::CHANGED; | 
|  | 3071 | } | 
|  | 3072 |  | 
| Johannes Doerfert | b19cd27 | 2019-09-03 20:42:16 +0000 | [diff] [blame] | 3073 | for (BasicBlock &BB : F) | 
|  | 3074 | if (!AssumedLiveBlocks.count(&BB)) | 
|  | 3075 | A.deleteAfterManifest(BB); | 
|  | 3076 |  | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3077 | return HasChanged; | 
|  | 3078 | } | 
|  | 3079 |  | 
|  | 3080 | /// See AbstractAttribute::updateImpl(...). | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 3081 | ChangeStatus updateImpl(Attributor &A) override; | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3082 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 3083 | /// See AbstractAttribute::trackStatistics() | 
|  | 3084 | void trackStatistics() const override {} | 
|  | 3085 |  | 
|  | 3086 | /// Returns true if the function is assumed dead. | 
|  | 3087 | bool isAssumedDead() const override { return false; } | 
|  | 3088 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 3089 | /// See AAIsDead::isKnownDead(). | 
|  | 3090 | bool isKnownDead() const override { return false; } | 
|  | 3091 |  | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 3092 | /// See AAIsDead::isAssumedDead(BasicBlock *). | 
| Johannes Doerfert | 4361da2 | 2019-08-04 18:38:53 +0000 | [diff] [blame] | 3093 | bool isAssumedDead(const BasicBlock *BB) const override { | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 3094 | assert(BB->getParent() == getAssociatedFunction() && | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 3095 | "BB must be in the same anchor scope function."); | 
|  | 3096 |  | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3097 | if (!getAssumed()) | 
|  | 3098 | return false; | 
|  | 3099 | return !AssumedLiveBlocks.count(BB); | 
|  | 3100 | } | 
|  | 3101 |  | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 3102 | /// See AAIsDead::isKnownDead(BasicBlock *). | 
| Johannes Doerfert | 4361da2 | 2019-08-04 18:38:53 +0000 | [diff] [blame] | 3103 | bool isKnownDead(const BasicBlock *BB) const override { | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 3104 | return getKnown() && isAssumedDead(BB); | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3105 | } | 
|  | 3106 |  | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 3107 | /// See AAIsDead::isAssumed(Instruction *I). | 
| Johannes Doerfert | 4361da2 | 2019-08-04 18:38:53 +0000 | [diff] [blame] | 3108 | bool isAssumedDead(const Instruction *I) const override { | 
| Johannes Doerfert | 6dedc78 | 2019-08-16 21:31:11 +0000 | [diff] [blame] | 3109 | assert(I->getParent()->getParent() == getAssociatedFunction() && | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 3110 | "Instruction must be in the same anchor scope function."); | 
|  | 3111 |  | 
| Stefan Stipanovic | 7849e41 | 2019-08-03 15:27:41 +0000 | [diff] [blame] | 3112 | if (!getAssumed()) | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 3113 | return false; | 
|  | 3114 |  | 
|  | 3115 | // If it is not in AssumedLiveBlocks then it for sure dead. | 
|  | 3116 | // Otherwise, it can still be after noreturn call in a live block. | 
|  | 3117 | if (!AssumedLiveBlocks.count(I->getParent())) | 
|  | 3118 | return true; | 
|  | 3119 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3120 | // If it is not after a liveness barrier it is live. | 
|  | 3121 | const Instruction *PrevI = I->getPrevNode(); | 
|  | 3122 | while (PrevI) { | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3123 | if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI)) | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3124 | return true; | 
|  | 3125 | PrevI = PrevI->getPrevNode(); | 
|  | 3126 | } | 
|  | 3127 | return false; | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 3128 | } | 
|  | 3129 |  | 
|  | 3130 | /// See AAIsDead::isKnownDead(Instruction *I). | 
| Johannes Doerfert | 4361da2 | 2019-08-04 18:38:53 +0000 | [diff] [blame] | 3131 | bool isKnownDead(const Instruction *I) const override { | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 3132 | return getKnown() && isAssumedDead(I); | 
|  | 3133 | } | 
|  | 3134 |  | 
| Johannes Doerfert | 924d213 | 2019-08-05 21:34:45 +0000 | [diff] [blame] | 3135 | /// Determine if \p F might catch asynchronous exceptions. | 
|  | 3136 | static bool mayCatchAsynchronousExceptions(const Function &F) { | 
|  | 3137 | return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F); | 
|  | 3138 | } | 
|  | 3139 |  | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 3140 | /// Assume \p BB is (partially) live now and indicate to the Attributor \p A | 
|  | 3141 | /// that internal function called from \p BB should now be looked at. | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3142 | bool assumeLive(Attributor &A, const BasicBlock &BB) { | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 3143 | if (!AssumedLiveBlocks.insert(&BB).second) | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3144 | return false; | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 3145 |  | 
|  | 3146 | // We assume that all of BB is (probably) live now and if there are calls to | 
|  | 3147 | // internal functions we will assume that those are now live as well. This | 
|  | 3148 | // is a performance optimization for blocks with calls to a lot of internal | 
|  | 3149 | // functions. It can however cause dead functions to be treated as live. | 
|  | 3150 | for (const Instruction &I : BB) | 
|  | 3151 | if (ImmutableCallSite ICS = ImmutableCallSite(&I)) | 
|  | 3152 | if (const Function *F = ICS.getCalledFunction()) | 
| Johannes Doerfert | 766f2cc | 2019-10-07 23:21:52 +0000 | [diff] [blame] | 3153 | if (F->hasLocalLinkage()) | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 3154 | A.markLiveInternalFunction(*F); | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3155 | return true; | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 3156 | } | 
|  | 3157 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3158 | /// Collection of instructions that need to be explored again, e.g., we | 
|  | 3159 | /// did assume they do not transfer control to (one of their) successors. | 
|  | 3160 | SmallSetVector<const Instruction *, 8> ToBeExploredFrom; | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3161 |  | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3162 | /// Collection of instructions that are known to not transfer control. | 
|  | 3163 | SmallSetVector<const Instruction *, 8> KnownDeadEnds; | 
|  | 3164 |  | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3165 | /// Collection of all assumed live BasicBlocks. | 
| Johannes Doerfert | 4361da2 | 2019-08-04 18:38:53 +0000 | [diff] [blame] | 3166 | DenseSet<const BasicBlock *> AssumedLiveBlocks; | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3167 | }; | 
|  | 3168 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3169 | static bool | 
|  | 3170 | identifyAliveSuccessors(Attributor &A, const CallBase &CB, | 
|  | 3171 | AbstractAttribute &AA, | 
|  | 3172 | SmallVectorImpl<const Instruction *> &AliveSuccessors) { | 
|  | 3173 | const IRPosition &IPos = IRPosition::callsite_function(CB); | 
|  | 3174 |  | 
|  | 3175 | const auto &NoReturnAA = A.getAAFor<AANoReturn>(AA, IPos); | 
|  | 3176 | if (NoReturnAA.isAssumedNoReturn()) | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3177 | return !NoReturnAA.isKnownNoReturn(); | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3178 | if (CB.isTerminator()) | 
|  | 3179 | AliveSuccessors.push_back(&CB.getSuccessor(0)->front()); | 
|  | 3180 | else | 
|  | 3181 | AliveSuccessors.push_back(CB.getNextNode()); | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 3182 | return false; | 
|  | 3183 | } | 
|  | 3184 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3185 | static bool | 
|  | 3186 | identifyAliveSuccessors(Attributor &A, const InvokeInst &II, | 
|  | 3187 | AbstractAttribute &AA, | 
|  | 3188 | SmallVectorImpl<const Instruction *> &AliveSuccessors) { | 
|  | 3189 | bool UsedAssumedInformation = | 
|  | 3190 | identifyAliveSuccessors(A, cast<CallBase>(II), AA, AliveSuccessors); | 
| Johannes Doerfert | 924d213 | 2019-08-05 21:34:45 +0000 | [diff] [blame] | 3191 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3192 | // First, determine if we can change an invoke to a call assuming the | 
|  | 3193 | // callee is nounwind. This is not possible if the personality of the | 
|  | 3194 | // function allows to catch asynchronous exceptions. | 
|  | 3195 | if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*II.getFunction())) { | 
|  | 3196 | AliveSuccessors.push_back(&II.getUnwindDest()->front()); | 
|  | 3197 | } else { | 
|  | 3198 | const IRPosition &IPos = IRPosition::callsite_function(II); | 
|  | 3199 | const auto &AANoUnw = A.getAAFor<AANoUnwind>(AA, IPos); | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3200 | if (AANoUnw.isAssumedNoUnwind()) { | 
|  | 3201 | UsedAssumedInformation |= !AANoUnw.isKnownNoUnwind(); | 
|  | 3202 | } else { | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3203 | AliveSuccessors.push_back(&II.getUnwindDest()->front()); | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3204 | } | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3205 | } | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3206 | return UsedAssumedInformation; | 
|  | 3207 | } | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3208 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3209 | static bool | 
|  | 3210 | identifyAliveSuccessors(Attributor &A, const BranchInst &BI, | 
|  | 3211 | AbstractAttribute &AA, | 
|  | 3212 | SmallVectorImpl<const Instruction *> &AliveSuccessors) { | 
|  | 3213 | bool UsedAssumedInformation = false; | 
|  | 3214 | if (BI.getNumSuccessors() == 1) { | 
|  | 3215 | AliveSuccessors.push_back(&BI.getSuccessor(0)->front()); | 
|  | 3216 | } else { | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3217 | Optional<ConstantInt *> CI = | 
|  | 3218 | getAssumedConstant(A, *BI.getCondition(), AA, UsedAssumedInformation); | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3219 | if (!CI.hasValue()) { | 
|  | 3220 | // No value yet, assume both edges are dead. | 
|  | 3221 | } else if (CI.getValue()) { | 
|  | 3222 | const BasicBlock *SuccBB = | 
|  | 3223 | BI.getSuccessor(1 - CI.getValue()->getZExtValue()); | 
|  | 3224 | AliveSuccessors.push_back(&SuccBB->front()); | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3225 | } else { | 
|  | 3226 | AliveSuccessors.push_back(&BI.getSuccessor(0)->front()); | 
|  | 3227 | AliveSuccessors.push_back(&BI.getSuccessor(1)->front()); | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3228 | UsedAssumedInformation = false; | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3229 | } | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3230 | } | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3231 | return UsedAssumedInformation; | 
|  | 3232 | } | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3233 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3234 | static bool | 
|  | 3235 | identifyAliveSuccessors(Attributor &A, const SwitchInst &SI, | 
|  | 3236 | AbstractAttribute &AA, | 
|  | 3237 | SmallVectorImpl<const Instruction *> &AliveSuccessors) { | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3238 | bool UsedAssumedInformation = false; | 
|  | 3239 | Optional<ConstantInt *> CI = | 
|  | 3240 | getAssumedConstant(A, *SI.getCondition(), AA, UsedAssumedInformation); | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3241 | if (!CI.hasValue()) { | 
|  | 3242 | // No value yet, assume all edges are dead. | 
|  | 3243 | } else if (CI.getValue()) { | 
|  | 3244 | for (auto &CaseIt : SI.cases()) { | 
|  | 3245 | if (CaseIt.getCaseValue() == CI.getValue()) { | 
|  | 3246 | AliveSuccessors.push_back(&CaseIt.getCaseSuccessor()->front()); | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3247 | return UsedAssumedInformation; | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3248 | } | 
|  | 3249 | } | 
| Johannes Doerfert | ed47a9c | 2019-11-01 13:57:49 -0500 | [diff] [blame] | 3250 | AliveSuccessors.push_back(&SI.getDefaultDest()->front()); | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3251 | return UsedAssumedInformation; | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3252 | } else { | 
|  | 3253 | for (const BasicBlock *SuccBB : successors(SI.getParent())) | 
|  | 3254 | AliveSuccessors.push_back(&SuccBB->front()); | 
|  | 3255 | } | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3256 | return UsedAssumedInformation; | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3257 | } | 
|  | 3258 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 3259 | ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A) { | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3260 | ChangeStatus Change = ChangeStatus::UNCHANGED; | 
| Stefan Stipanovic | 26121ae | 2019-08-20 23:16:57 +0000 | [diff] [blame] | 3261 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3262 | LLVM_DEBUG(dbgs() << "[AAIsDead] Live [" << AssumedLiveBlocks.size() << "/" | 
|  | 3263 | << getAssociatedFunction()->size() << "] BBs and " | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3264 | << ToBeExploredFrom.size() << " exploration points and " | 
|  | 3265 | << KnownDeadEnds.size() << " known dead ends\n"); | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3266 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3267 | // Copy and clear the list of instructions we need to explore from. It is | 
|  | 3268 | // refilled with instructions the next update has to look at. | 
|  | 3269 | SmallVector<const Instruction *, 8> Worklist(ToBeExploredFrom.begin(), | 
|  | 3270 | ToBeExploredFrom.end()); | 
|  | 3271 | decltype(ToBeExploredFrom) NewToBeExploredFrom; | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3272 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3273 | SmallVector<const Instruction *, 8> AliveSuccessors; | 
|  | 3274 | while (!Worklist.empty()) { | 
|  | 3275 | const Instruction *I = Worklist.pop_back_val(); | 
|  | 3276 | LLVM_DEBUG(dbgs() << "[AAIsDead] Exploration inst: " << *I << "\n"); | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3277 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3278 | AliveSuccessors.clear(); | 
|  | 3279 |  | 
|  | 3280 | bool UsedAssumedInformation = false; | 
|  | 3281 | switch (I->getOpcode()) { | 
|  | 3282 | // TODO: look for (assumed) UB to backwards propagate "deadness". | 
|  | 3283 | default: | 
|  | 3284 | if (I->isTerminator()) { | 
|  | 3285 | for (const BasicBlock *SuccBB : successors(I->getParent())) | 
|  | 3286 | AliveSuccessors.push_back(&SuccBB->front()); | 
|  | 3287 | } else { | 
|  | 3288 | AliveSuccessors.push_back(I->getNextNode()); | 
|  | 3289 | } | 
|  | 3290 | break; | 
|  | 3291 | case Instruction::Call: | 
|  | 3292 | UsedAssumedInformation = identifyAliveSuccessors(A, cast<CallInst>(*I), | 
|  | 3293 | *this, AliveSuccessors); | 
|  | 3294 | break; | 
|  | 3295 | case Instruction::Invoke: | 
|  | 3296 | UsedAssumedInformation = identifyAliveSuccessors(A, cast<InvokeInst>(*I), | 
|  | 3297 | *this, AliveSuccessors); | 
|  | 3298 | break; | 
|  | 3299 | case Instruction::Br: | 
|  | 3300 | UsedAssumedInformation = identifyAliveSuccessors(A, cast<BranchInst>(*I), | 
|  | 3301 | *this, AliveSuccessors); | 
|  | 3302 | break; | 
|  | 3303 | case Instruction::Switch: | 
|  | 3304 | UsedAssumedInformation = identifyAliveSuccessors(A, cast<SwitchInst>(*I), | 
|  | 3305 | *this, AliveSuccessors); | 
|  | 3306 | break; | 
| Johannes Doerfert | 4361da2 | 2019-08-04 18:38:53 +0000 | [diff] [blame] | 3307 | } | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3308 |  | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3309 | if (UsedAssumedInformation) { | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3310 | NewToBeExploredFrom.insert(I); | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3311 | } else { | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3312 | Change = ChangeStatus::CHANGED; | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3313 | if (AliveSuccessors.empty() || | 
|  | 3314 | (I->isTerminator() && AliveSuccessors.size() < I->getNumSuccessors())) | 
|  | 3315 | KnownDeadEnds.insert(I); | 
|  | 3316 | } | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3317 |  | 
|  | 3318 | LLVM_DEBUG(dbgs() << "[AAIsDead] #AliveSuccessors: " | 
|  | 3319 | << AliveSuccessors.size() << " UsedAssumedInformation: " | 
|  | 3320 | << UsedAssumedInformation << "\n"); | 
|  | 3321 |  | 
|  | 3322 | for (const Instruction *AliveSuccessor : AliveSuccessors) { | 
|  | 3323 | if (!I->isTerminator()) { | 
|  | 3324 | assert(AliveSuccessors.size() == 1 && | 
|  | 3325 | "Non-terminator expected to have a single successor!"); | 
|  | 3326 | Worklist.push_back(AliveSuccessor); | 
|  | 3327 | } else { | 
|  | 3328 | if (assumeLive(A, *AliveSuccessor->getParent())) | 
|  | 3329 | Worklist.push_back(AliveSuccessor); | 
|  | 3330 | } | 
| Johannes Doerfert | 4361da2 | 2019-08-04 18:38:53 +0000 | [diff] [blame] | 3331 | } | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3332 | } | 
|  | 3333 |  | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3334 | ToBeExploredFrom = std::move(NewToBeExploredFrom); | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3335 |  | 
| Johannes Doerfert | d620781 | 2019-08-07 22:32:38 +0000 | [diff] [blame] | 3336 | // If we know everything is live there is no need to query for liveness. | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3337 | // Instead, indicating a pessimistic fixpoint will cause the state to be | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3338 | // "invalid" and all queries to be answered conservatively without lookups. | 
|  | 3339 | // To be in this state we have to (1) finished the exploration and (3) not | 
|  | 3340 | // discovered any non-trivial dead end and (2) not ruled unreachable code | 
|  | 3341 | // dead. | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3342 | if (ToBeExploredFrom.empty() && | 
| Johannes Doerfert | 3cbe331 | 2019-11-01 21:04:54 -0500 | [diff] [blame] | 3343 | getAssociatedFunction()->size() == AssumedLiveBlocks.size() && | 
|  | 3344 | llvm::all_of(KnownDeadEnds, [](const Instruction *DeadEndI) { | 
|  | 3345 | return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0; | 
|  | 3346 | })) | 
| Johannes Doerfert | dac2d40 | 2019-10-29 11:47:47 -0500 | [diff] [blame] | 3347 | return indicatePessimisticFixpoint(); | 
|  | 3348 | return Change; | 
| Stefan Stipanovic | 6058b86 | 2019-07-22 23:58:23 +0000 | [diff] [blame] | 3349 | } | 
|  | 3350 |  | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 3351 | /// Liveness information for a call sites. | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 3352 | struct AAIsDeadCallSite final : AAIsDeadFunction { | 
|  | 3353 | AAIsDeadCallSite(const IRPosition &IRP) : AAIsDeadFunction(IRP) {} | 
| Johannes Doerfert | 07a5c12 | 2019-08-28 14:09:14 +0000 | [diff] [blame] | 3354 |  | 
|  | 3355 | /// See AbstractAttribute::initialize(...). | 
|  | 3356 | void initialize(Attributor &A) override { | 
|  | 3357 | // TODO: Once we have call site specific value information we can provide | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 3358 | //       call site specific liveness information and then it makes | 
| Johannes Doerfert | 07a5c12 | 2019-08-28 14:09:14 +0000 | [diff] [blame] | 3359 | //       sense to specialize attributes for call sites instead of | 
|  | 3360 | //       redirecting requests to the callee. | 
|  | 3361 | llvm_unreachable("Abstract attributes for liveness are not " | 
|  | 3362 | "supported for call sites yet!"); | 
|  | 3363 | } | 
|  | 3364 |  | 
|  | 3365 | /// See AbstractAttribute::updateImpl(...). | 
|  | 3366 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 3367 | return indicatePessimisticFixpoint(); | 
|  | 3368 | } | 
|  | 3369 |  | 
|  | 3370 | /// See AbstractAttribute::trackStatistics() | 
|  | 3371 | void trackStatistics() const override {} | 
|  | 3372 | }; | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 3373 |  | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 3374 | /// -------------------- Dereferenceable Argument Attribute -------------------- | 
|  | 3375 |  | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3376 | template <> | 
|  | 3377 | ChangeStatus clampStateAndIndicateChange<DerefState>(DerefState &S, | 
|  | 3378 | const DerefState &R) { | 
| Johannes Doerfert | 3178424 | 2019-10-29 23:18:49 -0500 | [diff] [blame] | 3379 | ChangeStatus CS0 = | 
|  | 3380 | clampStateAndIndicateChange(S.DerefBytesState, R.DerefBytesState); | 
|  | 3381 | ChangeStatus CS1 = clampStateAndIndicateChange(S.GlobalState, R.GlobalState); | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3382 | return CS0 | CS1; | 
|  | 3383 | } | 
|  | 3384 |  | 
| Hideto Ueno | 70576ca | 2019-08-22 14:18:29 +0000 | [diff] [blame] | 3385 | struct AADereferenceableImpl : AADereferenceable { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 3386 | AADereferenceableImpl(const IRPosition &IRP) : AADereferenceable(IRP) {} | 
| Johannes Doerfert | 344d038 | 2019-08-07 22:34:26 +0000 | [diff] [blame] | 3387 | using StateType = DerefState; | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 3388 |  | 
| Johannes Doerfert | 6a1274a | 2019-08-14 21:31:32 +0000 | [diff] [blame] | 3389 | void initialize(Attributor &A) override { | 
|  | 3390 | SmallVector<Attribute, 4> Attrs; | 
|  | 3391 | getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull}, | 
|  | 3392 | Attrs); | 
|  | 3393 | for (const Attribute &Attr : Attrs) | 
|  | 3394 | takeKnownDerefBytesMaximum(Attr.getValueAsInt()); | 
|  | 3395 |  | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 3396 | NonNullAA = &A.getAAFor<AANonNull>(*this, getIRPosition(), | 
|  | 3397 | /* TrackDependence */ false); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 3398 |  | 
|  | 3399 | const IRPosition &IRP = this->getIRPosition(); | 
|  | 3400 | bool IsFnInterface = IRP.isFnInterfaceKind(); | 
|  | 3401 | const Function *FnScope = IRP.getAnchorScope(); | 
|  | 3402 | if (IsFnInterface && (!FnScope || !FnScope->hasExactDefinition())) | 
|  | 3403 | indicatePessimisticFixpoint(); | 
| Johannes Doerfert | 6a1274a | 2019-08-14 21:31:32 +0000 | [diff] [blame] | 3404 | } | 
|  | 3405 |  | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 3406 | /// See AbstractAttribute::getState() | 
|  | 3407 | /// { | 
| Johannes Doerfert | 344d038 | 2019-08-07 22:34:26 +0000 | [diff] [blame] | 3408 | StateType &getState() override { return *this; } | 
|  | 3409 | const StateType &getState() const override { return *this; } | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 3410 | /// } | 
|  | 3411 |  | 
| Hideto Ueno | 6c742fd | 2019-11-29 06:55:58 +0000 | [diff] [blame] | 3412 | /// Helper function for collecting accessed bytes in must-be-executed-context | 
|  | 3413 | void addAccessedBytesForUse(Attributor &A, const Use *U, | 
|  | 3414 | const Instruction *I) { | 
|  | 3415 | const Value *UseV = U->get(); | 
|  | 3416 | if (!UseV->getType()->isPointerTy()) | 
|  | 3417 | return; | 
|  | 3418 |  | 
|  | 3419 | Type *PtrTy = UseV->getType(); | 
|  | 3420 | const DataLayout &DL = A.getDataLayout(); | 
|  | 3421 | int64_t Offset; | 
|  | 3422 | if (const Value *Base = getBasePointerOfAccessPointerOperand( | 
|  | 3423 | I, Offset, DL, /*AllowNonInbounds*/ true)) { | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 3424 | if (Base == &getAssociatedValue() && | 
| Johannes Doerfert | b6dbd0f | 2020-01-26 02:49:58 -0600 | [diff] [blame] | 3425 | getPointerOperand(I, /* AllowVolatile */ false) == UseV) { | 
| Hideto Ueno | 6c742fd | 2019-11-29 06:55:58 +0000 | [diff] [blame] | 3426 | uint64_t Size = DL.getTypeStoreSize(PtrTy->getPointerElementType()); | 
|  | 3427 | addAccessedBytes(Offset, Size); | 
|  | 3428 | } | 
|  | 3429 | } | 
|  | 3430 | return; | 
|  | 3431 | } | 
|  | 3432 |  | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 3433 | /// See AAFromMustBeExecutedContext | 
|  | 3434 | bool followUse(Attributor &A, const Use *U, const Instruction *I) { | 
|  | 3435 | bool IsNonNull = false; | 
|  | 3436 | bool TrackUse = false; | 
|  | 3437 | int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse( | 
|  | 3438 | A, *this, getAssociatedValue(), U, I, IsNonNull, TrackUse); | 
| Hideto Ueno | 6c742fd | 2019-11-29 06:55:58 +0000 | [diff] [blame] | 3439 |  | 
|  | 3440 | addAccessedBytesForUse(A, U, I); | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 3441 | takeKnownDerefBytesMaximum(DerefBytes); | 
|  | 3442 | return TrackUse; | 
|  | 3443 | } | 
|  | 3444 |  | 
| Hideto Ueno | dfedae5 | 2019-11-29 06:45:07 +0000 | [diff] [blame] | 3445 | /// See AbstractAttribute::manifest(...). | 
|  | 3446 | ChangeStatus manifest(Attributor &A) override { | 
|  | 3447 | ChangeStatus Change = AADereferenceable::manifest(A); | 
|  | 3448 | if (isAssumedNonNull() && hasAttr(Attribute::DereferenceableOrNull)) { | 
|  | 3449 | removeAttrs({Attribute::DereferenceableOrNull}); | 
|  | 3450 | return ChangeStatus::CHANGED; | 
|  | 3451 | } | 
|  | 3452 | return Change; | 
|  | 3453 | } | 
|  | 3454 |  | 
| Johannes Doerfert | eccdf08 | 2019-08-05 23:35:12 +0000 | [diff] [blame] | 3455 | void getDeducedAttributes(LLVMContext &Ctx, | 
|  | 3456 | SmallVectorImpl<Attribute> &Attrs) const override { | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 3457 | // TODO: Add *_globally support | 
|  | 3458 | if (isAssumedNonNull()) | 
|  | 3459 | Attrs.emplace_back(Attribute::getWithDereferenceableBytes( | 
|  | 3460 | Ctx, getAssumedDereferenceableBytes())); | 
|  | 3461 | else | 
|  | 3462 | Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes( | 
|  | 3463 | Ctx, getAssumedDereferenceableBytes())); | 
|  | 3464 | } | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 3465 |  | 
|  | 3466 | /// See AbstractAttribute::getAsStr(). | 
|  | 3467 | const std::string getAsStr() const override { | 
|  | 3468 | if (!getAssumedDereferenceableBytes()) | 
|  | 3469 | return "unknown-dereferenceable"; | 
|  | 3470 | return std::string("dereferenceable") + | 
|  | 3471 | (isAssumedNonNull() ? "" : "_or_null") + | 
|  | 3472 | (isAssumedGlobal() ? "_globally" : "") + "<" + | 
|  | 3473 | std::to_string(getKnownDereferenceableBytes()) + "-" + | 
|  | 3474 | std::to_string(getAssumedDereferenceableBytes()) + ">"; | 
|  | 3475 | } | 
|  | 3476 | }; | 
|  | 3477 |  | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3478 | /// Dereferenceable attribute for a floating value. | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 3479 | struct AADereferenceableFloating | 
|  | 3480 | : AAFromMustBeExecutedContext<AADereferenceable, AADereferenceableImpl> { | 
|  | 3481 | using Base = | 
|  | 3482 | AAFromMustBeExecutedContext<AADereferenceable, AADereferenceableImpl>; | 
|  | 3483 | AADereferenceableFloating(const IRPosition &IRP) : Base(IRP) {} | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 3484 |  | 
|  | 3485 | /// See AbstractAttribute::updateImpl(...). | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3486 | ChangeStatus updateImpl(Attributor &A) override { | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 3487 | ChangeStatus Change = Base::updateImpl(A); | 
|  | 3488 |  | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3489 | const DataLayout &DL = A.getDataLayout(); | 
|  | 3490 |  | 
|  | 3491 | auto VisitValueCB = [&](Value &V, DerefState &T, bool Stripped) -> bool { | 
|  | 3492 | unsigned IdxWidth = | 
|  | 3493 | DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace()); | 
|  | 3494 | APInt Offset(IdxWidth, 0); | 
|  | 3495 | const Value *Base = | 
|  | 3496 | V.stripAndAccumulateInBoundsConstantOffsets(DL, Offset); | 
|  | 3497 |  | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 3498 | const auto &AA = | 
|  | 3499 | A.getAAFor<AADereferenceable>(*this, IRPosition::value(*Base)); | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3500 | int64_t DerefBytes = 0; | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 3501 | if (!Stripped && this == &AA) { | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3502 | // Use IR information if we did not strip anything. | 
|  | 3503 | // TODO: track globally. | 
|  | 3504 | bool CanBeNull; | 
|  | 3505 | DerefBytes = Base->getPointerDereferenceableBytes(DL, CanBeNull); | 
|  | 3506 | T.GlobalState.indicatePessimisticFixpoint(); | 
|  | 3507 | } else { | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 3508 | const DerefState &DS = static_cast<const DerefState &>(AA.getState()); | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3509 | DerefBytes = DS.DerefBytesState.getAssumed(); | 
|  | 3510 | T.GlobalState &= DS.GlobalState; | 
|  | 3511 | } | 
|  | 3512 |  | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 3513 | // TODO: Use `AAConstantRange` to infer dereferenceable bytes. | 
|  | 3514 |  | 
| Johannes Doerfert | 2f2d7c3 | 2019-08-23 15:45:46 +0000 | [diff] [blame] | 3515 | // For now we do not try to "increase" dereferenceability due to negative | 
|  | 3516 | // indices as we first have to come up with code to deal with loops and | 
|  | 3517 | // for overflows of the dereferenceable bytes. | 
| Johannes Doerfert | 785fad3 | 2019-08-23 17:29:23 +0000 | [diff] [blame] | 3518 | int64_t OffsetSExt = Offset.getSExtValue(); | 
|  | 3519 | if (OffsetSExt < 0) | 
| Johannes Doerfert | db6efb0 | 2019-10-13 20:40:10 +0000 | [diff] [blame] | 3520 | OffsetSExt = 0; | 
| Johannes Doerfert | 2f2d7c3 | 2019-08-23 15:45:46 +0000 | [diff] [blame] | 3521 |  | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3522 | T.takeAssumedDerefBytesMinimum( | 
| Johannes Doerfert | 785fad3 | 2019-08-23 17:29:23 +0000 | [diff] [blame] | 3523 | std::max(int64_t(0), DerefBytes - OffsetSExt)); | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3524 |  | 
| Johannes Doerfert | 785fad3 | 2019-08-23 17:29:23 +0000 | [diff] [blame] | 3525 | if (this == &AA) { | 
|  | 3526 | if (!Stripped) { | 
|  | 3527 | // If nothing was stripped IR information is all we got. | 
|  | 3528 | T.takeKnownDerefBytesMaximum( | 
|  | 3529 | std::max(int64_t(0), DerefBytes - OffsetSExt)); | 
|  | 3530 | T.indicatePessimisticFixpoint(); | 
|  | 3531 | } else if (OffsetSExt > 0) { | 
|  | 3532 | // If something was stripped but there is circular reasoning we look | 
|  | 3533 | // for the offset. If it is positive we basically decrease the | 
|  | 3534 | // dereferenceable bytes in a circluar loop now, which will simply | 
|  | 3535 | // drive them down to the known value in a very slow way which we | 
|  | 3536 | // can accelerate. | 
|  | 3537 | T.indicatePessimisticFixpoint(); | 
|  | 3538 | } | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3539 | } | 
|  | 3540 |  | 
|  | 3541 | return T.isValidState(); | 
|  | 3542 | }; | 
|  | 3543 |  | 
|  | 3544 | DerefState T; | 
|  | 3545 | if (!genericValueTraversal<AADereferenceable, DerefState>( | 
|  | 3546 | A, getIRPosition(), *this, T, VisitValueCB)) | 
|  | 3547 | return indicatePessimisticFixpoint(); | 
|  | 3548 |  | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 3549 | return Change | clampStateAndIndicateChange(getState(), T); | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3550 | } | 
|  | 3551 |  | 
|  | 3552 | /// See AbstractAttribute::trackStatistics() | 
|  | 3553 | void trackStatistics() const override { | 
|  | 3554 | STATS_DECLTRACK_FLOATING_ATTR(dereferenceable) | 
|  | 3555 | } | 
|  | 3556 | }; | 
|  | 3557 |  | 
|  | 3558 | /// Dereferenceable attribute for a return value. | 
|  | 3559 | struct AADereferenceableReturned final | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 3560 | : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> { | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3561 | AADereferenceableReturned(const IRPosition &IRP) | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 3562 | : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>( | 
|  | 3563 | IRP) {} | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 3564 |  | 
|  | 3565 | /// See AbstractAttribute::trackStatistics() | 
|  | 3566 | void trackStatistics() const override { | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 3567 | STATS_DECLTRACK_FNRET_ATTR(dereferenceable) | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 3568 | } | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 3569 | }; | 
|  | 3570 |  | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3571 | /// Dereferenceable attribute for an argument | 
|  | 3572 | struct AADereferenceableArgument final | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 3573 | : AAArgumentFromCallSiteArgumentsAndMustBeExecutedContext< | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 3574 | AADereferenceable, AADereferenceableImpl> { | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 3575 | using Base = AAArgumentFromCallSiteArgumentsAndMustBeExecutedContext< | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 3576 | AADereferenceable, AADereferenceableImpl>; | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 3577 | AADereferenceableArgument(const IRPosition &IRP) : Base(IRP) {} | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 3578 |  | 
|  | 3579 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 3580 | void trackStatistics() const override { | 
| Johannes Doerfert | 169af99 | 2019-08-20 06:09:56 +0000 | [diff] [blame] | 3581 | STATS_DECLTRACK_ARG_ATTR(dereferenceable) | 
|  | 3582 | } | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 3583 | }; | 
|  | 3584 |  | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 3585 | /// Dereferenceable attribute for a call site argument. | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3586 | struct AADereferenceableCallSiteArgument final : AADereferenceableFloating { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 3587 | AADereferenceableCallSiteArgument(const IRPosition &IRP) | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3588 | : AADereferenceableFloating(IRP) {} | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 3589 |  | 
|  | 3590 | /// See AbstractAttribute::trackStatistics() | 
|  | 3591 | void trackStatistics() const override { | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 3592 | STATS_DECLTRACK_CSARG_ATTR(dereferenceable) | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 3593 | } | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 3594 | }; | 
|  | 3595 |  | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 3596 | /// Dereferenceable attribute deduction for a call site return value. | 
| Hideto Ueno | 96e6ce4 | 2019-10-08 15:25:56 +0000 | [diff] [blame] | 3597 | struct AADereferenceableCallSiteReturned final | 
|  | 3598 | : AACallSiteReturnedFromReturnedAndMustBeExecutedContext< | 
|  | 3599 | AADereferenceable, AADereferenceableImpl> { | 
|  | 3600 | using Base = AACallSiteReturnedFromReturnedAndMustBeExecutedContext< | 
|  | 3601 | AADereferenceable, AADereferenceableImpl>; | 
|  | 3602 | AADereferenceableCallSiteReturned(const IRPosition &IRP) : Base(IRP) {} | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 3603 |  | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 3604 | /// See AbstractAttribute::trackStatistics() | 
|  | 3605 | void trackStatistics() const override { | 
|  | 3606 | STATS_DECLTRACK_CS_ATTR(dereferenceable); | 
|  | 3607 | } | 
|  | 3608 | }; | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 3609 |  | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 3610 | // ------------------------ Align Argument Attribute ------------------------ | 
|  | 3611 |  | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3612 | static unsigned int getKnownAlignForUse(Attributor &A, | 
|  | 3613 | AbstractAttribute &QueryingAA, | 
|  | 3614 | Value &AssociatedValue, const Use *U, | 
|  | 3615 | const Instruction *I, bool &TrackUse) { | 
| Hideto Ueno | 78a7502 | 2019-11-26 07:51:59 +0000 | [diff] [blame] | 3616 | // We need to follow common pointer manipulation uses to the accesses they | 
|  | 3617 | // feed into. | 
|  | 3618 | if (isa<CastInst>(I)) { | 
| Johannes Doerfert | c90681b | 2020-01-02 16:41:17 -0600 | [diff] [blame] | 3619 | // Follow all but ptr2int casts. | 
|  | 3620 | TrackUse = !isa<PtrToIntInst>(I); | 
| Hideto Ueno | 78a7502 | 2019-11-26 07:51:59 +0000 | [diff] [blame] | 3621 | return 0; | 
|  | 3622 | } | 
|  | 3623 | if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) { | 
|  | 3624 | if (GEP->hasAllConstantIndices()) { | 
|  | 3625 | TrackUse = true; | 
|  | 3626 | return 0; | 
|  | 3627 | } | 
|  | 3628 | } | 
|  | 3629 |  | 
|  | 3630 | unsigned Alignment = 0; | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3631 | if (ImmutableCallSite ICS = ImmutableCallSite(I)) { | 
|  | 3632 | if (ICS.isBundleOperand(U) || ICS.isCallee(U)) | 
|  | 3633 | return 0; | 
|  | 3634 |  | 
|  | 3635 | unsigned ArgNo = ICS.getArgumentNo(U); | 
|  | 3636 | IRPosition IRP = IRPosition::callsite_argument(ICS, ArgNo); | 
|  | 3637 | // As long as we only use known information there is no need to track | 
|  | 3638 | // dependences here. | 
|  | 3639 | auto &AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP, | 
|  | 3640 | /* TrackDependence */ false); | 
| Hideto Ueno | 78a7502 | 2019-11-26 07:51:59 +0000 | [diff] [blame] | 3641 | Alignment = AlignAA.getKnownAlign(); | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3642 | } | 
|  | 3643 |  | 
| Hideto Ueno | 78a7502 | 2019-11-26 07:51:59 +0000 | [diff] [blame] | 3644 | const Value *UseV = U->get(); | 
| Johannes Doerfert | 30ae859 | 2020-01-10 12:13:10 -0600 | [diff] [blame] | 3645 | if (auto *SI = dyn_cast<StoreInst>(I)) { | 
|  | 3646 | if (SI->getPointerOperand() == UseV) | 
|  | 3647 | Alignment = SI->getAlignment(); | 
|  | 3648 | } else if (auto *LI = dyn_cast<LoadInst>(I)) | 
| Hideto Ueno | 78a7502 | 2019-11-26 07:51:59 +0000 | [diff] [blame] | 3649 | Alignment = LI->getAlignment(); | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3650 |  | 
| Hideto Ueno | 78a7502 | 2019-11-26 07:51:59 +0000 | [diff] [blame] | 3651 | if (Alignment <= 1) | 
|  | 3652 | return 0; | 
|  | 3653 |  | 
|  | 3654 | auto &DL = A.getDataLayout(); | 
|  | 3655 | int64_t Offset; | 
|  | 3656 |  | 
|  | 3657 | if (const Value *Base = GetPointerBaseWithConstantOffset(UseV, Offset, DL)) { | 
|  | 3658 | if (Base == &AssociatedValue) { | 
|  | 3659 | // BasePointerAddr + Offset = Alignment * Q for some integer Q. | 
|  | 3660 | // So we can say that the maximum power of two which is a divisor of | 
|  | 3661 | // gcd(Offset, Alignment) is an alignment. | 
|  | 3662 |  | 
|  | 3663 | uint32_t gcd = | 
|  | 3664 | greatestCommonDivisor(uint32_t(abs((int32_t)Offset)), Alignment); | 
|  | 3665 | Alignment = llvm::PowerOf2Floor(gcd); | 
|  | 3666 | } | 
|  | 3667 | } | 
|  | 3668 |  | 
|  | 3669 | return Alignment; | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3670 | } | 
| Johannes Doerfert | 344d038 | 2019-08-07 22:34:26 +0000 | [diff] [blame] | 3671 | struct AAAlignImpl : AAAlign { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 3672 | AAAlignImpl(const IRPosition &IRP) : AAAlign(IRP) {} | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 3673 |  | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3674 | /// See AbstractAttribute::initialize(...). | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 3675 | void initialize(Attributor &A) override { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 3676 | SmallVector<Attribute, 4> Attrs; | 
|  | 3677 | getAttrs({Attribute::Alignment}, Attrs); | 
|  | 3678 | for (const Attribute &Attr : Attrs) | 
|  | 3679 | takeKnownMaximum(Attr.getValueAsInt()); | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 3680 |  | 
|  | 3681 | if (getIRPosition().isFnInterfaceKind() && | 
|  | 3682 | (!getAssociatedFunction() || | 
|  | 3683 | !getAssociatedFunction()->hasExactDefinition())) | 
|  | 3684 | indicatePessimisticFixpoint(); | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 3685 | } | 
|  | 3686 |  | 
| Johannes Doerfert | 5a5a139 | 2019-08-23 20:20:10 +0000 | [diff] [blame] | 3687 | /// See AbstractAttribute::manifest(...). | 
|  | 3688 | ChangeStatus manifest(Attributor &A) override { | 
| Johannes Doerfert | 30179d7 | 2020-01-12 00:25:45 -0600 | [diff] [blame] | 3689 | ChangeStatus LoadStoreChanged = ChangeStatus::UNCHANGED; | 
| Johannes Doerfert | 5a5a139 | 2019-08-23 20:20:10 +0000 | [diff] [blame] | 3690 |  | 
|  | 3691 | // Check for users that allow alignment annotations. | 
|  | 3692 | Value &AnchorVal = getIRPosition().getAnchorValue(); | 
|  | 3693 | for (const Use &U : AnchorVal.uses()) { | 
|  | 3694 | if (auto *SI = dyn_cast<StoreInst>(U.getUser())) { | 
|  | 3695 | if (SI->getPointerOperand() == &AnchorVal) | 
|  | 3696 | if (SI->getAlignment() < getAssumedAlign()) { | 
|  | 3697 | STATS_DECLTRACK(AAAlign, Store, | 
| James Henderson | d68904f | 2020-01-06 10:15:44 +0000 | [diff] [blame] | 3698 | "Number of times alignment added to a store"); | 
| Guillaume Chatelet | d400d45 | 2019-10-03 13:17:21 +0000 | [diff] [blame] | 3699 | SI->setAlignment(Align(getAssumedAlign())); | 
| Johannes Doerfert | 30179d7 | 2020-01-12 00:25:45 -0600 | [diff] [blame] | 3700 | LoadStoreChanged = ChangeStatus::CHANGED; | 
| Johannes Doerfert | 5a5a139 | 2019-08-23 20:20:10 +0000 | [diff] [blame] | 3701 | } | 
|  | 3702 | } else if (auto *LI = dyn_cast<LoadInst>(U.getUser())) { | 
|  | 3703 | if (LI->getPointerOperand() == &AnchorVal) | 
|  | 3704 | if (LI->getAlignment() < getAssumedAlign()) { | 
| Guillaume Chatelet | 1738022 | 2019-09-30 09:37:05 +0000 | [diff] [blame] | 3705 | LI->setAlignment(Align(getAssumedAlign())); | 
| Johannes Doerfert | 5a5a139 | 2019-08-23 20:20:10 +0000 | [diff] [blame] | 3706 | STATS_DECLTRACK(AAAlign, Load, | 
| James Henderson | d68904f | 2020-01-06 10:15:44 +0000 | [diff] [blame] | 3707 | "Number of times alignment added to a load"); | 
| Johannes Doerfert | 30179d7 | 2020-01-12 00:25:45 -0600 | [diff] [blame] | 3708 | LoadStoreChanged = ChangeStatus::CHANGED; | 
| Johannes Doerfert | 5a5a139 | 2019-08-23 20:20:10 +0000 | [diff] [blame] | 3709 | } | 
|  | 3710 | } | 
|  | 3711 | } | 
|  | 3712 |  | 
| Johannes Doerfert | 30179d7 | 2020-01-12 00:25:45 -0600 | [diff] [blame] | 3713 | ChangeStatus Changed = AAAlign::manifest(A); | 
|  | 3714 |  | 
|  | 3715 | MaybeAlign InheritAlign = | 
|  | 3716 | getAssociatedValue().getPointerAlignment(A.getDataLayout()); | 
|  | 3717 | if (InheritAlign.valueOrOne() >= getAssumedAlign()) | 
|  | 3718 | return LoadStoreChanged; | 
|  | 3719 | return Changed | LoadStoreChanged; | 
| Johannes Doerfert | 5a5a139 | 2019-08-23 20:20:10 +0000 | [diff] [blame] | 3720 | } | 
|  | 3721 |  | 
| Johannes Doerfert | 81df452 | 2019-08-30 15:22:28 +0000 | [diff] [blame] | 3722 | // TODO: Provide a helper to determine the implied ABI alignment and check in | 
|  | 3723 | //       the existing manifest method and a new one for AAAlignImpl that value | 
|  | 3724 | //       to avoid making the alignment explicit if it did not improve. | 
|  | 3725 |  | 
|  | 3726 | /// See AbstractAttribute::getDeducedAttributes | 
|  | 3727 | virtual void | 
|  | 3728 | getDeducedAttributes(LLVMContext &Ctx, | 
|  | 3729 | SmallVectorImpl<Attribute> &Attrs) const override { | 
|  | 3730 | if (getAssumedAlign() > 1) | 
| Guillaume Chatelet | b65fa48 | 2019-10-15 12:56:24 +0000 | [diff] [blame] | 3731 | Attrs.emplace_back( | 
|  | 3732 | Attribute::getWithAlignment(Ctx, Align(getAssumedAlign()))); | 
| Johannes Doerfert | 81df452 | 2019-08-30 15:22:28 +0000 | [diff] [blame] | 3733 | } | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3734 | /// See AAFromMustBeExecutedContext | 
|  | 3735 | bool followUse(Attributor &A, const Use *U, const Instruction *I) { | 
|  | 3736 | bool TrackUse = false; | 
|  | 3737 |  | 
| Hideto Ueno | 4ecf255 | 2019-12-12 13:42:40 +0000 | [diff] [blame] | 3738 | unsigned int KnownAlign = | 
|  | 3739 | getKnownAlignForUse(A, *this, getAssociatedValue(), U, I, TrackUse); | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3740 | takeKnownMaximum(KnownAlign); | 
|  | 3741 |  | 
|  | 3742 | return TrackUse; | 
|  | 3743 | } | 
| Johannes Doerfert | 81df452 | 2019-08-30 15:22:28 +0000 | [diff] [blame] | 3744 |  | 
|  | 3745 | /// See AbstractAttribute::getAsStr(). | 
|  | 3746 | const std::string getAsStr() const override { | 
|  | 3747 | return getAssumedAlign() ? ("align<" + std::to_string(getKnownAlign()) + | 
|  | 3748 | "-" + std::to_string(getAssumedAlign()) + ">") | 
|  | 3749 | : "unknown-align"; | 
|  | 3750 | } | 
|  | 3751 | }; | 
|  | 3752 |  | 
|  | 3753 | /// Align attribute for a floating value. | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3754 | struct AAAlignFloating : AAFromMustBeExecutedContext<AAAlign, AAAlignImpl> { | 
|  | 3755 | using Base = AAFromMustBeExecutedContext<AAAlign, AAAlignImpl>; | 
|  | 3756 | AAAlignFloating(const IRPosition &IRP) : Base(IRP) {} | 
| Johannes Doerfert | 81df452 | 2019-08-30 15:22:28 +0000 | [diff] [blame] | 3757 |  | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 3758 | /// See AbstractAttribute::updateImpl(...). | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3759 | ChangeStatus updateImpl(Attributor &A) override { | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3760 | Base::updateImpl(A); | 
|  | 3761 |  | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3762 | const DataLayout &DL = A.getDataLayout(); | 
|  | 3763 |  | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 3764 | auto VisitValueCB = [&](Value &V, AAAlign::StateType &T, | 
|  | 3765 | bool Stripped) -> bool { | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 3766 | const auto &AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V)); | 
|  | 3767 | if (!Stripped && this == &AA) { | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3768 | // Use only IR information if we did not strip anything. | 
| Guillaume Chatelet | bae629b | 2019-10-15 13:58:22 +0000 | [diff] [blame] | 3769 | const MaybeAlign PA = V.getPointerAlignment(DL); | 
|  | 3770 | T.takeKnownMaximum(PA ? PA->value() : 0); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3771 | T.indicatePessimisticFixpoint(); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3772 | } else { | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 3773 | // Use abstract attribute information. | 
|  | 3774 | const AAAlign::StateType &DS = | 
|  | 3775 | static_cast<const AAAlign::StateType &>(AA.getState()); | 
|  | 3776 | T ^= DS; | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3777 | } | 
| Johannes Doerfert | b9b8791 | 2019-08-20 06:02:39 +0000 | [diff] [blame] | 3778 | return T.isValidState(); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3779 | }; | 
|  | 3780 |  | 
|  | 3781 | StateType T; | 
|  | 3782 | if (!genericValueTraversal<AAAlign, StateType>(A, getIRPosition(), *this, T, | 
|  | 3783 | VisitValueCB)) | 
| Johannes Doerfert | cfcca1a | 2019-08-20 06:08:35 +0000 | [diff] [blame] | 3784 | return indicatePessimisticFixpoint(); | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3785 |  | 
| Johannes Doerfert | 028b2aa | 2019-08-20 05:57:01 +0000 | [diff] [blame] | 3786 | // TODO: If we know we visited all incoming values, thus no are assumed | 
|  | 3787 | // dead, we can take the known information from the state T. | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3788 | return clampStateAndIndicateChange(getState(), T); | 
|  | 3789 | } | 
|  | 3790 |  | 
|  | 3791 | /// See AbstractAttribute::trackStatistics() | 
|  | 3792 | void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) } | 
|  | 3793 | }; | 
|  | 3794 |  | 
|  | 3795 | /// Align attribute for function return value. | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 3796 | struct AAAlignReturned final | 
|  | 3797 | : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> { | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3798 | AAAlignReturned(const IRPosition &IRP) | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 3799 | : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>(IRP) {} | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 3800 |  | 
|  | 3801 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 3802 | void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) } | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 3803 | }; | 
|  | 3804 |  | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 3805 | /// Align attribute for function argument. | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 3806 | struct AAAlignArgument final | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3807 | : AAArgumentFromCallSiteArgumentsAndMustBeExecutedContext<AAAlign, | 
|  | 3808 | AAAlignImpl> { | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3809 | AAAlignArgument(const IRPosition &IRP) | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3810 | : AAArgumentFromCallSiteArgumentsAndMustBeExecutedContext<AAAlign, | 
|  | 3811 | AAAlignImpl>( | 
|  | 3812 | IRP) {} | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 3813 |  | 
|  | 3814 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 169af99 | 2019-08-20 06:09:56 +0000 | [diff] [blame] | 3815 | void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) } | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 3816 | }; | 
|  | 3817 |  | 
| Johannes Doerfert | 234eda5 | 2019-08-16 19:51:23 +0000 | [diff] [blame] | 3818 | struct AAAlignCallSiteArgument final : AAAlignFloating { | 
|  | 3819 | AAAlignCallSiteArgument(const IRPosition &IRP) : AAAlignFloating(IRP) {} | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 3820 |  | 
| Johannes Doerfert | 5a5a139 | 2019-08-23 20:20:10 +0000 | [diff] [blame] | 3821 | /// See AbstractAttribute::manifest(...). | 
|  | 3822 | ChangeStatus manifest(Attributor &A) override { | 
| Johannes Doerfert | 30179d7 | 2020-01-12 00:25:45 -0600 | [diff] [blame] | 3823 | ChangeStatus Changed = AAAlignImpl::manifest(A); | 
|  | 3824 | MaybeAlign InheritAlign = | 
|  | 3825 | getAssociatedValue().getPointerAlignment(A.getDataLayout()); | 
|  | 3826 | if (InheritAlign.valueOrOne() >= getAssumedAlign()) | 
|  | 3827 | Changed = ChangeStatus::UNCHANGED; | 
|  | 3828 | return Changed; | 
| Johannes Doerfert | 5a5a139 | 2019-08-23 20:20:10 +0000 | [diff] [blame] | 3829 | } | 
|  | 3830 |  | 
| Johannes Doerfert | dada813 | 2019-12-31 01:27:50 -0600 | [diff] [blame] | 3831 | /// See AbstractAttribute::updateImpl(Attributor &A). | 
|  | 3832 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 3833 | ChangeStatus Changed = AAAlignFloating::updateImpl(A); | 
|  | 3834 | if (Argument *Arg = getAssociatedArgument()) { | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 3835 | // We only take known information from the argument | 
|  | 3836 | // so we do not need to track a dependence. | 
| Johannes Doerfert | dada813 | 2019-12-31 01:27:50 -0600 | [diff] [blame] | 3837 | const auto &ArgAlignAA = A.getAAFor<AAAlign>( | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 3838 | *this, IRPosition::argument(*Arg), /* TrackDependence */ false); | 
| Johannes Doerfert | dada813 | 2019-12-31 01:27:50 -0600 | [diff] [blame] | 3839 | takeKnownMaximum(ArgAlignAA.getKnownAlign()); | 
|  | 3840 | } | 
|  | 3841 | return Changed; | 
|  | 3842 | } | 
|  | 3843 |  | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 3844 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 3845 | void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) } | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 3846 | }; | 
|  | 3847 |  | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 3848 | /// Align attribute deduction for a call site return value. | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3849 | struct AAAlignCallSiteReturned final | 
|  | 3850 | : AACallSiteReturnedFromReturnedAndMustBeExecutedContext<AAAlign, | 
|  | 3851 | AAAlignImpl> { | 
|  | 3852 | using Base = | 
|  | 3853 | AACallSiteReturnedFromReturnedAndMustBeExecutedContext<AAAlign, | 
|  | 3854 | AAAlignImpl>; | 
|  | 3855 | AAAlignCallSiteReturned(const IRPosition &IRP) : Base(IRP) {} | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 3856 |  | 
|  | 3857 | /// See AbstractAttribute::initialize(...). | 
|  | 3858 | void initialize(Attributor &A) override { | 
| Hideto Ueno | 88b04ef | 2019-11-12 06:36:49 +0000 | [diff] [blame] | 3859 | Base::initialize(A); | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 3860 | Function *F = getAssociatedFunction(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 3861 | if (!F) | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 3862 | indicatePessimisticFixpoint(); | 
|  | 3863 | } | 
|  | 3864 |  | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 3865 | /// See AbstractAttribute::trackStatistics() | 
|  | 3866 | void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(align); } | 
|  | 3867 | }; | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 3868 |  | 
| Johannes Doerfert | e83f303 | 2019-08-05 23:22:05 +0000 | [diff] [blame] | 3869 | /// ------------------ Function No-Return Attribute ---------------------------- | 
| Johannes Doerfert | 344d038 | 2019-08-07 22:34:26 +0000 | [diff] [blame] | 3870 | struct AANoReturnImpl : public AANoReturn { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 3871 | AANoReturnImpl(const IRPosition &IRP) : AANoReturn(IRP) {} | 
| Johannes Doerfert | e83f303 | 2019-08-05 23:22:05 +0000 | [diff] [blame] | 3872 |  | 
| Johannes Doerfert | 0cc2b61 | 2019-10-13 21:25:53 +0000 | [diff] [blame] | 3873 | /// See AbstractAttribute::initialize(...). | 
|  | 3874 | void initialize(Attributor &A) override { | 
|  | 3875 | AANoReturn::initialize(A); | 
|  | 3876 | Function *F = getAssociatedFunction(); | 
| Johannes Doerfert | 1b6041a | 2019-11-01 20:17:48 -0500 | [diff] [blame] | 3877 | if (!F) | 
| Johannes Doerfert | 0cc2b61 | 2019-10-13 21:25:53 +0000 | [diff] [blame] | 3878 | indicatePessimisticFixpoint(); | 
|  | 3879 | } | 
|  | 3880 |  | 
| Johannes Doerfert | e83f303 | 2019-08-05 23:22:05 +0000 | [diff] [blame] | 3881 | /// See AbstractAttribute::getAsStr(). | 
|  | 3882 | const std::string getAsStr() const override { | 
|  | 3883 | return getAssumed() ? "noreturn" : "may-return"; | 
|  | 3884 | } | 
|  | 3885 |  | 
| Johannes Doerfert | e83f303 | 2019-08-05 23:22:05 +0000 | [diff] [blame] | 3886 | /// See AbstractAttribute::updateImpl(Attributor &A). | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 3887 | virtual ChangeStatus updateImpl(Attributor &A) override { | 
| Johannes Doerfert | d0f6400 | 2019-08-06 00:32:43 +0000 | [diff] [blame] | 3888 | auto CheckForNoReturn = [](Instruction &) { return false; }; | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 3889 | if (!A.checkForAllInstructions(CheckForNoReturn, *this, | 
| Johannes Doerfert | d0f6400 | 2019-08-06 00:32:43 +0000 | [diff] [blame] | 3890 | {(unsigned)Instruction::Ret})) | 
| Johannes Doerfert | e83f303 | 2019-08-05 23:22:05 +0000 | [diff] [blame] | 3891 | return indicatePessimisticFixpoint(); | 
| Johannes Doerfert | e83f303 | 2019-08-05 23:22:05 +0000 | [diff] [blame] | 3892 | return ChangeStatus::UNCHANGED; | 
|  | 3893 | } | 
|  | 3894 | }; | 
|  | 3895 |  | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 3896 | struct AANoReturnFunction final : AANoReturnImpl { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 3897 | AANoReturnFunction(const IRPosition &IRP) : AANoReturnImpl(IRP) {} | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 3898 |  | 
|  | 3899 | /// See AbstractAttribute::trackStatistics() | 
| Johannes Doerfert | 17b578b | 2019-08-14 21:46:25 +0000 | [diff] [blame] | 3900 | void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) } | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 3901 | }; | 
|  | 3902 |  | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 3903 | /// NoReturn attribute deduction for a call sites. | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 3904 | struct AANoReturnCallSite final : AANoReturnImpl { | 
|  | 3905 | AANoReturnCallSite(const IRPosition &IRP) : AANoReturnImpl(IRP) {} | 
|  | 3906 |  | 
| Johannes Doerfert | 3fac668 | 2019-08-30 15:24:52 +0000 | [diff] [blame] | 3907 | /// See AbstractAttribute::updateImpl(...). | 
|  | 3908 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 3909 | // TODO: Once we have call site specific value information we can provide | 
|  | 3910 | //       call site specific liveness information and then it makes | 
|  | 3911 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 3912 | //       redirecting requests to the callee argument. | 
|  | 3913 | Function *F = getAssociatedFunction(); | 
|  | 3914 | const IRPosition &FnPos = IRPosition::function(*F); | 
|  | 3915 | auto &FnAA = A.getAAFor<AANoReturn>(*this, FnPos); | 
|  | 3916 | return clampStateAndIndicateChange( | 
|  | 3917 | getState(), | 
|  | 3918 | static_cast<const AANoReturn::StateType &>(FnAA.getState())); | 
|  | 3919 | } | 
|  | 3920 |  | 
|  | 3921 | /// See AbstractAttribute::trackStatistics() | 
|  | 3922 | void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noreturn); } | 
|  | 3923 | }; | 
| Johannes Doerfert | 66cf87e | 2019-08-16 19:49:00 +0000 | [diff] [blame] | 3924 |  | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 3925 | /// ----------------------- Variable Capturing --------------------------------- | 
|  | 3926 |  | 
|  | 3927 | /// A class to hold the state of for no-capture attributes. | 
|  | 3928 | struct AANoCaptureImpl : public AANoCapture { | 
|  | 3929 | AANoCaptureImpl(const IRPosition &IRP) : AANoCapture(IRP) {} | 
|  | 3930 |  | 
|  | 3931 | /// See AbstractAttribute::initialize(...). | 
|  | 3932 | void initialize(Attributor &A) override { | 
| Johannes Doerfert | 0437bfc | 2019-10-31 20:03:13 -0500 | [diff] [blame] | 3933 | if (hasAttr(getAttrKind(), /* IgnoreSubsumingPositions */ true)) { | 
|  | 3934 | indicateOptimisticFixpoint(); | 
|  | 3935 | return; | 
|  | 3936 | } | 
|  | 3937 | Function *AnchorScope = getAnchorScope(); | 
|  | 3938 | if (isFnInterfaceKind() && | 
|  | 3939 | (!AnchorScope || !AnchorScope->hasExactDefinition())) { | 
|  | 3940 | indicatePessimisticFixpoint(); | 
|  | 3941 | return; | 
|  | 3942 | } | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 3943 |  | 
| Johannes Doerfert | 72adda1 | 2019-10-10 05:33:21 +0000 | [diff] [blame] | 3944 | // You cannot "capture" null in the default address space. | 
|  | 3945 | if (isa<ConstantPointerNull>(getAssociatedValue()) && | 
|  | 3946 | getAssociatedValue().getType()->getPointerAddressSpace() == 0) { | 
|  | 3947 | indicateOptimisticFixpoint(); | 
|  | 3948 | return; | 
|  | 3949 | } | 
|  | 3950 |  | 
| Johannes Doerfert | 0437bfc | 2019-10-31 20:03:13 -0500 | [diff] [blame] | 3951 | const Function *F = getArgNo() >= 0 ? getAssociatedFunction() : AnchorScope; | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 3952 |  | 
|  | 3953 | // Check what state the associated function can actually capture. | 
|  | 3954 | if (F) | 
| Johannes Doerfert | 0437bfc | 2019-10-31 20:03:13 -0500 | [diff] [blame] | 3955 | determineFunctionCaptureCapabilities(getIRPosition(), *F, *this); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 3956 | else | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 3957 | indicatePessimisticFixpoint(); | 
|  | 3958 | } | 
|  | 3959 |  | 
|  | 3960 | /// See AbstractAttribute::updateImpl(...). | 
|  | 3961 | ChangeStatus updateImpl(Attributor &A) override; | 
|  | 3962 |  | 
|  | 3963 | /// see AbstractAttribute::isAssumedNoCaptureMaybeReturned(...). | 
|  | 3964 | virtual void | 
|  | 3965 | getDeducedAttributes(LLVMContext &Ctx, | 
|  | 3966 | SmallVectorImpl<Attribute> &Attrs) const override { | 
|  | 3967 | if (!isAssumedNoCaptureMaybeReturned()) | 
|  | 3968 | return; | 
|  | 3969 |  | 
| Hideto Ueno | 3736764 | 2019-09-11 06:52:11 +0000 | [diff] [blame] | 3970 | if (getArgNo() >= 0) { | 
|  | 3971 | if (isAssumedNoCapture()) | 
|  | 3972 | Attrs.emplace_back(Attribute::get(Ctx, Attribute::NoCapture)); | 
|  | 3973 | else if (ManifestInternal) | 
|  | 3974 | Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned")); | 
|  | 3975 | } | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 3976 | } | 
|  | 3977 |  | 
|  | 3978 | /// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known | 
|  | 3979 | /// depending on the ability of the function associated with \p IRP to capture | 
|  | 3980 | /// state in memory and through "returning/throwing", respectively. | 
| Johannes Doerfert | 3839b57 | 2019-10-21 00:48:42 +0000 | [diff] [blame] | 3981 | static void determineFunctionCaptureCapabilities(const IRPosition &IRP, | 
|  | 3982 | const Function &F, | 
| Johannes Doerfert | 1a74645 | 2019-10-20 22:28:49 -0500 | [diff] [blame] | 3983 | BitIntegerState &State) { | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 3984 | // TODO: Once we have memory behavior attributes we should use them here. | 
|  | 3985 |  | 
|  | 3986 | // If we know we cannot communicate or write to memory, we do not care about | 
|  | 3987 | // ptr2int anymore. | 
|  | 3988 | if (F.onlyReadsMemory() && F.doesNotThrow() && | 
|  | 3989 | F.getReturnType()->isVoidTy()) { | 
|  | 3990 | State.addKnownBits(NO_CAPTURE); | 
|  | 3991 | return; | 
|  | 3992 | } | 
|  | 3993 |  | 
|  | 3994 | // A function cannot capture state in memory if it only reads memory, it can | 
|  | 3995 | // however return/throw state and the state might be influenced by the | 
|  | 3996 | // pointer value, e.g., loading from a returned pointer might reveal a bit. | 
|  | 3997 | if (F.onlyReadsMemory()) | 
|  | 3998 | State.addKnownBits(NOT_CAPTURED_IN_MEM); | 
|  | 3999 |  | 
|  | 4000 | // A function cannot communicate state back if it does not through | 
|  | 4001 | // exceptions and doesn not return values. | 
|  | 4002 | if (F.doesNotThrow() && F.getReturnType()->isVoidTy()) | 
|  | 4003 | State.addKnownBits(NOT_CAPTURED_IN_RET); | 
| Johannes Doerfert | 3839b57 | 2019-10-21 00:48:42 +0000 | [diff] [blame] | 4004 |  | 
|  | 4005 | // Check existing "returned" attributes. | 
|  | 4006 | int ArgNo = IRP.getArgNo(); | 
|  | 4007 | if (F.doesNotThrow() && ArgNo >= 0) { | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 4008 | for (unsigned u = 0, e = F.arg_size(); u < e; ++u) | 
| Johannes Doerfert | 3839b57 | 2019-10-21 00:48:42 +0000 | [diff] [blame] | 4009 | if (F.hasParamAttribute(u, Attribute::Returned)) { | 
| Johannes Doerfert | 9d5ad5e | 2019-10-21 01:29:10 +0000 | [diff] [blame] | 4010 | if (u == unsigned(ArgNo)) | 
| Johannes Doerfert | 3839b57 | 2019-10-21 00:48:42 +0000 | [diff] [blame] | 4011 | State.removeAssumedBits(NOT_CAPTURED_IN_RET); | 
|  | 4012 | else if (F.onlyReadsMemory()) | 
|  | 4013 | State.addKnownBits(NO_CAPTURE); | 
|  | 4014 | else | 
|  | 4015 | State.addKnownBits(NOT_CAPTURED_IN_RET); | 
|  | 4016 | break; | 
|  | 4017 | } | 
|  | 4018 | } | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 4019 | } | 
|  | 4020 |  | 
|  | 4021 | /// See AbstractState::getAsStr(). | 
|  | 4022 | const std::string getAsStr() const override { | 
|  | 4023 | if (isKnownNoCapture()) | 
|  | 4024 | return "known not-captured"; | 
|  | 4025 | if (isAssumedNoCapture()) | 
|  | 4026 | return "assumed not-captured"; | 
|  | 4027 | if (isKnownNoCaptureMaybeReturned()) | 
|  | 4028 | return "known not-captured-maybe-returned"; | 
|  | 4029 | if (isAssumedNoCaptureMaybeReturned()) | 
|  | 4030 | return "assumed not-captured-maybe-returned"; | 
|  | 4031 | return "assumed-captured"; | 
|  | 4032 | } | 
|  | 4033 | }; | 
|  | 4034 |  | 
|  | 4035 | /// Attributor-aware capture tracker. | 
|  | 4036 | struct AACaptureUseTracker final : public CaptureTracker { | 
|  | 4037 |  | 
|  | 4038 | /// Create a capture tracker that can lookup in-flight abstract attributes | 
|  | 4039 | /// through the Attributor \p A. | 
|  | 4040 | /// | 
|  | 4041 | /// If a use leads to a potential capture, \p CapturedInMemory is set and the | 
|  | 4042 | /// search is stopped. If a use leads to a return instruction, | 
|  | 4043 | /// \p CommunicatedBack is set to true and \p CapturedInMemory is not changed. | 
|  | 4044 | /// If a use leads to a ptr2int which may capture the value, | 
|  | 4045 | /// \p CapturedInInteger is set. If a use is found that is currently assumed | 
|  | 4046 | /// "no-capture-maybe-returned", the user is added to the \p PotentialCopies | 
|  | 4047 | /// set. All values in \p PotentialCopies are later tracked as well. For every | 
|  | 4048 | /// explored use we decrement \p RemainingUsesToExplore. Once it reaches 0, | 
|  | 4049 | /// the search is stopped with \p CapturedInMemory and \p CapturedInInteger | 
|  | 4050 | /// conservatively set to true. | 
|  | 4051 | AACaptureUseTracker(Attributor &A, AANoCapture &NoCaptureAA, | 
| Johannes Doerfert | 3178424 | 2019-10-29 23:18:49 -0500 | [diff] [blame] | 4052 | const AAIsDead &IsDeadAA, AANoCapture::StateType &State, | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 4053 | SmallVectorImpl<const Value *> &PotentialCopies, | 
|  | 4054 | unsigned &RemainingUsesToExplore) | 
|  | 4055 | : A(A), NoCaptureAA(NoCaptureAA), IsDeadAA(IsDeadAA), State(State), | 
|  | 4056 | PotentialCopies(PotentialCopies), | 
|  | 4057 | RemainingUsesToExplore(RemainingUsesToExplore) {} | 
|  | 4058 |  | 
|  | 4059 | /// Determine if \p V maybe captured. *Also updates the state!* | 
|  | 4060 | bool valueMayBeCaptured(const Value *V) { | 
|  | 4061 | if (V->getType()->isPointerTy()) { | 
|  | 4062 | PointerMayBeCaptured(V, this); | 
|  | 4063 | } else { | 
|  | 4064 | State.indicatePessimisticFixpoint(); | 
|  | 4065 | } | 
|  | 4066 | return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED); | 
|  | 4067 | } | 
|  | 4068 |  | 
|  | 4069 | /// See CaptureTracker::tooManyUses(). | 
|  | 4070 | void tooManyUses() override { | 
|  | 4071 | State.removeAssumedBits(AANoCapture::NO_CAPTURE); | 
|  | 4072 | } | 
|  | 4073 |  | 
|  | 4074 | bool isDereferenceableOrNull(Value *O, const DataLayout &DL) override { | 
|  | 4075 | if (CaptureTracker::isDereferenceableOrNull(O, DL)) | 
|  | 4076 | return true; | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 4077 | const auto &DerefAA = A.getAAFor<AADereferenceable>( | 
|  | 4078 | NoCaptureAA, IRPosition::value(*O), /* TrackDependence */ true, | 
|  | 4079 | DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 4080 | return DerefAA.getAssumedDereferenceableBytes(); | 
|  | 4081 | } | 
|  | 4082 |  | 
|  | 4083 | /// See CaptureTracker::captured(...). | 
|  | 4084 | bool captured(const Use *U) override { | 
|  | 4085 | Instruction *UInst = cast<Instruction>(U->getUser()); | 
|  | 4086 | LLVM_DEBUG(dbgs() << "Check use: " << *U->get() << " in " << *UInst | 
|  | 4087 | << "\n"); | 
|  | 4088 |  | 
|  | 4089 | // Because we may reuse the tracker multiple times we keep track of the | 
|  | 4090 | // number of explored uses ourselves as well. | 
|  | 4091 | if (RemainingUsesToExplore-- == 0) { | 
|  | 4092 | LLVM_DEBUG(dbgs() << " - too many uses to explore!\n"); | 
|  | 4093 | return isCapturedIn(/* Memory */ true, /* Integer */ true, | 
|  | 4094 | /* Return */ true); | 
|  | 4095 | } | 
|  | 4096 |  | 
|  | 4097 | // Deal with ptr2int by following uses. | 
|  | 4098 | if (isa<PtrToIntInst>(UInst)) { | 
|  | 4099 | LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n"); | 
|  | 4100 | return valueMayBeCaptured(UInst); | 
|  | 4101 | } | 
|  | 4102 |  | 
|  | 4103 | // Explicitly catch return instructions. | 
|  | 4104 | if (isa<ReturnInst>(UInst)) | 
|  | 4105 | return isCapturedIn(/* Memory */ false, /* Integer */ false, | 
|  | 4106 | /* Return */ true); | 
|  | 4107 |  | 
|  | 4108 | // For now we only use special logic for call sites. However, the tracker | 
|  | 4109 | // itself knows about a lot of other non-capturing cases already. | 
|  | 4110 | CallSite CS(UInst); | 
|  | 4111 | if (!CS || !CS.isArgOperand(U)) | 
|  | 4112 | return isCapturedIn(/* Memory */ true, /* Integer */ true, | 
|  | 4113 | /* Return */ true); | 
|  | 4114 |  | 
|  | 4115 | unsigned ArgNo = CS.getArgumentNo(U); | 
|  | 4116 | const IRPosition &CSArgPos = IRPosition::callsite_argument(CS, ArgNo); | 
|  | 4117 | // If we have a abstract no-capture attribute for the argument we can use | 
|  | 4118 | // it to justify a non-capture attribute here. This allows recursion! | 
|  | 4119 | auto &ArgNoCaptureAA = A.getAAFor<AANoCapture>(NoCaptureAA, CSArgPos); | 
|  | 4120 | if (ArgNoCaptureAA.isAssumedNoCapture()) | 
|  | 4121 | return isCapturedIn(/* Memory */ false, /* Integer */ false, | 
|  | 4122 | /* Return */ false); | 
|  | 4123 | if (ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) { | 
|  | 4124 | addPotentialCopy(CS); | 
|  | 4125 | return isCapturedIn(/* Memory */ false, /* Integer */ false, | 
|  | 4126 | /* Return */ false); | 
|  | 4127 | } | 
|  | 4128 |  | 
|  | 4129 | // Lastly, we could not find a reason no-capture can be assumed so we don't. | 
|  | 4130 | return isCapturedIn(/* Memory */ true, /* Integer */ true, | 
|  | 4131 | /* Return */ true); | 
|  | 4132 | } | 
|  | 4133 |  | 
|  | 4134 | /// Register \p CS as potential copy of the value we are checking. | 
|  | 4135 | void addPotentialCopy(CallSite CS) { | 
|  | 4136 | PotentialCopies.push_back(CS.getInstruction()); | 
|  | 4137 | } | 
|  | 4138 |  | 
|  | 4139 | /// See CaptureTracker::shouldExplore(...). | 
|  | 4140 | bool shouldExplore(const Use *U) override { | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 4141 | // Check liveness, if it is used to stop exploring we need a dependence. | 
|  | 4142 | if (IsDeadAA.isAssumedDead(cast<Instruction>(U->getUser()))) { | 
|  | 4143 | A.recordDependence(IsDeadAA, NoCaptureAA, DepClassTy::OPTIONAL); | 
|  | 4144 | return false; | 
|  | 4145 | } | 
|  | 4146 | return true; | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 4147 | } | 
|  | 4148 |  | 
|  | 4149 | /// Update the state according to \p CapturedInMem, \p CapturedInInt, and | 
|  | 4150 | /// \p CapturedInRet, then return the appropriate value for use in the | 
|  | 4151 | /// CaptureTracker::captured() interface. | 
|  | 4152 | bool isCapturedIn(bool CapturedInMem, bool CapturedInInt, | 
|  | 4153 | bool CapturedInRet) { | 
|  | 4154 | LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int " | 
|  | 4155 | << CapturedInInt << "|Ret " << CapturedInRet << "]\n"); | 
|  | 4156 | if (CapturedInMem) | 
|  | 4157 | State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM); | 
|  | 4158 | if (CapturedInInt) | 
|  | 4159 | State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT); | 
|  | 4160 | if (CapturedInRet) | 
|  | 4161 | State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET); | 
|  | 4162 | return !State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED); | 
|  | 4163 | } | 
|  | 4164 |  | 
|  | 4165 | private: | 
|  | 4166 | /// The attributor providing in-flight abstract attributes. | 
|  | 4167 | Attributor &A; | 
|  | 4168 |  | 
|  | 4169 | /// The abstract attribute currently updated. | 
|  | 4170 | AANoCapture &NoCaptureAA; | 
|  | 4171 |  | 
|  | 4172 | /// The abstract liveness state. | 
|  | 4173 | const AAIsDead &IsDeadAA; | 
|  | 4174 |  | 
|  | 4175 | /// The state currently updated. | 
| Johannes Doerfert | 3178424 | 2019-10-29 23:18:49 -0500 | [diff] [blame] | 4176 | AANoCapture::StateType &State; | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 4177 |  | 
|  | 4178 | /// Set of potential copies of the tracked value. | 
|  | 4179 | SmallVectorImpl<const Value *> &PotentialCopies; | 
|  | 4180 |  | 
|  | 4181 | /// Global counter to limit the number of explored uses. | 
|  | 4182 | unsigned &RemainingUsesToExplore; | 
|  | 4183 | }; | 
|  | 4184 |  | 
|  | 4185 | ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) { | 
|  | 4186 | const IRPosition &IRP = getIRPosition(); | 
|  | 4187 | const Value *V = | 
|  | 4188 | getArgNo() >= 0 ? IRP.getAssociatedArgument() : &IRP.getAssociatedValue(); | 
|  | 4189 | if (!V) | 
|  | 4190 | return indicatePessimisticFixpoint(); | 
|  | 4191 |  | 
|  | 4192 | const Function *F = | 
|  | 4193 | getArgNo() >= 0 ? IRP.getAssociatedFunction() : IRP.getAnchorScope(); | 
|  | 4194 | assert(F && "Expected a function!"); | 
| Johannes Doerfert | 3839b57 | 2019-10-21 00:48:42 +0000 | [diff] [blame] | 4195 | const IRPosition &FnPos = IRPosition::function(*F); | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 4196 | const auto &IsDeadAA = | 
|  | 4197 | A.getAAFor<AAIsDead>(*this, FnPos, /* TrackDependence */ false); | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 4198 |  | 
|  | 4199 | AANoCapture::StateType T; | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 4200 |  | 
| Johannes Doerfert | 3839b57 | 2019-10-21 00:48:42 +0000 | [diff] [blame] | 4201 | // Readonly means we cannot capture through memory. | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 4202 | const auto &FnMemAA = A.getAAFor<AAMemoryBehavior>( | 
|  | 4203 | *this, FnPos, /* TrackDependence */ true, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 3839b57 | 2019-10-21 00:48:42 +0000 | [diff] [blame] | 4204 | if (FnMemAA.isAssumedReadOnly()) { | 
|  | 4205 | T.addKnownBits(NOT_CAPTURED_IN_MEM); | 
|  | 4206 | if (FnMemAA.isKnownReadOnly()) | 
|  | 4207 | addKnownBits(NOT_CAPTURED_IN_MEM); | 
|  | 4208 | } | 
|  | 4209 |  | 
|  | 4210 | // Make sure all returned values are different than the underlying value. | 
|  | 4211 | // TODO: we could do this in a more sophisticated way inside | 
|  | 4212 | //       AAReturnedValues, e.g., track all values that escape through returns | 
|  | 4213 | //       directly somehow. | 
|  | 4214 | auto CheckReturnedArgs = [&](const AAReturnedValues &RVAA) { | 
|  | 4215 | bool SeenConstant = false; | 
|  | 4216 | for (auto &It : RVAA.returned_values()) { | 
|  | 4217 | if (isa<Constant>(It.first)) { | 
|  | 4218 | if (SeenConstant) | 
|  | 4219 | return false; | 
|  | 4220 | SeenConstant = true; | 
|  | 4221 | } else if (!isa<Argument>(It.first) || | 
|  | 4222 | It.first == getAssociatedArgument()) | 
|  | 4223 | return false; | 
|  | 4224 | } | 
|  | 4225 | return true; | 
|  | 4226 | }; | 
|  | 4227 |  | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 4228 | const auto &NoUnwindAA = A.getAAFor<AANoUnwind>( | 
|  | 4229 | *this, FnPos, /* TrackDependence */ true, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 3839b57 | 2019-10-21 00:48:42 +0000 | [diff] [blame] | 4230 | if (NoUnwindAA.isAssumedNoUnwind()) { | 
|  | 4231 | bool IsVoidTy = F->getReturnType()->isVoidTy(); | 
|  | 4232 | const AAReturnedValues *RVAA = | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 4233 | IsVoidTy ? nullptr | 
|  | 4234 | : &A.getAAFor<AAReturnedValues>(*this, FnPos, | 
|  | 4235 | /* TrackDependence */ true, | 
|  | 4236 | DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 3839b57 | 2019-10-21 00:48:42 +0000 | [diff] [blame] | 4237 | if (IsVoidTy || CheckReturnedArgs(*RVAA)) { | 
|  | 4238 | T.addKnownBits(NOT_CAPTURED_IN_RET); | 
|  | 4239 | if (T.isKnown(NOT_CAPTURED_IN_MEM)) | 
|  | 4240 | return ChangeStatus::UNCHANGED; | 
|  | 4241 | if (NoUnwindAA.isKnownNoUnwind() && | 
|  | 4242 | (IsVoidTy || RVAA->getState().isAtFixpoint())) { | 
|  | 4243 | addKnownBits(NOT_CAPTURED_IN_RET); | 
|  | 4244 | if (isKnown(NOT_CAPTURED_IN_MEM)) | 
|  | 4245 | return indicateOptimisticFixpoint(); | 
|  | 4246 | } | 
|  | 4247 | } | 
|  | 4248 | } | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 4249 |  | 
|  | 4250 | // Use the CaptureTracker interface and logic with the specialized tracker, | 
|  | 4251 | // defined in AACaptureUseTracker, that can look at in-flight abstract | 
|  | 4252 | // attributes and directly updates the assumed state. | 
|  | 4253 | SmallVector<const Value *, 4> PotentialCopies; | 
|  | 4254 | unsigned RemainingUsesToExplore = DefaultMaxUsesToExplore; | 
|  | 4255 | AACaptureUseTracker Tracker(A, *this, IsDeadAA, T, PotentialCopies, | 
|  | 4256 | RemainingUsesToExplore); | 
|  | 4257 |  | 
|  | 4258 | // Check all potential copies of the associated value until we can assume | 
|  | 4259 | // none will be captured or we have to assume at least one might be. | 
|  | 4260 | unsigned Idx = 0; | 
|  | 4261 | PotentialCopies.push_back(V); | 
|  | 4262 | while (T.isAssumed(NO_CAPTURE_MAYBE_RETURNED) && Idx < PotentialCopies.size()) | 
|  | 4263 | Tracker.valueMayBeCaptured(PotentialCopies[Idx++]); | 
|  | 4264 |  | 
| Johannes Doerfert | 1a74645 | 2019-10-20 22:28:49 -0500 | [diff] [blame] | 4265 | AANoCapture::StateType &S = getState(); | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 4266 | auto Assumed = S.getAssumed(); | 
|  | 4267 | S.intersectAssumedBits(T.getAssumed()); | 
| Johannes Doerfert | 3178424 | 2019-10-29 23:18:49 -0500 | [diff] [blame] | 4268 | if (!isAssumedNoCaptureMaybeReturned()) | 
|  | 4269 | return indicatePessimisticFixpoint(); | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 4270 | return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED | 
|  | 4271 | : ChangeStatus::CHANGED; | 
|  | 4272 | } | 
|  | 4273 |  | 
|  | 4274 | /// NoCapture attribute for function arguments. | 
|  | 4275 | struct AANoCaptureArgument final : AANoCaptureImpl { | 
|  | 4276 | AANoCaptureArgument(const IRPosition &IRP) : AANoCaptureImpl(IRP) {} | 
|  | 4277 |  | 
|  | 4278 | /// See AbstractAttribute::trackStatistics() | 
|  | 4279 | void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture) } | 
|  | 4280 | }; | 
|  | 4281 |  | 
|  | 4282 | /// NoCapture attribute for call site arguments. | 
|  | 4283 | struct AANoCaptureCallSiteArgument final : AANoCaptureImpl { | 
|  | 4284 | AANoCaptureCallSiteArgument(const IRPosition &IRP) : AANoCaptureImpl(IRP) {} | 
|  | 4285 |  | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 4286 | /// See AbstractAttribute::initialize(...). | 
|  | 4287 | void initialize(Attributor &A) override { | 
|  | 4288 | if (Argument *Arg = getAssociatedArgument()) | 
|  | 4289 | if (Arg->hasByValAttr()) | 
|  | 4290 | indicateOptimisticFixpoint(); | 
|  | 4291 | AANoCaptureImpl::initialize(A); | 
|  | 4292 | } | 
|  | 4293 |  | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 4294 | /// See AbstractAttribute::updateImpl(...). | 
|  | 4295 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 4296 | // TODO: Once we have call site specific value information we can provide | 
|  | 4297 | //       call site specific liveness information and then it makes | 
|  | 4298 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 4299 | //       redirecting requests to the callee argument. | 
|  | 4300 | Argument *Arg = getAssociatedArgument(); | 
|  | 4301 | if (!Arg) | 
|  | 4302 | return indicatePessimisticFixpoint(); | 
|  | 4303 | const IRPosition &ArgPos = IRPosition::argument(*Arg); | 
|  | 4304 | auto &ArgAA = A.getAAFor<AANoCapture>(*this, ArgPos); | 
|  | 4305 | return clampStateAndIndicateChange( | 
|  | 4306 | getState(), | 
|  | 4307 | static_cast<const AANoCapture::StateType &>(ArgAA.getState())); | 
|  | 4308 | } | 
|  | 4309 |  | 
|  | 4310 | /// See AbstractAttribute::trackStatistics() | 
|  | 4311 | void trackStatistics() const override{STATS_DECLTRACK_CSARG_ATTR(nocapture)}; | 
|  | 4312 | }; | 
|  | 4313 |  | 
|  | 4314 | /// NoCapture attribute for floating values. | 
|  | 4315 | struct AANoCaptureFloating final : AANoCaptureImpl { | 
|  | 4316 | AANoCaptureFloating(const IRPosition &IRP) : AANoCaptureImpl(IRP) {} | 
|  | 4317 |  | 
|  | 4318 | /// See AbstractAttribute::trackStatistics() | 
|  | 4319 | void trackStatistics() const override { | 
|  | 4320 | STATS_DECLTRACK_FLOATING_ATTR(nocapture) | 
|  | 4321 | } | 
|  | 4322 | }; | 
|  | 4323 |  | 
|  | 4324 | /// NoCapture attribute for function return value. | 
|  | 4325 | struct AANoCaptureReturned final : AANoCaptureImpl { | 
|  | 4326 | AANoCaptureReturned(const IRPosition &IRP) : AANoCaptureImpl(IRP) { | 
|  | 4327 | llvm_unreachable("NoCapture is not applicable to function returns!"); | 
|  | 4328 | } | 
|  | 4329 |  | 
|  | 4330 | /// See AbstractAttribute::initialize(...). | 
|  | 4331 | void initialize(Attributor &A) override { | 
|  | 4332 | llvm_unreachable("NoCapture is not applicable to function returns!"); | 
|  | 4333 | } | 
|  | 4334 |  | 
|  | 4335 | /// See AbstractAttribute::updateImpl(...). | 
|  | 4336 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 4337 | llvm_unreachable("NoCapture is not applicable to function returns!"); | 
|  | 4338 | } | 
|  | 4339 |  | 
|  | 4340 | /// See AbstractAttribute::trackStatistics() | 
|  | 4341 | void trackStatistics() const override {} | 
|  | 4342 | }; | 
|  | 4343 |  | 
|  | 4344 | /// NoCapture attribute deduction for a call site return value. | 
|  | 4345 | struct AANoCaptureCallSiteReturned final : AANoCaptureImpl { | 
|  | 4346 | AANoCaptureCallSiteReturned(const IRPosition &IRP) : AANoCaptureImpl(IRP) {} | 
|  | 4347 |  | 
|  | 4348 | /// See AbstractAttribute::trackStatistics() | 
|  | 4349 | void trackStatistics() const override { | 
|  | 4350 | STATS_DECLTRACK_CSRET_ATTR(nocapture) | 
|  | 4351 | } | 
|  | 4352 | }; | 
|  | 4353 |  | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4354 | /// ------------------ Value Simplify Attribute ---------------------------- | 
|  | 4355 | struct AAValueSimplifyImpl : AAValueSimplify { | 
|  | 4356 | AAValueSimplifyImpl(const IRPosition &IRP) : AAValueSimplify(IRP) {} | 
|  | 4357 |  | 
| Johannes Doerfert | 9dcf889 | 2020-01-11 23:59:36 -0600 | [diff] [blame] | 4358 | /// See AbstractAttribute::initialize(...). | 
|  | 4359 | void initialize(Attributor &A) override { | 
|  | 4360 | if (getAssociatedValue().getType()->isVoidTy()) | 
|  | 4361 | indicatePessimisticFixpoint(); | 
|  | 4362 | } | 
|  | 4363 |  | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4364 | /// See AbstractAttribute::getAsStr(). | 
|  | 4365 | const std::string getAsStr() const override { | 
|  | 4366 | return getAssumed() ? (getKnown() ? "simplified" : "maybe-simple") | 
|  | 4367 | : "not-simple"; | 
|  | 4368 | } | 
|  | 4369 |  | 
|  | 4370 | /// See AbstractAttribute::trackStatistics() | 
|  | 4371 | void trackStatistics() const override {} | 
|  | 4372 |  | 
|  | 4373 | /// See AAValueSimplify::getAssumedSimplifiedValue() | 
|  | 4374 | Optional<Value *> getAssumedSimplifiedValue(Attributor &A) const override { | 
|  | 4375 | if (!getAssumed()) | 
|  | 4376 | return const_cast<Value *>(&getAssociatedValue()); | 
|  | 4377 | return SimplifiedAssociatedValue; | 
|  | 4378 | } | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4379 |  | 
|  | 4380 | /// Helper function for querying AAValueSimplify and updating candicate. | 
|  | 4381 | /// \param QueryingValue Value trying to unify with SimplifiedValue | 
|  | 4382 | /// \param AccumulatedSimplifiedValue Current simplification result. | 
|  | 4383 | static bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA, | 
|  | 4384 | Value &QueryingValue, | 
|  | 4385 | Optional<Value *> &AccumulatedSimplifiedValue) { | 
|  | 4386 | // FIXME: Add a typecast support. | 
|  | 4387 |  | 
| Johannes Doerfert | d07b5a5 | 2020-01-12 00:00:33 -0600 | [diff] [blame] | 4388 | auto &ValueSimplifyAA = A.getAAFor<AAValueSimplify>( | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4389 | QueryingAA, IRPosition::value(QueryingValue)); | 
|  | 4390 |  | 
|  | 4391 | Optional<Value *> QueryingValueSimplified = | 
| Johannes Doerfert | d07b5a5 | 2020-01-12 00:00:33 -0600 | [diff] [blame] | 4392 | ValueSimplifyAA.getAssumedSimplifiedValue(A); | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4393 |  | 
|  | 4394 | if (!QueryingValueSimplified.hasValue()) | 
|  | 4395 | return true; | 
|  | 4396 |  | 
|  | 4397 | if (!QueryingValueSimplified.getValue()) | 
|  | 4398 | return false; | 
|  | 4399 |  | 
|  | 4400 | Value &QueryingValueSimplifiedUnwrapped = | 
|  | 4401 | *QueryingValueSimplified.getValue(); | 
|  | 4402 |  | 
|  | 4403 | if (isa<UndefValue>(QueryingValueSimplifiedUnwrapped)) | 
|  | 4404 | return true; | 
|  | 4405 |  | 
|  | 4406 | if (AccumulatedSimplifiedValue.hasValue()) | 
|  | 4407 | return AccumulatedSimplifiedValue == QueryingValueSimplified; | 
|  | 4408 |  | 
| Johannes Doerfert | 02bd818 | 2020-01-28 11:49:35 -0600 | [diff] [blame] | 4409 | LLVM_DEBUG(dbgs() << "[ValueSimplify] " << QueryingValue | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4410 | << " is assumed to be " | 
|  | 4411 | << QueryingValueSimplifiedUnwrapped << "\n"); | 
|  | 4412 |  | 
|  | 4413 | AccumulatedSimplifiedValue = QueryingValueSimplified; | 
|  | 4414 | return true; | 
|  | 4415 | } | 
|  | 4416 |  | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 4417 | bool askSimplifiedValueForAAValueConstantRange(Attributor &A) { | 
|  | 4418 | if (!getAssociatedValue().getType()->isIntegerTy()) | 
|  | 4419 | return false; | 
|  | 4420 |  | 
|  | 4421 | const auto &ValueConstantRangeAA = | 
|  | 4422 | A.getAAFor<AAValueConstantRange>(*this, getIRPosition()); | 
|  | 4423 |  | 
|  | 4424 | Optional<ConstantInt *> COpt = | 
|  | 4425 | ValueConstantRangeAA.getAssumedConstantInt(A); | 
|  | 4426 | if (COpt.hasValue()) { | 
|  | 4427 | if (auto *C = COpt.getValue()) | 
|  | 4428 | SimplifiedAssociatedValue = C; | 
|  | 4429 | else | 
|  | 4430 | return false; | 
|  | 4431 | } else { | 
| Johannes Doerfert | 63adbb9 | 2020-02-09 20:21:56 -0600 | [diff] [blame] | 4432 | SimplifiedAssociatedValue = llvm::None; | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 4433 | } | 
|  | 4434 | return true; | 
|  | 4435 | } | 
|  | 4436 |  | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4437 | /// See AbstractAttribute::manifest(...). | 
|  | 4438 | ChangeStatus manifest(Attributor &A) override { | 
|  | 4439 | ChangeStatus Changed = ChangeStatus::UNCHANGED; | 
|  | 4440 |  | 
|  | 4441 | if (!SimplifiedAssociatedValue.hasValue() || | 
|  | 4442 | !SimplifiedAssociatedValue.getValue()) | 
|  | 4443 | return Changed; | 
|  | 4444 |  | 
|  | 4445 | if (auto *C = dyn_cast<Constant>(SimplifiedAssociatedValue.getValue())) { | 
|  | 4446 | // We can replace the AssociatedValue with the constant. | 
|  | 4447 | Value &V = getAssociatedValue(); | 
|  | 4448 | if (!V.user_empty() && &V != C && V.getType() == C->getType()) { | 
| Johannes Doerfert | 02bd818 | 2020-01-28 11:49:35 -0600 | [diff] [blame] | 4449 | LLVM_DEBUG(dbgs() << "[ValueSimplify] " << V << " -> " << *C | 
|  | 4450 | << " :: " << *this << "\n"); | 
| Johannes Doerfert | 4c62a35 | 2020-01-12 00:17:08 -0600 | [diff] [blame] | 4451 | if (A.changeValueAfterManifest(V, *C)) | 
|  | 4452 | Changed = ChangeStatus::CHANGED; | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4453 | } | 
|  | 4454 | } | 
|  | 4455 |  | 
|  | 4456 | return Changed | AAValueSimplify::manifest(A); | 
|  | 4457 | } | 
|  | 4458 |  | 
| Hideto Ueno | 1d5d074 | 2019-12-25 14:14:32 +0900 | [diff] [blame] | 4459 | /// See AbstractState::indicatePessimisticFixpoint(...). | 
|  | 4460 | ChangeStatus indicatePessimisticFixpoint() override { | 
|  | 4461 | // NOTE: Associated value will be returned in a pessimistic fixpoint and is | 
|  | 4462 | // regarded as known. That's why`indicateOptimisticFixpoint` is called. | 
|  | 4463 | SimplifiedAssociatedValue = &getAssociatedValue(); | 
| Johannes Doerfert | a4b3588 | 2019-12-31 13:25:47 -0600 | [diff] [blame] | 4464 | indicateOptimisticFixpoint(); | 
|  | 4465 | return ChangeStatus::CHANGED; | 
| Hideto Ueno | 1d5d074 | 2019-12-25 14:14:32 +0900 | [diff] [blame] | 4466 | } | 
|  | 4467 |  | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4468 | protected: | 
|  | 4469 | // An assumed simplified value. Initially, it is set to Optional::None, which | 
|  | 4470 | // means that the value is not clear under current assumption. If in the | 
|  | 4471 | // pessimistic state, getAssumedSimplifiedValue doesn't return this value but | 
|  | 4472 | // returns orignal associated value. | 
|  | 4473 | Optional<Value *> SimplifiedAssociatedValue; | 
|  | 4474 | }; | 
|  | 4475 |  | 
|  | 4476 | struct AAValueSimplifyArgument final : AAValueSimplifyImpl { | 
|  | 4477 | AAValueSimplifyArgument(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {} | 
|  | 4478 |  | 
| Johannes Doerfert | 15cd90a | 2019-11-01 13:42:54 -0500 | [diff] [blame] | 4479 | void initialize(Attributor &A) override { | 
|  | 4480 | AAValueSimplifyImpl::initialize(A); | 
|  | 4481 | if (!getAssociatedFunction() || getAssociatedFunction()->isDeclaration()) | 
|  | 4482 | indicatePessimisticFixpoint(); | 
|  | 4483 | if (hasAttr({Attribute::InAlloca, Attribute::StructRet, Attribute::Nest}, | 
|  | 4484 | /* IgnoreSubsumingPositions */ true)) | 
|  | 4485 | indicatePessimisticFixpoint(); | 
|  | 4486 | } | 
|  | 4487 |  | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4488 | /// See AbstractAttribute::updateImpl(...). | 
|  | 4489 | ChangeStatus updateImpl(Attributor &A) override { | 
| Johannes Doerfert | 15cd90a | 2019-11-01 13:42:54 -0500 | [diff] [blame] | 4490 | // Byval is only replacable if it is readonly otherwise we would write into | 
|  | 4491 | // the replaced value and not the copy that byval creates implicitly. | 
|  | 4492 | Argument *Arg = getAssociatedArgument(); | 
|  | 4493 | if (Arg->hasByValAttr()) { | 
|  | 4494 | const auto &MemAA = A.getAAFor<AAMemoryBehavior>(*this, getIRPosition()); | 
|  | 4495 | if (!MemAA.isAssumedReadOnly()) | 
|  | 4496 | return indicatePessimisticFixpoint(); | 
|  | 4497 | } | 
|  | 4498 |  | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4499 | bool HasValueBefore = SimplifiedAssociatedValue.hasValue(); | 
|  | 4500 |  | 
| Johannes Doerfert | 661db04 | 2019-10-07 23:14:58 +0000 | [diff] [blame] | 4501 | auto PredForCallSite = [&](AbstractCallSite ACS) { | 
|  | 4502 | // Check if we have an associated argument or not (which can happen for | 
|  | 4503 | // callback calls). | 
| Johannes Doerfert | e360ee6 | 2019-11-01 18:45:25 -0500 | [diff] [blame] | 4504 | Value *ArgOp = ACS.getCallArgOperand(getArgNo()); | 
|  | 4505 | if (!ArgOp) | 
| Hideto Ueno | 4ecf255 | 2019-12-12 13:42:40 +0000 | [diff] [blame] | 4506 | return false; | 
| Johannes Doerfert | e360ee6 | 2019-11-01 18:45:25 -0500 | [diff] [blame] | 4507 | // We can only propagate thread independent values through callbacks. | 
|  | 4508 | // This is different to direct/indirect call sites because for them we | 
|  | 4509 | // know the thread executing the caller and callee is the same. For | 
|  | 4510 | // callbacks this is not guaranteed, thus a thread dependent value could | 
|  | 4511 | // be different for the caller and callee, making it invalid to propagate. | 
|  | 4512 | if (ACS.isCallbackCall()) | 
| Hideto Ueno | 4ecf255 | 2019-12-12 13:42:40 +0000 | [diff] [blame] | 4513 | if (auto *C = dyn_cast<Constant>(ArgOp)) | 
| Johannes Doerfert | e360ee6 | 2019-11-01 18:45:25 -0500 | [diff] [blame] | 4514 | if (C->isThreadDependent()) | 
|  | 4515 | return false; | 
|  | 4516 | return checkAndUpdate(A, *this, *ArgOp, SimplifiedAssociatedValue); | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4517 | }; | 
|  | 4518 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 4519 | bool AllCallSitesKnown; | 
|  | 4520 | if (!A.checkForAllCallSites(PredForCallSite, *this, true, | 
|  | 4521 | AllCallSitesKnown)) | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 4522 | if (!askSimplifiedValueForAAValueConstantRange(A)) | 
|  | 4523 | return indicatePessimisticFixpoint(); | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4524 |  | 
|  | 4525 | // If a candicate was found in this update, return CHANGED. | 
|  | 4526 | return HasValueBefore == SimplifiedAssociatedValue.hasValue() | 
|  | 4527 | ? ChangeStatus::UNCHANGED | 
|  | 4528 | : ChangeStatus ::CHANGED; | 
|  | 4529 | } | 
|  | 4530 |  | 
|  | 4531 | /// See AbstractAttribute::trackStatistics() | 
|  | 4532 | void trackStatistics() const override { | 
|  | 4533 | STATS_DECLTRACK_ARG_ATTR(value_simplify) | 
|  | 4534 | } | 
|  | 4535 | }; | 
|  | 4536 |  | 
|  | 4537 | struct AAValueSimplifyReturned : AAValueSimplifyImpl { | 
|  | 4538 | AAValueSimplifyReturned(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {} | 
|  | 4539 |  | 
|  | 4540 | /// See AbstractAttribute::updateImpl(...). | 
|  | 4541 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 4542 | bool HasValueBefore = SimplifiedAssociatedValue.hasValue(); | 
|  | 4543 |  | 
|  | 4544 | auto PredForReturned = [&](Value &V) { | 
|  | 4545 | return checkAndUpdate(A, *this, V, SimplifiedAssociatedValue); | 
|  | 4546 | }; | 
|  | 4547 |  | 
|  | 4548 | if (!A.checkForAllReturnedValues(PredForReturned, *this)) | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 4549 | if (!askSimplifiedValueForAAValueConstantRange(A)) | 
|  | 4550 | return indicatePessimisticFixpoint(); | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4551 |  | 
|  | 4552 | // If a candicate was found in this update, return CHANGED. | 
|  | 4553 | return HasValueBefore == SimplifiedAssociatedValue.hasValue() | 
|  | 4554 | ? ChangeStatus::UNCHANGED | 
|  | 4555 | : ChangeStatus ::CHANGED; | 
|  | 4556 | } | 
|  | 4557 | /// See AbstractAttribute::trackStatistics() | 
|  | 4558 | void trackStatistics() const override { | 
|  | 4559 | STATS_DECLTRACK_FNRET_ATTR(value_simplify) | 
|  | 4560 | } | 
|  | 4561 | }; | 
|  | 4562 |  | 
|  | 4563 | struct AAValueSimplifyFloating : AAValueSimplifyImpl { | 
|  | 4564 | AAValueSimplifyFloating(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {} | 
|  | 4565 |  | 
|  | 4566 | /// See AbstractAttribute::initialize(...). | 
|  | 4567 | void initialize(Attributor &A) override { | 
|  | 4568 | Value &V = getAnchorValue(); | 
|  | 4569 |  | 
|  | 4570 | // TODO: add other stuffs | 
| Hideto Ueno | 1d5d074 | 2019-12-25 14:14:32 +0900 | [diff] [blame] | 4571 | if (isa<Constant>(V)) | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4572 | indicatePessimisticFixpoint(); | 
|  | 4573 | } | 
|  | 4574 |  | 
|  | 4575 | /// See AbstractAttribute::updateImpl(...). | 
|  | 4576 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 4577 | bool HasValueBefore = SimplifiedAssociatedValue.hasValue(); | 
|  | 4578 |  | 
| Johannes Doerfert | 76843ba | 2020-01-28 23:51:25 -0600 | [diff] [blame] | 4579 | auto VisitValueCB = [&](Value &V, bool &, bool Stripped) -> bool { | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4580 | auto &AA = A.getAAFor<AAValueSimplify>(*this, IRPosition::value(V)); | 
|  | 4581 | if (!Stripped && this == &AA) { | 
|  | 4582 | // TODO: Look the instruction and check recursively. | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 4583 |  | 
| Johannes Doerfert | 02bd818 | 2020-01-28 11:49:35 -0600 | [diff] [blame] | 4584 | LLVM_DEBUG(dbgs() << "[ValueSimplify] Can't be stripped more : " << V | 
|  | 4585 | << "\n"); | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4586 | return false; | 
|  | 4587 | } | 
|  | 4588 | return checkAndUpdate(A, *this, V, SimplifiedAssociatedValue); | 
|  | 4589 | }; | 
|  | 4590 |  | 
| Johannes Doerfert | 76843ba | 2020-01-28 23:51:25 -0600 | [diff] [blame] | 4591 | bool Dummy = false; | 
| Johannes Doerfert | 6626d1b | 2020-01-28 11:49:59 -0600 | [diff] [blame] | 4592 | if (!genericValueTraversal<AAValueSimplify, bool>(A, getIRPosition(), *this, | 
|  | 4593 | Dummy, VisitValueCB)) | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 4594 | if (!askSimplifiedValueForAAValueConstantRange(A)) | 
|  | 4595 | return indicatePessimisticFixpoint(); | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 4596 |  | 
|  | 4597 | // If a candicate was found in this update, return CHANGED. | 
|  | 4598 |  | 
|  | 4599 | return HasValueBefore == SimplifiedAssociatedValue.hasValue() | 
|  | 4600 | ? ChangeStatus::UNCHANGED | 
|  | 4601 | : ChangeStatus ::CHANGED; | 
|  | 4602 | } | 
|  | 4603 |  | 
|  | 4604 | /// See AbstractAttribute::trackStatistics() | 
|  | 4605 | void trackStatistics() const override { | 
|  | 4606 | STATS_DECLTRACK_FLOATING_ATTR(value_simplify) | 
|  | 4607 | } | 
|  | 4608 | }; | 
|  | 4609 |  | 
|  | 4610 | struct AAValueSimplifyFunction : AAValueSimplifyImpl { | 
|  | 4611 | AAValueSimplifyFunction(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {} | 
|  | 4612 |  | 
|  | 4613 | /// See AbstractAttribute::initialize(...). | 
|  | 4614 | void initialize(Attributor &A) override { | 
|  | 4615 | SimplifiedAssociatedValue = &getAnchorValue(); | 
|  | 4616 | indicateOptimisticFixpoint(); | 
|  | 4617 | } | 
|  | 4618 | /// See AbstractAttribute::initialize(...). | 
|  | 4619 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 4620 | llvm_unreachable( | 
|  | 4621 | "AAValueSimplify(Function|CallSite)::updateImpl will not be called"); | 
|  | 4622 | } | 
|  | 4623 | /// See AbstractAttribute::trackStatistics() | 
|  | 4624 | void trackStatistics() const override { | 
|  | 4625 | STATS_DECLTRACK_FN_ATTR(value_simplify) | 
|  | 4626 | } | 
|  | 4627 | }; | 
|  | 4628 |  | 
|  | 4629 | struct AAValueSimplifyCallSite : AAValueSimplifyFunction { | 
|  | 4630 | AAValueSimplifyCallSite(const IRPosition &IRP) | 
|  | 4631 | : AAValueSimplifyFunction(IRP) {} | 
|  | 4632 | /// See AbstractAttribute::trackStatistics() | 
|  | 4633 | void trackStatistics() const override { | 
|  | 4634 | STATS_DECLTRACK_CS_ATTR(value_simplify) | 
|  | 4635 | } | 
|  | 4636 | }; | 
|  | 4637 |  | 
|  | 4638 | struct AAValueSimplifyCallSiteReturned : AAValueSimplifyReturned { | 
|  | 4639 | AAValueSimplifyCallSiteReturned(const IRPosition &IRP) | 
|  | 4640 | : AAValueSimplifyReturned(IRP) {} | 
|  | 4641 |  | 
|  | 4642 | void trackStatistics() const override { | 
|  | 4643 | STATS_DECLTRACK_CSRET_ATTR(value_simplify) | 
|  | 4644 | } | 
|  | 4645 | }; | 
|  | 4646 | struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating { | 
|  | 4647 | AAValueSimplifyCallSiteArgument(const IRPosition &IRP) | 
|  | 4648 | : AAValueSimplifyFloating(IRP) {} | 
|  | 4649 |  | 
|  | 4650 | void trackStatistics() const override { | 
|  | 4651 | STATS_DECLTRACK_CSARG_ATTR(value_simplify) | 
|  | 4652 | } | 
|  | 4653 | }; | 
|  | 4654 |  | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4655 | /// ----------------------- Heap-To-Stack Conversion --------------------------- | 
|  | 4656 | struct AAHeapToStackImpl : public AAHeapToStack { | 
|  | 4657 | AAHeapToStackImpl(const IRPosition &IRP) : AAHeapToStack(IRP) {} | 
|  | 4658 |  | 
|  | 4659 | const std::string getAsStr() const override { | 
|  | 4660 | return "[H2S] Mallocs: " + std::to_string(MallocCalls.size()); | 
|  | 4661 | } | 
|  | 4662 |  | 
|  | 4663 | ChangeStatus manifest(Attributor &A) override { | 
|  | 4664 | assert(getState().isValidState() && | 
|  | 4665 | "Attempted to manifest an invalid state!"); | 
|  | 4666 |  | 
|  | 4667 | ChangeStatus HasChanged = ChangeStatus::UNCHANGED; | 
|  | 4668 | Function *F = getAssociatedFunction(); | 
|  | 4669 | const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F); | 
|  | 4670 |  | 
|  | 4671 | for (Instruction *MallocCall : MallocCalls) { | 
|  | 4672 | // This malloc cannot be replaced. | 
|  | 4673 | if (BadMallocCalls.count(MallocCall)) | 
|  | 4674 | continue; | 
|  | 4675 |  | 
|  | 4676 | for (Instruction *FreeCall : FreesForMalloc[MallocCall]) { | 
|  | 4677 | LLVM_DEBUG(dbgs() << "H2S: Removing free call: " << *FreeCall << "\n"); | 
|  | 4678 | A.deleteAfterManifest(*FreeCall); | 
|  | 4679 | HasChanged = ChangeStatus::CHANGED; | 
|  | 4680 | } | 
|  | 4681 |  | 
|  | 4682 | LLVM_DEBUG(dbgs() << "H2S: Removing malloc call: " << *MallocCall | 
|  | 4683 | << "\n"); | 
|  | 4684 |  | 
|  | 4685 | Constant *Size; | 
|  | 4686 | if (isCallocLikeFn(MallocCall, TLI)) { | 
|  | 4687 | auto *Num = cast<ConstantInt>(MallocCall->getOperand(0)); | 
|  | 4688 | auto *SizeT = dyn_cast<ConstantInt>(MallocCall->getOperand(1)); | 
|  | 4689 | APInt TotalSize = SizeT->getValue() * Num->getValue(); | 
|  | 4690 | Size = | 
|  | 4691 | ConstantInt::get(MallocCall->getOperand(0)->getType(), TotalSize); | 
|  | 4692 | } else { | 
|  | 4693 | Size = cast<ConstantInt>(MallocCall->getOperand(0)); | 
|  | 4694 | } | 
|  | 4695 |  | 
|  | 4696 | unsigned AS = cast<PointerType>(MallocCall->getType())->getAddressSpace(); | 
|  | 4697 | Instruction *AI = new AllocaInst(Type::getInt8Ty(F->getContext()), AS, | 
|  | 4698 | Size, "", MallocCall->getNextNode()); | 
|  | 4699 |  | 
|  | 4700 | if (AI->getType() != MallocCall->getType()) | 
|  | 4701 | AI = new BitCastInst(AI, MallocCall->getType(), "malloc_bc", | 
|  | 4702 | AI->getNextNode()); | 
|  | 4703 |  | 
| Johannes Doerfert | 4c62a35 | 2020-01-12 00:17:08 -0600 | [diff] [blame] | 4704 | A.changeValueAfterManifest(*MallocCall, *AI); | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4705 |  | 
|  | 4706 | if (auto *II = dyn_cast<InvokeInst>(MallocCall)) { | 
|  | 4707 | auto *NBB = II->getNormalDest(); | 
|  | 4708 | BranchInst::Create(NBB, MallocCall->getParent()); | 
|  | 4709 | A.deleteAfterManifest(*MallocCall); | 
|  | 4710 | } else { | 
|  | 4711 | A.deleteAfterManifest(*MallocCall); | 
|  | 4712 | } | 
|  | 4713 |  | 
|  | 4714 | if (isCallocLikeFn(MallocCall, TLI)) { | 
|  | 4715 | auto *BI = new BitCastInst(AI, MallocCall->getType(), "calloc_bc", | 
|  | 4716 | AI->getNextNode()); | 
|  | 4717 | Value *Ops[] = { | 
|  | 4718 | BI, ConstantInt::get(F->getContext(), APInt(8, 0, false)), Size, | 
|  | 4719 | ConstantInt::get(Type::getInt1Ty(F->getContext()), false)}; | 
|  | 4720 |  | 
|  | 4721 | Type *Tys[] = {BI->getType(), MallocCall->getOperand(0)->getType()}; | 
|  | 4722 | Module *M = F->getParent(); | 
|  | 4723 | Function *Fn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys); | 
|  | 4724 | CallInst::Create(Fn, Ops, "", BI->getNextNode()); | 
|  | 4725 | } | 
|  | 4726 | HasChanged = ChangeStatus::CHANGED; | 
|  | 4727 | } | 
|  | 4728 |  | 
|  | 4729 | return HasChanged; | 
|  | 4730 | } | 
|  | 4731 |  | 
|  | 4732 | /// Collection of all malloc calls in a function. | 
|  | 4733 | SmallSetVector<Instruction *, 4> MallocCalls; | 
|  | 4734 |  | 
|  | 4735 | /// Collection of malloc calls that cannot be converted. | 
|  | 4736 | DenseSet<const Instruction *> BadMallocCalls; | 
|  | 4737 |  | 
|  | 4738 | /// A map for each malloc call to the set of associated free calls. | 
|  | 4739 | DenseMap<Instruction *, SmallPtrSet<Instruction *, 4>> FreesForMalloc; | 
|  | 4740 |  | 
|  | 4741 | ChangeStatus updateImpl(Attributor &A) override; | 
|  | 4742 | }; | 
|  | 4743 |  | 
|  | 4744 | ChangeStatus AAHeapToStackImpl::updateImpl(Attributor &A) { | 
|  | 4745 | const Function *F = getAssociatedFunction(); | 
|  | 4746 | const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F); | 
|  | 4747 |  | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4748 | MustBeExecutedContextExplorer &Explorer = | 
|  | 4749 | A.getInfoCache().getMustBeExecutedContextExplorer(); | 
|  | 4750 |  | 
|  | 4751 | auto FreeCheck = [&](Instruction &I) { | 
|  | 4752 | const auto &Frees = FreesForMalloc.lookup(&I); | 
|  | 4753 | if (Frees.size() != 1) | 
|  | 4754 | return false; | 
|  | 4755 | Instruction *UniqueFree = *Frees.begin(); | 
|  | 4756 | return Explorer.findInContextOf(UniqueFree, I.getNextNode()); | 
|  | 4757 | }; | 
|  | 4758 |  | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4759 | auto UsesCheck = [&](Instruction &I) { | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4760 | bool ValidUsesOnly = true; | 
|  | 4761 | bool MustUse = true; | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4762 | auto Pred = [&](const Use &U, bool &Follow) -> bool { | 
|  | 4763 | Instruction *UserI = cast<Instruction>(U.getUser()); | 
| Johannes Doerfert | af6e479 | 2019-10-13 04:14:15 +0000 | [diff] [blame] | 4764 | if (isa<LoadInst>(UserI)) | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4765 | return true; | 
| Johannes Doerfert | af6e479 | 2019-10-13 04:14:15 +0000 | [diff] [blame] | 4766 | if (auto *SI = dyn_cast<StoreInst>(UserI)) { | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4767 | if (SI->getValueOperand() == U.get()) { | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4768 | LLVM_DEBUG(dbgs() | 
|  | 4769 | << "[H2S] escaping store to memory: " << *UserI << "\n"); | 
|  | 4770 | ValidUsesOnly = false; | 
|  | 4771 | } else { | 
|  | 4772 | // A store into the malloc'ed memory is fine. | 
| Johannes Doerfert | af6e479 | 2019-10-13 04:14:15 +0000 | [diff] [blame] | 4773 | } | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4774 | return true; | 
| Johannes Doerfert | af6e479 | 2019-10-13 04:14:15 +0000 | [diff] [blame] | 4775 | } | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4776 | if (auto *CB = dyn_cast<CallBase>(UserI)) { | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4777 | if (!CB->isArgOperand(&U) || CB->isLifetimeStartOrEnd()) | 
|  | 4778 | return true; | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4779 | // Record malloc. | 
|  | 4780 | if (isFreeCall(UserI, TLI)) { | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4781 | if (MustUse) { | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4782 | FreesForMalloc[&I].insert(UserI); | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4783 | } else { | 
|  | 4784 | LLVM_DEBUG(dbgs() << "[H2S] free potentially on different mallocs: " | 
|  | 4785 | << *UserI << "\n"); | 
|  | 4786 | ValidUsesOnly = false; | 
|  | 4787 | } | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4788 | return true; | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4789 | } | 
|  | 4790 |  | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4791 | unsigned ArgNo = CB->getArgOperandNo(&U); | 
| Stefan Stipanovic | a516fba | 2019-11-17 21:35:04 +0100 | [diff] [blame] | 4792 |  | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4793 | const auto &NoCaptureAA = A.getAAFor<AANoCapture>( | 
|  | 4794 | *this, IRPosition::callsite_argument(*CB, ArgNo)); | 
|  | 4795 |  | 
| Stefan Stipanovic | a516fba | 2019-11-17 21:35:04 +0100 | [diff] [blame] | 4796 | // If a callsite argument use is nofree, we are fine. | 
|  | 4797 | const auto &ArgNoFreeAA = A.getAAFor<AANoFree>( | 
|  | 4798 | *this, IRPosition::callsite_argument(*CB, ArgNo)); | 
|  | 4799 |  | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4800 | if (!NoCaptureAA.isAssumedNoCapture() || | 
|  | 4801 | !ArgNoFreeAA.isAssumedNoFree()) { | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4802 | LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n"); | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4803 | ValidUsesOnly = false; | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4804 | } | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4805 | return true; | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4806 | } | 
|  | 4807 |  | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4808 | if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) || | 
|  | 4809 | isa<PHINode>(UserI) || isa<SelectInst>(UserI)) { | 
|  | 4810 | MustUse &= !(isa<PHINode>(UserI) || isa<SelectInst>(UserI)); | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4811 | Follow = true; | 
|  | 4812 | return true; | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4813 | } | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4814 | // Unknown user for which we can not track uses further (in a way that | 
|  | 4815 | // makes sense). | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4816 | LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n"); | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4817 | ValidUsesOnly = false; | 
| Hideto Ueno | 827bade | 2019-12-12 12:26:30 +0000 | [diff] [blame] | 4818 | return true; | 
|  | 4819 | }; | 
|  | 4820 | A.checkForAllUses(Pred, *this, I); | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4821 | return ValidUsesOnly; | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4822 | }; | 
|  | 4823 |  | 
|  | 4824 | auto MallocCallocCheck = [&](Instruction &I) { | 
| Johannes Doerfert | d20f807 | 2019-10-13 03:54:08 +0000 | [diff] [blame] | 4825 | if (BadMallocCalls.count(&I)) | 
|  | 4826 | return true; | 
|  | 4827 |  | 
|  | 4828 | bool IsMalloc = isMallocLikeFn(&I, TLI); | 
|  | 4829 | bool IsCalloc = !IsMalloc && isCallocLikeFn(&I, TLI); | 
|  | 4830 | if (!IsMalloc && !IsCalloc) { | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4831 | BadMallocCalls.insert(&I); | 
|  | 4832 | return true; | 
|  | 4833 | } | 
|  | 4834 |  | 
| Johannes Doerfert | d20f807 | 2019-10-13 03:54:08 +0000 | [diff] [blame] | 4835 | if (IsMalloc) { | 
|  | 4836 | if (auto *Size = dyn_cast<ConstantInt>(I.getOperand(0))) | 
| Stefan Stipanovic | fff8ec9 | 2019-12-17 20:41:09 +0100 | [diff] [blame] | 4837 | if (Size->getValue().ule(MaxHeapToStackSize)) | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4838 | if (UsesCheck(I) || FreeCheck(I)) { | 
| Johannes Doerfert | d20f807 | 2019-10-13 03:54:08 +0000 | [diff] [blame] | 4839 | MallocCalls.insert(&I); | 
|  | 4840 | return true; | 
|  | 4841 | } | 
|  | 4842 | } else if (IsCalloc) { | 
|  | 4843 | bool Overflow = false; | 
|  | 4844 | if (auto *Num = dyn_cast<ConstantInt>(I.getOperand(0))) | 
|  | 4845 | if (auto *Size = dyn_cast<ConstantInt>(I.getOperand(1))) | 
|  | 4846 | if ((Size->getValue().umul_ov(Num->getValue(), Overflow)) | 
| Stefan Stipanovic | fff8ec9 | 2019-12-17 20:41:09 +0100 | [diff] [blame] | 4847 | .ule(MaxHeapToStackSize)) | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4848 | if (!Overflow && (UsesCheck(I) || FreeCheck(I))) { | 
| Johannes Doerfert | d20f807 | 2019-10-13 03:54:08 +0000 | [diff] [blame] | 4849 | MallocCalls.insert(&I); | 
|  | 4850 | return true; | 
|  | 4851 | } | 
|  | 4852 | } | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4853 |  | 
| Johannes Doerfert | d20f807 | 2019-10-13 03:54:08 +0000 | [diff] [blame] | 4854 | BadMallocCalls.insert(&I); | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4855 | return true; | 
|  | 4856 | }; | 
|  | 4857 |  | 
|  | 4858 | size_t NumBadMallocs = BadMallocCalls.size(); | 
|  | 4859 |  | 
|  | 4860 | A.checkForAllCallLikeInstructions(MallocCallocCheck, *this); | 
|  | 4861 |  | 
|  | 4862 | if (NumBadMallocs != BadMallocCalls.size()) | 
|  | 4863 | return ChangeStatus::CHANGED; | 
|  | 4864 |  | 
|  | 4865 | return ChangeStatus::UNCHANGED; | 
|  | 4866 | } | 
|  | 4867 |  | 
|  | 4868 | struct AAHeapToStackFunction final : public AAHeapToStackImpl { | 
|  | 4869 | AAHeapToStackFunction(const IRPosition &IRP) : AAHeapToStackImpl(IRP) {} | 
|  | 4870 |  | 
|  | 4871 | /// See AbstractAttribute::trackStatistics() | 
|  | 4872 | void trackStatistics() const override { | 
|  | 4873 | STATS_DECL(MallocCalls, Function, | 
| Johannes Doerfert | 0be9cf2 | 2019-10-14 17:29:05 -0500 | [diff] [blame] | 4874 | "Number of malloc calls converted to allocas"); | 
|  | 4875 | for (auto *C : MallocCalls) | 
|  | 4876 | if (!BadMallocCalls.count(C)) | 
|  | 4877 | ++BUILD_STAT_NAME(MallocCalls, Function); | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 4878 | } | 
|  | 4879 | }; | 
|  | 4880 |  | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 4881 | /// ----------------------- Privatizable Pointers ------------------------------ | 
|  | 4882 | struct AAPrivatizablePtrImpl : public AAPrivatizablePtr { | 
|  | 4883 | AAPrivatizablePtrImpl(const IRPosition &IRP) | 
|  | 4884 | : AAPrivatizablePtr(IRP), PrivatizableType(llvm::None) {} | 
|  | 4885 |  | 
|  | 4886 | ChangeStatus indicatePessimisticFixpoint() override { | 
|  | 4887 | AAPrivatizablePtr::indicatePessimisticFixpoint(); | 
|  | 4888 | PrivatizableType = nullptr; | 
|  | 4889 | return ChangeStatus::CHANGED; | 
|  | 4890 | } | 
|  | 4891 |  | 
|  | 4892 | /// Identify the type we can chose for a private copy of the underlying | 
|  | 4893 | /// argument. None means it is not clear yet, nullptr means there is none. | 
|  | 4894 | virtual Optional<Type *> identifyPrivatizableType(Attributor &A) = 0; | 
|  | 4895 |  | 
|  | 4896 | /// Return a privatizable type that encloses both T0 and T1. | 
|  | 4897 | /// TODO: This is merely a stub for now as we should manage a mapping as well. | 
|  | 4898 | Optional<Type *> combineTypes(Optional<Type *> T0, Optional<Type *> T1) { | 
|  | 4899 | if (!T0.hasValue()) | 
|  | 4900 | return T1; | 
|  | 4901 | if (!T1.hasValue()) | 
|  | 4902 | return T0; | 
|  | 4903 | if (T0 == T1) | 
|  | 4904 | return T0; | 
|  | 4905 | return nullptr; | 
|  | 4906 | } | 
|  | 4907 |  | 
|  | 4908 | Optional<Type *> getPrivatizableType() const override { | 
|  | 4909 | return PrivatizableType; | 
|  | 4910 | } | 
|  | 4911 |  | 
|  | 4912 | const std::string getAsStr() const override { | 
|  | 4913 | return isAssumedPrivatizablePtr() ? "[priv]" : "[no-priv]"; | 
|  | 4914 | } | 
|  | 4915 |  | 
|  | 4916 | protected: | 
|  | 4917 | Optional<Type *> PrivatizableType; | 
|  | 4918 | }; | 
|  | 4919 |  | 
|  | 4920 | // TODO: Do this for call site arguments (probably also other values) as well. | 
|  | 4921 |  | 
|  | 4922 | struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl { | 
|  | 4923 | AAPrivatizablePtrArgument(const IRPosition &IRP) | 
|  | 4924 | : AAPrivatizablePtrImpl(IRP) {} | 
|  | 4925 |  | 
|  | 4926 | /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...) | 
|  | 4927 | Optional<Type *> identifyPrivatizableType(Attributor &A) override { | 
|  | 4928 | // If this is a byval argument and we know all the call sites (so we can | 
|  | 4929 | // rewrite them), there is no need to check them explicitly. | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 4930 | bool AllCallSitesKnown; | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 4931 | if (getIRPosition().hasAttr(Attribute::ByVal) && | 
|  | 4932 | A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this, | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 4933 | true, AllCallSitesKnown)) | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 4934 | return getAssociatedValue().getType()->getPointerElementType(); | 
|  | 4935 |  | 
|  | 4936 | Optional<Type *> Ty; | 
|  | 4937 | unsigned ArgNo = getIRPosition().getArgNo(); | 
|  | 4938 |  | 
|  | 4939 | // Make sure the associated call site argument has the same type at all call | 
|  | 4940 | // sites and it is an allocation we know is safe to privatize, for now that | 
|  | 4941 | // means we only allow alloca instructions. | 
|  | 4942 | // TODO: We can additionally analyze the accesses in the callee to  create | 
|  | 4943 | //       the type from that information instead. That is a little more | 
|  | 4944 | //       involved and will be done in a follow up patch. | 
|  | 4945 | auto CallSiteCheck = [&](AbstractCallSite ACS) { | 
|  | 4946 | IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo); | 
|  | 4947 | // Check if a coresponding argument was found or if it is one not | 
|  | 4948 | // associated (which can happen for callback calls). | 
|  | 4949 | if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID) | 
|  | 4950 | return false; | 
|  | 4951 |  | 
|  | 4952 | // Check that all call sites agree on a type. | 
|  | 4953 | auto &PrivCSArgAA = A.getAAFor<AAPrivatizablePtr>(*this, ACSArgPos); | 
|  | 4954 | Optional<Type *> CSTy = PrivCSArgAA.getPrivatizableType(); | 
|  | 4955 |  | 
|  | 4956 | LLVM_DEBUG({ | 
|  | 4957 | dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSTy: "; | 
|  | 4958 | if (CSTy.hasValue() && CSTy.getValue()) | 
|  | 4959 | CSTy.getValue()->print(dbgs()); | 
|  | 4960 | else if (CSTy.hasValue()) | 
|  | 4961 | dbgs() << "<nullptr>"; | 
|  | 4962 | else | 
|  | 4963 | dbgs() << "<none>"; | 
|  | 4964 | }); | 
|  | 4965 |  | 
|  | 4966 | Ty = combineTypes(Ty, CSTy); | 
|  | 4967 |  | 
|  | 4968 | LLVM_DEBUG({ | 
|  | 4969 | dbgs() << " : New Type: "; | 
|  | 4970 | if (Ty.hasValue() && Ty.getValue()) | 
|  | 4971 | Ty.getValue()->print(dbgs()); | 
|  | 4972 | else if (Ty.hasValue()) | 
|  | 4973 | dbgs() << "<nullptr>"; | 
|  | 4974 | else | 
|  | 4975 | dbgs() << "<none>"; | 
|  | 4976 | dbgs() << "\n"; | 
|  | 4977 | }); | 
|  | 4978 |  | 
|  | 4979 | return !Ty.hasValue() || Ty.getValue(); | 
|  | 4980 | }; | 
|  | 4981 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 4982 | if (!A.checkForAllCallSites(CallSiteCheck, *this, true, AllCallSitesKnown)) | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 4983 | return nullptr; | 
|  | 4984 | return Ty; | 
|  | 4985 | } | 
|  | 4986 |  | 
|  | 4987 | /// See AbstractAttribute::updateImpl(...). | 
|  | 4988 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 4989 | PrivatizableType = identifyPrivatizableType(A); | 
|  | 4990 | if (!PrivatizableType.hasValue()) | 
|  | 4991 | return ChangeStatus::UNCHANGED; | 
|  | 4992 | if (!PrivatizableType.getValue()) | 
|  | 4993 | return indicatePessimisticFixpoint(); | 
|  | 4994 |  | 
|  | 4995 | // Avoid arguments with padding for now. | 
|  | 4996 | if (!getIRPosition().hasAttr(Attribute::ByVal) && | 
|  | 4997 | !ArgumentPromotionPass::isDenselyPacked(PrivatizableType.getValue(), | 
|  | 4998 | A.getInfoCache().getDL())) { | 
|  | 4999 | LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n"); | 
|  | 5000 | return indicatePessimisticFixpoint(); | 
|  | 5001 | } | 
|  | 5002 |  | 
|  | 5003 | // Verify callee and caller agree on how the promoted argument would be | 
|  | 5004 | // passed. | 
|  | 5005 | // TODO: The use of the ArgumentPromotion interface here is ugly, we need a | 
|  | 5006 | // specialized form of TargetTransformInfo::areFunctionArgsABICompatible | 
|  | 5007 | // which doesn't require the arguments ArgumentPromotion wanted to pass. | 
|  | 5008 | Function &Fn = *getIRPosition().getAnchorScope(); | 
|  | 5009 | SmallPtrSet<Argument *, 1> ArgsToPromote, Dummy; | 
|  | 5010 | ArgsToPromote.insert(getAssociatedArgument()); | 
|  | 5011 | const auto *TTI = | 
|  | 5012 | A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn); | 
|  | 5013 | if (!TTI || | 
|  | 5014 | !ArgumentPromotionPass::areFunctionArgsABICompatible( | 
|  | 5015 | Fn, *TTI, ArgsToPromote, Dummy) || | 
|  | 5016 | ArgsToPromote.empty()) { | 
|  | 5017 | LLVM_DEBUG( | 
|  | 5018 | dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for " | 
|  | 5019 | << Fn.getName() << "\n"); | 
|  | 5020 | return indicatePessimisticFixpoint(); | 
|  | 5021 | } | 
|  | 5022 |  | 
|  | 5023 | // Collect the types that will replace the privatizable type in the function | 
|  | 5024 | // signature. | 
|  | 5025 | SmallVector<Type *, 16> ReplacementTypes; | 
|  | 5026 | identifyReplacementTypes(PrivatizableType.getValue(), ReplacementTypes); | 
|  | 5027 |  | 
|  | 5028 | // Register a rewrite of the argument. | 
|  | 5029 | Argument *Arg = getAssociatedArgument(); | 
|  | 5030 | if (!A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) { | 
|  | 5031 | LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n"); | 
|  | 5032 | return indicatePessimisticFixpoint(); | 
|  | 5033 | } | 
|  | 5034 |  | 
|  | 5035 | unsigned ArgNo = Arg->getArgNo(); | 
|  | 5036 |  | 
|  | 5037 | // Helper to check if for the given call site the associated argument is | 
|  | 5038 | // passed to a callback where the privatization would be different. | 
|  | 5039 | auto IsCompatiblePrivArgOfCallback = [&](CallSite CS) { | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 5040 | SmallVector<const Use *, 4> CBUses; | 
|  | 5041 | AbstractCallSite::getCallbackUses(CS, CBUses); | 
|  | 5042 | for (const Use *U : CBUses) { | 
|  | 5043 | AbstractCallSite CBACS(U); | 
|  | 5044 | assert(CBACS && CBACS.isCallbackCall()); | 
|  | 5045 | for (Argument &CBArg : CBACS.getCalledFunction()->args()) { | 
|  | 5046 | int CBArgNo = CBACS.getCallArgOperandNo(CBArg); | 
|  | 5047 |  | 
|  | 5048 | LLVM_DEBUG({ | 
|  | 5049 | dbgs() | 
|  | 5050 | << "[AAPrivatizablePtr] Argument " << *Arg | 
|  | 5051 | << "check if can be privatized in the context of its parent (" | 
|  | 5052 | << Arg->getParent()->getName() | 
|  | 5053 | << ")\n[AAPrivatizablePtr] because it is an argument in a " | 
|  | 5054 | "callback (" | 
|  | 5055 | << CBArgNo << "@" << CBACS.getCalledFunction()->getName() | 
|  | 5056 | << ")\n[AAPrivatizablePtr] " << CBArg << " : " | 
| Michael Forster | 676c296 | 2020-01-30 10:20:49 +0100 | [diff] [blame] | 5057 | << CBACS.getCallArgOperand(CBArg) << " vs " | 
|  | 5058 | << CS.getArgOperand(ArgNo) << "\n" | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 5059 | << "[AAPrivatizablePtr] " << CBArg << " : " | 
|  | 5060 | << CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo << "\n"; | 
|  | 5061 | }); | 
|  | 5062 |  | 
|  | 5063 | if (CBArgNo != int(ArgNo)) | 
|  | 5064 | continue; | 
|  | 5065 | const auto &CBArgPrivAA = | 
|  | 5066 | A.getAAFor<AAPrivatizablePtr>(*this, IRPosition::argument(CBArg)); | 
|  | 5067 | if (CBArgPrivAA.isValidState()) { | 
|  | 5068 | auto CBArgPrivTy = CBArgPrivAA.getPrivatizableType(); | 
|  | 5069 | if (!CBArgPrivTy.hasValue()) | 
|  | 5070 | continue; | 
|  | 5071 | if (CBArgPrivTy.getValue() == PrivatizableType) | 
|  | 5072 | continue; | 
|  | 5073 | } | 
|  | 5074 |  | 
|  | 5075 | LLVM_DEBUG({ | 
|  | 5076 | dbgs() << "[AAPrivatizablePtr] Argument " << *Arg | 
|  | 5077 | << " cannot be privatized in the context of its parent (" | 
|  | 5078 | << Arg->getParent()->getName() | 
|  | 5079 | << ")\n[AAPrivatizablePtr] because it is an argument in a " | 
|  | 5080 | "callback (" | 
|  | 5081 | << CBArgNo << "@" << CBACS.getCalledFunction()->getName() | 
|  | 5082 | << ").\n[AAPrivatizablePtr] for which the argument " | 
|  | 5083 | "privatization is not compatible.\n"; | 
|  | 5084 | }); | 
|  | 5085 | return false; | 
|  | 5086 | } | 
|  | 5087 | } | 
|  | 5088 | return true; | 
|  | 5089 | }; | 
|  | 5090 |  | 
|  | 5091 | // Helper to check if for the given call site the associated argument is | 
|  | 5092 | // passed to a direct call where the privatization would be different. | 
|  | 5093 | auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) { | 
|  | 5094 | CallBase *DC = cast<CallBase>(ACS.getInstruction()); | 
|  | 5095 | int DCArgNo = ACS.getCallArgOperandNo(ArgNo); | 
|  | 5096 | assert(DCArgNo >= 0 && unsigned(DCArgNo) < DC->getNumArgOperands() && | 
|  | 5097 | "Expected a direct call operand for callback call operand"); | 
|  | 5098 |  | 
|  | 5099 | LLVM_DEBUG({ | 
|  | 5100 | dbgs() << "[AAPrivatizablePtr] Argument " << *Arg | 
|  | 5101 | << " check if be privatized in the context of its parent (" | 
|  | 5102 | << Arg->getParent()->getName() | 
|  | 5103 | << ")\n[AAPrivatizablePtr] because it is an argument in a " | 
|  | 5104 | "direct call of (" | 
|  | 5105 | << DCArgNo << "@" << DC->getCalledFunction()->getName() | 
|  | 5106 | << ").\n"; | 
|  | 5107 | }); | 
|  | 5108 |  | 
|  | 5109 | Function *DCCallee = DC->getCalledFunction(); | 
|  | 5110 | if (unsigned(DCArgNo) < DCCallee->arg_size()) { | 
|  | 5111 | const auto &DCArgPrivAA = A.getAAFor<AAPrivatizablePtr>( | 
|  | 5112 | *this, IRPosition::argument(*DCCallee->getArg(DCArgNo))); | 
|  | 5113 | if (DCArgPrivAA.isValidState()) { | 
|  | 5114 | auto DCArgPrivTy = DCArgPrivAA.getPrivatizableType(); | 
|  | 5115 | if (!DCArgPrivTy.hasValue()) | 
|  | 5116 | return true; | 
|  | 5117 | if (DCArgPrivTy.getValue() == PrivatizableType) | 
|  | 5118 | return true; | 
|  | 5119 | } | 
|  | 5120 | } | 
|  | 5121 |  | 
|  | 5122 | LLVM_DEBUG({ | 
|  | 5123 | dbgs() << "[AAPrivatizablePtr] Argument " << *Arg | 
|  | 5124 | << " cannot be privatized in the context of its parent (" | 
|  | 5125 | << Arg->getParent()->getName() | 
|  | 5126 | << ")\n[AAPrivatizablePtr] because it is an argument in a " | 
|  | 5127 | "direct call of (" | 
|  | 5128 | << ACS.getCallSite().getCalledFunction()->getName() | 
|  | 5129 | << ").\n[AAPrivatizablePtr] for which the argument " | 
|  | 5130 | "privatization is not compatible.\n"; | 
|  | 5131 | }); | 
|  | 5132 | return false; | 
|  | 5133 | }; | 
|  | 5134 |  | 
|  | 5135 | // Helper to check if the associated argument is used at the given abstract | 
|  | 5136 | // call site in a way that is incompatible with the privatization assumed | 
|  | 5137 | // here. | 
|  | 5138 | auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) { | 
|  | 5139 | if (ACS.isDirectCall()) | 
|  | 5140 | return IsCompatiblePrivArgOfCallback(ACS.getCallSite()); | 
|  | 5141 | if (ACS.isCallbackCall()) | 
|  | 5142 | return IsCompatiblePrivArgOfDirectCS(ACS); | 
|  | 5143 | return false; | 
|  | 5144 | }; | 
|  | 5145 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 5146 | bool AllCallSitesKnown; | 
|  | 5147 | if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true, | 
|  | 5148 | AllCallSitesKnown)) | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 5149 | return indicatePessimisticFixpoint(); | 
|  | 5150 |  | 
|  | 5151 | return ChangeStatus::UNCHANGED; | 
|  | 5152 | } | 
|  | 5153 |  | 
|  | 5154 | /// Given a type to private \p PrivType, collect the constituates (which are | 
|  | 5155 | /// used) in \p ReplacementTypes. | 
|  | 5156 | static void | 
|  | 5157 | identifyReplacementTypes(Type *PrivType, | 
|  | 5158 | SmallVectorImpl<Type *> &ReplacementTypes) { | 
|  | 5159 | // TODO: For now we expand the privatization type to the fullest which can | 
|  | 5160 | //       lead to dead arguments that need to be removed later. | 
|  | 5161 | assert(PrivType && "Expected privatizable type!"); | 
|  | 5162 |  | 
|  | 5163 | // Traverse the type, extract constituate types on the outermost level. | 
|  | 5164 | if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) { | 
|  | 5165 | for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) | 
|  | 5166 | ReplacementTypes.push_back(PrivStructType->getElementType(u)); | 
|  | 5167 | } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) { | 
|  | 5168 | ReplacementTypes.append(PrivArrayType->getNumElements(), | 
|  | 5169 | PrivArrayType->getElementType()); | 
|  | 5170 | } else { | 
|  | 5171 | ReplacementTypes.push_back(PrivType); | 
|  | 5172 | } | 
|  | 5173 | } | 
|  | 5174 |  | 
|  | 5175 | /// Initialize \p Base according to the type \p PrivType at position \p IP. | 
|  | 5176 | /// The values needed are taken from the arguments of \p F starting at | 
|  | 5177 | /// position \p ArgNo. | 
|  | 5178 | static void createInitialization(Type *PrivType, Value &Base, Function &F, | 
|  | 5179 | unsigned ArgNo, Instruction &IP) { | 
|  | 5180 | assert(PrivType && "Expected privatizable type!"); | 
|  | 5181 |  | 
|  | 5182 | IRBuilder<NoFolder> IRB(&IP); | 
|  | 5183 | const DataLayout &DL = F.getParent()->getDataLayout(); | 
|  | 5184 |  | 
|  | 5185 | // Traverse the type, build GEPs and stores. | 
|  | 5186 | if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) { | 
|  | 5187 | const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType); | 
|  | 5188 | for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) { | 
|  | 5189 | Type *PointeeTy = PrivStructType->getElementType(u)->getPointerTo(); | 
|  | 5190 | Value *Ptr = constructPointer( | 
|  | 5191 | PointeeTy, &Base, PrivStructLayout->getElementOffset(u), IRB, DL); | 
|  | 5192 | new StoreInst(F.getArg(ArgNo + u), Ptr, &IP); | 
|  | 5193 | } | 
|  | 5194 | } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) { | 
|  | 5195 | Type *PointeePtrTy = PrivArrayType->getElementType()->getPointerTo(); | 
|  | 5196 | uint64_t PointeeTySize = DL.getTypeStoreSize(PointeePtrTy); | 
|  | 5197 | for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) { | 
|  | 5198 | Value *Ptr = | 
|  | 5199 | constructPointer(PointeePtrTy, &Base, u * PointeeTySize, IRB, DL); | 
|  | 5200 | new StoreInst(F.getArg(ArgNo + u), Ptr, &IP); | 
|  | 5201 | } | 
|  | 5202 | } else { | 
|  | 5203 | new StoreInst(F.getArg(ArgNo), &Base, &IP); | 
|  | 5204 | } | 
|  | 5205 | } | 
|  | 5206 |  | 
|  | 5207 | /// Extract values from \p Base according to the type \p PrivType at the | 
|  | 5208 | /// call position \p ACS. The values are appended to \p ReplacementValues. | 
|  | 5209 | void createReplacementValues(Type *PrivType, AbstractCallSite ACS, | 
|  | 5210 | Value *Base, | 
|  | 5211 | SmallVectorImpl<Value *> &ReplacementValues) { | 
|  | 5212 | assert(Base && "Expected base value!"); | 
|  | 5213 | assert(PrivType && "Expected privatizable type!"); | 
|  | 5214 | Instruction *IP = ACS.getInstruction(); | 
|  | 5215 |  | 
|  | 5216 | IRBuilder<NoFolder> IRB(IP); | 
|  | 5217 | const DataLayout &DL = IP->getModule()->getDataLayout(); | 
|  | 5218 |  | 
|  | 5219 | if (Base->getType()->getPointerElementType() != PrivType) | 
|  | 5220 | Base = BitCastInst::CreateBitOrPointerCast(Base, PrivType->getPointerTo(), | 
|  | 5221 | "", ACS.getInstruction()); | 
|  | 5222 |  | 
|  | 5223 | // TODO: Improve the alignment of the loads. | 
|  | 5224 | // Traverse the type, build GEPs and loads. | 
|  | 5225 | if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) { | 
|  | 5226 | const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType); | 
|  | 5227 | for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) { | 
|  | 5228 | Type *PointeeTy = PrivStructType->getElementType(u); | 
|  | 5229 | Value *Ptr = | 
|  | 5230 | constructPointer(PointeeTy->getPointerTo(), Base, | 
|  | 5231 | PrivStructLayout->getElementOffset(u), IRB, DL); | 
|  | 5232 | LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP); | 
|  | 5233 | L->setAlignment(MaybeAlign(1)); | 
|  | 5234 | ReplacementValues.push_back(L); | 
|  | 5235 | } | 
|  | 5236 | } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) { | 
|  | 5237 | Type *PointeeTy = PrivArrayType->getElementType(); | 
|  | 5238 | uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy); | 
|  | 5239 | Type *PointeePtrTy = PointeeTy->getPointerTo(); | 
|  | 5240 | for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) { | 
|  | 5241 | Value *Ptr = | 
|  | 5242 | constructPointer(PointeePtrTy, Base, u * PointeeTySize, IRB, DL); | 
|  | 5243 | LoadInst *L = new LoadInst(PointeePtrTy, Ptr, "", IP); | 
|  | 5244 | L->setAlignment(MaybeAlign(1)); | 
|  | 5245 | ReplacementValues.push_back(L); | 
|  | 5246 | } | 
|  | 5247 | } else { | 
|  | 5248 | LoadInst *L = new LoadInst(PrivType, Base, "", IP); | 
|  | 5249 | L->setAlignment(MaybeAlign(1)); | 
|  | 5250 | ReplacementValues.push_back(L); | 
|  | 5251 | } | 
|  | 5252 | } | 
|  | 5253 |  | 
|  | 5254 | /// See AbstractAttribute::manifest(...) | 
|  | 5255 | ChangeStatus manifest(Attributor &A) override { | 
|  | 5256 | if (!PrivatizableType.hasValue()) | 
|  | 5257 | return ChangeStatus::UNCHANGED; | 
|  | 5258 | assert(PrivatizableType.getValue() && "Expected privatizable type!"); | 
|  | 5259 |  | 
|  | 5260 | // Collect all tail calls in the function as we cannot allow new allocas to | 
|  | 5261 | // escape into tail recursion. | 
|  | 5262 | // TODO: Be smarter about new allocas escaping into tail calls. | 
|  | 5263 | SmallVector<CallInst *, 16> TailCalls; | 
|  | 5264 | if (!A.checkForAllInstructions( | 
|  | 5265 | [&](Instruction &I) { | 
|  | 5266 | CallInst &CI = cast<CallInst>(I); | 
|  | 5267 | if (CI.isTailCall()) | 
|  | 5268 | TailCalls.push_back(&CI); | 
|  | 5269 | return true; | 
|  | 5270 | }, | 
|  | 5271 | *this, {Instruction::Call})) | 
|  | 5272 | return ChangeStatus::UNCHANGED; | 
|  | 5273 |  | 
|  | 5274 | Argument *Arg = getAssociatedArgument(); | 
|  | 5275 |  | 
|  | 5276 | // Callback to repair the associated function. A new alloca is placed at the | 
|  | 5277 | // beginning and initialized with the values passed through arguments. The | 
|  | 5278 | // new alloca replaces the use of the old pointer argument. | 
|  | 5279 | Attributor::ArgumentReplacementInfo::CalleeRepairCBTy FnRepairCB = | 
|  | 5280 | [=](const Attributor::ArgumentReplacementInfo &ARI, | 
|  | 5281 | Function &ReplacementFn, Function::arg_iterator ArgIt) { | 
|  | 5282 | BasicBlock &EntryBB = ReplacementFn.getEntryBlock(); | 
|  | 5283 | Instruction *IP = &*EntryBB.getFirstInsertionPt(); | 
|  | 5284 | auto *AI = new AllocaInst(PrivatizableType.getValue(), 0, | 
|  | 5285 | Arg->getName() + ".priv", IP); | 
|  | 5286 | createInitialization(PrivatizableType.getValue(), *AI, ReplacementFn, | 
|  | 5287 | ArgIt->getArgNo(), *IP); | 
|  | 5288 | Arg->replaceAllUsesWith(AI); | 
|  | 5289 |  | 
|  | 5290 | for (CallInst *CI : TailCalls) | 
|  | 5291 | CI->setTailCall(false); | 
|  | 5292 | }; | 
|  | 5293 |  | 
|  | 5294 | // Callback to repair a call site of the associated function. The elements | 
|  | 5295 | // of the privatizable type are loaded prior to the call and passed to the | 
|  | 5296 | // new function version. | 
|  | 5297 | Attributor::ArgumentReplacementInfo::ACSRepairCBTy ACSRepairCB = | 
|  | 5298 | [=](const Attributor::ArgumentReplacementInfo &ARI, | 
|  | 5299 | AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) { | 
|  | 5300 | createReplacementValues( | 
|  | 5301 | PrivatizableType.getValue(), ACS, | 
|  | 5302 | ACS.getCallArgOperand(ARI.getReplacedArg().getArgNo()), | 
|  | 5303 | NewArgOperands); | 
|  | 5304 | }; | 
|  | 5305 |  | 
|  | 5306 | // Collect the types that will replace the privatizable type in the function | 
|  | 5307 | // signature. | 
|  | 5308 | SmallVector<Type *, 16> ReplacementTypes; | 
|  | 5309 | identifyReplacementTypes(PrivatizableType.getValue(), ReplacementTypes); | 
|  | 5310 |  | 
|  | 5311 | // Register a rewrite of the argument. | 
|  | 5312 | if (A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes, | 
|  | 5313 | std::move(FnRepairCB), | 
|  | 5314 | std::move(ACSRepairCB))) | 
|  | 5315 | return ChangeStatus::CHANGED; | 
|  | 5316 | return ChangeStatus::UNCHANGED; | 
|  | 5317 | } | 
|  | 5318 |  | 
|  | 5319 | /// See AbstractAttribute::trackStatistics() | 
|  | 5320 | void trackStatistics() const override { | 
|  | 5321 | STATS_DECLTRACK_ARG_ATTR(privatizable_ptr); | 
|  | 5322 | } | 
|  | 5323 | }; | 
|  | 5324 |  | 
|  | 5325 | struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl { | 
|  | 5326 | AAPrivatizablePtrFloating(const IRPosition &IRP) | 
|  | 5327 | : AAPrivatizablePtrImpl(IRP) {} | 
|  | 5328 |  | 
|  | 5329 | /// See AbstractAttribute::initialize(...). | 
|  | 5330 | virtual void initialize(Attributor &A) override { | 
|  | 5331 | // TODO: We can privatize more than arguments. | 
|  | 5332 | indicatePessimisticFixpoint(); | 
|  | 5333 | } | 
|  | 5334 |  | 
|  | 5335 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 5336 | llvm_unreachable("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::" | 
|  | 5337 | "updateImpl will not be called"); | 
|  | 5338 | } | 
|  | 5339 |  | 
|  | 5340 | /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...) | 
|  | 5341 | Optional<Type *> identifyPrivatizableType(Attributor &A) override { | 
|  | 5342 | Value *Obj = | 
|  | 5343 | GetUnderlyingObject(&getAssociatedValue(), A.getInfoCache().getDL()); | 
|  | 5344 | if (!Obj) { | 
|  | 5345 | LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] No underlying object found!\n"); | 
|  | 5346 | return nullptr; | 
|  | 5347 | } | 
|  | 5348 |  | 
|  | 5349 | if (auto *AI = dyn_cast<AllocaInst>(Obj)) | 
|  | 5350 | if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize())) | 
|  | 5351 | if (CI->isOne()) | 
|  | 5352 | return Obj->getType()->getPointerElementType(); | 
|  | 5353 | if (auto *Arg = dyn_cast<Argument>(Obj)) { | 
|  | 5354 | auto &PrivArgAA = | 
|  | 5355 | A.getAAFor<AAPrivatizablePtr>(*this, IRPosition::argument(*Arg)); | 
|  | 5356 | if (PrivArgAA.isAssumedPrivatizablePtr()) | 
|  | 5357 | return Obj->getType()->getPointerElementType(); | 
|  | 5358 | } | 
|  | 5359 |  | 
|  | 5360 | LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Underlying object neither valid " | 
|  | 5361 | "alloca nor privatizable argument: " | 
|  | 5362 | << *Obj << "!\n"); | 
|  | 5363 | return nullptr; | 
|  | 5364 | } | 
|  | 5365 |  | 
|  | 5366 | /// See AbstractAttribute::trackStatistics() | 
|  | 5367 | void trackStatistics() const override { | 
|  | 5368 | STATS_DECLTRACK_FLOATING_ATTR(privatizable_ptr); | 
|  | 5369 | } | 
|  | 5370 | }; | 
|  | 5371 |  | 
|  | 5372 | struct AAPrivatizablePtrCallSiteArgument final | 
|  | 5373 | : public AAPrivatizablePtrFloating { | 
|  | 5374 | AAPrivatizablePtrCallSiteArgument(const IRPosition &IRP) | 
|  | 5375 | : AAPrivatizablePtrFloating(IRP) {} | 
|  | 5376 |  | 
|  | 5377 | /// See AbstractAttribute::initialize(...). | 
|  | 5378 | void initialize(Attributor &A) override { | 
|  | 5379 | if (getIRPosition().hasAttr(Attribute::ByVal)) | 
|  | 5380 | indicateOptimisticFixpoint(); | 
|  | 5381 | } | 
|  | 5382 |  | 
|  | 5383 | /// See AbstractAttribute::updateImpl(...). | 
|  | 5384 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 5385 | PrivatizableType = identifyPrivatizableType(A); | 
|  | 5386 | if (!PrivatizableType.hasValue()) | 
|  | 5387 | return ChangeStatus::UNCHANGED; | 
|  | 5388 | if (!PrivatizableType.getValue()) | 
|  | 5389 | return indicatePessimisticFixpoint(); | 
|  | 5390 |  | 
|  | 5391 | const IRPosition &IRP = getIRPosition(); | 
|  | 5392 | auto &NoCaptureAA = A.getAAFor<AANoCapture>(*this, IRP); | 
|  | 5393 | if (!NoCaptureAA.isAssumedNoCapture()) { | 
|  | 5394 | LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might be captured!\n"); | 
|  | 5395 | return indicatePessimisticFixpoint(); | 
|  | 5396 | } | 
|  | 5397 |  | 
|  | 5398 | auto &NoAliasAA = A.getAAFor<AANoAlias>(*this, IRP); | 
|  | 5399 | if (!NoAliasAA.isAssumedNoAlias()) { | 
|  | 5400 | LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might alias!\n"); | 
|  | 5401 | return indicatePessimisticFixpoint(); | 
|  | 5402 | } | 
|  | 5403 |  | 
|  | 5404 | const auto &MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(*this, IRP); | 
|  | 5405 | if (!MemBehaviorAA.isAssumedReadOnly()) { | 
|  | 5406 | LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer is written!\n"); | 
|  | 5407 | return indicatePessimisticFixpoint(); | 
|  | 5408 | } | 
|  | 5409 |  | 
|  | 5410 | return ChangeStatus::UNCHANGED; | 
|  | 5411 | } | 
|  | 5412 |  | 
|  | 5413 | /// See AbstractAttribute::trackStatistics() | 
|  | 5414 | void trackStatistics() const override { | 
|  | 5415 | STATS_DECLTRACK_CSARG_ATTR(privatizable_ptr); | 
|  | 5416 | } | 
|  | 5417 | }; | 
|  | 5418 |  | 
|  | 5419 | struct AAPrivatizablePtrCallSiteReturned final | 
|  | 5420 | : public AAPrivatizablePtrFloating { | 
|  | 5421 | AAPrivatizablePtrCallSiteReturned(const IRPosition &IRP) | 
|  | 5422 | : AAPrivatizablePtrFloating(IRP) {} | 
|  | 5423 |  | 
|  | 5424 | /// See AbstractAttribute::initialize(...). | 
|  | 5425 | void initialize(Attributor &A) override { | 
|  | 5426 | // TODO: We can privatize more than arguments. | 
|  | 5427 | indicatePessimisticFixpoint(); | 
|  | 5428 | } | 
|  | 5429 |  | 
|  | 5430 | /// See AbstractAttribute::trackStatistics() | 
|  | 5431 | void trackStatistics() const override { | 
|  | 5432 | STATS_DECLTRACK_CSRET_ATTR(privatizable_ptr); | 
|  | 5433 | } | 
|  | 5434 | }; | 
|  | 5435 |  | 
|  | 5436 | struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating { | 
|  | 5437 | AAPrivatizablePtrReturned(const IRPosition &IRP) | 
|  | 5438 | : AAPrivatizablePtrFloating(IRP) {} | 
|  | 5439 |  | 
|  | 5440 | /// See AbstractAttribute::initialize(...). | 
|  | 5441 | void initialize(Attributor &A) override { | 
|  | 5442 | // TODO: We can privatize more than arguments. | 
|  | 5443 | indicatePessimisticFixpoint(); | 
|  | 5444 | } | 
|  | 5445 |  | 
|  | 5446 | /// See AbstractAttribute::trackStatistics() | 
|  | 5447 | void trackStatistics() const override { | 
|  | 5448 | STATS_DECLTRACK_FNRET_ATTR(privatizable_ptr); | 
|  | 5449 | } | 
|  | 5450 | }; | 
|  | 5451 |  | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5452 | /// -------------------- Memory Behavior Attributes ---------------------------- | 
|  | 5453 | /// Includes read-none, read-only, and write-only. | 
|  | 5454 | /// ---------------------------------------------------------------------------- | 
|  | 5455 | struct AAMemoryBehaviorImpl : public AAMemoryBehavior { | 
|  | 5456 | AAMemoryBehaviorImpl(const IRPosition &IRP) : AAMemoryBehavior(IRP) {} | 
|  | 5457 |  | 
|  | 5458 | /// See AbstractAttribute::initialize(...). | 
|  | 5459 | void initialize(Attributor &A) override { | 
|  | 5460 | intersectAssumedBits(BEST_STATE); | 
|  | 5461 | getKnownStateFromValue(getIRPosition(), getState()); | 
|  | 5462 | IRAttribute::initialize(A); | 
|  | 5463 | } | 
|  | 5464 |  | 
|  | 5465 | /// Return the memory behavior information encoded in the IR for \p IRP. | 
|  | 5466 | static void getKnownStateFromValue(const IRPosition &IRP, | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 5467 | BitIntegerState &State, | 
|  | 5468 | bool IgnoreSubsumingPositions = false) { | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5469 | SmallVector<Attribute, 2> Attrs; | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 5470 | IRP.getAttrs(AttrKinds, Attrs, IgnoreSubsumingPositions); | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5471 | for (const Attribute &Attr : Attrs) { | 
|  | 5472 | switch (Attr.getKindAsEnum()) { | 
|  | 5473 | case Attribute::ReadNone: | 
|  | 5474 | State.addKnownBits(NO_ACCESSES); | 
|  | 5475 | break; | 
|  | 5476 | case Attribute::ReadOnly: | 
|  | 5477 | State.addKnownBits(NO_WRITES); | 
|  | 5478 | break; | 
|  | 5479 | case Attribute::WriteOnly: | 
|  | 5480 | State.addKnownBits(NO_READS); | 
|  | 5481 | break; | 
|  | 5482 | default: | 
|  | 5483 | llvm_unreachable("Unexpcted attribute!"); | 
|  | 5484 | } | 
|  | 5485 | } | 
|  | 5486 |  | 
|  | 5487 | if (auto *I = dyn_cast<Instruction>(&IRP.getAnchorValue())) { | 
|  | 5488 | if (!I->mayReadFromMemory()) | 
|  | 5489 | State.addKnownBits(NO_READS); | 
|  | 5490 | if (!I->mayWriteToMemory()) | 
|  | 5491 | State.addKnownBits(NO_WRITES); | 
|  | 5492 | } | 
|  | 5493 | } | 
|  | 5494 |  | 
|  | 5495 | /// See AbstractAttribute::getDeducedAttributes(...). | 
|  | 5496 | void getDeducedAttributes(LLVMContext &Ctx, | 
|  | 5497 | SmallVectorImpl<Attribute> &Attrs) const override { | 
|  | 5498 | assert(Attrs.size() == 0); | 
|  | 5499 | if (isAssumedReadNone()) | 
|  | 5500 | Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone)); | 
|  | 5501 | else if (isAssumedReadOnly()) | 
|  | 5502 | Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly)); | 
|  | 5503 | else if (isAssumedWriteOnly()) | 
|  | 5504 | Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly)); | 
|  | 5505 | assert(Attrs.size() <= 1); | 
|  | 5506 | } | 
|  | 5507 |  | 
|  | 5508 | /// See AbstractAttribute::manifest(...). | 
|  | 5509 | ChangeStatus manifest(Attributor &A) override { | 
| Johannes Doerfert | b2083c5 | 2019-10-20 22:46:48 -0500 | [diff] [blame] | 5510 | const IRPosition &IRP = getIRPosition(); | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5511 |  | 
|  | 5512 | // Check if we would improve the existing attributes first. | 
|  | 5513 | SmallVector<Attribute, 4> DeducedAttrs; | 
|  | 5514 | getDeducedAttributes(IRP.getAnchorValue().getContext(), DeducedAttrs); | 
|  | 5515 | if (llvm::all_of(DeducedAttrs, [&](const Attribute &Attr) { | 
|  | 5516 | return IRP.hasAttr(Attr.getKindAsEnum(), | 
|  | 5517 | /* IgnoreSubsumingPositions */ true); | 
|  | 5518 | })) | 
|  | 5519 | return ChangeStatus::UNCHANGED; | 
|  | 5520 |  | 
|  | 5521 | // Clear existing attributes. | 
|  | 5522 | IRP.removeAttrs(AttrKinds); | 
|  | 5523 |  | 
|  | 5524 | // Use the generic manifest method. | 
|  | 5525 | return IRAttribute::manifest(A); | 
|  | 5526 | } | 
|  | 5527 |  | 
|  | 5528 | /// See AbstractState::getAsStr(). | 
|  | 5529 | const std::string getAsStr() const override { | 
|  | 5530 | if (isAssumedReadNone()) | 
|  | 5531 | return "readnone"; | 
|  | 5532 | if (isAssumedReadOnly()) | 
|  | 5533 | return "readonly"; | 
|  | 5534 | if (isAssumedWriteOnly()) | 
|  | 5535 | return "writeonly"; | 
|  | 5536 | return "may-read/write"; | 
|  | 5537 | } | 
|  | 5538 |  | 
|  | 5539 | /// The set of IR attributes AAMemoryBehavior deals with. | 
|  | 5540 | static const Attribute::AttrKind AttrKinds[3]; | 
|  | 5541 | }; | 
|  | 5542 |  | 
|  | 5543 | const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = { | 
|  | 5544 | Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly}; | 
|  | 5545 |  | 
|  | 5546 | /// Memory behavior attribute for a floating value. | 
|  | 5547 | struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl { | 
|  | 5548 | AAMemoryBehaviorFloating(const IRPosition &IRP) : AAMemoryBehaviorImpl(IRP) {} | 
|  | 5549 |  | 
|  | 5550 | /// See AbstractAttribute::initialize(...). | 
|  | 5551 | void initialize(Attributor &A) override { | 
|  | 5552 | AAMemoryBehaviorImpl::initialize(A); | 
|  | 5553 | // Initialize the use vector with all direct uses of the associated value. | 
|  | 5554 | for (const Use &U : getAssociatedValue().uses()) | 
|  | 5555 | Uses.insert(&U); | 
|  | 5556 | } | 
|  | 5557 |  | 
|  | 5558 | /// See AbstractAttribute::updateImpl(...). | 
|  | 5559 | ChangeStatus updateImpl(Attributor &A) override; | 
|  | 5560 |  | 
|  | 5561 | /// See AbstractAttribute::trackStatistics() | 
|  | 5562 | void trackStatistics() const override { | 
|  | 5563 | if (isAssumedReadNone()) | 
|  | 5564 | STATS_DECLTRACK_FLOATING_ATTR(readnone) | 
|  | 5565 | else if (isAssumedReadOnly()) | 
|  | 5566 | STATS_DECLTRACK_FLOATING_ATTR(readonly) | 
|  | 5567 | else if (isAssumedWriteOnly()) | 
|  | 5568 | STATS_DECLTRACK_FLOATING_ATTR(writeonly) | 
|  | 5569 | } | 
|  | 5570 |  | 
|  | 5571 | private: | 
|  | 5572 | /// Return true if users of \p UserI might access the underlying | 
|  | 5573 | /// variable/location described by \p U and should therefore be analyzed. | 
|  | 5574 | bool followUsersOfUseIn(Attributor &A, const Use *U, | 
|  | 5575 | const Instruction *UserI); | 
|  | 5576 |  | 
|  | 5577 | /// Update the state according to the effect of use \p U in \p UserI. | 
|  | 5578 | void analyzeUseIn(Attributor &A, const Use *U, const Instruction *UserI); | 
|  | 5579 |  | 
|  | 5580 | protected: | 
|  | 5581 | /// Container for (transitive) uses of the associated argument. | 
|  | 5582 | SetVector<const Use *> Uses; | 
|  | 5583 | }; | 
|  | 5584 |  | 
|  | 5585 | /// Memory behavior attribute for function argument. | 
|  | 5586 | struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating { | 
|  | 5587 | AAMemoryBehaviorArgument(const IRPosition &IRP) | 
|  | 5588 | : AAMemoryBehaviorFloating(IRP) {} | 
|  | 5589 |  | 
|  | 5590 | /// See AbstractAttribute::initialize(...). | 
|  | 5591 | void initialize(Attributor &A) override { | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 5592 | intersectAssumedBits(BEST_STATE); | 
|  | 5593 | const IRPosition &IRP = getIRPosition(); | 
|  | 5594 | // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we | 
|  | 5595 | // can query it when we use has/getAttr. That would allow us to reuse the | 
|  | 5596 | // initialize of the base class here. | 
|  | 5597 | bool HasByVal = | 
|  | 5598 | IRP.hasAttr({Attribute::ByVal}, /* IgnoreSubsumingPositions */ true); | 
|  | 5599 | getKnownStateFromValue(IRP, getState(), | 
|  | 5600 | /* IgnoreSubsumingPositions */ HasByVal); | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5601 |  | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5602 | // Initialize the use vector with all direct uses of the associated value. | 
|  | 5603 | Argument *Arg = getAssociatedArgument(); | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 5604 | if (!Arg || !Arg->getParent()->hasExactDefinition()) { | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5605 | indicatePessimisticFixpoint(); | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 5606 | } else { | 
|  | 5607 | // Initialize the use vector with all direct uses of the associated value. | 
|  | 5608 | for (const Use &U : Arg->uses()) | 
|  | 5609 | Uses.insert(&U); | 
|  | 5610 | } | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5611 | } | 
|  | 5612 |  | 
| Johannes Doerfert | 8ee410c | 2019-10-13 20:47:16 +0000 | [diff] [blame] | 5613 | ChangeStatus manifest(Attributor &A) override { | 
|  | 5614 | // TODO: From readattrs.ll: "inalloca parameters are always | 
|  | 5615 | //                           considered written" | 
|  | 5616 | if (hasAttr({Attribute::InAlloca})) { | 
|  | 5617 | removeKnownBits(NO_WRITES); | 
|  | 5618 | removeAssumedBits(NO_WRITES); | 
|  | 5619 | } | 
|  | 5620 | return AAMemoryBehaviorFloating::manifest(A); | 
|  | 5621 | } | 
|  | 5622 |  | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5623 | /// See AbstractAttribute::trackStatistics() | 
|  | 5624 | void trackStatistics() const override { | 
|  | 5625 | if (isAssumedReadNone()) | 
|  | 5626 | STATS_DECLTRACK_ARG_ATTR(readnone) | 
|  | 5627 | else if (isAssumedReadOnly()) | 
|  | 5628 | STATS_DECLTRACK_ARG_ATTR(readonly) | 
|  | 5629 | else if (isAssumedWriteOnly()) | 
|  | 5630 | STATS_DECLTRACK_ARG_ATTR(writeonly) | 
|  | 5631 | } | 
|  | 5632 | }; | 
|  | 5633 |  | 
|  | 5634 | struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument { | 
|  | 5635 | AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP) | 
|  | 5636 | : AAMemoryBehaviorArgument(IRP) {} | 
|  | 5637 |  | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 5638 | /// See AbstractAttribute::initialize(...). | 
|  | 5639 | void initialize(Attributor &A) override { | 
|  | 5640 | if (Argument *Arg = getAssociatedArgument()) { | 
|  | 5641 | if (Arg->hasByValAttr()) { | 
|  | 5642 | addKnownBits(NO_WRITES); | 
|  | 5643 | removeKnownBits(NO_READS); | 
|  | 5644 | removeAssumedBits(NO_READS); | 
|  | 5645 | } | 
|  | 5646 | } else { | 
|  | 5647 | } | 
|  | 5648 | AAMemoryBehaviorArgument::initialize(A); | 
|  | 5649 | } | 
|  | 5650 |  | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5651 | /// See AbstractAttribute::updateImpl(...). | 
|  | 5652 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 5653 | // TODO: Once we have call site specific value information we can provide | 
|  | 5654 | //       call site specific liveness liveness information and then it makes | 
|  | 5655 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 5656 | //       redirecting requests to the callee argument. | 
|  | 5657 | Argument *Arg = getAssociatedArgument(); | 
|  | 5658 | const IRPosition &ArgPos = IRPosition::argument(*Arg); | 
|  | 5659 | auto &ArgAA = A.getAAFor<AAMemoryBehavior>(*this, ArgPos); | 
|  | 5660 | return clampStateAndIndicateChange( | 
|  | 5661 | getState(), | 
| Johannes Doerfert | 3178424 | 2019-10-29 23:18:49 -0500 | [diff] [blame] | 5662 | static_cast<const AAMemoryBehavior::StateType &>(ArgAA.getState())); | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5663 | } | 
|  | 5664 |  | 
|  | 5665 | /// See AbstractAttribute::trackStatistics() | 
|  | 5666 | void trackStatistics() const override { | 
|  | 5667 | if (isAssumedReadNone()) | 
|  | 5668 | STATS_DECLTRACK_CSARG_ATTR(readnone) | 
|  | 5669 | else if (isAssumedReadOnly()) | 
|  | 5670 | STATS_DECLTRACK_CSARG_ATTR(readonly) | 
|  | 5671 | else if (isAssumedWriteOnly()) | 
|  | 5672 | STATS_DECLTRACK_CSARG_ATTR(writeonly) | 
|  | 5673 | } | 
|  | 5674 | }; | 
|  | 5675 |  | 
|  | 5676 | /// Memory behavior attribute for a call site return position. | 
|  | 5677 | struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating { | 
|  | 5678 | AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP) | 
|  | 5679 | : AAMemoryBehaviorFloating(IRP) {} | 
|  | 5680 |  | 
|  | 5681 | /// See AbstractAttribute::manifest(...). | 
|  | 5682 | ChangeStatus manifest(Attributor &A) override { | 
|  | 5683 | // We do not annotate returned values. | 
|  | 5684 | return ChangeStatus::UNCHANGED; | 
|  | 5685 | } | 
|  | 5686 |  | 
|  | 5687 | /// See AbstractAttribute::trackStatistics() | 
|  | 5688 | void trackStatistics() const override {} | 
|  | 5689 | }; | 
|  | 5690 |  | 
|  | 5691 | /// An AA to represent the memory behavior function attributes. | 
|  | 5692 | struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl { | 
|  | 5693 | AAMemoryBehaviorFunction(const IRPosition &IRP) : AAMemoryBehaviorImpl(IRP) {} | 
|  | 5694 |  | 
|  | 5695 | /// See AbstractAttribute::updateImpl(Attributor &A). | 
|  | 5696 | virtual ChangeStatus updateImpl(Attributor &A) override; | 
|  | 5697 |  | 
|  | 5698 | /// See AbstractAttribute::manifest(...). | 
|  | 5699 | ChangeStatus manifest(Attributor &A) override { | 
|  | 5700 | Function &F = cast<Function>(getAnchorValue()); | 
|  | 5701 | if (isAssumedReadNone()) { | 
|  | 5702 | F.removeFnAttr(Attribute::ArgMemOnly); | 
|  | 5703 | F.removeFnAttr(Attribute::InaccessibleMemOnly); | 
|  | 5704 | F.removeFnAttr(Attribute::InaccessibleMemOrArgMemOnly); | 
|  | 5705 | } | 
|  | 5706 | return AAMemoryBehaviorImpl::manifest(A); | 
|  | 5707 | } | 
|  | 5708 |  | 
|  | 5709 | /// See AbstractAttribute::trackStatistics() | 
|  | 5710 | void trackStatistics() const override { | 
|  | 5711 | if (isAssumedReadNone()) | 
|  | 5712 | STATS_DECLTRACK_FN_ATTR(readnone) | 
|  | 5713 | else if (isAssumedReadOnly()) | 
|  | 5714 | STATS_DECLTRACK_FN_ATTR(readonly) | 
|  | 5715 | else if (isAssumedWriteOnly()) | 
|  | 5716 | STATS_DECLTRACK_FN_ATTR(writeonly) | 
|  | 5717 | } | 
|  | 5718 | }; | 
|  | 5719 |  | 
|  | 5720 | /// AAMemoryBehavior attribute for call sites. | 
|  | 5721 | struct AAMemoryBehaviorCallSite final : AAMemoryBehaviorImpl { | 
|  | 5722 | AAMemoryBehaviorCallSite(const IRPosition &IRP) : AAMemoryBehaviorImpl(IRP) {} | 
|  | 5723 |  | 
|  | 5724 | /// See AbstractAttribute::initialize(...). | 
|  | 5725 | void initialize(Attributor &A) override { | 
|  | 5726 | AAMemoryBehaviorImpl::initialize(A); | 
|  | 5727 | Function *F = getAssociatedFunction(); | 
|  | 5728 | if (!F || !F->hasExactDefinition()) | 
|  | 5729 | indicatePessimisticFixpoint(); | 
|  | 5730 | } | 
|  | 5731 |  | 
|  | 5732 | /// See AbstractAttribute::updateImpl(...). | 
|  | 5733 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 5734 | // TODO: Once we have call site specific value information we can provide | 
|  | 5735 | //       call site specific liveness liveness information and then it makes | 
|  | 5736 | //       sense to specialize attributes for call sites arguments instead of | 
|  | 5737 | //       redirecting requests to the callee argument. | 
|  | 5738 | Function *F = getAssociatedFunction(); | 
|  | 5739 | const IRPosition &FnPos = IRPosition::function(*F); | 
|  | 5740 | auto &FnAA = A.getAAFor<AAMemoryBehavior>(*this, FnPos); | 
|  | 5741 | return clampStateAndIndicateChange( | 
| Johannes Doerfert | 1a74645 | 2019-10-20 22:28:49 -0500 | [diff] [blame] | 5742 | getState(), | 
|  | 5743 | static_cast<const AAMemoryBehavior::StateType &>(FnAA.getState())); | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5744 | } | 
|  | 5745 |  | 
|  | 5746 | /// See AbstractAttribute::trackStatistics() | 
|  | 5747 | void trackStatistics() const override { | 
|  | 5748 | if (isAssumedReadNone()) | 
|  | 5749 | STATS_DECLTRACK_CS_ATTR(readnone) | 
|  | 5750 | else if (isAssumedReadOnly()) | 
|  | 5751 | STATS_DECLTRACK_CS_ATTR(readonly) | 
|  | 5752 | else if (isAssumedWriteOnly()) | 
|  | 5753 | STATS_DECLTRACK_CS_ATTR(writeonly) | 
|  | 5754 | } | 
|  | 5755 | }; | 
| Benjamin Kramer | c5d1d56 | 2019-10-12 11:01:52 +0000 | [diff] [blame] | 5756 | } // namespace | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5757 |  | 
|  | 5758 | ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) { | 
|  | 5759 |  | 
|  | 5760 | // The current assumed state used to determine a change. | 
|  | 5761 | auto AssumedState = getAssumed(); | 
|  | 5762 |  | 
|  | 5763 | auto CheckRWInst = [&](Instruction &I) { | 
|  | 5764 | // If the instruction has an own memory behavior state, use it to restrict | 
|  | 5765 | // the local state. No further analysis is required as the other memory | 
|  | 5766 | // state is as optimistic as it gets. | 
|  | 5767 | if (ImmutableCallSite ICS = ImmutableCallSite(&I)) { | 
|  | 5768 | const auto &MemBehaviorAA = A.getAAFor<AAMemoryBehavior>( | 
|  | 5769 | *this, IRPosition::callsite_function(ICS)); | 
|  | 5770 | intersectAssumedBits(MemBehaviorAA.getAssumed()); | 
|  | 5771 | return !isAtFixpoint(); | 
|  | 5772 | } | 
|  | 5773 |  | 
|  | 5774 | // Remove access kind modifiers if necessary. | 
|  | 5775 | if (I.mayReadFromMemory()) | 
|  | 5776 | removeAssumedBits(NO_READS); | 
|  | 5777 | if (I.mayWriteToMemory()) | 
|  | 5778 | removeAssumedBits(NO_WRITES); | 
|  | 5779 | return !isAtFixpoint(); | 
|  | 5780 | }; | 
|  | 5781 |  | 
|  | 5782 | if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this)) | 
|  | 5783 | return indicatePessimisticFixpoint(); | 
|  | 5784 |  | 
|  | 5785 | return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED | 
|  | 5786 | : ChangeStatus::UNCHANGED; | 
|  | 5787 | } | 
|  | 5788 |  | 
|  | 5789 | ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) { | 
|  | 5790 |  | 
|  | 5791 | const IRPosition &IRP = getIRPosition(); | 
|  | 5792 | const IRPosition &FnPos = IRPosition::function_scope(IRP); | 
|  | 5793 | AAMemoryBehavior::StateType &S = getState(); | 
|  | 5794 |  | 
|  | 5795 | // First, check the function scope. We take the known information and we avoid | 
|  | 5796 | // work if the assumed information implies the current assumed information for | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 5797 | // this attribute. This is a valid for all but byval arguments. | 
|  | 5798 | Argument *Arg = IRP.getAssociatedArgument(); | 
|  | 5799 | AAMemoryBehavior::base_t FnMemAssumedState = | 
|  | 5800 | AAMemoryBehavior::StateType::getWorstState(); | 
|  | 5801 | if (!Arg || !Arg->hasByValAttr()) { | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 5802 | const auto &FnMemAA = A.getAAFor<AAMemoryBehavior>( | 
|  | 5803 | *this, FnPos, /* TrackDependence */ true, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 5804 | FnMemAssumedState = FnMemAA.getAssumed(); | 
|  | 5805 | S.addKnownBits(FnMemAA.getKnown()); | 
|  | 5806 | if ((S.getAssumed() & FnMemAA.getAssumed()) == S.getAssumed()) | 
|  | 5807 | return ChangeStatus::UNCHANGED; | 
|  | 5808 | } | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5809 |  | 
|  | 5810 | // Make sure the value is not captured (except through "return"), if | 
|  | 5811 | // it is, any information derived would be irrelevant anyway as we cannot | 
| Johannes Doerfert | 8ee410c | 2019-10-13 20:47:16 +0000 | [diff] [blame] | 5812 | // check the potential aliases introduced by the capture. However, no need | 
|  | 5813 | // to fall back to anythign less optimistic than the function state. | 
| Johannes Doerfert | 2888019 | 2019-12-31 00:57:00 -0600 | [diff] [blame] | 5814 | const auto &ArgNoCaptureAA = A.getAAFor<AANoCapture>( | 
|  | 5815 | *this, IRP, /* TrackDependence */ true, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 8ee410c | 2019-10-13 20:47:16 +0000 | [diff] [blame] | 5816 | if (!ArgNoCaptureAA.isAssumedNoCaptureMaybeReturned()) { | 
| Johannes Doerfert | 6abd01e | 2019-12-12 15:02:36 -0600 | [diff] [blame] | 5817 | S.intersectAssumedBits(FnMemAssumedState); | 
| Johannes Doerfert | 8ee410c | 2019-10-13 20:47:16 +0000 | [diff] [blame] | 5818 | return ChangeStatus::CHANGED; | 
|  | 5819 | } | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5820 |  | 
|  | 5821 | // The current assumed state used to determine a change. | 
|  | 5822 | auto AssumedState = S.getAssumed(); | 
|  | 5823 |  | 
|  | 5824 | // Liveness information to exclude dead users. | 
|  | 5825 | // TODO: Take the FnPos once we have call site specific liveness information. | 
|  | 5826 | const auto &LivenessAA = A.getAAFor<AAIsDead>( | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 5827 | *this, IRPosition::function(*IRP.getAssociatedFunction()), | 
|  | 5828 | /* TrackDependence */ false); | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5829 |  | 
|  | 5830 | // Visit and expand uses until all are analyzed or a fixpoint is reached. | 
|  | 5831 | for (unsigned i = 0; i < Uses.size() && !isAtFixpoint(); i++) { | 
|  | 5832 | const Use *U = Uses[i]; | 
|  | 5833 | Instruction *UserI = cast<Instruction>(U->getUser()); | 
|  | 5834 | LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << **U << " in " << *UserI | 
|  | 5835 | << " [Dead: " << (LivenessAA.isAssumedDead(UserI)) | 
|  | 5836 | << "]\n"); | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 5837 | if (LivenessAA.isAssumedDead(UserI)) { | 
|  | 5838 | A.recordDependence(LivenessAA, *this, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5839 | continue; | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 5840 | } | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5841 |  | 
|  | 5842 | // Check if the users of UserI should also be visited. | 
|  | 5843 | if (followUsersOfUseIn(A, U, UserI)) | 
|  | 5844 | for (const Use &UserIUse : UserI->uses()) | 
|  | 5845 | Uses.insert(&UserIUse); | 
|  | 5846 |  | 
|  | 5847 | // If UserI might touch memory we analyze the use in detail. | 
|  | 5848 | if (UserI->mayReadOrWriteMemory()) | 
|  | 5849 | analyzeUseIn(A, U, UserI); | 
|  | 5850 | } | 
|  | 5851 |  | 
|  | 5852 | return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED | 
|  | 5853 | : ChangeStatus::UNCHANGED; | 
|  | 5854 | } | 
|  | 5855 |  | 
|  | 5856 | bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use *U, | 
|  | 5857 | const Instruction *UserI) { | 
|  | 5858 | // The loaded value is unrelated to the pointer argument, no need to | 
|  | 5859 | // follow the users of the load. | 
|  | 5860 | if (isa<LoadInst>(UserI)) | 
|  | 5861 | return false; | 
|  | 5862 |  | 
|  | 5863 | // By default we follow all uses assuming UserI might leak information on U, | 
|  | 5864 | // we have special handling for call sites operands though. | 
|  | 5865 | ImmutableCallSite ICS(UserI); | 
|  | 5866 | if (!ICS || !ICS.isArgOperand(U)) | 
|  | 5867 | return true; | 
|  | 5868 |  | 
|  | 5869 | // If the use is a call argument known not to be captured, the users of | 
|  | 5870 | // the call do not need to be visited because they have to be unrelated to | 
|  | 5871 | // the input. Note that this check is not trivial even though we disallow | 
|  | 5872 | // general capturing of the underlying argument. The reason is that the | 
|  | 5873 | // call might the argument "through return", which we allow and for which we | 
|  | 5874 | // need to check call users. | 
| Johannes Doerfert | ff6254d | 2020-01-10 12:32:24 -0600 | [diff] [blame] | 5875 | if (U->get()->getType()->isPointerTy()) { | 
|  | 5876 | unsigned ArgNo = ICS.getArgumentNo(U); | 
|  | 5877 | const auto &ArgNoCaptureAA = A.getAAFor<AANoCapture>( | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 5878 | *this, IRPosition::callsite_argument(ICS, ArgNo), | 
|  | 5879 | /* TrackDependence */ true, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | ff6254d | 2020-01-10 12:32:24 -0600 | [diff] [blame] | 5880 | return !ArgNoCaptureAA.isAssumedNoCapture(); | 
|  | 5881 | } | 
|  | 5882 |  | 
|  | 5883 | return true; | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5884 | } | 
|  | 5885 |  | 
|  | 5886 | void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use *U, | 
|  | 5887 | const Instruction *UserI) { | 
|  | 5888 | assert(UserI->mayReadOrWriteMemory()); | 
|  | 5889 |  | 
|  | 5890 | switch (UserI->getOpcode()) { | 
|  | 5891 | default: | 
|  | 5892 | // TODO: Handle all atomics and other side-effect operations we know of. | 
|  | 5893 | break; | 
|  | 5894 | case Instruction::Load: | 
|  | 5895 | // Loads cause the NO_READS property to disappear. | 
|  | 5896 | removeAssumedBits(NO_READS); | 
|  | 5897 | return; | 
|  | 5898 |  | 
|  | 5899 | case Instruction::Store: | 
|  | 5900 | // Stores cause the NO_WRITES property to disappear if the use is the | 
|  | 5901 | // pointer operand. Note that we do assume that capturing was taken care of | 
|  | 5902 | // somewhere else. | 
|  | 5903 | if (cast<StoreInst>(UserI)->getPointerOperand() == U->get()) | 
|  | 5904 | removeAssumedBits(NO_WRITES); | 
|  | 5905 | return; | 
|  | 5906 |  | 
|  | 5907 | case Instruction::Call: | 
|  | 5908 | case Instruction::CallBr: | 
|  | 5909 | case Instruction::Invoke: { | 
|  | 5910 | // For call sites we look at the argument memory behavior attribute (this | 
|  | 5911 | // could be recursive!) in order to restrict our own state. | 
|  | 5912 | ImmutableCallSite ICS(UserI); | 
|  | 5913 |  | 
|  | 5914 | // Give up on operand bundles. | 
|  | 5915 | if (ICS.isBundleOperand(U)) { | 
|  | 5916 | indicatePessimisticFixpoint(); | 
|  | 5917 | return; | 
|  | 5918 | } | 
|  | 5919 |  | 
|  | 5920 | // Calling a function does read the function pointer, maybe write it if the | 
|  | 5921 | // function is self-modifying. | 
|  | 5922 | if (ICS.isCallee(U)) { | 
|  | 5923 | removeAssumedBits(NO_READS); | 
|  | 5924 | break; | 
|  | 5925 | } | 
|  | 5926 |  | 
|  | 5927 | // Adjust the possible access behavior based on the information on the | 
|  | 5928 | // argument. | 
| Johannes Doerfert | ff6254d | 2020-01-10 12:32:24 -0600 | [diff] [blame] | 5929 | IRPosition Pos; | 
|  | 5930 | if (U->get()->getType()->isPointerTy()) | 
|  | 5931 | Pos = IRPosition::callsite_argument(ICS, ICS.getArgumentNo(U)); | 
|  | 5932 | else | 
|  | 5933 | Pos = IRPosition::callsite_function(ICS); | 
| Johannes Doerfert | 7ad17e0 | 2020-01-12 00:11:56 -0600 | [diff] [blame] | 5934 | const auto &MemBehaviorAA = A.getAAFor<AAMemoryBehavior>( | 
|  | 5935 | *this, Pos, | 
|  | 5936 | /* TrackDependence */ true, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 5937 | // "assumed" has at most the same bits as the MemBehaviorAA assumed | 
|  | 5938 | // and at least "known". | 
|  | 5939 | intersectAssumedBits(MemBehaviorAA.getAssumed()); | 
|  | 5940 | return; | 
|  | 5941 | } | 
|  | 5942 | }; | 
|  | 5943 |  | 
|  | 5944 | // Generally, look at the "may-properties" and adjust the assumed state if we | 
|  | 5945 | // did not trigger special handling before. | 
|  | 5946 | if (UserI->mayReadFromMemory()) | 
|  | 5947 | removeAssumedBits(NO_READS); | 
|  | 5948 | if (UserI->mayWriteToMemory()) | 
|  | 5949 | removeAssumedBits(NO_WRITES); | 
|  | 5950 | } | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 5951 | /// ------------------ Value Constant Range Attribute ------------------------- | 
| Hideto Ueno | e996303 | 2020-01-01 15:25:19 +0900 | [diff] [blame] | 5952 |  | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 5953 | struct AAValueConstantRangeImpl : AAValueConstantRange { | 
|  | 5954 | using StateType = IntegerRangeState; | 
|  | 5955 | AAValueConstantRangeImpl(const IRPosition &IRP) : AAValueConstantRange(IRP) {} | 
|  | 5956 |  | 
|  | 5957 | /// See AbstractAttribute::getAsStr(). | 
|  | 5958 | const std::string getAsStr() const override { | 
|  | 5959 | std::string Str; | 
|  | 5960 | llvm::raw_string_ostream OS(Str); | 
|  | 5961 | OS << "range(" << getBitWidth() << ")<"; | 
|  | 5962 | getKnown().print(OS); | 
|  | 5963 | OS << " / "; | 
|  | 5964 | getAssumed().print(OS); | 
|  | 5965 | OS << ">"; | 
|  | 5966 | return OS.str(); | 
|  | 5967 | } | 
|  | 5968 |  | 
|  | 5969 | /// Helper function to get a SCEV expr for the associated value at program | 
|  | 5970 | /// point \p I. | 
|  | 5971 | const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const { | 
|  | 5972 | if (!getAnchorScope()) | 
|  | 5973 | return nullptr; | 
|  | 5974 |  | 
|  | 5975 | ScalarEvolution *SE = | 
|  | 5976 | A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>( | 
|  | 5977 | *getAnchorScope()); | 
|  | 5978 |  | 
|  | 5979 | LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>( | 
|  | 5980 | *getAnchorScope()); | 
|  | 5981 |  | 
|  | 5982 | if (!SE || !LI) | 
|  | 5983 | return nullptr; | 
|  | 5984 |  | 
|  | 5985 | const SCEV *S = SE->getSCEV(&getAssociatedValue()); | 
|  | 5986 | if (!I) | 
|  | 5987 | return S; | 
|  | 5988 |  | 
|  | 5989 | return SE->getSCEVAtScope(S, LI->getLoopFor(I->getParent())); | 
|  | 5990 | } | 
|  | 5991 |  | 
|  | 5992 | /// Helper function to get a range from SCEV for the associated value at | 
|  | 5993 | /// program point \p I. | 
|  | 5994 | ConstantRange getConstantRangeFromSCEV(Attributor &A, | 
|  | 5995 | const Instruction *I = nullptr) const { | 
|  | 5996 | if (!getAnchorScope()) | 
|  | 5997 | return getWorstState(getBitWidth()); | 
|  | 5998 |  | 
|  | 5999 | ScalarEvolution *SE = | 
|  | 6000 | A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>( | 
|  | 6001 | *getAnchorScope()); | 
|  | 6002 |  | 
|  | 6003 | const SCEV *S = getSCEV(A, I); | 
|  | 6004 | if (!SE || !S) | 
|  | 6005 | return getWorstState(getBitWidth()); | 
|  | 6006 |  | 
|  | 6007 | return SE->getUnsignedRange(S); | 
|  | 6008 | } | 
|  | 6009 |  | 
|  | 6010 | /// Helper function to get a range from LVI for the associated value at | 
|  | 6011 | /// program point \p I. | 
|  | 6012 | ConstantRange | 
|  | 6013 | getConstantRangeFromLVI(Attributor &A, | 
|  | 6014 | const Instruction *CtxI = nullptr) const { | 
|  | 6015 | if (!getAnchorScope()) | 
|  | 6016 | return getWorstState(getBitWidth()); | 
|  | 6017 |  | 
|  | 6018 | LazyValueInfo *LVI = | 
|  | 6019 | A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>( | 
|  | 6020 | *getAnchorScope()); | 
|  | 6021 |  | 
|  | 6022 | if (!LVI || !CtxI) | 
|  | 6023 | return getWorstState(getBitWidth()); | 
|  | 6024 | return LVI->getConstantRange(&getAssociatedValue(), | 
|  | 6025 | const_cast<BasicBlock *>(CtxI->getParent()), | 
|  | 6026 | const_cast<Instruction *>(CtxI)); | 
|  | 6027 | } | 
|  | 6028 |  | 
|  | 6029 | /// See AAValueConstantRange::getKnownConstantRange(..). | 
|  | 6030 | ConstantRange | 
|  | 6031 | getKnownConstantRange(Attributor &A, | 
|  | 6032 | const Instruction *CtxI = nullptr) const override { | 
|  | 6033 | if (!CtxI || CtxI == getCtxI()) | 
|  | 6034 | return getKnown(); | 
|  | 6035 |  | 
|  | 6036 | ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI); | 
|  | 6037 | ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI); | 
|  | 6038 | return getKnown().intersectWith(SCEVR).intersectWith(LVIR); | 
|  | 6039 | } | 
|  | 6040 |  | 
|  | 6041 | /// See AAValueConstantRange::getAssumedConstantRange(..). | 
|  | 6042 | ConstantRange | 
|  | 6043 | getAssumedConstantRange(Attributor &A, | 
|  | 6044 | const Instruction *CtxI = nullptr) const override { | 
|  | 6045 | // TODO: Make SCEV use Attributor assumption. | 
|  | 6046 | //       We may be able to bound a variable range via assumptions in | 
|  | 6047 | //       Attributor. ex.) If x is assumed to be in [1, 3] and y is known to | 
|  | 6048 | //       evolve to x^2 + x, then we can say that y is in [2, 12]. | 
|  | 6049 |  | 
|  | 6050 | if (!CtxI || CtxI == getCtxI()) | 
|  | 6051 | return getAssumed(); | 
|  | 6052 |  | 
|  | 6053 | ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI); | 
|  | 6054 | ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI); | 
|  | 6055 | return getAssumed().intersectWith(SCEVR).intersectWith(LVIR); | 
|  | 6056 | } | 
|  | 6057 |  | 
|  | 6058 | /// See AbstractAttribute::initialize(..). | 
|  | 6059 | void initialize(Attributor &A) override { | 
|  | 6060 | // Intersect a range given by SCEV. | 
|  | 6061 | intersectKnown(getConstantRangeFromSCEV(A, getCtxI())); | 
|  | 6062 |  | 
|  | 6063 | // Intersect a range given by LVI. | 
|  | 6064 | intersectKnown(getConstantRangeFromLVI(A, getCtxI())); | 
|  | 6065 | } | 
|  | 6066 |  | 
|  | 6067 | /// Helper function to create MDNode for range metadata. | 
|  | 6068 | static MDNode * | 
|  | 6069 | getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx, | 
|  | 6070 | const ConstantRange &AssumedConstantRange) { | 
|  | 6071 | Metadata *LowAndHigh[] = {ConstantAsMetadata::get(ConstantInt::get( | 
|  | 6072 | Ty, AssumedConstantRange.getLower())), | 
|  | 6073 | ConstantAsMetadata::get(ConstantInt::get( | 
|  | 6074 | Ty, AssumedConstantRange.getUpper()))}; | 
|  | 6075 | return MDNode::get(Ctx, LowAndHigh); | 
|  | 6076 | } | 
|  | 6077 |  | 
|  | 6078 | /// Return true if \p Assumed is included in \p KnownRanges. | 
|  | 6079 | static bool isBetterRange(const ConstantRange &Assumed, MDNode *KnownRanges) { | 
|  | 6080 |  | 
|  | 6081 | if (Assumed.isFullSet()) | 
|  | 6082 | return false; | 
|  | 6083 |  | 
|  | 6084 | if (!KnownRanges) | 
|  | 6085 | return true; | 
|  | 6086 |  | 
|  | 6087 | // If multiple ranges are annotated in IR, we give up to annotate assumed | 
|  | 6088 | // range for now. | 
|  | 6089 |  | 
|  | 6090 | // TODO:  If there exists a known range which containts assumed range, we | 
|  | 6091 | // can say assumed range is better. | 
|  | 6092 | if (KnownRanges->getNumOperands() > 2) | 
|  | 6093 | return false; | 
|  | 6094 |  | 
|  | 6095 | ConstantInt *Lower = | 
|  | 6096 | mdconst::extract<ConstantInt>(KnownRanges->getOperand(0)); | 
|  | 6097 | ConstantInt *Upper = | 
|  | 6098 | mdconst::extract<ConstantInt>(KnownRanges->getOperand(1)); | 
|  | 6099 |  | 
|  | 6100 | ConstantRange Known(Lower->getValue(), Upper->getValue()); | 
|  | 6101 | return Known.contains(Assumed) && Known != Assumed; | 
|  | 6102 | } | 
|  | 6103 |  | 
|  | 6104 | /// Helper function to set range metadata. | 
|  | 6105 | static bool | 
|  | 6106 | setRangeMetadataIfisBetterRange(Instruction *I, | 
|  | 6107 | const ConstantRange &AssumedConstantRange) { | 
|  | 6108 | auto *OldRangeMD = I->getMetadata(LLVMContext::MD_range); | 
|  | 6109 | if (isBetterRange(AssumedConstantRange, OldRangeMD)) { | 
|  | 6110 | if (!AssumedConstantRange.isEmptySet()) { | 
|  | 6111 | I->setMetadata(LLVMContext::MD_range, | 
|  | 6112 | getMDNodeForConstantRange(I->getType(), I->getContext(), | 
|  | 6113 | AssumedConstantRange)); | 
|  | 6114 | return true; | 
|  | 6115 | } | 
|  | 6116 | } | 
|  | 6117 | return false; | 
|  | 6118 | } | 
|  | 6119 |  | 
|  | 6120 | /// See AbstractAttribute::manifest() | 
|  | 6121 | ChangeStatus manifest(Attributor &A) override { | 
|  | 6122 | ChangeStatus Changed = ChangeStatus::UNCHANGED; | 
|  | 6123 | ConstantRange AssumedConstantRange = getAssumedConstantRange(A); | 
|  | 6124 | assert(!AssumedConstantRange.isFullSet() && "Invalid state"); | 
|  | 6125 |  | 
|  | 6126 | auto &V = getAssociatedValue(); | 
|  | 6127 | if (!AssumedConstantRange.isEmptySet() && | 
|  | 6128 | !AssumedConstantRange.isSingleElement()) { | 
|  | 6129 | if (Instruction *I = dyn_cast<Instruction>(&V)) | 
|  | 6130 | if (isa<CallInst>(I) || isa<LoadInst>(I)) | 
|  | 6131 | if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange)) | 
|  | 6132 | Changed = ChangeStatus::CHANGED; | 
|  | 6133 | } | 
|  | 6134 |  | 
|  | 6135 | return Changed; | 
|  | 6136 | } | 
|  | 6137 | }; | 
|  | 6138 |  | 
| Johannes Doerfert | ea5fabe | 2020-01-28 09:46:15 -0600 | [diff] [blame] | 6139 | struct AAValueConstantRangeArgument final | 
|  | 6140 | : AAArgumentFromCallSiteArguments< | 
|  | 6141 | AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState> { | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6142 | AAValueConstantRangeArgument(const IRPosition &IRP) | 
| Johannes Doerfert | ea5fabe | 2020-01-28 09:46:15 -0600 | [diff] [blame] | 6143 | : AAArgumentFromCallSiteArguments< | 
|  | 6144 | AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState>( | 
|  | 6145 | IRP) {} | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6146 |  | 
|  | 6147 | /// See AbstractAttribute::trackStatistics() | 
|  | 6148 | void trackStatistics() const override { | 
|  | 6149 | STATS_DECLTRACK_ARG_ATTR(value_range) | 
|  | 6150 | } | 
|  | 6151 | }; | 
|  | 6152 |  | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 6153 | struct AAValueConstantRangeReturned | 
|  | 6154 | : AAReturnedFromReturnedValues<AAValueConstantRange, | 
|  | 6155 | AAValueConstantRangeImpl> { | 
|  | 6156 | using Base = AAReturnedFromReturnedValues<AAValueConstantRange, | 
|  | 6157 | AAValueConstantRangeImpl>; | 
|  | 6158 | AAValueConstantRangeReturned(const IRPosition &IRP) : Base(IRP) {} | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6159 |  | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 6160 | /// See AbstractAttribute::initialize(...). | 
|  | 6161 | void initialize(Attributor &A) override {} | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6162 |  | 
|  | 6163 | /// See AbstractAttribute::trackStatistics() | 
|  | 6164 | void trackStatistics() const override { | 
|  | 6165 | STATS_DECLTRACK_FNRET_ATTR(value_range) | 
|  | 6166 | } | 
|  | 6167 | }; | 
|  | 6168 |  | 
|  | 6169 | struct AAValueConstantRangeFloating : AAValueConstantRangeImpl { | 
|  | 6170 | AAValueConstantRangeFloating(const IRPosition &IRP) | 
|  | 6171 | : AAValueConstantRangeImpl(IRP) {} | 
|  | 6172 |  | 
|  | 6173 | /// See AbstractAttribute::initialize(...). | 
|  | 6174 | void initialize(Attributor &A) override { | 
| Johannes Doerfert | 028db8c4 | 2020-02-09 19:05:15 -0600 | [diff] [blame] | 6175 | AAValueConstantRangeImpl::initialize(A); | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6176 | Value &V = getAssociatedValue(); | 
|  | 6177 |  | 
|  | 6178 | if (auto *C = dyn_cast<ConstantInt>(&V)) { | 
|  | 6179 | unionAssumed(ConstantRange(C->getValue())); | 
|  | 6180 | indicateOptimisticFixpoint(); | 
|  | 6181 | return; | 
|  | 6182 | } | 
|  | 6183 |  | 
|  | 6184 | if (isa<UndefValue>(&V)) { | 
|  | 6185 | indicateOptimisticFixpoint(); | 
|  | 6186 | return; | 
|  | 6187 | } | 
|  | 6188 |  | 
|  | 6189 | if (auto *I = dyn_cast<Instruction>(&V)) | 
|  | 6190 | if (isa<BinaryOperator>(I) || isa<CmpInst>(I)) { | 
|  | 6191 | Value *LHS = I->getOperand(0); | 
|  | 6192 | Value *RHS = I->getOperand(1); | 
|  | 6193 |  | 
|  | 6194 | if (LHS->getType()->isIntegerTy() && RHS->getType()->isIntegerTy()) | 
|  | 6195 | return; | 
|  | 6196 | } | 
|  | 6197 |  | 
|  | 6198 | // If it is a load instruction with range metadata, use it. | 
|  | 6199 | if (LoadInst *LI = dyn_cast<LoadInst>(&V)) | 
|  | 6200 | if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) { | 
|  | 6201 | intersectKnown(getConstantRangeFromMetadata(*RangeMD)); | 
|  | 6202 | return; | 
|  | 6203 | } | 
|  | 6204 |  | 
| Johannes Doerfert | ffdbd2a | 2020-02-09 19:07:30 -0600 | [diff] [blame] | 6205 | // We handle casts in the updateImpl. | 
|  | 6206 | // TODO: Allow non integers as well. | 
|  | 6207 | if (CastInst *CI = dyn_cast<CastInst>(&V)) | 
|  | 6208 | if (CI->getOperand(0)->getType()->isIntegerTy()) | 
|  | 6209 | return; | 
|  | 6210 |  | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6211 | // We can work with PHI and select instruction as we traverse their operands | 
| Johannes Doerfert | 7e7e659 | 2020-02-09 19:08:04 -0600 | [diff] [blame] | 6212 | // during update. | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6213 | if (isa<SelectInst>(V) || isa<PHINode>(V)) | 
| Johannes Doerfert | 7e7e659 | 2020-02-09 19:08:04 -0600 | [diff] [blame] | 6214 | return; | 
|  | 6215 |  | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6216 | // Otherwise we give up. | 
|  | 6217 | indicatePessimisticFixpoint(); | 
|  | 6218 |  | 
| Johannes Doerfert | 02bd818 | 2020-01-28 11:49:35 -0600 | [diff] [blame] | 6219 | LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: " | 
|  | 6220 | << getAssociatedValue() << "\n"); | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6221 | } | 
|  | 6222 |  | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6223 | bool calculateBinaryOperator( | 
|  | 6224 | Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T, | 
|  | 6225 | Instruction *CtxI, | 
|  | 6226 | SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) { | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6227 | Value *LHS = BinOp->getOperand(0); | 
|  | 6228 | Value *RHS = BinOp->getOperand(1); | 
|  | 6229 |  | 
|  | 6230 | auto &LHSAA = | 
|  | 6231 | A.getAAFor<AAValueConstantRange>(*this, IRPosition::value(*LHS)); | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6232 | QuerriedAAs.push_back(&LHSAA); | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6233 | auto LHSAARange = LHSAA.getAssumedConstantRange(A, CtxI); | 
|  | 6234 |  | 
|  | 6235 | auto &RHSAA = | 
|  | 6236 | A.getAAFor<AAValueConstantRange>(*this, IRPosition::value(*RHS)); | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6237 | QuerriedAAs.push_back(&RHSAA); | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6238 | auto RHSAARange = RHSAA.getAssumedConstantRange(A, CtxI); | 
|  | 6239 |  | 
|  | 6240 | auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange); | 
|  | 6241 |  | 
|  | 6242 | T.unionAssumed(AssumedRange); | 
|  | 6243 |  | 
|  | 6244 | // TODO: Track a known state too. | 
|  | 6245 |  | 
|  | 6246 | return T.isValidState(); | 
|  | 6247 | } | 
|  | 6248 |  | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6249 | bool calculateCastInst( | 
|  | 6250 | Attributor &A, CastInst *CastI, IntegerRangeState &T, Instruction *CtxI, | 
|  | 6251 | SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) { | 
| Johannes Doerfert | ffdbd2a | 2020-02-09 19:07:30 -0600 | [diff] [blame] | 6252 | assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!"); | 
|  | 6253 | // TODO: Allow non integers as well. | 
|  | 6254 | Value &OpV = *CastI->getOperand(0); | 
|  | 6255 | assert(OpV.getType()->isIntegerTy() && "Expected integer cast"); | 
|  | 6256 |  | 
|  | 6257 | auto &OpAA = | 
|  | 6258 | A.getAAFor<AAValueConstantRange>(*this, IRPosition::value(OpV)); | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6259 | QuerriedAAs.push_back(&OpAA); | 
| Johannes Doerfert | ffdbd2a | 2020-02-09 19:07:30 -0600 | [diff] [blame] | 6260 | T.unionAssumed( | 
|  | 6261 | OpAA.getAssumed().castOp(CastI->getOpcode(), getState().getBitWidth())); | 
|  | 6262 | return T.isValidState(); | 
|  | 6263 | } | 
|  | 6264 |  | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6265 | bool | 
|  | 6266 | calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T, | 
|  | 6267 | Instruction *CtxI, | 
|  | 6268 | SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) { | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6269 | Value *LHS = CmpI->getOperand(0); | 
|  | 6270 | Value *RHS = CmpI->getOperand(1); | 
|  | 6271 |  | 
|  | 6272 | auto &LHSAA = | 
|  | 6273 | A.getAAFor<AAValueConstantRange>(*this, IRPosition::value(*LHS)); | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6274 | QuerriedAAs.push_back(&LHSAA); | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6275 | auto &RHSAA = | 
|  | 6276 | A.getAAFor<AAValueConstantRange>(*this, IRPosition::value(*RHS)); | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6277 | QuerriedAAs.push_back(&RHSAA); | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6278 |  | 
|  | 6279 | auto LHSAARange = LHSAA.getAssumedConstantRange(A, CtxI); | 
|  | 6280 | auto RHSAARange = RHSAA.getAssumedConstantRange(A, CtxI); | 
|  | 6281 |  | 
|  | 6282 | // If one of them is empty set, we can't decide. | 
|  | 6283 | if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet()) | 
|  | 6284 | return true; | 
|  | 6285 |  | 
|  | 6286 | bool MustTrue = false, MustFalse = false; | 
|  | 6287 |  | 
|  | 6288 | auto AllowedRegion = | 
|  | 6289 | ConstantRange::makeAllowedICmpRegion(CmpI->getPredicate(), RHSAARange); | 
|  | 6290 |  | 
|  | 6291 | auto SatisfyingRegion = ConstantRange::makeSatisfyingICmpRegion( | 
|  | 6292 | CmpI->getPredicate(), RHSAARange); | 
|  | 6293 |  | 
|  | 6294 | if (AllowedRegion.intersectWith(LHSAARange).isEmptySet()) | 
|  | 6295 | MustFalse = true; | 
|  | 6296 |  | 
|  | 6297 | if (SatisfyingRegion.contains(LHSAARange)) | 
|  | 6298 | MustTrue = true; | 
|  | 6299 |  | 
|  | 6300 | assert((!MustTrue || !MustFalse) && | 
|  | 6301 | "Either MustTrue or MustFalse should be false!"); | 
|  | 6302 |  | 
|  | 6303 | if (MustTrue) | 
|  | 6304 | T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 1))); | 
|  | 6305 | else if (MustFalse) | 
|  | 6306 | T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 0))); | 
|  | 6307 | else | 
|  | 6308 | T.unionAssumed(ConstantRange(/* BitWidth */ 1, /* isFullSet */ true)); | 
|  | 6309 |  | 
|  | 6310 | LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " " << LHSAA | 
|  | 6311 | << " " << RHSAA << "\n"); | 
|  | 6312 |  | 
|  | 6313 | // TODO: Track a known state too. | 
|  | 6314 | return T.isValidState(); | 
|  | 6315 | } | 
|  | 6316 |  | 
|  | 6317 | /// See AbstractAttribute::updateImpl(...). | 
|  | 6318 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 6319 | Instruction *CtxI = getCtxI(); | 
|  | 6320 | auto VisitValueCB = [&](Value &V, IntegerRangeState &T, | 
|  | 6321 | bool Stripped) -> bool { | 
|  | 6322 | Instruction *I = dyn_cast<Instruction>(&V); | 
|  | 6323 | if (!I) { | 
|  | 6324 |  | 
|  | 6325 | // If the value is not instruction, we query AA to Attributor. | 
|  | 6326 | const auto &AA = | 
|  | 6327 | A.getAAFor<AAValueConstantRange>(*this, IRPosition::value(V)); | 
|  | 6328 |  | 
|  | 6329 | // Clamp operator is not used to utilize a program point CtxI. | 
|  | 6330 | T.unionAssumed(AA.getAssumedConstantRange(A, CtxI)); | 
|  | 6331 |  | 
|  | 6332 | return T.isValidState(); | 
|  | 6333 | } | 
|  | 6334 |  | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6335 | SmallVector<const AAValueConstantRange *, 4> QuerriedAAs; | 
|  | 6336 | if (auto *BinOp = dyn_cast<BinaryOperator>(I)) { | 
|  | 6337 | if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs)) | 
|  | 6338 | return false; | 
|  | 6339 | } else if (auto *CmpI = dyn_cast<CmpInst>(I)) { | 
|  | 6340 | if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs)) | 
|  | 6341 | return false; | 
|  | 6342 | } else if (auto *CastI = dyn_cast<CastInst>(I)) { | 
|  | 6343 | if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs)) | 
|  | 6344 | return false; | 
|  | 6345 | } else { | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6346 | // Give up with other instructions. | 
|  | 6347 | // TODO: Add other instructions | 
|  | 6348 |  | 
|  | 6349 | T.indicatePessimisticFixpoint(); | 
|  | 6350 | return false; | 
|  | 6351 | } | 
| Johannes Doerfert | 8155439 | 2020-02-09 20:14:35 -0600 | [diff] [blame] | 6352 |  | 
|  | 6353 | // Catch circular reasoning in a pessimistic way for now. | 
|  | 6354 | // TODO: Check how the range evolves and if we stripped anything, see also | 
|  | 6355 | //       AADereferenceable or AAAlign for similar situations. | 
|  | 6356 | for (const AAValueConstantRange *QueriedAA : QuerriedAAs) { | 
|  | 6357 | if (QueriedAA != this) | 
|  | 6358 | continue; | 
|  | 6359 | // If we are in a stady state we do not need to worry. | 
|  | 6360 | if (T.getAssumed() == getState().getAssumed()) | 
|  | 6361 | continue; | 
|  | 6362 | T.indicatePessimisticFixpoint(); | 
|  | 6363 | } | 
|  | 6364 |  | 
|  | 6365 | return T.isValidState(); | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6366 | }; | 
|  | 6367 |  | 
|  | 6368 | IntegerRangeState T(getBitWidth()); | 
|  | 6369 |  | 
|  | 6370 | if (!genericValueTraversal<AAValueConstantRange, IntegerRangeState>( | 
|  | 6371 | A, getIRPosition(), *this, T, VisitValueCB)) | 
|  | 6372 | return indicatePessimisticFixpoint(); | 
|  | 6373 |  | 
|  | 6374 | return clampStateAndIndicateChange(getState(), T); | 
|  | 6375 | } | 
|  | 6376 |  | 
|  | 6377 | /// See AbstractAttribute::trackStatistics() | 
|  | 6378 | void trackStatistics() const override { | 
|  | 6379 | STATS_DECLTRACK_FLOATING_ATTR(value_range) | 
|  | 6380 | } | 
|  | 6381 | }; | 
|  | 6382 |  | 
|  | 6383 | struct AAValueConstantRangeFunction : AAValueConstantRangeImpl { | 
|  | 6384 | AAValueConstantRangeFunction(const IRPosition &IRP) | 
|  | 6385 | : AAValueConstantRangeImpl(IRP) {} | 
|  | 6386 |  | 
|  | 6387 | /// See AbstractAttribute::initialize(...). | 
|  | 6388 | ChangeStatus updateImpl(Attributor &A) override { | 
|  | 6389 | llvm_unreachable("AAValueConstantRange(Function|CallSite)::updateImpl will " | 
|  | 6390 | "not be called"); | 
|  | 6391 | } | 
|  | 6392 |  | 
|  | 6393 | /// See AbstractAttribute::trackStatistics() | 
|  | 6394 | void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(value_range) } | 
|  | 6395 | }; | 
|  | 6396 |  | 
|  | 6397 | struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction { | 
|  | 6398 | AAValueConstantRangeCallSite(const IRPosition &IRP) | 
|  | 6399 | : AAValueConstantRangeFunction(IRP) {} | 
|  | 6400 |  | 
|  | 6401 | /// See AbstractAttribute::trackStatistics() | 
|  | 6402 | void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(value_range) } | 
|  | 6403 | }; | 
|  | 6404 |  | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 6405 | struct AAValueConstantRangeCallSiteReturned | 
|  | 6406 | : AACallSiteReturnedFromReturned<AAValueConstantRange, | 
|  | 6407 | AAValueConstantRangeImpl> { | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6408 | AAValueConstantRangeCallSiteReturned(const IRPosition &IRP) | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 6409 | : AACallSiteReturnedFromReturned<AAValueConstantRange, | 
|  | 6410 | AAValueConstantRangeImpl>(IRP) {} | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6411 |  | 
|  | 6412 | /// See AbstractAttribute::initialize(...). | 
|  | 6413 | void initialize(Attributor &A) override { | 
|  | 6414 | // If it is a load instruction with range metadata, use the metadata. | 
|  | 6415 | if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue())) | 
|  | 6416 | if (auto *RangeMD = CI->getMetadata(LLVMContext::MD_range)) | 
|  | 6417 | intersectKnown(getConstantRangeFromMetadata(*RangeMD)); | 
|  | 6418 |  | 
| Johannes Doerfert | 791c9f1 | 2020-01-29 18:02:42 -0600 | [diff] [blame] | 6419 | AAValueConstantRangeImpl::initialize(A); | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 6420 | } | 
|  | 6421 |  | 
|  | 6422 | /// See AbstractAttribute::trackStatistics() | 
|  | 6423 | void trackStatistics() const override { | 
|  | 6424 | STATS_DECLTRACK_CSRET_ATTR(value_range) | 
|  | 6425 | } | 
|  | 6426 | }; | 
|  | 6427 | struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating { | 
|  | 6428 | AAValueConstantRangeCallSiteArgument(const IRPosition &IRP) | 
|  | 6429 | : AAValueConstantRangeFloating(IRP) {} | 
|  | 6430 |  | 
|  | 6431 | /// See AbstractAttribute::trackStatistics() | 
|  | 6432 | void trackStatistics() const override { | 
|  | 6433 | STATS_DECLTRACK_CSARG_ATTR(value_range) | 
|  | 6434 | } | 
|  | 6435 | }; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6436 | /// ---------------------------------------------------------------------------- | 
|  | 6437 | ///                               Attributor | 
|  | 6438 | /// ---------------------------------------------------------------------------- | 
|  | 6439 |  | 
| Johannes Doerfert | 9a1a1f9 | 2019-08-14 21:25:08 +0000 | [diff] [blame] | 6440 | bool Attributor::isAssumedDead(const AbstractAttribute &AA, | 
|  | 6441 | const AAIsDead *LivenessAA) { | 
|  | 6442 | const Instruction *CtxI = AA.getIRPosition().getCtxI(); | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 6443 | if (!CtxI || !Functions.count(const_cast<Function *>(CtxI->getFunction()))) | 
| Johannes Doerfert | 9a1a1f9 | 2019-08-14 21:25:08 +0000 | [diff] [blame] | 6444 | return false; | 
|  | 6445 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 6446 | // TODO: Find a good way to utilize fine and coarse grained liveness | 
|  | 6447 | // information. | 
| Johannes Doerfert | 9a1a1f9 | 2019-08-14 21:25:08 +0000 | [diff] [blame] | 6448 | if (!LivenessAA) | 
|  | 6449 | LivenessAA = | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6450 | &getAAFor<AAIsDead>(AA, IRPosition::function(*CtxI->getFunction()), | 
|  | 6451 | /* TrackDependence */ false); | 
| Stefan Stipanovic | 26121ae | 2019-08-20 23:16:57 +0000 | [diff] [blame] | 6452 |  | 
|  | 6453 | // Don't check liveness for AAIsDead. | 
|  | 6454 | if (&AA == LivenessAA) | 
|  | 6455 | return false; | 
|  | 6456 |  | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 6457 | if (!LivenessAA->isAssumedDead(CtxI)) | 
| Johannes Doerfert | 9a1a1f9 | 2019-08-14 21:25:08 +0000 | [diff] [blame] | 6458 | return false; | 
|  | 6459 |  | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6460 | // We actually used liveness information so we have to record a dependence. | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6461 | recordDependence(*LivenessAA, AA, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6462 |  | 
| Johannes Doerfert | 9a1a1f9 | 2019-08-14 21:25:08 +0000 | [diff] [blame] | 6463 | return true; | 
|  | 6464 | } | 
|  | 6465 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 6466 | bool Attributor::checkForAllUses( | 
|  | 6467 | const function_ref<bool(const Use &, bool &)> &Pred, | 
|  | 6468 | const AbstractAttribute &QueryingAA, const Value &V) { | 
|  | 6469 | const IRPosition &IRP = QueryingAA.getIRPosition(); | 
|  | 6470 | SmallVector<const Use *, 16> Worklist; | 
|  | 6471 | SmallPtrSet<const Use *, 16> Visited; | 
|  | 6472 |  | 
|  | 6473 | for (const Use &U : V.uses()) | 
|  | 6474 | Worklist.push_back(&U); | 
|  | 6475 |  | 
|  | 6476 | LLVM_DEBUG(dbgs() << "[Attributor] Got " << Worklist.size() | 
|  | 6477 | << " initial uses to check\n"); | 
|  | 6478 |  | 
|  | 6479 | if (Worklist.empty()) | 
|  | 6480 | return true; | 
|  | 6481 |  | 
|  | 6482 | bool AnyDead = false; | 
|  | 6483 | const Function *ScopeFn = IRP.getAnchorScope(); | 
|  | 6484 | const auto *LivenessAA = | 
|  | 6485 | ScopeFn ? &getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*ScopeFn), | 
|  | 6486 | /* TrackDependence */ false) | 
|  | 6487 | : nullptr; | 
|  | 6488 |  | 
|  | 6489 | while (!Worklist.empty()) { | 
|  | 6490 | const Use *U = Worklist.pop_back_val(); | 
|  | 6491 | if (!Visited.insert(U).second) | 
|  | 6492 | continue; | 
| Johannes Doerfert | 8e62968 | 2020-02-11 00:10:35 -0600 | [diff] [blame] | 6493 | LLVM_DEBUG(dbgs() << "[Attributor] Check use: " << **U << " [" << LivenessAA | 
|  | 6494 | << "]\n"); | 
|  | 6495 | if (LivenessAA) { | 
|  | 6496 | if (Instruction *UserI = dyn_cast<Instruction>(U->getUser())) { | 
|  | 6497 | if (LivenessAA->isAssumedDead(UserI)) { | 
|  | 6498 | LLVM_DEBUG(dbgs() << "[Attributor] Dead user: " << *UserI << ": " | 
|  | 6499 | << *LivenessAA << "\n"); | 
|  | 6500 | AnyDead = true; | 
|  | 6501 | continue; | 
|  | 6502 | } | 
|  | 6503 | if (PHINode *PHI = dyn_cast<PHINode>(UserI)) { | 
|  | 6504 | BasicBlock *IncomingBB = PHI->getIncomingBlock(*U); | 
|  | 6505 | if (LivenessAA->isAssumedDead(IncomingBB->getTerminator())) { | 
|  | 6506 | LLVM_DEBUG(dbgs() << "[Attributor] Dead user: " << *UserI << ": " | 
|  | 6507 | << *LivenessAA << "\n"); | 
|  | 6508 | AnyDead = true; | 
|  | 6509 | continue; | 
|  | 6510 | } | 
|  | 6511 | } | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 6512 | } | 
| Johannes Doerfert | 8e62968 | 2020-02-11 00:10:35 -0600 | [diff] [blame] | 6513 | } | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 6514 |  | 
|  | 6515 | bool Follow = false; | 
|  | 6516 | if (!Pred(*U, Follow)) | 
|  | 6517 | return false; | 
|  | 6518 | if (!Follow) | 
|  | 6519 | continue; | 
|  | 6520 | for (const Use &UU : U->getUser()->uses()) | 
|  | 6521 | Worklist.push_back(&UU); | 
|  | 6522 | } | 
|  | 6523 |  | 
|  | 6524 | if (AnyDead) | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6525 | recordDependence(*LivenessAA, QueryingAA, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 6526 |  | 
|  | 6527 | return true; | 
|  | 6528 | } | 
|  | 6529 |  | 
| Johannes Doerfert | 661db04 | 2019-10-07 23:14:58 +0000 | [diff] [blame] | 6530 | bool Attributor::checkForAllCallSites( | 
|  | 6531 | const function_ref<bool(AbstractCallSite)> &Pred, | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 6532 | const AbstractAttribute &QueryingAA, bool RequireAllCallSites, | 
|  | 6533 | bool &AllCallSitesKnown) { | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 6534 | // We can try to determine information from | 
|  | 6535 | // the call sites. However, this is only possible all call sites are known, | 
|  | 6536 | // hence the function has internal linkage. | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6537 | const IRPosition &IRP = QueryingAA.getIRPosition(); | 
|  | 6538 | const Function *AssociatedFunction = IRP.getAssociatedFunction(); | 
| Johannes Doerfert | 748538e | 2019-10-07 23:30:04 +0000 | [diff] [blame] | 6539 | if (!AssociatedFunction) { | 
|  | 6540 | LLVM_DEBUG(dbgs() << "[Attributor] No function associated with " << IRP | 
|  | 6541 | << "\n"); | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 6542 | AllCallSitesKnown = false; | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6543 | return false; | 
| Johannes Doerfert | 748538e | 2019-10-07 23:30:04 +0000 | [diff] [blame] | 6544 | } | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6545 |  | 
| Johannes Doerfert | 3753aa7 | 2019-10-13 04:16:02 +0000 | [diff] [blame] | 6546 | return checkForAllCallSites(Pred, *AssociatedFunction, RequireAllCallSites, | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 6547 | &QueryingAA, AllCallSitesKnown); | 
| Johannes Doerfert | 3753aa7 | 2019-10-13 04:16:02 +0000 | [diff] [blame] | 6548 | } | 
|  | 6549 |  | 
|  | 6550 | bool Attributor::checkForAllCallSites( | 
|  | 6551 | const function_ref<bool(AbstractCallSite)> &Pred, const Function &Fn, | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 6552 | bool RequireAllCallSites, const AbstractAttribute *QueryingAA, | 
|  | 6553 | bool &AllCallSitesKnown) { | 
| Johannes Doerfert | 3753aa7 | 2019-10-13 04:16:02 +0000 | [diff] [blame] | 6554 | if (RequireAllCallSites && !Fn.hasLocalLinkage()) { | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 6555 | LLVM_DEBUG( | 
|  | 6556 | dbgs() | 
| Johannes Doerfert | 3753aa7 | 2019-10-13 04:16:02 +0000 | [diff] [blame] | 6557 | << "[Attributor] Function " << Fn.getName() | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 6558 | << " has no internal linkage, hence not all call sites are known\n"); | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 6559 | AllCallSitesKnown = false; | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 6560 | return false; | 
|  | 6561 | } | 
|  | 6562 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 6563 | // If we do not require all call sites we might not see all. | 
|  | 6564 | AllCallSitesKnown = RequireAllCallSites; | 
|  | 6565 |  | 
| Johannes Doerfert | 3753aa7 | 2019-10-13 04:16:02 +0000 | [diff] [blame] | 6566 | for (const Use &U : Fn.uses()) { | 
| Johannes Doerfert | 661db04 | 2019-10-07 23:14:58 +0000 | [diff] [blame] | 6567 | AbstractCallSite ACS(&U); | 
|  | 6568 | if (!ACS) { | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 6569 | LLVM_DEBUG(dbgs() << "[Attributor] Function " << Fn.getName() | 
| Johannes Doerfert | 661db04 | 2019-10-07 23:14:58 +0000 | [diff] [blame] | 6570 | << " has non call site use " << *U.get() << " in " | 
|  | 6571 | << *U.getUser() << "\n"); | 
| Johannes Doerfert | 2d77b0c | 2019-11-01 22:35:18 -0500 | [diff] [blame] | 6572 | // BlockAddress users are allowed. | 
|  | 6573 | if (isa<BlockAddress>(U.getUser())) | 
|  | 6574 | continue; | 
| Johannes Doerfert | d98f975 | 2019-08-21 21:48:56 +0000 | [diff] [blame] | 6575 | return false; | 
| Johannes Doerfert | 661db04 | 2019-10-07 23:14:58 +0000 | [diff] [blame] | 6576 | } | 
| Johannes Doerfert | d98f975 | 2019-08-21 21:48:56 +0000 | [diff] [blame] | 6577 |  | 
| Johannes Doerfert | 661db04 | 2019-10-07 23:14:58 +0000 | [diff] [blame] | 6578 | Instruction *I = ACS.getInstruction(); | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6579 | Function *Caller = I->getFunction(); | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 6580 |  | 
| Johannes Doerfert | 3753aa7 | 2019-10-13 04:16:02 +0000 | [diff] [blame] | 6581 | const auto *LivenessAA = | 
|  | 6582 | lookupAAFor<AAIsDead>(IRPosition::function(*Caller), QueryingAA, | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 6583 | /* TrackDependence */ false); | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 6584 |  | 
|  | 6585 | // Skip dead calls. | 
| Johannes Doerfert | 3753aa7 | 2019-10-13 04:16:02 +0000 | [diff] [blame] | 6586 | if (LivenessAA && LivenessAA->isAssumedDead(I)) { | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6587 | // We actually used liveness information so we have to record a | 
|  | 6588 | // dependence. | 
| Johannes Doerfert | 3753aa7 | 2019-10-13 04:16:02 +0000 | [diff] [blame] | 6589 | if (QueryingAA) | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6590 | recordDependence(*LivenessAA, *QueryingAA, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 6591 | AllCallSitesKnown = false; | 
| Stefan Stipanovic | d021617 | 2019-08-02 21:31:22 +0000 | [diff] [blame] | 6592 | continue; | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6593 | } | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 6594 |  | 
| Johannes Doerfert | 661db04 | 2019-10-07 23:14:58 +0000 | [diff] [blame] | 6595 | const Use *EffectiveUse = | 
|  | 6596 | ACS.isCallbackCall() ? &ACS.getCalleeUseForCallback() : &U; | 
|  | 6597 | if (!ACS.isCallee(EffectiveUse)) { | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 6598 | if (!RequireAllCallSites) | 
|  | 6599 | continue; | 
| Johannes Doerfert | 661db04 | 2019-10-07 23:14:58 +0000 | [diff] [blame] | 6600 | LLVM_DEBUG(dbgs() << "[Attributor] User " << EffectiveUse->getUser() | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 6601 | << " is an invalid use of " << Fn.getName() << "\n"); | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 6602 | return false; | 
|  | 6603 | } | 
|  | 6604 |  | 
| Johannes Doerfert | 661db04 | 2019-10-07 23:14:58 +0000 | [diff] [blame] | 6605 | if (Pred(ACS)) | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 6606 | continue; | 
|  | 6607 |  | 
| Johannes Doerfert | 5304b72 | 2019-08-14 22:04:28 +0000 | [diff] [blame] | 6608 | LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for " | 
| Johannes Doerfert | 661db04 | 2019-10-07 23:14:58 +0000 | [diff] [blame] | 6609 | << *ACS.getInstruction() << "\n"); | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 6610 | return false; | 
|  | 6611 | } | 
|  | 6612 |  | 
|  | 6613 | return true; | 
|  | 6614 | } | 
|  | 6615 |  | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 6616 | bool Attributor::checkForAllReturnedValuesAndReturnInsts( | 
| Johannes Doerfert | 695089e | 2019-08-23 15:23:49 +0000 | [diff] [blame] | 6617 | const function_ref<bool(Value &, const SmallSetVector<ReturnInst *, 4> &)> | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 6618 | &Pred, | 
|  | 6619 | const AbstractAttribute &QueryingAA) { | 
|  | 6620 |  | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6621 | const IRPosition &IRP = QueryingAA.getIRPosition(); | 
|  | 6622 | // Since we need to provide return instructions we have to have an exact | 
|  | 6623 | // definition. | 
|  | 6624 | const Function *AssociatedFunction = IRP.getAssociatedFunction(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 6625 | if (!AssociatedFunction) | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 6626 | return false; | 
|  | 6627 |  | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6628 | // If this is a call site query we use the call site specific return values | 
|  | 6629 | // and liveness information. | 
| Johannes Doerfert | 07a5c12 | 2019-08-28 14:09:14 +0000 | [diff] [blame] | 6630 | // TODO: use the function scope once we have call site AAReturnedValues. | 
|  | 6631 | const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction); | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6632 | const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP); | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 6633 | if (!AARetVal.getState().isValidState()) | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6634 | return false; | 
|  | 6635 |  | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 6636 | return AARetVal.checkForAllReturnedValuesAndReturnInsts(Pred); | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 6637 | } | 
|  | 6638 |  | 
|  | 6639 | bool Attributor::checkForAllReturnedValues( | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6640 | const function_ref<bool(Value &)> &Pred, | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 6641 | const AbstractAttribute &QueryingAA) { | 
|  | 6642 |  | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6643 | const IRPosition &IRP = QueryingAA.getIRPosition(); | 
|  | 6644 | const Function *AssociatedFunction = IRP.getAssociatedFunction(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 6645 | if (!AssociatedFunction) | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 6646 | return false; | 
|  | 6647 |  | 
| Johannes Doerfert | 07a5c12 | 2019-08-28 14:09:14 +0000 | [diff] [blame] | 6648 | // TODO: use the function scope once we have call site AAReturnedValues. | 
|  | 6649 | const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction); | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6650 | const auto &AARetVal = getAAFor<AAReturnedValues>(QueryingAA, QueryIRP); | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 6651 | if (!AARetVal.getState().isValidState()) | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6652 | return false; | 
|  | 6653 |  | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 6654 | return AARetVal.checkForAllReturnedValuesAndReturnInsts( | 
| Johannes Doerfert | 695089e | 2019-08-23 15:23:49 +0000 | [diff] [blame] | 6655 | [&](Value &RV, const SmallSetVector<ReturnInst *, 4> &) { | 
| Johannes Doerfert | def9928 | 2019-08-14 21:29:37 +0000 | [diff] [blame] | 6656 | return Pred(RV); | 
|  | 6657 | }); | 
| Johannes Doerfert | 14a0493 | 2019-08-07 22:27:24 +0000 | [diff] [blame] | 6658 | } | 
|  | 6659 |  | 
| Johannes Doerfert | 3ab9e8b | 2019-09-17 10:52:41 +0000 | [diff] [blame] | 6660 | static bool | 
|  | 6661 | checkForAllInstructionsImpl(InformationCache::OpcodeInstMapTy &OpcodeInstMap, | 
|  | 6662 | const function_ref<bool(Instruction &)> &Pred, | 
|  | 6663 | const AAIsDead *LivenessAA, bool &AnyDead, | 
|  | 6664 | const ArrayRef<unsigned> &Opcodes) { | 
|  | 6665 | for (unsigned Opcode : Opcodes) { | 
|  | 6666 | for (Instruction *I : OpcodeInstMap[Opcode]) { | 
|  | 6667 | // Skip dead instructions. | 
|  | 6668 | if (LivenessAA && LivenessAA->isAssumedDead(I)) { | 
|  | 6669 | AnyDead = true; | 
|  | 6670 | continue; | 
|  | 6671 | } | 
|  | 6672 |  | 
|  | 6673 | if (!Pred(*I)) | 
|  | 6674 | return false; | 
|  | 6675 | } | 
|  | 6676 | } | 
|  | 6677 | return true; | 
|  | 6678 | } | 
|  | 6679 |  | 
| Johannes Doerfert | d0f6400 | 2019-08-06 00:32:43 +0000 | [diff] [blame] | 6680 | bool Attributor::checkForAllInstructions( | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6681 | const llvm::function_ref<bool(Instruction &)> &Pred, | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 6682 | const AbstractAttribute &QueryingAA, const ArrayRef<unsigned> &Opcodes) { | 
| Johannes Doerfert | d0f6400 | 2019-08-06 00:32:43 +0000 | [diff] [blame] | 6683 |  | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6684 | const IRPosition &IRP = QueryingAA.getIRPosition(); | 
|  | 6685 | // Since we need to provide instructions we have to have an exact definition. | 
|  | 6686 | const Function *AssociatedFunction = IRP.getAssociatedFunction(); | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 6687 | if (!AssociatedFunction) | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6688 | return false; | 
| Johannes Doerfert | d0f6400 | 2019-08-06 00:32:43 +0000 | [diff] [blame] | 6689 |  | 
| Johannes Doerfert | 07a5c12 | 2019-08-28 14:09:14 +0000 | [diff] [blame] | 6690 | // TODO: use the function scope once we have call site AAReturnedValues. | 
|  | 6691 | const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction); | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6692 | const auto &LivenessAA = | 
|  | 6693 | getAAFor<AAIsDead>(QueryingAA, QueryIRP, /* TrackDependence */ false); | 
|  | 6694 | bool AnyDead = false; | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6695 |  | 
|  | 6696 | auto &OpcodeInstMap = | 
|  | 6697 | InfoCache.getOpcodeInstMapForFunction(*AssociatedFunction); | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 6698 | if (!checkForAllInstructionsImpl(OpcodeInstMap, Pred, &LivenessAA, AnyDead, | 
|  | 6699 | Opcodes)) | 
| Johannes Doerfert | 3ab9e8b | 2019-09-17 10:52:41 +0000 | [diff] [blame] | 6700 | return false; | 
| Johannes Doerfert | d0f6400 | 2019-08-06 00:32:43 +0000 | [diff] [blame] | 6701 |  | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6702 | // If we actually used liveness information so we have to record a dependence. | 
|  | 6703 | if (AnyDead) | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6704 | recordDependence(LivenessAA, QueryingAA, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6705 |  | 
| Johannes Doerfert | d0f6400 | 2019-08-06 00:32:43 +0000 | [diff] [blame] | 6706 | return true; | 
|  | 6707 | } | 
|  | 6708 |  | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 6709 | bool Attributor::checkForAllReadWriteInstructions( | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6710 | const llvm::function_ref<bool(Instruction &)> &Pred, | 
| Johannes Doerfert | ece8190 | 2019-08-12 22:05:53 +0000 | [diff] [blame] | 6711 | AbstractAttribute &QueryingAA) { | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 6712 |  | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6713 | const Function *AssociatedFunction = | 
|  | 6714 | QueryingAA.getIRPosition().getAssociatedFunction(); | 
|  | 6715 | if (!AssociatedFunction) | 
|  | 6716 | return false; | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 6717 |  | 
| Johannes Doerfert | 07a5c12 | 2019-08-28 14:09:14 +0000 | [diff] [blame] | 6718 | // TODO: use the function scope once we have call site AAReturnedValues. | 
|  | 6719 | const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction); | 
|  | 6720 | const auto &LivenessAA = | 
|  | 6721 | getAAFor<AAIsDead>(QueryingAA, QueryIRP, /* TrackDependence */ false); | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6722 | bool AnyDead = false; | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 6723 |  | 
|  | 6724 | for (Instruction *I : | 
|  | 6725 | InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) { | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 6726 | // Skip dead instructions. | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6727 | if (LivenessAA.isAssumedDead(I)) { | 
|  | 6728 | AnyDead = true; | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 6729 | continue; | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6730 | } | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 6731 |  | 
|  | 6732 | if (!Pred(*I)) | 
|  | 6733 | return false; | 
|  | 6734 | } | 
|  | 6735 |  | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6736 | // If we actually used liveness information so we have to record a dependence. | 
|  | 6737 | if (AnyDead) | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6738 | recordDependence(LivenessAA, QueryingAA, DepClassTy::OPTIONAL); | 
| Johannes Doerfert | 19b0043 | 2019-08-26 17:48:05 +0000 | [diff] [blame] | 6739 |  | 
| Stefan Stipanovic | aaa5270 | 2019-08-07 18:26:02 +0000 | [diff] [blame] | 6740 | return true; | 
|  | 6741 | } | 
|  | 6742 |  | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 6743 | ChangeStatus Attributor::run() { | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6744 | LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized " | 
|  | 6745 | << AllAbstractAttributes.size() | 
|  | 6746 | << " abstract attributes.\n"); | 
|  | 6747 |  | 
| Stefan Stipanovic | 5360589 | 2019-06-27 11:27:54 +0000 | [diff] [blame] | 6748 | // Now that all abstract attributes are collected and initialized we start | 
|  | 6749 | // the abstract analysis. | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6750 |  | 
|  | 6751 | unsigned IterationCounter = 1; | 
|  | 6752 |  | 
|  | 6753 | SmallVector<AbstractAttribute *, 64> ChangedAAs; | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6754 | SetVector<AbstractAttribute *> Worklist, InvalidAAs; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6755 | Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end()); | 
|  | 6756 |  | 
| Johannes Doerfert | f7ca0fe | 2019-08-28 16:58:52 +0000 | [diff] [blame] | 6757 | bool RecomputeDependences = false; | 
|  | 6758 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6759 | do { | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 6760 | // Remember the size to determine new attributes. | 
|  | 6761 | size_t NumAAs = AllAbstractAttributes.size(); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6762 | LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter | 
|  | 6763 | << ", Worklist size: " << Worklist.size() << "\n"); | 
|  | 6764 |  | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6765 | // For invalid AAs we can fix dependent AAs that have a required dependence, | 
|  | 6766 | // thereby folding long dependence chains in a single step without the need | 
|  | 6767 | // to run updates. | 
|  | 6768 | for (unsigned u = 0; u < InvalidAAs.size(); ++u) { | 
|  | 6769 | AbstractAttribute *InvalidAA = InvalidAAs[u]; | 
|  | 6770 | auto &QuerriedAAs = QueryMap[InvalidAA]; | 
|  | 6771 | LLVM_DEBUG(dbgs() << "[Attributor] InvalidAA: " << *InvalidAA << " has " | 
|  | 6772 | << QuerriedAAs.RequiredAAs.size() << "/" | 
|  | 6773 | << QuerriedAAs.OptionalAAs.size() | 
|  | 6774 | << " required/optional dependences\n"); | 
|  | 6775 | for (AbstractAttribute *DepOnInvalidAA : QuerriedAAs.RequiredAAs) { | 
|  | 6776 | AbstractState &DOIAAState = DepOnInvalidAA->getState(); | 
|  | 6777 | DOIAAState.indicatePessimisticFixpoint(); | 
|  | 6778 | ++NumAttributesFixedDueToRequiredDependences; | 
|  | 6779 | assert(DOIAAState.isAtFixpoint() && "Expected fixpoint state!"); | 
|  | 6780 | if (!DOIAAState.isValidState()) | 
|  | 6781 | InvalidAAs.insert(DepOnInvalidAA); | 
| Johannes Doerfert | 2240854 | 2020-01-28 09:38:07 -0600 | [diff] [blame] | 6782 | else | 
|  | 6783 | ChangedAAs.push_back(DepOnInvalidAA); | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6784 | } | 
|  | 6785 | if (!RecomputeDependences) | 
|  | 6786 | Worklist.insert(QuerriedAAs.OptionalAAs.begin(), | 
|  | 6787 | QuerriedAAs.OptionalAAs.end()); | 
|  | 6788 | } | 
|  | 6789 |  | 
| Johannes Doerfert | f7ca0fe | 2019-08-28 16:58:52 +0000 | [diff] [blame] | 6790 | // If dependences (=QueryMap) are recomputed we have to look at all abstract | 
|  | 6791 | // attributes again, regardless of what changed in the last iteration. | 
|  | 6792 | if (RecomputeDependences) { | 
|  | 6793 | LLVM_DEBUG( | 
|  | 6794 | dbgs() << "[Attributor] Run all AAs to recompute dependences\n"); | 
|  | 6795 | QueryMap.clear(); | 
|  | 6796 | ChangedAAs.clear(); | 
|  | 6797 | Worklist.insert(AllAbstractAttributes.begin(), | 
|  | 6798 | AllAbstractAttributes.end()); | 
|  | 6799 | } | 
|  | 6800 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6801 | // Add all abstract attributes that are potentially dependent on one that | 
|  | 6802 | // changed to the work list. | 
|  | 6803 | for (AbstractAttribute *ChangedAA : ChangedAAs) { | 
|  | 6804 | auto &QuerriedAAs = QueryMap[ChangedAA]; | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6805 | Worklist.insert(QuerriedAAs.OptionalAAs.begin(), | 
|  | 6806 | QuerriedAAs.OptionalAAs.end()); | 
|  | 6807 | Worklist.insert(QuerriedAAs.RequiredAAs.begin(), | 
|  | 6808 | QuerriedAAs.RequiredAAs.end()); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6809 | } | 
|  | 6810 |  | 
| Johannes Doerfert | b504eb8 | 2019-08-26 18:55:47 +0000 | [diff] [blame] | 6811 | LLVM_DEBUG(dbgs() << "[Attributor] #Iteration: " << IterationCounter | 
|  | 6812 | << ", Worklist+Dependent size: " << Worklist.size() | 
|  | 6813 | << "\n"); | 
|  | 6814 |  | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6815 | // Reset the changed and invalid set. | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6816 | ChangedAAs.clear(); | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6817 | InvalidAAs.clear(); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6818 |  | 
|  | 6819 | // Update all abstract attribute in the work list and record the ones that | 
|  | 6820 | // changed. | 
|  | 6821 | for (AbstractAttribute *AA : Worklist) | 
| Johannes Doerfert | 2dad729 | 2019-10-13 21:10:31 -0500 | [diff] [blame] | 6822 | if (!AA->getState().isAtFixpoint() && !isAssumedDead(*AA, nullptr)) { | 
|  | 6823 | QueriedNonFixAA = false; | 
|  | 6824 | if (AA->update(*this) == ChangeStatus::CHANGED) { | 
| Johannes Doerfert | 9a1a1f9 | 2019-08-14 21:25:08 +0000 | [diff] [blame] | 6825 | ChangedAAs.push_back(AA); | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6826 | if (!AA->getState().isValidState()) | 
|  | 6827 | InvalidAAs.insert(AA); | 
| Johannes Doerfert | 2dad729 | 2019-10-13 21:10:31 -0500 | [diff] [blame] | 6828 | } else if (!QueriedNonFixAA) { | 
|  | 6829 | // If the attribute did not query any non-fix information, the state | 
|  | 6830 | // will not change and we can indicate that right away. | 
|  | 6831 | AA->getState().indicateOptimisticFixpoint(); | 
|  | 6832 | } | 
|  | 6833 | } | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6834 |  | 
| Johannes Doerfert | f7ca0fe | 2019-08-28 16:58:52 +0000 | [diff] [blame] | 6835 | // Check if we recompute the dependences in the next iteration. | 
|  | 6836 | RecomputeDependences = (DepRecomputeInterval > 0 && | 
|  | 6837 | IterationCounter % DepRecomputeInterval == 0); | 
|  | 6838 |  | 
| Johannes Doerfert | 9543f14 | 2019-08-23 15:24:57 +0000 | [diff] [blame] | 6839 | // Add attributes to the changed set if they have been created in the last | 
|  | 6840 | // iteration. | 
|  | 6841 | ChangedAAs.append(AllAbstractAttributes.begin() + NumAAs, | 
|  | 6842 | AllAbstractAttributes.end()); | 
|  | 6843 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6844 | // Reset the work list and repopulate with the changed abstract attributes. | 
|  | 6845 | // Note that dependent ones are added above. | 
|  | 6846 | Worklist.clear(); | 
|  | 6847 | Worklist.insert(ChangedAAs.begin(), ChangedAAs.end()); | 
|  | 6848 |  | 
| Johannes Doerfert | bf11213 | 2019-08-29 01:29:44 +0000 | [diff] [blame] | 6849 | } while (!Worklist.empty() && (IterationCounter++ < MaxFixpointIterations || | 
|  | 6850 | VerifyMaxFixpointIterations)); | 
| Johannes Doerfert | f7ca0fe | 2019-08-28 16:58:52 +0000 | [diff] [blame] | 6851 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6852 | LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: " | 
|  | 6853 | << IterationCounter << "/" << MaxFixpointIterations | 
|  | 6854 | << " iterations\n"); | 
|  | 6855 |  | 
| Johannes Doerfert | bf11213 | 2019-08-29 01:29:44 +0000 | [diff] [blame] | 6856 | size_t NumFinalAAs = AllAbstractAttributes.size(); | 
| Johannes Doerfert | b504eb8 | 2019-08-26 18:55:47 +0000 | [diff] [blame] | 6857 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6858 | // Reset abstract arguments not settled in a sound fixpoint by now. This | 
|  | 6859 | // happens when we stopped the fixpoint iteration early. Note that only the | 
|  | 6860 | // ones marked as "changed" *and* the ones transitively depending on them | 
|  | 6861 | // need to be reverted to a pessimistic state. Others might not be in a | 
|  | 6862 | // fixpoint state but we can use the optimistic results for them anyway. | 
|  | 6863 | SmallPtrSet<AbstractAttribute *, 32> Visited; | 
|  | 6864 | for (unsigned u = 0; u < ChangedAAs.size(); u++) { | 
|  | 6865 | AbstractAttribute *ChangedAA = ChangedAAs[u]; | 
|  | 6866 | if (!Visited.insert(ChangedAA).second) | 
|  | 6867 | continue; | 
|  | 6868 |  | 
|  | 6869 | AbstractState &State = ChangedAA->getState(); | 
|  | 6870 | if (!State.isAtFixpoint()) { | 
|  | 6871 | State.indicatePessimisticFixpoint(); | 
|  | 6872 |  | 
|  | 6873 | NumAttributesTimedOut++; | 
|  | 6874 | } | 
|  | 6875 |  | 
|  | 6876 | auto &QuerriedAAs = QueryMap[ChangedAA]; | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 6877 | ChangedAAs.append(QuerriedAAs.OptionalAAs.begin(), | 
|  | 6878 | QuerriedAAs.OptionalAAs.end()); | 
|  | 6879 | ChangedAAs.append(QuerriedAAs.RequiredAAs.begin(), | 
|  | 6880 | QuerriedAAs.RequiredAAs.end()); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6881 | } | 
|  | 6882 |  | 
|  | 6883 | LLVM_DEBUG({ | 
|  | 6884 | if (!Visited.empty()) | 
|  | 6885 | dbgs() << "\n[Attributor] Finalized " << Visited.size() | 
|  | 6886 | << " abstract attributes.\n"; | 
|  | 6887 | }); | 
|  | 6888 |  | 
|  | 6889 | unsigned NumManifested = 0; | 
|  | 6890 | unsigned NumAtFixpoint = 0; | 
|  | 6891 | ChangeStatus ManifestChange = ChangeStatus::UNCHANGED; | 
|  | 6892 | for (AbstractAttribute *AA : AllAbstractAttributes) { | 
|  | 6893 | AbstractState &State = AA->getState(); | 
|  | 6894 |  | 
|  | 6895 | // If there is not already a fixpoint reached, we can now take the | 
|  | 6896 | // optimistic state. This is correct because we enforced a pessimistic one | 
|  | 6897 | // on abstract attributes that were transitively dependent on a changed one | 
|  | 6898 | // already above. | 
|  | 6899 | if (!State.isAtFixpoint()) | 
|  | 6900 | State.indicateOptimisticFixpoint(); | 
|  | 6901 |  | 
|  | 6902 | // If the state is invalid, we do not try to manifest it. | 
|  | 6903 | if (!State.isValidState()) | 
|  | 6904 | continue; | 
|  | 6905 |  | 
| Johannes Doerfert | 9a1a1f9 | 2019-08-14 21:25:08 +0000 | [diff] [blame] | 6906 | // Skip dead code. | 
|  | 6907 | if (isAssumedDead(*AA, nullptr)) | 
|  | 6908 | continue; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6909 | // Manifest the state and record if we changed the IR. | 
|  | 6910 | ChangeStatus LocalChange = AA->manifest(*this); | 
| Johannes Doerfert | d1b79e0 | 2019-08-07 22:46:11 +0000 | [diff] [blame] | 6911 | if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled()) | 
|  | 6912 | AA->trackStatistics(); | 
|  | 6913 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6914 | ManifestChange = ManifestChange | LocalChange; | 
|  | 6915 |  | 
|  | 6916 | NumAtFixpoint++; | 
|  | 6917 | NumManifested += (LocalChange == ChangeStatus::CHANGED); | 
|  | 6918 | } | 
|  | 6919 |  | 
|  | 6920 | (void)NumManifested; | 
|  | 6921 | (void)NumAtFixpoint; | 
|  | 6922 | LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested | 
|  | 6923 | << " arguments while " << NumAtFixpoint | 
|  | 6924 | << " were in a valid fixpoint state\n"); | 
|  | 6925 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 6926 | NumAttributesManifested += NumManifested; | 
|  | 6927 | NumAttributesValidFixpoint += NumAtFixpoint; | 
|  | 6928 |  | 
| Fangrui Song | f182617 | 2019-08-20 07:21:43 +0000 | [diff] [blame] | 6929 | (void)NumFinalAAs; | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 6930 | assert(NumFinalAAs == AllAbstractAttributes.size() && | 
|  | 6931 | "Expected the final number of abstract attributes to remain " | 
|  | 6932 | "unchanged!"); | 
| Johannes Doerfert | 39681e7 | 2019-08-27 04:57:54 +0000 | [diff] [blame] | 6933 |  | 
|  | 6934 | // Delete stuff at the end to avoid invalid references and a nice order. | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 6935 | { | 
|  | 6936 | LLVM_DEBUG(dbgs() << "\n[Attributor] Delete at least " | 
|  | 6937 | << ToBeDeletedFunctions.size() << " functions and " | 
|  | 6938 | << ToBeDeletedBlocks.size() << " blocks and " | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 6939 | << ToBeDeletedInsts.size() << " instructions and " | 
|  | 6940 | << ToBeChangedUses.size() << " uses\n"); | 
|  | 6941 |  | 
| Alina Sbirlea | 9e66c4e | 2020-01-23 14:21:08 -0800 | [diff] [blame] | 6942 | SmallVector<WeakTrackingVH, 32> DeadInsts; | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 6943 | SmallVector<Instruction *, 32> TerminatorsToFold; | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 6944 |  | 
|  | 6945 | for (auto &It : ToBeChangedUses) { | 
|  | 6946 | Use *U = It.first; | 
|  | 6947 | Value *NewV = It.second; | 
|  | 6948 | Value *OldV = U->get(); | 
|  | 6949 | LLVM_DEBUG(dbgs() << "Use " << *NewV << " in " << *U->getUser() | 
|  | 6950 | << " instead of " << *OldV << "\n"); | 
|  | 6951 | U->set(NewV); | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 6952 | if (Instruction *I = dyn_cast<Instruction>(OldV)) { | 
|  | 6953 | CGModifiedFunctions.insert(I->getFunction()); | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 6954 | if (!isa<PHINode>(I) && !ToBeDeletedInsts.count(I) && | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 6955 | isInstructionTriviallyDead(I)) | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 6956 | DeadInsts.push_back(I); | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 6957 | } | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 6958 | if (isa<Constant>(NewV) && isa<BranchInst>(U->getUser())) { | 
|  | 6959 | Instruction *UserI = cast<Instruction>(U->getUser()); | 
|  | 6960 | if (isa<UndefValue>(NewV)) { | 
| Hideto Ueno | cb5eb13 | 2019-12-27 02:39:37 +0900 | [diff] [blame] | 6961 | ToBeChangedToUnreachableInsts.insert(UserI); | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 6962 | } else { | 
|  | 6963 | TerminatorsToFold.push_back(UserI); | 
|  | 6964 | } | 
|  | 6965 | } | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 6966 | } | 
| Johannes Doerfert | a4088c7 | 2020-01-07 16:01:57 -0600 | [diff] [blame] | 6967 | for (auto &V : InvokeWithDeadSuccessor) | 
|  | 6968 | if (InvokeInst *II = dyn_cast_or_null<InvokeInst>(V)) { | 
|  | 6969 | bool UnwindBBIsDead = II->hasFnAttr(Attribute::NoUnwind); | 
|  | 6970 | bool NormalBBIsDead = II->hasFnAttr(Attribute::NoReturn); | 
|  | 6971 | bool Invoke2CallAllowed = | 
|  | 6972 | !AAIsDeadFunction::mayCatchAsynchronousExceptions( | 
|  | 6973 | *II->getFunction()); | 
|  | 6974 | assert((UnwindBBIsDead || NormalBBIsDead) && | 
|  | 6975 | "Invoke does not have dead successors!"); | 
|  | 6976 | BasicBlock *BB = II->getParent(); | 
|  | 6977 | BasicBlock *NormalDestBB = II->getNormalDest(); | 
|  | 6978 | if (UnwindBBIsDead) { | 
|  | 6979 | Instruction *NormalNextIP = &NormalDestBB->front(); | 
|  | 6980 | if (Invoke2CallAllowed) { | 
|  | 6981 | changeToCall(II); | 
|  | 6982 | NormalNextIP = BB->getTerminator(); | 
|  | 6983 | } | 
|  | 6984 | if (NormalBBIsDead) | 
|  | 6985 | ToBeChangedToUnreachableInsts.insert(NormalNextIP); | 
|  | 6986 | } else { | 
|  | 6987 | assert(NormalBBIsDead && "Broken invariant!"); | 
|  | 6988 | if (!NormalDestBB->getUniquePredecessor()) | 
|  | 6989 | NormalDestBB = SplitBlockPredecessors(NormalDestBB, {BB}, ".dead"); | 
|  | 6990 | ToBeChangedToUnreachableInsts.insert(&NormalDestBB->front()); | 
|  | 6991 | } | 
|  | 6992 | } | 
| Johannes Doerfert | 1e46eb7 | 2020-01-07 15:10:30 -0600 | [diff] [blame] | 6993 | for (auto &V : ToBeChangedToUnreachableInsts) | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 6994 | if (Instruction *I = dyn_cast_or_null<Instruction>(V)) { | 
|  | 6995 | CGModifiedFunctions.insert(I->getFunction()); | 
| Johannes Doerfert | 1e46eb7 | 2020-01-07 15:10:30 -0600 | [diff] [blame] | 6996 | changeToUnreachable(I, /* UseLLVMTrap */ false); | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 6997 | } | 
|  | 6998 | for (Instruction *I : TerminatorsToFold) { | 
|  | 6999 | CGModifiedFunctions.insert(I->getFunction()); | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 7000 | ConstantFoldTerminator(I->getParent()); | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7001 | } | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 7002 |  | 
| Johannes Doerfert | 5429c82 | 2020-01-11 23:30:36 -0600 | [diff] [blame] | 7003 | for (auto &V : ToBeDeletedInsts) { | 
|  | 7004 | if (Instruction *I = dyn_cast_or_null<Instruction>(V)) { | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7005 | CGModifiedFunctions.insert(I->getFunction()); | 
| Johannes Doerfert | 5429c82 | 2020-01-11 23:30:36 -0600 | [diff] [blame] | 7006 | I->replaceAllUsesWith(UndefValue::get(I->getType())); | 
|  | 7007 | if (!isa<PHINode>(I) && isInstructionTriviallyDead(I)) | 
|  | 7008 | DeadInsts.push_back(I); | 
|  | 7009 | else | 
|  | 7010 | I->eraseFromParent(); | 
|  | 7011 | } | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 7012 | } | 
|  | 7013 |  | 
|  | 7014 | RecursivelyDeleteTriviallyDeadInstructions(DeadInsts); | 
| Johannes Doerfert | b19cd27 | 2019-09-03 20:42:16 +0000 | [diff] [blame] | 7015 |  | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 7016 | if (unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) { | 
|  | 7017 | SmallVector<BasicBlock *, 8> ToBeDeletedBBs; | 
|  | 7018 | ToBeDeletedBBs.reserve(NumDeadBlocks); | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7019 | for (BasicBlock *BB : ToBeDeletedBlocks) { | 
|  | 7020 | CGModifiedFunctions.insert(BB->getParent()); | 
|  | 7021 | ToBeDeletedBBs.push_back(BB); | 
|  | 7022 | } | 
| Johannes Doerfert | 5e442a5 | 2019-10-30 17:34:59 -0500 | [diff] [blame] | 7023 | // Actually we do not delete the blocks but squash them into a single | 
|  | 7024 | // unreachable but untangling branches that jump here is something we need | 
|  | 7025 | // to do in a more generic way. | 
|  | 7026 | DetatchDeadBlocks(ToBeDeletedBBs, nullptr); | 
|  | 7027 | STATS_DECL(AAIsDead, BasicBlock, "Number of dead basic blocks deleted."); | 
|  | 7028 | BUILD_STAT_NAME(AAIsDead, BasicBlock) += ToBeDeletedBlocks.size(); | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 7029 | } | 
| Johannes Doerfert | b19cd27 | 2019-09-03 20:42:16 +0000 | [diff] [blame] | 7030 |  | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 7031 | // Identify dead internal functions and delete them. This happens outside | 
|  | 7032 | // the other fixpoint analysis as we might treat potentially dead functions | 
|  | 7033 | // as live to lower the number of iterations. If they happen to be dead, the | 
|  | 7034 | // below fixpoint loop will identify and eliminate them. | 
|  | 7035 | SmallVector<Function *, 8> InternalFns; | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7036 | for (Function *F : Functions) | 
|  | 7037 | if (F->hasLocalLinkage()) | 
|  | 7038 | InternalFns.push_back(F); | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 7039 |  | 
|  | 7040 | bool FoundDeadFn = true; | 
|  | 7041 | while (FoundDeadFn) { | 
|  | 7042 | FoundDeadFn = false; | 
|  | 7043 | for (unsigned u = 0, e = InternalFns.size(); u < e; ++u) { | 
|  | 7044 | Function *F = InternalFns[u]; | 
|  | 7045 | if (!F) | 
|  | 7046 | continue; | 
|  | 7047 |  | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 7048 | bool AllCallSitesKnown; | 
| Johannes Doerfert | 6b9ee2d | 2020-01-02 16:53:37 -0600 | [diff] [blame] | 7049 | if (!checkForAllCallSites( | 
|  | 7050 | [this](AbstractCallSite ACS) { | 
|  | 7051 | return ToBeDeletedFunctions.count( | 
|  | 7052 | ACS.getInstruction()->getFunction()); | 
|  | 7053 | }, | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 7054 | *F, true, nullptr, AllCallSitesKnown)) | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 7055 | continue; | 
|  | 7056 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 7057 | ToBeDeletedFunctions.insert(F); | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 7058 | InternalFns[u] = nullptr; | 
|  | 7059 | FoundDeadFn = true; | 
|  | 7060 | } | 
|  | 7061 | } | 
| Johannes Doerfert | 39681e7 | 2019-08-27 04:57:54 +0000 | [diff] [blame] | 7062 | } | 
|  | 7063 |  | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7064 | // Rewrite the functions as requested during manifest. | 
|  | 7065 | ManifestChange = | 
|  | 7066 | ManifestChange | rewriteFunctionSignatures(CGModifiedFunctions); | 
|  | 7067 |  | 
|  | 7068 | for (Function *Fn : CGModifiedFunctions) | 
|  | 7069 | CGUpdater.reanalyzeFunction(*Fn); | 
|  | 7070 |  | 
| Johannes Doerfert | d2d2fb1 | 2020-01-02 17:20:47 -0600 | [diff] [blame] | 7071 | STATS_DECL(AAIsDead, Function, "Number of dead functions deleted."); | 
|  | 7072 | BUILD_STAT_NAME(AAIsDead, Function) += ToBeDeletedFunctions.size(); | 
|  | 7073 |  | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7074 | for (Function *Fn : ToBeDeletedFunctions) | 
|  | 7075 | CGUpdater.removeFunction(*Fn); | 
| Johannes Doerfert | 6b9ee2d | 2020-01-02 16:53:37 -0600 | [diff] [blame] | 7076 |  | 
| Johannes Doerfert | bf11213 | 2019-08-29 01:29:44 +0000 | [diff] [blame] | 7077 | if (VerifyMaxFixpointIterations && | 
|  | 7078 | IterationCounter != MaxFixpointIterations) { | 
|  | 7079 | errs() << "\n[Attributor] Fixpoint iteration done after: " | 
|  | 7080 | << IterationCounter << "/" << MaxFixpointIterations | 
|  | 7081 | << " iterations\n"; | 
|  | 7082 | llvm_unreachable("The fixpoint was not reached with exactly the number of " | 
|  | 7083 | "specified iterations!"); | 
|  | 7084 | } | 
|  | 7085 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7086 | return ManifestChange; | 
|  | 7087 | } | 
|  | 7088 |  | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 7089 | bool Attributor::isValidFunctionSignatureRewrite( | 
|  | 7090 | Argument &Arg, ArrayRef<Type *> ReplacementTypes) { | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7091 |  | 
|  | 7092 | auto CallSiteCanBeChanged = [](AbstractCallSite ACS) { | 
|  | 7093 | // Forbid must-tail calls for now. | 
|  | 7094 | return !ACS.isCallbackCall() && !ACS.getCallSite().isMustTailCall(); | 
|  | 7095 | }; | 
|  | 7096 |  | 
|  | 7097 | Function *Fn = Arg.getParent(); | 
|  | 7098 | // Avoid var-arg functions for now. | 
|  | 7099 | if (Fn->isVarArg()) { | 
|  | 7100 | LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite var-args functions\n"); | 
|  | 7101 | return false; | 
|  | 7102 | } | 
|  | 7103 |  | 
|  | 7104 | // Avoid functions with complicated argument passing semantics. | 
|  | 7105 | AttributeList FnAttributeList = Fn->getAttributes(); | 
|  | 7106 | if (FnAttributeList.hasAttrSomewhere(Attribute::Nest) || | 
|  | 7107 | FnAttributeList.hasAttrSomewhere(Attribute::StructRet) || | 
|  | 7108 | FnAttributeList.hasAttrSomewhere(Attribute::InAlloca)) { | 
|  | 7109 | LLVM_DEBUG( | 
|  | 7110 | dbgs() << "[Attributor] Cannot rewrite due to complex attribute\n"); | 
|  | 7111 | return false; | 
|  | 7112 | } | 
|  | 7113 |  | 
|  | 7114 | // Avoid callbacks for now. | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 7115 | bool AllCallSitesKnown; | 
|  | 7116 | if (!checkForAllCallSites(CallSiteCanBeChanged, *Fn, true, nullptr, | 
|  | 7117 | AllCallSitesKnown)) { | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7118 | LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite all call sites\n"); | 
|  | 7119 | return false; | 
|  | 7120 | } | 
|  | 7121 |  | 
|  | 7122 | auto InstPred = [](Instruction &I) { | 
|  | 7123 | if (auto *CI = dyn_cast<CallInst>(&I)) | 
|  | 7124 | return !CI->isMustTailCall(); | 
|  | 7125 | return true; | 
|  | 7126 | }; | 
|  | 7127 |  | 
|  | 7128 | // Forbid must-tail calls for now. | 
|  | 7129 | // TODO: | 
|  | 7130 | bool AnyDead; | 
|  | 7131 | auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn); | 
|  | 7132 | if (!checkForAllInstructionsImpl(OpcodeInstMap, InstPred, nullptr, AnyDead, | 
|  | 7133 | {Instruction::Call})) { | 
|  | 7134 | LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite due to instructions\n"); | 
|  | 7135 | return false; | 
|  | 7136 | } | 
|  | 7137 |  | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 7138 | return true; | 
|  | 7139 | } | 
|  | 7140 |  | 
|  | 7141 | bool Attributor::registerFunctionSignatureRewrite( | 
|  | 7142 | Argument &Arg, ArrayRef<Type *> ReplacementTypes, | 
|  | 7143 | ArgumentReplacementInfo::CalleeRepairCBTy &&CalleeRepairCB, | 
|  | 7144 | ArgumentReplacementInfo::ACSRepairCBTy &&ACSRepairCB) { | 
|  | 7145 | LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in " | 
|  | 7146 | << Arg.getParent()->getName() << " with " | 
|  | 7147 | << ReplacementTypes.size() << " replacements\n"); | 
|  | 7148 | assert(isValidFunctionSignatureRewrite(Arg, ReplacementTypes) && | 
|  | 7149 | "Cannot register an invalid rewrite"); | 
|  | 7150 |  | 
|  | 7151 | Function *Fn = Arg.getParent(); | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7152 | SmallVectorImpl<ArgumentReplacementInfo *> &ARIs = ArgumentReplacementMap[Fn]; | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 7153 | if (ARIs.empty()) | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7154 | ARIs.resize(Fn->arg_size()); | 
|  | 7155 |  | 
|  | 7156 | // If we have a replacement already with less than or equal new arguments, | 
|  | 7157 | // ignore this request. | 
|  | 7158 | ArgumentReplacementInfo *&ARI = ARIs[Arg.getArgNo()]; | 
|  | 7159 | if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.size()) { | 
|  | 7160 | LLVM_DEBUG(dbgs() << "[Attributor] Existing rewrite is preferred\n"); | 
|  | 7161 | return false; | 
|  | 7162 | } | 
|  | 7163 |  | 
|  | 7164 | // If we have a replacement already but we like the new one better, delete | 
|  | 7165 | // the old. | 
|  | 7166 | if (ARI) | 
|  | 7167 | delete ARI; | 
|  | 7168 |  | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 7169 | LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in " | 
|  | 7170 | << Arg.getParent()->getName() << " with " | 
|  | 7171 | << ReplacementTypes.size() << " replacements\n"); | 
|  | 7172 |  | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7173 | // Remember the replacement. | 
|  | 7174 | ARI = new ArgumentReplacementInfo(*this, Arg, ReplacementTypes, | 
|  | 7175 | std::move(CalleeRepairCB), | 
|  | 7176 | std::move(ACSRepairCB)); | 
|  | 7177 |  | 
|  | 7178 | return true; | 
|  | 7179 | } | 
|  | 7180 |  | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7181 | ChangeStatus Attributor::rewriteFunctionSignatures( | 
|  | 7182 | SmallPtrSetImpl<Function *> &ModifiedFns) { | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7183 | ChangeStatus Changed = ChangeStatus::UNCHANGED; | 
|  | 7184 |  | 
|  | 7185 | for (auto &It : ArgumentReplacementMap) { | 
|  | 7186 | Function *OldFn = It.getFirst(); | 
|  | 7187 |  | 
|  | 7188 | // Deleted functions do not require rewrites. | 
|  | 7189 | if (ToBeDeletedFunctions.count(OldFn)) | 
|  | 7190 | continue; | 
|  | 7191 |  | 
|  | 7192 | const SmallVectorImpl<ArgumentReplacementInfo *> &ARIs = It.getSecond(); | 
|  | 7193 | assert(ARIs.size() == OldFn->arg_size() && "Inconsistent state!"); | 
|  | 7194 |  | 
|  | 7195 | SmallVector<Type *, 16> NewArgumentTypes; | 
|  | 7196 | SmallVector<AttributeSet, 16> NewArgumentAttributes; | 
|  | 7197 |  | 
|  | 7198 | // Collect replacement argument types and copy over existing attributes. | 
|  | 7199 | AttributeList OldFnAttributeList = OldFn->getAttributes(); | 
|  | 7200 | for (Argument &Arg : OldFn->args()) { | 
|  | 7201 | if (ArgumentReplacementInfo *ARI = ARIs[Arg.getArgNo()]) { | 
|  | 7202 | NewArgumentTypes.append(ARI->ReplacementTypes.begin(), | 
|  | 7203 | ARI->ReplacementTypes.end()); | 
|  | 7204 | NewArgumentAttributes.append(ARI->getNumReplacementArgs(), | 
|  | 7205 | AttributeSet()); | 
|  | 7206 | } else { | 
|  | 7207 | NewArgumentTypes.push_back(Arg.getType()); | 
|  | 7208 | NewArgumentAttributes.push_back( | 
|  | 7209 | OldFnAttributeList.getParamAttributes(Arg.getArgNo())); | 
|  | 7210 | } | 
|  | 7211 | } | 
|  | 7212 |  | 
|  | 7213 | FunctionType *OldFnTy = OldFn->getFunctionType(); | 
|  | 7214 | Type *RetTy = OldFnTy->getReturnType(); | 
|  | 7215 |  | 
|  | 7216 | // Construct the new function type using the new arguments types. | 
|  | 7217 | FunctionType *NewFnTy = | 
|  | 7218 | FunctionType::get(RetTy, NewArgumentTypes, OldFnTy->isVarArg()); | 
|  | 7219 |  | 
|  | 7220 | LLVM_DEBUG(dbgs() << "[Attributor] Function rewrite '" << OldFn->getName() | 
|  | 7221 | << "' from " << *OldFn->getFunctionType() << " to " | 
|  | 7222 | << *NewFnTy << "\n"); | 
|  | 7223 |  | 
|  | 7224 | // Create the new function body and insert it into the module. | 
|  | 7225 | Function *NewFn = Function::Create(NewFnTy, OldFn->getLinkage(), | 
|  | 7226 | OldFn->getAddressSpace(), ""); | 
|  | 7227 | OldFn->getParent()->getFunctionList().insert(OldFn->getIterator(), NewFn); | 
|  | 7228 | NewFn->takeName(OldFn); | 
|  | 7229 | NewFn->copyAttributesFrom(OldFn); | 
|  | 7230 |  | 
|  | 7231 | // Patch the pointer to LLVM function in debug info descriptor. | 
|  | 7232 | NewFn->setSubprogram(OldFn->getSubprogram()); | 
|  | 7233 | OldFn->setSubprogram(nullptr); | 
|  | 7234 |  | 
|  | 7235 | // Recompute the parameter attributes list based on the new arguments for | 
|  | 7236 | // the function. | 
|  | 7237 | LLVMContext &Ctx = OldFn->getContext(); | 
|  | 7238 | NewFn->setAttributes(AttributeList::get( | 
|  | 7239 | Ctx, OldFnAttributeList.getFnAttributes(), | 
|  | 7240 | OldFnAttributeList.getRetAttributes(), NewArgumentAttributes)); | 
|  | 7241 |  | 
|  | 7242 | // Since we have now created the new function, splice the body of the old | 
|  | 7243 | // function right into the new function, leaving the old rotting hulk of the | 
|  | 7244 | // function empty. | 
|  | 7245 | NewFn->getBasicBlockList().splice(NewFn->begin(), | 
|  | 7246 | OldFn->getBasicBlockList()); | 
|  | 7247 |  | 
| Johannes Doerfert | d2d2fb1 | 2020-01-02 17:20:47 -0600 | [diff] [blame] | 7248 | // Set of all "call-like" instructions that invoke the old function mapped | 
|  | 7249 | // to their new replacements. | 
|  | 7250 | SmallVector<std::pair<CallBase *, CallBase *>, 8> CallSitePairs; | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7251 |  | 
|  | 7252 | // Callback to create a new "call-like" instruction for a given one. | 
|  | 7253 | auto CallSiteReplacementCreator = [&](AbstractCallSite ACS) { | 
|  | 7254 | CallBase *OldCB = cast<CallBase>(ACS.getInstruction()); | 
|  | 7255 | const AttributeList &OldCallAttributeList = OldCB->getAttributes(); | 
|  | 7256 |  | 
|  | 7257 | // Collect the new argument operands for the replacement call site. | 
|  | 7258 | SmallVector<Value *, 16> NewArgOperands; | 
|  | 7259 | SmallVector<AttributeSet, 16> NewArgOperandAttributes; | 
|  | 7260 | for (unsigned OldArgNum = 0; OldArgNum < ARIs.size(); ++OldArgNum) { | 
|  | 7261 | unsigned NewFirstArgNum = NewArgOperands.size(); | 
| Ilya Biryukov | 4f82af8 | 2019-12-31 10:21:52 +0100 | [diff] [blame] | 7262 | (void)NewFirstArgNum; // only used inside assert. | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7263 | if (ArgumentReplacementInfo *ARI = ARIs[OldArgNum]) { | 
|  | 7264 | if (ARI->ACSRepairCB) | 
|  | 7265 | ARI->ACSRepairCB(*ARI, ACS, NewArgOperands); | 
|  | 7266 | assert(ARI->getNumReplacementArgs() + NewFirstArgNum == | 
|  | 7267 | NewArgOperands.size() && | 
|  | 7268 | "ACS repair callback did not provide as many operand as new " | 
|  | 7269 | "types were registered!"); | 
|  | 7270 | // TODO: Exose the attribute set to the ACS repair callback | 
|  | 7271 | NewArgOperandAttributes.append(ARI->ReplacementTypes.size(), | 
|  | 7272 | AttributeSet()); | 
|  | 7273 | } else { | 
|  | 7274 | NewArgOperands.push_back(ACS.getCallArgOperand(OldArgNum)); | 
|  | 7275 | NewArgOperandAttributes.push_back( | 
|  | 7276 | OldCallAttributeList.getParamAttributes(OldArgNum)); | 
|  | 7277 | } | 
|  | 7278 | } | 
|  | 7279 |  | 
|  | 7280 | assert(NewArgOperands.size() == NewArgOperandAttributes.size() && | 
|  | 7281 | "Mismatch # argument operands vs. # argument operand attributes!"); | 
|  | 7282 | assert(NewArgOperands.size() == NewFn->arg_size() && | 
|  | 7283 | "Mismatch # argument operands vs. # function arguments!"); | 
|  | 7284 |  | 
|  | 7285 | SmallVector<OperandBundleDef, 4> OperandBundleDefs; | 
|  | 7286 | OldCB->getOperandBundlesAsDefs(OperandBundleDefs); | 
|  | 7287 |  | 
|  | 7288 | // Create a new call or invoke instruction to replace the old one. | 
|  | 7289 | CallBase *NewCB; | 
|  | 7290 | if (InvokeInst *II = dyn_cast<InvokeInst>(OldCB)) { | 
|  | 7291 | NewCB = | 
|  | 7292 | InvokeInst::Create(NewFn, II->getNormalDest(), II->getUnwindDest(), | 
|  | 7293 | NewArgOperands, OperandBundleDefs, "", OldCB); | 
|  | 7294 | } else { | 
|  | 7295 | auto *NewCI = CallInst::Create(NewFn, NewArgOperands, OperandBundleDefs, | 
|  | 7296 | "", OldCB); | 
|  | 7297 | NewCI->setTailCallKind(cast<CallInst>(OldCB)->getTailCallKind()); | 
|  | 7298 | NewCB = NewCI; | 
|  | 7299 | } | 
|  | 7300 |  | 
|  | 7301 | // Copy over various properties and the new attributes. | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7302 | uint64_t W; | 
|  | 7303 | if (OldCB->extractProfTotalWeight(W)) | 
|  | 7304 | NewCB->setProfWeight(W); | 
|  | 7305 | NewCB->setCallingConv(OldCB->getCallingConv()); | 
|  | 7306 | NewCB->setDebugLoc(OldCB->getDebugLoc()); | 
|  | 7307 | NewCB->takeName(OldCB); | 
|  | 7308 | NewCB->setAttributes(AttributeList::get( | 
|  | 7309 | Ctx, OldCallAttributeList.getFnAttributes(), | 
|  | 7310 | OldCallAttributeList.getRetAttributes(), NewArgOperandAttributes)); | 
|  | 7311 |  | 
| Johannes Doerfert | d2d2fb1 | 2020-01-02 17:20:47 -0600 | [diff] [blame] | 7312 | CallSitePairs.push_back({OldCB, NewCB}); | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7313 | return true; | 
|  | 7314 | }; | 
|  | 7315 |  | 
|  | 7316 | // Use the CallSiteReplacementCreator to create replacement call sites. | 
| Johannes Doerfert | 368f7ee | 2019-12-30 16:12:36 -0600 | [diff] [blame] | 7317 | bool AllCallSitesKnown; | 
|  | 7318 | bool Success = checkForAllCallSites(CallSiteReplacementCreator, *OldFn, | 
|  | 7319 | true, nullptr, AllCallSitesKnown); | 
| Ilya Biryukov | 4f82af8 | 2019-12-31 10:21:52 +0100 | [diff] [blame] | 7320 | (void)Success; | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7321 | assert(Success && "Assumed call site replacement to succeed!"); | 
|  | 7322 |  | 
|  | 7323 | // Rewire the arguments. | 
|  | 7324 | auto OldFnArgIt = OldFn->arg_begin(); | 
|  | 7325 | auto NewFnArgIt = NewFn->arg_begin(); | 
|  | 7326 | for (unsigned OldArgNum = 0; OldArgNum < ARIs.size(); | 
|  | 7327 | ++OldArgNum, ++OldFnArgIt) { | 
|  | 7328 | if (ArgumentReplacementInfo *ARI = ARIs[OldArgNum]) { | 
|  | 7329 | if (ARI->CalleeRepairCB) | 
|  | 7330 | ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt); | 
|  | 7331 | NewFnArgIt += ARI->ReplacementTypes.size(); | 
|  | 7332 | } else { | 
|  | 7333 | NewFnArgIt->takeName(&*OldFnArgIt); | 
|  | 7334 | OldFnArgIt->replaceAllUsesWith(&*NewFnArgIt); | 
|  | 7335 | ++NewFnArgIt; | 
|  | 7336 | } | 
|  | 7337 | } | 
|  | 7338 |  | 
|  | 7339 | // Eliminate the instructions *after* we visited all of them. | 
| Johannes Doerfert | d2d2fb1 | 2020-01-02 17:20:47 -0600 | [diff] [blame] | 7340 | for (auto &CallSitePair : CallSitePairs) { | 
|  | 7341 | CallBase &OldCB = *CallSitePair.first; | 
|  | 7342 | CallBase &NewCB = *CallSitePair.second; | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7343 | // We do not modify the call graph here but simply reanalyze the old | 
|  | 7344 | // function. This should be revisited once the old PM is gone. | 
|  | 7345 | ModifiedFns.insert(OldCB.getFunction()); | 
| Johannes Doerfert | d2d2fb1 | 2020-01-02 17:20:47 -0600 | [diff] [blame] | 7346 | OldCB.replaceAllUsesWith(&NewCB); | 
|  | 7347 | OldCB.eraseFromParent(); | 
|  | 7348 | } | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7349 |  | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7350 | // Replace the function in the call graph (if any). | 
|  | 7351 | CGUpdater.replaceFunctionWith(*OldFn, *NewFn); | 
|  | 7352 |  | 
|  | 7353 | // If the old function was modified and needed to be reanalyzed, the new one | 
|  | 7354 | // does now. | 
|  | 7355 | if (ModifiedFns.erase(OldFn)) | 
|  | 7356 | ModifiedFns.insert(NewFn); | 
| Johannes Doerfert | d2d2fb1 | 2020-01-02 17:20:47 -0600 | [diff] [blame] | 7357 |  | 
| Johannes Doerfert | 7513363 | 2019-10-10 01:39:16 -0500 | [diff] [blame] | 7358 | Changed = ChangeStatus::CHANGED; | 
|  | 7359 | } | 
|  | 7360 |  | 
|  | 7361 | return Changed; | 
|  | 7362 | } | 
|  | 7363 |  | 
| Johannes Doerfert | 3ab9e8b | 2019-09-17 10:52:41 +0000 | [diff] [blame] | 7364 | void Attributor::initializeInformationCache(Function &F) { | 
|  | 7365 |  | 
|  | 7366 | // Walk all instructions to find interesting instructions that might be | 
|  | 7367 | // queried by abstract attributes during their initialization or update. | 
|  | 7368 | // This has to happen before we create attributes. | 
|  | 7369 | auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F]; | 
|  | 7370 | auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F]; | 
|  | 7371 |  | 
|  | 7372 | for (Instruction &I : instructions(&F)) { | 
|  | 7373 | bool IsInterestingOpcode = false; | 
|  | 7374 |  | 
|  | 7375 | // To allow easy access to all instructions in a function with a given | 
|  | 7376 | // opcode we store them in the InfoCache. As not all opcodes are interesting | 
|  | 7377 | // to concrete attributes we only cache the ones that are as identified in | 
|  | 7378 | // the following switch. | 
|  | 7379 | // Note: There are no concrete attributes now so this is initially empty. | 
|  | 7380 | switch (I.getOpcode()) { | 
|  | 7381 | default: | 
|  | 7382 | assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) && | 
|  | 7383 | "New call site/base instruction type needs to be known int the " | 
|  | 7384 | "Attributor."); | 
|  | 7385 | break; | 
|  | 7386 | case Instruction::Load: | 
|  | 7387 | // The alignment of a pointer is interesting for loads. | 
|  | 7388 | case Instruction::Store: | 
|  | 7389 | // The alignment of a pointer is interesting for stores. | 
|  | 7390 | case Instruction::Call: | 
|  | 7391 | case Instruction::CallBr: | 
|  | 7392 | case Instruction::Invoke: | 
|  | 7393 | case Instruction::CleanupRet: | 
|  | 7394 | case Instruction::CatchSwitch: | 
| Johannes Doerfert | 5732f56 | 2019-12-24 19:25:08 -0600 | [diff] [blame] | 7395 | case Instruction::AtomicRMW: | 
|  | 7396 | case Instruction::AtomicCmpXchg: | 
| Hideto Ueno | ef4febd | 2019-12-29 17:34:08 +0900 | [diff] [blame] | 7397 | case Instruction::Br: | 
| Johannes Doerfert | 3ab9e8b | 2019-09-17 10:52:41 +0000 | [diff] [blame] | 7398 | case Instruction::Resume: | 
|  | 7399 | case Instruction::Ret: | 
|  | 7400 | IsInterestingOpcode = true; | 
|  | 7401 | } | 
|  | 7402 | if (IsInterestingOpcode) | 
|  | 7403 | InstOpcodeMap[I.getOpcode()].push_back(&I); | 
|  | 7404 | if (I.mayReadOrWriteMemory()) | 
|  | 7405 | ReadOrWriteInsts.push_back(&I); | 
|  | 7406 | } | 
|  | 7407 | } | 
|  | 7408 |  | 
| Johannes Doerfert | 12173e6 | 2019-10-13 20:25:25 -0500 | [diff] [blame] | 7409 | void Attributor::recordDependence(const AbstractAttribute &FromAA, | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 7410 | const AbstractAttribute &ToAA, | 
|  | 7411 | DepClassTy DepClass) { | 
| Johannes Doerfert | 2dad729 | 2019-10-13 21:10:31 -0500 | [diff] [blame] | 7412 | if (FromAA.getState().isAtFixpoint()) | 
|  | 7413 | return; | 
|  | 7414 |  | 
| Johannes Doerfert | 680f638 | 2019-11-02 02:48:05 -0500 | [diff] [blame] | 7415 | if (DepClass == DepClassTy::REQUIRED) | 
|  | 7416 | QueryMap[&FromAA].RequiredAAs.insert( | 
|  | 7417 | const_cast<AbstractAttribute *>(&ToAA)); | 
|  | 7418 | else | 
|  | 7419 | QueryMap[&FromAA].OptionalAAs.insert( | 
|  | 7420 | const_cast<AbstractAttribute *>(&ToAA)); | 
| Johannes Doerfert | 2dad729 | 2019-10-13 21:10:31 -0500 | [diff] [blame] | 7421 | QueriedNonFixAA = true; | 
| Johannes Doerfert | 12173e6 | 2019-10-13 20:25:25 -0500 | [diff] [blame] | 7422 | } | 
|  | 7423 |  | 
| Hideto Ueno | 3bb5cbc | 2019-09-17 05:45:18 +0000 | [diff] [blame] | 7424 | void Attributor::identifyDefaultAbstractAttributes(Function &F) { | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 7425 | if (!VisitedFunctions.insert(&F).second) | 
|  | 7426 | return; | 
| Johannes Doerfert | c36e2eb | 2019-10-31 20:15:02 -0500 | [diff] [blame] | 7427 | if (F.isDeclaration()) | 
|  | 7428 | return; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7429 |  | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 7430 | IRPosition FPos = IRPosition::function(F); | 
|  | 7431 |  | 
| Johannes Doerfert | 305b961 | 2019-08-04 18:40:01 +0000 | [diff] [blame] | 7432 | // Check for dead BasicBlocks in every function. | 
| Johannes Doerfert | 21fe0a3 | 2019-08-06 00:55:11 +0000 | [diff] [blame] | 7433 | // We need dead instruction detection because we do not want to deal with | 
|  | 7434 | // broken IR in which SSA rules do not apply. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7435 | getOrCreateAAFor<AAIsDead>(FPos); | 
| Johannes Doerfert | 305b961 | 2019-08-04 18:40:01 +0000 | [diff] [blame] | 7436 |  | 
|  | 7437 | // Every function might be "will-return". | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7438 | getOrCreateAAFor<AAWillReturn>(FPos); | 
| Johannes Doerfert | 305b961 | 2019-08-04 18:40:01 +0000 | [diff] [blame] | 7439 |  | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 7440 | // Every function might contain instructions that cause "undefined behavior". | 
|  | 7441 | getOrCreateAAFor<AAUndefinedBehavior>(FPos); | 
|  | 7442 |  | 
| Stefan Stipanovic | 5360589 | 2019-06-27 11:27:54 +0000 | [diff] [blame] | 7443 | // Every function can be nounwind. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7444 | getOrCreateAAFor<AANoUnwind>(FPos); | 
| Stefan Stipanovic | 5360589 | 2019-06-27 11:27:54 +0000 | [diff] [blame] | 7445 |  | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 7446 | // Every function might be marked "nosync" | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7447 | getOrCreateAAFor<AANoSync>(FPos); | 
| Stefan Stipanovic | 0626367 | 2019-07-11 21:37:40 +0000 | [diff] [blame] | 7448 |  | 
| Hideto Ueno | 65bbaf9 | 2019-07-12 17:38:51 +0000 | [diff] [blame] | 7449 | // Every function might be "no-free". | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7450 | getOrCreateAAFor<AANoFree>(FPos); | 
| Hideto Ueno | 65bbaf9 | 2019-07-12 17:38:51 +0000 | [diff] [blame] | 7451 |  | 
| Johannes Doerfert | e83f303 | 2019-08-05 23:22:05 +0000 | [diff] [blame] | 7452 | // Every function might be "no-return". | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7453 | getOrCreateAAFor<AANoReturn>(FPos); | 
| Johannes Doerfert | e83f303 | 2019-08-05 23:22:05 +0000 | [diff] [blame] | 7454 |  | 
| Hideto Ueno | 63f6066 | 2019-09-21 15:13:19 +0000 | [diff] [blame] | 7455 | // Every function might be "no-recurse". | 
|  | 7456 | getOrCreateAAFor<AANoRecurse>(FPos); | 
|  | 7457 |  | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 7458 | // Every function might be "readnone/readonly/writeonly/...". | 
|  | 7459 | getOrCreateAAFor<AAMemoryBehavior>(FPos); | 
|  | 7460 |  | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 7461 | // Every function might be applicable for Heap-To-Stack conversion. | 
|  | 7462 | if (EnableHeapToStack) | 
|  | 7463 | getOrCreateAAFor<AAHeapToStack>(FPos); | 
|  | 7464 |  | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 7465 | // Return attributes are only appropriate if the return type is non void. | 
|  | 7466 | Type *ReturnType = F.getReturnType(); | 
|  | 7467 | if (!ReturnType->isVoidTy()) { | 
|  | 7468 | // Argument attribute "returned" --- Create only one per function even | 
|  | 7469 | // though it is an argument attribute. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7470 | getOrCreateAAFor<AAReturnedValues>(FPos); | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 7471 |  | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 7472 | IRPosition RetPos = IRPosition::returned(F); | 
|  | 7473 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 7474 | // Every returned value might be dead. | 
|  | 7475 | getOrCreateAAFor<AAIsDead>(RetPos); | 
|  | 7476 |  | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 7477 | // Every function might be simplified. | 
|  | 7478 | getOrCreateAAFor<AAValueSimplify>(RetPos); | 
|  | 7479 |  | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 7480 | if (ReturnType->isPointerTy()) { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 7481 |  | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 7482 | // Every function with pointer return type might be marked align. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7483 | getOrCreateAAFor<AAAlign>(RetPos); | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 7484 |  | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 7485 | // Every function with pointer return type might be marked nonnull. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7486 | getOrCreateAAFor<AANonNull>(RetPos); | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 7487 |  | 
|  | 7488 | // Every function with pointer return type might be marked noalias. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7489 | getOrCreateAAFor<AANoAlias>(RetPos); | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 7490 |  | 
|  | 7491 | // Every function with pointer return type might be marked | 
|  | 7492 | // dereferenceable. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7493 | getOrCreateAAFor<AADereferenceable>(RetPos); | 
| Stefan Stipanovic | 69ebb02 | 2019-07-22 19:36:27 +0000 | [diff] [blame] | 7494 | } | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 7495 | } | 
|  | 7496 |  | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 7497 | for (Argument &Arg : F.args()) { | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 7498 | IRPosition ArgPos = IRPosition::argument(Arg); | 
|  | 7499 |  | 
|  | 7500 | // Every argument might be simplified. | 
|  | 7501 | getOrCreateAAFor<AAValueSimplify>(ArgPos); | 
|  | 7502 |  | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 7503 | if (Arg.getType()->isPointerTy()) { | 
|  | 7504 | // Every argument with pointer type might be marked nonnull. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7505 | getOrCreateAAFor<AANonNull>(ArgPos); | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 7506 |  | 
| Hideto Ueno | cbab334 | 2019-08-29 05:52:00 +0000 | [diff] [blame] | 7507 | // Every argument with pointer type might be marked noalias. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7508 | getOrCreateAAFor<AANoAlias>(ArgPos); | 
| Hideto Ueno | cbab334 | 2019-08-29 05:52:00 +0000 | [diff] [blame] | 7509 |  | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 7510 | // Every argument with pointer type might be marked dereferenceable. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7511 | getOrCreateAAFor<AADereferenceable>(ArgPos); | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 7512 |  | 
|  | 7513 | // Every argument with pointer type might be marked align. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7514 | getOrCreateAAFor<AAAlign>(ArgPos); | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 7515 |  | 
|  | 7516 | // Every argument with pointer type might be marked nocapture. | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7517 | getOrCreateAAFor<AANoCapture>(ArgPos); | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 7518 |  | 
|  | 7519 | // Every argument with pointer type might be marked | 
|  | 7520 | // "readnone/readonly/writeonly/..." | 
|  | 7521 | getOrCreateAAFor<AAMemoryBehavior>(ArgPos); | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 7522 |  | 
|  | 7523 | // Every argument with pointer type might be marked nofree. | 
|  | 7524 | getOrCreateAAFor<AANoFree>(ArgPos); | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 7525 |  | 
|  | 7526 | // Every argument with pointer type might be privatizable (or promotable) | 
|  | 7527 | getOrCreateAAFor<AAPrivatizablePtr>(ArgPos); | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 7528 | } | 
| Johannes Doerfert | accd3e8 | 2019-07-08 23:27:20 +0000 | [diff] [blame] | 7529 | } | 
|  | 7530 |  | 
| Johannes Doerfert | 3ab9e8b | 2019-09-17 10:52:41 +0000 | [diff] [blame] | 7531 | auto CallSitePred = [&](Instruction &I) -> bool { | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 7532 | CallSite CS(&I); | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 7533 | if (Function *Callee = CS.getCalledFunction()) { | 
| Johannes Doerfert | c36e2eb | 2019-10-31 20:15:02 -0500 | [diff] [blame] | 7534 | // Skip declerations except if annotations on their call sites were | 
|  | 7535 | // explicitly requested. | 
| Johannes Doerfert | 139c9ef | 2019-12-13 23:41:02 -0600 | [diff] [blame] | 7536 | if (!AnnotateDeclarationCallSites && Callee->isDeclaration() && | 
|  | 7537 | !Callee->hasMetadata(LLVMContext::MD_callback)) | 
| Johannes Doerfert | c36e2eb | 2019-10-31 20:15:02 -0500 | [diff] [blame] | 7538 | return true; | 
|  | 7539 |  | 
|  | 7540 | if (!Callee->getReturnType()->isVoidTy() && !CS->use_empty()) { | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 7541 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 7542 | IRPosition CSRetPos = IRPosition::callsite_returned(CS); | 
|  | 7543 |  | 
|  | 7544 | // Call site return values might be dead. | 
|  | 7545 | getOrCreateAAFor<AAIsDead>(CSRetPos); | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 7546 |  | 
|  | 7547 | // Call site return integer values might be limited by a constant range. | 
|  | 7548 | if (Callee->getReturnType()->isIntegerTy()) { | 
|  | 7549 | getOrCreateAAFor<AAValueConstantRange>(CSRetPos); | 
|  | 7550 | } | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 7551 | } | 
|  | 7552 |  | 
| Johannes Doerfert | 2888019 | 2019-12-31 00:57:00 -0600 | [diff] [blame] | 7553 | for (int i = 0, e = CS.getNumArgOperands(); i < e; i++) { | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 7554 |  | 
|  | 7555 | IRPosition CSArgPos = IRPosition::callsite_argument(CS, i); | 
|  | 7556 |  | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 7557 | // Every call site argument might be dead. | 
|  | 7558 | getOrCreateAAFor<AAIsDead>(CSArgPos); | 
|  | 7559 |  | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 7560 | // Call site argument might be simplified. | 
|  | 7561 | getOrCreateAAFor<AAValueSimplify>(CSArgPos); | 
|  | 7562 |  | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 7563 | if (!CS.getArgument(i)->getType()->isPointerTy()) | 
|  | 7564 | continue; | 
|  | 7565 |  | 
|  | 7566 | // Call site argument attribute "non-null". | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7567 | getOrCreateAAFor<AANonNull>(CSArgPos); | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 7568 |  | 
| Hideto Ueno | cbab334 | 2019-08-29 05:52:00 +0000 | [diff] [blame] | 7569 | // Call site argument attribute "no-alias". | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7570 | getOrCreateAAFor<AANoAlias>(CSArgPos); | 
| Hideto Ueno | cbab334 | 2019-08-29 05:52:00 +0000 | [diff] [blame] | 7571 |  | 
| Hideto Ueno | 19c07af | 2019-07-23 08:16:17 +0000 | [diff] [blame] | 7572 | // Call site argument attribute "dereferenceable". | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7573 | getOrCreateAAFor<AADereferenceable>(CSArgPos); | 
| Hideto Ueno | e7bea9b | 2019-07-28 07:04:01 +0000 | [diff] [blame] | 7574 |  | 
|  | 7575 | // Call site argument attribute "align". | 
| Johannes Doerfert | 97fd582 | 2019-09-04 16:26:20 +0000 | [diff] [blame] | 7576 | getOrCreateAAFor<AAAlign>(CSArgPos); | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 7577 |  | 
| Johannes Doerfert | 2888019 | 2019-12-31 00:57:00 -0600 | [diff] [blame] | 7578 | // Call site argument attribute | 
|  | 7579 | // "readnone/readonly/writeonly/..." | 
|  | 7580 | getOrCreateAAFor<AAMemoryBehavior>(CSArgPos); | 
|  | 7581 |  | 
| Hideto Ueno | 4ecf255 | 2019-12-12 13:42:40 +0000 | [diff] [blame] | 7582 | // Call site argument attribute "nofree". | 
|  | 7583 | getOrCreateAAFor<AANoFree>(CSArgPos); | 
| Hideto Ueno | 54869ec | 2019-07-15 06:49:04 +0000 | [diff] [blame] | 7584 | } | 
|  | 7585 | } | 
| Johannes Doerfert | 3ab9e8b | 2019-09-17 10:52:41 +0000 | [diff] [blame] | 7586 | return true; | 
|  | 7587 | }; | 
|  | 7588 |  | 
|  | 7589 | auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F); | 
|  | 7590 | bool Success, AnyDead = false; | 
|  | 7591 | Success = checkForAllInstructionsImpl( | 
|  | 7592 | OpcodeInstMap, CallSitePred, nullptr, AnyDead, | 
|  | 7593 | {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr, | 
|  | 7594 | (unsigned)Instruction::Call}); | 
|  | 7595 | (void)Success; | 
|  | 7596 | assert(Success && !AnyDead && "Expected the check call to be successful!"); | 
|  | 7597 |  | 
|  | 7598 | auto LoadStorePred = [&](Instruction &I) -> bool { | 
|  | 7599 | if (isa<LoadInst>(I)) | 
|  | 7600 | getOrCreateAAFor<AAAlign>( | 
|  | 7601 | IRPosition::value(*cast<LoadInst>(I).getPointerOperand())); | 
|  | 7602 | else | 
|  | 7603 | getOrCreateAAFor<AAAlign>( | 
|  | 7604 | IRPosition::value(*cast<StoreInst>(I).getPointerOperand())); | 
|  | 7605 | return true; | 
|  | 7606 | }; | 
|  | 7607 | Success = checkForAllInstructionsImpl( | 
|  | 7608 | OpcodeInstMap, LoadStorePred, nullptr, AnyDead, | 
|  | 7609 | {(unsigned)Instruction::Load, (unsigned)Instruction::Store}); | 
|  | 7610 | (void)Success; | 
|  | 7611 | assert(Success && !AnyDead && "Expected the check call to be successful!"); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7612 | } | 
|  | 7613 |  | 
|  | 7614 | /// Helpers to ease debugging through output streams and print calls. | 
|  | 7615 | /// | 
|  | 7616 | ///{ | 
|  | 7617 | raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) { | 
|  | 7618 | return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged"); | 
|  | 7619 | } | 
|  | 7620 |  | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 7621 | raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) { | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7622 | switch (AP) { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 7623 | case IRPosition::IRP_INVALID: | 
|  | 7624 | return OS << "inv"; | 
|  | 7625 | case IRPosition::IRP_FLOAT: | 
|  | 7626 | return OS << "flt"; | 
|  | 7627 | case IRPosition::IRP_RETURNED: | 
|  | 7628 | return OS << "fn_ret"; | 
|  | 7629 | case IRPosition::IRP_CALL_SITE_RETURNED: | 
|  | 7630 | return OS << "cs_ret"; | 
|  | 7631 | case IRPosition::IRP_FUNCTION: | 
|  | 7632 | return OS << "fn"; | 
|  | 7633 | case IRPosition::IRP_CALL_SITE: | 
|  | 7634 | return OS << "cs"; | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 7635 | case IRPosition::IRP_ARGUMENT: | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7636 | return OS << "arg"; | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 7637 | case IRPosition::IRP_CALL_SITE_ARGUMENT: | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7638 | return OS << "cs_arg"; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7639 | } | 
|  | 7640 | llvm_unreachable("Unknown attribute position!"); | 
|  | 7641 | } | 
|  | 7642 |  | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 7643 | raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) { | 
| Johannes Doerfert | 710ebb0 | 2019-08-14 21:18:01 +0000 | [diff] [blame] | 7644 | const Value &AV = Pos.getAssociatedValue(); | 
|  | 7645 | return OS << "{" << Pos.getPositionKind() << ":" << AV.getName() << " [" | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 7646 | << Pos.getAnchorValue().getName() << "@" << Pos.getArgNo() << "]}"; | 
|  | 7647 | } | 
|  | 7648 |  | 
| Johannes Doerfert | 1a74645 | 2019-10-20 22:28:49 -0500 | [diff] [blame] | 7649 | template <typename base_ty, base_ty BestState, base_ty WorstState> | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 7650 | raw_ostream & | 
|  | 7651 | llvm::operator<<(raw_ostream &OS, | 
|  | 7652 | const IntegerStateBase<base_ty, BestState, WorstState> &S) { | 
| Johannes Doerfert | acc8079 | 2019-08-12 22:07:34 +0000 | [diff] [blame] | 7653 | return OS << "(" << S.getKnown() << "-" << S.getAssumed() << ")" | 
|  | 7654 | << static_cast<const AbstractState &>(S); | 
|  | 7655 | } | 
|  | 7656 |  | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 7657 | raw_ostream &llvm::operator<<(raw_ostream &OS, const IntegerRangeState &S) { | 
|  | 7658 | OS << "range-state(" << S.getBitWidth() << ")<"; | 
|  | 7659 | S.getKnown().print(OS); | 
|  | 7660 | OS << " / "; | 
|  | 7661 | S.getAssumed().print(OS); | 
|  | 7662 | OS << ">"; | 
|  | 7663 |  | 
|  | 7664 | return OS << static_cast<const AbstractState &>(S); | 
|  | 7665 | } | 
|  | 7666 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7667 | raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) { | 
|  | 7668 | return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : "")); | 
|  | 7669 | } | 
|  | 7670 |  | 
|  | 7671 | raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) { | 
|  | 7672 | AA.print(OS); | 
|  | 7673 | return OS; | 
|  | 7674 | } | 
|  | 7675 |  | 
|  | 7676 | void AbstractAttribute::print(raw_ostream &OS) const { | 
| Johannes Doerfert | fb69f76 | 2019-08-05 23:32:31 +0000 | [diff] [blame] | 7677 | OS << "[P: " << getIRPosition() << "][" << getAsStr() << "][S: " << getState() | 
|  | 7678 | << "]"; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7679 | } | 
|  | 7680 | ///} | 
|  | 7681 |  | 
|  | 7682 | /// ---------------------------------------------------------------------------- | 
|  | 7683 | ///                       Pass (Manager) Boilerplate | 
|  | 7684 | /// ---------------------------------------------------------------------------- | 
|  | 7685 |  | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7686 | static bool runAttributorOnFunctions(InformationCache &InfoCache, | 
|  | 7687 | SetVector<Function *> &Functions, | 
|  | 7688 | AnalysisGetter &AG, | 
|  | 7689 | CallGraphUpdater &CGUpdater) { | 
|  | 7690 | if (DisableAttributor || Functions.empty()) | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7691 | return false; | 
|  | 7692 |  | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7693 | LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << Functions.size() | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7694 | << " functions.\n"); | 
|  | 7695 |  | 
|  | 7696 | // Create an Attributor and initially empty information cache that is filled | 
|  | 7697 | // while we identify default attribute opportunities. | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7698 | Attributor A(Functions, InfoCache, CGUpdater, DepRecInterval); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7699 |  | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7700 | for (Function *F : Functions) | 
|  | 7701 | A.initializeInformationCache(*F); | 
| Johannes Doerfert | 3ab9e8b | 2019-09-17 10:52:41 +0000 | [diff] [blame] | 7702 |  | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7703 | for (Function *F : Functions) { | 
|  | 7704 | if (F->hasExactDefinition()) | 
| Johannes Doerfert | b0412e4 | 2019-09-04 16:16:13 +0000 | [diff] [blame] | 7705 | NumFnWithExactDefinition++; | 
|  | 7706 | else | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7707 | NumFnWithoutExactDefinition++; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7708 |  | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 7709 | // We look at internal functions only on-demand but if any use is not a | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7710 | // direct call or outside the current set of analyzed functions, we have to | 
|  | 7711 | // do it eagerly. | 
|  | 7712 | if (F->hasLocalLinkage()) { | 
|  | 7713 | if (llvm::all_of(F->uses(), [&Functions](const Use &U) { | 
|  | 7714 | ImmutableCallSite ICS(U.getUser()); | 
|  | 7715 | return ICS && ICS.isCallee(&U) && | 
|  | 7716 | Functions.count(const_cast<Function *>(ICS.getCaller())); | 
| Johannes Doerfert | 2f62206 | 2019-09-04 16:35:20 +0000 | [diff] [blame] | 7717 | })) | 
|  | 7718 | continue; | 
|  | 7719 | } | 
|  | 7720 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7721 | // Populate the Attributor with abstract attribute opportunities in the | 
|  | 7722 | // function and the information cache with IR information. | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7723 | A.identifyDefaultAbstractAttributes(*F); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7724 | } | 
|  | 7725 |  | 
| Johannes Doerfert | 77a9e61 | 2020-01-11 23:36:17 -0600 | [diff] [blame] | 7726 | ChangeStatus Changed = A.run(); | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7727 | assert(!verifyModule(*Functions.front()->getParent(), &errs()) && | 
|  | 7728 | "Module verification failed!"); | 
| Johannes Doerfert | 77a9e61 | 2020-01-11 23:36:17 -0600 | [diff] [blame] | 7729 | LLVM_DEBUG(dbgs() << "[Attributor] Done with " << Functions.size() | 
|  | 7730 | << " functions, result: " << Changed << ".\n"); | 
|  | 7731 | return Changed == ChangeStatus::CHANGED; | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7732 | } | 
|  | 7733 |  | 
|  | 7734 | PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) { | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7735 | FunctionAnalysisManager &FAM = | 
|  | 7736 | AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); | 
|  | 7737 | AnalysisGetter AG(FAM); | 
|  | 7738 |  | 
|  | 7739 | SetVector<Function *> Functions; | 
|  | 7740 | for (Function &F : M) | 
|  | 7741 | Functions.insert(&F); | 
|  | 7742 |  | 
|  | 7743 | CallGraphUpdater CGUpdater; | 
|  | 7744 | InformationCache InfoCache(M, AG, /* CGSCC */ nullptr); | 
|  | 7745 | if (runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater)) { | 
|  | 7746 | // FIXME: Think about passes we will preserve and add them here. | 
|  | 7747 | return PreservedAnalyses::none(); | 
|  | 7748 | } | 
|  | 7749 | return PreservedAnalyses::all(); | 
|  | 7750 | } | 
|  | 7751 |  | 
|  | 7752 | PreservedAnalyses AttributorCGSCCPass::run(LazyCallGraph::SCC &C, | 
|  | 7753 | CGSCCAnalysisManager &AM, | 
|  | 7754 | LazyCallGraph &CG, | 
|  | 7755 | CGSCCUpdateResult &UR) { | 
|  | 7756 | FunctionAnalysisManager &FAM = | 
|  | 7757 | AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager(); | 
|  | 7758 | AnalysisGetter AG(FAM); | 
|  | 7759 |  | 
|  | 7760 | SetVector<Function *> Functions; | 
|  | 7761 | for (LazyCallGraph::Node &N : C) | 
|  | 7762 | Functions.insert(&N.getFunction()); | 
|  | 7763 |  | 
|  | 7764 | if (Functions.empty()) | 
|  | 7765 | return PreservedAnalyses::all(); | 
|  | 7766 |  | 
|  | 7767 | Module &M = *Functions.back()->getParent(); | 
|  | 7768 | CallGraphUpdater CGUpdater; | 
|  | 7769 | CGUpdater.initialize(CG, C, AM, UR); | 
|  | 7770 | InformationCache InfoCache(M, AG, /* CGSCC */ &Functions); | 
|  | 7771 | if (runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater)) { | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7772 | // FIXME: Think about passes we will preserve and add them here. | 
|  | 7773 | return PreservedAnalyses::none(); | 
|  | 7774 | } | 
|  | 7775 | return PreservedAnalyses::all(); | 
|  | 7776 | } | 
|  | 7777 |  | 
|  | 7778 | namespace { | 
|  | 7779 |  | 
|  | 7780 | struct AttributorLegacyPass : public ModulePass { | 
|  | 7781 | static char ID; | 
|  | 7782 |  | 
|  | 7783 | AttributorLegacyPass() : ModulePass(ID) { | 
|  | 7784 | initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry()); | 
|  | 7785 | } | 
|  | 7786 |  | 
|  | 7787 | bool runOnModule(Module &M) override { | 
|  | 7788 | if (skipModule(M)) | 
|  | 7789 | return false; | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 7790 |  | 
| Hideto Ueno | 3bb5cbc | 2019-09-17 05:45:18 +0000 | [diff] [blame] | 7791 | AnalysisGetter AG; | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7792 | SetVector<Function *> Functions; | 
|  | 7793 | for (Function &F : M) | 
|  | 7794 | Functions.insert(&F); | 
|  | 7795 |  | 
|  | 7796 | CallGraphUpdater CGUpdater; | 
|  | 7797 | InformationCache InfoCache(M, AG, /* CGSCC */ nullptr); | 
|  | 7798 | return runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7799 | } | 
|  | 7800 |  | 
|  | 7801 | void getAnalysisUsage(AnalysisUsage &AU) const override { | 
|  | 7802 | // FIXME: Think about passes we will preserve and add them here. | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 7803 | AU.addRequired<TargetLibraryInfoWrapperPass>(); | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7804 | } | 
|  | 7805 | }; | 
|  | 7806 |  | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7807 | struct AttributorCGSCCLegacyPass : public CallGraphSCCPass { | 
|  | 7808 | CallGraphUpdater CGUpdater; | 
|  | 7809 | static char ID; | 
|  | 7810 |  | 
|  | 7811 | AttributorCGSCCLegacyPass() : CallGraphSCCPass(ID) { | 
|  | 7812 | initializeAttributorCGSCCLegacyPassPass(*PassRegistry::getPassRegistry()); | 
|  | 7813 | } | 
|  | 7814 |  | 
|  | 7815 | bool runOnSCC(CallGraphSCC &SCC) override { | 
|  | 7816 | if (skipSCC(SCC)) | 
|  | 7817 | return false; | 
|  | 7818 |  | 
|  | 7819 | SetVector<Function *> Functions; | 
|  | 7820 | for (CallGraphNode *CGN : SCC) | 
|  | 7821 | if (Function *Fn = CGN->getFunction()) | 
|  | 7822 | if (!Fn->isDeclaration()) | 
|  | 7823 | Functions.insert(Fn); | 
|  | 7824 |  | 
|  | 7825 | if (Functions.empty()) | 
|  | 7826 | return false; | 
|  | 7827 |  | 
|  | 7828 | AnalysisGetter AG; | 
|  | 7829 | CallGraph &CG = const_cast<CallGraph &>(SCC.getCallGraph()); | 
|  | 7830 | CGUpdater.initialize(CG, SCC); | 
|  | 7831 | Module &M = *Functions.back()->getParent(); | 
|  | 7832 | InformationCache InfoCache(M, AG, /* CGSCC */ &Functions); | 
|  | 7833 | return runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater); | 
|  | 7834 | } | 
|  | 7835 |  | 
|  | 7836 | bool doFinalization(CallGraph &CG) override { return CGUpdater.finalize(); } | 
|  | 7837 |  | 
|  | 7838 | void getAnalysisUsage(AnalysisUsage &AU) const override { | 
|  | 7839 | // FIXME: Think about passes we will preserve and add them here. | 
|  | 7840 | AU.addRequired<TargetLibraryInfoWrapperPass>(); | 
|  | 7841 | CallGraphSCCPass::getAnalysisUsage(AU); | 
|  | 7842 | } | 
|  | 7843 | }; | 
|  | 7844 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7845 | } // end anonymous namespace | 
|  | 7846 |  | 
|  | 7847 | Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); } | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7848 | Pass *llvm::createAttributorCGSCCLegacyPass() { | 
|  | 7849 | return new AttributorCGSCCLegacyPass(); | 
|  | 7850 | } | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 7851 |  | 
|  | 7852 | char AttributorLegacyPass::ID = 0; | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 7853 | char AttributorCGSCCLegacyPass::ID = 0; | 
| Johannes Doerfert | 2402062 | 2019-08-05 23:30:01 +0000 | [diff] [blame] | 7854 |  | 
|  | 7855 | const char AAReturnedValues::ID = 0; | 
|  | 7856 | const char AANoUnwind::ID = 0; | 
|  | 7857 | const char AANoSync::ID = 0; | 
| Johannes Doerfert | eccdf08 | 2019-08-05 23:35:12 +0000 | [diff] [blame] | 7858 | const char AANoFree::ID = 0; | 
| Johannes Doerfert | 2402062 | 2019-08-05 23:30:01 +0000 | [diff] [blame] | 7859 | const char AANonNull::ID = 0; | 
|  | 7860 | const char AANoRecurse::ID = 0; | 
|  | 7861 | const char AAWillReturn::ID = 0; | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 7862 | const char AAUndefinedBehavior::ID = 0; | 
| Johannes Doerfert | 2402062 | 2019-08-05 23:30:01 +0000 | [diff] [blame] | 7863 | const char AANoAlias::ID = 0; | 
| Pankaj Gode | 04945c9 | 2019-11-22 18:40:47 +0530 | [diff] [blame] | 7864 | const char AAReachability::ID = 0; | 
| Johannes Doerfert | 2402062 | 2019-08-05 23:30:01 +0000 | [diff] [blame] | 7865 | const char AANoReturn::ID = 0; | 
|  | 7866 | const char AAIsDead::ID = 0; | 
|  | 7867 | const char AADereferenceable::ID = 0; | 
|  | 7868 | const char AAAlign::ID = 0; | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 7869 | const char AANoCapture::ID = 0; | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 7870 | const char AAValueSimplify::ID = 0; | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 7871 | const char AAHeapToStack::ID = 0; | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 7872 | const char AAPrivatizablePtr::ID = 0; | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 7873 | const char AAMemoryBehavior::ID = 0; | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 7874 | const char AAValueConstantRange::ID = 0; | 
| Johannes Doerfert | 2402062 | 2019-08-05 23:30:01 +0000 | [diff] [blame] | 7875 |  | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 7876 | // Macro magic to create the static generator function for attributes that | 
|  | 7877 | // follow the naming scheme. | 
|  | 7878 |  | 
|  | 7879 | #define SWITCH_PK_INV(CLASS, PK, POS_NAME)                                     \ | 
|  | 7880 | case IRPosition::PK:                                                         \ | 
|  | 7881 | llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!"); | 
|  | 7882 |  | 
|  | 7883 | #define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX)                               \ | 
|  | 7884 | case IRPosition::PK:                                                         \ | 
|  | 7885 | AA = new CLASS##SUFFIX(IRP);                                               \ | 
|  | 7886 | break; | 
|  | 7887 |  | 
|  | 7888 | #define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                 \ | 
|  | 7889 | CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \ | 
|  | 7890 | CLASS *AA = nullptr;                                                       \ | 
|  | 7891 | switch (IRP.getPositionKind()) {                                           \ | 
|  | 7892 | SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \ | 
|  | 7893 | SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating")                              \ | 
|  | 7894 | SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument")                           \ | 
|  | 7895 | SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned")                           \ | 
|  | 7896 | SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned")       \ | 
|  | 7897 | SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument")       \ | 
|  | 7898 | SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \ | 
|  | 7899 | SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite)                    \ | 
|  | 7900 | }                                                                          \ | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 7901 | return *AA;                                                                \ | 
|  | 7902 | } | 
|  | 7903 |  | 
|  | 7904 | #define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                    \ | 
|  | 7905 | CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \ | 
|  | 7906 | CLASS *AA = nullptr;                                                       \ | 
|  | 7907 | switch (IRP.getPositionKind()) {                                           \ | 
|  | 7908 | SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \ | 
|  | 7909 | SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function")                           \ | 
|  | 7910 | SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site")                         \ | 
|  | 7911 | SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating)                        \ | 
|  | 7912 | SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument)                     \ | 
|  | 7913 | SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned)                     \ | 
|  | 7914 | SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned)   \ | 
|  | 7915 | SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument)   \ | 
|  | 7916 | }                                                                          \ | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 7917 | return *AA;                                                                \ | 
|  | 7918 | } | 
|  | 7919 |  | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 7920 | #define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                      \ | 
|  | 7921 | CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \ | 
|  | 7922 | CLASS *AA = nullptr;                                                       \ | 
|  | 7923 | switch (IRP.getPositionKind()) {                                           \ | 
|  | 7924 | SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \ | 
|  | 7925 | SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \ | 
|  | 7926 | SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite)                    \ | 
|  | 7927 | SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating)                        \ | 
|  | 7928 | SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument)                     \ | 
|  | 7929 | SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned)                     \ | 
|  | 7930 | SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned)   \ | 
|  | 7931 | SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument)   \ | 
|  | 7932 | }                                                                          \ | 
|  | 7933 | return *AA;                                                                \ | 
|  | 7934 | } | 
|  | 7935 |  | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 7936 | #define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)            \ | 
|  | 7937 | CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \ | 
|  | 7938 | CLASS *AA = nullptr;                                                       \ | 
|  | 7939 | switch (IRP.getPositionKind()) {                                           \ | 
|  | 7940 | SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \ | 
|  | 7941 | SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument")                           \ | 
|  | 7942 | SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating")                              \ | 
|  | 7943 | SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned")                           \ | 
|  | 7944 | SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned")       \ | 
|  | 7945 | SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument")       \ | 
|  | 7946 | SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site")                         \ | 
|  | 7947 | SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \ | 
|  | 7948 | }                                                                          \ | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 7949 | return *AA;                                                                \ | 
|  | 7950 | } | 
|  | 7951 |  | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 7952 | #define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                  \ | 
|  | 7953 | CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \ | 
|  | 7954 | CLASS *AA = nullptr;                                                       \ | 
|  | 7955 | switch (IRP.getPositionKind()) {                                           \ | 
|  | 7956 | SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \ | 
|  | 7957 | SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned")                           \ | 
|  | 7958 | SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \ | 
|  | 7959 | SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite)                    \ | 
|  | 7960 | SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating)                        \ | 
|  | 7961 | SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument)                     \ | 
|  | 7962 | SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned)   \ | 
|  | 7963 | SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument)   \ | 
|  | 7964 | }                                                                          \ | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 7965 | return *AA;                                                                \ | 
|  | 7966 | } | 
|  | 7967 |  | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 7968 | CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind) | 
|  | 7969 | CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync) | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 7970 | CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse) | 
|  | 7971 | CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn) | 
|  | 7972 | CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn) | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 7973 | CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReturnedValues) | 
|  | 7974 |  | 
|  | 7975 | CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull) | 
|  | 7976 | CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias) | 
| Johannes Doerfert | 89c2e73 | 2019-10-30 17:20:20 -0500 | [diff] [blame] | 7977 | CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPrivatizablePtr) | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 7978 | CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable) | 
|  | 7979 | CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign) | 
| Johannes Doerfert | 7516a5e | 2019-09-03 20:37:24 +0000 | [diff] [blame] | 7980 | CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoCapture) | 
| Hideto Ueno | 188f9a3 | 2020-01-15 15:25:52 +0900 | [diff] [blame] | 7981 | CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueConstantRange) | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 7982 |  | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 7983 | CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify) | 
| Johannes Doerfert | cd4aab4 | 2019-10-13 03:08:18 -0500 | [diff] [blame] | 7984 | CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead) | 
| Stefan Stipanovic | f35740d | 2019-11-02 16:35:38 +0100 | [diff] [blame] | 7985 | CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree) | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 7986 |  | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 7987 | CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAHeapToStack) | 
| Pankaj Gode | 04945c9 | 2019-11-22 18:40:47 +0530 | [diff] [blame] | 7988 | CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReachability) | 
| Johannes Doerfert | 58f324a | 2019-12-24 18:48:50 -0600 | [diff] [blame] | 7989 | CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUndefinedBehavior) | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 7990 |  | 
| Johannes Doerfert | 1097fab | 2019-10-07 21:07:57 +0000 | [diff] [blame] | 7991 | CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryBehavior) | 
|  | 7992 |  | 
| Johannes Doerfert | d4bea88 | 2019-10-07 23:28:54 +0000 | [diff] [blame] | 7993 | #undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 7994 | #undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION | 
| Johannes Doerfert | d4bea88 | 2019-10-07 23:28:54 +0000 | [diff] [blame] | 7995 | #undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 7996 | #undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION | 
| Hideto Ueno | f2b9dc4 | 2019-09-07 07:03:05 +0000 | [diff] [blame] | 7997 | #undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION | 
| Johannes Doerfert | 12cbbab | 2019-08-20 06:15:50 +0000 | [diff] [blame] | 7998 | #undef SWITCH_PK_CREATE | 
|  | 7999 | #undef SWITCH_PK_INV | 
|  | 8000 |  | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 8001 | INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor", | 
|  | 8002 | "Deduce and propagate attributes", false, false) | 
| Stefan Stipanovic | 431141c | 2019-09-15 21:47:41 +0000 | [diff] [blame] | 8003 | INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) | 
| Johannes Doerfert | aade782 | 2019-06-05 03:02:24 +0000 | [diff] [blame] | 8004 | INITIALIZE_PASS_END(AttributorLegacyPass, "attributor", | 
|  | 8005 | "Deduce and propagate attributes", false, false) | 
| Johannes Doerfert | b0c77c3 | 2019-11-27 00:30:12 -0600 | [diff] [blame] | 8006 | INITIALIZE_PASS_BEGIN(AttributorCGSCCLegacyPass, "attributor-cgscc", | 
|  | 8007 | "Deduce and propagate attributes (CGSCC pass)", false, | 
|  | 8008 | false) | 
|  | 8009 | INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) | 
|  | 8010 | INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) | 
|  | 8011 | INITIALIZE_PASS_END(AttributorCGSCCLegacyPass, "attributor-cgscc", | 
|  | 8012 | "Deduce and propagate attributes (CGSCC pass)", false, | 
|  | 8013 | false) |