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("Enable stress test of coldcc by adding "

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

103

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

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

109 "coldcc"));

110

111

112

114

115

116

117

118

119

120

121

123 return false;

124

127

128 unsigned Limit = 20;

129 do {

130 Type *Ty = Types.pop_back_val();

132 default: break;

134 return true;

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

138 return true;

139 break;

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

142 break;

144 StructType *STy = cast(Ty);

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

147 if (isa(InnerTy)) return true;

148 if (isa(InnerTy) || isa(InnerTy) ||

149 isa(InnerTy))

150 Types.push_back(InnerTy);

151 }

152 break;

153 }

154 }

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

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

157 return false;

158}

159

160

161

162

165 do {

166 if (isa(V))

167 return true;

168 if (!V->hasOneUse())

169 return false;

170 if (isa(V) || isa(V) || isa(V) ||

171 isa(V))

172 return false;

174 return true;

175

177 if (I->mayHaveSideEffects())

178 return false;

180 if (GEP->hasAllConstantIndices())

181 return false;

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

183 return false;

184 }

185

186 V = I->getOperand(0);

187 } while (true);

188}

189

190

191

192

193static bool

196

197

198

199

200

201

202

203

204

205 bool Changed = false;

206

207

208

210

212

213 while (!Worklist.empty()) {

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

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

217 if (isa(V)) {

218 Changed = true;

219 SI->eraseFromParent();

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

221 if (I->hasOneUse())

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

223 }

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

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

226 Changed = true;

227 MSI->eraseFromParent();

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

229 if (I->hasOneUse())

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

231 }

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

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

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

235 Changed = true;

236 MTI->eraseFromParent();

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

238 if (I->hasOneUse())

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

240 }

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

242 if (isa(CE))

244 }

245 }

246

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

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

251 do {

253 break;

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

255 if (!J)

256 break;

257 I->eraseFromParent();

258 I = J;

259 } while (true);

260 I->eraseFromParent();

261 Changed = true;

262 }

263 }

264

266 return Changed;

267}

268

269

270

271

277 bool Changed = false;

278

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

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

284 I->eraseFromParent();

285 Changed = true;

286 };

287 while (!WorkList.empty()) {

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

290 continue;

291

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

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

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

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

299

300

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

303 LI->replaceAllUsesWith(Res);

304 EraseFromParent(LI);

305 continue;

306 }

307

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

311 DL, Offset, true);

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

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

314 PtrOp = II->getArgOperand(0);

315 }

316 if (PtrOp == GV) {

318 LI->replaceAllUsesWith(Value);

319 EraseFromParent(LI);

320 }

321 }

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

323

324 EraseFromParent(SI);

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

327 EraseFromParent(MI);

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

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

331 }

332 }

333

334 Changed |=

337 return Changed;

338}

339

340

341

347};

348

349

350

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

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

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

359 };

360 AppendUses(GV);

361 while (!Worklist.empty()) {

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

364

365 auto *GEP = dyn_cast(V);

366 if (isa(V) || isa(V) ||

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

368 AppendUses(V);

369 continue;

370 }

371

373

374

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

376 return false;

377

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

380 true);

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

382 return false;

383

384

385

387 const auto &[It, Inserted] =

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

390 return false;

391

392 if (Inserted) {

393 It->second.Initializer =

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

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

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

398 << Offset.getZExtValue());

399 return false;

400 }

401 }

402

403

405 return false;

406

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

408 auto *SI = dyn_cast(V);

409 if (!SI)

410 return false;

411

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

413 if (!StoredConst)

414 return true;

415

416

417 return Initializer != StoredConst;

418 };

419

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

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

422 continue;

423 }

424

425

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

428 return false;

429 continue;

430 }

431

432

433 return false;

434 }

435

436 return true;

437}

438

439

441 uint64_t FragmentOffsetInBits,

446 for (auto *GVE : GVs) {

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

449 int64_t CurVarOffsetInBytes = 0;

450 uint64_t CurVarOffsetInBits = 0;

451 uint64_t FragmentEndInBits = FragmentOffsetInBits + FragmentSizeInBits;

452

453

455 continue;

456

457

458 if (CurVarOffsetInBytes < 0)

459 continue;

460

461

462 CurVarOffsetInBits = CHAR_BIT * (uint64_t)CurVarOffsetInBytes;

463

464

465 if (CurVarOffsetInBits >= FragmentEndInBits)

466 continue;

467

469 uint64_t CurVarEndInBits = CurVarOffsetInBits + CurVarSize;

470

471 if (CurVarSize != 0 &&

472 CurVarEndInBits <= FragmentOffsetInBits)

473 continue;

474

475

476

477 if (CurVarSize != 0 &&

478 CurVarOffsetInBits >= FragmentOffsetInBits &&

479 CurVarEndInBits <= FragmentEndInBits) {

480 uint64_t CurVarOffsetInFragment =

481 (CurVarOffsetInBits - FragmentOffsetInBits) / 8;

482 if (CurVarOffsetInFragment != 0)

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

484 CurVarOffsetInFragment});

485 else

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

487 auto *NGVE =

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

490 continue;

491 }

492

493

494 if (FragmentSizeInBits < VarSize) {

495 if (CurVarOffsetInBits > FragmentOffsetInBits)

496 continue;

497 uint64_t CurVarFragmentOffsetInBits =

498 FragmentOffsetInBits - CurVarOffsetInBits;

499 uint64_t CurVarFragmentSizeInBits = FragmentSizeInBits;

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

501 CurVarFragmentSizeInBits -= (FragmentEndInBits - CurVarEndInBits);

502 if (CurVarOffsetInBits)

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

505 Expr, CurVarFragmentOffsetInBits, CurVarFragmentSizeInBits))

506 Expr = *E;

507 else

508 continue;

509 }

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

512 }

513}

514

515

516

517

518

519

522

523

526 return nullptr;

527

528

530 return nullptr;

531

532

533

534

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

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

537 });

538 if (NumParts > 16)

539 return nullptr;

540

541

543 for (const auto &Pair : Parts) {

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

546 }

548

549

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

552

553 if (OffsetForTy < Offset)

554 return nullptr;

555

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

557 }

558

559

561 return nullptr;

562

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

564

565

566 Align StartAlignment =

569

570

572 unsigned NameSuffix = 0;

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

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

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

578

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

581

582

583

584

585

588

589

591 DL.getTypeAllocSizeInBits(Ty), VarSize);

592 }

593

594

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

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

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

602 };

603 AppendUsers(GV);

604 while (!Worklist.empty()) {

606 if (isa(V) || isa(V) ||

607 isa(V)) {

608 AppendUsers(V);

609 if (isa(V))

611 continue;

612 }

613

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

617 true);

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

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

621

622

626

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

628 LI->setOperand(0, NGV);

629 LI->setAlignment(NewAlign);

630 } else {

631 auto *SI = cast(V);

632 SI->setOperand(1, NGV);

633 SI->setAlignment(NewAlign);

634 }

635 continue;

636 }

637

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

640 }

641

642

646 ++NumSRA;

647

649 return NewGlobals.begin()->second;

650}

651

652

653

654

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

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

659

660

662 return false;

663 }

664 if (isa(U)) {

665

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

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

668 return false;

669 }

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

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

672 return false;

673 }

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

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

676 return false;

677 }

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

680 return false;

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

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

684

685

687 return false;

688 } else if (isa(U) &&

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

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

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

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

693 ->getPointerOperand()

694 ->stripPointerCasts()) &&

695 "Should be GlobalVariable");

696

697

698

699 } else {

700 return false;

701 }

702 }

703 return true;

704}

705

706

707

708

712 while (!Worklist.empty()) {

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

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

718 return false;

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

720

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

722 return false;

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

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

725 return false;

726

728 } else {

729

730 return false;

731 }

732 }

733 }

734

735 return true;

736}

737

738

743 while (!Worklist.empty()) {

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

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

748 continue;

749 }

750

751 assert((isa(U) || isa(U)) &&

752 "Expect only load or store instructions");

753 Uses.push_back(U);

754 }

755 }

756}

757

759 bool Changed = false;

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

762

763

765 return false;

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

767 LI->setOperand(0, NewV);

768 Changed = true;

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

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

771 SI->setOperand(1, NewV);

772 Changed = true;

773 }

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

775 CallBase *CB = cast(I);

777

778

780 Changed = true;

781 bool PassedAsArg = false;

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

784 PassedAsArg = true;

786 }

787

788 if (PassedAsArg) {

789

790 UI = V->user_begin();

791 }

792 }

796 if (CI->use_empty()) {

797 Changed = true;

798 CI->eraseFromParent();

799 }

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

801

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

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

805 i != e; ++i)

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

808 else

809 break;

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

813 NewV, Idxs));

814 if (GEPI->use_empty()) {

815 Changed = true;

816 GEPI->eraseFromParent();

817 }

818 }

819 }

820

821 return Changed;

822}

823

824

825

826

827

831 bool Changed = false;

832

833

834

835 bool AllNonStoreUsesGone = true;

836

837

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

841

842 if (LI->use_empty()) {

843 LI->eraseFromParent();

844 Changed = true;

845 } else {

846 AllNonStoreUsesGone = false;

847 }

848 } else if (isa(GlobalUser)) {

849

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

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

852 } else {

853 AllNonStoreUsesGone = false;

854

855

856

857 assert((isa(GlobalUser) || isa(GlobalUser) ||

858 isa(GlobalUser) || isa(GlobalUser) ||

859 isa(GlobalUser) ||

860 isa(GlobalUser) ||

861 isa(GlobalUser)) &&

862 "Only expect load and stores!");

863 }

864 }

865

866 if (Changed) {

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

868 << "\n");

869 ++NumGlobUses;

870 }

871

872

873

874 if (AllNonStoreUsesGone) {

877 } else {

878 Changed = true;

880 }

883 Changed = true;

885 ++NumDeleted;

886 }

887 }

888 return Changed;

889}

890

891

892

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

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

898 I->replaceAllUsesWith(NewC);

899

900

901

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

903 ++UI;

905 I->eraseFromParent();

906 }

907}

908

909

910

911

912

913

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

920 << '\n');

921

922

924 AllocSize);

925

926

927

932

933

934

935

936

937

938 if (!isa(InitVal)) {

940

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

942 }

943

944

946

947

948

953 bool InitBoolUsed = false;

954

955

958 for (auto *U : Guses) {

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

960

961

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

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

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

967 SI->eraseFromParent();

968 continue;

969 }

970

971 LoadInst *LI = cast(U);

975 if (!ICI) {

976 LoadUse.set(NewGV);

977 continue;

978 }

979

980

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

985 InitBoolUsed = true;

988 case ICmpInst::ICMP_ULT:

990 break;

991 case ICmpInst::ICMP_UGE:

993 break;

994 case ICmpInst::ICMP_ULE:

995 case ICmpInst::ICMP_EQ:

997 break;

998 case ICmpInst::ICMP_NE:

999 case ICmpInst::ICMP_UGT:

1000 break;

1001 }

1004 }

1006 }

1007

1008

1009 if (!InitBoolUsed) {

1010 while (!InitBool->use_empty())

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

1012 delete InitBool;

1013 } else

1015

1016

1019

1020

1021

1022

1024

1025 return NewGV;

1026}

1027

1028

1029

1030

1031static bool

1037

1038 while (!Worklist.empty()) {

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

1041 continue;

1042

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

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

1045 if (isa(U) || isa(U))

1046 continue;

1047

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

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

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

1051 return false;

1052 continue;

1053 }

1054

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

1057 continue;

1058 }

1059

1060 return false;

1061 }

1062 }

1063

1064 return true;

1065}

1066

1067

1068

1069

1070

1076

1077 return false;

1078

1081 if (!InitVal)

1082

1083 return false;

1084

1087 return false;

1088

1089

1090

1091

1092 if (AllocSize >= 2048)

1093 return false;

1094

1095

1096

1097

1098

1099

1100

1102 return false;

1103

1104

1105

1106

1107

1109 return false;

1110

1112 return true;

1113}

1114

1115

1116

1117static bool

1121

1123

1124

1125

1126

1127

1132 nullptr ,

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

1135

1137 return true;

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

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

1142 return true;

1143 }

1144 }

1145 }

1146

1147 return false;

1148}

1149

1150

1151

1152

1153

1156

1157

1158

1159

1160

1161

1165 return false;

1166

1167

1168

1170 if (!isa(U) && !isa(U))

1171 return false;

1173 return false;

1174 }

1175

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

1177

1178

1180 false,

1188

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

1192

1195

1196

1197

1198 bool IsOneZero = false;

1199 bool EmitOneOrZero = true;

1200 auto *CI = dyn_cast(OtherVal);

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

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

1203

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

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

1206 uint64_t ValInit = CIInit->getZExtValue();

1207 uint64_t ValOther = CI->getZExtValue();

1208 uint64_t ValMinus = ValOther - ValInit;

1209

1210 for(auto *GVe : GVs){

1214 unsigned SizeInOctets =

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

1216

1217

1218

1219

1220

1221

1222

1223

1224

1226 dwarf::DW_OP_deref_size, SizeInOctets,

1227 dwarf::DW_OP_constu, ValMinus,

1228 dwarf::DW_OP_mul, dwarf::DW_OP_constu, ValInit,

1229 dwarf::DW_OP_plus};

1230 bool WithStackValue = true;

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

1235 }

1236 EmitOneOrZero = false;

1237 }

1238 }

1239

1240 if (EmitOneOrZero) {

1241

1242

1243 for(auto *GV : GVs)

1245 }

1246

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

1250

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

1252

1253 Value *StoreVal;

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

1256 StoringOther);

1257 } else {

1258

1259

1260

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

1262

1263

1264

1265

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

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

1268

1269 StoreVal =

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

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

1273 } else {

1274 assert((isa(StoredVal) || isa(StoredVal)) &&

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

1276 StoreVal = StoredVal->getOperand(0);

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

1278 }

1279 }

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

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

1284 } else {

1285

1286 LoadInst *LI = cast(UI);

1291 if (IsOneZero)

1293 else

1296

1297

1301 }

1303 }

1304

1305

1306

1309 return true;

1310}

1311

1312static bool

1317

1319 return false;

1320

1323 return false;

1324

1325 bool Dead;

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

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

1328 else

1330 if (!Dead)

1331 return false;

1332

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

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

1335 if (DeleteFnCallback)

1336 DeleteFnCallback(*F);

1337 }

1340 ++NumDeleted;

1341 return true;

1342}

1343

1347

1348

1349

1350

1351

1352

1353

1354

1355

1356

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

1362 if (I)

1363 return false;

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

1365

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

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

1370 else

1371 return false;

1372 }

1373

1374

1375

1376

1377

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

1379

1380

1381

1382

1383

1384

1385

1386

1387

1388

1389 const unsigned Threshold = 100;

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

1391 return false;

1392

1393 for (auto *L : Loads) {

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

1397

1398

1399

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

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

1403 }))

1404 return false;

1405 }

1406

1407 return true;

1408}

1409

1410

1411

1412

1417

1418

1419

1420 if (!isa(StoredOnceValue))

1421 return false;

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

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

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

1429 }

1430 }

1431

1432 bool MadeChange = false;

1433 if (!Loads.empty()) {

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

1435 for (auto *LI : Loads) {

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

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

1438 LI->eraseFromParent();

1439 MadeChange = true;

1440 }

1441 }

1442 }

1443 return MadeChange;

1444}

1445

1446

1447

1448static bool

1454

1455

1456

1457

1458

1459

1460

1461

1462 if (!GS.HasMultipleAccessingFunctions &&

1463 GS.AccessingFunction &&

1467 GS.AccessingFunction->doesNotRecurse() &&

1469 LookupDomTree)) {

1471

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

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

1476

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

1481

1484 ++NumLocalized;

1485 return true;

1486 }

1487

1488 bool Changed = false;

1489

1490

1491

1492 if (!GS.IsLoaded) {

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

1494

1496

1498 } else {

1499

1500

1502 }

1503

1504

1507 ++NumDeleted;

1508 Changed = true;

1509 }

1510 return Changed;

1511

1512 }

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

1515

1516

1517

1518

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

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

1522 Changed = true;

1523 }

1524

1525

1527

1528

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

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

1533 ++NumDeleted;

1534 return true;

1535 }

1536

1537

1538 ++NumMarked;

1539 }

1543 return true;

1544 }

1545 Value *StoredOnceValue = GS.getStoredOnceValue();

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

1549 bool CanHaveNonUndefGlobalInitializer =

1550 GetTTI(StoreFn).canHaveNonUndefGlobalInitializerInAddressSpace(

1552

1553

1554

1555

1556

1557

1558

1559 auto *SOVConstant = dyn_cast(StoredOnceValue);

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

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

1563 CanHaveNonUndefGlobalInitializer) {

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

1565

1567 } else {

1568

1573 NGV->takeName(GV);

1574 NGV->copyAttributesFrom(GV);

1577 GV = NGV;

1578 }

1579

1580

1582

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

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

1587 ++NumDeleted;

1588 }

1589 ++NumSubstitute;

1590 return true;

1591 }

1592

1593

1594

1596 return true;

1597

1598

1599

1600 if (GS.NumStores == 1)

1602 return true;

1603

1604

1605

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

1608 CanHaveNonUndefGlobalInitializer)) {

1610 ++NumShrunkToBool;

1611 return true;

1612 }

1613 }

1614 }

1615

1616 return Changed;

1617}

1618

1619

1620

1621static bool

1627 return false;

1628

1630

1632 return false;

1633

1634 bool Changed = false;

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

1637 : GlobalValue::UnnamedAddr::Local;

1640 NumUnnamed++;

1641 Changed = true;

1642 }

1643 }

1644

1645

1647 return Changed;

1648

1649 auto *GVar = dyn_cast(&GV);

1650 if (!GVar)

1651 return Changed;

1652

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

1654 return Changed;

1655

1657 Changed;

1658}

1659

1660

1661

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

1664 if (isa(U))

1665 continue;

1667 }

1668}

1669

1672 unsigned AttrIndex;

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

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

1675 return Attrs;

1676}

1677

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

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

1681 if (isa(U))

1682 continue;

1683 CallBase *CB = cast(U);

1685 }

1686}

1687

1688

1689

1690

1691

1694

1695

1697 return false;

1698

1699 if (F->isVarArg())

1700 return false;

1701

1702

1703

1704

1705

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

1707 if (isa(U))

1708 continue;

1709 CallInst* CI = dyn_cast(U);

1710 if (!CI)

1711 continue;

1712

1714 return false;

1715 }

1716

1718 if (BB.getTerminatingMustTailCall())

1719 return false;

1720

1721 return F->hasAddressTaken();

1722}

1723

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

1728 if (Res.second)

1730 return Res.first->second;

1731}

1732

1733

1734

1737 auto *CallSiteBB = CB.getParent();

1738 auto CallSiteFreq = CallerBFI.getBlockFreq(CallSiteBB);

1739 auto CallerEntryFreq =

1741 return CallSiteFreq < CallerEntryFreq * ColdProb;

1742}

1743

1744

1745

1746

1747

1748static bool

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

1752

1753 if (F.user_empty())

1754 return false;

1755

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

1757 if (isa(U))

1758 continue;

1759

1760 CallBase &CB = cast(*U);

1764 return false;

1766 return false;

1767 }

1768 return true;

1769}

1770

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

1773 if (isa(U))

1774 continue;

1776 }

1777}

1778

1779

1780

1781

1782static bool

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

1789

1790 if (CI->isInlineAsm())

1791 continue;

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

1793 if (!CalledFn)

1794 return false;

1795

1796

1797

1798

1800 continue;

1802 return false;

1803

1805 return false;

1808 return false;

1809 }

1810 }

1811 }

1812 return true;

1813}

1814

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

1817 CallBase *CB = dyn_cast(U);

1818 if (!CB) {

1819 assert(isa(U) &&

1820 "Expected either CallBase or BlockAddress");

1821 continue;

1822 }

1824 return true;

1825 }

1826 return false;

1827}

1828

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

1831 if (isa(U))

1832 return true;

1833 return false;

1834}

1835

1838

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

1840

1842

1843

1845 for (User *U : PreallocatedCalls) {

1846 CallBase *CB = dyn_cast(U);

1847 if (!CB)

1848 continue;

1849

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

1853

1856 CallBase *PreallocatedSetup = nullptr;

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

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

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

1860 OpBundles.erase(It);

1861 break;

1862 }

1863 }

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

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

1867

1868 assert((isa(CB) || isa(CB)) &&

1869 "Unknown indirect call type");

1874

1879

1880

1881

1882

1883

1884

1885

1886

1889 for (auto *User : PreallocatedArgs) {

1890 auto *UseCall = cast(User);

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

1892 Intrinsic::call_preallocated_arg &&

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

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

1896 Value *AllocaReplacement = ArgAllocas[AllocArgIndex];

1897 if (!AllocaReplacement) {

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

1899 auto *ArgType =

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

1903 auto *Alloca =

1905 ArgAllocas[AllocArgIndex] = Alloca;

1906 AllocaReplacement = Alloca;

1907 }

1908

1910 UseCall->eraseFromParent();

1911 }

1912

1913 cast(PreallocatedSetup)->eraseFromParent();

1914 }

1915}

1916

1917static bool

1926

1927 bool Changed = false;

1928

1930 std::vector<Function *> AllCallsCold;

1933 AllCallsCold.push_back(&F);

1934

1935

1937

1938

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

1940 continue;

1941

1942

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

1945

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

1947 Changed = true;

1948 continue;

1949 }

1950

1951

1952

1953

1954

1955

1956

1957

1958

1959

1960 if (F.isDeclaration()) {

1962 Changed = true;

1963 ChangedCFGCallback(F);

1964 }

1965 }

1966

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

1968

1969 if (F.hasLocalLinkage())

1970 continue;

1971

1972

1973

1974

1975

1976

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

1980 Changed = true;

1981 }

1982

1983

1984

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

1989 Changed = true;

1990 }

1991 continue;

1992 }

1993

1995 NumInternalFunc++;

1997

1998

1999

2000

2004 ChangeableCCCache.erase(&F);

2007 Changed = true;

2008 NumColdCC++;

2009 }

2010 }

2011

2013

2014

2015

2018 ++NumFastCallFns;

2019 Changed = true;

2020 }

2021

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

2023 F.hasAddressTaken()) {

2024

2025

2027 ++NumNestRemoved;

2028 Changed = true;

2029 }

2030 }

2031 return Changed;

2032}

2033

2035 if (!CI)

2036 return false;

2037

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

2040 return false;

2041

2042 return true;

2043}

2044

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

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

2048

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

2050 return false;

2051

2052 if (!Alloca->isStaticAlloca())

2053 return false;

2054

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

2056 return false;

2057

2058 return true;

2059}

2060

2062 unsigned NumBytesToPad,

2063 unsigned NumBytesToCopy) {

2065 return nullptr;

2066

2068 dyn_cast(OldVar->getInitializer());

2069 if (!DataArray)

2070 return nullptr;

2071

2072

2073

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

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

2077 StrData.push_back('\0');

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

2079

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

2083 SourceReplace, SourceReplace->getName());

2084

2085

2088 return NewGV;

2089}

2090

2092 const unsigned NumBytesToCopy,

2094

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

2096 if (Alloca) {

2098 unsigned int TotalBytes = NumBytesToCopy + NumBytesToPad;

2099 unsigned NumElementsToCopy = divideCeil(TotalBytes, ElementByteWidth);

2100

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

2104 NewAlloca->takeName(Alloca);

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

2106 Alloca->replaceAllUsesWith(NewAlloca);

2107 Alloca->eraseFromParent();

2108 }

2109}

2110

2112 const unsigned NumBytesToPad,

2113 const unsigned NumBytesToCopy,

2116 auto *NewSourceGV =

2118 if (!NewSourceGV)

2119 return false;

2120

2121

2122

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

2124 auto *CI = dyn_cast(User);

2126 continue;

2127

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

2129 continue;

2130

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

2132

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

2134 NumBytesToCopy + NumBytesToPad));

2135 }

2137

2138 NumGlobalArraysPadded++;

2139 return true;

2140}

2141

2145

2148 return false;

2149

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

2153 continue;

2154

2156

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

2158 if (!BytesToCopyOp)

2159 continue;

2160

2163 if (!SourceDataArray)

2164 continue;

2165

2166 unsigned NumBytesToCopy = BytesToCopyOp->getZExtValue();

2167

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

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

2172

2173

2174

2175 unsigned NumElementsToCopy = divideCeil(NumBytesToCopy, ElementByteWidth);

2176

2177

2178

2179

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

2181 continue;

2182

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

2184 NumBytesToCopy, SourceDataArray->getType());

2185 if (NumBytesToPad) {

2187 BytesToCopyOp, SourceDataArray);

2188 }

2189 }

2190 return false;

2191}

2192

2193static bool

2199 bool Changed = false;

2200

2202

2205

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

2208 auto &DL = M.getDataLayout();

2209

2210

2211

2213 if (New != C)

2215 }

2216

2217 if (deleteIfDead(GV, NotDiscardableComdats)) {

2218 Changed = true;

2219 continue;

2220 }

2221

2222

2223

2225

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

2227 }

2228 return Changed;

2229}

2230

2231

2232

2235

2236 if (F->isDeclaration())

2237 return false;

2238

2243

2244 if (EvalSuccess) {

2245 ++NumCtorsEvaluated;

2246

2247

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

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

2251 << " stores.\n");

2252 for (const auto &Pair : NewInitializers)

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

2256 }

2257

2258 return EvalSuccess;

2259}

2260

2265}

2266

2269 if (Init.empty()) {

2270 V.eraseFromParent();

2271 return;

2272 }

2273

2274

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

2276 const auto *VAT = cast(UsedArrayType);

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

2278

2279

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

2282

2287 }

2288

2289

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

2292

2293 Module *M = V.getParent();

2294 V.removeFromParent();

2298 NV->takeName(&V);

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

2300 delete &V;

2301}

2302

2303namespace {

2304

2305

2306class LLVMUsed {

2311

2312public:

2313 LLVMUsed(Module &M) {

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

2320 }

2321

2324

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

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

2327

2328 used_iterator_range used() {

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

2330 }

2331

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

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

2334

2335 used_iterator_range compilerUsed() {

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

2337 }

2338

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

2340

2341 bool compilerUsedCount(GlobalValue *GV) const {

2342 return CompilerUsed.count(GV);

2343 }

2344

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

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

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

2348

2349 bool compilerUsedInsert(GlobalValue *GV) {

2350 return CompilerUsed.insert(GV).second;

2351 }

2352

2353 void syncVariablesAndSets() {

2354 if (UsedV)

2356 if (CompilerUsedV)

2358 }

2359};

2360

2361}

2362

2364 if (GA.use_empty())

2365 return false;

2366

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

2368 "We should have removed the duplicated "

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

2371

2372

2373 return true;

2374

2375

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

2377}

2378

2381 return true;

2382

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

2384}

2385

2387 bool &RenameTarget) {

2389 return false;

2390

2391 RenameTarget = false;

2392 bool Ret = false;

2394 Ret = true;

2395

2396

2398 return Ret;

2399

2400

2401

2402

2403

2404

2405

2406

2410 return Ret;

2411

2412 RenameTarget = true;

2413 return true;

2414}

2415

2416static bool

2419 bool Changed = false;

2420 LLVMUsed Used(M);

2421

2423 Used.compilerUsedErase(GV);

2424

2425

2426

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

2430 };

2431

2433

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

2436

2437 if (deleteIfDead(J, NotDiscardableComdats)) {

2438 Changed = true;

2439 continue;

2440 }

2441

2442

2443 if (!IsModuleLocal(J))

2444 continue;

2445

2446 Constant *Aliasee = J.getAliasee();

2448

2449

2450

2451

2452

2453

2455 continue;

2456

2457 Target->removeDeadConstantUsers();

2458

2459

2460 bool RenameTarget;

2462 continue;

2463

2464 J.replaceAllUsesWith(Aliasee);

2465 ++NumAliasesResolved;

2466 Changed = true;

2467

2468 if (RenameTarget) {

2469

2470 Target->takeName(&J);

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

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

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

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

2475

2476 if (Used.usedErase(&J))

2477 Used.usedInsert(Target);

2478

2479 if (Used.compilerUsedErase(&J))

2480 Used.compilerUsedInsert(Target);

2482 continue;

2483

2484

2485 M.eraseAlias(&J);

2486 ++NumAliasesRemoved;

2487 Changed = true;

2488 }

2489

2490 Used.syncVariablesAndSets();

2491

2492 return Changed;

2493}

2494

2499

2500 auto FuncIter = M.begin();

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

2502 return nullptr;

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

2504

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

2506 return nullptr;

2507

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

2509 if (!Fn)

2510 return nullptr;

2511

2512

2513 TLI = &GetTLI(*Fn);

2514

2515

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

2518 return nullptr;

2519

2520 return Fn;

2521}

2522

2523

2524

2525

2526

2528

2529

2531 return false;

2532

2534 if (I.isDebugOrPseudoInst())

2535 continue;

2536 if (isa(I))

2537 return true;

2538 break;

2539 }

2540 return false;

2541}

2542

2544

2545

2546

2547

2548

2549

2550

2551

2552

2553

2554

2555

2556

2557

2558 bool Changed = false;

2559

2561

2562

2563

2564 CallInst *CI = dyn_cast(U);

2565 if (!CI)

2566 continue;

2567

2571 continue;

2572

2573

2576

2577 if (isCXX)

2578 ++NumCXXDtorsRemoved;

2579 else

2580 ++NumAtExitRemoved;

2581

2582 Changed |= true;

2583 }

2584

2585 return Changed;

2586}

2587

2589 if (IF.isInterposable())

2590 return nullptr;

2591

2594 return nullptr;

2595

2596 if (Resolver->isInterposable())

2597 return nullptr;

2598

2599

2600 auto It = Resolver->begin();

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

2602 return nullptr;

2603

2605

2607 return nullptr;

2608

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

2610 if (!Ret)

2611 return nullptr;

2612

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

2614}

2615

2616

2617

2619 bool Changed = false;

2622 if (!IF.use_empty() &&

2623 (!Callee->isDeclaration() ||

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

2625 IF.replaceAllUsesWith(Callee);

2626 NumIFuncsResolved++;

2627 Changed = true;

2628 }

2629 return Changed;

2630}

2631

2632static bool

2635 bool Changed = false;

2637 if (deleteIfDead(IF, NotDiscardableComdats)) {

2638 NumIFuncsDeleted++;

2639 Changed = true;

2640 }

2641 return Changed;

2642}

2643

2644

2645

2646

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

2651 return false;

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

2655 return false;

2657 return false;

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

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

2661 return false;

2662 } else {

2663

2664 return false;

2665 }

2666 return true;

2667}

2668

2669

2670

2671

2672

2673

2674

2675

2676

2677

2678

2679

2680

2681

2682

2683

2684

2685

2688 bool Changed = false;

2689

2690

2692

2694 if (IF.isInterposable())

2695 continue;

2696

2699 continue;

2700

2701 if (Resolver->isInterposable())

2702 continue;

2703

2705

2706

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

2711 return true;

2712 return false;

2713 }))

2714 continue;

2715

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

2717

2718

2719 for (Function *Callee : Callees) {

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

2721 if (Inserted)

2723 }

2724

2725

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

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

2728 });

2729

2730

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

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

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

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

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

2738 if (FeatInserted)

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

2741 if (CallInserted)

2742 Callers.push_back(Caller);

2743 CallIt->second.push_back(CB);

2744 }

2745 }

2746 }

2747

2748

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

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

2751 });

2752

2754

2755

2756 unsigned I = 0;

2757

2758 for (Function *Caller : Callers) {

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

2760

2762 uint64_t CallerBits = FeatureMask[Caller];

2763 uint64_t CalleeBits = FeatureMask[Callee];

2764

2765

2766

2767

2768

2770

2771

2772

2773 if (CallerBits == CalleeBits)

2774 ++I;

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

2776

2777

2778 while (implies(CalleeBits, CallerBits)) {

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

2780 break;

2781 CalleeBits = FeatureMask[Callees[I]];

2782 }

2783 continue;

2784 }

2785 } else {

2786

2787

2788

2789

2790

2791

2792

2793

2794

2795

2796

2797 continue;

2798 }

2799 auto &Calls = CallSites[Caller];

2801 CS->setCalledOperand(Callee);

2802 Changed = true;

2803 }

2804 if (IF.use_empty() ||

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

2806 NumIFuncsResolved++;

2807 }

2808 return Changed;

2809}

2810

2811static bool

2820 bool Changed = false;

2821 bool LocalChange = true;

2822 std::optional<uint32_t> FirstNotFullyEvaluatedPriority;

2823

2824 while (LocalChange) {

2825 LocalChange = false;

2826

2827 NotDiscardableComdats.clear();

2831 NotDiscardableComdats.insert(C);

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

2834 if (F.isDefTriviallyDead())

2835 NotDiscardableComdats.insert(C);

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

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

2839 NotDiscardableComdats.insert(C);

2840

2841

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

2843 NotDiscardableComdats, ChangedCFGCallback,

2844 DeleteFnCallback);

2845

2846

2847 LocalChange |=

2849 if (FirstNotFullyEvaluatedPriority &&

2850 *FirstNotFullyEvaluatedPriority != Priority)

2851 return false;

2853 if (!Evaluated)

2854 FirstNotFullyEvaluatedPriority = Priority;

2855 return Evaluated;

2856 });

2857

2858

2860 NotDiscardableComdats);

2861

2862

2864

2865

2866

2870

2873

2874

2876

2877

2879

2880

2882

2883 Changed |= LocalChange;

2884 }

2885

2886

2887

2888

2889 return Changed;

2890}

2891

2893 auto &DL = M.getDataLayout();

2894 auto &FAM =

2898 };

2901 };

2904 };

2905

2908 };

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

2911 };

2913

2915 ChangedCFGCallback, DeleteFnCallback))

2917

2919

2921

2922

2923

2925 return PA;

2926}

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