LLVM: lib/Transforms/IPO/GlobalOpt.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
66#include
67#include
68#include
69#include
70#include
71
72using namespace llvm;
73
74#define DEBUG_TYPE "globalopt"
75
76STATISTIC(NumMarked , "Number of globals marked constant");
77STATISTIC(NumUnnamed , "Number of globals marked unnamed_addr");
78STATISTIC(NumSRA , "Number of aggregate globals broken into scalars");
79STATISTIC(NumSubstitute,"Number of globals with initializers stored into them");
80STATISTIC(NumDeleted , "Number of globals deleted");
81STATISTIC(NumGlobUses , "Number of global uses devirtualized");
82STATISTIC(NumLocalized , "Number of globals localized");
83STATISTIC(NumShrunkToBool , "Number of global vars shrunk to booleans");
84STATISTIC(NumFastCallFns , "Number of functions converted to fastcc");
85STATISTIC(NumCtorsEvaluated, "Number of static ctors evaluated");
86STATISTIC(NumNestRemoved , "Number of nest attributes removed");
87STATISTIC(NumAliasesResolved, "Number of global aliases resolved");
88STATISTIC(NumAliasesRemoved, "Number of global aliases eliminated");
89STATISTIC(NumCXXDtorsRemoved, "Number of global C++ destructors removed");
90STATISTIC(NumAtExitRemoved, "Number of atexit handlers removed");
91STATISTIC(NumInternalFunc, "Number of internal functions");
92STATISTIC(NumColdCC, "Number of functions marked coldcc");
93STATISTIC(NumIFuncsResolved, "Number of statically resolved IFuncs");
94STATISTIC(NumIFuncsDeleted, "Number of IFuncs removed");
96 "Number of global arrays padded to alignment boundary");
97
100 cl::desc("Statically resolve calls to versioned "
101 "functions from non-versioned callers."),
103
106 cl::desc("Enable stress test of coldcc by adding "
107 "calling conv to all internal functions."),
109
113 "Maximum block frequency, expressed as a percentage of caller's "
114 "entry frequency, for a call site to be considered cold for enabling "
115 "coldcc"));
116
117
118
120
121
122
123
124
125
126
127
129 return false;
130
133
134 unsigned Limit = 20;
135 do {
136 Type *Ty = Types.pop_back_val();
138 default: break;
140 return true;
143 if (cast(Ty)->getElementType()->isPointerTy())
144 return true;
145 break;
147 Types.push_back(cast(Ty)->getElementType());
148 break;
150 StructType *STy = cast(Ty);
151 if (STy->isOpaque()) return true;
153 if (isa(InnerTy)) return true;
154 if (isa(InnerTy) || isa(InnerTy) ||
155 isa(InnerTy))
156 Types.push_back(InnerTy);
157 }
158 break;
159 }
160 }
161 if (--Limit == 0) return true;
162 } while (!Types.empty());
163 return false;
164}
165
166
167
168
171 do {
172 if (isa(V))
173 return true;
174 if (!V->hasOneUse())
175 return false;
176 if (isa(V) || isa(V) || isa(V) ||
177 isa(V))
178 return false;
180 return true;
181
183 if (I->mayHaveSideEffects())
184 return false;
186 if (->hasAllConstantIndices())
187 return false;
188 } else if (I->getNumOperands() != 1) {
189 return false;
190 }
191
192 V = I->getOperand(0);
193 } while (true);
194}
195
196
197
198
199static bool
202
203
204
205
206
207
208
209
210
211 bool Changed = false;
212
213
214
216
218
219 while (!Worklist.empty()) {
221 if (StoreInst *SI = dyn_cast(U)) {
222 Value *V = SI->getValueOperand();
223 if (isa(V)) {
224 Changed = true;
225 SI->eraseFromParent();
226 } else if (Instruction *I = dyn_cast(V)) {
227 if (I->hasOneUse())
228 Dead.push_back(std::make_pair(I, SI));
229 }
230 } else if (MemSetInst *MSI = dyn_cast(U)) {
231 if (isa(MSI->getValue())) {
232 Changed = true;
233 MSI->eraseFromParent();
234 } else if (Instruction *I = dyn_cast(MSI->getValue())) {
235 if (I->hasOneUse())
236 Dead.push_back(std::make_pair(I, MSI));
237 }
238 } else if (MemTransferInst *MTI = dyn_cast(U)) {
239 GlobalVariable *MemSrc = dyn_cast(MTI->getSource());
240 if (MemSrc && MemSrc->isConstant()) {
241 Changed = true;
242 MTI->eraseFromParent();
243 } else if (Instruction *I = dyn_cast(MTI->getSource())) {
244 if (I->hasOneUse())
245 Dead.push_back(std::make_pair(I, MTI));
246 }
247 } else if (ConstantExpr *CE = dyn_cast(U)) {
248 if (isa(CE))
250 }
251 }
252
253 for (int i = 0, e = Dead.size(); i != e; ++i) {
255 Dead[i].second->eraseFromParent();
257 do {
259 break;
260 Instruction *J = dyn_cast(I->getOperand(0));
261 if (!J)
262 break;
263 I->eraseFromParent();
264 I = J;
265 } while (true);
266 I->eraseFromParent();
267 Changed = true;
268 }
269 }
270
272 return Changed;
273}
274
275
276
277
283 bool Changed = false;
284
287 for (Value *Op : I->operands())
288 if (auto *OpI = dyn_cast(Op))
290 I->eraseFromParent();
291 Changed = true;
292 };
293 while (!WorkList.empty()) {
295 if (!Visited.insert(U).second)
296 continue;
297
298 if (auto *BO = dyn_cast(U))
300 if (auto *ASC = dyn_cast(U))
302 else if (auto *GEP = dyn_cast(U))
304 else if (auto *LI = dyn_cast(U)) {
305
306
307 Type *Ty = LI->getType();
309 LI->replaceAllUsesWith(Res);
310 EraseFromParent(LI);
311 continue;
312 }
313
314 Value *PtrOp = LI->getPointerOperand();
318 if (IntrinsicInst *II = dyn_cast(PtrOp)) {
319 if (II->getIntrinsicID() == Intrinsic::threadlocal_address)
320 PtrOp = II->getArgOperand(0);
321 }
322 if (PtrOp == GV) {
324 LI->replaceAllUsesWith(Value);
325 EraseFromParent(LI);
326 }
327 }
328 } else if (StoreInst *SI = dyn_cast(U)) {
329
330 EraseFromParent(SI);
331 } else if (MemIntrinsic *MI = dyn_cast(U)) {
333 EraseFromParent(MI);
334 } else if (IntrinsicInst *II = dyn_cast(U)) {
335 if (II->getIntrinsicID() == Intrinsic::threadlocal_address)
337 }
338 }
339
340 Changed |=
343 return Changed;
344}
345
346
347
353};
354
355
356
361 auto AppendUses = [&](Value *V) {
362 for (Use &U : V->uses())
363 if (Visited.insert(&U).second)
365 };
366 AppendUses(GV);
367 while (!Worklist.empty()) {
369 User *V = U->getUser();
370
371 auto *GEP = dyn_cast(V);
372 if (isa(V) || isa(V) ||
373 (GEP && GEP->hasAllConstantIndices())) {
374 AppendUses(V);
375 continue;
376 }
377
379
380
381 if (isa(V) && U->getOperandNo() == 0)
382 return false;
383
385 Ptr = Ptr->stripAndAccumulateConstantOffsets(DL, Offset,
386 true);
387 if (Ptr != GV || Offset.getActiveBits() >= 64)
388 return false;
389
390
391
393 const auto &[It, Inserted] =
395 if (Ty != It->second.Ty)
396 return false;
397
398 if (Inserted) {
399 It->second.Initializer =
401 if (!It->second.Initializer) {
402 LLVM_DEBUG(dbgs() << "Global SRA: Failed to evaluate initializer of "
403 << *GV << " with type " << *Ty << " at offset "
404 << Offset.getZExtValue());
405 return false;
406 }
407 }
408
409
411 return false;
412
413 auto IsStored = [](Value *V, Constant *Initializer) {
414 auto *SI = dyn_cast(V);
415 if (!SI)
416 return false;
417
418 Constant *StoredConst = dyn_cast(SI->getOperand(0));
419 if (!StoredConst)
420 return true;
421
422
423 return Initializer != StoredConst;
424 };
425
426 It->second.IsLoaded |= isa(V);
427 It->second.IsStored |= IsStored(V, It->second.Initializer);
428 continue;
429 }
430
431
432 if (auto *C = dyn_cast(V)) {
434 return false;
435 continue;
436 }
437
438
439 return false;
440 }
441
442 return true;
443}
444
445
447 uint64_t FragmentOffsetInBits,
452 for (auto *GVE : GVs) {
453 DIVariable *Var = GVE->getVariable();
455 int64_t CurVarOffsetInBytes = 0;
456 uint64_t CurVarOffsetInBits = 0;
457 uint64_t FragmentEndInBits = FragmentOffsetInBits + FragmentSizeInBits;
458
459
461 continue;
462
463
464 if (CurVarOffsetInBytes < 0)
465 continue;
466
467
468 CurVarOffsetInBits = CHAR_BIT * (uint64_t)CurVarOffsetInBytes;
469
470
471 if (CurVarOffsetInBits >= FragmentEndInBits)
472 continue;
473
475 uint64_t CurVarEndInBits = CurVarOffsetInBits + CurVarSize;
476
477 if (CurVarSize != 0 &&
478 CurVarEndInBits <= FragmentOffsetInBits)
479 continue;
480
481
482
483 if (CurVarSize != 0 &&
484 CurVarOffsetInBits >= FragmentOffsetInBits &&
485 CurVarEndInBits <= FragmentEndInBits) {
486 uint64_t CurVarOffsetInFragment =
487 (CurVarOffsetInBits - FragmentOffsetInBits) / 8;
488 if (CurVarOffsetInFragment != 0)
489 Expr = DIExpression::get(Expr->getContext(), {dwarf::DW_OP_plus_uconst,
490 CurVarOffsetInFragment});
491 else
492 Expr = DIExpression::get(Expr->getContext(), {});
493 auto *NGVE =
494 DIGlobalVariableExpression::get(GVE->getContext(), Var, Expr);
496 continue;
497 }
498
499
500 if (FragmentSizeInBits < VarSize) {
501 if (CurVarOffsetInBits > FragmentOffsetInBits)
502 continue;
503 uint64_t CurVarFragmentOffsetInBits =
504 FragmentOffsetInBits - CurVarOffsetInBits;
505 uint64_t CurVarFragmentSizeInBits = FragmentSizeInBits;
506 if (CurVarSize != 0 && CurVarEndInBits < FragmentEndInBits)
507 CurVarFragmentSizeInBits -= (FragmentEndInBits - CurVarEndInBits);
508 if (CurVarOffsetInBits)
509 Expr = DIExpression::get(Expr->getContext(), {});
511 Expr, CurVarFragmentOffsetInBits, CurVarFragmentSizeInBits))
512 Expr = *E;
513 else
514 continue;
515 }
516 auto *NGVE = DIGlobalVariableExpression::get(GVE->getContext(), Var, Expr);
518 }
519}
520
521
522
523
524
525
528
529
532 return nullptr;
533
534
536 return nullptr;
537
538
539
540
541 unsigned NumParts = count_if(Parts, [](const auto &Pair) {
542 return Pair.second.IsLoaded && Pair.second.IsStored;
543 });
544 if (NumParts > 16)
545 return nullptr;
546
547
549 for (const auto &Pair : Parts) {
551 {Pair.first, Pair.second.Ty, Pair.second.Initializer});
552 }
554
555
557 for (const auto &[OffsetForTy, Ty, _] : TypesVector) {
558
559 if (OffsetForTy < Offset)
560 return nullptr;
561
562 Offset = OffsetForTy + DL.getTypeAllocSize(Ty);
563 }
564
565
567 return nullptr;
568
569 LLVM_DEBUG(dbgs() << "PERFORMING GLOBAL SRA ON: " << *GV << "\n");
570
571
572 Align StartAlignment =
575
576
578 unsigned NameSuffix = 0;
579 for (auto &[OffsetForTy, Ty, Initializer] : TypesVector) {
581 *GV->getParent(), Ty, false, GlobalVariable::InternalLinkage,
582 Initializer, GV->getName() + "." + Twine(NameSuffix++), GV,
584
586 NewGlobals.insert({OffsetForTy, NGV});
587
588
589
590
591
594
595
597 DL.getTypeAllocSizeInBits(Ty), VarSize);
598 }
599
600
604 auto AppendUsers = [&](Value *V) {
605 for (User *U : V->users())
606 if (Visited.insert(U).second)
608 };
609 AppendUsers(GV);
610 while (!Worklist.empty()) {
612 if (isa(V) || isa(V) ||
613 isa(V)) {
614 AppendUsers(V);
615 if (isa(V))
617 continue;
618 }
619
622 Ptr = Ptr->stripAndAccumulateConstantOffsets(DL, Offset,
623 true);
624 assert(Ptr == GV && "Load/store must be from/to global");
626 assert(NGV && "Must have replacement global for this offset");
627
628
632
633 if (auto *LI = dyn_cast(V)) {
634 LI->setOperand(0, NGV);
635 LI->setAlignment(NewAlign);
636 } else {
637 auto *SI = cast(V);
638 SI->setOperand(1, NGV);
639 SI->setAlignment(NewAlign);
640 }
641 continue;
642 }
643
645 "Other users can only be dead constants");
646 }
647
648
652 ++NumSRA;
653
655 return NewGlobals.begin()->second;
656}
657
658
659
660
663 for (const User *U : V->users()) {
664 if (const Instruction *I = dyn_cast(U)) {
665
666
668 return false;
669 }
670 if (isa(U)) {
671
672 } else if (const StoreInst *SI = dyn_cast(U)) {
673 if (SI->getOperand(0) == V) {
674 return false;
675 }
676 } else if (const CallInst *CI = dyn_cast(U)) {
677 if (CI->getCalledOperand() != V) {
678 return false;
679 }
680 } else if (const InvokeInst *II = dyn_cast(U)) {
681 if (II->getCalledOperand() != V) {
682 return false;
683 }
684 } else if (const AddrSpaceCastInst *CI = dyn_cast(U)) {
686 return false;
687 } else if (const GetElementPtrInst *GEPI = dyn_cast(U)) {
689 } else if (const PHINode *PN = dyn_cast(U)) {
690
691
693 return false;
694 } else if (isa(U) &&
695 !ICmpInst::isSigned(cast(U)->getPredicate()) &&
696 isa(U->getOperand(0)) &&
697 isa(U->getOperand(1))) {
698 assert(isa(cast(U->getOperand(0))
699 ->getPointerOperand()
700 ->stripPointerCasts()) &&
701 "Should be GlobalVariable");
702
703
704
705 } else {
706 return false;
707 }
708 }
709 return true;
710}
711
712
713
714
718 while (!Worklist.empty()) {
720 for (const auto *U : P->users()) {
721 if (auto *LI = dyn_cast(U)) {
724 return false;
725 } else if (auto *SI = dyn_cast(U)) {
726
727 if (SI->getPointerOperand() != P)
728 return false;
729 } else if (auto *CE = dyn_cast(U)) {
730 if (CE->stripPointerCasts() != GV)
731 return false;
732
734 } else {
735
736 return false;
737 }
738 }
739 }
740
741 return true;
742}
743
744
749 while (!Worklist.empty()) {
751 for (auto *U : P->users()) {
752 if (auto *CE = dyn_cast(U)) {
754 continue;
755 }
756
757 assert((isa(U) || isa(U)) &&
758 "Expect only load or store instructions");
759 Uses.push_back(U);
760 }
761 }
762}
763
765 bool Changed = false;
766 for (auto UI = V->user_begin(), E = V->user_end(); UI != E; ) {
768
769
771 return false;
772 if (LoadInst *LI = dyn_cast(I)) {
773 LI->setOperand(0, NewV);
774 Changed = true;
775 } else if (StoreInst *SI = dyn_cast(I)) {
776 if (SI->getOperand(1) == V) {
777 SI->setOperand(1, NewV);
778 Changed = true;
779 }
780 } else if (isa(I) || isa(I)) {
783
784
786 Changed = true;
787 bool PassedAsArg = false;
788 for (unsigned i = 0, e = CB->arg_size(); i != e; ++i)
790 PassedAsArg = true;
792 }
793
794 if (PassedAsArg) {
795
796 UI = V->user_begin();
797 }
798 }
802 if (CI->use_empty()) {
803 Changed = true;
804 CI->eraseFromParent();
805 }
806 } else if (GetElementPtrInst *GEPI = dyn_cast(I)) {
807
809 Idxs.reserve(GEPI->getNumOperands()-1);
810 for (User::op_iterator i = GEPI->op_begin() + 1, e = GEPI->op_end();
811 i != e; ++i)
812 if (Constant *C = dyn_cast(*i))
814 else
815 break;
816 if (Idxs.size() == GEPI->getNumOperands()-1)
819 NewV, Idxs));
820 if (GEPI->use_empty()) {
821 Changed = true;
822 GEPI->eraseFromParent();
823 }
824 }
825 }
826
827 return Changed;
828}
829
830
831
832
833
837 bool Changed = false;
838
839
840
841 bool AllNonStoreUsesGone = true;
842
843
845 if (LoadInst *LI = dyn_cast(GlobalUser)) {
847
848 if (LI->use_empty()) {
849 LI->eraseFromParent();
850 Changed = true;
851 } else {
852 AllNonStoreUsesGone = false;
853 }
854 } else if (isa(GlobalUser)) {
855
856 assert(GlobalUser->getOperand(1) == GV &&
857 "Must be storing *to* the global");
858 } else {
859 AllNonStoreUsesGone = false;
860
861
862
863 assert((isa(GlobalUser) || isa(GlobalUser) ||
864 isa(GlobalUser) || isa(GlobalUser) ||
865 isa(GlobalUser) ||
866 isa(GlobalUser) ||
867 isa(GlobalUser)) &&
868 "Only expect load and stores!");
869 }
870 }
871
872 if (Changed) {
873 LLVM_DEBUG(dbgs() << "OPTIMIZED LOADS FROM STORED ONCE POINTER: " << *GV
874 << "\n");
875 ++NumGlobUses;
876 }
877
878
879
880 if (AllNonStoreUsesGone) {
883 } else {
884 Changed = true;
886 }
889 Changed = true;
891 ++NumDeleted;
892 }
893 }
894 return Changed;
895}
896
897
898
901 for (Value::user_iterator UI = V->user_begin(), E = V->user_end(); UI != E; )
902 if (Instruction *I = dyn_cast(*UI++))
904 I->replaceAllUsesWith(NewC);
905
906
907
908 while (UI != E && *UI == I)
909 ++UI;
911 I->eraseFromParent();
912 }
913}
914
915
916
917
918
919
925 LLVM_DEBUG(errs() << "PROMOTING GLOBAL: " << *GV << " CALL = " << *CI
926 << '\n');
927
928
930 AllocSize);
931
932
933
938
939
940
941
942
943
944 if (!isa(InitVal)) {
946
947 Builder.CreateMemSet(NewGV, InitVal, AllocSize, std::nullopt);
948 }
949
950
952
953
954
959 bool InitBoolUsed = false;
960
961
964 for (auto *U : Guses) {
965 if (StoreInst *SI = dyn_cast(U)) {
966
967
970 !isa(SI->getValueOperand())),
971 InitBool, false, Align(1), SI->getOrdering(),
972 SI->getSyncScopeID(), SI->getIterator());
973 SI->eraseFromParent();
974 continue;
975 }
976
977 LoadInst *LI = cast(U);
981 if (!ICI) {
982 LoadUse.set(NewGV);
983 continue;
984 }
985
986
988 InitBool->getName() + ".val", false, Align(1),
991 InitBoolUsed = true;
994 case ICmpInst::ICMP_ULT:
996 break;
997 case ICmpInst::ICMP_UGE:
999 break;
1000 case ICmpInst::ICMP_ULE:
1001 case ICmpInst::ICMP_EQ:
1003 break;
1004 case ICmpInst::ICMP_NE:
1005 case ICmpInst::ICMP_UGT:
1006 break;
1007 }
1010 }
1012 }
1013
1014
1015 if (!InitBoolUsed) {
1016 while (!InitBool->use_empty())
1017 cast(InitBool->user_back())->eraseFromParent();
1018 delete InitBool;
1019 } else
1021
1022
1025
1026
1027
1028
1030
1031 return NewGV;
1032}
1033
1034
1035
1036
1037static bool
1043
1044 while (!Worklist.empty()) {
1046 if (!Visited.insert(V).second)
1047 continue;
1048
1049 for (const Use &VUse : V->uses()) {
1050 const User *U = VUse.getUser();
1051 if (isa(U) || isa(U))
1052 continue;
1053
1054 if (auto *SI = dyn_cast(U)) {
1055 if (SI->getValueOperand() == V &&
1056 SI->getPointerOperand()->stripPointerCasts() != GV)
1057 return false;
1058 continue;
1059 }
1060
1061 if (auto *GEPI = dyn_cast(U)) {
1063 continue;
1064 }
1065
1066 return false;
1067 }
1068 }
1069
1070 return true;
1071}
1072
1073
1074
1075
1076
1082
1083 return false;
1084
1087 if (!InitVal)
1088
1089 return false;
1090
1093 return false;
1094
1095
1096
1097
1098 if (AllocSize >= 2048)
1099 return false;
1100
1101
1102
1103
1104
1105
1106
1108 return false;
1109
1110
1111
1112
1113
1115 return false;
1116
1118 return true;
1119}
1120
1121
1122
1123static bool
1127
1129
1130
1131
1132
1133
1138 nullptr ,
1140 if (Constant *SOVC = dyn_cast(StoredOnceVal)) {
1141
1143 return true;
1145 if (auto *CI = dyn_cast(StoredOnceVal)) {
1146 auto *TLI = &GetTLI(*CI->getFunction());
1148 return true;
1149 }
1150 }
1151 }
1152
1153 return false;
1154}
1155
1156
1157
1158
1159
1162
1163
1164
1165
1166
1167
1171 return false;
1172
1173
1174
1176 if (!isa(U) && !isa(U))
1177 return false;
1179 return false;
1180 }
1181
1182 LLVM_DEBUG(dbgs() << " *** SHRINKING TO BOOL: " << *GV << "\n");
1183
1184
1186 false,
1194
1197 "No reason to shrink to bool!");
1198
1201
1202
1203
1204 bool IsOneZero = false;
1205 bool EmitOneOrZero = true;
1206 auto *CI = dyn_cast(OtherVal);
1207 if (CI && CI->getValue().getActiveBits() <= 64) {
1208 IsOneZero = InitVal->isNullValue() && CI->isOne();
1209
1210 auto *CIInit = dyn_cast(GV->getInitializer());
1211 if (CIInit && CIInit->getValue().getActiveBits() <= 64) {
1212 uint64_t ValInit = CIInit->getZExtValue();
1213 uint64_t ValOther = CI->getZExtValue();
1214 uint64_t ValMinus = ValOther - ValInit;
1215
1216 for(auto *GVe : GVs){
1220 unsigned SizeInOctets =
1221 DL.getTypeAllocSizeInBits(NewGV->getValueType()) / 8;
1222
1223
1224
1225
1226
1227
1228
1229
1230
1232 dwarf::DW_OP_deref_size, SizeInOctets,
1233 dwarf::DW_OP_constu, ValMinus,
1234 dwarf::DW_OP_mul, dwarf::DW_OP_constu, ValInit,
1235 dwarf::DW_OP_plus};
1236 bool WithStackValue = true;
1239 DIGlobalVariableExpression::get(NewGV->getContext(), DGV, E);
1241 }
1242 EmitOneOrZero = false;
1243 }
1244 }
1245
1246 if (EmitOneOrZero) {
1247
1248
1249 for(auto *GV : GVs)
1251 }
1252
1255 if (StoreInst *SI = dyn_cast(UI)) {
1256
1257 bool StoringOther = SI->getOperand(0) == OtherVal;
1258
1259 Value *StoreVal;
1260 if (StoringOther || SI->getOperand(0) == InitVal) {
1262 StoringOther);
1263 } else {
1264
1265
1266
1267 Instruction *StoredVal = cast(SI->getOperand(0));
1268
1269
1270
1271
1272 if (LoadInst *LI = dyn_cast(StoredVal)) {
1273 assert(LI->getOperand(0) == GV && "Not a copy!");
1274
1275 StoreVal =
1277 false, Align(1), LI->getOrdering(),
1278 LI->getSyncScopeID(), LI->getIterator());
1279 } else {
1280 assert((isa(StoredVal) || isa(StoredVal)) &&
1281 "This is not a form that we understand!");
1282 StoreVal = StoredVal->getOperand(0);
1283 assert(isa(StoreVal) && "Not a load of NewGV!");
1284 }
1285 }
1287 new StoreInst(StoreVal, NewGV, false, Align(1), SI->getOrdering(),
1288 SI->getSyncScopeID(), SI->getIterator());
1290 } else {
1291
1292 LoadInst *LI = cast(UI);
1297 if (IsOneZero)
1299 else
1302
1303
1307 }
1309 }
1310
1311
1312
1315 return true;
1316}
1317
1318static bool
1323
1325 return false;
1326
1329 return false;
1330
1331 bool Dead;
1332 if (auto *F = dyn_cast(&GV))
1333 Dead = (F->isDeclaration() && F->use_empty()) || F->isDefTriviallyDead();
1334 else
1336 if (!Dead)
1337 return false;
1338
1339 LLVM_DEBUG(dbgs() << "GLOBAL DEAD: " << GV << "\n");
1340 if (auto *F = dyn_cast(&GV)) {
1341 if (DeleteFnCallback)
1342 DeleteFnCallback(*F);
1343 }
1346 ++NumDeleted;
1347 return true;
1348}
1349
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1366 for (auto *U : GV->users()) {
1368 if ()
1369 return false;
1370 assert(I->getParent()->getParent() == F);
1371
1372 if (auto *LI = dyn_cast(I))
1374 else if (auto *SI = dyn_cast(I))
1376 else
1377 return false;
1378 }
1379
1380
1381
1382
1383
1384 auto &DT = LookupDomTree(*const_cast<Function *>(F));
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395 const unsigned Threshold = 100;
1396 if (Loads.size() * Stores.size() > Threshold)
1397 return false;
1398
1399 for (auto *L : Loads) {
1400 auto *LTy = L->getType();
1403
1404
1405
1407 DL.getTypeStoreSize(LTy).getFixedValue() <=
1408 DL.getTypeStoreSize(STy).getFixedValue();
1409 }))
1410 return false;
1411 }
1412
1413 return true;
1414}
1415
1416
1417
1418
1423
1424
1425
1426 if (!isa(StoredOnceValue))
1427 return false;
1431 if (auto *LI = dyn_cast(U)) {
1432 if (LI->getFunction() == F &&
1433 LI->getType() == StoredOnceValue->getType() && LI->isSimple())
1435 }
1436 }
1437
1438 bool MadeChange = false;
1439 if (!Loads.empty()) {
1440 auto &DT = LookupDomTree(*const_cast<Function *>(F));
1441 for (auto *LI : Loads) {
1442 if (DT.dominates(StoredOnceStore, LI)) {
1443 LI->replaceAllUsesWith(const_cast<Value *>(StoredOnceValue));
1444 LI->eraseFromParent();
1445 MadeChange = true;
1446 }
1447 }
1448 }
1449 return MadeChange;
1450}
1451
1452
1453
1454static bool
1460
1461
1462
1463
1464
1465
1466
1467
1468 if (!GS.HasMultipleAccessingFunctions &&
1469 GS.AccessingFunction &&
1473 GS.AccessingFunction->doesNotRecurse() &&
1475 LookupDomTree)) {
1477
1478 LLVM_DEBUG(dbgs() << "LOCALIZING GLOBAL: " << *GV << "\n");
1480 GS.AccessingFunction->getEntryBlock().begin().getNonConst();
1482
1484 nullptr, GV->getName(), FirstI);
1487
1490 ++NumLocalized;
1491 return true;
1492 }
1493
1494 bool Changed = false;
1495
1496
1497
1498 if (!GS.IsLoaded) {
1499 LLVM_DEBUG(dbgs() << "GLOBAL NEVER LOADED: " << *GV << "\n");
1500
1502
1504 } else {
1505
1506
1508 }
1509
1510
1513 ++NumDeleted;
1514 Changed = true;
1515 }
1516 return Changed;
1517
1518 }
1520 LLVM_DEBUG(dbgs() << "MARKING CONSTANT: " << *GV << "\n");
1521
1522
1523
1524
1525 if (GS.Ordering == AtomicOrdering::NotAtomic) {
1526 assert(!GV->isConstant() && "Expected a non-constant global");
1528 Changed = true;
1529 }
1530
1531
1533
1534
1536 LLVM_DEBUG(dbgs() << " *** Marking constant allowed us to simplify "
1537 << "all users and delete global!\n");
1539 ++NumDeleted;
1540 return true;
1541 }
1542
1543
1544 ++NumMarked;
1545 }
1549 return true;
1550 }
1551 Value *StoredOnceValue = GS.getStoredOnceValue();
1554 const_cast<Function &>(*GS.StoredOnceStore->getFunction());
1555 bool CanHaveNonUndefGlobalInitializer =
1556 GetTTI(StoreFn).canHaveNonUndefGlobalInitializerInAddressSpace(
1558
1559
1560
1561
1562
1563
1564
1565 auto *SOVConstant = dyn_cast(StoredOnceValue);
1566 if (SOVConstant && isa(GV->getInitializer()) &&
1567 DL.getTypeAllocSize(SOVConstant->getType()) ==
1569 CanHaveNonUndefGlobalInitializer) {
1570 if (SOVConstant->getType() == GV->getValueType()) {
1571
1573 } else {
1574
1579 NGV->takeName(GV);
1580 NGV->copyAttributesFrom(GV);
1583 GV = NGV;
1584 }
1585
1586
1588
1590 LLVM_DEBUG(dbgs() << " *** Substituting initializer allowed us to "
1591 << "simplify all users and delete global!\n");
1593 ++NumDeleted;
1594 }
1595 ++NumSubstitute;
1596 return true;
1597 }
1598
1599
1600
1602 return true;
1603
1604
1605
1606 if (GS.NumStores == 1)
1608 return true;
1609
1610
1611
1612 if (SOVConstant && GS.Ordering == AtomicOrdering::NotAtomic &&
1614 CanHaveNonUndefGlobalInitializer)) {
1616 ++NumShrunkToBool;
1617 return true;
1618 }
1619 }
1620 }
1621
1622 return Changed;
1623}
1624
1625
1626
1627static bool
1633 return false;
1634
1636
1638 return false;
1639
1640 bool Changed = false;
1642 auto NewUnnamedAddr = GV.hasLocalLinkage() ? GlobalValue::UnnamedAddr::Global
1643 : GlobalValue::UnnamedAddr::Local;
1646 NumUnnamed++;
1647 Changed = true;
1648 }
1649 }
1650
1651
1653 return Changed;
1654
1655 auto *GVar = dyn_cast(&GV);
1656 if (!GVar)
1657 return Changed;
1658
1659 if (GVar->isConstant() || !GVar->hasInitializer())
1660 return Changed;
1661
1663 Changed;
1664}
1665
1666
1667
1669 for (User *U : F->users()) {
1670 if (isa(U))
1671 continue;
1673 }
1674}
1675
1678 unsigned AttrIndex;
1679 if (Attrs.hasAttrSomewhere(A, &AttrIndex))
1680 return Attrs.removeAttributeAtIndex(C, AttrIndex, A);
1681 return Attrs;
1682}
1683
1685 F->setAttributes(StripAttr(F->getContext(), F->getAttributes(), A));
1686 for (User *U : F->users()) {
1687 if (isa(U))
1688 continue;
1689 CallBase *CB = cast(U);
1691 }
1692}
1693
1694
1695
1696
1697
1700
1701
1703 return false;
1704
1705 if (F->isVarArg())
1706 return false;
1707
1708
1709
1710
1711
1712 for (User *U : F->users()) {
1713 if (isa(U))
1714 continue;
1715 CallInst* CI = dyn_cast(U);
1716 if (!CI)
1717 continue;
1718
1720 return false;
1721 }
1722
1724 if (BB.getTerminatingMustTailCall())
1725 return false;
1726
1727 return ->hasAddressTaken();
1728}
1729
1733 auto Res = ChangeableCCCache.try_emplace(F, false);
1734 if (Res.second)
1736 return Res.first->second;
1737}
1738
1739
1740
1743 auto *CallSiteBB = CB.getParent();
1744 auto CallSiteFreq = CallerBFI.getBlockFreq(CallSiteBB);
1745 auto CallerEntryFreq =
1747 return CallSiteFreq < CallerEntryFreq * ColdProb;
1748}
1749
1750
1751
1752
1753
1754static bool
1757 const std::vector<Function *> &AllCallsCold) {
1758
1759 if (F.user_empty())
1760 return false;
1761
1762 for (User *U : F.users()) {
1763 if (isa(U))
1764 continue;
1765
1766 CallBase &CB = cast(*U);
1770 return false;
1772 return false;
1773 }
1774 return true;
1775}
1776
1778 for (User *U : F->users()) {
1779 if (isa(U))
1780 continue;
1782 }
1783}
1784
1785
1786
1787
1788static bool
1794 if (CallInst *CI = dyn_cast(&I)) {
1795
1796 if (CI->isInlineAsm())
1797 continue;
1798 Function *CalledFn = CI->getCalledFunction();
1799 if (!CalledFn)
1800 return false;
1801
1802
1803
1804
1806 continue;
1808 return false;
1809
1811 return false;
1814 return false;
1815 }
1816 }
1817 }
1818 return true;
1819}
1820
1822 for (User *U : F->users()) {
1823 CallBase *CB = dyn_cast(U);
1824 if (!CB) {
1825 assert(isa(U) &&
1826 "Expected either CallBase or BlockAddress");
1827 continue;
1828 }
1830 return true;
1831 }
1832 return false;
1833}
1834
1836 for (User *U : F->users())
1837 if (isa(U))
1838 return true;
1839 return false;
1840}
1841
1844
1845 auto *M = F->getParent();
1846
1848
1849
1851 for (User *U : PreallocatedCalls) {
1852 CallBase *CB = dyn_cast(U);
1853 if (!CB)
1854 continue;
1855
1858 "Shouldn't call RemotePreallocated() on a musttail preallocated call");
1859
1862 CallBase *PreallocatedSetup = nullptr;
1863 for (auto *It = OpBundles.begin(); It != OpBundles.end(); ++It) {
1864 if (It->getTag() == "preallocated") {
1865 PreallocatedSetup = cast(*It->input_begin());
1866 OpBundles.erase(It);
1867 break;
1868 }
1869 }
1870 assert(PreallocatedSetup && "Did not find preallocated bundle");
1872 cast(PreallocatedSetup->getArgOperand(0))->getZExtValue();
1873
1874 assert((isa(CB) || isa(CB)) &&
1875 "Unknown indirect call type");
1880
1885
1886
1887
1888
1889
1890
1891
1892
1895 for (auto *User : PreallocatedArgs) {
1896 auto *UseCall = cast(User);
1897 assert(UseCall->getCalledFunction()->getIntrinsicID() ==
1898 Intrinsic::call_preallocated_arg &&
1899 "preallocated token use was not a llvm.call.preallocated.arg");
1901 cast(UseCall->getArgOperand(1))->getZExtValue();
1902 Value *AllocaReplacement = ArgAllocas[AllocArgIndex];
1903 if (!AllocaReplacement) {
1904 auto AddressSpace = UseCall->getType()->getPointerAddressSpace();
1905 auto *ArgType =
1906 UseCall->getFnAttr(Attribute::Preallocated).getValueAsType();
1909 auto *Alloca =
1911 ArgAllocas[AllocArgIndex] = Alloca;
1912 AllocaReplacement = Alloca;
1913 }
1914
1916 UseCall->eraseFromParent();
1917 }
1918
1919 cast(PreallocatedSetup)->eraseFromParent();
1920 }
1921}
1922
1923static bool
1932
1933 bool Changed = false;
1934
1936 std::vector<Function *> AllCallsCold;
1939 AllCallsCold.push_back(&F);
1940
1941
1943
1944
1945 if (F.hasFnAttribute(Attribute::Naked))
1946 continue;
1947
1948
1949 if (.hasName() &&
.isDeclaration() &&
.hasLocalLinkage())
1951
1952 if (deleteIfDead(F, NotDiscardableComdats, DeleteFnCallback)) {
1953 Changed = true;
1954 continue;
1955 }
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966 if (.isDeclaration()) {
1968 Changed = true;
1969 ChangedCFGCallback(F);
1970 }
1971 }
1972
1973 Changed |= processGlobal(F, GetTTI, GetTLI, LookupDomTree);
1974
1975 if (.hasLocalLinkage())
1976 continue;
1977
1978
1979
1980
1981
1982
1983 if (F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) &&
1986 Changed = true;
1987 }
1988
1989
1990
1991 if (F.getAttributes().hasAttrSomewhere(Attribute::Preallocated)) {
1995 Changed = true;
1996 }
1997 continue;
1998 }
1999
2001 NumInternalFunc++;
2003
2004
2005
2006
2010 ChangeableCCCache.erase(&F);
2013 Changed = true;
2014 NumColdCC++;
2015 }
2016 }
2017
2019
2020
2021
2024 ++NumFastCallFns;
2025 Changed = true;
2026 }
2027
2028 if (F.getAttributes().hasAttrSomewhere(Attribute::Nest) &&
2029 .hasAddressTaken()) {
2030
2031
2033 ++NumNestRemoved;
2034 Changed = true;
2035 }
2036 }
2037 return Changed;
2038}
2039
2041 if (!CI)
2042 return false;
2043
2045 if ( ||
->isIntrinsic() || F->getIntrinsicID() != Intrinsic::memcpy)
2046 return false;
2047
2048 return true;
2049}
2050
2052 auto *IsVolatile = dyn_cast(CI->getArgOperand(3));
2053 auto *Alloca = dyn_cast(CI->getArgOperand(0));
2054
2055 if (!Alloca || !IsVolatile || IsVolatile->isOne())
2056 return false;
2057
2058 if (!Alloca->isStaticAlloca())
2059 return false;
2060
2061 if (!Alloca->getAllocatedType()->isArrayTy())
2062 return false;
2063
2064 return true;
2065}
2066
2068 unsigned NumBytesToPad,
2069 unsigned NumBytesToCopy) {
2071 return nullptr;
2072
2074 dyn_cast(OldVar->getInitializer());
2075 if (!DataArray)
2076 return nullptr;
2077
2078
2079
2081 std::vector<uint8_t> StrData(Data.begin(), Data.end());
2082 for (unsigned int p = 0; p < NumBytesToPad; p++)
2083 StrData.push_back('\0');
2084 auto Arr = ArrayRef(StrData.data(), NumBytesToCopy + NumBytesToPad);
2085
2088 *(F->getParent()), SourceReplace->getType(), true, OldVar->getLinkage(),
2089 SourceReplace, SourceReplace->getName());
2090
2091
2094 return NewGV;
2095}
2096
2098 const unsigned NumBytesToCopy,
2100
2101 auto *Alloca = dyn_cast(CI->getArgOperand(0));
2102 if (Alloca) {
2104 unsigned int TotalBytes = NumBytesToCopy + NumBytesToPad;
2105 unsigned NumElementsToCopy = divideCeil(TotalBytes, ElementByteWidth);
2106
2109 Alloca->getAllocatedType()->getArrayElementType(), NumElementsToCopy));
2110 NewAlloca->takeName(Alloca);
2111 NewAlloca->setAlignment(Alloca->getAlign());
2112 Alloca->replaceAllUsesWith(NewAlloca);
2113 Alloca->eraseFromParent();
2114 }
2115}
2116
2118 const unsigned NumBytesToPad,
2119 const unsigned NumBytesToCopy,
2122 auto *NewSourceGV =
2124 if (!NewSourceGV)
2125 return false;
2126
2127
2128
2129 for (auto *User : SourceVar->users()) {
2130 auto *CI = dyn_cast(User);
2132 continue;
2133
2134 if (CI->getArgOperand(1) != SourceVar)
2135 continue;
2136
2137 widenDestArray(CI, NumBytesToPad, NumBytesToCopy, SourceDataArray);
2138
2139 CI->setArgOperand(2, ConstantInt::get(BytesToCopyOp->getType(),
2140 NumBytesToCopy + NumBytesToPad));
2141 }
2143
2144 NumGlobalArraysPadded++;
2145 return true;
2146}
2147
2151
2154 return false;
2155
2156 for (auto *User : GV->users()) {
2159 continue;
2160
2162
2163 auto *BytesToCopyOp = dyn_cast(CI->getArgOperand(2));
2164 if (!BytesToCopyOp)
2165 continue;
2166
2169 if (!SourceDataArray)
2170 continue;
2171
2172 unsigned NumBytesToCopy = BytesToCopyOp->getZExtValue();
2173
2174 auto *Alloca = dyn_cast(CI->getArgOperand(0));
2175 uint64_t DZSize = Alloca->getAllocatedType()->getArrayNumElements();
2178
2179
2180
2181 unsigned NumElementsToCopy = divideCeil(NumBytesToCopy, ElementByteWidth);
2182
2183
2184
2185
2186 if (NumElementsToCopy != DZSize || DZSize != SZSize)
2187 continue;
2188
2189 unsigned NumBytesToPad = GetTTI(*F).getNumBytesToPadGlobalArray(
2190 NumBytesToCopy, SourceDataArray->getType());
2191 if (NumBytesToPad) {
2193 BytesToCopyOp, SourceDataArray);
2194 }
2195 }
2196 return false;
2197}
2198
2199static bool
2205 bool Changed = false;
2206
2208
2211
2213 if (auto *C = dyn_cast(GV.getInitializer())) {
2214 auto &DL = M.getDataLayout();
2215
2216
2217
2219 if (New != C)
2221 }
2222
2223 if (deleteIfDead(GV, NotDiscardableComdats)) {
2224 Changed = true;
2225 continue;
2226 }
2227
2228
2229
2231
2232 Changed |= processGlobal(GV, GetTTI, GetTLI, LookupDomTree);
2233 }
2234 return Changed;
2235}
2236
2237
2238
2241
2242 if (F->isDeclaration())
2243 return false;
2244
2249
2250 if (EvalSuccess) {
2251 ++NumCtorsEvaluated;
2252
2253
2255 LLVM_DEBUG(dbgs() << "FULLY EVALUATED GLOBAL CTOR FUNCTION '"
2256 << F->getName() << "' to " << NewInitializers.size()
2257 << " stores.\n");
2258 for (const auto &Pair : NewInitializers)
2259 Pair.first->setInitializer(Pair.second);
2262 }
2263
2264 return EvalSuccess;
2265}
2266
2271}
2272
2275 if (Init.empty()) {
2276 V.eraseFromParent();
2277 return;
2278 }
2279
2280
2281 const Type *UsedArrayType = V.getValueType();
2282 const auto *VAT = cast(UsedArrayType);
2283 const auto *VEPT = cast(VAT->getArrayElementType());
2284
2285
2287 PointerType::get(V.getContext(), VEPT->getAddressSpace());
2288
2293 }
2294
2295
2297 ArrayType *ATy = ArrayType::get(PtrTy, UsedArray.size());
2298
2299 Module *M = V.getParent();
2300 V.removeFromParent();
2304 NV->takeName(&V);
2305 NV->setSection("llvm.metadata");
2306 delete &V;
2307}
2308
2309namespace {
2310
2311
2312class LLVMUsed {
2317
2318public:
2319 LLVMUsed(Module &M) {
2325 CompilerUsed = {Vec.begin(), Vec.end()};
2326 }
2327
2330
2331 iterator usedBegin() { return Used.begin(); }
2332 iterator usedEnd() { return Used.end(); }
2333
2334 used_iterator_range used() {
2335 return used_iterator_range(usedBegin(), usedEnd());
2336 }
2337
2338 iterator compilerUsedBegin() { return CompilerUsed.begin(); }
2339 iterator compilerUsedEnd() { return CompilerUsed.end(); }
2340
2341 used_iterator_range compilerUsed() {
2342 return used_iterator_range(compilerUsedBegin(), compilerUsedEnd());
2343 }
2344
2345 bool usedCount(GlobalValue *GV) const { return Used.count(GV); }
2346
2347 bool compilerUsedCount(GlobalValue *GV) const {
2348 return CompilerUsed.count(GV);
2349 }
2350
2351 bool usedErase(GlobalValue *GV) { return Used.erase(GV); }
2352 bool compilerUsedErase(GlobalValue *GV) { return CompilerUsed.erase(GV); }
2353 bool usedInsert(GlobalValue *GV) { return Used.insert(GV).second; }
2354
2355 bool compilerUsedInsert(GlobalValue *GV) {
2356 return CompilerUsed.insert(GV).second;
2357 }
2358
2359 void syncVariablesAndSets() {
2360 if (UsedV)
2362 if (CompilerUsedV)
2364 }
2365};
2366
2367}
2368
2370 if (GA.use_empty())
2371 return false;
2372
2373 assert((!U.usedCount(&GA) || !U.compilerUsedCount(&GA)) &&
2374 "We should have removed the duplicated "
2375 "element from llvm.compiler.used");
2377
2378
2379 return true;
2380
2381
2382 return !U.usedCount(&GA) && !U.compilerUsedCount(&GA);
2383}
2384
2387 return true;
2388
2389 return U.usedCount(&GV) || U.compilerUsedCount(&GV);
2390}
2391
2393 bool &RenameTarget) {
2395 return false;
2396
2397 RenameTarget = false;
2398 bool Ret = false;
2400 Ret = true;
2401
2402
2404 return Ret;
2405
2406
2407
2408
2409
2410
2411
2412
2416 return Ret;
2417
2418 RenameTarget = true;
2419 return true;
2420}
2421
2422static bool
2425 bool Changed = false;
2426 LLVMUsed Used(M);
2427
2429 Used.compilerUsedErase(GV);
2430
2431
2432
2433 auto IsModuleLocal = [](GlobalValue &GV) {
2436 };
2437
2439
2440 if (!J.hasName() && !J.isDeclaration() && !J.hasLocalLinkage())
2442
2443 if (deleteIfDead(J, NotDiscardableComdats)) {
2444 Changed = true;
2445 continue;
2446 }
2447
2448
2449 if (!IsModuleLocal(J))
2450 continue;
2451
2452 Constant *Aliasee = J.getAliasee();
2454
2455
2456
2457
2458
2459
2461 continue;
2462
2463 Target->removeDeadConstantUsers();
2464
2465
2466 bool RenameTarget;
2468 continue;
2469
2470 J.replaceAllUsesWith(Aliasee);
2471 ++NumAliasesResolved;
2472 Changed = true;
2473
2474 if (RenameTarget) {
2475
2476 Target->takeName(&J);
2477 Target->setLinkage(J.getLinkage());
2478 Target->setDSOLocal(J.isDSOLocal());
2479 Target->setVisibility(J.getVisibility());
2480 Target->setDLLStorageClass(J.getDLLStorageClass());
2481
2482 if (Used.usedErase(&J))
2483 Used.usedInsert(Target);
2484
2485 if (Used.compilerUsedErase(&J))
2486 Used.compilerUsedInsert(Target);
2488 continue;
2489
2490
2491 M.eraseAlias(&J);
2492 ++NumAliasesRemoved;
2493 Changed = true;
2494 }
2495
2496 Used.syncVariablesAndSets();
2497
2498 return Changed;
2499}
2500
2505
2506 auto FuncIter = M.begin();
2507 if (FuncIter == M.end())
2508 return nullptr;
2509 auto *TLI = &GetTLI(*FuncIter);
2510
2511 if (!TLI->has(Func))
2512 return nullptr;
2513
2514 Function *Fn = M.getFunction(TLI->getName(Func));
2515 if (!Fn)
2516 return nullptr;
2517
2518
2519 TLI = &GetTLI(*Fn);
2520
2521
2523 if (!TLI->getLibFunc(*Fn, F) || F != Func)
2524 return nullptr;
2525
2526 return Fn;
2527}
2528
2529
2530
2531
2532
2534
2535
2537 return false;
2538
2540 if (I.isDebugOrPseudoInst())
2541 continue;
2542 if (isa(I))
2543 return true;
2544 break;
2545 }
2546 return false;
2547}
2548
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564 bool Changed = false;
2565
2567
2568
2569
2570 CallInst *CI = dyn_cast(U);
2571 if (!CI)
2572 continue;
2573
2577 continue;
2578
2579
2582
2583 if (isCXX)
2584 ++NumCXXDtorsRemoved;
2585 else
2586 ++NumAtExitRemoved;
2587
2588 Changed |= true;
2589 }
2590
2591 return Changed;
2592}
2593
2595 if (IF.isInterposable())
2596 return nullptr;
2597
2600 return nullptr;
2601
2602 if (Resolver->isInterposable())
2603 return nullptr;
2604
2605
2606 auto It = Resolver->begin();
2607 if (++It != Resolver->end())
2608 return nullptr;
2609
2611
2613 return nullptr;
2614
2615 auto *Ret = dyn_cast(BB.getTerminator());
2616 if (!Ret)
2617 return nullptr;
2618
2619 return dyn_cast(Ret->getReturnValue());
2620}
2621
2622
2625 bool Changed = false;
2628 if (!IF.use_empty() &&
2629 (!Callee->isDeclaration() ||
2630 none_of(IF.users(), [](User *U) { return isa(U); }))) {
2631 IF.replaceAllUsesWith(Callee);
2632 NumIFuncsResolved++;
2633 Changed = true;
2634 }
2635 return Changed;
2636}
2637
2638static bool
2641 bool Changed = false;
2643 if (deleteIfDead(IF, NotDiscardableComdats)) {
2644 NumIFuncsDeleted++;
2645 Changed = true;
2646 }
2647 return Changed;
2648}
2649
2650
2651
2652
2655 if (auto *F = dyn_cast(V)) {
2657 return false;
2659 } else if (auto *Sel = dyn_cast(V)) {
2661 return false;
2663 return false;
2664 } else if (auto *Phi = dyn_cast(V)) {
2665 for (unsigned I = 0, E = Phi->getNumIncomingValues(); I != E; ++I)
2667 return false;
2668 } else {
2669
2670 return false;
2671 }
2672 return true;
2673}
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2694 bool Changed = false;
2695
2696
2698
2700 if (IF.isInterposable())
2701 continue;
2702
2705 continue;
2706
2707 if (Resolver->isInterposable())
2708 continue;
2709
2711
2712
2715 if (auto *Ret = dyn_cast_or_null(BB.getTerminator()))
2717 return true;
2718 return false;
2719 }))
2720 continue;
2721
2722 assert(!Callees.empty() && "Expecting successful collection of versions");
2723
2724 LLVM_DEBUG(dbgs() << "Statically resolving calls to function "
2725 << Resolver->getName() << "\n");
2726
2727
2728 for (Function *Callee : Callees) {
2729 auto [It, Inserted] = FeatureMask.try_emplace(Callee);
2730 if (Inserted)
2732 }
2733
2734
2735 sort(Callees, [&](auto *LHS, auto *RHS) {
2736 return FeatureMask[LHS] > FeatureMask[RHS];
2737 });
2738
2739
2742 for (User *U : IF.users()) {
2743 if (auto *CB = dyn_cast(U)) {
2744 if (CB->getCalledOperand() == &IF) {
2745 Function *Caller = CB->getFunction();
2746 auto [FeatIt, FeatInserted] = FeatureMask.try_emplace(Caller);
2747 if (FeatInserted)
2749 auto [CallIt, CallInserted] = CallSites.try_emplace(Caller);
2750 if (CallInserted)
2751 Callers.push_back(Caller);
2752 CallIt->second.push_back(CB);
2753 }
2754 }
2755 }
2756
2757
2758 sort(Callers, [&](auto *LHS, auto *RHS) {
2759 return FeatureMask[LHS] > FeatureMask[RHS];
2760 });
2761
2763
2764
2765 unsigned I = 0;
2766
2767 for (Function *Caller : Callers) {
2768 assert(I < Callees.size() && "Found callers of equal priority");
2769
2771 uint64_t CallerBits = FeatureMask[Caller];
2772 uint64_t CalleeBits = FeatureMask[Callee];
2773
2774
2775
2776
2777
2779
2780
2781
2782 if (CallerBits == CalleeBits)
2783 ++I;
2784 else if (!implies(CallerBits, CalleeBits)) {
2785
2786
2787 while (implies(CalleeBits, CallerBits)) {
2788 if (++I == Callees.size())
2789 break;
2790 CalleeBits = FeatureMask[Callees[I]];
2791 }
2792 continue;
2793 }
2794 } else {
2795
2796
2798 continue;
2799 }
2800 auto &Calls = CallSites[Caller];
2801 for (CallBase *CS : Calls) {
2802 LLVM_DEBUG(dbgs() << "Redirecting call " << Caller->getName() << " -> "
2803 << Callee->getName() << "\n");
2804 CS->setCalledOperand(Callee);
2805 }
2806 Changed = true;
2807 }
2808 if (IF.use_empty() ||
2809 all_of(IF.users(), [](User *U) { return isa(U); }))
2810 NumIFuncsResolved++;
2811 }
2812 return Changed;
2813}
2814
2815static bool
2824 bool Changed = false;
2825 bool LocalChange = true;
2826 std::optional<uint32_t> FirstNotFullyEvaluatedPriority;
2827
2828 while (LocalChange) {
2829 LocalChange = false;
2830
2831 NotDiscardableComdats.clear();
2835 NotDiscardableComdats.insert(C);
2837 if (const Comdat *C = F.getComdat())
2838 if (.isDefTriviallyDead())
2839 NotDiscardableComdats.insert(C);
2841 if (const Comdat *C = GA.getComdat())
2842 if (!GA.isDiscardableIfUnused() || !GA.use_empty())
2843 NotDiscardableComdats.insert(C);
2844
2845
2846 LocalChange |= OptimizeFunctions(M, GetTLI, GetTTI, GetBFI, LookupDomTree,
2847 NotDiscardableComdats, ChangedCFGCallback,
2848 DeleteFnCallback);
2849
2850
2851 LocalChange |=
2853 if (FirstNotFullyEvaluatedPriority &&
2854 *FirstNotFullyEvaluatedPriority != Priority)
2855 return false;
2857 if (!Evaluated)
2858 FirstNotFullyEvaluatedPriority = Priority;
2859 return Evaluated;
2860 });
2861
2862
2864 NotDiscardableComdats);
2865
2866
2868
2869
2870
2874
2877
2878
2880
2881
2883
2884
2886
2887 Changed |= LocalChange;
2888 }
2889
2890
2891
2892
2893 return Changed;
2894}
2895
2897 auto &DL = M.getDataLayout();
2898 auto &FAM =
2902 };
2905 };
2908 };
2909
2912 };
2913 auto ChangedCFGCallback = [&FAM](Function &F) {
2915 };
2917
2919 ChangedCFGCallback, DeleteFnCallback))
2921
2923
2925
2926
2927
2929 return PA;
2930}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
static bool IsSafeComputationToRemove(Value *V, function_ref< TargetLibraryInfo &(Function &)> GetTLI)
Given a value that is stored to a global but never read, determine whether it's safe to remove the st...
static Function * FindAtExitLibFunc(Module &M, function_ref< TargetLibraryInfo &(Function &)> GetTLI, LibFunc Func)
static bool optimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal, const DataLayout &DL, function_ref< TargetLibraryInfo &(Function &)> GetTLI)
static Function * hasSideeffectFreeStaticResolution(GlobalIFunc &IF)
static bool tryToOptimizeStoreOfAllocationToGlobal(GlobalVariable *GV, CallInst *CI, const DataLayout &DL, TargetLibraryInfo *TLI)
If we have a global that is only initialized with a fixed size allocation try to transform the progra...
static void ConstantPropUsersOf(Value *V, const DataLayout &DL, TargetLibraryInfo *TLI)
Walk the use list of V, constant folding all of the instructions that are foldable.
static bool hasOnlyColdCalls(Function &F, function_ref< BlockFrequencyInfo &(Function &)> GetBFI, ChangeableCCCacheTy &ChangeableCCCache)
static bool allUsesOfLoadedValueWillTrapIfNull(const GlobalVariable *GV)
Return true if all uses of any loads from GV will trap if the loaded value is null.
static bool hasChangeableCCImpl(Function *F)
Return true if this is a calling convention that we'd like to change.
static bool tryWidenGlobalArrayAndDests(Function *F, GlobalVariable *SourceVar, const unsigned NumBytesToPad, const unsigned NumBytesToCopy, ConstantInt *BytesToCopyOp, ConstantDataArray *SourceDataArray)
static GlobalVariable * widenGlobalVariable(GlobalVariable *OldVar, Function *F, unsigned NumBytesToPad, unsigned NumBytesToCopy)
static bool AllUsesOfValueWillTrapIfNull(const Value *V, SmallPtrSetImpl< const PHINode * > &PHIs)
Return true if all users of the specified value will trap if the value is dynamically null.
static GlobalVariable * OptimizeGlobalAddressOfAllocation(GlobalVariable *GV, CallInst *CI, uint64_t AllocSize, Constant *InitVal, const DataLayout &DL, TargetLibraryInfo *TLI)
This function takes the specified global variable, and transforms the program as if it always contain...
Returns whether the given function is an empty C destructor or atexit handler and can therefore be eliminated Note that we assume that other optimization passes have already simplified the code so we simply check for static ret bool IsEmptyAtExitFunction(const Function &Fn)
static bool collectSRATypes(DenseMap< uint64_t, GlobalPart > &Parts, GlobalVariable *GV, const DataLayout &DL)
Look at all uses of the global and determine which (offset, type) pairs it can be split into.
static bool valueIsOnlyUsedLocallyOrStoredToOneGlobal(const CallInst *CI, const GlobalVariable *GV)
Scan the use-list of GV checking to make sure that there are no complex uses of GV.
static bool OptimizeFunctions(Module &M, function_ref< TargetLibraryInfo &(Function &)> GetTLI, function_ref< TargetTransformInfo &(Function &)> GetTTI, function_ref< BlockFrequencyInfo &(Function &)> GetBFI, function_ref< DominatorTree &(Function &)> LookupDomTree, SmallPtrSetImpl< const Comdat * > &NotDiscardableComdats, function_ref< void(Function &F)> ChangedCFGCallback, function_ref< void(Function &F)> DeleteFnCallback)
static bool DeleteDeadIFuncs(Module &M, SmallPtrSetImpl< const Comdat * > &NotDiscardableComdats)
static void RemoveAttribute(Function *F, Attribute::AttrKind A)
static bool tryWidenGlobalArraysUsedByMemcpy(GlobalVariable *GV, function_ref< TargetTransformInfo &(Function &)> GetTTI)
static bool hasChangeableCC(Function *F, ChangeableCCCacheTy &ChangeableCCCache)
static bool deleteIfDead(GlobalValue &GV, SmallPtrSetImpl< const Comdat * > &NotDiscardableComdats, function_ref< void(Function &)> DeleteFnCallback=nullptr)
static void RemovePreallocated(Function *F)
static cl::opt< bool > OptimizeNonFMVCallers("optimize-non-fmv-callers", cl::desc("Statically resolve calls to versioned " "functions from non-versioned callers."), cl::init(true), cl::Hidden)
static bool processGlobal(GlobalValue &GV, function_ref< TargetTransformInfo &(Function &)> GetTTI, function_ref< TargetLibraryInfo &(Function &)> GetTLI, function_ref< DominatorTree &(Function &)> LookupDomTree)
Analyze the specified global variable and optimize it if possible.
static bool isColdCallSite(CallBase &CB, BlockFrequencyInfo &CallerBFI)
Return true if the block containing the call site has a BlockFrequency of less than ColdCCRelFreq% of...
static void transferSRADebugInfo(GlobalVariable *GV, GlobalVariable *NGV, uint64_t FragmentOffsetInBits, uint64_t FragmentSizeInBits, uint64_t VarSize)
Copy over the debug info for a variable to its SRA replacements.
static cl::opt< bool > EnableColdCCStressTest("enable-coldcc-stress-test", cl::desc("Enable stress test of coldcc by adding " "calling conv to all internal functions."), cl::init(false), cl::Hidden)
static bool OptimizeGlobalAliases(Module &M, SmallPtrSetImpl< const Comdat * > &NotDiscardableComdats)
static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal)
At this point, we have learned that the only two values ever stored into GV are its initializer and O...
static void ChangeCalleesToFastCall(Function *F)
Walk all of the direct calls of the specified function, changing them to FastCC.
static bool hasMustTailCallers(Function *F)
static bool callInstIsMemcpy(CallInst *CI)
static bool OptimizeNonTrivialIFuncs(Module &M, function_ref< TargetTransformInfo &(Function &)> GetTTI)
static bool OptimizeGlobalVars(Module &M, function_ref< TargetTransformInfo &(Function &)> GetTTI, function_ref< TargetLibraryInfo &(Function &)> GetTLI, function_ref< DominatorTree &(Function &)> LookupDomTree, SmallPtrSetImpl< const Comdat * > &NotDiscardableComdats)
static void allUsesOfLoadAndStores(GlobalVariable *GV, SmallVector< Value *, 4 > &Uses)
Get all the loads/store uses for global variable GV.
static void widenDestArray(CallInst *CI, const unsigned NumBytesToPad, const unsigned NumBytesToCopy, ConstantDataArray *SourceDataArray)
static bool OptimizeEmptyGlobalAtExitDtors(Function *CXAAtExitFn, bool isCXX)
static bool mayHaveOtherReferences(GlobalValue &GV, const LLVMUsed &U)
static void changeCallSitesToColdCC(Function *F)
static AttributeList StripAttr(LLVMContext &C, AttributeList Attrs, Attribute::AttrKind A)
static bool hasInvokeCallers(Function *F)
static void setUsedInitializer(GlobalVariable &V, const SmallPtrSetImpl< GlobalValue * > &Init)
static bool OptimizeAwayTrappingUsesOfLoads(GlobalVariable *GV, Constant *LV, const DataLayout &DL, function_ref< TargetLibraryInfo &(Function &)> GetTLI)
The specified global has only one non-null value stored into it.
static bool isValidCandidateForColdCC(Function &F, function_ref< BlockFrequencyInfo &(Function &)> GetBFI, const std::vector< Function * > &AllCallsCold)
static cl::opt< int > ColdCCRelFreq("coldcc-rel-freq", cl::Hidden, cl::init(2), cl::desc("Maximum block frequency, expressed as a percentage of caller's " "entry frequency, for a call site to be considered cold for enabling " "coldcc"))
static bool optimizeGlobalsInModule(Module &M, const DataLayout &DL, function_ref< TargetLibraryInfo &(Function &)> GetTLI, function_ref< TargetTransformInfo &(Function &)> GetTTI, function_ref< BlockFrequencyInfo &(Function &)> GetBFI, function_ref< DominatorTree &(Function &)> LookupDomTree, function_ref< void(Function &F)> ChangedCFGCallback, function_ref< void(Function &F)> DeleteFnCallback)
static bool EvaluateStaticConstructor(Function *F, const DataLayout &DL, TargetLibraryInfo *TLI)
Evaluate static constructors in the function, if we can.
static bool CleanupConstantGlobalUsers(GlobalVariable *GV, const DataLayout &DL)
We just marked GV constant.
Find IFuncs that have resolvers that always point at the same statically known and replace their callers with a direct static call bool OptimizeStaticIFuncs(Module &M)
static bool isLeakCheckerRoot(GlobalVariable *GV)
Is this global variable possibly used by a leak checker as a root? If so, we might not really want to...
static bool forwardStoredOnceStore(GlobalVariable *GV, const StoreInst *StoredOnceStore, function_ref< DominatorTree &(Function &)> LookupDomTree)
static int compareNames(Constant *const *A, Constant *const *B)
static bool collectVersions(TargetTransformInfo &TTI, Value *V, SmallVectorImpl< Function * > &Versions)
static bool CleanupPointerRootUsers(GlobalVariable *GV, function_ref< TargetLibraryInfo &(Function &)> GetTLI)
This GV is a pointer root.
static bool isPointerValueDeadOnEntryToFunction(const Function *F, GlobalValue *GV, function_ref< DominatorTree &(Function &)> LookupDomTree)
static bool processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS, function_ref< TargetTransformInfo &(Function &)> GetTTI, function_ref< TargetLibraryInfo &(Function &)> GetTLI, function_ref< DominatorTree &(Function &)> LookupDomTree)
Analyze the specified global variable and optimize it if possible.
static bool hasUsesToReplace(GlobalAlias &GA, const LLVMUsed &U, bool &RenameTarget)
static bool OptimizeAwayTrappingUsesOfValue(Value *V, Constant *NewV)
static GlobalVariable * SRAGlobal(GlobalVariable *GV, const DataLayout &DL)
Perform scalar replacement of aggregates on the specified global variable.
static bool destArrayCanBeWidened(CallInst *CI)
static bool hasUseOtherThanLLVMUsed(GlobalAlias &GA, const LLVMUsed &U)
Module.h This file contains the declarations for the Module class.
This defines the Use class.
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
Remove Loads Into Fake Uses
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
This pass exposes codegen information to IR-level passes.
Class for arbitrary precision integers.
This class represents a conversion between pointers from one address space to another.
an instruction to allocate memory on the stack
void setAlignment(Align Align)
A container for analyses that lazily runs them and caches their results.
void clear(IRUnitT &IR, llvm::StringRef Name)
Clear any cached analysis results for a single unit of IR.
void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Invalidate cached analyses for an IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
uint64_t getNumElements() const
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
LLVM Basic Block Representation.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BinaryOperator * CreateNot(Value *Op, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
BlockFrequency getBlockFreq(const BasicBlock *BB) const
getblockFreq - Return block frequency.
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the attributes for this call.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
static CallBase * Create(CallBase *CB, ArrayRef< OperandBundleDef > Bundles, InsertPosition InsertPt=nullptr)
Create a clone of CB with a different set of operand bundles and insert it before InsertPt.
void setCalledOperand(Value *V)
unsigned arg_size() const
AttributeList getAttributes() const
Return the attributes for this call.
Function * getCaller()
Helper to get the caller (the parent function).
This class represents a function call, abstracting a target machine's calling convention.
bool isMustTailCall() const
Predicate getPredicate() const
Return the predicate for this instruction.
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
An array constant whose element type is a simple 1/2/4/8-byte integer or float/double,...
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
ArrayType * getType() const
Specialize the getType() method to always return an ArrayType, which reduces the amount of casting ne...
uint64_t getElementByteSize() const
Return the size (in bytes) of each element in the array/vector.
StringRef getRawDataValues() const
Return the raw, underlying, bytes of this data.
A constant value that is initialized with an expression using other constant values.
static Constant * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)
Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.
static Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
This is the shared class of boolean and integer constants.
static ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getFalse(LLVMContext &Context)
static ConstantInt * getBool(LLVMContext &Context, bool V)
This is an important base class in LLVM.
const Constant * stripPointerCasts() const
void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
bool extractIfOffset(int64_t &Offset) const
If this is a constant offset, extract it.
static std::optional< DIExpression * > createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits)
Create a DIExpression to describe one part of an aggregate variable that is fragmented across multipl...
static DIExpression * prependOpcodes(const DIExpression *Expr, SmallVectorImpl< uint64_t > &Ops, bool StackValue=false, bool EntryValue=false)
Prepend DIExpr with the given opcodes and optionally turn it into a stack value.
A pair of DIGlobalVariable and DIExpression.
uint64_t getSizeInBits() const
Base class for variables.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
bool erase(const KeyT &Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
This class evaluates LLVM IR, producing the Constant representing each SSA instruction.
DenseMap< GlobalVariable *, Constant * > getMutatedInitializers() const
bool EvaluateFunction(Function *F, Constant *&RetVal, const SmallVectorImpl< Constant * > &ActualArgs)
Evaluate a call to function F, returning true if successful, false if we can't evaluate it.
const SmallPtrSetImpl< GlobalVariable * > & getInvariants() const
const BasicBlock & getEntryBlock() const
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
const Constant * getAliasee() const
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalObject.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
bool isImplicitDSOLocal() const
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
LinkageTypes getLinkage() const
void setUnnamedAddr(UnnamedAddr Val)
bool hasLocalLinkage() const
bool hasPrivateLinkage() const
const Comdat * getComdat() const
ThreadLocalMode getThreadLocalMode() const
void setLinkage(LinkageTypes LT)
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
void eraseFromParent()
This method unlinks 'this' from the containing module and deletes it.
PointerType * getType() const
Global values are always pointers.
const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
static bool isInterposableLinkage(LinkageTypes Linkage)
Whether the definition of this global may be replaced by something non-equivalent at link time.
bool hasGlobalUnnamedAddr() const
UnnamedAddr getUnnamedAddr() const
static bool isWeakForLinker(LinkageTypes Linkage)
Whether the definition of this global may be replaced at link time.
static bool isDiscardableIfUnused(LinkageTypes Linkage)
Whether the definition of this global may be discarded if it is not used in its compilation unit.
@ InternalLinkage
Rename collisions when linking (static functions).
@ AppendingLinkage
Special purpose, only applies to global arrays.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
bool isExternallyInitialized() const
bool hasInitializer() const
Definitions have initializers, declarations don't.
void setConstant(bool Val)
void copyAttributesFrom(const GlobalVariable *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a GlobalVariable) fro...
void getDebugInfo(SmallVectorImpl< DIGlobalVariableExpression * > &GVs) const
Fill the vector with all debug info attachements.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
void addDebugInfo(DIGlobalVariableExpression *GV)
Attach a DIGlobalVariableExpression.
This instruction compares its operands according to the predicate given to the constructor.
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
CallInst * CreateStackSave(const Twine &Name="")
Create a call to llvm.stacksave.
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)
Create and insert a memset to the specified pointer and the specified value.
CallInst * CreateStackRestore(Value *Ptr, const Twine &Name="")
Create a call to llvm.stackrestore.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
const Function * getFunction() const
Return the function this instruction belongs to.
const Instruction * getNextNonDebugInstruction(bool SkipPseudoOp=false) const
Return a pointer to the next non-debug instruction in the same basic block as 'this',...
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
LLVMContext & getContext() const
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
This class wraps the llvm.memcpy/memmove intrinsics.
A Module instance is used to store all the information related to an LLVM module.
void insertGlobalVariable(GlobalVariable *GV)
Insert global variable GV at the end of the global variable list and take ownership.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserveSet()
Mark an analysis set as preserved.
void preserve()
Mark an analysis as preserved.
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, Instruction *MDFrom=nullptr)
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Value * getValueOperand()
StringRef - Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
int compare(StringRef RHS) const
compare - Compare two strings; the result is negative, zero, or positive if this string is lexicograp...
Class to represent struct types.
ArrayRef< Type * > elements() const
bool isOpaque() const
Return true if this is a type with an identity that has no body specified yet.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
uint64_t getFeatureMask(const Function &F) const
Returns a bitmask constructed from the target-features or fmv-features metadata of a function.
bool isMultiversionedFunction(const Function &F) const
Returns true if this is an instance of a function with multiple versions.
bool useColdCCForColdCall(Function &F) const
Return true if the input function which is cold at all call sites, should use coldcc calling conventi...
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isPointerTy() const
True if this is an instance of PointerType.
static IntegerType * getInt1Ty(LLVMContext &C)
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
@ ScalableVectorTyID
Scalable SIMD vector type.
@ FixedVectorTyID
Fixed width SIMD vector type.
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
static IntegerType * getInt8Ty(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
TypeID getTypeID() const
Return the type id for the type.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr) const
Accumulate the constant offset this value has compared to a base pointer.
bool hasOneUse() const
Return true if there is exactly one use of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVMContext & getContext() const
All values hold a context through their type.
user_iterator_impl< User > user_iterator
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
This class represents zero extension of integer types.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
A range adaptor for a pair of iterators.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Cold
Attempts to make code in the caller as efficient as possible under the assumption that the call is no...
@ X86_ThisCall
Similar to X86_StdCall.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI)
Return true if this is a call to an allocation function that does not have side effects that we are r...
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Constant * ConstantFoldConstant(const Constant *C, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldConstant - Fold the constant using the specified DataLayout.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Compute the size of the object pointed by Ptr.
Constant * ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty, const DataLayout &DL)
If C is a uniform value where all bits are the same (either all zero, all ones, all undef or all pois...
bool isSafeToDestroyConstant(const Constant *C)
It is safe to destroy a constant iff it is only used by constants itself.
Align getOrEnforceKnownAlignment(Value *V, MaybeAlign PrefAlign, const DataLayout &DL, const Instruction *CxtI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr)
Try to ensure that the alignment of V is at least PrefAlign bytes.
bool optimizeGlobalCtorsList(Module &M, function_ref< bool(uint32_t, Function *)> ShouldRemove)
Call "ShouldRemove" for every entry in M's global_ctor list and remove the entries for which it retur...
void sort(IteratorTy Start, IteratorTy End)
bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isPointerTy(const Type *T)
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Constant * ConstantFoldLoadFromConst(Constant *C, Type *Ty, const APInt &Offset, const DataLayout &DL)
Extract value of C at the given Offset reinterpreted as Ty.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Constant * ConstantFoldInstruction(Instruction *I, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldInstruction - Try to constant fold the specified instruction.
bool RecursivelyDeleteTriviallyDeadInstructionsPermissive(SmallVectorImpl< WeakTrackingVH > &DeadInsts, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
Same functionality as RecursivelyDeleteTriviallyDeadInstructions, but allow instructions that are not...
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates or reallocates memory (eith...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
GlobalVariable * collectUsedGlobalVariables(const Module &M, SmallVectorImpl< GlobalValue * > &Vec, bool CompilerUsed)
Given "llvm.used" or "llvm.compiler.used" as a global name, collect the initializer elements of that ...
Part of the global at a specific offset, which is only accessed through loads and stores with the giv...
This struct is a compact representation of a valid (non-zero power of two) alignment.
As we analyze each global or thread-local variable, keep track of some information about it.
@ InitializerStored
This global is stored to, but the only thing stored is the constant it was initialized with.
@ StoredOnce
This global is stored to, but only its initializer and one other value is ever stored to it.
static bool analyzeGlobal(const Value *V, GlobalStatus &GS)
Look at all uses of the global and fill in the GlobalStatus structure.
Various options to control the behavior of getObjectSize.
Function object to check whether the first component of a container supported by std::get (like std::...