| File: | src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Transforms/Utils/PredicateInfo.cpp |
| Warning: | line 593, column 21 Access to field 'AssumeInst' results in a dereference of a null pointer (loaded from variable 'PAssume') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | //===-- PredicateInfo.cpp - PredicateInfo Builder--------------------===// | ||||||||
| 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 the PredicateInfo class. | ||||||||
| 10 | // | ||||||||
| 11 | //===----------------------------------------------------------------===// | ||||||||
| 12 | |||||||||
| 13 | #include "llvm/Transforms/Utils/PredicateInfo.h" | ||||||||
| 14 | #include "llvm/ADT/DenseMap.h" | ||||||||
| 15 | #include "llvm/ADT/DepthFirstIterator.h" | ||||||||
| 16 | #include "llvm/ADT/STLExtras.h" | ||||||||
| 17 | #include "llvm/ADT/SmallPtrSet.h" | ||||||||
| 18 | #include "llvm/ADT/Statistic.h" | ||||||||
| 19 | #include "llvm/ADT/StringExtras.h" | ||||||||
| 20 | #include "llvm/Analysis/AssumptionCache.h" | ||||||||
| 21 | #include "llvm/Analysis/CFG.h" | ||||||||
| 22 | #include "llvm/IR/AssemblyAnnotationWriter.h" | ||||||||
| 23 | #include "llvm/IR/DataLayout.h" | ||||||||
| 24 | #include "llvm/IR/Dominators.h" | ||||||||
| 25 | #include "llvm/IR/GlobalVariable.h" | ||||||||
| 26 | #include "llvm/IR/IRBuilder.h" | ||||||||
| 27 | #include "llvm/IR/InstIterator.h" | ||||||||
| 28 | #include "llvm/IR/IntrinsicInst.h" | ||||||||
| 29 | #include "llvm/IR/LLVMContext.h" | ||||||||
| 30 | #include "llvm/IR/Metadata.h" | ||||||||
| 31 | #include "llvm/IR/Module.h" | ||||||||
| 32 | #include "llvm/IR/PatternMatch.h" | ||||||||
| 33 | #include "llvm/InitializePasses.h" | ||||||||
| 34 | #include "llvm/Support/CommandLine.h" | ||||||||
| 35 | #include "llvm/Support/Debug.h" | ||||||||
| 36 | #include "llvm/Support/DebugCounter.h" | ||||||||
| 37 | #include "llvm/Support/FormattedStream.h" | ||||||||
| 38 | #include "llvm/Transforms/Utils.h" | ||||||||
| 39 | #include <algorithm> | ||||||||
| 40 | #define DEBUG_TYPE"predicateinfo" "predicateinfo" | ||||||||
| 41 | using namespace llvm; | ||||||||
| 42 | using namespace PatternMatch; | ||||||||
| 43 | |||||||||
| 44 | INITIALIZE_PASS_BEGIN(PredicateInfoPrinterLegacyPass, "print-predicateinfo",static void *initializePredicateInfoPrinterLegacyPassPassOnce (PassRegistry &Registry) { | ||||||||
| 45 | "PredicateInfo Printer", false, false)static void *initializePredicateInfoPrinterLegacyPassPassOnce (PassRegistry &Registry) { | ||||||||
| 46 | INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)initializeDominatorTreeWrapperPassPass(Registry); | ||||||||
| 47 | INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)initializeAssumptionCacheTrackerPass(Registry); | ||||||||
| 48 | INITIALIZE_PASS_END(PredicateInfoPrinterLegacyPass, "print-predicateinfo",PassInfo *PI = new PassInfo( "PredicateInfo Printer", "print-predicateinfo" , &PredicateInfoPrinterLegacyPass::ID, PassInfo::NormalCtor_t (callDefaultCtor<PredicateInfoPrinterLegacyPass>), false , false); Registry.registerPass(*PI, true); return PI; } static llvm::once_flag InitializePredicateInfoPrinterLegacyPassPassFlag ; void llvm::initializePredicateInfoPrinterLegacyPassPass(PassRegistry &Registry) { llvm::call_once(InitializePredicateInfoPrinterLegacyPassPassFlag , initializePredicateInfoPrinterLegacyPassPassOnce, std::ref( Registry)); } | ||||||||
| 49 | "PredicateInfo Printer", false, false)PassInfo *PI = new PassInfo( "PredicateInfo Printer", "print-predicateinfo" , &PredicateInfoPrinterLegacyPass::ID, PassInfo::NormalCtor_t (callDefaultCtor<PredicateInfoPrinterLegacyPass>), false , false); Registry.registerPass(*PI, true); return PI; } static llvm::once_flag InitializePredicateInfoPrinterLegacyPassPassFlag ; void llvm::initializePredicateInfoPrinterLegacyPassPass(PassRegistry &Registry) { llvm::call_once(InitializePredicateInfoPrinterLegacyPassPassFlag , initializePredicateInfoPrinterLegacyPassPassOnce, std::ref( Registry)); } | ||||||||
| 50 | static cl::opt<bool> VerifyPredicateInfo( | ||||||||
| 51 | "verify-predicateinfo", cl::init(false), cl::Hidden, | ||||||||
| 52 | cl::desc("Verify PredicateInfo in legacy printer pass.")); | ||||||||
| 53 | DEBUG_COUNTER(RenameCounter, "predicateinfo-rename",static const unsigned RenameCounter = DebugCounter::registerCounter ("predicateinfo-rename", "Controls which variables are renamed with predicateinfo" ) | ||||||||
| 54 | "Controls which variables are renamed with predicateinfo")static const unsigned RenameCounter = DebugCounter::registerCounter ("predicateinfo-rename", "Controls which variables are renamed with predicateinfo" ); | ||||||||
| 55 | |||||||||
| 56 | // Maximum number of conditions considered for renaming for each branch/assume. | ||||||||
| 57 | // This limits renaming of deep and/or chains. | ||||||||
| 58 | static const unsigned MaxCondsPerBranch = 8; | ||||||||
| 59 | |||||||||
| 60 | namespace { | ||||||||
| 61 | // Given a predicate info that is a type of branching terminator, get the | ||||||||
| 62 | // branching block. | ||||||||
| 63 | const BasicBlock *getBranchBlock(const PredicateBase *PB) { | ||||||||
| 64 | assert(isa<PredicateWithEdge>(PB) &&((void)0) | ||||||||
| 65 | "Only branches and switches should have PHIOnly defs that "((void)0) | ||||||||
| 66 | "require branch blocks.")((void)0); | ||||||||
| 67 | return cast<PredicateWithEdge>(PB)->From; | ||||||||
| 68 | } | ||||||||
| 69 | |||||||||
| 70 | // Given a predicate info that is a type of branching terminator, get the | ||||||||
| 71 | // branching terminator. | ||||||||
| 72 | static Instruction *getBranchTerminator(const PredicateBase *PB) { | ||||||||
| 73 | assert(isa<PredicateWithEdge>(PB) &&((void)0) | ||||||||
| 74 | "Not a predicate info type we know how to get a terminator from.")((void)0); | ||||||||
| 75 | return cast<PredicateWithEdge>(PB)->From->getTerminator(); | ||||||||
| 76 | } | ||||||||
| 77 | |||||||||
| 78 | // Given a predicate info that is a type of branching terminator, get the | ||||||||
| 79 | // edge this predicate info represents | ||||||||
| 80 | std::pair<BasicBlock *, BasicBlock *> getBlockEdge(const PredicateBase *PB) { | ||||||||
| 81 | assert(isa<PredicateWithEdge>(PB) &&((void)0) | ||||||||
| 82 | "Not a predicate info type we know how to get an edge from.")((void)0); | ||||||||
| 83 | const auto *PEdge = cast<PredicateWithEdge>(PB); | ||||||||
| 84 | return std::make_pair(PEdge->From, PEdge->To); | ||||||||
| 85 | } | ||||||||
| 86 | } | ||||||||
| 87 | |||||||||
| 88 | namespace llvm { | ||||||||
| 89 | enum LocalNum { | ||||||||
| 90 | // Operations that must appear first in the block. | ||||||||
| 91 | LN_First, | ||||||||
| 92 | // Operations that are somewhere in the middle of the block, and are sorted on | ||||||||
| 93 | // demand. | ||||||||
| 94 | LN_Middle, | ||||||||
| 95 | // Operations that must appear last in a block, like successor phi node uses. | ||||||||
| 96 | LN_Last | ||||||||
| 97 | }; | ||||||||
| 98 | |||||||||
| 99 | // Associate global and local DFS info with defs and uses, so we can sort them | ||||||||
| 100 | // into a global domination ordering. | ||||||||
| 101 | struct ValueDFS { | ||||||||
| 102 | int DFSIn = 0; | ||||||||
| 103 | int DFSOut = 0; | ||||||||
| 104 | unsigned int LocalNum = LN_Middle; | ||||||||
| 105 | // Only one of Def or Use will be set. | ||||||||
| 106 | Value *Def = nullptr; | ||||||||
| 107 | Use *U = nullptr; | ||||||||
| 108 | // Neither PInfo nor EdgeOnly participate in the ordering | ||||||||
| 109 | PredicateBase *PInfo = nullptr; | ||||||||
| 110 | bool EdgeOnly = false; | ||||||||
| 111 | }; | ||||||||
| 112 | |||||||||
| 113 | // Perform a strict weak ordering on instructions and arguments. | ||||||||
| 114 | static bool valueComesBefore(const Value *A, const Value *B) { | ||||||||
| 115 | auto *ArgA = dyn_cast_or_null<Argument>(A); | ||||||||
| 116 | auto *ArgB = dyn_cast_or_null<Argument>(B); | ||||||||
| 117 | if (ArgA && !ArgB) | ||||||||
| 118 | return true; | ||||||||
| 119 | if (ArgB && !ArgA) | ||||||||
| 120 | return false; | ||||||||
| 121 | if (ArgA && ArgB) | ||||||||
| 122 | return ArgA->getArgNo() < ArgB->getArgNo(); | ||||||||
| 123 | return cast<Instruction>(A)->comesBefore(cast<Instruction>(B)); | ||||||||
| 124 | } | ||||||||
| 125 | |||||||||
| 126 | // This compares ValueDFS structures. Doing so allows us to walk the minimum | ||||||||
| 127 | // number of instructions necessary to compute our def/use ordering. | ||||||||
| 128 | struct ValueDFS_Compare { | ||||||||
| 129 | DominatorTree &DT; | ||||||||
| 130 | ValueDFS_Compare(DominatorTree &DT) : DT(DT) {} | ||||||||
| 131 | |||||||||
| 132 | bool operator()(const ValueDFS &A, const ValueDFS &B) const { | ||||||||
| 133 | if (&A == &B) | ||||||||
| 134 | return false; | ||||||||
| 135 | // The only case we can't directly compare them is when they in the same | ||||||||
| 136 | // block, and both have localnum == middle. In that case, we have to use | ||||||||
| 137 | // comesbefore to see what the real ordering is, because they are in the | ||||||||
| 138 | // same basic block. | ||||||||
| 139 | |||||||||
| 140 | assert((A.DFSIn != B.DFSIn || A.DFSOut == B.DFSOut) &&((void)0) | ||||||||
| 141 | "Equal DFS-in numbers imply equal out numbers")((void)0); | ||||||||
| 142 | bool SameBlock = A.DFSIn == B.DFSIn; | ||||||||
| 143 | |||||||||
| 144 | // We want to put the def that will get used for a given set of phi uses, | ||||||||
| 145 | // before those phi uses. | ||||||||
| 146 | // So we sort by edge, then by def. | ||||||||
| 147 | // Note that only phi nodes uses and defs can come last. | ||||||||
| 148 | if (SameBlock && A.LocalNum == LN_Last && B.LocalNum == LN_Last) | ||||||||
| 149 | return comparePHIRelated(A, B); | ||||||||
| 150 | |||||||||
| 151 | bool isADef = A.Def; | ||||||||
| 152 | bool isBDef = B.Def; | ||||||||
| 153 | if (!SameBlock || A.LocalNum != LN_Middle || B.LocalNum != LN_Middle) | ||||||||
| 154 | return std::tie(A.DFSIn, A.LocalNum, isADef) < | ||||||||
| 155 | std::tie(B.DFSIn, B.LocalNum, isBDef); | ||||||||
| 156 | return localComesBefore(A, B); | ||||||||
| 157 | } | ||||||||
| 158 | |||||||||
| 159 | // For a phi use, or a non-materialized def, return the edge it represents. | ||||||||
| 160 | std::pair<BasicBlock *, BasicBlock *> getBlockEdge(const ValueDFS &VD) const { | ||||||||
| 161 | if (!VD.Def && VD.U) { | ||||||||
| 162 | auto *PHI = cast<PHINode>(VD.U->getUser()); | ||||||||
| 163 | return std::make_pair(PHI->getIncomingBlock(*VD.U), PHI->getParent()); | ||||||||
| 164 | } | ||||||||
| 165 | // This is really a non-materialized def. | ||||||||
| 166 | return ::getBlockEdge(VD.PInfo); | ||||||||
| 167 | } | ||||||||
| 168 | |||||||||
| 169 | // For two phi related values, return the ordering. | ||||||||
| 170 | bool comparePHIRelated(const ValueDFS &A, const ValueDFS &B) const { | ||||||||
| 171 | BasicBlock *ASrc, *ADest, *BSrc, *BDest; | ||||||||
| 172 | std::tie(ASrc, ADest) = getBlockEdge(A); | ||||||||
| 173 | std::tie(BSrc, BDest) = getBlockEdge(B); | ||||||||
| 174 | |||||||||
| 175 | #ifndef NDEBUG1 | ||||||||
| 176 | // This function should only be used for values in the same BB, check that. | ||||||||
| 177 | DomTreeNode *DomASrc = DT.getNode(ASrc); | ||||||||
| 178 | DomTreeNode *DomBSrc = DT.getNode(BSrc); | ||||||||
| 179 | assert(DomASrc->getDFSNumIn() == (unsigned)A.DFSIn &&((void)0) | ||||||||
| 180 | "DFS numbers for A should match the ones of the source block")((void)0); | ||||||||
| 181 | assert(DomBSrc->getDFSNumIn() == (unsigned)B.DFSIn &&((void)0) | ||||||||
| 182 | "DFS numbers for B should match the ones of the source block")((void)0); | ||||||||
| 183 | assert(A.DFSIn == B.DFSIn && "Values must be in the same block")((void)0); | ||||||||
| 184 | #endif | ||||||||
| 185 | (void)ASrc; | ||||||||
| 186 | (void)BSrc; | ||||||||
| 187 | |||||||||
| 188 | // Use DFS numbers to compare destination blocks, to guarantee a | ||||||||
| 189 | // deterministic order. | ||||||||
| 190 | DomTreeNode *DomADest = DT.getNode(ADest); | ||||||||
| 191 | DomTreeNode *DomBDest = DT.getNode(BDest); | ||||||||
| 192 | unsigned AIn = DomADest->getDFSNumIn(); | ||||||||
| 193 | unsigned BIn = DomBDest->getDFSNumIn(); | ||||||||
| 194 | bool isADef = A.Def; | ||||||||
| 195 | bool isBDef = B.Def; | ||||||||
| 196 | assert((!A.Def || !A.U) && (!B.Def || !B.U) &&((void)0) | ||||||||
| 197 | "Def and U cannot be set at the same time")((void)0); | ||||||||
| 198 | // Now sort by edge destination and then defs before uses. | ||||||||
| 199 | return std::tie(AIn, isADef) < std::tie(BIn, isBDef); | ||||||||
| 200 | } | ||||||||
| 201 | |||||||||
| 202 | // Get the definition of an instruction that occurs in the middle of a block. | ||||||||
| 203 | Value *getMiddleDef(const ValueDFS &VD) const { | ||||||||
| 204 | if (VD.Def) | ||||||||
| 205 | return VD.Def; | ||||||||
| 206 | // It's possible for the defs and uses to be null. For branches, the local | ||||||||
| 207 | // numbering will say the placed predicaeinfos should go first (IE | ||||||||
| 208 | // LN_beginning), so we won't be in this function. For assumes, we will end | ||||||||
| 209 | // up here, beause we need to order the def we will place relative to the | ||||||||
| 210 | // assume. So for the purpose of ordering, we pretend the def is right | ||||||||
| 211 | // after the assume, because that is where we will insert the info. | ||||||||
| 212 | if (!VD.U) { | ||||||||
| 213 | assert(VD.PInfo &&((void)0) | ||||||||
| 214 | "No def, no use, and no predicateinfo should not occur")((void)0); | ||||||||
| 215 | assert(isa<PredicateAssume>(VD.PInfo) &&((void)0) | ||||||||
| 216 | "Middle of block should only occur for assumes")((void)0); | ||||||||
| 217 | return cast<PredicateAssume>(VD.PInfo)->AssumeInst->getNextNode(); | ||||||||
| 218 | } | ||||||||
| 219 | return nullptr; | ||||||||
| 220 | } | ||||||||
| 221 | |||||||||
| 222 | // Return either the Def, if it's not null, or the user of the Use, if the def | ||||||||
| 223 | // is null. | ||||||||
| 224 | const Instruction *getDefOrUser(const Value *Def, const Use *U) const { | ||||||||
| 225 | if (Def) | ||||||||
| 226 | return cast<Instruction>(Def); | ||||||||
| 227 | return cast<Instruction>(U->getUser()); | ||||||||
| 228 | } | ||||||||
| 229 | |||||||||
| 230 | // This performs the necessary local basic block ordering checks to tell | ||||||||
| 231 | // whether A comes before B, where both are in the same basic block. | ||||||||
| 232 | bool localComesBefore(const ValueDFS &A, const ValueDFS &B) const { | ||||||||
| 233 | auto *ADef = getMiddleDef(A); | ||||||||
| 234 | auto *BDef = getMiddleDef(B); | ||||||||
| 235 | |||||||||
| 236 | // See if we have real values or uses. If we have real values, we are | ||||||||
| 237 | // guaranteed they are instructions or arguments. No matter what, we are | ||||||||
| 238 | // guaranteed they are in the same block if they are instructions. | ||||||||
| 239 | auto *ArgA = dyn_cast_or_null<Argument>(ADef); | ||||||||
| 240 | auto *ArgB = dyn_cast_or_null<Argument>(BDef); | ||||||||
| 241 | |||||||||
| 242 | if (ArgA || ArgB) | ||||||||
| 243 | return valueComesBefore(ArgA, ArgB); | ||||||||
| 244 | |||||||||
| 245 | auto *AInst = getDefOrUser(ADef, A.U); | ||||||||
| 246 | auto *BInst = getDefOrUser(BDef, B.U); | ||||||||
| 247 | return valueComesBefore(AInst, BInst); | ||||||||
| 248 | } | ||||||||
| 249 | }; | ||||||||
| 250 | |||||||||
| 251 | class PredicateInfoBuilder { | ||||||||
| 252 | // Used to store information about each value we might rename. | ||||||||
| 253 | struct ValueInfo { | ||||||||
| 254 | SmallVector<PredicateBase *, 4> Infos; | ||||||||
| 255 | }; | ||||||||
| 256 | |||||||||
| 257 | PredicateInfo &PI; | ||||||||
| 258 | Function &F; | ||||||||
| 259 | DominatorTree &DT; | ||||||||
| 260 | AssumptionCache &AC; | ||||||||
| 261 | |||||||||
| 262 | // This stores info about each operand or comparison result we make copies | ||||||||
| 263 | // of. The real ValueInfos start at index 1, index 0 is unused so that we | ||||||||
| 264 | // can more easily detect invalid indexing. | ||||||||
| 265 | SmallVector<ValueInfo, 32> ValueInfos; | ||||||||
| 266 | |||||||||
| 267 | // This gives the index into the ValueInfos array for a given Value. Because | ||||||||
| 268 | // 0 is not a valid Value Info index, you can use DenseMap::lookup and tell | ||||||||
| 269 | // whether it returned a valid result. | ||||||||
| 270 | DenseMap<Value *, unsigned int> ValueInfoNums; | ||||||||
| 271 | |||||||||
| 272 | // The set of edges along which we can only handle phi uses, due to critical | ||||||||
| 273 | // edges. | ||||||||
| 274 | DenseSet<std::pair<BasicBlock *, BasicBlock *>> EdgeUsesOnly; | ||||||||
| 275 | |||||||||
| 276 | ValueInfo &getOrCreateValueInfo(Value *); | ||||||||
| 277 | const ValueInfo &getValueInfo(Value *) const; | ||||||||
| 278 | |||||||||
| 279 | void processAssume(IntrinsicInst *, BasicBlock *, | ||||||||
| 280 | SmallVectorImpl<Value *> &OpsToRename); | ||||||||
| 281 | void processBranch(BranchInst *, BasicBlock *, | ||||||||
| 282 | SmallVectorImpl<Value *> &OpsToRename); | ||||||||
| 283 | void processSwitch(SwitchInst *, BasicBlock *, | ||||||||
| 284 | SmallVectorImpl<Value *> &OpsToRename); | ||||||||
| 285 | void renameUses(SmallVectorImpl<Value *> &OpsToRename); | ||||||||
| 286 | void addInfoFor(SmallVectorImpl<Value *> &OpsToRename, Value *Op, | ||||||||
| 287 | PredicateBase *PB); | ||||||||
| 288 | |||||||||
| 289 | typedef SmallVectorImpl<ValueDFS> ValueDFSStack; | ||||||||
| 290 | void convertUsesToDFSOrdered(Value *, SmallVectorImpl<ValueDFS> &); | ||||||||
| 291 | Value *materializeStack(unsigned int &, ValueDFSStack &, Value *); | ||||||||
| 292 | bool stackIsInScope(const ValueDFSStack &, const ValueDFS &) const; | ||||||||
| 293 | void popStackUntilDFSScope(ValueDFSStack &, const ValueDFS &); | ||||||||
| 294 | |||||||||
| 295 | public: | ||||||||
| 296 | PredicateInfoBuilder(PredicateInfo &PI, Function &F, DominatorTree &DT, | ||||||||
| 297 | AssumptionCache &AC) | ||||||||
| 298 | : PI(PI), F(F), DT(DT), AC(AC) { | ||||||||
| 299 | // Push an empty operand info so that we can detect 0 as not finding one | ||||||||
| 300 | ValueInfos.resize(1); | ||||||||
| 301 | } | ||||||||
| 302 | |||||||||
| 303 | void buildPredicateInfo(); | ||||||||
| 304 | }; | ||||||||
| 305 | |||||||||
| 306 | bool PredicateInfoBuilder::stackIsInScope(const ValueDFSStack &Stack, | ||||||||
| 307 | const ValueDFS &VDUse) const { | ||||||||
| 308 | if (Stack.empty()) | ||||||||
| 309 | return false; | ||||||||
| 310 | // If it's a phi only use, make sure it's for this phi node edge, and that the | ||||||||
| 311 | // use is in a phi node. If it's anything else, and the top of the stack is | ||||||||
| 312 | // EdgeOnly, we need to pop the stack. We deliberately sort phi uses next to | ||||||||
| 313 | // the defs they must go with so that we can know it's time to pop the stack | ||||||||
| 314 | // when we hit the end of the phi uses for a given def. | ||||||||
| 315 | if (Stack.back().EdgeOnly) { | ||||||||
| 316 | if (!VDUse.U) | ||||||||
| 317 | return false; | ||||||||
| 318 | auto *PHI = dyn_cast<PHINode>(VDUse.U->getUser()); | ||||||||
| 319 | if (!PHI) | ||||||||
| 320 | return false; | ||||||||
| 321 | // Check edge | ||||||||
| 322 | BasicBlock *EdgePred = PHI->getIncomingBlock(*VDUse.U); | ||||||||
| 323 | if (EdgePred != getBranchBlock(Stack.back().PInfo)) | ||||||||
| 324 | return false; | ||||||||
| 325 | |||||||||
| 326 | // Use dominates, which knows how to handle edge dominance. | ||||||||
| 327 | return DT.dominates(getBlockEdge(Stack.back().PInfo), *VDUse.U); | ||||||||
| 328 | } | ||||||||
| 329 | |||||||||
| 330 | return (VDUse.DFSIn >= Stack.back().DFSIn && | ||||||||
| 331 | VDUse.DFSOut <= Stack.back().DFSOut); | ||||||||
| 332 | } | ||||||||
| 333 | |||||||||
| 334 | void PredicateInfoBuilder::popStackUntilDFSScope(ValueDFSStack &Stack, | ||||||||
| 335 | const ValueDFS &VD) { | ||||||||
| 336 | while (!Stack.empty() && !stackIsInScope(Stack, VD)) | ||||||||
| 337 | Stack.pop_back(); | ||||||||
| 338 | } | ||||||||
| 339 | |||||||||
| 340 | // Convert the uses of Op into a vector of uses, associating global and local | ||||||||
| 341 | // DFS info with each one. | ||||||||
| 342 | void PredicateInfoBuilder::convertUsesToDFSOrdered( | ||||||||
| 343 | Value *Op, SmallVectorImpl<ValueDFS> &DFSOrderedSet) { | ||||||||
| 344 | for (auto &U : Op->uses()) { | ||||||||
| 345 | if (auto *I = dyn_cast<Instruction>(U.getUser())) { | ||||||||
| 346 | ValueDFS VD; | ||||||||
| 347 | // Put the phi node uses in the incoming block. | ||||||||
| 348 | BasicBlock *IBlock; | ||||||||
| 349 | if (auto *PN = dyn_cast<PHINode>(I)) { | ||||||||
| 350 | IBlock = PN->getIncomingBlock(U); | ||||||||
| 351 | // Make phi node users appear last in the incoming block | ||||||||
| 352 | // they are from. | ||||||||
| 353 | VD.LocalNum = LN_Last; | ||||||||
| 354 | } else { | ||||||||
| 355 | // If it's not a phi node use, it is somewhere in the middle of the | ||||||||
| 356 | // block. | ||||||||
| 357 | IBlock = I->getParent(); | ||||||||
| 358 | VD.LocalNum = LN_Middle; | ||||||||
| 359 | } | ||||||||
| 360 | DomTreeNode *DomNode = DT.getNode(IBlock); | ||||||||
| 361 | // It's possible our use is in an unreachable block. Skip it if so. | ||||||||
| 362 | if (!DomNode) | ||||||||
| 363 | continue; | ||||||||
| 364 | VD.DFSIn = DomNode->getDFSNumIn(); | ||||||||
| 365 | VD.DFSOut = DomNode->getDFSNumOut(); | ||||||||
| 366 | VD.U = &U; | ||||||||
| 367 | DFSOrderedSet.push_back(VD); | ||||||||
| 368 | } | ||||||||
| 369 | } | ||||||||
| 370 | } | ||||||||
| 371 | |||||||||
| 372 | bool shouldRename(Value *V) { | ||||||||
| 373 | // Only want real values, not constants. Additionally, operands with one use | ||||||||
| 374 | // are only being used in the comparison, which means they will not be useful | ||||||||
| 375 | // for us to consider for predicateinfo. | ||||||||
| 376 | return (isa<Instruction>(V) || isa<Argument>(V)) && !V->hasOneUse(); | ||||||||
| 377 | } | ||||||||
| 378 | |||||||||
| 379 | // Collect relevant operations from Comparison that we may want to insert copies | ||||||||
| 380 | // for. | ||||||||
| 381 | void collectCmpOps(CmpInst *Comparison, SmallVectorImpl<Value *> &CmpOperands) { | ||||||||
| 382 | auto *Op0 = Comparison->getOperand(0); | ||||||||
| 383 | auto *Op1 = Comparison->getOperand(1); | ||||||||
| 384 | if (Op0 == Op1) | ||||||||
| 385 | return; | ||||||||
| 386 | |||||||||
| 387 | CmpOperands.push_back(Op0); | ||||||||
| 388 | CmpOperands.push_back(Op1); | ||||||||
| 389 | } | ||||||||
| 390 | |||||||||
| 391 | // Add Op, PB to the list of value infos for Op, and mark Op to be renamed. | ||||||||
| 392 | void PredicateInfoBuilder::addInfoFor(SmallVectorImpl<Value *> &OpsToRename, | ||||||||
| 393 | Value *Op, PredicateBase *PB) { | ||||||||
| 394 | auto &OperandInfo = getOrCreateValueInfo(Op); | ||||||||
| 395 | if (OperandInfo.Infos.empty()) | ||||||||
| 396 | OpsToRename.push_back(Op); | ||||||||
| 397 | PI.AllInfos.push_back(PB); | ||||||||
| 398 | OperandInfo.Infos.push_back(PB); | ||||||||
| 399 | } | ||||||||
| 400 | |||||||||
| 401 | // Process an assume instruction and place relevant operations we want to rename | ||||||||
| 402 | // into OpsToRename. | ||||||||
| 403 | void PredicateInfoBuilder::processAssume( | ||||||||
| 404 | IntrinsicInst *II, BasicBlock *AssumeBB, | ||||||||
| 405 | SmallVectorImpl<Value *> &OpsToRename) { | ||||||||
| 406 | SmallVector<Value *, 4> Worklist; | ||||||||
| 407 | SmallPtrSet<Value *, 4> Visited; | ||||||||
| 408 | Worklist.push_back(II->getOperand(0)); | ||||||||
| 409 | while (!Worklist.empty()) { | ||||||||
| 410 | Value *Cond = Worklist.pop_back_val(); | ||||||||
| 411 | if (!Visited.insert(Cond).second) | ||||||||
| 412 | continue; | ||||||||
| 413 | if (Visited.size() > MaxCondsPerBranch) | ||||||||
| 414 | break; | ||||||||
| 415 | |||||||||
| 416 | Value *Op0, *Op1; | ||||||||
| 417 | if (match(Cond, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))) { | ||||||||
| 418 | Worklist.push_back(Op1); | ||||||||
| 419 | Worklist.push_back(Op0); | ||||||||
| 420 | } | ||||||||
| 421 | |||||||||
| 422 | SmallVector<Value *, 4> Values; | ||||||||
| 423 | Values.push_back(Cond); | ||||||||
| 424 | if (auto *Cmp = dyn_cast<CmpInst>(Cond)) | ||||||||
| 425 | collectCmpOps(Cmp, Values); | ||||||||
| 426 | |||||||||
| 427 | for (Value *V : Values) { | ||||||||
| 428 | if (shouldRename(V)) { | ||||||||
| 429 | auto *PA = new PredicateAssume(V, II, Cond); | ||||||||
| 430 | addInfoFor(OpsToRename, V, PA); | ||||||||
| 431 | } | ||||||||
| 432 | } | ||||||||
| 433 | } | ||||||||
| 434 | } | ||||||||
| 435 | |||||||||
| 436 | // Process a block terminating branch, and place relevant operations to be | ||||||||
| 437 | // renamed into OpsToRename. | ||||||||
| 438 | void PredicateInfoBuilder::processBranch( | ||||||||
| 439 | BranchInst *BI, BasicBlock *BranchBB, | ||||||||
| 440 | SmallVectorImpl<Value *> &OpsToRename) { | ||||||||
| 441 | BasicBlock *FirstBB = BI->getSuccessor(0); | ||||||||
| 442 | BasicBlock *SecondBB = BI->getSuccessor(1); | ||||||||
| 443 | |||||||||
| 444 | for (BasicBlock *Succ : {FirstBB, SecondBB}) { | ||||||||
| 445 | bool TakenEdge = Succ == FirstBB; | ||||||||
| 446 | // Don't try to insert on a self-edge. This is mainly because we will | ||||||||
| 447 | // eliminate during renaming anyway. | ||||||||
| 448 | if (Succ == BranchBB) | ||||||||
| 449 | continue; | ||||||||
| 450 | |||||||||
| 451 | SmallVector<Value *, 4> Worklist; | ||||||||
| 452 | SmallPtrSet<Value *, 4> Visited; | ||||||||
| 453 | Worklist.push_back(BI->getCondition()); | ||||||||
| 454 | while (!Worklist.empty()) { | ||||||||
| 455 | Value *Cond = Worklist.pop_back_val(); | ||||||||
| 456 | if (!Visited.insert(Cond).second) | ||||||||
| 457 | continue; | ||||||||
| 458 | if (Visited.size() > MaxCondsPerBranch) | ||||||||
| 459 | break; | ||||||||
| 460 | |||||||||
| 461 | Value *Op0, *Op1; | ||||||||
| 462 | if (TakenEdge ? match(Cond, m_LogicalAnd(m_Value(Op0), m_Value(Op1))) | ||||||||
| 463 | : match(Cond, m_LogicalOr(m_Value(Op0), m_Value(Op1)))) { | ||||||||
| 464 | Worklist.push_back(Op1); | ||||||||
| 465 | Worklist.push_back(Op0); | ||||||||
| 466 | } | ||||||||
| 467 | |||||||||
| 468 | SmallVector<Value *, 4> Values; | ||||||||
| 469 | Values.push_back(Cond); | ||||||||
| 470 | if (auto *Cmp = dyn_cast<CmpInst>(Cond)) | ||||||||
| 471 | collectCmpOps(Cmp, Values); | ||||||||
| 472 | |||||||||
| 473 | for (Value *V : Values) { | ||||||||
| 474 | if (shouldRename(V)) { | ||||||||
| 475 | PredicateBase *PB = | ||||||||
| 476 | new PredicateBranch(V, BranchBB, Succ, Cond, TakenEdge); | ||||||||
| 477 | addInfoFor(OpsToRename, V, PB); | ||||||||
| 478 | if (!Succ->getSinglePredecessor()) | ||||||||
| 479 | EdgeUsesOnly.insert({BranchBB, Succ}); | ||||||||
| 480 | } | ||||||||
| 481 | } | ||||||||
| 482 | } | ||||||||
| 483 | } | ||||||||
| 484 | } | ||||||||
| 485 | // Process a block terminating switch, and place relevant operations to be | ||||||||
| 486 | // renamed into OpsToRename. | ||||||||
| 487 | void PredicateInfoBuilder::processSwitch( | ||||||||
| 488 | SwitchInst *SI, BasicBlock *BranchBB, | ||||||||
| 489 | SmallVectorImpl<Value *> &OpsToRename) { | ||||||||
| 490 | Value *Op = SI->getCondition(); | ||||||||
| 491 | if ((!isa<Instruction>(Op) && !isa<Argument>(Op)) || Op->hasOneUse()) | ||||||||
| 492 | return; | ||||||||
| 493 | |||||||||
| 494 | // Remember how many outgoing edges there are to every successor. | ||||||||
| 495 | SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges; | ||||||||
| 496 | for (unsigned i = 0, e = SI->getNumSuccessors(); i != e; ++i) { | ||||||||
| 497 | BasicBlock *TargetBlock = SI->getSuccessor(i); | ||||||||
| 498 | ++SwitchEdges[TargetBlock]; | ||||||||
| 499 | } | ||||||||
| 500 | |||||||||
| 501 | // Now propagate info for each case value | ||||||||
| 502 | for (auto C : SI->cases()) { | ||||||||
| 503 | BasicBlock *TargetBlock = C.getCaseSuccessor(); | ||||||||
| 504 | if (SwitchEdges.lookup(TargetBlock) == 1) { | ||||||||
| 505 | PredicateSwitch *PS = new PredicateSwitch( | ||||||||
| 506 | Op, SI->getParent(), TargetBlock, C.getCaseValue(), SI); | ||||||||
| 507 | addInfoFor(OpsToRename, Op, PS); | ||||||||
| 508 | if (!TargetBlock->getSinglePredecessor()) | ||||||||
| 509 | EdgeUsesOnly.insert({BranchBB, TargetBlock}); | ||||||||
| 510 | } | ||||||||
| 511 | } | ||||||||
| 512 | } | ||||||||
| 513 | |||||||||
| 514 | // Build predicate info for our function | ||||||||
| 515 | void PredicateInfoBuilder::buildPredicateInfo() { | ||||||||
| 516 | DT.updateDFSNumbers(); | ||||||||
| 517 | // Collect operands to rename from all conditional branch terminators, as well | ||||||||
| 518 | // as assume statements. | ||||||||
| 519 | SmallVector<Value *, 8> OpsToRename; | ||||||||
| 520 | for (auto DTN : depth_first(DT.getRootNode())) { | ||||||||
| 521 | BasicBlock *BranchBB = DTN->getBlock(); | ||||||||
| 522 | if (auto *BI = dyn_cast<BranchInst>(BranchBB->getTerminator())) { | ||||||||
| 523 | if (!BI->isConditional()) | ||||||||
| 524 | continue; | ||||||||
| 525 | // Can't insert conditional information if they all go to the same place. | ||||||||
| 526 | if (BI->getSuccessor(0) == BI->getSuccessor(1)) | ||||||||
| 527 | continue; | ||||||||
| 528 | processBranch(BI, BranchBB, OpsToRename); | ||||||||
| 529 | } else if (auto *SI = dyn_cast<SwitchInst>(BranchBB->getTerminator())) { | ||||||||
| 530 | processSwitch(SI, BranchBB, OpsToRename); | ||||||||
| 531 | } | ||||||||
| 532 | } | ||||||||
| 533 | for (auto &Assume : AC.assumptions()) { | ||||||||
| 534 | if (auto *II = dyn_cast_or_null<IntrinsicInst>(Assume)) | ||||||||
| 535 | if (DT.isReachableFromEntry(II->getParent())) | ||||||||
| 536 | processAssume(II, II->getParent(), OpsToRename); | ||||||||
| 537 | } | ||||||||
| 538 | // Now rename all our operations. | ||||||||
| 539 | renameUses(OpsToRename); | ||||||||
| 540 | } | ||||||||
| 541 | |||||||||
| 542 | // Given the renaming stack, make all the operands currently on the stack real | ||||||||
| 543 | // by inserting them into the IR. Return the last operation's value. | ||||||||
| 544 | Value *PredicateInfoBuilder::materializeStack(unsigned int &Counter, | ||||||||
| 545 | ValueDFSStack &RenameStack, | ||||||||
| 546 | Value *OrigOp) { | ||||||||
| 547 | // Find the first thing we have to materialize | ||||||||
| 548 | auto RevIter = RenameStack.rbegin(); | ||||||||
| 549 | for (; RevIter != RenameStack.rend(); ++RevIter) | ||||||||
| 550 | if (RevIter->Def) | ||||||||
| 551 | break; | ||||||||
| 552 | |||||||||
| 553 | size_t Start = RevIter - RenameStack.rbegin(); | ||||||||
| 554 | // The maximum number of things we should be trying to materialize at once | ||||||||
| 555 | // right now is 4, depending on if we had an assume, a branch, and both used | ||||||||
| 556 | // and of conditions. | ||||||||
| 557 | for (auto RenameIter = RenameStack.end() - Start; | ||||||||
| 558 | RenameIter != RenameStack.end(); ++RenameIter) { | ||||||||
| 559 | auto *Op = | ||||||||
| 560 | RenameIter == RenameStack.begin() ? OrigOp : (RenameIter - 1)->Def; | ||||||||
| 561 | ValueDFS &Result = *RenameIter; | ||||||||
| 562 | auto *ValInfo = Result.PInfo; | ||||||||
| 563 | ValInfo->RenamedOp = (RenameStack.end() - Start) == RenameStack.begin() | ||||||||
| 564 | ? OrigOp | ||||||||
| 565 | : (RenameStack.end() - Start - 1)->Def; | ||||||||
| 566 | // For edge predicates, we can just place the operand in the block before | ||||||||
| 567 | // the terminator. For assume, we have to place it right before the assume | ||||||||
| 568 | // to ensure we dominate all of our uses. Always insert right before the | ||||||||
| 569 | // relevant instruction (terminator, assume), so that we insert in proper | ||||||||
| 570 | // order in the case of multiple predicateinfo in the same block. | ||||||||
| 571 | // The number of named values is used to detect if a new declaration was | ||||||||
| 572 | // added. If so, that declaration is tracked so that it can be removed when | ||||||||
| 573 | // the analysis is done. The corner case were a new declaration results in | ||||||||
| 574 | // a name clash and the old name being renamed is not considered as that | ||||||||
| 575 | // represents an invalid module. | ||||||||
| 576 | if (isa<PredicateWithEdge>(ValInfo)) { | ||||||||
| 577 | IRBuilder<> B(getBranchTerminator(ValInfo)); | ||||||||
| 578 | auto NumDecls = F.getParent()->getNumNamedValues(); | ||||||||
| 579 | Function *IF = Intrinsic::getDeclaration( | ||||||||
| 580 | F.getParent(), Intrinsic::ssa_copy, Op->getType()); | ||||||||
| 581 | if (NumDecls != F.getParent()->getNumNamedValues()) | ||||||||
| 582 | PI.CreatedDeclarations.insert(IF); | ||||||||
| 583 | CallInst *PIC = | ||||||||
| 584 | B.CreateCall(IF, Op, Op->getName() + "." + Twine(Counter++)); | ||||||||
| 585 | PI.PredicateMap.insert({PIC, ValInfo}); | ||||||||
| 586 | Result.Def = PIC; | ||||||||
| 587 | } else { | ||||||||
| 588 | auto *PAssume = dyn_cast<PredicateAssume>(ValInfo); | ||||||||
| 589 | assert(PAssume &&((void)0) | ||||||||
| 590 | "Should not have gotten here without it being an assume")((void)0); | ||||||||
| 591 | // Insert the predicate directly after the assume. While it also holds | ||||||||
| 592 | // directly before it, assume(i1 true) is not a useful fact. | ||||||||
| 593 | IRBuilder<> B(PAssume->AssumeInst->getNextNode()); | ||||||||
| |||||||||
| 594 | auto NumDecls = F.getParent()->getNumNamedValues(); | ||||||||
| 595 | Function *IF = Intrinsic::getDeclaration( | ||||||||
| 596 | F.getParent(), Intrinsic::ssa_copy, Op->getType()); | ||||||||
| 597 | if (NumDecls != F.getParent()->getNumNamedValues()) | ||||||||
| 598 | PI.CreatedDeclarations.insert(IF); | ||||||||
| 599 | CallInst *PIC = B.CreateCall(IF, Op); | ||||||||
| 600 | PI.PredicateMap.insert({PIC, ValInfo}); | ||||||||
| 601 | Result.Def = PIC; | ||||||||
| 602 | } | ||||||||
| 603 | } | ||||||||
| 604 | return RenameStack.back().Def; | ||||||||
| 605 | } | ||||||||
| 606 | |||||||||
| 607 | // Instead of the standard SSA renaming algorithm, which is O(Number of | ||||||||
| 608 | // instructions), and walks the entire dominator tree, we walk only the defs + | ||||||||
| 609 | // uses. The standard SSA renaming algorithm does not really rely on the | ||||||||
| 610 | // dominator tree except to order the stack push/pops of the renaming stacks, so | ||||||||
| 611 | // that defs end up getting pushed before hitting the correct uses. This does | ||||||||
| 612 | // not require the dominator tree, only the *order* of the dominator tree. The | ||||||||
| 613 | // complete and correct ordering of the defs and uses, in dominator tree is | ||||||||
| 614 | // contained in the DFS numbering of the dominator tree. So we sort the defs and | ||||||||
| 615 | // uses into the DFS ordering, and then just use the renaming stack as per | ||||||||
| 616 | // normal, pushing when we hit a def (which is a predicateinfo instruction), | ||||||||
| 617 | // popping when we are out of the dfs scope for that def, and replacing any uses | ||||||||
| 618 | // with top of stack if it exists. In order to handle liveness without | ||||||||
| 619 | // propagating liveness info, we don't actually insert the predicateinfo | ||||||||
| 620 | // instruction def until we see a use that it would dominate. Once we see such | ||||||||
| 621 | // a use, we materialize the predicateinfo instruction in the right place and | ||||||||
| 622 | // use it. | ||||||||
| 623 | // | ||||||||
| 624 | // TODO: Use this algorithm to perform fast single-variable renaming in | ||||||||
| 625 | // promotememtoreg and memoryssa. | ||||||||
| 626 | void PredicateInfoBuilder::renameUses(SmallVectorImpl<Value *> &OpsToRename) { | ||||||||
| 627 | ValueDFS_Compare Compare(DT); | ||||||||
| 628 | // Compute liveness, and rename in O(uses) per Op. | ||||||||
| 629 | for (auto *Op : OpsToRename) { | ||||||||
| 630 | LLVM_DEBUG(dbgs() << "Visiting " << *Op << "\n")do { } while (false); | ||||||||
| 631 | unsigned Counter = 0; | ||||||||
| 632 | SmallVector<ValueDFS, 16> OrderedUses; | ||||||||
| 633 | const auto &ValueInfo = getValueInfo(Op); | ||||||||
| 634 | // Insert the possible copies into the def/use list. | ||||||||
| 635 | // They will become real copies if we find a real use for them, and never | ||||||||
| 636 | // created otherwise. | ||||||||
| 637 | for (auto &PossibleCopy : ValueInfo.Infos) { | ||||||||
| 638 | ValueDFS VD; | ||||||||
| 639 | // Determine where we are going to place the copy by the copy type. | ||||||||
| 640 | // The predicate info for branches always come first, they will get | ||||||||
| 641 | // materialized in the split block at the top of the block. | ||||||||
| 642 | // The predicate info for assumes will be somewhere in the middle, | ||||||||
| 643 | // it will get materialized in front of the assume. | ||||||||
| 644 | if (const auto *PAssume = dyn_cast<PredicateAssume>(PossibleCopy)) { | ||||||||
| 645 | VD.LocalNum = LN_Middle; | ||||||||
| 646 | DomTreeNode *DomNode = DT.getNode(PAssume->AssumeInst->getParent()); | ||||||||
| 647 | if (!DomNode) | ||||||||
| 648 | continue; | ||||||||
| 649 | VD.DFSIn = DomNode->getDFSNumIn(); | ||||||||
| 650 | VD.DFSOut = DomNode->getDFSNumOut(); | ||||||||
| 651 | VD.PInfo = PossibleCopy; | ||||||||
| 652 | OrderedUses.push_back(VD); | ||||||||
| 653 | } else if (isa<PredicateWithEdge>(PossibleCopy)) { | ||||||||
| 654 | // If we can only do phi uses, we treat it like it's in the branch | ||||||||
| 655 | // block, and handle it specially. We know that it goes last, and only | ||||||||
| 656 | // dominate phi uses. | ||||||||
| 657 | auto BlockEdge = getBlockEdge(PossibleCopy); | ||||||||
| 658 | if (EdgeUsesOnly.count(BlockEdge)) { | ||||||||
| 659 | VD.LocalNum = LN_Last; | ||||||||
| 660 | auto *DomNode = DT.getNode(BlockEdge.first); | ||||||||
| 661 | if (DomNode) { | ||||||||
| 662 | VD.DFSIn = DomNode->getDFSNumIn(); | ||||||||
| 663 | VD.DFSOut = DomNode->getDFSNumOut(); | ||||||||
| 664 | VD.PInfo = PossibleCopy; | ||||||||
| 665 | VD.EdgeOnly = true; | ||||||||
| 666 | OrderedUses.push_back(VD); | ||||||||
| 667 | } | ||||||||
| 668 | } else { | ||||||||
| 669 | // Otherwise, we are in the split block (even though we perform | ||||||||
| 670 | // insertion in the branch block). | ||||||||
| 671 | // Insert a possible copy at the split block and before the branch. | ||||||||
| 672 | VD.LocalNum = LN_First; | ||||||||
| 673 | auto *DomNode = DT.getNode(BlockEdge.second); | ||||||||
| 674 | if (DomNode) { | ||||||||
| 675 | VD.DFSIn = DomNode->getDFSNumIn(); | ||||||||
| 676 | VD.DFSOut = DomNode->getDFSNumOut(); | ||||||||
| 677 | VD.PInfo = PossibleCopy; | ||||||||
| 678 | OrderedUses.push_back(VD); | ||||||||
| 679 | } | ||||||||
| 680 | } | ||||||||
| 681 | } | ||||||||
| 682 | } | ||||||||
| 683 | |||||||||
| 684 | convertUsesToDFSOrdered(Op, OrderedUses); | ||||||||
| 685 | // Here we require a stable sort because we do not bother to try to | ||||||||
| 686 | // assign an order to the operands the uses represent. Thus, two | ||||||||
| 687 | // uses in the same instruction do not have a strict sort order | ||||||||
| 688 | // currently and will be considered equal. We could get rid of the | ||||||||
| 689 | // stable sort by creating one if we wanted. | ||||||||
| 690 | llvm::stable_sort(OrderedUses, Compare); | ||||||||
| 691 | SmallVector<ValueDFS, 8> RenameStack; | ||||||||
| 692 | // For each use, sorted into dfs order, push values and replaces uses with | ||||||||
| 693 | // top of stack, which will represent the reaching def. | ||||||||
| 694 | for (auto &VD : OrderedUses) { | ||||||||
| 695 | // We currently do not materialize copy over copy, but we should decide if | ||||||||
| 696 | // we want to. | ||||||||
| 697 | bool PossibleCopy = VD.PInfo != nullptr; | ||||||||
| 698 | if (RenameStack.empty()) { | ||||||||
| 699 | LLVM_DEBUG(dbgs() << "Rename Stack is empty\n")do { } while (false); | ||||||||
| 700 | } else { | ||||||||
| 701 | LLVM_DEBUG(dbgs() << "Rename Stack Top DFS numbers are ("do { } while (false) | ||||||||
| 702 | << RenameStack.back().DFSIn << ","do { } while (false) | ||||||||
| 703 | << RenameStack.back().DFSOut << ")\n")do { } while (false); | ||||||||
| 704 | } | ||||||||
| 705 | |||||||||
| 706 | LLVM_DEBUG(dbgs() << "Current DFS numbers are (" << VD.DFSIn << ","do { } while (false) | ||||||||
| 707 | << VD.DFSOut << ")\n")do { } while (false); | ||||||||
| 708 | |||||||||
| 709 | bool ShouldPush = (VD.Def || PossibleCopy); | ||||||||
| 710 | bool OutOfScope = !stackIsInScope(RenameStack, VD); | ||||||||
| 711 | if (OutOfScope
| ||||||||
| 712 | // Sync to our current scope. | ||||||||
| 713 | popStackUntilDFSScope(RenameStack, VD); | ||||||||
| 714 | if (ShouldPush
| ||||||||
| 715 | RenameStack.push_back(VD); | ||||||||
| 716 | } | ||||||||
| 717 | } | ||||||||
| 718 | // If we get to this point, and the stack is empty we must have a use | ||||||||
| 719 | // with no renaming needed, just skip it. | ||||||||
| 720 | if (RenameStack.empty()) | ||||||||
| 721 | continue; | ||||||||
| 722 | // Skip values, only want to rename the uses | ||||||||
| 723 | if (VD.Def
| ||||||||
| 724 | continue; | ||||||||
| 725 | if (!DebugCounter::shouldExecute(RenameCounter)) { | ||||||||
| 726 | LLVM_DEBUG(dbgs() << "Skipping execution due to debug counter\n")do { } while (false); | ||||||||
| 727 | continue; | ||||||||
| 728 | } | ||||||||
| 729 | ValueDFS &Result = RenameStack.back(); | ||||||||
| 730 | |||||||||
| 731 | // If the possible copy dominates something, materialize our stack up to | ||||||||
| 732 | // this point. This ensures every comparison that affects our operation | ||||||||
| 733 | // ends up with predicateinfo. | ||||||||
| 734 | if (!Result.Def) | ||||||||
| 735 | Result.Def = materializeStack(Counter, RenameStack, Op); | ||||||||
| 736 | |||||||||
| 737 | LLVM_DEBUG(dbgs() << "Found replacement " << *Result.Def << " for "do { } while (false) | ||||||||
| 738 | << *VD.U->get() << " in " << *(VD.U->getUser())do { } while (false) | ||||||||
| 739 | << "\n")do { } while (false); | ||||||||
| 740 | assert(DT.dominates(cast<Instruction>(Result.Def), *VD.U) &&((void)0) | ||||||||
| 741 | "Predicateinfo def should have dominated this use")((void)0); | ||||||||
| 742 | VD.U->set(Result.Def); | ||||||||
| 743 | } | ||||||||
| 744 | } | ||||||||
| 745 | } | ||||||||
| 746 | |||||||||
| 747 | PredicateInfoBuilder::ValueInfo & | ||||||||
| 748 | PredicateInfoBuilder::getOrCreateValueInfo(Value *Operand) { | ||||||||
| 749 | auto OIN = ValueInfoNums.find(Operand); | ||||||||
| 750 | if (OIN == ValueInfoNums.end()) { | ||||||||
| 751 | // This will grow it | ||||||||
| 752 | ValueInfos.resize(ValueInfos.size() + 1); | ||||||||
| 753 | // This will use the new size and give us a 0 based number of the info | ||||||||
| 754 | auto InsertResult = ValueInfoNums.insert({Operand, ValueInfos.size() - 1}); | ||||||||
| 755 | assert(InsertResult.second && "Value info number already existed?")((void)0); | ||||||||
| 756 | return ValueInfos[InsertResult.first->second]; | ||||||||
| 757 | } | ||||||||
| 758 | return ValueInfos[OIN->second]; | ||||||||
| 759 | } | ||||||||
| 760 | |||||||||
| 761 | const PredicateInfoBuilder::ValueInfo & | ||||||||
| 762 | PredicateInfoBuilder::getValueInfo(Value *Operand) const { | ||||||||
| 763 | auto OINI = ValueInfoNums.lookup(Operand); | ||||||||
| 764 | assert(OINI != 0 && "Operand was not really in the Value Info Numbers")((void)0); | ||||||||
| 765 | assert(OINI < ValueInfos.size() &&((void)0) | ||||||||
| 766 | "Value Info Number greater than size of Value Info Table")((void)0); | ||||||||
| 767 | return ValueInfos[OINI]; | ||||||||
| 768 | } | ||||||||
| 769 | |||||||||
| 770 | PredicateInfo::PredicateInfo(Function &F, DominatorTree &DT, | ||||||||
| 771 | AssumptionCache &AC) | ||||||||
| 772 | : F(F) { | ||||||||
| 773 | PredicateInfoBuilder Builder(*this, F, DT, AC); | ||||||||
| 774 | Builder.buildPredicateInfo(); | ||||||||
| 775 | } | ||||||||
| 776 | |||||||||
| 777 | // Remove all declarations we created . The PredicateInfo consumers are | ||||||||
| 778 | // responsible for remove the ssa_copy calls created. | ||||||||
| 779 | PredicateInfo::~PredicateInfo() { | ||||||||
| 780 | // Collect function pointers in set first, as SmallSet uses a SmallVector | ||||||||
| 781 | // internally and we have to remove the asserting value handles first. | ||||||||
| 782 | SmallPtrSet<Function *, 20> FunctionPtrs; | ||||||||
| 783 | for (auto &F : CreatedDeclarations) | ||||||||
| 784 | FunctionPtrs.insert(&*F); | ||||||||
| 785 | CreatedDeclarations.clear(); | ||||||||
| 786 | |||||||||
| 787 | for (Function *F : FunctionPtrs) { | ||||||||
| 788 | assert(F->user_begin() == F->user_end() &&((void)0) | ||||||||
| 789 | "PredicateInfo consumer did not remove all SSA copies.")((void)0); | ||||||||
| 790 | F->eraseFromParent(); | ||||||||
| 791 | } | ||||||||
| 792 | } | ||||||||
| 793 | |||||||||
| 794 | Optional<PredicateConstraint> PredicateBase::getConstraint() const { | ||||||||
| 795 | switch (Type) { | ||||||||
| 796 | case PT_Assume: | ||||||||
| 797 | case PT_Branch: { | ||||||||
| 798 | bool TrueEdge = true; | ||||||||
| 799 | if (auto *PBranch = dyn_cast<PredicateBranch>(this)) | ||||||||
| 800 | TrueEdge = PBranch->TrueEdge; | ||||||||
| 801 | |||||||||
| 802 | if (Condition == RenamedOp) { | ||||||||
| 803 | return {{CmpInst::ICMP_EQ, | ||||||||
| 804 | TrueEdge ? ConstantInt::getTrue(Condition->getType()) | ||||||||
| 805 | : ConstantInt::getFalse(Condition->getType())}}; | ||||||||
| 806 | } | ||||||||
| 807 | |||||||||
| 808 | CmpInst *Cmp = dyn_cast<CmpInst>(Condition); | ||||||||
| 809 | if (!Cmp) { | ||||||||
| 810 | // TODO: Make this an assertion once RenamedOp is fully accurate. | ||||||||
| 811 | return None; | ||||||||
| 812 | } | ||||||||
| 813 | |||||||||
| 814 | CmpInst::Predicate Pred; | ||||||||
| 815 | Value *OtherOp; | ||||||||
| 816 | if (Cmp->getOperand(0) == RenamedOp) { | ||||||||
| 817 | Pred = Cmp->getPredicate(); | ||||||||
| 818 | OtherOp = Cmp->getOperand(1); | ||||||||
| 819 | } else if (Cmp->getOperand(1) == RenamedOp) { | ||||||||
| 820 | Pred = Cmp->getSwappedPredicate(); | ||||||||
| 821 | OtherOp = Cmp->getOperand(0); | ||||||||
| 822 | } else { | ||||||||
| 823 | // TODO: Make this an assertion once RenamedOp is fully accurate. | ||||||||
| 824 | return None; | ||||||||
| 825 | } | ||||||||
| 826 | |||||||||
| 827 | // Invert predicate along false edge. | ||||||||
| 828 | if (!TrueEdge) | ||||||||
| 829 | Pred = CmpInst::getInversePredicate(Pred); | ||||||||
| 830 | |||||||||
| 831 | return {{Pred, OtherOp}}; | ||||||||
| 832 | } | ||||||||
| 833 | case PT_Switch: | ||||||||
| 834 | if (Condition != RenamedOp) { | ||||||||
| 835 | // TODO: Make this an assertion once RenamedOp is fully accurate. | ||||||||
| 836 | return None; | ||||||||
| 837 | } | ||||||||
| 838 | |||||||||
| 839 | return {{CmpInst::ICMP_EQ, cast<PredicateSwitch>(this)->CaseValue}}; | ||||||||
| 840 | } | ||||||||
| 841 | llvm_unreachable("Unknown predicate type")__builtin_unreachable(); | ||||||||
| 842 | } | ||||||||
| 843 | |||||||||
| 844 | void PredicateInfo::verifyPredicateInfo() const {} | ||||||||
| 845 | |||||||||
| 846 | char PredicateInfoPrinterLegacyPass::ID = 0; | ||||||||
| 847 | |||||||||
| 848 | PredicateInfoPrinterLegacyPass::PredicateInfoPrinterLegacyPass() | ||||||||
| 849 | : FunctionPass(ID) { | ||||||||
| 850 | initializePredicateInfoPrinterLegacyPassPass( | ||||||||
| 851 | *PassRegistry::getPassRegistry()); | ||||||||
| 852 | } | ||||||||
| 853 | |||||||||
| 854 | void PredicateInfoPrinterLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { | ||||||||
| 855 | AU.setPreservesAll(); | ||||||||
| 856 | AU.addRequiredTransitive<DominatorTreeWrapperPass>(); | ||||||||
| 857 | AU.addRequired<AssumptionCacheTracker>(); | ||||||||
| 858 | } | ||||||||
| 859 | |||||||||
| 860 | // Replace ssa_copy calls created by PredicateInfo with their operand. | ||||||||
| 861 | static void replaceCreatedSSACopys(PredicateInfo &PredInfo, Function &F) { | ||||||||
| 862 | for (Instruction &Inst : llvm::make_early_inc_range(instructions(F))) { | ||||||||
| 863 | const auto *PI = PredInfo.getPredicateInfoFor(&Inst); | ||||||||
| 864 | auto *II = dyn_cast<IntrinsicInst>(&Inst); | ||||||||
| 865 | if (!PI || !II || II->getIntrinsicID() != Intrinsic::ssa_copy) | ||||||||
| 866 | continue; | ||||||||
| 867 | |||||||||
| 868 | Inst.replaceAllUsesWith(II->getOperand(0)); | ||||||||
| 869 | Inst.eraseFromParent(); | ||||||||
| 870 | } | ||||||||
| 871 | } | ||||||||
| 872 | |||||||||
| 873 | bool PredicateInfoPrinterLegacyPass::runOnFunction(Function &F) { | ||||||||
| 874 | auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); | ||||||||
| 875 | auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); | ||||||||
| 876 | auto PredInfo = std::make_unique<PredicateInfo>(F, DT, AC); | ||||||||
| 877 | PredInfo->print(dbgs()); | ||||||||
| 878 | if (VerifyPredicateInfo) | ||||||||
| 879 | PredInfo->verifyPredicateInfo(); | ||||||||
| 880 | |||||||||
| 881 | replaceCreatedSSACopys(*PredInfo, F); | ||||||||
| 882 | return false; | ||||||||
| 883 | } | ||||||||
| 884 | |||||||||
| 885 | PreservedAnalyses PredicateInfoPrinterPass::run(Function &F, | ||||||||
| 886 | FunctionAnalysisManager &AM) { | ||||||||
| 887 | auto &DT = AM.getResult<DominatorTreeAnalysis>(F); | ||||||||
| 888 | auto &AC = AM.getResult<AssumptionAnalysis>(F); | ||||||||
| 889 | OS << "PredicateInfo for function: " << F.getName() << "\n"; | ||||||||
| 890 | auto PredInfo = std::make_unique<PredicateInfo>(F, DT, AC); | ||||||||
| 891 | PredInfo->print(OS); | ||||||||
| 892 | |||||||||
| 893 | replaceCreatedSSACopys(*PredInfo, F); | ||||||||
| 894 | return PreservedAnalyses::all(); | ||||||||
| 895 | } | ||||||||
| 896 | |||||||||
| 897 | /// An assembly annotator class to print PredicateInfo information in | ||||||||
| 898 | /// comments. | ||||||||
| 899 | class PredicateInfoAnnotatedWriter : public AssemblyAnnotationWriter { | ||||||||
| 900 | friend class PredicateInfo; | ||||||||
| 901 | const PredicateInfo *PredInfo; | ||||||||
| 902 | |||||||||
| 903 | public: | ||||||||
| 904 | PredicateInfoAnnotatedWriter(const PredicateInfo *M) : PredInfo(M) {} | ||||||||
| 905 | |||||||||
| 906 | void emitBasicBlockStartAnnot(const BasicBlock *BB, | ||||||||
| 907 | formatted_raw_ostream &OS) override {} | ||||||||
| 908 | |||||||||
| 909 | void emitInstructionAnnot(const Instruction *I, | ||||||||
| 910 | formatted_raw_ostream &OS) override { | ||||||||
| 911 | if (const auto *PI = PredInfo->getPredicateInfoFor(I)) { | ||||||||
| 912 | OS << "; Has predicate info\n"; | ||||||||
| 913 | if (const auto *PB = dyn_cast<PredicateBranch>(PI)) { | ||||||||
| 914 | OS << "; branch predicate info { TrueEdge: " << PB->TrueEdge | ||||||||
| 915 | << " Comparison:" << *PB->Condition << " Edge: ["; | ||||||||
| 916 | PB->From->printAsOperand(OS); | ||||||||
| 917 | OS << ","; | ||||||||
| 918 | PB->To->printAsOperand(OS); | ||||||||
| 919 | OS << "]"; | ||||||||
| 920 | } else if (const auto *PS = dyn_cast<PredicateSwitch>(PI)) { | ||||||||
| 921 | OS << "; switch predicate info { CaseValue: " << *PS->CaseValue | ||||||||
| 922 | << " Switch:" << *PS->Switch << " Edge: ["; | ||||||||
| 923 | PS->From->printAsOperand(OS); | ||||||||
| 924 | OS << ","; | ||||||||
| 925 | PS->To->printAsOperand(OS); | ||||||||
| 926 | OS << "]"; | ||||||||
| 927 | } else if (const auto *PA = dyn_cast<PredicateAssume>(PI)) { | ||||||||
| 928 | OS << "; assume predicate info {" | ||||||||
| 929 | << " Comparison:" << *PA->Condition; | ||||||||
| 930 | } | ||||||||
| 931 | OS << ", RenamedOp: "; | ||||||||
| 932 | PI->RenamedOp->printAsOperand(OS, false); | ||||||||
| 933 | OS << " }\n"; | ||||||||
| 934 | } | ||||||||
| 935 | } | ||||||||
| 936 | }; | ||||||||
| 937 | |||||||||
| 938 | void PredicateInfo::print(raw_ostream &OS) const { | ||||||||
| 939 | PredicateInfoAnnotatedWriter Writer(this); | ||||||||
| 940 | F.print(OS, &Writer); | ||||||||
| 941 | } | ||||||||
| 942 | |||||||||
| 943 | void PredicateInfo::dump() const { | ||||||||
| 944 | PredicateInfoAnnotatedWriter Writer(this); | ||||||||
| 945 | F.print(dbgs(), &Writer); | ||||||||
| 946 | } | ||||||||
| 947 | |||||||||
| 948 | PreservedAnalyses PredicateInfoVerifierPass::run(Function &F, | ||||||||
| 949 | FunctionAnalysisManager &AM) { | ||||||||
| 950 | auto &DT = AM.getResult<DominatorTreeAnalysis>(F); | ||||||||
| 951 | auto &AC = AM.getResult<AssumptionAnalysis>(F); | ||||||||
| 952 | std::make_unique<PredicateInfo>(F, DT, AC)->verifyPredicateInfo(); | ||||||||
| |||||||||
| 953 | |||||||||
| 954 | return PreservedAnalyses::all(); | ||||||||
| 955 | } | ||||||||
| 956 | } |
| 1 | // -*- C++ -*- |
| 2 | //===----------------------------------------------------------------------===// |
| 3 | // |
| 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 5 | // See https://llvm.org/LICENSE.txt for license information. |
| 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #ifndef _LIBCPP___MEMORY_UNIQUE_PTR_H |
| 11 | #define _LIBCPP___MEMORY_UNIQUE_PTR_H |
| 12 | |
| 13 | #include <__config> |
| 14 | #include <__functional_base> |
| 15 | #include <__functional/hash.h> |
| 16 | #include <__functional/operations.h> |
| 17 | #include <__memory/allocator_traits.h> // __pointer |
| 18 | #include <__memory/compressed_pair.h> |
| 19 | #include <__utility/forward.h> |
| 20 | #include <cstddef> |
| 21 | #include <type_traits> |
| 22 | #include <utility> |
| 23 | |
| 24 | #if _LIBCPP_STD_VER14 <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) |
| 25 | # include <__memory/auto_ptr.h> |
| 26 | #endif |
| 27 | |
| 28 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 29 | #pragma GCC system_header |
| 30 | #endif |
| 31 | |
| 32 | _LIBCPP_PUSH_MACROSpush_macro("min") push_macro("max") |
| 33 | #include <__undef_macros> |
| 34 | |
| 35 | _LIBCPP_BEGIN_NAMESPACE_STDnamespace std { inline namespace __1 { |
| 36 | |
| 37 | template <class _Tp> |
| 38 | struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) default_delete { |
| 39 | static_assert(!is_function<_Tp>::value, |
| 40 | "default_delete cannot be instantiated for function types"); |
| 41 | #ifndef _LIBCPP_CXX03_LANG |
| 42 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) constexpr default_delete() _NOEXCEPTnoexcept = default; |
| 43 | #else |
| 44 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) default_delete() {} |
| 45 | #endif |
| 46 | template <class _Up> |
| 47 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 48 | default_delete(const default_delete<_Up>&, |
| 49 | typename enable_if<is_convertible<_Up*, _Tp*>::value>::type* = |
| 50 | 0) _NOEXCEPTnoexcept {} |
| 51 | |
| 52 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) void operator()(_Tp* __ptr) const _NOEXCEPTnoexcept { |
| 53 | static_assert(sizeof(_Tp) > 0, |
| 54 | "default_delete can not delete incomplete type"); |
| 55 | static_assert(!is_void<_Tp>::value, |
| 56 | "default_delete can not delete incomplete type"); |
| 57 | delete __ptr; |
| 58 | } |
| 59 | }; |
| 60 | |
| 61 | template <class _Tp> |
| 62 | struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) default_delete<_Tp[]> { |
| 63 | private: |
| 64 | template <class _Up> |
| 65 | struct _EnableIfConvertible |
| 66 | : enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value> {}; |
| 67 | |
| 68 | public: |
| 69 | #ifndef _LIBCPP_CXX03_LANG |
| 70 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) constexpr default_delete() _NOEXCEPTnoexcept = default; |
| 71 | #else |
| 72 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) default_delete() {} |
| 73 | #endif |
| 74 | |
| 75 | template <class _Up> |
| 76 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 77 | default_delete(const default_delete<_Up[]>&, |
| 78 | typename _EnableIfConvertible<_Up>::type* = 0) _NOEXCEPTnoexcept {} |
| 79 | |
| 80 | template <class _Up> |
| 81 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 82 | typename _EnableIfConvertible<_Up>::type |
| 83 | operator()(_Up* __ptr) const _NOEXCEPTnoexcept { |
| 84 | static_assert(sizeof(_Tp) > 0, |
| 85 | "default_delete can not delete incomplete type"); |
| 86 | static_assert(!is_void<_Tp>::value, |
| 87 | "default_delete can not delete void type"); |
| 88 | delete[] __ptr; |
| 89 | } |
| 90 | }; |
| 91 | |
| 92 | template <class _Deleter> |
| 93 | struct __unique_ptr_deleter_sfinae { |
| 94 | static_assert(!is_reference<_Deleter>::value, "incorrect specialization"); |
| 95 | typedef const _Deleter& __lval_ref_type; |
| 96 | typedef _Deleter&& __good_rval_ref_type; |
| 97 | typedef true_type __enable_rval_overload; |
| 98 | }; |
| 99 | |
| 100 | template <class _Deleter> |
| 101 | struct __unique_ptr_deleter_sfinae<_Deleter const&> { |
| 102 | typedef const _Deleter& __lval_ref_type; |
| 103 | typedef const _Deleter&& __bad_rval_ref_type; |
| 104 | typedef false_type __enable_rval_overload; |
| 105 | }; |
| 106 | |
| 107 | template <class _Deleter> |
| 108 | struct __unique_ptr_deleter_sfinae<_Deleter&> { |
| 109 | typedef _Deleter& __lval_ref_type; |
| 110 | typedef _Deleter&& __bad_rval_ref_type; |
| 111 | typedef false_type __enable_rval_overload; |
| 112 | }; |
| 113 | |
| 114 | #if defined(_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI) |
| 115 | # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((trivial_abi)) |
| 116 | #else |
| 117 | # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI |
| 118 | #endif |
| 119 | |
| 120 | template <class _Tp, class _Dp = default_delete<_Tp> > |
| 121 | class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) unique_ptr { |
| 122 | public: |
| 123 | typedef _Tp element_type; |
| 124 | typedef _Dp deleter_type; |
| 125 | typedef _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) typename __pointer<_Tp, deleter_type>::type pointer; |
| 126 | |
| 127 | static_assert(!is_rvalue_reference<deleter_type>::value, |
| 128 | "the specified deleter type cannot be an rvalue reference"); |
| 129 | |
| 130 | private: |
| 131 | __compressed_pair<pointer, deleter_type> __ptr_; |
| 132 | |
| 133 | struct __nat { int __for_bool_; }; |
| 134 | |
| 135 | typedef _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE; |
| 136 | |
| 137 | template <bool _Dummy> |
| 138 | using _LValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
| 139 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type; |
| 140 | |
| 141 | template <bool _Dummy> |
| 142 | using _GoodRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
| 143 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type; |
| 144 | |
| 145 | template <bool _Dummy> |
| 146 | using _BadRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
| 147 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type; |
| 148 | |
| 149 | template <bool _Dummy, class _Deleter = typename __dependent_type< |
| 150 | __identity<deleter_type>, _Dummy>::type> |
| 151 | using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
| 152 | typename enable_if<is_default_constructible<_Deleter>::value && |
| 153 | !is_pointer<_Deleter>::value>::type; |
| 154 | |
| 155 | template <class _ArgType> |
| 156 | using _EnableIfDeleterConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
| 157 | typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type; |
| 158 | |
| 159 | template <class _UPtr, class _Up> |
| 160 | using _EnableIfMoveConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
| 161 | is_convertible<typename _UPtr::pointer, pointer>::value && |
| 162 | !is_array<_Up>::value |
| 163 | >::type; |
| 164 | |
| 165 | template <class _UDel> |
| 166 | using _EnableIfDeleterConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
| 167 | (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) || |
| 168 | (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) |
| 169 | >::type; |
| 170 | |
| 171 | template <class _UDel> |
| 172 | using _EnableIfDeleterAssignable = typename enable_if< |
| 173 | is_assignable<_Dp&, _UDel&&>::value |
| 174 | >::type; |
| 175 | |
| 176 | public: |
| 177 | template <bool _Dummy = true, |
| 178 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
| 179 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 180 | _LIBCPP_CONSTEXPRconstexpr unique_ptr() _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {} |
| 181 | |
| 182 | template <bool _Dummy = true, |
| 183 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
| 184 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 185 | _LIBCPP_CONSTEXPRconstexpr unique_ptr(nullptr_t) _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {} |
| 186 | |
| 187 | template <bool _Dummy = true, |
| 188 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
| 189 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 190 | explicit unique_ptr(pointer __p) _NOEXCEPTnoexcept : __ptr_(__p, __default_init_tag()) {} |
| 191 | |
| 192 | template <bool _Dummy = true, |
| 193 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > > |
| 194 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 195 | unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
| 196 | : __ptr_(__p, __d) {} |
| 197 | |
| 198 | template <bool _Dummy = true, |
| 199 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > > |
| 200 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 201 | unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
| 202 | : __ptr_(__p, _VSTDstd::__1::move(__d)) { |
| 203 | static_assert(!is_reference<deleter_type>::value, |
| 204 | "rvalue deleter bound to reference"); |
| 205 | } |
| 206 | |
| 207 | template <bool _Dummy = true, |
| 208 | class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> > > |
| 209 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 210 | unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete; |
| 211 | |
| 212 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 213 | unique_ptr(unique_ptr&& __u) _NOEXCEPTnoexcept |
| 214 | : __ptr_(__u.release(), _VSTDstd::__1::forward<deleter_type>(__u.get_deleter())) { |
| 215 | } |
| 216 | |
| 217 | template <class _Up, class _Ep, |
| 218 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
| 219 | class = _EnableIfDeleterConvertible<_Ep> |
| 220 | > |
| 221 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 222 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept |
| 223 | : __ptr_(__u.release(), _VSTDstd::__1::forward<_Ep>(__u.get_deleter())) {} |
| 224 | |
| 225 | #if _LIBCPP_STD_VER14 <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) |
| 226 | template <class _Up> |
| 227 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 228 | unique_ptr(auto_ptr<_Up>&& __p, |
| 229 | typename enable_if<is_convertible<_Up*, _Tp*>::value && |
| 230 | is_same<_Dp, default_delete<_Tp> >::value, |
| 231 | __nat>::type = __nat()) _NOEXCEPTnoexcept |
| 232 | : __ptr_(__p.release(), __default_init_tag()) {} |
| 233 | #endif |
| 234 | |
| 235 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 236 | unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPTnoexcept { |
| 237 | reset(__u.release()); |
| 238 | __ptr_.second() = _VSTDstd::__1::forward<deleter_type>(__u.get_deleter()); |
| 239 | return *this; |
| 240 | } |
| 241 | |
| 242 | template <class _Up, class _Ep, |
| 243 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
| 244 | class = _EnableIfDeleterAssignable<_Ep> |
| 245 | > |
| 246 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 247 | unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept { |
| 248 | reset(__u.release()); |
| 249 | __ptr_.second() = _VSTDstd::__1::forward<_Ep>(__u.get_deleter()); |
| 250 | return *this; |
| 251 | } |
| 252 | |
| 253 | #if _LIBCPP_STD_VER14 <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) |
| 254 | template <class _Up> |
| 255 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 256 | typename enable_if<is_convertible<_Up*, _Tp*>::value && |
| 257 | is_same<_Dp, default_delete<_Tp> >::value, |
| 258 | unique_ptr&>::type |
| 259 | operator=(auto_ptr<_Up> __p) { |
| 260 | reset(__p.release()); |
| 261 | return *this; |
| 262 | } |
| 263 | #endif |
| 264 | |
| 265 | #ifdef _LIBCPP_CXX03_LANG |
| 266 | unique_ptr(unique_ptr const&) = delete; |
| 267 | unique_ptr& operator=(unique_ptr const&) = delete; |
| 268 | #endif |
| 269 | |
| 270 | |
| 271 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 272 | ~unique_ptr() { reset(); } |
| 273 | |
| 274 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 275 | unique_ptr& operator=(nullptr_t) _NOEXCEPTnoexcept { |
| 276 | reset(); |
| 277 | return *this; |
| 278 | } |
| 279 | |
| 280 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 281 | typename add_lvalue_reference<_Tp>::type |
| 282 | operator*() const { |
| 283 | return *__ptr_.first(); |
| 284 | } |
| 285 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 286 | pointer operator->() const _NOEXCEPTnoexcept { |
| 287 | return __ptr_.first(); |
| 288 | } |
| 289 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 290 | pointer get() const _NOEXCEPTnoexcept { |
| 291 | return __ptr_.first(); |
| 292 | } |
| 293 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 294 | deleter_type& get_deleter() _NOEXCEPTnoexcept { |
| 295 | return __ptr_.second(); |
| 296 | } |
| 297 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 298 | const deleter_type& get_deleter() const _NOEXCEPTnoexcept { |
| 299 | return __ptr_.second(); |
| 300 | } |
| 301 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 302 | explicit operator bool() const _NOEXCEPTnoexcept { |
| 303 | return __ptr_.first() != nullptr; |
| 304 | } |
| 305 | |
| 306 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 307 | pointer release() _NOEXCEPTnoexcept { |
| 308 | pointer __t = __ptr_.first(); |
| 309 | __ptr_.first() = pointer(); |
| 310 | return __t; |
| 311 | } |
| 312 | |
| 313 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 314 | void reset(pointer __p = pointer()) _NOEXCEPTnoexcept { |
| 315 | pointer __tmp = __ptr_.first(); |
| 316 | __ptr_.first() = __p; |
| 317 | if (__tmp) |
| 318 | __ptr_.second()(__tmp); |
| 319 | } |
| 320 | |
| 321 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 322 | void swap(unique_ptr& __u) _NOEXCEPTnoexcept { |
| 323 | __ptr_.swap(__u.__ptr_); |
| 324 | } |
| 325 | }; |
| 326 | |
| 327 | |
| 328 | template <class _Tp, class _Dp> |
| 329 | class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) unique_ptr<_Tp[], _Dp> { |
| 330 | public: |
| 331 | typedef _Tp element_type; |
| 332 | typedef _Dp deleter_type; |
| 333 | typedef typename __pointer<_Tp, deleter_type>::type pointer; |
| 334 | |
| 335 | private: |
| 336 | __compressed_pair<pointer, deleter_type> __ptr_; |
| 337 | |
| 338 | template <class _From> |
| 339 | struct _CheckArrayPointerConversion : is_same<_From, pointer> {}; |
| 340 | |
| 341 | template <class _FromElem> |
| 342 | struct _CheckArrayPointerConversion<_FromElem*> |
| 343 | : integral_constant<bool, |
| 344 | is_same<_FromElem*, pointer>::value || |
| 345 | (is_same<pointer, element_type*>::value && |
| 346 | is_convertible<_FromElem(*)[], element_type(*)[]>::value) |
| 347 | > |
| 348 | {}; |
| 349 | |
| 350 | typedef __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE; |
| 351 | |
| 352 | template <bool _Dummy> |
| 353 | using _LValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
| 354 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type; |
| 355 | |
| 356 | template <bool _Dummy> |
| 357 | using _GoodRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
| 358 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type; |
| 359 | |
| 360 | template <bool _Dummy> |
| 361 | using _BadRValRefType _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
| 362 | typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type; |
| 363 | |
| 364 | template <bool _Dummy, class _Deleter = typename __dependent_type< |
| 365 | __identity<deleter_type>, _Dummy>::type> |
| 366 | using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
| 367 | typename enable_if<is_default_constructible<_Deleter>::value && |
| 368 | !is_pointer<_Deleter>::value>::type; |
| 369 | |
| 370 | template <class _ArgType> |
| 371 | using _EnableIfDeleterConstructible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = |
| 372 | typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type; |
| 373 | |
| 374 | template <class _Pp> |
| 375 | using _EnableIfPointerConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
| 376 | _CheckArrayPointerConversion<_Pp>::value |
| 377 | >::type; |
| 378 | |
| 379 | template <class _UPtr, class _Up, |
| 380 | class _ElemT = typename _UPtr::element_type> |
| 381 | using _EnableIfMoveConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
| 382 | is_array<_Up>::value && |
| 383 | is_same<pointer, element_type*>::value && |
| 384 | is_same<typename _UPtr::pointer, _ElemT*>::value && |
| 385 | is_convertible<_ElemT(*)[], element_type(*)[]>::value |
| 386 | >::type; |
| 387 | |
| 388 | template <class _UDel> |
| 389 | using _EnableIfDeleterConvertible _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
| 390 | (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) || |
| 391 | (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) |
| 392 | >::type; |
| 393 | |
| 394 | template <class _UDel> |
| 395 | using _EnableIfDeleterAssignable _LIBCPP_NODEBUG_TYPE__attribute__((nodebug)) = typename enable_if< |
| 396 | is_assignable<_Dp&, _UDel&&>::value |
| 397 | >::type; |
| 398 | |
| 399 | public: |
| 400 | template <bool _Dummy = true, |
| 401 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
| 402 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 403 | _LIBCPP_CONSTEXPRconstexpr unique_ptr() _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {} |
| 404 | |
| 405 | template <bool _Dummy = true, |
| 406 | class = _EnableIfDeleterDefaultConstructible<_Dummy> > |
| 407 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 408 | _LIBCPP_CONSTEXPRconstexpr unique_ptr(nullptr_t) _NOEXCEPTnoexcept : __ptr_(pointer(), __default_init_tag()) {} |
| 409 | |
| 410 | template <class _Pp, bool _Dummy = true, |
| 411 | class = _EnableIfDeleterDefaultConstructible<_Dummy>, |
| 412 | class = _EnableIfPointerConvertible<_Pp> > |
| 413 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 414 | explicit unique_ptr(_Pp __p) _NOEXCEPTnoexcept |
| 415 | : __ptr_(__p, __default_init_tag()) {} |
| 416 | |
| 417 | template <class _Pp, bool _Dummy = true, |
| 418 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >, |
| 419 | class = _EnableIfPointerConvertible<_Pp> > |
| 420 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 421 | unique_ptr(_Pp __p, _LValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
| 422 | : __ptr_(__p, __d) {} |
| 423 | |
| 424 | template <bool _Dummy = true, |
| 425 | class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > > |
| 426 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 427 | unique_ptr(nullptr_t, _LValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
| 428 | : __ptr_(nullptr, __d) {} |
| 429 | |
| 430 | template <class _Pp, bool _Dummy = true, |
| 431 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> >, |
| 432 | class = _EnableIfPointerConvertible<_Pp> > |
| 433 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 434 | unique_ptr(_Pp __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
| 435 | : __ptr_(__p, _VSTDstd::__1::move(__d)) { |
| 436 | static_assert(!is_reference<deleter_type>::value, |
| 437 | "rvalue deleter bound to reference"); |
| 438 | } |
| 439 | |
| 440 | template <bool _Dummy = true, |
| 441 | class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > > |
| 442 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 443 | unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __d) _NOEXCEPTnoexcept |
| 444 | : __ptr_(nullptr, _VSTDstd::__1::move(__d)) { |
| 445 | static_assert(!is_reference<deleter_type>::value, |
| 446 | "rvalue deleter bound to reference"); |
| 447 | } |
| 448 | |
| 449 | template <class _Pp, bool _Dummy = true, |
| 450 | class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> >, |
| 451 | class = _EnableIfPointerConvertible<_Pp> > |
| 452 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 453 | unique_ptr(_Pp __p, _BadRValRefType<_Dummy> __d) = delete; |
| 454 | |
| 455 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 456 | unique_ptr(unique_ptr&& __u) _NOEXCEPTnoexcept |
| 457 | : __ptr_(__u.release(), _VSTDstd::__1::forward<deleter_type>(__u.get_deleter())) { |
| 458 | } |
| 459 | |
| 460 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 461 | unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPTnoexcept { |
| 462 | reset(__u.release()); |
| 463 | __ptr_.second() = _VSTDstd::__1::forward<deleter_type>(__u.get_deleter()); |
| 464 | return *this; |
| 465 | } |
| 466 | |
| 467 | template <class _Up, class _Ep, |
| 468 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
| 469 | class = _EnableIfDeleterConvertible<_Ep> |
| 470 | > |
| 471 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 472 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept |
| 473 | : __ptr_(__u.release(), _VSTDstd::__1::forward<_Ep>(__u.get_deleter())) { |
| 474 | } |
| 475 | |
| 476 | template <class _Up, class _Ep, |
| 477 | class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, |
| 478 | class = _EnableIfDeleterAssignable<_Ep> |
| 479 | > |
| 480 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 481 | unique_ptr& |
| 482 | operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPTnoexcept { |
| 483 | reset(__u.release()); |
| 484 | __ptr_.second() = _VSTDstd::__1::forward<_Ep>(__u.get_deleter()); |
| 485 | return *this; |
| 486 | } |
| 487 | |
| 488 | #ifdef _LIBCPP_CXX03_LANG |
| 489 | unique_ptr(unique_ptr const&) = delete; |
| 490 | unique_ptr& operator=(unique_ptr const&) = delete; |
| 491 | #endif |
| 492 | |
| 493 | public: |
| 494 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 495 | ~unique_ptr() { reset(); } |
| 496 | |
| 497 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 498 | unique_ptr& operator=(nullptr_t) _NOEXCEPTnoexcept { |
| 499 | reset(); |
| 500 | return *this; |
| 501 | } |
| 502 | |
| 503 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 504 | typename add_lvalue_reference<_Tp>::type |
| 505 | operator[](size_t __i) const { |
| 506 | return __ptr_.first()[__i]; |
| 507 | } |
| 508 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 509 | pointer get() const _NOEXCEPTnoexcept { |
| 510 | return __ptr_.first(); |
| 511 | } |
| 512 | |
| 513 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 514 | deleter_type& get_deleter() _NOEXCEPTnoexcept { |
| 515 | return __ptr_.second(); |
| 516 | } |
| 517 | |
| 518 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 519 | const deleter_type& get_deleter() const _NOEXCEPTnoexcept { |
| 520 | return __ptr_.second(); |
| 521 | } |
| 522 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 523 | explicit operator bool() const _NOEXCEPTnoexcept { |
| 524 | return __ptr_.first() != nullptr; |
| 525 | } |
| 526 | |
| 527 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 528 | pointer release() _NOEXCEPTnoexcept { |
| 529 | pointer __t = __ptr_.first(); |
| 530 | __ptr_.first() = pointer(); |
| 531 | return __t; |
| 532 | } |
| 533 | |
| 534 | template <class _Pp> |
| 535 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 536 | typename enable_if< |
| 537 | _CheckArrayPointerConversion<_Pp>::value |
| 538 | >::type |
| 539 | reset(_Pp __p) _NOEXCEPTnoexcept { |
| 540 | pointer __tmp = __ptr_.first(); |
| 541 | __ptr_.first() = __p; |
| 542 | if (__tmp) |
| 543 | __ptr_.second()(__tmp); |
| 544 | } |
| 545 | |
| 546 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 547 | void reset(nullptr_t = nullptr) _NOEXCEPTnoexcept { |
| 548 | pointer __tmp = __ptr_.first(); |
| 549 | __ptr_.first() = nullptr; |
| 550 | if (__tmp) |
| 551 | __ptr_.second()(__tmp); |
| 552 | } |
| 553 | |
| 554 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 555 | void swap(unique_ptr& __u) _NOEXCEPTnoexcept { |
| 556 | __ptr_.swap(__u.__ptr_); |
| 557 | } |
| 558 | |
| 559 | }; |
| 560 | |
| 561 | template <class _Tp, class _Dp> |
| 562 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 563 | typename enable_if< |
| 564 | __is_swappable<_Dp>::value, |
| 565 | void |
| 566 | >::type |
| 567 | swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPTnoexcept {__x.swap(__y);} |
| 568 | |
| 569 | template <class _T1, class _D1, class _T2, class _D2> |
| 570 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 571 | bool |
| 572 | operator==(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __x.get() == __y.get();} |
| 573 | |
| 574 | template <class _T1, class _D1, class _T2, class _D2> |
| 575 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 576 | bool |
| 577 | operator!=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x == __y);} |
| 578 | |
| 579 | template <class _T1, class _D1, class _T2, class _D2> |
| 580 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 581 | bool |
| 582 | operator< (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) |
| 583 | { |
| 584 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; |
| 585 | typedef typename unique_ptr<_T2, _D2>::pointer _P2; |
| 586 | typedef typename common_type<_P1, _P2>::type _Vp; |
| 587 | return less<_Vp>()(__x.get(), __y.get()); |
| 588 | } |
| 589 | |
| 590 | template <class _T1, class _D1, class _T2, class _D2> |
| 591 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 592 | bool |
| 593 | operator> (const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __y < __x;} |
| 594 | |
| 595 | template <class _T1, class _D1, class _T2, class _D2> |
| 596 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 597 | bool |
| 598 | operator<=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__y < __x);} |
| 599 | |
| 600 | template <class _T1, class _D1, class _T2, class _D2> |
| 601 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 602 | bool |
| 603 | operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x < __y);} |
| 604 | |
| 605 | template <class _T1, class _D1> |
| 606 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 607 | bool |
| 608 | operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPTnoexcept |
| 609 | { |
| 610 | return !__x; |
| 611 | } |
| 612 | |
| 613 | template <class _T1, class _D1> |
| 614 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 615 | bool |
| 616 | operator==(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPTnoexcept |
| 617 | { |
| 618 | return !__x; |
| 619 | } |
| 620 | |
| 621 | template <class _T1, class _D1> |
| 622 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 623 | bool |
| 624 | operator!=(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPTnoexcept |
| 625 | { |
| 626 | return static_cast<bool>(__x); |
| 627 | } |
| 628 | |
| 629 | template <class _T1, class _D1> |
| 630 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 631 | bool |
| 632 | operator!=(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPTnoexcept |
| 633 | { |
| 634 | return static_cast<bool>(__x); |
| 635 | } |
| 636 | |
| 637 | template <class _T1, class _D1> |
| 638 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 639 | bool |
| 640 | operator<(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
| 641 | { |
| 642 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; |
| 643 | return less<_P1>()(__x.get(), nullptr); |
| 644 | } |
| 645 | |
| 646 | template <class _T1, class _D1> |
| 647 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 648 | bool |
| 649 | operator<(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
| 650 | { |
| 651 | typedef typename unique_ptr<_T1, _D1>::pointer _P1; |
| 652 | return less<_P1>()(nullptr, __x.get()); |
| 653 | } |
| 654 | |
| 655 | template <class _T1, class _D1> |
| 656 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 657 | bool |
| 658 | operator>(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
| 659 | { |
| 660 | return nullptr < __x; |
| 661 | } |
| 662 | |
| 663 | template <class _T1, class _D1> |
| 664 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 665 | bool |
| 666 | operator>(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
| 667 | { |
| 668 | return __x < nullptr; |
| 669 | } |
| 670 | |
| 671 | template <class _T1, class _D1> |
| 672 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 673 | bool |
| 674 | operator<=(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
| 675 | { |
| 676 | return !(nullptr < __x); |
| 677 | } |
| 678 | |
| 679 | template <class _T1, class _D1> |
| 680 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 681 | bool |
| 682 | operator<=(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
| 683 | { |
| 684 | return !(__x < nullptr); |
| 685 | } |
| 686 | |
| 687 | template <class _T1, class _D1> |
| 688 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 689 | bool |
| 690 | operator>=(const unique_ptr<_T1, _D1>& __x, nullptr_t) |
| 691 | { |
| 692 | return !(__x < nullptr); |
| 693 | } |
| 694 | |
| 695 | template <class _T1, class _D1> |
| 696 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 697 | bool |
| 698 | operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) |
| 699 | { |
| 700 | return !(nullptr < __x); |
| 701 | } |
| 702 | |
| 703 | #if _LIBCPP_STD_VER14 > 11 |
| 704 | |
| 705 | template<class _Tp> |
| 706 | struct __unique_if |
| 707 | { |
| 708 | typedef unique_ptr<_Tp> __unique_single; |
| 709 | }; |
| 710 | |
| 711 | template<class _Tp> |
| 712 | struct __unique_if<_Tp[]> |
| 713 | { |
| 714 | typedef unique_ptr<_Tp[]> __unique_array_unknown_bound; |
| 715 | }; |
| 716 | |
| 717 | template<class _Tp, size_t _Np> |
| 718 | struct __unique_if<_Tp[_Np]> |
| 719 | { |
| 720 | typedef void __unique_array_known_bound; |
| 721 | }; |
| 722 | |
| 723 | template<class _Tp, class... _Args> |
| 724 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 725 | typename __unique_if<_Tp>::__unique_single |
| 726 | make_unique(_Args&&... __args) |
| 727 | { |
| 728 | return unique_ptr<_Tp>(new _Tp(_VSTDstd::__1::forward<_Args>(__args)...)); |
| 729 | } |
| 730 | |
| 731 | template<class _Tp> |
| 732 | inline _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 733 | typename __unique_if<_Tp>::__unique_array_unknown_bound |
| 734 | make_unique(size_t __n) |
| 735 | { |
| 736 | typedef typename remove_extent<_Tp>::type _Up; |
| 737 | return unique_ptr<_Tp>(new _Up[__n]()); |
| 738 | } |
| 739 | |
| 740 | template<class _Tp, class... _Args> |
| 741 | typename __unique_if<_Tp>::__unique_array_known_bound |
| 742 | make_unique(_Args&&...) = delete; |
| 743 | |
| 744 | #endif // _LIBCPP_STD_VER > 11 |
| 745 | |
| 746 | template <class _Tp> struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) hash; |
| 747 | |
| 748 | template <class _Tp, class _Dp> |
| 749 | #ifdef _LIBCPP_CXX03_LANG |
| 750 | struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) hash<unique_ptr<_Tp, _Dp> > |
| 751 | #else |
| 752 | struct _LIBCPP_TEMPLATE_VIS__attribute__ ((__type_visibility__("default"))) hash<__enable_hash_helper< |
| 753 | unique_ptr<_Tp, _Dp>, typename unique_ptr<_Tp, _Dp>::pointer> > |
| 754 | #endif |
| 755 | { |
| 756 | #if _LIBCPP_STD_VER14 <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) |
| 757 | _LIBCPP_DEPRECATED_IN_CXX17 typedef unique_ptr<_Tp, _Dp> argument_type; |
| 758 | _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; |
| 759 | #endif |
| 760 | |
| 761 | _LIBCPP_INLINE_VISIBILITY__attribute__ ((__visibility__("hidden"))) __attribute__ ((__exclude_from_explicit_instantiation__ )) |
| 762 | size_t operator()(const unique_ptr<_Tp, _Dp>& __ptr) const |
| 763 | { |
| 764 | typedef typename unique_ptr<_Tp, _Dp>::pointer pointer; |
| 765 | return hash<pointer>()(__ptr.get()); |
| 766 | } |
| 767 | }; |
| 768 | |
| 769 | _LIBCPP_END_NAMESPACE_STD} } |
| 770 | |
| 771 | _LIBCPP_POP_MACROSpop_macro("min") pop_macro("max") |
| 772 | |
| 773 | #endif // _LIBCPP___MEMORY_UNIQUE_PTR_H |