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

98

99

100

101

102

103

104

105

106

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

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

112

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

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

118

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

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

124 "coldcc"));

125

126

127

129

130

131

132

133

134

135

136

138 return false;

139

142

143 unsigned Limit = 20;

144 do {

145 Type *Ty = Types.pop_back_val();

147 default: break;

149 return true;

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

153 return true;

154 break;

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

157 break;

159 StructType *STy = cast(Ty);

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

162 if (isa(InnerTy)) return true;

163 if (isa(InnerTy) || isa(InnerTy) ||

164 isa(InnerTy))

165 Types.push_back(InnerTy);

166 }

167 break;

168 }

169 }

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

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

172 return false;

173}

174

175

176

177

180 do {

181 if (isa(V))

182 return true;

183 if (!V->hasOneUse())

184 return false;

185 if (isa(V) || isa(V) || isa(V) ||

186 isa(V))

187 return false;

189 return true;

190

192 if (I->mayHaveSideEffects())

193 return false;

195 if (GEP->hasAllConstantIndices())

196 return false;

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

198 return false;

199 }

200

201 V = I->getOperand(0);

202 } while (true);

203}

204

205

206

207

208static bool

211

212

213

214

215

216

217

218

219

220 bool Changed = false;

221

222

223

225

227

228 while (!Worklist.empty()) {

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

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

232 if (isa(V)) {

233 Changed = true;

234 SI->eraseFromParent();

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

236 if (I->hasOneUse())

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

238 }

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

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

241 Changed = true;

242 MSI->eraseFromParent();

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

244 if (I->hasOneUse())

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

246 }

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

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

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

250 Changed = true;

251 MTI->eraseFromParent();

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

253 if (I->hasOneUse())

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

255 }

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

257 if (isa(CE))

259 }

260 }

261

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

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

266 do {

268 break;

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

270 if (!J)

271 break;

272 I->eraseFromParent();

273 I = J;

274 } while (true);

275 I->eraseFromParent();

276 Changed = true;

277 }

278 }

279

281 return Changed;

282}

283

284

285

286

292 bool Changed = false;

293

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

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

299 I->eraseFromParent();

300 Changed = true;

301 };

302 while (!WorkList.empty()) {

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

305 continue;

306

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

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

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

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

314

315

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

318 LI->replaceAllUsesWith(Res);

319 EraseFromParent(LI);

320 continue;

321 }

322

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

326 DL, Offset, true);

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

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

329 PtrOp = II->getArgOperand(0);

330 }

331 if (PtrOp == GV) {

333 LI->replaceAllUsesWith(Value);

334 EraseFromParent(LI);

335 }

336 }

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

338

339 EraseFromParent(SI);

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

342 EraseFromParent(MI);

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

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

346 }

347 }

348

349 Changed |=

352 return Changed;

353}

354

355

356

362};

363

364

365

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

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

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

374 };

375 AppendUses(GV);

376 while (!Worklist.empty()) {

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

379

380 auto *GEP = dyn_cast(V);

381 if (isa(V) || isa(V) ||

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

383 AppendUses(V);

384 continue;

385 }

386

388

389

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

391 return false;

392

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

395 true);

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

397 return false;

398

399

400

402 const auto &[It, Inserted] =

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

405 return false;

406

407 if (Inserted) {

408 It->second.Initializer =

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

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

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

413 << Offset.getZExtValue());

414 return false;

415 }

416 }

417

418

420 return false;

421

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

423 auto *SI = dyn_cast(V);

424 if (!SI)

425 return false;

426

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

428 if (!StoredConst)

429 return true;

430

431

432 return Initializer != StoredConst;

433 };

434

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

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

437 continue;

438 }

439

440

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

443 return false;

444 continue;

445 }

446

447

448 return false;

449 }

450

451 return true;

452}

453

454

456 uint64_t FragmentOffsetInBits,

461 for (auto *GVE : GVs) {

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

464 int64_t CurVarOffsetInBytes = 0;

465 uint64_t CurVarOffsetInBits = 0;

466 uint64_t FragmentEndInBits = FragmentOffsetInBits + FragmentSizeInBits;

467

468

470 continue;

471

472

473 if (CurVarOffsetInBytes < 0)

474 continue;

475

476

477 CurVarOffsetInBits = CHAR_BIT * (uint64_t)CurVarOffsetInBytes;

478

479

480 if (CurVarOffsetInBits >= FragmentEndInBits)

481 continue;

482

484 uint64_t CurVarEndInBits = CurVarOffsetInBits + CurVarSize;

485

486 if (CurVarSize != 0 &&

487 CurVarEndInBits <= FragmentOffsetInBits)

488 continue;

489

490

491

492 if (CurVarSize != 0 &&

493 CurVarOffsetInBits >= FragmentOffsetInBits &&

494 CurVarEndInBits <= FragmentEndInBits) {

495 uint64_t CurVarOffsetInFragment =

496 (CurVarOffsetInBits - FragmentOffsetInBits) / 8;

497 if (CurVarOffsetInFragment != 0)

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

499 CurVarOffsetInFragment});

500 else

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

502 auto *NGVE =

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

505 continue;

506 }

507

508

509 if (FragmentSizeInBits < VarSize) {

510 if (CurVarOffsetInBits > FragmentOffsetInBits)

511 continue;

512 uint64_t CurVarFragmentOffsetInBits =

513 FragmentOffsetInBits - CurVarOffsetInBits;

514 uint64_t CurVarFragmentSizeInBits = FragmentSizeInBits;

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

516 CurVarFragmentSizeInBits -= (FragmentEndInBits - CurVarEndInBits);

517 if (CurVarOffsetInBits)

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

520 Expr, CurVarFragmentOffsetInBits, CurVarFragmentSizeInBits))

521 Expr = *E;

522 else

523 continue;

524 }

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

527 }

528}

529

530

531

532

533

534

537

538

541 return nullptr;

542

543

545 return nullptr;

546

547

548

549

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

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

552 });

553 if (NumParts > 16)

554 return nullptr;

555

556

558 for (const auto &Pair : Parts) {

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

561 }

563

564

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

567

568 if (OffsetForTy < Offset)

569 return nullptr;

570

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

572 }

573

574

576 return nullptr;

577

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

579

580

581 Align StartAlignment =

584

585

587 unsigned NameSuffix = 0;

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

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

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

593

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

596

597

598

599

600

603

604

606 DL.getTypeAllocSizeInBits(Ty), VarSize);

607 }

608

609

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

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

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

617 };

618 AppendUsers(GV);

619 while (!Worklist.empty()) {

621 if (isa(V) || isa(V) ||

622 isa(V)) {

623 AppendUsers(V);

624 if (isa(V))

626 continue;

627 }

628

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

632 true);

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

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

636

637

641

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

643 LI->setOperand(0, NGV);

644 LI->setAlignment(NewAlign);

645 } else {

646 auto *SI = cast(V);

647 SI->setOperand(1, NGV);

648 SI->setAlignment(NewAlign);

649 }

650 continue;

651 }

652

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

655 }

656

657

661 ++NumSRA;

662

664 return NewGlobals.begin()->second;

665}

666

667

668

669

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

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

674

675

677 return false;

678 }

679 if (isa(U)) {

680

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

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

683 return false;

684 }

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

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

687 return false;

688 }

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

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

691 return false;

692 }

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

695 return false;

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

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

699

700

702 return false;

703 } else if (isa(U) &&

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

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

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

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

708 ->getPointerOperand()

709 ->stripPointerCasts()) &&

710 "Should be GlobalVariable");

711

712

713

714 } else {

715 return false;

716 }

717 }

718 return true;

719}

720

721

722

723

727 while (!Worklist.empty()) {

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

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

733 return false;

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

735

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

737 return false;

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

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

740 return false;

741

743 } else {

744

745 return false;

746 }

747 }

748 }

749

750 return true;

751}

752

753

758 while (!Worklist.empty()) {

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

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

763 continue;

764 }

765

766 assert((isa(U) || isa(U)) &&

767 "Expect only load or store instructions");

768 Uses.push_back(U);

769 }

770 }

771}

772

774 bool Changed = false;

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

777

778

780 return false;

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

782 LI->setOperand(0, NewV);

783 Changed = true;

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

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

786 SI->setOperand(1, NewV);

787 Changed = true;

788 }

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

790 CallBase *CB = cast(I);

792

793

795 Changed = true;

796 bool PassedAsArg = false;

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

799 PassedAsArg = true;

801 }

802

803 if (PassedAsArg) {

804

805 UI = V->user_begin();

806 }

807 }

811 if (CI->use_empty()) {

812 Changed = true;

813 CI->eraseFromParent();

814 }

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

816

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

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

820 i != e; ++i)

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

823 else

824 break;

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

828 NewV, Idxs));

829 if (GEPI->use_empty()) {

830 Changed = true;

831 GEPI->eraseFromParent();

832 }

833 }

834 }

835

836 return Changed;

837}

838

839

840

841

842

846 bool Changed = false;

847

848

849

850 bool AllNonStoreUsesGone = true;

851

852

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

856

857 if (LI->use_empty()) {

858 LI->eraseFromParent();

859 Changed = true;

860 } else {

861 AllNonStoreUsesGone = false;

862 }

863 } else if (isa(GlobalUser)) {

864

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

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

867 } else {

868 AllNonStoreUsesGone = false;

869

870

871

872 assert((isa(GlobalUser) || isa(GlobalUser) ||

873 isa(GlobalUser) || isa(GlobalUser) ||

874 isa(GlobalUser) ||

875 isa(GlobalUser) ||

876 isa(GlobalUser)) &&

877 "Only expect load and stores!");

878 }

879 }

880

881 if (Changed) {

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

883 << "\n");

884 ++NumGlobUses;

885 }

886

887

888

889 if (AllNonStoreUsesGone) {

892 } else {

893 Changed = true;

895 }

898 Changed = true;

900 ++NumDeleted;

901 }

902 }

903 return Changed;

904}

905

906

907

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

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

913 I->replaceAllUsesWith(NewC);

914

915

916

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

918 ++UI;

920 I->eraseFromParent();

921 }

922}

923

924

925

926

927

928

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

935 << '\n');

936

937

939 AllocSize);

940

941

942

947

948

949

950

951

952

953 if (!isa(InitVal)) {

955

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

957 }

958

959

961

962

963

968 bool InitBoolUsed = false;

969

970

973 for (auto *U : Guses) {

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

975

976

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

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

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

982 SI->eraseFromParent();

983 continue;

984 }

985

986 LoadInst *LI = cast(U);

990 if (!ICI) {

991 LoadUse.set(NewGV);

992 continue;

993 }

994

995

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

1000 InitBoolUsed = true;

1003 case ICmpInst::ICMP_ULT:

1005 break;

1006 case ICmpInst::ICMP_UGE:

1008 break;

1009 case ICmpInst::ICMP_ULE:

1010 case ICmpInst::ICMP_EQ:

1012 break;

1013 case ICmpInst::ICMP_NE:

1014 case ICmpInst::ICMP_UGT:

1015 break;

1016 }

1019 }

1021 }

1022

1023

1024 if (!InitBoolUsed) {

1025 while (!InitBool->use_empty())

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

1027 delete InitBool;

1028 } else

1030

1031

1034

1035

1036

1037

1039

1040 return NewGV;

1041}

1042

1043

1044

1045

1046static bool

1052

1053 while (!Worklist.empty()) {

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

1056 continue;

1057

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

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

1060 if (isa(U) || isa(U))

1061 continue;

1062

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

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

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

1066 return false;

1067 continue;

1068 }

1069

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

1072 continue;

1073 }

1074

1075 return false;

1076 }

1077 }

1078

1079 return true;

1080}

1081

1082

1083

1084

1085

1091

1092 return false;

1093

1096 if (!InitVal)

1097

1098 return false;

1099

1102 return false;

1103

1104

1105

1106

1107 if (AllocSize >= 2048)

1108 return false;

1109

1110

1111

1112

1113

1114

1115

1117 return false;

1118

1119

1120

1121

1122

1124 return false;

1125

1127 return true;

1128}

1129

1130

1131

1132static bool

1136

1138

1139

1140

1141

1142

1147 nullptr ,

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

1150

1152 return true;

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

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

1157 return true;

1158 }

1159 }

1160 }

1161

1162 return false;

1163}

1164

1165

1166

1167

1168

1171

1172

1173

1174

1175

1176

1180 return false;

1181

1182

1183

1185 if (!isa(U) && !isa(U))

1186 return false;

1188 return false;

1189 }

1190

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

1192

1193

1195 false,

1203

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

1207

1210

1211

1212

1213 bool IsOneZero = false;

1214 bool EmitOneOrZero = true;

1215 auto *CI = dyn_cast(OtherVal);

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

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

1218

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

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

1221 uint64_t ValInit = CIInit->getZExtValue();

1222 uint64_t ValOther = CI->getZExtValue();

1223 uint64_t ValMinus = ValOther - ValInit;

1224

1225 for(auto *GVe : GVs){

1229 unsigned SizeInOctets =

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

1231

1232

1233

1234

1235

1236

1237

1238

1239

1241 dwarf::DW_OP_deref_size, SizeInOctets,

1242 dwarf::DW_OP_constu, ValMinus,

1243 dwarf::DW_OP_mul, dwarf::DW_OP_constu, ValInit,

1244 dwarf::DW_OP_plus};

1245 bool WithStackValue = true;

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

1250 }

1251 EmitOneOrZero = false;

1252 }

1253 }

1254

1255 if (EmitOneOrZero) {

1256

1257

1258 for(auto *GV : GVs)

1260 }

1261

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

1265

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

1267

1268 Value *StoreVal;

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

1271 StoringOther);

1272 } else {

1273

1274

1275

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

1277

1278

1279

1280

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

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

1283

1284 StoreVal =

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

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

1288 } else {

1289 assert((isa(StoredVal) || isa(StoredVal)) &&

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

1291 StoreVal = StoredVal->getOperand(0);

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

1293 }

1294 }

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

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

1299 } else {

1300

1301 LoadInst *LI = cast(UI);

1306 if (IsOneZero)

1308 else

1311

1312

1316 }

1318 }

1319

1320

1321

1324 return true;

1325}

1326

1327static bool

1332

1334 return false;

1335

1338 return false;

1339

1340 bool Dead;

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

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

1343 else

1345 if (!Dead)

1346 return false;

1347

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

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

1350 if (DeleteFnCallback)

1351 DeleteFnCallback(*F);

1352 }

1355 ++NumDeleted;

1356 return true;

1357}

1358

1362

1363

1364

1365

1366

1367

1368

1369

1370

1371

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

1377 if (I)

1378 return false;

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

1380

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

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

1385 else

1386 return false;

1387 }

1388

1389

1390

1391

1392

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

1394

1395

1396

1397

1398

1399

1400

1401

1402

1403

1404 const unsigned Threshold = 100;

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

1406 return false;

1407

1408 for (auto *L : Loads) {

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

1412

1413

1414

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

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

1418 }))

1419 return false;

1420 }

1421

1422 return true;

1423}

1424

1425

1426

1427

1432

1433

1434

1435 if (!isa(StoredOnceValue))

1436 return false;

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

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

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

1444 }

1445 }

1446

1447 bool MadeChange = false;

1448 if (!Loads.empty()) {

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

1450 for (auto *LI : Loads) {

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

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

1453 LI->eraseFromParent();

1454 MadeChange = true;

1455 }

1456 }

1457 }

1458 return MadeChange;

1459}

1460

1461

1462

1463static bool

1469

1470

1471

1472

1473

1474

1475

1476

1477 if (!GS.HasMultipleAccessingFunctions &&

1478 GS.AccessingFunction &&

1482 GS.AccessingFunction->doesNotRecurse() &&

1484 LookupDomTree)) {

1486

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

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

1491

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

1496

1499 ++NumLocalized;

1500 return true;

1501 }

1502

1503 bool Changed = false;

1504

1505

1506

1507 if (!GS.IsLoaded) {

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

1509

1511

1513 } else {

1514

1515

1517 }

1518

1519

1522 ++NumDeleted;

1523 Changed = true;

1524 }

1525 return Changed;

1526

1527 }

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

1530

1531

1532

1533

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

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

1537 Changed = true;

1538 }

1539

1540

1542

1543

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

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

1548 ++NumDeleted;

1549 return true;

1550 }

1551

1552

1553 ++NumMarked;

1554 }

1558 return true;

1559 }

1560 Value *StoredOnceValue = GS.getStoredOnceValue();

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

1564 bool CanHaveNonUndefGlobalInitializer =

1565 GetTTI(StoreFn).canHaveNonUndefGlobalInitializerInAddressSpace(

1567

1568

1569

1570

1571

1572

1573

1574 auto *SOVConstant = dyn_cast(StoredOnceValue);

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

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

1578 CanHaveNonUndefGlobalInitializer) {

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

1580

1582 } else {

1583

1588 NGV->takeName(GV);

1589 NGV->copyAttributesFrom(GV);

1592 GV = NGV;

1593 }

1594

1595

1597

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

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

1602 ++NumDeleted;

1603 }

1604 ++NumSubstitute;

1605 return true;

1606 }

1607

1608

1609

1611 return true;

1612

1613

1614

1615 if (GS.NumStores == 1)

1617 return true;

1618

1619

1620

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

1623 CanHaveNonUndefGlobalInitializer)) {

1625 ++NumShrunkToBool;

1626 return true;

1627 }

1628 }

1629 }

1630

1631 return Changed;

1632}

1633

1634

1635

1636static bool

1642 return false;

1643

1645

1647 return false;

1648

1649 bool Changed = false;

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

1652 : GlobalValue::UnnamedAddr::Local;

1655 NumUnnamed++;

1656 Changed = true;

1657 }

1658 }

1659

1660

1662 return Changed;

1663

1664 auto *GVar = dyn_cast(&GV);

1665 if (!GVar)

1666 return Changed;

1667

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

1669 return Changed;

1670

1672 Changed;

1673}

1674

1675

1676

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

1679 if (isa(U))

1680 continue;

1682 }

1683}

1684

1687 unsigned AttrIndex;

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

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

1690 return Attrs;

1691}

1692

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

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

1696 if (isa(U))

1697 continue;

1698 CallBase *CB = cast(U);

1700 }

1701}

1702

1703

1704

1705

1706

1709

1710

1712 return false;

1713

1714 if (F->isVarArg())

1715 return false;

1716

1717

1718

1719

1720

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

1722 if (isa(U))

1723 continue;

1724 CallInst* CI = dyn_cast(U);

1725 if (!CI)

1726 continue;

1727

1729 return false;

1730 }

1731

1733 if (BB.getTerminatingMustTailCall())

1734 return false;

1735

1736 return F->hasAddressTaken();

1737}

1738

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

1743 if (Res.second)

1745 return Res.first->second;

1746}

1747

1748

1749

1752 auto *CallSiteBB = CB.getParent();

1753 auto CallSiteFreq = CallerBFI.getBlockFreq(CallSiteBB);

1754 auto CallerEntryFreq =

1756 return CallSiteFreq < CallerEntryFreq * ColdProb;

1757}

1758

1759

1760

1761

1762

1763static bool

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

1767

1768 if (F.user_empty())

1769 return false;

1770

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

1772 if (isa(U))

1773 continue;

1774

1775 CallBase &CB = cast(*U);

1779 return false;

1781 return false;

1782 }

1783 return true;

1784}

1785

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

1788 if (isa(U))

1789 continue;

1791 }

1792}

1793

1794

1795

1796

1797static bool

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

1804

1805 if (CI->isInlineAsm())

1806 continue;

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

1808 if (!CalledFn)

1809 return false;

1810

1811

1812

1813

1815 continue;

1817 return false;

1818

1820 return false;

1823 return false;

1824 }

1825 }

1826 }

1827 return true;

1828}

1829

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

1832 CallBase *CB = dyn_cast(U);

1833 if (!CB) {

1834 assert(isa(U) &&

1835 "Expected either CallBase or BlockAddress");

1836 continue;

1837 }

1839 return true;

1840 }

1841 return false;

1842}

1843

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

1846 if (isa(U))

1847 return true;

1848 return false;

1849}

1850

1853

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

1855

1857

1858

1860 for (User *U : PreallocatedCalls) {

1861 CallBase *CB = dyn_cast(U);

1862 if (!CB)

1863 continue;

1864

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

1868

1871 CallBase *PreallocatedSetup = nullptr;

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

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

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

1875 OpBundles.erase(It);

1876 break;

1877 }

1878 }

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

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

1882

1883 assert((isa(CB) || isa(CB)) &&

1884 "Unknown indirect call type");

1889

1894

1895

1896

1897

1898

1899

1900

1901

1904 for (auto *User : PreallocatedArgs) {

1905 auto *UseCall = cast(User);

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

1907 Intrinsic::call_preallocated_arg &&

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

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

1911 Value *AllocaReplacement = ArgAllocas[AllocArgIndex];

1912 if (!AllocaReplacement) {

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

1914 auto *ArgType =

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

1918 auto *Alloca =

1920 ArgAllocas[AllocArgIndex] = Alloca;

1921 AllocaReplacement = Alloca;

1922 }

1923

1925 UseCall->eraseFromParent();

1926 }

1927

1928 cast(PreallocatedSetup)->eraseFromParent();

1929 }

1930}

1931

1932static bool

1941

1942 bool Changed = false;

1943

1945 std::vector<Function *> AllCallsCold;

1948 AllCallsCold.push_back(&F);

1949

1950

1952

1953

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

1955 continue;

1956

1957

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

1960

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

1962 Changed = true;

1963 continue;

1964 }

1965

1966

1967

1968

1969

1970

1971

1972

1973

1974

1975 if (F.isDeclaration()) {

1977 Changed = true;

1978 ChangedCFGCallback(F);

1979 }

1980 }

1981

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

1983

1984 if (F.hasLocalLinkage())

1985 continue;

1986

1987

1988

1989

1990

1991

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

1995 Changed = true;

1996 }

1997

1998

1999

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

2004 Changed = true;

2005 }

2006 continue;

2007 }

2008

2010 NumInternalFunc++;

2012

2013

2014

2015

2019 ChangeableCCCache.erase(&F);

2022 Changed = true;

2023 NumColdCC++;

2024 }

2025 }

2026

2028

2029

2030

2033 ++NumFastCallFns;

2034 Changed = true;

2035 }

2036

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

2038 F.hasAddressTaken()) {

2039

2040

2042 ++NumNestRemoved;

2043 Changed = true;

2044 }

2045 }

2046 return Changed;

2047}

2048

2050 if (!CI)

2051 return false;

2052

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

2055 return false;

2056

2057 return true;

2058}

2059

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

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

2063

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

2065 return false;

2066

2067 if (!Alloca->isStaticAlloca())

2068 return false;

2069

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

2071 return false;

2072

2073 return true;

2074}

2075

2077 unsigned NumBytesToPad,

2078 unsigned NumBytesToCopy) {

2080 return nullptr;

2081

2083 dyn_cast(OldVar->getInitializer());

2084 if (!DataArray)

2085 return nullptr;

2086

2087

2088

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

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

2092 StrData.push_back('\0');

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

2094

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

2098 SourceReplace, SourceReplace->getName());

2099

2100

2103 return NewGV;

2104}

2105

2107 const unsigned NumBytesToCopy,

2109

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

2111 if (Alloca) {

2113 unsigned int TotalBytes = NumBytesToCopy + NumBytesToPad;

2114 unsigned NumElementsToCopy = divideCeil(TotalBytes, ElementByteWidth);

2115

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

2119 NewAlloca->takeName(Alloca);

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

2121 Alloca->replaceAllUsesWith(NewAlloca);

2122 Alloca->eraseFromParent();

2123 }

2124}

2125

2127 const unsigned NumBytesToPad,

2128 const unsigned NumBytesToCopy,

2131 auto *NewSourceGV =

2133 if (!NewSourceGV)

2134 return false;

2135

2136

2137

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

2139 auto *CI = dyn_cast(User);

2141 continue;

2142

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

2144 continue;

2145

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

2147

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

2149 NumBytesToCopy + NumBytesToPad));

2150 }

2152

2153 NumGlobalArraysPadded++;

2154 return true;

2155}

2156

2160

2163 return false;

2164

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

2168 continue;

2169

2171

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

2173 if (!BytesToCopyOp)

2174 continue;

2175

2178 if (!SourceDataArray)

2179 continue;

2180

2181 unsigned NumBytesToCopy = BytesToCopyOp->getZExtValue();

2182

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

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

2187

2188

2189

2190 unsigned NumElementsToCopy = divideCeil(NumBytesToCopy, ElementByteWidth);

2191

2192

2193

2194

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

2196 continue;

2197

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

2199 NumBytesToCopy, SourceDataArray->getType());

2200 if (NumBytesToPad) {

2202 BytesToCopyOp, SourceDataArray);

2203 }

2204 }

2205 return false;

2206}

2207

2208static bool

2214 bool Changed = false;

2215

2217

2220

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

2223 auto &DL = M.getDataLayout();

2224

2225

2226

2228 if (New != C)

2230 }

2231

2232 if (deleteIfDead(GV, NotDiscardableComdats)) {

2233 Changed = true;

2234 continue;

2235 }

2236

2237

2238

2240

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

2242 }

2243 return Changed;

2244}

2245

2246

2247

2250

2251 if (F->isDeclaration())

2252 return false;

2253

2258

2259 if (EvalSuccess) {

2260 ++NumCtorsEvaluated;

2261

2262

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

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

2266 << " stores.\n");

2267 for (const auto &Pair : NewInitializers)

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

2271 }

2272

2273 return EvalSuccess;

2274}

2275

2280}

2281

2284 if (Init.empty()) {

2285 V.eraseFromParent();

2286 return;

2287 }

2288

2289

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

2291 const auto *VAT = cast(UsedArrayType);

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

2293

2294

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

2297

2302 }

2303

2304

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

2307

2308 Module *M = V.getParent();

2309 V.removeFromParent();

2313 NV->takeName(&V);

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

2315 delete &V;

2316}

2317

2318namespace {

2319

2320

2321class LLVMUsed {

2326

2327public:

2328 LLVMUsed(Module &M) {

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

2335 }

2336

2339

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

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

2342

2343 used_iterator_range used() {

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

2345 }

2346

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

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

2349

2350 used_iterator_range compilerUsed() {

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

2352 }

2353

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

2355

2356 bool compilerUsedCount(GlobalValue *GV) const {

2357 return CompilerUsed.count(GV);

2358 }

2359

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

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

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

2363

2364 bool compilerUsedInsert(GlobalValue *GV) {

2365 return CompilerUsed.insert(GV).second;

2366 }

2367

2368 void syncVariablesAndSets() {

2369 if (UsedV)

2371 if (CompilerUsedV)

2373 }

2374};

2375

2376}

2377

2379 if (GA.use_empty())

2380 return false;

2381

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

2383 "We should have removed the duplicated "

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

2386

2387

2388 return true;

2389

2390

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

2392}

2393

2396 return true;

2397

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

2399}

2400

2402 bool &RenameTarget) {

2404 return false;

2405

2406 RenameTarget = false;

2407 bool Ret = false;

2409 Ret = true;

2410

2411

2413 return Ret;

2414

2415

2416

2417

2418

2419

2420

2421

2425 return Ret;

2426

2427 RenameTarget = true;

2428 return true;

2429}

2430

2431static bool

2434 bool Changed = false;

2435 LLVMUsed Used(M);

2436

2438 Used.compilerUsedErase(GV);

2439

2440

2441

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

2445 };

2446

2448

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

2451

2452 if (deleteIfDead(J, NotDiscardableComdats)) {

2453 Changed = true;

2454 continue;

2455 }

2456

2457

2458 if (!IsModuleLocal(J))

2459 continue;

2460

2461 Constant *Aliasee = J.getAliasee();

2463

2464

2465

2466

2467

2468

2470 continue;

2471

2472 Target->removeDeadConstantUsers();

2473

2474

2475 bool RenameTarget;

2477 continue;

2478

2479 J.replaceAllUsesWith(Aliasee);

2480 ++NumAliasesResolved;

2481 Changed = true;

2482

2483 if (RenameTarget) {

2484

2485 Target->takeName(&J);

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

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

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

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

2490

2491 if (Used.usedErase(&J))

2492 Used.usedInsert(Target);

2493

2494 if (Used.compilerUsedErase(&J))

2495 Used.compilerUsedInsert(Target);

2497 continue;

2498

2499

2500 M.eraseAlias(&J);

2501 ++NumAliasesRemoved;

2502 Changed = true;

2503 }

2504

2505 Used.syncVariablesAndSets();

2506

2507 return Changed;

2508}

2509

2514

2515 auto FuncIter = M.begin();

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

2517 return nullptr;

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

2519

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

2521 return nullptr;

2522

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

2524 if (!Fn)

2525 return nullptr;

2526

2527

2528 TLI = &GetTLI(*Fn);

2529

2530

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

2533 return nullptr;

2534

2535 return Fn;

2536}

2537

2538

2539

2540

2541

2543

2544

2546 return false;

2547

2549 if (I.isDebugOrPseudoInst())

2550 continue;

2551 if (isa(I))

2552 return true;

2553 break;

2554 }

2555 return false;

2556}

2557

2559

2560

2561

2562

2563

2564

2565

2566

2567

2568

2569

2570

2571

2572

2573 bool Changed = false;

2574

2576

2577

2578

2579 CallInst *CI = dyn_cast(U);

2580 if (!CI)

2581 continue;

2582

2586 continue;

2587

2588

2591

2592 if (isCXX)

2593 ++NumCXXDtorsRemoved;

2594 else

2595 ++NumAtExitRemoved;

2596

2597 Changed |= true;

2598 }

2599

2600 return Changed;

2601}

2602

2604 if (IF.isInterposable())

2605 return nullptr;

2606

2609 return nullptr;

2610

2611 if (Resolver->isInterposable())

2612 return nullptr;

2613

2614

2615 auto It = Resolver->begin();

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

2617 return nullptr;

2618

2620

2622 return nullptr;

2623

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

2625 if (!Ret)

2626 return nullptr;

2627

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

2629}

2630

2631

2632

2634 bool Changed = false;

2637 if (!IF.use_empty() &&

2638 (!Callee->isDeclaration() ||

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

2640 IF.replaceAllUsesWith(Callee);

2641 NumIFuncsResolved++;

2642 Changed = true;

2643 }

2644 return Changed;

2645}

2646

2647static bool

2650 bool Changed = false;

2652 if (deleteIfDead(IF, NotDiscardableComdats)) {

2653 NumIFuncsDeleted++;

2654 Changed = true;

2655 }

2656 return Changed;

2657}

2658

2659

2660

2661

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

2666 return false;

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

2670 return false;

2672 return false;

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

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

2676 return false;

2677 } else {

2678

2679 return false;

2680 }

2681 return true;

2682}

2683

2684

2685

2686

2687

2688

2689

2690

2691

2692

2693

2694

2695

2696

2697

2698

2699

2700

2703 bool Changed = false;

2704

2705

2707

2709 if (IF.isInterposable())

2710 continue;

2711

2714 continue;

2715

2716 if (Resolver->isInterposable())

2717 continue;

2718

2720

2721

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

2726 return true;

2727 return false;

2728 }))

2729 continue;

2730

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

2732

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

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

2735

2736

2737 for (Function *Callee : Callees) {

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

2739 if (Inserted)

2741 }

2742

2743

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

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

2746 });

2747

2748

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

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

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

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

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

2756 if (FeatInserted)

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

2759 if (CallInserted)

2760 Callers.push_back(Caller);

2761 CallIt->second.push_back(CB);

2762 }

2763 }

2764 }

2765

2766

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

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

2769 });

2770

2772

2773

2774 unsigned I = 0;

2775

2776 for (Function *Caller : Callers) {

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

2778

2780 uint64_t CallerBits = FeatureMask[Caller];

2781 uint64_t CalleeBits = FeatureMask[Callee];

2782

2783

2784

2785

2786

2788

2789

2790

2791 if (CallerBits == CalleeBits)

2792 ++I;

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

2794

2795

2796 while (implies(CalleeBits, CallerBits)) {

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

2798 break;

2799 CalleeBits = FeatureMask[Callees[I]];

2800 }

2801 continue;

2802 }

2803 } else {

2804

2805

2807 continue;

2808 }

2809 auto &Calls = CallSites[Caller];

2810 for (CallBase *CS : Calls) {

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

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

2813 CS->setCalledOperand(Callee);

2814 }

2815 Changed = true;

2816 }

2817 if (IF.use_empty() ||

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

2819 NumIFuncsResolved++;

2820 }

2821 return Changed;

2822}

2823

2824static bool

2833 bool Changed = false;

2834 bool LocalChange = true;

2835 std::optional<uint32_t> FirstNotFullyEvaluatedPriority;

2836

2837 while (LocalChange) {

2838 LocalChange = false;

2839

2840 NotDiscardableComdats.clear();

2844 NotDiscardableComdats.insert(C);

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

2847 if (F.isDefTriviallyDead())

2848 NotDiscardableComdats.insert(C);

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

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

2852 NotDiscardableComdats.insert(C);

2853

2854

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

2856 NotDiscardableComdats, ChangedCFGCallback,

2857 DeleteFnCallback);

2858

2859

2860 LocalChange |=

2862 if (FirstNotFullyEvaluatedPriority &&

2863 *FirstNotFullyEvaluatedPriority != Priority)

2864 return false;

2866 if (!Evaluated)

2867 FirstNotFullyEvaluatedPriority = Priority;

2868 return Evaluated;

2869 });

2870

2871

2873 NotDiscardableComdats);

2874

2875

2877

2878

2879

2883

2886

2887

2889

2890

2892

2893

2895

2896 Changed |= LocalChange;

2897 }

2898

2899

2900

2901

2902 return Changed;

2903}

2904

2906 auto &DL = M.getDataLayout();

2907 auto &FAM =

2911 };

2914 };

2917 };

2918

2921 };

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

2924 };

2926

2928 ChangedCFGCallback, DeleteFnCallback))

2930

2932

2934

2935

2936

2938 return PA;

2939}

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 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 cl::opt< bool > OptimizeNonFMVCallers("optimize-non-fmv-callers", cl::desc("Statically resolve calls to versioned " "functions from non-versioned callers."), cl::init(false), cl::Hidden)

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::...