1 //===-- LibCallsShrinkWrap.cpp ----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This pass shrink-wraps a call to function if the result is not used. 11 // The call can set errno but is otherwise side effect free. For example: 12 // sqrt(val); 13 // is transformed to 14 // if (val < 0) 15 // sqrt(val); 16 // Even if the result of library call is not being used, the compiler cannot 17 // safely delete the call because the function can set errno on error 18 // conditions. 19 // Note in many functions, the error condition solely depends on the incoming 20 // parameter. In this optimization, we can generate the condition can lead to 21 // the errno to shrink-wrap the call. Since the chances of hitting the error 22 // condition is low, the runtime call is effectively eliminated. 23 // 24 // These partially dead calls are usually results of C++ abstraction penalty 25 // exposed by inlining. 26 // 27 //===----------------------------------------------------------------------===// 28 29 #include "llvm/Transforms/Utils/LibCallsShrinkWrap.h" 30 #include "llvm/ADT/SmallVector.h" 31 #include "llvm/ADT/Statistic.h" 32 #include "llvm/Analysis/GlobalsModRef.h" 33 #include "llvm/Analysis/TargetLibraryInfo.h" 34 #include "llvm/IR/CFG.h" 35 #include "llvm/IR/Constants.h" 36 #include "llvm/IR/Function.h" 37 #include "llvm/IR/IRBuilder.h" 38 #include "llvm/IR/InstVisitor.h" 39 #include "llvm/IR/Instructions.h" 40 #include "llvm/IR/LLVMContext.h" 41 #include "llvm/IR/MDBuilder.h" 42 #include "llvm/Pass.h" 43 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 44 using namespace llvm; 45 46 #define DEBUG_TYPE "libcalls-shrinkwrap" 47 48 STATISTIC(NumWrappedOneCond, "Number of One-Condition Wrappers Inserted"); 49 STATISTIC(NumWrappedTwoCond, "Number of Two-Condition Wrappers Inserted"); 50 51 static cl::opt<bool> LibCallsShrinkWrapDoDomainError( 52 "libcalls-shrinkwrap-domain-error", cl::init(true), cl::Hidden, 53 cl::desc("Perform shrink-wrap on lib calls with domain errors")); 54 static cl::opt<bool> LibCallsShrinkWrapDoRangeError( 55 "libcalls-shrinkwrap-range-error", cl::init(true), cl::Hidden, 56 cl::desc("Perform shrink-wrap on lib calls with range errors")); 57 static cl::opt<bool> LibCallsShrinkWrapDoPoleError( 58 "libcalls-shrinkwrap-pole-error", cl::init(true), cl::Hidden, 59 cl::desc("Perform shrink-wrap on lib calls with pole errors")); 60 61 namespace { 62 class LibCallsShrinkWrapLegacyPass : public FunctionPass { 63 public: 64 static char ID; // Pass identification, replacement for typeid 65 explicit LibCallsShrinkWrapLegacyPass() : FunctionPass(ID) { 66 initializeLibCallsShrinkWrapLegacyPassPass( 67 *PassRegistry::getPassRegistry()); 68 } 69 void getAnalysisUsage(AnalysisUsage &AU) const override; 70 bool runOnFunction(Function &F) override; 71 }; 72 } 73 74 char LibCallsShrinkWrapLegacyPass::ID = 0; 75 INITIALIZE_PASS_BEGIN(LibCallsShrinkWrapLegacyPass, "libcalls-shrinkwrap", 76 "Conditionally eliminate dead library calls", false, 77 false) 78 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) 79 INITIALIZE_PASS_END(LibCallsShrinkWrapLegacyPass, "libcalls-shrinkwrap", 80 "Conditionally eliminate dead library calls", false, false) 81 82 namespace { 83 class LibCallsShrinkWrap : public InstVisitor<LibCallsShrinkWrap> { 84 public: 85 LibCallsShrinkWrap(const TargetLibraryInfo &TLI) : TLI(TLI), Changed(false){}; 86 bool isChanged() const { return Changed; } 87 void visitCallInst(CallInst &CI) { checkCandidate(CI); } 88 void perform() { 89 for (auto &CI : WorkList) { 90 DEBUG(dbgs() << "CDCE calls: " << CI->getCalledFunction()->getName() 91 << "\n"); 92 if (perform(CI)) { 93 Changed = true; 94 DEBUG(dbgs() << "Transformed\n"); 95 } 96 } 97 } 98 99 private: 100 bool perform(CallInst *CI); 101 void checkCandidate(CallInst &CI); 102 void shrinkWrapCI(CallInst *CI, Value *Cond); 103 bool performCallDomainErrorOnly(CallInst *CI, const LibFunc::Func &Func); 104 bool performCallErrors(CallInst *CI, const LibFunc::Func &Func); 105 bool performCallRangeErrorOnly(CallInst *CI, const LibFunc::Func &Func); 106 Value *generateOneRangeCond(CallInst *CI, const LibFunc::Func &Func); 107 Value *generateTwoRangeCond(CallInst *CI, const LibFunc::Func &Func); 108 Value *generateCondForPow(CallInst *CI, const LibFunc::Func &Func); 109 110 // Create an OR of two conditions. 111 Value *createOrCond(CallInst *CI, CmpInst::Predicate Cmp, float Val, 112 CmpInst::Predicate Cmp2, float Val2) { 113 IRBuilder<> BBBuilder(CI); 114 Value *Arg = CI->getArgOperand(0); 115 auto Cond2 = createCond(BBBuilder, Arg, Cmp2, Val2); 116 auto Cond1 = createCond(BBBuilder, Arg, Cmp, Val); 117 return BBBuilder.CreateOr(Cond1, Cond2); 118 } 119 120 // Create a single condition using IRBuilder. 121 Value *createCond(IRBuilder<> &BBBuilder, Value *Arg, CmpInst::Predicate Cmp, 122 float Val) { 123 Constant *V = ConstantFP::get(BBBuilder.getContext(), APFloat(Val)); 124 if (!Arg->getType()->isFloatTy()) 125 V = ConstantExpr::getFPExtend(V, Arg->getType()); 126 return BBBuilder.CreateFCmp(Cmp, Arg, V); 127 } 128 129 // Create a single condition. 130 Value *createCond(CallInst *CI, CmpInst::Predicate Cmp, float Val) { 131 IRBuilder<> BBBuilder(CI); 132 Value *Arg = CI->getArgOperand(0); 133 return createCond(BBBuilder, Arg, Cmp, Val); 134 } 135 136 const TargetLibraryInfo &TLI; 137 SmallVector<CallInst *, 16> WorkList; 138 bool Changed; 139 }; 140 } // end anonymous namespace 141 142 // Perform the transformation to calls with errno set by domain error. 143 bool LibCallsShrinkWrap::performCallDomainErrorOnly(CallInst *CI, 144 const LibFunc::Func &Func) { 145 Value *Cond = nullptr; 146 147 switch (Func) { 148 case LibFunc::acos: // DomainError: (x < -1 || x > 1) 149 case LibFunc::acosf: // Same as acos 150 case LibFunc::acosl: // Same as acos 151 case LibFunc::asin: // DomainError: (x < -1 || x > 1) 152 case LibFunc::asinf: // Same as asin 153 case LibFunc::asinl: // Same as asin 154 { 155 ++NumWrappedTwoCond; 156 Cond = createOrCond(CI, CmpInst::FCMP_OLT, -1.0f, CmpInst::FCMP_OGT, 1.0f); 157 break; 158 } 159 case LibFunc::cos: // DomainError: (x == +inf || x == -inf) 160 case LibFunc::cosf: // Same as cos 161 case LibFunc::cosl: // Same as cos 162 case LibFunc::sin: // DomainError: (x == +inf || x == -inf) 163 case LibFunc::sinf: // Same as sin 164 case LibFunc::sinl: // Same as sin 165 { 166 ++NumWrappedTwoCond; 167 Cond = createOrCond(CI, CmpInst::FCMP_OEQ, INFINITY, CmpInst::FCMP_OEQ, 168 -INFINITY); 169 break; 170 } 171 case LibFunc::acosh: // DomainError: (x < 1) 172 case LibFunc::acoshf: // Same as acosh 173 case LibFunc::acoshl: // Same as acosh 174 { 175 ++NumWrappedOneCond; 176 Cond = createCond(CI, CmpInst::FCMP_OLT, 1.0f); 177 break; 178 } 179 case LibFunc::sqrt: // DomainError: (x < 0) 180 case LibFunc::sqrtf: // Same as sqrt 181 case LibFunc::sqrtl: // Same as sqrt 182 { 183 ++NumWrappedOneCond; 184 Cond = createCond(CI, CmpInst::FCMP_OLT, 0.0f); 185 break; 186 } 187 default: 188 return false; 189 } 190 shrinkWrapCI(CI, Cond); 191 return true; 192 } 193 194 // Perform the transformation to calls with errno set by range error. 195 bool LibCallsShrinkWrap::performCallRangeErrorOnly(CallInst *CI, 196 const LibFunc::Func &Func) { 197 Value *Cond = nullptr; 198 199 switch (Func) { 200 case LibFunc::cosh: 201 case LibFunc::coshf: 202 case LibFunc::coshl: 203 case LibFunc::exp: 204 case LibFunc::expf: 205 case LibFunc::expl: 206 case LibFunc::exp10: 207 case LibFunc::exp10f: 208 case LibFunc::exp10l: 209 case LibFunc::exp2: 210 case LibFunc::exp2f: 211 case LibFunc::exp2l: 212 case LibFunc::sinh: 213 case LibFunc::sinhf: 214 case LibFunc::sinhl: { 215 Cond = generateTwoRangeCond(CI, Func); 216 break; 217 } 218 case LibFunc::expm1: // RangeError: (709, inf) 219 case LibFunc::expm1f: // RangeError: (88, inf) 220 case LibFunc::expm1l: // RangeError: (11356, inf) 221 { 222 Cond = generateOneRangeCond(CI, Func); 223 break; 224 } 225 default: 226 return false; 227 } 228 shrinkWrapCI(CI, Cond); 229 return true; 230 } 231 232 // Perform the transformation to calls with errno set by combination of errors. 233 bool LibCallsShrinkWrap::performCallErrors(CallInst *CI, 234 const LibFunc::Func &Func) { 235 Value *Cond = nullptr; 236 237 switch (Func) { 238 case LibFunc::atanh: // DomainError: (x < -1 || x > 1) 239 // PoleError: (x == -1 || x == 1) 240 // Overall Cond: (x <= -1 || x >= 1) 241 case LibFunc::atanhf: // Same as atanh 242 case LibFunc::atanhl: // Same as atanh 243 { 244 if (!LibCallsShrinkWrapDoDomainError || !LibCallsShrinkWrapDoPoleError) 245 return false; 246 ++NumWrappedTwoCond; 247 Cond = createOrCond(CI, CmpInst::FCMP_OLE, -1.0f, CmpInst::FCMP_OGE, 1.0f); 248 break; 249 } 250 case LibFunc::log: // DomainError: (x < 0) 251 // PoleError: (x == 0) 252 // Overall Cond: (x <= 0) 253 case LibFunc::logf: // Same as log 254 case LibFunc::logl: // Same as log 255 case LibFunc::log10: // Same as log 256 case LibFunc::log10f: // Same as log 257 case LibFunc::log10l: // Same as log 258 case LibFunc::log2: // Same as log 259 case LibFunc::log2f: // Same as log 260 case LibFunc::log2l: // Same as log 261 case LibFunc::logb: // Same as log 262 case LibFunc::logbf: // Same as log 263 case LibFunc::logbl: // Same as log 264 { 265 if (!LibCallsShrinkWrapDoDomainError || !LibCallsShrinkWrapDoPoleError) 266 return false; 267 ++NumWrappedOneCond; 268 Cond = createCond(CI, CmpInst::FCMP_OLE, 0.0f); 269 break; 270 } 271 case LibFunc::log1p: // DomainError: (x < -1) 272 // PoleError: (x == -1) 273 // Overall Cond: (x <= -1) 274 case LibFunc::log1pf: // Same as log1p 275 case LibFunc::log1pl: // Same as log1p 276 { 277 if (!LibCallsShrinkWrapDoDomainError || !LibCallsShrinkWrapDoPoleError) 278 return false; 279 ++NumWrappedOneCond; 280 Cond = createCond(CI, CmpInst::FCMP_OLE, -1.0f); 281 break; 282 } 283 case LibFunc::pow: // DomainError: x < 0 and y is noninteger 284 // PoleError: x == 0 and y < 0 285 // RangeError: overflow or underflow 286 case LibFunc::powf: 287 case LibFunc::powl: { 288 if (!LibCallsShrinkWrapDoDomainError || !LibCallsShrinkWrapDoPoleError || 289 !LibCallsShrinkWrapDoRangeError) 290 return false; 291 Cond = generateCondForPow(CI, Func); 292 if (Cond == nullptr) 293 return false; 294 break; 295 } 296 default: 297 return false; 298 } 299 assert(Cond && "performCallErrors should not see an empty condition"); 300 shrinkWrapCI(CI, Cond); 301 return true; 302 } 303 304 // Checks if CI is a candidate for shrinkwrapping and put it into work list if 305 // true. 306 void LibCallsShrinkWrap::checkCandidate(CallInst &CI) { 307 if (CI.isNoBuiltin()) 308 return; 309 // A possible improvement is to handle the calls with the return value being 310 // used. If there is API for fast libcall implementation without setting 311 // errno, we can use the same framework to direct/wrap the call to the fast 312 // API in the error free path, and leave the original call in the slow path. 313 if (!CI.use_empty()) 314 return; 315 316 LibFunc::Func Func; 317 Function *Callee = CI.getCalledFunction(); 318 if (!Callee) 319 return; 320 if (!TLI.getLibFunc(*Callee, Func) || !TLI.has(Func)) 321 return; 322 323 if (CI.getNumArgOperands() == 0) 324 return; 325 // TODO: Handle long double in other formats. 326 Type *ArgType = CI.getArgOperand(0)->getType(); 327 if (!(ArgType->isFloatTy() || ArgType->isDoubleTy() || 328 ArgType->isX86_FP80Ty())) 329 return; 330 331 WorkList.push_back(&CI); 332 } 333 334 // Generate the upper bound condition for RangeError. 335 Value *LibCallsShrinkWrap::generateOneRangeCond(CallInst *CI, 336 const LibFunc::Func &Func) { 337 float UpperBound; 338 switch (Func) { 339 case LibFunc::expm1: // RangeError: (709, inf) 340 UpperBound = 709.0f; 341 break; 342 case LibFunc::expm1f: // RangeError: (88, inf) 343 UpperBound = 88.0f; 344 break; 345 case LibFunc::expm1l: // RangeError: (11356, inf) 346 UpperBound = 11356.0f; 347 break; 348 default: 349 llvm_unreachable("Should be reach here"); 350 } 351 352 ++NumWrappedOneCond; 353 return createCond(CI, CmpInst::FCMP_OGT, UpperBound); 354 } 355 356 // Generate the lower and upper bound condition for RangeError. 357 Value *LibCallsShrinkWrap::generateTwoRangeCond(CallInst *CI, 358 const LibFunc::Func &Func) { 359 float UpperBound, LowerBound; 360 switch (Func) { 361 case LibFunc::cosh: // RangeError: (x < -710 || x > 710) 362 case LibFunc::sinh: // Same as cosh 363 LowerBound = -710.0f; 364 UpperBound = 710.0f; 365 break; 366 case LibFunc::coshf: // RangeError: (x < -89 || x > 89) 367 case LibFunc::sinhf: // Same as coshf 368 LowerBound = -89.0f; 369 UpperBound = 89.0f; 370 break; 371 case LibFunc::coshl: // RangeError: (x < -11357 || x > 11357) 372 case LibFunc::sinhl: // Same as coshl 373 LowerBound = -11357.0f; 374 UpperBound = 11357.0f; 375 break; 376 case LibFunc::exp: // RangeError: (x < -745 || x > 709) 377 LowerBound = -745.0f; 378 UpperBound = 709.0f; 379 break; 380 case LibFunc::expf: // RangeError: (x < -103 || x > 88) 381 LowerBound = -103.0f; 382 UpperBound = 88.0f; 383 break; 384 case LibFunc::expl: // RangeError: (x < -11399 || x > 11356) 385 LowerBound = -11399.0f; 386 UpperBound = 11356.0f; 387 break; 388 case LibFunc::exp10: // RangeError: (x < -323 || x > 308) 389 LowerBound = -323.0f; 390 UpperBound = 308.0f; 391 break; 392 case LibFunc::exp10f: // RangeError: (x < -45 || x > 38) 393 LowerBound = -45.0f; 394 UpperBound = 38.0f; 395 break; 396 case LibFunc::exp10l: // RangeError: (x < -4950 || x > 4932) 397 LowerBound = -4950.0f; 398 UpperBound = 4932.0f; 399 break; 400 case LibFunc::exp2: // RangeError: (x < -1074 || x > 1023) 401 LowerBound = -1074.0f; 402 UpperBound = 1023.0f; 403 break; 404 case LibFunc::exp2f: // RangeError: (x < -149 || x > 127) 405 LowerBound = -149.0f; 406 UpperBound = 127.0f; 407 break; 408 case LibFunc::exp2l: // RangeError: (x < -16445 || x > 11383) 409 LowerBound = -16445.0f; 410 UpperBound = 11383.0f; 411 break; 412 default: 413 llvm_unreachable("Should be reach here"); 414 } 415 416 ++NumWrappedTwoCond; 417 return createOrCond(CI, CmpInst::FCMP_OGT, UpperBound, CmpInst::FCMP_OLT, 418 LowerBound); 419 } 420 421 // For pow(x,y), We only handle the following cases: 422 // (1) x is a constant && (x >= 1) && (x < MaxUInt8) 423 // Cond is: (y > 127) 424 // (2) x is a value coming from an integer type. 425 // (2.1) if x's bit_size == 8 426 // Cond: (x <= 0 || y > 128) 427 // (2.2) if x's bit_size is 16 428 // Cond: (x <= 0 || y > 64) 429 // (2.3) if x's bit_size is 32 430 // Cond: (x <= 0 || y > 32) 431 // Support for powl(x,y) and powf(x,y) are TBD. 432 // 433 // Note that condition can be more conservative than the actual condition 434 // (i.e. we might invoke the calls that will not set the errno.). 435 // 436 Value *LibCallsShrinkWrap::generateCondForPow(CallInst *CI, 437 const LibFunc::Func &Func) { 438 // FIXME: LibFunc::powf and powl TBD. 439 if (Func != LibFunc::pow) { 440 DEBUG(dbgs() << "Not handled powf() and powl()\n"); 441 return nullptr; 442 } 443 444 Value *Base = CI->getArgOperand(0); 445 Value *Exp = CI->getArgOperand(1); 446 IRBuilder<> BBBuilder(CI); 447 448 // Constant Base case. 449 if (ConstantFP *CF = dyn_cast<ConstantFP>(Base)) { 450 double D = CF->getValueAPF().convertToDouble(); 451 if (D < 1.0f || D > APInt::getMaxValue(8).getZExtValue()) { 452 DEBUG(dbgs() << "Not handled pow(): constant base out of range\n"); 453 return nullptr; 454 } 455 456 ++NumWrappedOneCond; 457 Constant *V = ConstantFP::get(CI->getContext(), APFloat(127.0f)); 458 if (!Exp->getType()->isFloatTy()) 459 V = ConstantExpr::getFPExtend(V, Exp->getType()); 460 return BBBuilder.CreateFCmp(CmpInst::FCMP_OGT, Exp, V); 461 } 462 463 // If the Base value coming from an integer type. 464 Instruction *I = dyn_cast<Instruction>(Base); 465 if (!I) { 466 DEBUG(dbgs() << "Not handled pow(): FP type base\n"); 467 return nullptr; 468 } 469 unsigned Opcode = I->getOpcode(); 470 if (Opcode == Instruction::UIToFP || Opcode == Instruction::SIToFP) { 471 unsigned BW = I->getOperand(0)->getType()->getPrimitiveSizeInBits(); 472 float UpperV = 0.0f; 473 if (BW == 8) 474 UpperV = 128.0f; 475 else if (BW == 16) 476 UpperV = 64.0f; 477 else if (BW == 32) 478 UpperV = 32.0f; 479 else { 480 DEBUG(dbgs() << "Not handled pow(): type too wide\n"); 481 return nullptr; 482 } 483 484 ++NumWrappedTwoCond; 485 Constant *V = ConstantFP::get(CI->getContext(), APFloat(UpperV)); 486 Constant *V0 = ConstantFP::get(CI->getContext(), APFloat(0.0f)); 487 if (!Exp->getType()->isFloatTy()) 488 V = ConstantExpr::getFPExtend(V, Exp->getType()); 489 if (!Base->getType()->isFloatTy()) 490 V0 = ConstantExpr::getFPExtend(V0, Exp->getType()); 491 492 Value *Cond = BBBuilder.CreateFCmp(CmpInst::FCMP_OGT, Exp, V); 493 Value *Cond0 = BBBuilder.CreateFCmp(CmpInst::FCMP_OLE, Base, V0); 494 return BBBuilder.CreateOr(Cond0, Cond); 495 } 496 DEBUG(dbgs() << "Not handled pow(): base not from integer convert\n"); 497 return nullptr; 498 } 499 500 // Wrap conditions that can potentially generate errno to the library call. 501 void LibCallsShrinkWrap::shrinkWrapCI(CallInst *CI, Value *Cond) { 502 assert(Cond != nullptr && "hrinkWrapCI is not expecting an empty call inst"); 503 MDNode *BranchWeights = 504 MDBuilder(CI->getContext()).createBranchWeights(1, 2000); 505 TerminatorInst *NewInst = 506 SplitBlockAndInsertIfThen(Cond, CI, false, BranchWeights); 507 BasicBlock *CallBB = NewInst->getParent(); 508 CallBB->setName("cdce.call"); 509 CallBB->getSingleSuccessor()->setName("cdce.end"); 510 CI->removeFromParent(); 511 CallBB->getInstList().insert(CallBB->getFirstInsertionPt(), CI); 512 DEBUG(dbgs() << "== Basic Block After =="); 513 DEBUG(dbgs() << *CallBB->getSinglePredecessor() << *CallBB 514 << *CallBB->getSingleSuccessor() << "\n"); 515 } 516 517 // Perform the transformation to a single candidate. 518 bool LibCallsShrinkWrap::perform(CallInst *CI) { 519 LibFunc::Func Func; 520 Function *Callee = CI->getCalledFunction(); 521 assert(Callee && "perform() should apply to a non-empty callee"); 522 TLI.getLibFunc(*Callee, Func); 523 assert(Func && "perform() is not expecting an empty function"); 524 525 if (LibCallsShrinkWrapDoDomainError && performCallDomainErrorOnly(CI, Func)) 526 return true; 527 528 if (LibCallsShrinkWrapDoRangeError && performCallRangeErrorOnly(CI, Func)) 529 return true; 530 531 return performCallErrors(CI, Func); 532 } 533 534 void LibCallsShrinkWrapLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { 535 AU.addPreserved<GlobalsAAWrapperPass>(); 536 AU.addRequired<TargetLibraryInfoWrapperPass>(); 537 } 538 539 static bool runImpl(Function &F, const TargetLibraryInfo &TLI) { 540 if (F.hasFnAttribute(Attribute::OptimizeForSize)) 541 return false; 542 LibCallsShrinkWrap CCDCE(TLI); 543 CCDCE.visit(F); 544 CCDCE.perform(); 545 return CCDCE.isChanged(); 546 } 547 548 bool LibCallsShrinkWrapLegacyPass::runOnFunction(Function &F) { 549 auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); 550 return runImpl(F, TLI); 551 } 552 553 namespace llvm { 554 char &LibCallsShrinkWrapPassID = LibCallsShrinkWrapLegacyPass::ID; 555 556 // Public interface to LibCallsShrinkWrap pass. 557 FunctionPass *createLibCallsShrinkWrapPass() { 558 return new LibCallsShrinkWrapLegacyPass(); 559 } 560 561 PreservedAnalyses LibCallsShrinkWrapPass::run(Function &F, 562 FunctionAnalysisManager &FAM) { 563 auto &TLI = FAM.getResult<TargetLibraryAnalysis>(F); 564 bool Changed = runImpl(F, TLI); 565 if (!Changed) 566 return PreservedAnalyses::all(); 567 auto PA = PreservedAnalyses(); 568 PA.preserve<GlobalsAA>(); 569 return PA; 570 } 571 } 572