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 16 #include "llvm/Transforms/IPO/Attributor.h" 17 18 #include "llvm/ADT/SetVector.h" 19 #include "llvm/ADT/SmallPtrSet.h" 20 #include "llvm/ADT/SmallVector.h" 21 #include "llvm/ADT/Statistic.h" 22 #include "llvm/Analysis/GlobalsModRef.h" 23 #include "llvm/IR/Argument.h" 24 #include "llvm/IR/Attributes.h" 25 #include "llvm/IR/InstIterator.h" 26 #include "llvm/Support/CommandLine.h" 27 #include "llvm/Support/Debug.h" 28 #include "llvm/Support/raw_ostream.h" 29 #include <cassert> 30 31 using namespace llvm; 32 33 #define DEBUG_TYPE "attributor" 34 35 STATISTIC(NumFnWithExactDefinition, 36 "Number of function with exact definitions"); 37 STATISTIC(NumFnWithoutExactDefinition, 38 "Number of function without exact definitions"); 39 STATISTIC(NumAttributesTimedOut, 40 "Number of abstract attributes timed out before fixpoint"); 41 STATISTIC(NumAttributesValidFixpoint, 42 "Number of abstract attributes in a valid fixpoint state"); 43 STATISTIC(NumAttributesManifested, 44 "Number of abstract attributes manifested in IR"); 45 STATISTIC(NumFnNoUnwind, "Number of functions marked nounwind"); 46 47 // TODO: Determine a good default value. 48 // 49 // In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads 50 // (when run with the first 5 abstract attributes). The results also indicate 51 // that we never reach 32 iterations but always find a fixpoint sooner. 52 // 53 // This will become more evolved once we perform two interleaved fixpoint 54 // iterations: bottom-up and top-down. 55 static cl::opt<unsigned> 56 MaxFixpointIterations("attributor-max-iterations", cl::Hidden, 57 cl::desc("Maximal number of fixpoint iterations."), 58 cl::init(32)); 59 60 static cl::opt<bool> DisableAttributor( 61 "attributor-disable", cl::Hidden, 62 cl::desc("Disable the attributor inter-procedural deduction pass."), 63 cl::init(true)); 64 65 static cl::opt<bool> VerifyAttributor( 66 "attributor-verify", cl::Hidden, 67 cl::desc("Verify the Attributor deduction and " 68 "manifestation of attributes -- may issue false-positive errors"), 69 cl::init(false)); 70 71 /// Logic operators for the change status enum class. 72 /// 73 ///{ 74 ChangeStatus llvm::operator|(ChangeStatus l, ChangeStatus r) { 75 return l == ChangeStatus::CHANGED ? l : r; 76 } 77 ChangeStatus llvm::operator&(ChangeStatus l, ChangeStatus r) { 78 return l == ChangeStatus::UNCHANGED ? l : r; 79 } 80 ///} 81 82 /// Helper to adjust the statistics. 83 static void bookkeeping(AbstractAttribute::ManifestPosition MP, 84 const Attribute &Attr) { 85 if (!AreStatisticsEnabled()) 86 return; 87 88 if (!Attr.isEnumAttribute()) 89 return; 90 switch (Attr.getKindAsEnum()) { 91 case Attribute::NoUnwind: 92 NumFnNoUnwind++; 93 return; 94 default: 95 return; 96 } 97 } 98 99 /// Helper to identify the correct offset into an attribute list. 100 static unsigned getAttrIndex(AbstractAttribute::ManifestPosition MP, 101 unsigned ArgNo = 0) { 102 switch (MP) { 103 case AbstractAttribute::MP_ARGUMENT: 104 case AbstractAttribute::MP_CALL_SITE_ARGUMENT: 105 return ArgNo + AttributeList::FirstArgIndex; 106 case AbstractAttribute::MP_FUNCTION: 107 return AttributeList::FunctionIndex; 108 case AbstractAttribute::MP_RETURNED: 109 return AttributeList::ReturnIndex; 110 } 111 llvm_unreachable("Unknown manifest position!"); 112 } 113 114 /// Return true if \p New is equal or worse than \p Old. 115 static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) { 116 if (!Old.isIntAttribute()) 117 return true; 118 119 return Old.getValueAsInt() >= New.getValueAsInt(); 120 } 121 122 /// Return true if the information provided by \p Attr was added to the 123 /// attribute list \p Attrs. This is only the case if it was not already present 124 /// in \p Attrs at the position describe by \p MP and \p ArgNo. 125 static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr, 126 AttributeList &Attrs, 127 AbstractAttribute::ManifestPosition MP, 128 unsigned ArgNo = 0) { 129 unsigned AttrIdx = getAttrIndex(MP, ArgNo); 130 131 if (Attr.isEnumAttribute()) { 132 Attribute::AttrKind Kind = Attr.getKindAsEnum(); 133 if (Attrs.hasAttribute(AttrIdx, Kind)) 134 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind))) 135 return false; 136 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr); 137 return true; 138 } 139 if (Attr.isStringAttribute()) { 140 StringRef Kind = Attr.getKindAsString(); 141 if (Attrs.hasAttribute(AttrIdx, Kind)) 142 if (isEqualOrWorse(Attr, Attrs.getAttribute(AttrIdx, Kind))) 143 return false; 144 Attrs = Attrs.addAttribute(Ctx, AttrIdx, Attr); 145 return true; 146 } 147 148 llvm_unreachable("Expected enum or string attribute!"); 149 } 150 151 ChangeStatus AbstractAttribute::update(Attributor &A) { 152 ChangeStatus HasChanged = ChangeStatus::UNCHANGED; 153 if (getState().isAtFixpoint()) 154 return HasChanged; 155 156 LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n"); 157 158 HasChanged = updateImpl(A); 159 160 LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this 161 << "\n"); 162 163 return HasChanged; 164 } 165 166 ChangeStatus AbstractAttribute::manifest(Attributor &A) { 167 assert(getState().isValidState() && 168 "Attempted to manifest an invalid state!"); 169 assert(getAssociatedValue() && 170 "Attempted to manifest an attribute without associated value!"); 171 172 ChangeStatus HasChanged = ChangeStatus::UNCHANGED; 173 SmallVector<Attribute, 4> DeducedAttrs; 174 getDeducedAttributes(DeducedAttrs); 175 176 Function &ScopeFn = getAnchorScope(); 177 LLVMContext &Ctx = ScopeFn.getContext(); 178 ManifestPosition MP = getManifestPosition(); 179 180 AttributeList Attrs; 181 SmallVector<unsigned, 4> ArgNos; 182 183 // In the following some generic code that will manifest attributes in 184 // DeducedAttrs if they improve the current IR. Due to the different 185 // annotation positions we use the underlying AttributeList interface. 186 // Note that MP_CALL_SITE_ARGUMENT can annotate multiple locations. 187 188 switch (MP) { 189 case MP_ARGUMENT: 190 ArgNos.push_back(cast<Argument>(getAssociatedValue())->getArgNo()); 191 Attrs = ScopeFn.getAttributes(); 192 break; 193 case MP_FUNCTION: 194 case MP_RETURNED: 195 ArgNos.push_back(0); 196 Attrs = ScopeFn.getAttributes(); 197 break; 198 case MP_CALL_SITE_ARGUMENT: { 199 CallSite CS(&getAnchoredValue()); 200 for (unsigned u = 0, e = CS.getNumArgOperands(); u != e; u++) 201 if (CS.getArgOperand(u) == getAssociatedValue()) 202 ArgNos.push_back(u); 203 Attrs = CS.getAttributes(); 204 } 205 } 206 207 for (const Attribute &Attr : DeducedAttrs) { 208 for (unsigned ArgNo : ArgNos) { 209 if (!addIfNotExistent(Ctx, Attr, Attrs, MP, ArgNo)) 210 continue; 211 212 HasChanged = ChangeStatus::CHANGED; 213 bookkeeping(MP, Attr); 214 } 215 } 216 217 if (HasChanged == ChangeStatus::UNCHANGED) 218 return HasChanged; 219 220 switch (MP) { 221 case MP_ARGUMENT: 222 case MP_FUNCTION: 223 case MP_RETURNED: 224 ScopeFn.setAttributes(Attrs); 225 break; 226 case MP_CALL_SITE_ARGUMENT: 227 CallSite(&getAnchoredValue()).setAttributes(Attrs); 228 } 229 230 return HasChanged; 231 } 232 233 Function &AbstractAttribute::getAnchorScope() { 234 Value &V = getAnchoredValue(); 235 if (isa<Function>(V)) 236 return cast<Function>(V); 237 if (isa<Argument>(V)) 238 return *cast<Argument>(V).getParent(); 239 if (isa<Instruction>(V)) 240 return *cast<Instruction>(V).getFunction(); 241 llvm_unreachable("No scope for anchored value found!"); 242 } 243 244 const Function &AbstractAttribute::getAnchorScope() const { 245 return const_cast<AbstractAttribute *>(this)->getAnchorScope(); 246 } 247 248 /// -----------------------NoUnwind Function Attribute-------------------------- 249 250 struct AANoUnwindFunction : AANoUnwind, BooleanState { 251 252 AANoUnwindFunction(Function &F, InformationCache &InfoCache) 253 : AANoUnwind(F, InfoCache) {} 254 255 /// See AbstractAttribute::getState() 256 /// { 257 AbstractState &getState() override { return *this; } 258 const AbstractState &getState() const override { return *this; } 259 /// } 260 261 /// See AbstractAttribute::getManifestPosition(). 262 virtual ManifestPosition getManifestPosition() const override { 263 return MP_FUNCTION; 264 } 265 266 virtual const std::string getAsStr() const override { 267 return getAssumed() ? "nounwind" : "may-unwind"; 268 } 269 270 /// See AbstractAttribute::updateImpl(...). 271 virtual ChangeStatus updateImpl(Attributor &A) override; 272 273 /// See AANoUnwind::isAssumedNoUnwind(). 274 virtual bool isAssumedNoUnwind() const override { return getAssumed(); } 275 276 /// See AANoUnwind::isKnownNoUnwind(). 277 virtual bool isKnownNoUnwind() const override { return getKnown(); } 278 }; 279 280 ChangeStatus AANoUnwindFunction::updateImpl(Attributor &A) { 281 Function &F = getAnchorScope(); 282 283 // The map from instruction opcodes to those instructions in the function. 284 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F); 285 auto Opcodes = { 286 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr, 287 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet, 288 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume}; 289 290 for (unsigned Opcode : Opcodes) { 291 for (Instruction *I : OpcodeInstMap[Opcode]) { 292 if (!I->mayThrow()) 293 continue; 294 295 auto *NoUnwindAA = A.getAAFor<AANoUnwind>(*this, *I); 296 297 if (!NoUnwindAA || !NoUnwindAA->isAssumedNoUnwind()) { 298 indicatePessimisticFixpoint(); 299 return ChangeStatus::CHANGED; 300 } 301 } 302 } 303 return ChangeStatus::UNCHANGED; 304 } 305 306 /// ---------------------------------------------------------------------------- 307 /// Attributor 308 /// ---------------------------------------------------------------------------- 309 310 ChangeStatus Attributor::run() { 311 // Initialize all abstract attributes. 312 for (AbstractAttribute *AA : AllAbstractAttributes) 313 AA->initialize(*this); 314 315 LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized " 316 << AllAbstractAttributes.size() 317 << " abstract attributes.\n"); 318 319 // Now that all abstract attributes are collected and initialized we start 320 // the abstract analysis. 321 322 unsigned IterationCounter = 1; 323 324 SmallVector<AbstractAttribute *, 64> ChangedAAs; 325 SetVector<AbstractAttribute *> Worklist; 326 Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end()); 327 328 do { 329 LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter 330 << ", Worklist size: " << Worklist.size() << "\n"); 331 332 // Add all abstract attributes that are potentially dependent on one that 333 // changed to the work list. 334 for (AbstractAttribute *ChangedAA : ChangedAAs) { 335 auto &QuerriedAAs = QueryMap[ChangedAA]; 336 Worklist.insert(QuerriedAAs.begin(), QuerriedAAs.end()); 337 } 338 339 // Reset the changed set. 340 ChangedAAs.clear(); 341 342 // Update all abstract attribute in the work list and record the ones that 343 // changed. 344 for (AbstractAttribute *AA : Worklist) 345 if (AA->update(*this) == ChangeStatus::CHANGED) 346 ChangedAAs.push_back(AA); 347 348 // Reset the work list and repopulate with the changed abstract attributes. 349 // Note that dependent ones are added above. 350 Worklist.clear(); 351 Worklist.insert(ChangedAAs.begin(), ChangedAAs.end()); 352 353 } while (!Worklist.empty() && ++IterationCounter < MaxFixpointIterations); 354 355 LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: " 356 << IterationCounter << "/" << MaxFixpointIterations 357 << " iterations\n"); 358 359 bool FinishedAtFixpoint = Worklist.empty(); 360 361 // Reset abstract arguments not settled in a sound fixpoint by now. This 362 // happens when we stopped the fixpoint iteration early. Note that only the 363 // ones marked as "changed" *and* the ones transitively depending on them 364 // need to be reverted to a pessimistic state. Others might not be in a 365 // fixpoint state but we can use the optimistic results for them anyway. 366 SmallPtrSet<AbstractAttribute *, 32> Visited; 367 for (unsigned u = 0; u < ChangedAAs.size(); u++) { 368 AbstractAttribute *ChangedAA = ChangedAAs[u]; 369 if (!Visited.insert(ChangedAA).second) 370 continue; 371 372 AbstractState &State = ChangedAA->getState(); 373 if (!State.isAtFixpoint()) { 374 State.indicatePessimisticFixpoint(); 375 376 NumAttributesTimedOut++; 377 } 378 379 auto &QuerriedAAs = QueryMap[ChangedAA]; 380 ChangedAAs.append(QuerriedAAs.begin(), QuerriedAAs.end()); 381 } 382 383 LLVM_DEBUG({ 384 if (!Visited.empty()) 385 dbgs() << "\n[Attributor] Finalized " << Visited.size() 386 << " abstract attributes.\n"; 387 }); 388 389 unsigned NumManifested = 0; 390 unsigned NumAtFixpoint = 0; 391 ChangeStatus ManifestChange = ChangeStatus::UNCHANGED; 392 for (AbstractAttribute *AA : AllAbstractAttributes) { 393 AbstractState &State = AA->getState(); 394 395 // If there is not already a fixpoint reached, we can now take the 396 // optimistic state. This is correct because we enforced a pessimistic one 397 // on abstract attributes that were transitively dependent on a changed one 398 // already above. 399 if (!State.isAtFixpoint()) 400 State.indicateOptimisticFixpoint(); 401 402 // If the state is invalid, we do not try to manifest it. 403 if (!State.isValidState()) 404 continue; 405 406 // Manifest the state and record if we changed the IR. 407 ChangeStatus LocalChange = AA->manifest(*this); 408 ManifestChange = ManifestChange | LocalChange; 409 410 NumAtFixpoint++; 411 NumManifested += (LocalChange == ChangeStatus::CHANGED); 412 } 413 414 (void)NumManifested; 415 (void)NumAtFixpoint; 416 LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested 417 << " arguments while " << NumAtFixpoint 418 << " were in a valid fixpoint state\n"); 419 420 // If verification is requested, we finished this run at a fixpoint, and the 421 // IR was changed, we re-run the whole fixpoint analysis, starting at 422 // re-initialization of the arguments. This re-run should not result in an IR 423 // change. Though, the (virtual) state of attributes at the end of the re-run 424 // might be more optimistic than the known state or the IR state if the better 425 // state cannot be manifested. 426 if (VerifyAttributor && FinishedAtFixpoint && 427 ManifestChange == ChangeStatus::CHANGED) { 428 VerifyAttributor = false; 429 ChangeStatus VerifyStatus = run(); 430 if (VerifyStatus != ChangeStatus::UNCHANGED) 431 llvm_unreachable( 432 "Attributor verification failed, re-run did result in an IR change " 433 "even after a fixpoint was reached in the original run. (False " 434 "positives possible!)"); 435 VerifyAttributor = true; 436 } 437 438 NumAttributesManifested += NumManifested; 439 NumAttributesValidFixpoint += NumAtFixpoint; 440 441 return ManifestChange; 442 } 443 444 void Attributor::identifyDefaultAbstractAttributes( 445 Function &F, InformationCache &InfoCache, 446 DenseSet</* Attribute::AttrKind */ unsigned> *Whitelist) { 447 448 // Every function can be nounwind. 449 registerAA(*new AANoUnwindFunction(F, InfoCache)); 450 451 // Walk all instructions to find more attribute opportunities and also 452 // interesting instructions that might be queried by abstract attributes 453 // during their initialization or update. 454 auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F]; 455 auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F]; 456 457 for (Instruction &I : instructions(&F)) { 458 bool IsInterestingOpcode = false; 459 460 // To allow easy access to all instructions in a function with a given 461 // opcode we store them in the InfoCache. As not all opcodes are interesting 462 // to concrete attributes we only cache the ones that are as identified in 463 // the following switch. 464 // Note: There are no concrete attributes now so this is initially empty. 465 switch (I.getOpcode()) { 466 default: 467 assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) && 468 "New call site/base instruction type needs to be known int the " 469 "attributor."); 470 break; 471 case Instruction::Call: 472 case Instruction::CallBr: 473 case Instruction::Invoke: 474 case Instruction::CleanupRet: 475 case Instruction::CatchSwitch: 476 case Instruction::Resume: 477 IsInterestingOpcode = true; 478 } 479 if (IsInterestingOpcode) 480 InstOpcodeMap[I.getOpcode()].push_back(&I); 481 if (I.mayReadOrWriteMemory()) 482 ReadOrWriteInsts.push_back(&I); 483 } 484 } 485 486 /// Helpers to ease debugging through output streams and print calls. 487 /// 488 ///{ 489 raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) { 490 return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged"); 491 } 492 493 raw_ostream &llvm::operator<<(raw_ostream &OS, 494 AbstractAttribute::ManifestPosition AP) { 495 switch (AP) { 496 case AbstractAttribute::MP_ARGUMENT: 497 return OS << "arg"; 498 case AbstractAttribute::MP_CALL_SITE_ARGUMENT: 499 return OS << "cs_arg"; 500 case AbstractAttribute::MP_FUNCTION: 501 return OS << "fn"; 502 case AbstractAttribute::MP_RETURNED: 503 return OS << "fn_ret"; 504 } 505 llvm_unreachable("Unknown attribute position!"); 506 } 507 508 raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) { 509 return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : "")); 510 } 511 512 raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) { 513 AA.print(OS); 514 return OS; 515 } 516 517 void AbstractAttribute::print(raw_ostream &OS) const { 518 OS << "[" << getManifestPosition() << "][" << getAsStr() << "][" 519 << AnchoredVal.getName() << "]"; 520 } 521 ///} 522 523 /// ---------------------------------------------------------------------------- 524 /// Pass (Manager) Boilerplate 525 /// ---------------------------------------------------------------------------- 526 527 static bool runAttributorOnModule(Module &M) { 528 if (DisableAttributor) 529 return false; 530 531 LLVM_DEBUG(dbgs() << "[Attributor] Run on module with " << M.size() 532 << " functions.\n"); 533 534 // Create an Attributor and initially empty information cache that is filled 535 // while we identify default attribute opportunities. 536 Attributor A; 537 InformationCache InfoCache; 538 539 for (Function &F : M) { 540 // TODO: Not all attributes require an exact definition. Find a way to 541 // enable deduction for some but not all attributes in case the 542 // definition might be changed at runtime, see also 543 // http://lists.llvm.org/pipermail/llvm-dev/2018-February/121275.html. 544 // TODO: We could always determine abstract attributes and if sufficient 545 // information was found we could duplicate the functions that do not 546 // have an exact definition. 547 if (!F.hasExactDefinition()) { 548 NumFnWithoutExactDefinition++; 549 continue; 550 } 551 552 // For now we ignore naked and optnone functions. 553 if (F.hasFnAttribute(Attribute::Naked) || 554 F.hasFnAttribute(Attribute::OptimizeNone)) 555 continue; 556 557 NumFnWithExactDefinition++; 558 559 // Populate the Attributor with abstract attribute opportunities in the 560 // function and the information cache with IR information. 561 A.identifyDefaultAbstractAttributes(F, InfoCache); 562 } 563 564 return A.run() == ChangeStatus::CHANGED; 565 } 566 567 PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) { 568 if (runAttributorOnModule(M)) { 569 // FIXME: Think about passes we will preserve and add them here. 570 return PreservedAnalyses::none(); 571 } 572 return PreservedAnalyses::all(); 573 } 574 575 namespace { 576 577 struct AttributorLegacyPass : public ModulePass { 578 static char ID; 579 580 AttributorLegacyPass() : ModulePass(ID) { 581 initializeAttributorLegacyPassPass(*PassRegistry::getPassRegistry()); 582 } 583 584 bool runOnModule(Module &M) override { 585 if (skipModule(M)) 586 return false; 587 return runAttributorOnModule(M); 588 } 589 590 void getAnalysisUsage(AnalysisUsage &AU) const override { 591 // FIXME: Think about passes we will preserve and add them here. 592 AU.setPreservesCFG(); 593 } 594 }; 595 596 } // end anonymous namespace 597 598 Pass *llvm::createAttributorLegacyPass() { return new AttributorLegacyPass(); } 599 600 char AttributorLegacyPass::ID = 0; 601 INITIALIZE_PASS_BEGIN(AttributorLegacyPass, "attributor", 602 "Deduce and propagate attributes", false, false) 603 INITIALIZE_PASS_END(AttributorLegacyPass, "attributor", 604 "Deduce and propagate attributes", false, false) 605