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 (->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();
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)) {
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 ()
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 ->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 (.hasName() &&
.isDeclaration() &&
.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 (.isDeclaration()) {
1977 Changed = true;
1978 ChangedCFGCallback(F);
1979 }
1980 }
1981
1982 Changed |= processGlobal(F, GetTTI, GetTLI, LookupDomTree);
1983
1984 if (.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 .hasAddressTaken()) {
2039
2040
2042 ++NumNestRemoved;
2043 Changed = true;
2044 }
2045 }
2046 return Changed;
2047}
2048
2050 if (!CI)
2051 return false;
2052
2054 if ( ||
->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
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 (.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::...