LLVM: lib/Transforms/IPO/GlobalOpt.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

66#include

67#include

68#include

69#include

70#include

71

72using namespace llvm;

73

74#define DEBUG_TYPE "globalopt"

75

76STATISTIC(NumMarked , "Number of globals marked constant");

77STATISTIC(NumUnnamed , "Number of globals marked unnamed_addr");

78STATISTIC(NumSRA , "Number of aggregate globals broken into scalars");

79STATISTIC(NumSubstitute,"Number of globals with initializers stored into them");

80STATISTIC(NumDeleted , "Number of globals deleted");

81STATISTIC(NumGlobUses , "Number of global uses devirtualized");

82STATISTIC(NumLocalized , "Number of globals localized");

83STATISTIC(NumShrunkToBool , "Number of global vars shrunk to booleans");

84STATISTIC(NumFastCallFns , "Number of functions converted to fastcc");

85STATISTIC(NumCtorsEvaluated, "Number of static ctors evaluated");

86STATISTIC(NumNestRemoved , "Number of nest attributes removed");

87STATISTIC(NumAliasesResolved, "Number of global aliases resolved");

88STATISTIC(NumAliasesRemoved, "Number of global aliases eliminated");

89STATISTIC(NumCXXDtorsRemoved, "Number of global C++ destructors removed");

90STATISTIC(NumAtExitRemoved, "Number of atexit handlers removed");

91STATISTIC(NumInternalFunc, "Number of internal functions");

92STATISTIC(NumColdCC, "Number of functions marked coldcc");

93STATISTIC(NumIFuncsResolved, "Number of statically resolved IFuncs");

94STATISTIC(NumIFuncsDeleted, "Number of IFuncs removed");

96 "Number of global arrays padded to alignment boundary");

97

100 cl::desc("Statically resolve calls to versioned "

101 "functions from non-versioned callers."),

103

106 cl::desc("Enable stress test of coldcc by adding "

107 "calling conv to all internal functions."),

109

113 "Maximum block frequency, expressed as a percentage of caller's "

114 "entry frequency, for a call site to be considered cold for enabling "

115 "coldcc"));

116

117

118

120

121

122

123

124

125

126

127

129 return false;

130

133

134 unsigned Limit = 20;

135 do {

136 Type *Ty = Types.pop_back_val();

138 default: break;

140 return true;

143 if (cast(Ty)->getElementType()->isPointerTy())

144 return true;

145 break;

147 Types.push_back(cast(Ty)->getElementType());

148 break;

150 StructType *STy = cast(Ty);

151 if (STy->isOpaque()) return true;

153 if (isa(InnerTy)) return true;

154 if (isa(InnerTy) || isa(InnerTy) ||

155 isa(InnerTy))

156 Types.push_back(InnerTy);

157 }

158 break;

159 }

160 }

161 if (--Limit == 0) return true;

162 } while (!Types.empty());

163 return false;

164}

165

166

167

168

171 do {

172 if (isa(V))

173 return true;

174 if (!V->hasOneUse())

175 return false;

176 if (isa(V) || isa(V) || isa(V) ||

177 isa(V))

178 return false;

180 return true;

181

183 if (I->mayHaveSideEffects())

184 return false;

186 if (GEP->hasAllConstantIndices())

187 return false;

188 } else if (I->getNumOperands() != 1) {

189 return false;

190 }

191

192 V = I->getOperand(0);

193 } while (true);

194}

195

196

197

198

199static bool

202

203

204

205

206

207

208

209

210

211 bool Changed = false;

212

213

214

216

218

219 while (!Worklist.empty()) {

221 if (StoreInst *SI = dyn_cast(U)) {

222 Value *V = SI->getValueOperand();

223 if (isa(V)) {

224 Changed = true;

225 SI->eraseFromParent();

226 } else if (Instruction *I = dyn_cast(V)) {

227 if (I->hasOneUse())

228 Dead.push_back(std::make_pair(I, SI));

229 }

230 } else if (MemSetInst *MSI = dyn_cast(U)) {

231 if (isa(MSI->getValue())) {

232 Changed = true;

233 MSI->eraseFromParent();

234 } else if (Instruction *I = dyn_cast(MSI->getValue())) {

235 if (I->hasOneUse())

236 Dead.push_back(std::make_pair(I, MSI));

237 }

238 } else if (MemTransferInst *MTI = dyn_cast(U)) {

239 GlobalVariable *MemSrc = dyn_cast(MTI->getSource());

240 if (MemSrc && MemSrc->isConstant()) {

241 Changed = true;

242 MTI->eraseFromParent();

243 } else if (Instruction *I = dyn_cast(MTI->getSource())) {

244 if (I->hasOneUse())

245 Dead.push_back(std::make_pair(I, MTI));

246 }

247 } else if (ConstantExpr *CE = dyn_cast(U)) {

248 if (isa(CE))

250 }

251 }

252

253 for (int i = 0, e = Dead.size(); i != e; ++i) {

255 Dead[i].second->eraseFromParent();

257 do {

259 break;

260 Instruction *J = dyn_cast(I->getOperand(0));

261 if (!J)

262 break;

263 I->eraseFromParent();

264 I = J;

265 } while (true);

266 I->eraseFromParent();

267 Changed = true;

268 }

269 }

270

272 return Changed;

273}

274

275

276

277

283 bool Changed = false;

284

287 for (Value *Op : I->operands())

288 if (auto *OpI = dyn_cast(Op))

290 I->eraseFromParent();

291 Changed = true;

292 };

293 while (!WorkList.empty()) {

295 if (!Visited.insert(U).second)

296 continue;

297

298 if (auto *BO = dyn_cast(U))

300 if (auto *ASC = dyn_cast(U))

302 else if (auto *GEP = dyn_cast(U))

304 else if (auto *LI = dyn_cast(U)) {

305

306

307 Type *Ty = LI->getType();

309 LI->replaceAllUsesWith(Res);

310 EraseFromParent(LI);

311 continue;

312 }

313

314 Value *PtrOp = LI->getPointerOperand();

317 DL, Offset, true);

318 if (IntrinsicInst *II = dyn_cast(PtrOp)) {

319 if (II->getIntrinsicID() == Intrinsic::threadlocal_address)

320 PtrOp = II->getArgOperand(0);

321 }

322 if (PtrOp == GV) {

324 LI->replaceAllUsesWith(Value);

325 EraseFromParent(LI);

326 }

327 }

328 } else if (StoreInst *SI = dyn_cast(U)) {

329

330 EraseFromParent(SI);

331 } else if (MemIntrinsic *MI = dyn_cast(U)) {

333 EraseFromParent(MI);

334 } else if (IntrinsicInst *II = dyn_cast(U)) {

335 if (II->getIntrinsicID() == Intrinsic::threadlocal_address)

337 }

338 }

339

340 Changed |=

343 return Changed;

344}

345

346

347

353};

354

355

356

361 auto AppendUses = [&](Value *V) {

362 for (Use &U : V->uses())

363 if (Visited.insert(&U).second)

365 };

366 AppendUses(GV);

367 while (!Worklist.empty()) {

369 User *V = U->getUser();

370

371 auto *GEP = dyn_cast(V);

372 if (isa(V) || isa(V) ||

373 (GEP && GEP->hasAllConstantIndices())) {

374 AppendUses(V);

375 continue;

376 }

377

379

380

381 if (isa(V) && U->getOperandNo() == 0)

382 return false;

383

385 Ptr = Ptr->stripAndAccumulateConstantOffsets(DL, Offset,

386 true);

387 if (Ptr != GV || Offset.getActiveBits() >= 64)

388 return false;

389

390

391

393 const auto &[It, Inserted] =

395 if (Ty != It->second.Ty)

396 return false;

397

398 if (Inserted) {

399 It->second.Initializer =

401 if (!It->second.Initializer) {

402 LLVM_DEBUG(dbgs() << "Global SRA: Failed to evaluate initializer of "

403 << *GV << " with type " << *Ty << " at offset "

404 << Offset.getZExtValue());

405 return false;

406 }

407 }

408

409

411 return false;

412

413 auto IsStored = [](Value *V, Constant *Initializer) {

414 auto *SI = dyn_cast(V);

415 if (!SI)

416 return false;

417

418 Constant *StoredConst = dyn_cast(SI->getOperand(0));

419 if (!StoredConst)

420 return true;

421

422

423 return Initializer != StoredConst;

424 };

425

426 It->second.IsLoaded |= isa(V);

427 It->second.IsStored |= IsStored(V, It->second.Initializer);

428 continue;

429 }

430

431

432 if (auto *C = dyn_cast(V)) {

434 return false;

435 continue;

436 }

437

438

439 return false;

440 }

441

442 return true;

443}

444

445

447 uint64_t FragmentOffsetInBits,

452 for (auto *GVE : GVs) {

453 DIVariable *Var = GVE->getVariable();

455 int64_t CurVarOffsetInBytes = 0;

456 uint64_t CurVarOffsetInBits = 0;

457 uint64_t FragmentEndInBits = FragmentOffsetInBits + FragmentSizeInBits;

458

459

461 continue;

462

463

464 if (CurVarOffsetInBytes < 0)

465 continue;

466

467

468 CurVarOffsetInBits = CHAR_BIT * (uint64_t)CurVarOffsetInBytes;

469

470

471 if (CurVarOffsetInBits >= FragmentEndInBits)

472 continue;

473

475 uint64_t CurVarEndInBits = CurVarOffsetInBits + CurVarSize;

476

477 if (CurVarSize != 0 &&

478 CurVarEndInBits <= FragmentOffsetInBits)

479 continue;

480

481

482

483 if (CurVarSize != 0 &&

484 CurVarOffsetInBits >= FragmentOffsetInBits &&

485 CurVarEndInBits <= FragmentEndInBits) {

486 uint64_t CurVarOffsetInFragment =

487 (CurVarOffsetInBits - FragmentOffsetInBits) / 8;

488 if (CurVarOffsetInFragment != 0)

489 Expr = DIExpression::get(Expr->getContext(), {dwarf::DW_OP_plus_uconst,

490 CurVarOffsetInFragment});

491 else

492 Expr = DIExpression::get(Expr->getContext(), {});

493 auto *NGVE =

494 DIGlobalVariableExpression::get(GVE->getContext(), Var, Expr);

496 continue;

497 }

498

499

500 if (FragmentSizeInBits < VarSize) {

501 if (CurVarOffsetInBits > FragmentOffsetInBits)

502 continue;

503 uint64_t CurVarFragmentOffsetInBits =

504 FragmentOffsetInBits - CurVarOffsetInBits;

505 uint64_t CurVarFragmentSizeInBits = FragmentSizeInBits;

506 if (CurVarSize != 0 && CurVarEndInBits < FragmentEndInBits)

507 CurVarFragmentSizeInBits -= (FragmentEndInBits - CurVarEndInBits);

508 if (CurVarOffsetInBits)

509 Expr = DIExpression::get(Expr->getContext(), {});

511 Expr, CurVarFragmentOffsetInBits, CurVarFragmentSizeInBits))

512 Expr = *E;

513 else

514 continue;

515 }

516 auto *NGVE = DIGlobalVariableExpression::get(GVE->getContext(), Var, Expr);

518 }

519}

520

521

522

523

524

525

528

529

532 return nullptr;

533

534

536 return nullptr;

537

538

539

540

541 unsigned NumParts = count_if(Parts, [](const auto &Pair) {

542 return Pair.second.IsLoaded && Pair.second.IsStored;

543 });

544 if (NumParts > 16)

545 return nullptr;

546

547

549 for (const auto &Pair : Parts) {

551 {Pair.first, Pair.second.Ty, Pair.second.Initializer});

552 }

554

555

557 for (const auto &[OffsetForTy, Ty, _] : TypesVector) {

558

559 if (OffsetForTy < Offset)

560 return nullptr;

561

562 Offset = OffsetForTy + DL.getTypeAllocSize(Ty);

563 }

564

565

567 return nullptr;

568

569 LLVM_DEBUG(dbgs() << "PERFORMING GLOBAL SRA ON: " << *GV << "\n");

570

571

572 Align StartAlignment =

575

576

578 unsigned NameSuffix = 0;

579 for (auto &[OffsetForTy, Ty, Initializer] : TypesVector) {

581 *GV->getParent(), Ty, false, GlobalVariable::InternalLinkage,

582 Initializer, GV->getName() + "." + Twine(NameSuffix++), GV,

584

586 NewGlobals.insert({OffsetForTy, NGV});

587

588

589

590

591

594

595

597 DL.getTypeAllocSizeInBits(Ty), VarSize);

598 }

599

600

604 auto AppendUsers = [&](Value *V) {

605 for (User *U : V->users())

606 if (Visited.insert(U).second)

608 };

609 AppendUsers(GV);

610 while (!Worklist.empty()) {

612 if (isa(V) || isa(V) ||

613 isa(V)) {

614 AppendUsers(V);

615 if (isa(V))

617 continue;

618 }

619

622 Ptr = Ptr->stripAndAccumulateConstantOffsets(DL, Offset,

623 true);

624 assert(Ptr == GV && "Load/store must be from/to global");

626 assert(NGV && "Must have replacement global for this offset");

627

628

632

633 if (auto *LI = dyn_cast(V)) {

634 LI->setOperand(0, NGV);

635 LI->setAlignment(NewAlign);

636 } else {

637 auto *SI = cast(V);

638 SI->setOperand(1, NGV);

639 SI->setAlignment(NewAlign);

640 }

641 continue;

642 }

643

645 "Other users can only be dead constants");

646 }

647

648

652 ++NumSRA;

653

655 return NewGlobals.begin()->second;

656}

657

658

659

660

663 for (const User *U : V->users()) {

664 if (const Instruction *I = dyn_cast(U)) {

665

666

668 return false;

669 }

670 if (isa(U)) {

671

672 } else if (const StoreInst *SI = dyn_cast(U)) {

673 if (SI->getOperand(0) == V) {

674 return false;

675 }

676 } else if (const CallInst *CI = dyn_cast(U)) {

677 if (CI->getCalledOperand() != V) {

678 return false;

679 }

680 } else if (const InvokeInst *II = dyn_cast(U)) {

681 if (II->getCalledOperand() != V) {

682 return false;

683 }

684 } else if (const AddrSpaceCastInst *CI = dyn_cast(U)) {

686 return false;

687 } else if (const GetElementPtrInst *GEPI = dyn_cast(U)) {

689 } else if (const PHINode *PN = dyn_cast(U)) {

690

691

693 return false;

694 } else if (isa(U) &&

695 !ICmpInst::isSigned(cast(U)->getPredicate()) &&

696 isa(U->getOperand(0)) &&

697 isa(U->getOperand(1))) {

698 assert(isa(cast(U->getOperand(0))

699 ->getPointerOperand()

700 ->stripPointerCasts()) &&

701 "Should be GlobalVariable");

702

703

704

705 } else {

706 return false;

707 }

708 }

709 return true;

710}

711

712

713

714

718 while (!Worklist.empty()) {

720 for (const auto *U : P->users()) {

721 if (auto *LI = dyn_cast(U)) {

724 return false;

725 } else if (auto *SI = dyn_cast(U)) {

726

727 if (SI->getPointerOperand() != P)

728 return false;

729 } else if (auto *CE = dyn_cast(U)) {

730 if (CE->stripPointerCasts() != GV)

731 return false;

732

734 } else {

735

736 return false;

737 }

738 }

739 }

740

741 return true;

742}

743

744

749 while (!Worklist.empty()) {

751 for (auto *U : P->users()) {

752 if (auto *CE = dyn_cast(U)) {

754 continue;

755 }

756

757 assert((isa(U) || isa(U)) &&

758 "Expect only load or store instructions");

759 Uses.push_back(U);

760 }

761 }

762}

763

765 bool Changed = false;

766 for (auto UI = V->user_begin(), E = V->user_end(); UI != E; ) {

768

769

771 return false;

772 if (LoadInst *LI = dyn_cast(I)) {

773 LI->setOperand(0, NewV);

774 Changed = true;

775 } else if (StoreInst *SI = dyn_cast(I)) {

776 if (SI->getOperand(1) == V) {

777 SI->setOperand(1, NewV);

778 Changed = true;

779 }

780 } else if (isa(I) || isa(I)) {

781 CallBase *CB = cast(I);

783

784

786 Changed = true;

787 bool PassedAsArg = false;

788 for (unsigned i = 0, e = CB->arg_size(); i != e; ++i)

790 PassedAsArg = true;

792 }

793

794 if (PassedAsArg) {

795

796 UI = V->user_begin();

797 }

798 }

802 if (CI->use_empty()) {

803 Changed = true;

804 CI->eraseFromParent();

805 }

806 } else if (GetElementPtrInst *GEPI = dyn_cast(I)) {

807

809 Idxs.reserve(GEPI->getNumOperands()-1);

810 for (User::op_iterator i = GEPI->op_begin() + 1, e = GEPI->op_end();

811 i != e; ++i)

812 if (Constant *C = dyn_cast(*i))

814 else

815 break;

816 if (Idxs.size() == GEPI->getNumOperands()-1)

819 NewV, Idxs));

820 if (GEPI->use_empty()) {

821 Changed = true;

822 GEPI->eraseFromParent();

823 }

824 }

825 }

826

827 return Changed;

828}

829

830

831

832

833

837 bool Changed = false;

838

839

840

841 bool AllNonStoreUsesGone = true;

842

843

845 if (LoadInst *LI = dyn_cast(GlobalUser)) {

847

848 if (LI->use_empty()) {

849 LI->eraseFromParent();

850 Changed = true;

851 } else {

852 AllNonStoreUsesGone = false;

853 }

854 } else if (isa(GlobalUser)) {

855

856 assert(GlobalUser->getOperand(1) == GV &&

857 "Must be storing *to* the global");

858 } else {

859 AllNonStoreUsesGone = false;

860

861

862

863 assert((isa(GlobalUser) || isa(GlobalUser) ||

864 isa(GlobalUser) || isa(GlobalUser) ||

865 isa(GlobalUser) ||

866 isa(GlobalUser) ||

867 isa(GlobalUser)) &&

868 "Only expect load and stores!");

869 }

870 }

871

872 if (Changed) {

873 LLVM_DEBUG(dbgs() << "OPTIMIZED LOADS FROM STORED ONCE POINTER: " << *GV

874 << "\n");

875 ++NumGlobUses;

876 }

877

878

879

880 if (AllNonStoreUsesGone) {

883 } else {

884 Changed = true;

886 }

889 Changed = true;

891 ++NumDeleted;

892 }

893 }

894 return Changed;

895}

896

897

898

901 for (Value::user_iterator UI = V->user_begin(), E = V->user_end(); UI != E; )

902 if (Instruction *I = dyn_cast(*UI++))

904 I->replaceAllUsesWith(NewC);

905

906

907

908 while (UI != E && *UI == I)

909 ++UI;

911 I->eraseFromParent();

912 }

913}

914

915

916

917

918

919

925 LLVM_DEBUG(errs() << "PROMOTING GLOBAL: " << *GV << " CALL = " << *CI

926 << '\n');

927

928

930 AllocSize);

931

932

933

938

939

940

941

942

943

944 if (!isa(InitVal)) {

946

947 Builder.CreateMemSet(NewGV, InitVal, AllocSize, std::nullopt);

948 }

949

950

952

953

954

959 bool InitBoolUsed = false;

960

961

964 for (auto *U : Guses) {

965 if (StoreInst *SI = dyn_cast(U)) {

966

967

970 !isa(SI->getValueOperand())),

971 InitBool, false, Align(1), SI->getOrdering(),

972 SI->getSyncScopeID(), SI->getIterator());

973 SI->eraseFromParent();

974 continue;

975 }

976

977 LoadInst *LI = cast(U);

981 if (!ICI) {

982 LoadUse.set(NewGV);

983 continue;

984 }

985

986

988 InitBool->getName() + ".val", false, Align(1),

991 InitBoolUsed = true;

994 case ICmpInst::ICMP_ULT:

996 break;

997 case ICmpInst::ICMP_UGE:

999 break;

1000 case ICmpInst::ICMP_ULE:

1001 case ICmpInst::ICMP_EQ:

1003 break;

1004 case ICmpInst::ICMP_NE:

1005 case ICmpInst::ICMP_UGT:

1006 break;

1007 }

1010 }

1012 }

1013

1014

1015 if (!InitBoolUsed) {

1016 while (!InitBool->use_empty())

1017 cast(InitBool->user_back())->eraseFromParent();

1018 delete InitBool;

1019 } else

1021

1022

1025

1026

1027

1028

1030

1031 return NewGV;

1032}

1033

1034

1035

1036

1037static bool

1043

1044 while (!Worklist.empty()) {

1046 if (!Visited.insert(V).second)

1047 continue;

1048

1049 for (const Use &VUse : V->uses()) {

1050 const User *U = VUse.getUser();

1051 if (isa(U) || isa(U))

1052 continue;

1053

1054 if (auto *SI = dyn_cast(U)) {

1055 if (SI->getValueOperand() == V &&

1056 SI->getPointerOperand()->stripPointerCasts() != GV)

1057 return false;

1058 continue;

1059 }

1060

1061 if (auto *GEPI = dyn_cast(U)) {

1063 continue;

1064 }

1065

1066 return false;

1067 }

1068 }

1069

1070 return true;

1071}

1072

1073

1074

1075

1076

1082

1083 return false;

1084

1087 if (!InitVal)

1088

1089 return false;

1090

1093 return false;

1094

1095

1096

1097

1098 if (AllocSize >= 2048)

1099 return false;

1100

1101

1102

1103

1104

1105

1106

1108 return false;

1109

1110

1111

1112

1113

1115 return false;

1116

1118 return true;

1119}

1120

1121

1122

1123static bool

1127

1129

1130

1131

1132

1133

1138 nullptr ,

1140 if (Constant *SOVC = dyn_cast(StoredOnceVal)) {

1141

1143 return true;

1145 if (auto *CI = dyn_cast(StoredOnceVal)) {

1146 auto *TLI = &GetTLI(*CI->getFunction());

1148 return true;

1149 }

1150 }

1151 }

1152

1153 return false;

1154}

1155

1156

1157

1158

1159

1162

1163

1164

1165

1166

1167

1171 return false;

1172

1173

1174

1176 if (!isa(U) && !isa(U))

1177 return false;

1179 return false;

1180 }

1181

1182 LLVM_DEBUG(dbgs() << " *** SHRINKING TO BOOL: " << *GV << "\n");

1183

1184

1186 false,

1194

1197 "No reason to shrink to bool!");

1198

1201

1202

1203

1204 bool IsOneZero = false;

1205 bool EmitOneOrZero = true;

1206 auto *CI = dyn_cast(OtherVal);

1207 if (CI && CI->getValue().getActiveBits() <= 64) {

1208 IsOneZero = InitVal->isNullValue() && CI->isOne();

1209

1210 auto *CIInit = dyn_cast(GV->getInitializer());

1211 if (CIInit && CIInit->getValue().getActiveBits() <= 64) {

1212 uint64_t ValInit = CIInit->getZExtValue();

1213 uint64_t ValOther = CI->getZExtValue();

1214 uint64_t ValMinus = ValOther - ValInit;

1215

1216 for(auto *GVe : GVs){

1220 unsigned SizeInOctets =

1221 DL.getTypeAllocSizeInBits(NewGV->getValueType()) / 8;

1222

1223

1224

1225

1226

1227

1228

1229

1230

1232 dwarf::DW_OP_deref_size, SizeInOctets,

1233 dwarf::DW_OP_constu, ValMinus,

1234 dwarf::DW_OP_mul, dwarf::DW_OP_constu, ValInit,

1235 dwarf::DW_OP_plus};

1236 bool WithStackValue = true;

1239 DIGlobalVariableExpression::get(NewGV->getContext(), DGV, E);

1241 }

1242 EmitOneOrZero = false;

1243 }

1244 }

1245

1246 if (EmitOneOrZero) {

1247

1248

1249 for(auto *GV : GVs)

1251 }

1252

1255 if (StoreInst *SI = dyn_cast(UI)) {

1256

1257 bool StoringOther = SI->getOperand(0) == OtherVal;

1258

1259 Value *StoreVal;

1260 if (StoringOther || SI->getOperand(0) == InitVal) {

1262 StoringOther);

1263 } else {

1264

1265

1266

1267 Instruction *StoredVal = cast(SI->getOperand(0));

1268

1269

1270

1271

1272 if (LoadInst *LI = dyn_cast(StoredVal)) {

1273 assert(LI->getOperand(0) == GV && "Not a copy!");

1274

1275 StoreVal =

1277 false, Align(1), LI->getOrdering(),

1278 LI->getSyncScopeID(), LI->getIterator());

1279 } else {

1280 assert((isa(StoredVal) || isa(StoredVal)) &&

1281 "This is not a form that we understand!");

1282 StoreVal = StoredVal->getOperand(0);

1283 assert(isa(StoreVal) && "Not a load of NewGV!");

1284 }

1285 }

1287 new StoreInst(StoreVal, NewGV, false, Align(1), SI->getOrdering(),

1288 SI->getSyncScopeID(), SI->getIterator());

1290 } else {

1291

1292 LoadInst *LI = cast(UI);

1297 if (IsOneZero)

1299 else

1302

1303

1307 }

1309 }

1310

1311

1312

1315 return true;

1316}

1317

1318static bool

1323

1325 return false;

1326

1329 return false;

1330

1331 bool Dead;

1332 if (auto *F = dyn_cast(&GV))

1333 Dead = (F->isDeclaration() && F->use_empty()) || F->isDefTriviallyDead();

1334 else

1336 if (!Dead)

1337 return false;

1338

1339 LLVM_DEBUG(dbgs() << "GLOBAL DEAD: " << GV << "\n");

1340 if (auto *F = dyn_cast(&GV)) {

1341 if (DeleteFnCallback)

1342 DeleteFnCallback(*F);

1343 }

1346 ++NumDeleted;

1347 return true;

1348}

1349

1353

1354

1355

1356

1357

1358

1359

1360

1361

1362

1366 for (auto *U : GV->users()) {

1368 if (I)

1369 return false;

1370 assert(I->getParent()->getParent() == F);

1371

1372 if (auto *LI = dyn_cast(I))

1374 else if (auto *SI = dyn_cast(I))

1376 else

1377 return false;

1378 }

1379

1380

1381

1382

1383

1384 auto &DT = LookupDomTree(*const_cast<Function *>(F));

1385

1386

1387

1388

1389

1390

1391

1392

1393

1394

1395 const unsigned Threshold = 100;

1396 if (Loads.size() * Stores.size() > Threshold)

1397 return false;

1398

1399 for (auto *L : Loads) {

1400 auto *LTy = L->getType();

1403

1404

1405

1407 DL.getTypeStoreSize(LTy).getFixedValue() <=

1408 DL.getTypeStoreSize(STy).getFixedValue();

1409 }))

1410 return false;

1411 }

1412

1413 return true;

1414}

1415

1416

1417

1418

1423

1424

1425

1426 if (!isa(StoredOnceValue))

1427 return false;

1431 if (auto *LI = dyn_cast(U)) {

1432 if (LI->getFunction() == F &&

1433 LI->getType() == StoredOnceValue->getType() && LI->isSimple())

1435 }

1436 }

1437

1438 bool MadeChange = false;

1439 if (!Loads.empty()) {

1440 auto &DT = LookupDomTree(*const_cast<Function *>(F));

1441 for (auto *LI : Loads) {

1442 if (DT.dominates(StoredOnceStore, LI)) {

1443 LI->replaceAllUsesWith(const_cast<Value *>(StoredOnceValue));

1444 LI->eraseFromParent();

1445 MadeChange = true;

1446 }

1447 }

1448 }

1449 return MadeChange;

1450}

1451

1452

1453

1454static bool

1460

1461

1462

1463

1464

1465

1466

1467

1468 if (!GS.HasMultipleAccessingFunctions &&

1469 GS.AccessingFunction &&

1473 GS.AccessingFunction->doesNotRecurse() &&

1475 LookupDomTree)) {

1477

1478 LLVM_DEBUG(dbgs() << "LOCALIZING GLOBAL: " << *GV << "\n");

1480 GS.AccessingFunction->getEntryBlock().begin().getNonConst();

1482

1484 nullptr, GV->getName(), FirstI);

1487

1490 ++NumLocalized;

1491 return true;

1492 }

1493

1494 bool Changed = false;

1495

1496

1497

1498 if (!GS.IsLoaded) {

1499 LLVM_DEBUG(dbgs() << "GLOBAL NEVER LOADED: " << *GV << "\n");

1500

1502

1504 } else {

1505

1506

1508 }

1509

1510

1513 ++NumDeleted;

1514 Changed = true;

1515 }

1516 return Changed;

1517

1518 }

1520 LLVM_DEBUG(dbgs() << "MARKING CONSTANT: " << *GV << "\n");

1521

1522

1523

1524

1525 if (GS.Ordering == AtomicOrdering::NotAtomic) {

1526 assert(!GV->isConstant() && "Expected a non-constant global");

1528 Changed = true;

1529 }

1530

1531

1533

1534

1536 LLVM_DEBUG(dbgs() << " *** Marking constant allowed us to simplify "

1537 << "all users and delete global!\n");

1539 ++NumDeleted;

1540 return true;

1541 }

1542

1543

1544 ++NumMarked;

1545 }

1549 return true;

1550 }

1551 Value *StoredOnceValue = GS.getStoredOnceValue();

1554 const_cast<Function &>(*GS.StoredOnceStore->getFunction());

1555 bool CanHaveNonUndefGlobalInitializer =

1556 GetTTI(StoreFn).canHaveNonUndefGlobalInitializerInAddressSpace(

1558

1559

1560

1561

1562

1563

1564

1565 auto *SOVConstant = dyn_cast(StoredOnceValue);

1566 if (SOVConstant && isa(GV->getInitializer()) &&

1567 DL.getTypeAllocSize(SOVConstant->getType()) ==

1569 CanHaveNonUndefGlobalInitializer) {

1570 if (SOVConstant->getType() == GV->getValueType()) {

1571

1573 } else {

1574

1579 NGV->takeName(GV);

1580 NGV->copyAttributesFrom(GV);

1583 GV = NGV;

1584 }

1585

1586

1588

1590 LLVM_DEBUG(dbgs() << " *** Substituting initializer allowed us to "

1591 << "simplify all users and delete global!\n");

1593 ++NumDeleted;

1594 }

1595 ++NumSubstitute;

1596 return true;

1597 }

1598

1599

1600

1602 return true;

1603

1604

1605

1606 if (GS.NumStores == 1)

1608 return true;

1609

1610

1611

1612 if (SOVConstant && GS.Ordering == AtomicOrdering::NotAtomic &&

1614 CanHaveNonUndefGlobalInitializer)) {

1616 ++NumShrunkToBool;

1617 return true;

1618 }

1619 }

1620 }

1621

1622 return Changed;

1623}

1624

1625

1626

1627static bool

1633 return false;

1634

1636

1638 return false;

1639

1640 bool Changed = false;

1642 auto NewUnnamedAddr = GV.hasLocalLinkage() ? GlobalValue::UnnamedAddr::Global

1643 : GlobalValue::UnnamedAddr::Local;

1646 NumUnnamed++;

1647 Changed = true;

1648 }

1649 }

1650

1651

1653 return Changed;

1654

1655 auto *GVar = dyn_cast(&GV);

1656 if (!GVar)

1657 return Changed;

1658

1659 if (GVar->isConstant() || !GVar->hasInitializer())

1660 return Changed;

1661

1663 Changed;

1664}

1665

1666

1667

1669 for (User *U : F->users()) {

1670 if (isa(U))

1671 continue;

1673 }

1674}

1675

1678 unsigned AttrIndex;

1679 if (Attrs.hasAttrSomewhere(A, &AttrIndex))

1680 return Attrs.removeAttributeAtIndex(C, AttrIndex, A);

1681 return Attrs;

1682}

1683

1685 F->setAttributes(StripAttr(F->getContext(), F->getAttributes(), A));

1686 for (User *U : F->users()) {

1687 if (isa(U))

1688 continue;

1689 CallBase *CB = cast(U);

1691 }

1692}

1693

1694

1695

1696

1697

1700

1701

1703 return false;

1704

1705 if (F->isVarArg())

1706 return false;

1707

1708

1709

1710

1711

1712 for (User *U : F->users()) {

1713 if (isa(U))

1714 continue;

1715 CallInst* CI = dyn_cast(U);

1716 if (!CI)

1717 continue;

1718

1720 return false;

1721 }

1722

1724 if (BB.getTerminatingMustTailCall())

1725 return false;

1726

1727 return F->hasAddressTaken();

1728}

1729

1733 auto Res = ChangeableCCCache.try_emplace(F, false);

1734 if (Res.second)

1736 return Res.first->second;

1737}

1738

1739

1740

1743 auto *CallSiteBB = CB.getParent();

1744 auto CallSiteFreq = CallerBFI.getBlockFreq(CallSiteBB);

1745 auto CallerEntryFreq =

1747 return CallSiteFreq < CallerEntryFreq * ColdProb;

1748}

1749

1750

1751

1752

1753

1754static bool

1757 const std::vector<Function *> &AllCallsCold) {

1758

1759 if (F.user_empty())

1760 return false;

1761

1762 for (User *U : F.users()) {

1763 if (isa(U))

1764 continue;

1765

1766 CallBase &CB = cast(*U);

1770 return false;

1772 return false;

1773 }

1774 return true;

1775}

1776

1778 for (User *U : F->users()) {

1779 if (isa(U))

1780 continue;

1782 }

1783}

1784

1785

1786

1787

1788static bool

1794 if (CallInst *CI = dyn_cast(&I)) {

1795

1796 if (CI->isInlineAsm())

1797 continue;

1798 Function *CalledFn = CI->getCalledFunction();

1799 if (!CalledFn)

1800 return false;

1801

1802

1803

1804

1806 continue;

1808 return false;

1809

1811 return false;

1814 return false;

1815 }

1816 }

1817 }

1818 return true;

1819}

1820

1822 for (User *U : F->users()) {

1823 CallBase *CB = dyn_cast(U);

1824 if (!CB) {

1825 assert(isa(U) &&

1826 "Expected either CallBase or BlockAddress");

1827 continue;

1828 }

1830 return true;

1831 }

1832 return false;

1833}

1834

1836 for (User *U : F->users())

1837 if (isa(U))

1838 return true;

1839 return false;

1840}

1841

1844

1845 auto *M = F->getParent();

1846

1848

1849

1851 for (User *U : PreallocatedCalls) {

1852 CallBase *CB = dyn_cast(U);

1853 if (!CB)

1854 continue;

1855

1858 "Shouldn't call RemotePreallocated() on a musttail preallocated call");

1859

1862 CallBase *PreallocatedSetup = nullptr;

1863 for (auto *It = OpBundles.begin(); It != OpBundles.end(); ++It) {

1864 if (It->getTag() == "preallocated") {

1865 PreallocatedSetup = cast(*It->input_begin());

1866 OpBundles.erase(It);

1867 break;

1868 }

1869 }

1870 assert(PreallocatedSetup && "Did not find preallocated bundle");

1872 cast(PreallocatedSetup->getArgOperand(0))->getZExtValue();

1873

1874 assert((isa(CB) || isa(CB)) &&

1875 "Unknown indirect call type");

1880

1885

1886

1887

1888

1889

1890

1891

1892

1895 for (auto *User : PreallocatedArgs) {

1896 auto *UseCall = cast(User);

1897 assert(UseCall->getCalledFunction()->getIntrinsicID() ==

1898 Intrinsic::call_preallocated_arg &&

1899 "preallocated token use was not a llvm.call.preallocated.arg");

1901 cast(UseCall->getArgOperand(1))->getZExtValue();

1902 Value *AllocaReplacement = ArgAllocas[AllocArgIndex];

1903 if (!AllocaReplacement) {

1904 auto AddressSpace = UseCall->getType()->getPointerAddressSpace();

1905 auto *ArgType =

1906 UseCall->getFnAttr(Attribute::Preallocated).getValueAsType();

1909 auto *Alloca =

1911 ArgAllocas[AllocArgIndex] = Alloca;

1912 AllocaReplacement = Alloca;

1913 }

1914

1916 UseCall->eraseFromParent();

1917 }

1918

1919 cast(PreallocatedSetup)->eraseFromParent();

1920 }

1921}

1922

1923static bool

1932

1933 bool Changed = false;

1934

1936 std::vector<Function *> AllCallsCold;

1939 AllCallsCold.push_back(&F);

1940

1941

1943

1944

1945 if (F.hasFnAttribute(Attribute::Naked))

1946 continue;

1947

1948

1949 if (F.hasName() && F.isDeclaration() && F.hasLocalLinkage())

1951

1952 if (deleteIfDead(F, NotDiscardableComdats, DeleteFnCallback)) {

1953 Changed = true;

1954 continue;

1955 }

1956

1957

1958

1959

1960

1961

1962

1963

1964

1965

1966 if (F.isDeclaration()) {

1968 Changed = true;

1969 ChangedCFGCallback(F);

1970 }

1971 }

1972

1973 Changed |= processGlobal(F, GetTTI, GetTLI, LookupDomTree);

1974

1975 if (F.hasLocalLinkage())

1976 continue;

1977

1978

1979

1980

1981

1982

1983 if (F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) &&

1986 Changed = true;

1987 }

1988

1989

1990

1991 if (F.getAttributes().hasAttrSomewhere(Attribute::Preallocated)) {

1995 Changed = true;

1996 }

1997 continue;

1998 }

1999

2001 NumInternalFunc++;

2003

2004

2005

2006

2010 ChangeableCCCache.erase(&F);

2013 Changed = true;

2014 NumColdCC++;

2015 }

2016 }

2017

2019

2020

2021

2024 ++NumFastCallFns;

2025 Changed = true;

2026 }

2027

2028 if (F.getAttributes().hasAttrSomewhere(Attribute::Nest) &&

2029 F.hasAddressTaken()) {

2030

2031

2033 ++NumNestRemoved;

2034 Changed = true;

2035 }

2036 }

2037 return Changed;

2038}

2039

2041 if (!CI)

2042 return false;

2043

2045 if (F || F->isIntrinsic() || F->getIntrinsicID() != Intrinsic::memcpy)

2046 return false;

2047

2048 return true;

2049}

2050

2052 auto *IsVolatile = dyn_cast(CI->getArgOperand(3));

2053 auto *Alloca = dyn_cast(CI->getArgOperand(0));

2054

2055 if (!Alloca || !IsVolatile || IsVolatile->isOne())

2056 return false;

2057

2058 if (!Alloca->isStaticAlloca())

2059 return false;

2060

2061 if (!Alloca->getAllocatedType()->isArrayTy())

2062 return false;

2063

2064 return true;

2065}

2066

2068 unsigned NumBytesToPad,

2069 unsigned NumBytesToCopy) {

2071 return nullptr;

2072

2074 dyn_cast(OldVar->getInitializer());

2075 if (!DataArray)

2076 return nullptr;

2077

2078

2079

2081 std::vector<uint8_t> StrData(Data.begin(), Data.end());

2082 for (unsigned int p = 0; p < NumBytesToPad; p++)

2083 StrData.push_back('\0');

2084 auto Arr = ArrayRef(StrData.data(), NumBytesToCopy + NumBytesToPad);

2085

2088 *(F->getParent()), SourceReplace->getType(), true, OldVar->getLinkage(),

2089 SourceReplace, SourceReplace->getName());

2090

2091

2094 return NewGV;

2095}

2096

2098 const unsigned NumBytesToCopy,

2100

2101 auto *Alloca = dyn_cast(CI->getArgOperand(0));

2102 if (Alloca) {

2104 unsigned int TotalBytes = NumBytesToCopy + NumBytesToPad;

2105 unsigned NumElementsToCopy = divideCeil(TotalBytes, ElementByteWidth);

2106

2109 Alloca->getAllocatedType()->getArrayElementType(), NumElementsToCopy));

2110 NewAlloca->takeName(Alloca);

2111 NewAlloca->setAlignment(Alloca->getAlign());

2112 Alloca->replaceAllUsesWith(NewAlloca);

2113 Alloca->eraseFromParent();

2114 }

2115}

2116

2118 const unsigned NumBytesToPad,

2119 const unsigned NumBytesToCopy,

2122 auto *NewSourceGV =

2124 if (!NewSourceGV)

2125 return false;

2126

2127

2128

2129 for (auto *User : SourceVar->users()) {

2130 auto *CI = dyn_cast(User);

2132 continue;

2133

2134 if (CI->getArgOperand(1) != SourceVar)

2135 continue;

2136

2137 widenDestArray(CI, NumBytesToPad, NumBytesToCopy, SourceDataArray);

2138

2139 CI->setArgOperand(2, ConstantInt::get(BytesToCopyOp->getType(),

2140 NumBytesToCopy + NumBytesToPad));

2141 }

2143

2144 NumGlobalArraysPadded++;

2145 return true;

2146}

2147

2151

2154 return false;

2155

2156 for (auto *User : GV->users()) {

2159 continue;

2160

2162

2163 auto *BytesToCopyOp = dyn_cast(CI->getArgOperand(2));

2164 if (!BytesToCopyOp)

2165 continue;

2166

2169 if (!SourceDataArray)

2170 continue;

2171

2172 unsigned NumBytesToCopy = BytesToCopyOp->getZExtValue();

2173

2174 auto *Alloca = dyn_cast(CI->getArgOperand(0));

2175 uint64_t DZSize = Alloca->getAllocatedType()->getArrayNumElements();

2178

2179

2180

2181 unsigned NumElementsToCopy = divideCeil(NumBytesToCopy, ElementByteWidth);

2182

2183

2184

2185

2186 if (NumElementsToCopy != DZSize || DZSize != SZSize)

2187 continue;

2188

2189 unsigned NumBytesToPad = GetTTI(*F).getNumBytesToPadGlobalArray(

2190 NumBytesToCopy, SourceDataArray->getType());

2191 if (NumBytesToPad) {

2193 BytesToCopyOp, SourceDataArray);

2194 }

2195 }

2196 return false;

2197}

2198

2199static bool

2205 bool Changed = false;

2206

2208

2211

2213 if (auto *C = dyn_cast(GV.getInitializer())) {

2214 auto &DL = M.getDataLayout();

2215

2216

2217

2219 if (New != C)

2221 }

2222

2223 if (deleteIfDead(GV, NotDiscardableComdats)) {

2224 Changed = true;

2225 continue;

2226 }

2227

2228

2229

2231

2232 Changed |= processGlobal(GV, GetTTI, GetTLI, LookupDomTree);

2233 }

2234 return Changed;

2235}

2236

2237

2238

2241

2242 if (F->isDeclaration())

2243 return false;

2244

2249

2250 if (EvalSuccess) {

2251 ++NumCtorsEvaluated;

2252

2253

2255 LLVM_DEBUG(dbgs() << "FULLY EVALUATED GLOBAL CTOR FUNCTION '"

2256 << F->getName() << "' to " << NewInitializers.size()

2257 << " stores.\n");

2258 for (const auto &Pair : NewInitializers)

2259 Pair.first->setInitializer(Pair.second);

2262 }

2263

2264 return EvalSuccess;

2265}

2266

2271}

2272

2275 if (Init.empty()) {

2276 V.eraseFromParent();

2277 return;

2278 }

2279

2280

2281 const Type *UsedArrayType = V.getValueType();

2282 const auto *VAT = cast(UsedArrayType);

2283 const auto *VEPT = cast(VAT->getArrayElementType());

2284

2285

2287 PointerType::get(V.getContext(), VEPT->getAddressSpace());

2288

2293 }

2294

2295

2297 ArrayType *ATy = ArrayType::get(PtrTy, UsedArray.size());

2298

2299 Module *M = V.getParent();

2300 V.removeFromParent();

2304 NV->takeName(&V);

2305 NV->setSection("llvm.metadata");

2306 delete &V;

2307}

2308

2309namespace {

2310

2311

2312class LLVMUsed {

2317

2318public:

2319 LLVMUsed(Module &M) {

2325 CompilerUsed = {Vec.begin(), Vec.end()};

2326 }

2327

2330

2331 iterator usedBegin() { return Used.begin(); }

2332 iterator usedEnd() { return Used.end(); }

2333

2334 used_iterator_range used() {

2335 return used_iterator_range(usedBegin(), usedEnd());

2336 }

2337

2338 iterator compilerUsedBegin() { return CompilerUsed.begin(); }

2339 iterator compilerUsedEnd() { return CompilerUsed.end(); }

2340

2341 used_iterator_range compilerUsed() {

2342 return used_iterator_range(compilerUsedBegin(), compilerUsedEnd());

2343 }

2344

2345 bool usedCount(GlobalValue *GV) const { return Used.count(GV); }

2346

2347 bool compilerUsedCount(GlobalValue *GV) const {

2348 return CompilerUsed.count(GV);

2349 }

2350

2351 bool usedErase(GlobalValue *GV) { return Used.erase(GV); }

2352 bool compilerUsedErase(GlobalValue *GV) { return CompilerUsed.erase(GV); }

2353 bool usedInsert(GlobalValue *GV) { return Used.insert(GV).second; }

2354

2355 bool compilerUsedInsert(GlobalValue *GV) {

2356 return CompilerUsed.insert(GV).second;

2357 }

2358

2359 void syncVariablesAndSets() {

2360 if (UsedV)

2362 if (CompilerUsedV)

2364 }

2365};

2366

2367}

2368

2370 if (GA.use_empty())

2371 return false;

2372

2373 assert((!U.usedCount(&GA) || !U.compilerUsedCount(&GA)) &&

2374 "We should have removed the duplicated "

2375 "element from llvm.compiler.used");

2377

2378

2379 return true;

2380

2381

2382 return !U.usedCount(&GA) && !U.compilerUsedCount(&GA);

2383}

2384

2387 return true;

2388

2389 return U.usedCount(&GV) || U.compilerUsedCount(&GV);

2390}

2391

2393 bool &RenameTarget) {

2395 return false;

2396

2397 RenameTarget = false;

2398 bool Ret = false;

2400 Ret = true;

2401

2402

2404 return Ret;

2405

2406

2407

2408

2409

2410

2411

2412

2416 return Ret;

2417

2418 RenameTarget = true;

2419 return true;

2420}

2421

2422static bool

2425 bool Changed = false;

2426 LLVMUsed Used(M);

2427

2429 Used.compilerUsedErase(GV);

2430

2431

2432

2433 auto IsModuleLocal = [](GlobalValue &GV) {

2436 };

2437

2439

2440 if (!J.hasName() && !J.isDeclaration() && !J.hasLocalLinkage())

2442

2443 if (deleteIfDead(J, NotDiscardableComdats)) {

2444 Changed = true;

2445 continue;

2446 }

2447

2448

2449 if (!IsModuleLocal(J))

2450 continue;

2451

2452 Constant *Aliasee = J.getAliasee();

2454

2455

2456

2457

2458

2459

2461 continue;

2462

2463 Target->removeDeadConstantUsers();

2464

2465

2466 bool RenameTarget;

2468 continue;

2469

2470 J.replaceAllUsesWith(Aliasee);

2471 ++NumAliasesResolved;

2472 Changed = true;

2473

2474 if (RenameTarget) {

2475

2476 Target->takeName(&J);

2477 Target->setLinkage(J.getLinkage());

2478 Target->setDSOLocal(J.isDSOLocal());

2479 Target->setVisibility(J.getVisibility());

2480 Target->setDLLStorageClass(J.getDLLStorageClass());

2481

2482 if (Used.usedErase(&J))

2483 Used.usedInsert(Target);

2484

2485 if (Used.compilerUsedErase(&J))

2486 Used.compilerUsedInsert(Target);

2488 continue;

2489

2490

2491 M.eraseAlias(&J);

2492 ++NumAliasesRemoved;

2493 Changed = true;

2494 }

2495

2496 Used.syncVariablesAndSets();

2497

2498 return Changed;

2499}

2500

2505

2506 auto FuncIter = M.begin();

2507 if (FuncIter == M.end())

2508 return nullptr;

2509 auto *TLI = &GetTLI(*FuncIter);

2510

2511 if (!TLI->has(Func))

2512 return nullptr;

2513

2514 Function *Fn = M.getFunction(TLI->getName(Func));

2515 if (!Fn)

2516 return nullptr;

2517

2518

2519 TLI = &GetTLI(*Fn);

2520

2521

2523 if (!TLI->getLibFunc(*Fn, F) || F != Func)

2524 return nullptr;

2525

2526 return Fn;

2527}

2528

2529

2530

2531

2532

2534

2535

2537 return false;

2538

2540 if (I.isDebugOrPseudoInst())

2541 continue;

2542 if (isa(I))

2543 return true;

2544 break;

2545 }

2546 return false;

2547}

2548

2550

2551

2552

2553

2554

2555

2556

2557

2558

2559

2560

2561

2562

2563

2564 bool Changed = false;

2565

2567

2568

2569

2570 CallInst *CI = dyn_cast(U);

2571 if (!CI)

2572 continue;

2573

2577 continue;

2578

2579

2582

2583 if (isCXX)

2584 ++NumCXXDtorsRemoved;

2585 else

2586 ++NumAtExitRemoved;

2587

2588 Changed |= true;

2589 }

2590

2591 return Changed;

2592}

2593

2595 if (IF.isInterposable())

2596 return nullptr;

2597

2600 return nullptr;

2601

2602 if (Resolver->isInterposable())

2603 return nullptr;

2604

2605

2606 auto It = Resolver->begin();

2607 if (++It != Resolver->end())

2608 return nullptr;

2609

2611

2613 return nullptr;

2614

2615 auto *Ret = dyn_cast(BB.getTerminator());

2616 if (!Ret)

2617 return nullptr;

2618

2619 return dyn_cast(Ret->getReturnValue());

2620}

2621

2622

2623

2625 bool Changed = false;

2628 if (!IF.use_empty() &&

2629 (!Callee->isDeclaration() ||

2630 none_of(IF.users(), [](User *U) { return isa(U); }))) {

2631 IF.replaceAllUsesWith(Callee);

2632 NumIFuncsResolved++;

2633 Changed = true;

2634 }

2635 return Changed;

2636}

2637

2638static bool

2641 bool Changed = false;

2643 if (deleteIfDead(IF, NotDiscardableComdats)) {

2644 NumIFuncsDeleted++;

2645 Changed = true;

2646 }

2647 return Changed;

2648}

2649

2650

2651

2652

2655 if (auto *F = dyn_cast(V)) {

2657 return false;

2659 } else if (auto *Sel = dyn_cast(V)) {

2661 return false;

2663 return false;

2664 } else if (auto *Phi = dyn_cast(V)) {

2665 for (unsigned I = 0, E = Phi->getNumIncomingValues(); I != E; ++I)

2667 return false;

2668 } else {

2669

2670 return false;

2671 }

2672 return true;

2673}

2674

2675

2676

2677

2678

2679

2680

2681

2682

2683

2684

2685

2686

2687

2688

2689

2690

2691

2694 bool Changed = false;

2695

2696

2698

2700 if (IF.isInterposable())

2701 continue;

2702

2705 continue;

2706

2707 if (Resolver->isInterposable())

2708 continue;

2709

2711

2712

2715 if (auto *Ret = dyn_cast_or_null(BB.getTerminator()))

2717 return true;

2718 return false;

2719 }))

2720 continue;

2721

2722 assert(!Callees.empty() && "Expecting successful collection of versions");

2723

2724 LLVM_DEBUG(dbgs() << "Statically resolving calls to function "

2725 << Resolver->getName() << "\n");

2726

2727

2728 for (Function *Callee : Callees) {

2729 auto [It, Inserted] = FeatureMask.try_emplace(Callee);

2730 if (Inserted)

2732 }

2733

2734

2735 sort(Callees, [&](auto *LHS, auto *RHS) {

2736 return FeatureMask[LHS] > FeatureMask[RHS];

2737 });

2738

2739

2742 for (User *U : IF.users()) {

2743 if (auto *CB = dyn_cast(U)) {

2744 if (CB->getCalledOperand() == &IF) {

2745 Function *Caller = CB->getFunction();

2746 auto [FeatIt, FeatInserted] = FeatureMask.try_emplace(Caller);

2747 if (FeatInserted)

2749 auto [CallIt, CallInserted] = CallSites.try_emplace(Caller);

2750 if (CallInserted)

2751 Callers.push_back(Caller);

2752 CallIt->second.push_back(CB);

2753 }

2754 }

2755 }

2756

2757

2758 sort(Callers, [&](auto *LHS, auto *RHS) {

2759 return FeatureMask[LHS] > FeatureMask[RHS];

2760 });

2761

2763

2764

2765 unsigned I = 0;

2766

2767 for (Function *Caller : Callers) {

2768 assert(I < Callees.size() && "Found callers of equal priority");

2769

2771 uint64_t CallerBits = FeatureMask[Caller];

2772 uint64_t CalleeBits = FeatureMask[Callee];

2773

2774

2775

2776

2777

2779

2780

2781

2782 if (CallerBits == CalleeBits)

2783 ++I;

2784 else if (!implies(CallerBits, CalleeBits)) {

2785

2786

2787 while (implies(CalleeBits, CallerBits)) {

2788 if (++I == Callees.size())

2789 break;

2790 CalleeBits = FeatureMask[Callees[I]];

2791 }

2792 continue;

2793 }

2794 } else {

2795

2796

2798 continue;

2799 }

2800 auto &Calls = CallSites[Caller];

2801 for (CallBase *CS : Calls) {

2802 LLVM_DEBUG(dbgs() << "Redirecting call " << Caller->getName() << " -> "

2803 << Callee->getName() << "\n");

2804 CS->setCalledOperand(Callee);

2805 }

2806 Changed = true;

2807 }

2808 if (IF.use_empty() ||

2809 all_of(IF.users(), [](User *U) { return isa(U); }))

2810 NumIFuncsResolved++;

2811 }

2812 return Changed;

2813}

2814

2815static bool

2824 bool Changed = false;

2825 bool LocalChange = true;

2826 std::optional<uint32_t> FirstNotFullyEvaluatedPriority;

2827

2828 while (LocalChange) {

2829 LocalChange = false;

2830

2831 NotDiscardableComdats.clear();

2835 NotDiscardableComdats.insert(C);

2837 if (const Comdat *C = F.getComdat())

2838 if (F.isDefTriviallyDead())

2839 NotDiscardableComdats.insert(C);

2841 if (const Comdat *C = GA.getComdat())

2842 if (!GA.isDiscardableIfUnused() || !GA.use_empty())

2843 NotDiscardableComdats.insert(C);

2844

2845

2846 LocalChange |= OptimizeFunctions(M, GetTLI, GetTTI, GetBFI, LookupDomTree,

2847 NotDiscardableComdats, ChangedCFGCallback,

2848 DeleteFnCallback);

2849

2850

2851 LocalChange |=

2853 if (FirstNotFullyEvaluatedPriority &&

2854 *FirstNotFullyEvaluatedPriority != Priority)

2855 return false;

2857 if (!Evaluated)

2858 FirstNotFullyEvaluatedPriority = Priority;

2859 return Evaluated;

2860 });

2861

2862

2864 NotDiscardableComdats);

2865

2866

2868

2869

2870

2874

2877

2878

2880

2881

2883

2884

2886

2887 Changed |= LocalChange;

2888 }

2889

2890

2891

2892

2893 return Changed;

2894}

2895

2897 auto &DL = M.getDataLayout();

2898 auto &FAM =

2902 };

2905 };

2908 };

2909

2912 };

2913 auto ChangedCFGCallback = [&FAM](Function &F) {

2915 };

2917

2919 ChangedCFGCallback, DeleteFnCallback))

2921

2923

2925

2926

2927

2929 return PA;

2930}

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

Atomic ordering constants.

This file contains the simple types necessary to represent the attributes associated with functions a...

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

This file contains the declarations for the subclasses of Constant, which represent the different fla...

This file defines the DenseMap class.

This file contains constants used for implementing Dwarf debug support.

static bool IsSafeComputationToRemove(Value *V, function_ref< TargetLibraryInfo &(Function &)> GetTLI)

Given a value that is stored to a global but never read, determine whether it's safe to remove the st...

static Function * FindAtExitLibFunc(Module &M, function_ref< TargetLibraryInfo &(Function &)> GetTLI, LibFunc Func)

static bool optimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal, const DataLayout &DL, function_ref< TargetLibraryInfo &(Function &)> GetTLI)

static Function * hasSideeffectFreeStaticResolution(GlobalIFunc &IF)

static bool tryToOptimizeStoreOfAllocationToGlobal(GlobalVariable *GV, CallInst *CI, const DataLayout &DL, TargetLibraryInfo *TLI)

If we have a global that is only initialized with a fixed size allocation try to transform the progra...

static void ConstantPropUsersOf(Value *V, const DataLayout &DL, TargetLibraryInfo *TLI)

Walk the use list of V, constant folding all of the instructions that are foldable.

static bool hasOnlyColdCalls(Function &F, function_ref< BlockFrequencyInfo &(Function &)> GetBFI, ChangeableCCCacheTy &ChangeableCCCache)

static bool allUsesOfLoadedValueWillTrapIfNull(const GlobalVariable *GV)

Return true if all uses of any loads from GV will trap if the loaded value is null.

static bool hasChangeableCCImpl(Function *F)

Return true if this is a calling convention that we'd like to change.

static bool tryWidenGlobalArrayAndDests(Function *F, GlobalVariable *SourceVar, const unsigned NumBytesToPad, const unsigned NumBytesToCopy, ConstantInt *BytesToCopyOp, ConstantDataArray *SourceDataArray)

static GlobalVariable * widenGlobalVariable(GlobalVariable *OldVar, Function *F, unsigned NumBytesToPad, unsigned NumBytesToCopy)

static bool AllUsesOfValueWillTrapIfNull(const Value *V, SmallPtrSetImpl< const PHINode * > &PHIs)

Return true if all users of the specified value will trap if the value is dynamically null.

static GlobalVariable * OptimizeGlobalAddressOfAllocation(GlobalVariable *GV, CallInst *CI, uint64_t AllocSize, Constant *InitVal, const DataLayout &DL, TargetLibraryInfo *TLI)

This function takes the specified global variable, and transforms the program as if it always contain...

Returns whether the given function is an empty C destructor or atexit handler and can therefore be eliminated Note that we assume that other optimization passes have already simplified the code so we simply check for static ret bool IsEmptyAtExitFunction(const Function &Fn)

static bool collectSRATypes(DenseMap< uint64_t, GlobalPart > &Parts, GlobalVariable *GV, const DataLayout &DL)

Look at all uses of the global and determine which (offset, type) pairs it can be split into.

static bool valueIsOnlyUsedLocallyOrStoredToOneGlobal(const CallInst *CI, const GlobalVariable *GV)

Scan the use-list of GV checking to make sure that there are no complex uses of GV.

static bool OptimizeFunctions(Module &M, function_ref< TargetLibraryInfo &(Function &)> GetTLI, function_ref< TargetTransformInfo &(Function &)> GetTTI, function_ref< BlockFrequencyInfo &(Function &)> GetBFI, function_ref< DominatorTree &(Function &)> LookupDomTree, SmallPtrSetImpl< const Comdat * > &NotDiscardableComdats, function_ref< void(Function &F)> ChangedCFGCallback, function_ref< void(Function &F)> DeleteFnCallback)

static bool DeleteDeadIFuncs(Module &M, SmallPtrSetImpl< const Comdat * > &NotDiscardableComdats)

static void RemoveAttribute(Function *F, Attribute::AttrKind A)

static bool tryWidenGlobalArraysUsedByMemcpy(GlobalVariable *GV, function_ref< TargetTransformInfo &(Function &)> GetTTI)

static bool hasChangeableCC(Function *F, ChangeableCCCacheTy &ChangeableCCCache)

static bool deleteIfDead(GlobalValue &GV, SmallPtrSetImpl< const Comdat * > &NotDiscardableComdats, function_ref< void(Function &)> DeleteFnCallback=nullptr)

static void RemovePreallocated(Function *F)

static cl::opt< bool > OptimizeNonFMVCallers("optimize-non-fmv-callers", cl::desc("Statically resolve calls to versioned " "functions from non-versioned callers."), cl::init(true), cl::Hidden)

static bool processGlobal(GlobalValue &GV, function_ref< TargetTransformInfo &(Function &)> GetTTI, function_ref< TargetLibraryInfo &(Function &)> GetTLI, function_ref< DominatorTree &(Function &)> LookupDomTree)

Analyze the specified global variable and optimize it if possible.

static bool isColdCallSite(CallBase &CB, BlockFrequencyInfo &CallerBFI)

Return true if the block containing the call site has a BlockFrequency of less than ColdCCRelFreq% of...

static void transferSRADebugInfo(GlobalVariable *GV, GlobalVariable *NGV, uint64_t FragmentOffsetInBits, uint64_t FragmentSizeInBits, uint64_t VarSize)

Copy over the debug info for a variable to its SRA replacements.

static cl::opt< bool > EnableColdCCStressTest("enable-coldcc-stress-test", cl::desc("Enable stress test of coldcc by adding " "calling conv to all internal functions."), cl::init(false), cl::Hidden)

static bool OptimizeGlobalAliases(Module &M, SmallPtrSetImpl< const Comdat * > &NotDiscardableComdats)

static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal)

At this point, we have learned that the only two values ever stored into GV are its initializer and O...

static void ChangeCalleesToFastCall(Function *F)

Walk all of the direct calls of the specified function, changing them to FastCC.

static bool hasMustTailCallers(Function *F)

static bool callInstIsMemcpy(CallInst *CI)

static bool OptimizeNonTrivialIFuncs(Module &M, function_ref< TargetTransformInfo &(Function &)> GetTTI)

static bool OptimizeGlobalVars(Module &M, function_ref< TargetTransformInfo &(Function &)> GetTTI, function_ref< TargetLibraryInfo &(Function &)> GetTLI, function_ref< DominatorTree &(Function &)> LookupDomTree, SmallPtrSetImpl< const Comdat * > &NotDiscardableComdats)

static void allUsesOfLoadAndStores(GlobalVariable *GV, SmallVector< Value *, 4 > &Uses)

Get all the loads/store uses for global variable GV.

static void widenDestArray(CallInst *CI, const unsigned NumBytesToPad, const unsigned NumBytesToCopy, ConstantDataArray *SourceDataArray)

static bool OptimizeEmptyGlobalAtExitDtors(Function *CXAAtExitFn, bool isCXX)

static bool mayHaveOtherReferences(GlobalValue &GV, const LLVMUsed &U)

static void changeCallSitesToColdCC(Function *F)

static AttributeList StripAttr(LLVMContext &C, AttributeList Attrs, Attribute::AttrKind A)

static bool hasInvokeCallers(Function *F)

static void setUsedInitializer(GlobalVariable &V, const SmallPtrSetImpl< GlobalValue * > &Init)

static bool OptimizeAwayTrappingUsesOfLoads(GlobalVariable *GV, Constant *LV, const DataLayout &DL, function_ref< TargetLibraryInfo &(Function &)> GetTLI)

The specified global has only one non-null value stored into it.

static bool isValidCandidateForColdCC(Function &F, function_ref< BlockFrequencyInfo &(Function &)> GetBFI, const std::vector< Function * > &AllCallsCold)

static cl::opt< int > ColdCCRelFreq("coldcc-rel-freq", cl::Hidden, cl::init(2), cl::desc("Maximum block frequency, expressed as a percentage of caller's " "entry frequency, for a call site to be considered cold for enabling " "coldcc"))

static bool optimizeGlobalsInModule(Module &M, const DataLayout &DL, function_ref< TargetLibraryInfo &(Function &)> GetTLI, function_ref< TargetTransformInfo &(Function &)> GetTTI, function_ref< BlockFrequencyInfo &(Function &)> GetBFI, function_ref< DominatorTree &(Function &)> LookupDomTree, function_ref< void(Function &F)> ChangedCFGCallback, function_ref< void(Function &F)> DeleteFnCallback)

static bool EvaluateStaticConstructor(Function *F, const DataLayout &DL, TargetLibraryInfo *TLI)

Evaluate static constructors in the function, if we can.

static bool CleanupConstantGlobalUsers(GlobalVariable *GV, const DataLayout &DL)

We just marked GV constant.

Find IFuncs that have resolvers that always point at the same statically known and replace their callers with a direct static call bool OptimizeStaticIFuncs(Module &M)

static bool isLeakCheckerRoot(GlobalVariable *GV)

Is this global variable possibly used by a leak checker as a root? If so, we might not really want to...

static bool forwardStoredOnceStore(GlobalVariable *GV, const StoreInst *StoredOnceStore, function_ref< DominatorTree &(Function &)> LookupDomTree)

static int compareNames(Constant *const *A, Constant *const *B)

static bool collectVersions(TargetTransformInfo &TTI, Value *V, SmallVectorImpl< Function * > &Versions)

static bool CleanupPointerRootUsers(GlobalVariable *GV, function_ref< TargetLibraryInfo &(Function &)> GetTLI)

This GV is a pointer root.

static bool isPointerValueDeadOnEntryToFunction(const Function *F, GlobalValue *GV, function_ref< DominatorTree &(Function &)> LookupDomTree)

static bool processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS, function_ref< TargetTransformInfo &(Function &)> GetTTI, function_ref< TargetLibraryInfo &(Function &)> GetTLI, function_ref< DominatorTree &(Function &)> LookupDomTree)

Analyze the specified global variable and optimize it if possible.

static bool hasUsesToReplace(GlobalAlias &GA, const LLVMUsed &U, bool &RenameTarget)

static bool OptimizeAwayTrappingUsesOfValue(Value *V, Constant *NewV)

static GlobalVariable * SRAGlobal(GlobalVariable *GV, const DataLayout &DL)

Perform scalar replacement of aggregates on the specified global variable.

static bool destArrayCanBeWidened(CallInst *CI)

static bool hasUseOtherThanLLVMUsed(GlobalAlias &GA, const LLVMUsed &U)

Module.h This file contains the declarations for the Module class.

This defines the Use class.

uint64_t IntrinsicInst * II

FunctionAnalysisManager FAM

Remove Loads Into Fake Uses

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file defines the SmallPtrSet class.

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

static SymbolRef::Type getType(const Symbol *Sym)

This pass exposes codegen information to IR-level passes.

Class for arbitrary precision integers.

This class represents a conversion between pointers from one address space to another.

an instruction to allocate memory on the stack

void setAlignment(Align Align)

A container for analyses that lazily runs them and caches their results.

void clear(IRUnitT &IR, llvm::StringRef Name)

Clear any cached analysis results for a single unit of IR.

void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)

Invalidate cached analyses for an IR unit.

PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)

Get the result of an analysis pass for a given IR unit.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

uint64_t getNumElements() const

AttrKind

This enumeration lists the attributes that can be associated with parameters, function results,...

LLVM Basic Block Representation.

InstListType::iterator iterator

Instruction iterators...

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

static BinaryOperator * CreateNot(Value *Op, const Twine &Name="", InsertPosition InsertBefore=nullptr)

Analysis pass which computes BlockFrequencyInfo.

BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...

BlockFrequency getBlockFreq(const BasicBlock *BB) const

getblockFreq - Return block frequency.

Represents analyses that only rely on functions' control flow.

Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...

void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const

Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.

Function * getCalledFunction() const

Returns the function called, or null if this is an indirect function invocation or the function signa...

bool isMustTailCall() const

Tests if this call site must be tail call optimized.

Value * getCalledOperand() const

void setAttributes(AttributeList A)

Set the attributes for this call.

Value * getArgOperand(unsigned i) const

void setArgOperand(unsigned i, Value *v)

static CallBase * Create(CallBase *CB, ArrayRef< OperandBundleDef > Bundles, InsertPosition InsertPt=nullptr)

Create a clone of CB with a different set of operand bundles and insert it before InsertPt.

void setCalledOperand(Value *V)

unsigned arg_size() const

AttributeList getAttributes() const

Return the attributes for this call.

Function * getCaller()

Helper to get the caller (the parent function).

This class represents a function call, abstracting a target machine's calling convention.

bool isMustTailCall() const

Predicate getPredicate() const

Return the predicate for this instruction.

static Constant * get(ArrayType *T, ArrayRef< Constant * > V)

An array constant whose element type is a simple 1/2/4/8-byte integer or float/double,...

static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)

get() constructor - Return a constant with array type with an element count and element type matching...

ArrayType * getType() const

Specialize the getType() method to always return an ArrayType, which reduces the amount of casting ne...

uint64_t getElementByteSize() const

Return the size (in bytes) of each element in the array/vector.

StringRef getRawDataValues() const

Return the raw, underlying, bytes of this data.

A constant value that is initialized with an expression using other constant values.

static Constant * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)

Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.

static Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)

static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)

Getelementptr form.

This is the shared class of boolean and integer constants.

static ConstantInt * getTrue(LLVMContext &Context)

static ConstantInt * getFalse(LLVMContext &Context)

static ConstantInt * getBool(LLVMContext &Context, bool V)

This is an important base class in LLVM.

const Constant * stripPointerCasts() const

void removeDeadConstantUsers() const

If there are any dead constant users dangling off of this constant, remove them.

static Constant * getNullValue(Type *Ty)

Constructor to create a '0' constant of arbitrary type.

bool isNullValue() const

Return true if this is the value that would be returned by getNullValue.

bool extractIfOffset(int64_t &Offset) const

If this is a constant offset, extract it.

static std::optional< DIExpression * > createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits)

Create a DIExpression to describe one part of an aggregate variable that is fragmented across multipl...

static DIExpression * prependOpcodes(const DIExpression *Expr, SmallVectorImpl< uint64_t > &Ops, bool StackValue=false, bool EntryValue=false)

Prepend DIExpr with the given opcodes and optionally turn it into a stack value.

A pair of DIGlobalVariable and DIExpression.

uint64_t getSizeInBits() const

Base class for variables.

This class represents an Operation in the Expression.

A parsed version of the target data layout string in and methods for querying it.

std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)

bool erase(const KeyT &Val)

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

Analysis pass which computes a DominatorTree.

Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.

bool dominates(const BasicBlock *BB, const Use &U) const

Return true if the (end of the) basic block BB dominates the use U.

This class evaluates LLVM IR, producing the Constant representing each SSA instruction.

DenseMap< GlobalVariable *, Constant * > getMutatedInitializers() const

bool EvaluateFunction(Function *F, Constant *&RetVal, const SmallVectorImpl< Constant * > &ActualArgs)

Evaluate a call to function F, returning true if successful, false if we can't evaluate it.

const SmallPtrSetImpl< GlobalVariable * > & getInvariants() const

const BasicBlock & getEntryBlock() const

Intrinsic::ID getIntrinsicID() const LLVM_READONLY

getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

an instruction for type-safe pointer arithmetic to access elements of arrays and structs

const Constant * getAliasee() const

MaybeAlign getAlign() const

Returns the alignment of the given variable or function.

void setAlignment(Align Align)

Sets the alignment attribute of the GlobalObject.

PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)

bool isImplicitDSOLocal() const

bool isDeclaration() const

Return true if the primary definition of this global value is outside of the current translation unit...

LinkageTypes getLinkage() const

void setUnnamedAddr(UnnamedAddr Val)

bool hasLocalLinkage() const

bool hasPrivateLinkage() const

const Comdat * getComdat() const

ThreadLocalMode getThreadLocalMode() const

void setLinkage(LinkageTypes LT)

unsigned getAddressSpace() const

Module * getParent()

Get the module that this global value is contained inside of...

void eraseFromParent()

This method unlinks 'this' from the containing module and deletes it.

PointerType * getType() const

Global values are always pointers.

const DataLayout & getDataLayout() const

Get the data layout of the module this global belongs to.

static bool isInterposableLinkage(LinkageTypes Linkage)

Whether the definition of this global may be replaced by something non-equivalent at link time.

bool hasGlobalUnnamedAddr() const

UnnamedAddr getUnnamedAddr() const

static bool isWeakForLinker(LinkageTypes Linkage)

Whether the definition of this global may be replaced at link time.

static bool isDiscardableIfUnused(LinkageTypes Linkage)

Whether the definition of this global may be discarded if it is not used in its compilation unit.

@ InternalLinkage

Rename collisions when linking (static functions).

@ AppendingLinkage

Special purpose, only applies to global arrays.

Type * getValueType() const

const Constant * getInitializer() const

getInitializer - Return the initializer for this global variable.

void setInitializer(Constant *InitVal)

setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...

bool isExternallyInitialized() const

bool hasInitializer() const

Definitions have initializers, declarations don't.

void setConstant(bool Val)

void copyAttributesFrom(const GlobalVariable *Src)

copyAttributesFrom - copy all additional attributes (those not needed to create a GlobalVariable) fro...

void getDebugInfo(SmallVectorImpl< DIGlobalVariableExpression * > &GVs) const

Fill the vector with all debug info attachements.

bool isConstant() const

If the value is a global constant, its value is immutable throughout the runtime execution of the pro...

void eraseFromParent()

eraseFromParent - This method unlinks 'this' from the containing module and deletes it.

void addDebugInfo(DIGlobalVariableExpression *GV)

Attach a DIGlobalVariableExpression.

This instruction compares its operands according to the predicate given to the constructor.

AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")

CallInst * CreateStackSave(const Twine &Name="")

Create a call to llvm.stacksave.

CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)

Create and insert a memset to the specified pointer and the specified value.

CallInst * CreateStackRestore(Value *Ptr, const Twine &Name="")

Create a call to llvm.stackrestore.

void SetInsertPoint(BasicBlock *TheBB)

This specifies that created instructions should be appended to the end of the specified block.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...

const DebugLoc & getDebugLoc() const

Return the debug location for this node as a DebugLoc.

InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

const Function * getFunction() const

Return the function this instruction belongs to.

const Instruction * getNextNonDebugInstruction(bool SkipPseudoOp=false) const

Return a pointer to the next non-debug instruction in the same basic block as 'this',...

void setDebugLoc(DebugLoc Loc)

Set the debug location information for this instruction.

A wrapper class for inspecting calls to intrinsic functions.

This is an important class for using LLVM in a threaded context.

An instruction for reading from memory.

AtomicOrdering getOrdering() const

Returns the ordering constraint of this load instruction.

SyncScope::ID getSyncScopeID() const

Returns the synchronization scope ID of this load instruction.

LLVMContext & getContext() const

This is the common base class for memset/memcpy/memmove.

This class wraps the llvm.memset and llvm.memset.inline intrinsics.

This class wraps the llvm.memcpy/memmove intrinsics.

A Module instance is used to store all the information related to an LLVM module.

void insertGlobalVariable(GlobalVariable *GV)

Insert global variable GV at the end of the global variable list and take ownership.

unsigned getAddressSpace() const

Return the address space of the Pointer type.

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses none()

Convenience factory function for the empty preserved set.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

void preserveSet()

Mark an analysis set as preserved.

void preserve()

Mark an analysis as preserved.

Interface for looking up the initializer for a variable name, used by Init::resolveReferences.

static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, Instruction *MDFrom=nullptr)

A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...

bool erase(PtrType Ptr)

Remove pointer from the set.

size_type count(ConstPtrType Ptr) const

count - Return 1 if the specified pointer is in the set, 0 otherwise.

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void reserve(size_type N)

iterator erase(const_iterator CI)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

An instruction for storing to memory.

Value * getValueOperand()

StringRef - Represent a constant reference to a string, i.e.

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

int compare(StringRef RHS) const

compare - Compare two strings; the result is negative, zero, or positive if this string is lexicograp...

Class to represent struct types.

ArrayRef< Type * > elements() const

bool isOpaque() const

Return true if this is a type with an identity that has no body specified yet.

Analysis pass providing the TargetTransformInfo.

Analysis pass providing the TargetLibraryInfo.

Provides information about what library functions are available for the current target.

This pass provides access to the codegen interfaces that are needed for IR-level transformations.

uint64_t getFeatureMask(const Function &F) const

Returns a bitmask constructed from the target-features or fmv-features metadata of a function.

bool isMultiversionedFunction(const Function &F) const

Returns true if this is an instance of a function with multiple versions.

bool useColdCCForColdCall(Function &F) const

Return true if the input function which is cold at all call sites, should use coldcc calling conventi...

Target - Wrapper for Target specific information.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

The instances of the Type class are immutable: once they are created, they are never changed.

bool isVectorTy() const

True if this is an instance of VectorType.

bool isPointerTy() const

True if this is an instance of PointerType.

static IntegerType * getInt1Ty(LLVMContext &C)

unsigned getPointerAddressSpace() const

Get the address space of this pointer or pointer vector type.

@ ScalableVectorTyID

Scalable SIMD vector type.

@ FixedVectorTyID

Fixed width SIMD vector type.

bool isSingleValueType() const

Return true if the type is a valid type for a register in codegen.

bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const

Return true if this is a type whose size is a known multiple of vscale.

static IntegerType * getInt8Ty(LLVMContext &C)

bool isFloatingPointTy() const

Return true if this is one of the floating-point types.

TypeID getTypeID() const

Return the type id for the type.

static UndefValue * get(Type *T)

Static factory methods - Return an 'undef' object of the specified type.

A Use represents the edge between a Value definition and its users.

User * getUser() const

Returns the User that contains this Use.

Value * getOperand(unsigned i) const

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr) const

Accumulate the constant offset this value has compared to a base pointer.

bool hasOneUse() const

Return true if there is exactly one use of this value.

void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

iterator_range< user_iterator > users()

const Value * stripPointerCasts() const

Strip off pointer casts, all-zero GEPs and address space casts.

LLVMContext & getContext() const

All values hold a context through their type.

user_iterator_impl< User > user_iterator

StringRef getName() const

Return a constant reference to the value's name.

void takeName(Value *V)

Transfer the name from V to this value.

This class represents zero extension of integer types.

An efficient, type-erasing, non-owning reference to a callable.

const ParentTy * getParent() const

self_iterator getIterator()

NodeTy * getNextNode()

Get the next node, or nullptr for the list tail.

A range adaptor for a pair of iterators.

This provides a very simple, boring adaptor for a begin and end iterator into a range type.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ Cold

Attempts to make code in the caller as efficient as possible under the assumption that the call is no...

@ X86_ThisCall

Similar to X86_StdCall.

@ Fast

Attempts to make calls as fast as possible (e.g.

@ C

The default llvm calling convention, compatible with C.

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)

If this is a call to an allocation function that initializes memory to a fixed value,...

bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())

If the specified value is a trivially dead instruction, delete it.

bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI)

Return true if this is a call to an allocation function that does not have side effects that we are r...

const Value * getLoadStorePointerOperand(const Value *V)

A helper function that returns the pointer operand of a load or store instruction.

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)

This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

Constant * ConstantFoldConstant(const Constant *C, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)

ConstantFoldConstant - Fold the constant using the specified DataLayout.

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)

Return true if the result produced by the instruction is not used, and the instruction will return.

bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})

Compute the size of the object pointed by Ptr.

Constant * ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty, const DataLayout &DL)

If C is a uniform value where all bits are the same (either all zero, all ones, all undef or all pois...

bool isSafeToDestroyConstant(const Constant *C)

It is safe to destroy a constant iff it is only used by constants itself.

Align getOrEnforceKnownAlignment(Value *V, MaybeAlign PrefAlign, const DataLayout &DL, const Instruction *CxtI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr)

Try to ensure that the alignment of V is at least PrefAlign bytes.

bool optimizeGlobalCtorsList(Module &M, function_ref< bool(uint32_t, Function *)> ShouldRemove)

Call "ShouldRemove" for every entry in M's global_ctor list and remove the entries for which it retur...

void sort(IteratorTy Start, IteratorTy End)

bool NullPointerIsDefined(const Function *F, unsigned AS=0)

Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...

raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

bool isPointerTy(const Type *T)

bool none_of(R &&Range, UnaryPredicate P)

Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.

Constant * ConstantFoldLoadFromConst(Constant *C, Type *Ty, const APInt &Offset, const DataLayout &DL)

Extract value of C at the given Offset reinterpreted as Ty.

raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

constexpr T divideCeil(U Numerator, V Denominator)

Returns the integer ceil(Numerator / Denominator).

Constant * ConstantFoldInstruction(Instruction *I, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)

ConstantFoldInstruction - Try to constant fold the specified instruction.

bool RecursivelyDeleteTriviallyDeadInstructionsPermissive(SmallVectorImpl< WeakTrackingVH > &DeadInsts, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())

Same functionality as RecursivelyDeleteTriviallyDeadInstructions, but allow instructions that are not...

auto count_if(R &&Range, UnaryPredicate P)

Wrapper function around std::count_if to count the number of times an element satisfying a given pred...

bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI)

Tests if a value is a call or invoke to a library function that allocates or reallocates memory (eith...

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

Align commonAlignment(Align A, uint64_t Offset)

Returns the alignment that satisfies both alignments.

Type * getLoadStoreType(const Value *I)

A helper function that returns the type of a load or store instruction.

void array_pod_sort(IteratorTy Start, IteratorTy End)

array_pod_sort - This sorts an array with the specified start and end extent.

bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)

Remove all blocks that can not be reached from the function's entry.

GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)

Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...

Part of the global at a specific offset, which is only accessed through loads and stores with the giv...

This struct is a compact representation of a valid (non-zero power of two) alignment.

As we analyze each global or thread-local variable, keep track of some information about it.

@ InitializerStored

This global is stored to, but the only thing stored is the constant it was initialized with.

@ StoredOnce

This global is stored to, but only its initializer and one other value is ever stored to it.

static bool analyzeGlobal(const Value *V, GlobalStatus &GS)

Look at all uses of the global and fill in the GlobalStatus structure.

Various options to control the behavior of getObjectSize.

Function object to check whether the first component of a container supported by std::get (like std::...