LLVM 24.0.0git
WholeProgramDevirt.cpp
Go to the documentation of this file.
1//===- WholeProgramDevirt.cpp - Whole program virtual call optimization ---===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This pass implements whole program optimization of virtual calls in cases
10// where we know (via !type metadata) that the list of callees is fixed. This
11// includes the following:
12// - Single implementation devirtualization: if a virtual call has a single
13// possible callee, replace all calls with a direct call to that callee.
14// - Virtual constant propagation: if the virtual function's return type is an
15// integer <=64 bits and all possible callees are readnone, for each class and
16// each list of constant arguments: evaluate the function, store the return
17// value alongside the virtual table, and rewrite each virtual call as a load
18// from the virtual table.
19// - Uniform return value optimization: if the conditions for virtual constant
20// propagation hold and each function returns the same constant value, replace
21// each virtual call with that constant.
22// - Unique return value optimization for i1 return values: if the conditions
23// for virtual constant propagation hold and a single vtable's function
24// returns 0, or a single vtable's function returns 1, replace each virtual
25// call with a comparison of the vptr against that vtable's address.
26//
27// This pass is intended to be used during the regular/thin and non-LTO
28// pipelines:
29//
30// During regular LTO, the pass determines the best optimization for each
31// virtual call and applies the resolutions directly to virtual calls that are
32// eligible for virtual call optimization (i.e. calls that use either of the
33// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics).
34//
35// During hybrid Regular/ThinLTO, the pass operates in two phases:
36// - Export phase: this is run during the thin link over a single merged module
37// that contains all vtables with !type metadata that participate in the link.
38// The pass computes a resolution for each virtual call and stores it in the
39// type identifier summary.
40// - Import phase: this is run during the thin backends over the individual
41// modules. The pass applies the resolutions previously computed during the
42// import phase to each eligible virtual call.
43//
44// During ThinLTO, the pass operates in two phases:
45// - Export phase: this is run during the thin link over the index which
46// contains a summary of all vtables with !type metadata that participate in
47// the link. It computes a resolution for each virtual call and stores it in
48// the type identifier summary. Only single implementation devirtualization
49// is supported.
50// - Import phase: (same as with hybrid case above).
51//
52// During Speculative devirtualization mode -not restricted to LTO-:
53// - The pass applies speculative devirtualization without requiring any type of
54// visibility.
55// - Skips other features like virtual constant propagation, uniform return
56// value optimization, unique return value optimization and branch funnels as
57// they need LTO.
58// - This mode is enabled via 'devirtualize-speculatively' flag.
59//
60//===----------------------------------------------------------------------===//
61
63#include "IPOOptions.h"
64#include "llvm/ADT/ArrayRef.h"
65#include "llvm/ADT/DenseMap.h"
67#include "llvm/ADT/DenseSet.h"
68#include "llvm/ADT/MapVector.h"
71#include "llvm/ADT/Statistic.h"
81#include "llvm/IR/Constants.h"
82#include "llvm/IR/DataLayout.h"
83#include "llvm/IR/DebugLoc.h"
86#include "llvm/IR/Dominators.h"
87#include "llvm/IR/Function.h"
88#include "llvm/IR/GlobalAlias.h"
90#include "llvm/IR/IRBuilder.h"
91#include "llvm/IR/InstrTypes.h"
92#include "llvm/IR/Instruction.h"
94#include "llvm/IR/Intrinsics.h"
95#include "llvm/IR/LLVMContext.h"
96#include "llvm/IR/MDBuilder.h"
97#include "llvm/IR/Metadata.h"
98#include "llvm/IR/Module.h"
100#include "llvm/IR/PassManager.h"
102#include "llvm/Support/Casting.h"
105#include "llvm/Support/Errc.h"
106#include "llvm/Support/Error.h"
111#include "llvm/Transforms/IPO.h"
116#include <algorithm>
117#include <cmath>
118#include <cstddef>
119#include <map>
120#include <set>
121#include <string>
122
123using namespace llvm;
124using namespace wholeprogramdevirt;
125
126#define DEBUG_TYPE "wholeprogramdevirt"
127
128STATISTIC(NumDevirtTargets, "Number of whole program devirtualization targets");
129STATISTIC(NumSingleImpl, "Number of single implementation devirtualizations");
130STATISTIC(NumBranchFunnel, "Number of branch funnels");
131STATISTIC(NumUniformRetVal, "Number of uniform return value optimizations");
132STATISTIC(NumUniqueRetVal, "Number of unique return value optimizations");
133STATISTIC(NumVirtConstProp1Bit,
134 "Number of 1 bit virtual constant propagations");
135STATISTIC(NumVirtConstProp, "Number of virtual constant propagations");
136DEBUG_COUNTER(CallsToDevirt, "calls-to-devirt",
137 "Controls how many calls should be devirtualized.");
138
139namespace llvm {
140
141static cl::opt<bool>
142 PrintSummaryDevirt("wholeprogramdevirt-print-index-based", cl::Hidden,
143 cl::desc("Print index-based devirtualization messages"));
144
145/// Provide a way to force enable whole program visibility in tests.
146/// This is needed to support legacy tests that don't contain
147/// !vcall_visibility metadata (the mere presense of type tests
148/// previously implied hidden visibility).
149static cl::opt<bool>
150 WholeProgramVisibility("whole-program-visibility", cl::Hidden,
151 cl::desc("Enable whole program visibility"));
152
153/// Provide a way to force disable whole program for debugging or workarounds,
154/// when enabled via the linker.
156 "disable-whole-program-visibility", cl::Hidden,
157 cl::desc("Disable whole program visibility (overrides enabling options)"));
158
159/// Provide way to prevent certain function from being devirtualized
161 SkipFunctionNames("wholeprogramdevirt-skip",
162 cl::desc("Prevent function(s) from being devirtualized"),
164
165} // end namespace llvm
166
167/// With Clang, a pure virtual class's deleting destructor is emitted as a
168/// `llvm.trap` intrinsic followed by an unreachable IR instruction. In the
169/// context of whole program devirtualization, the deleting destructor of a pure
170/// virtual class won't be invoked by the source code so safe to skip as a
171/// devirtualize target.
172///
173/// However, not all unreachable functions are safe to skip. In some cases, the
174/// program intends to run such functions and terminate, for instance, a unit
175/// test may run a death test. A non-test program might (or allowed to) invoke
176/// such functions to report failures (whether/when it's a good practice or not
177/// is a different topic).
178///
179/// This option is enabled to keep an unreachable function as a possible
180/// devirtualize target to conservatively keep the program behavior.
181///
182/// TODO: Make a pure virtual class's deleting destructor precisely identifiable
183/// in Clang's codegen for more devirtualization in LLVM.
185 "wholeprogramdevirt-keep-unreachable-function",
186 cl::desc("Regard unreachable functions as possible devirtualize targets."),
187 cl::Hidden, cl::init(true));
188
189namespace {
190struct PatternList {
191 std::vector<GlobPattern> Patterns;
192 template <class T> void init(const T &StringList) {
193 for (const auto &S : StringList)
195 Patterns.push_back(std::move(*Pat));
196 }
197 bool match(StringRef S) {
198 for (const GlobPattern &P : Patterns)
199 if (P.match(S))
200 return true;
201 return false;
202 }
203};
204} // namespace
205
206// Find the minimum offset that we may store a value of size Size bits at. If
207// IsAfter is set, look for an offset before the object, otherwise look for an
208// offset after the object.
211 bool IsAfter, uint64_t Size) {
212 // Find a minimum offset taking into account only vtable sizes.
213 uint64_t MinByte = 0;
214 for (const VirtualCallTarget &Target : Targets) {
215 if (IsAfter)
216 MinByte = std::max(MinByte, Target.minAfterBytes());
217 else
218 MinByte = std::max(MinByte, Target.minBeforeBytes());
219 }
220
221 // Build a vector of arrays of bytes covering, for each target, a slice of the
222 // used region (see AccumBitVector::BytesUsed in
223 // llvm/Transforms/IPO/WholeProgramDevirt.h) starting at MinByte. Effectively,
224 // this aligns the used regions to start at MinByte.
225 //
226 // In this example, A, B and C are vtables, # is a byte already allocated for
227 // a virtual function pointer, AAAA... (etc.) are the used regions for the
228 // vtables and Offset(X) is the value computed for the Offset variable below
229 // for X.
230 //
231 // Offset(A)
232 // | |
233 // |MinByte
234 // A: ################AAAAAAAA|AAAAAAAA
235 // B: ########BBBBBBBBBBBBBBBB|BBBB
236 // C: ########################|CCCCCCCCCCCCCCCC
237 // | Offset(B) |
238 //
239 // This code produces the slices of A, B and C that appear after the divider
240 // at MinByte.
241 std::vector<ArrayRef<uint8_t>> Used;
242 for (const VirtualCallTarget &Target : Targets) {
243 ArrayRef<uint8_t> VTUsed = IsAfter ? Target.TM->Bits->After.BytesUsed
244 : Target.TM->Bits->Before.BytesUsed;
245 uint64_t Offset = IsAfter ? MinByte - Target.minAfterBytes()
246 : MinByte - Target.minBeforeBytes();
247
248 // Disregard used regions that are smaller than Offset. These are
249 // effectively all-free regions that do not need to be checked.
250 if (VTUsed.size() > Offset)
251 Used.push_back(VTUsed.slice(Offset));
252 }
253
254 if (Size == 1) {
255 // Find a free bit in each member of Used.
256 for (unsigned I = 0;; ++I) {
257 uint8_t BitsUsed = 0;
258 for (auto &&B : Used)
259 if (I < B.size())
260 BitsUsed |= B[I];
261 if (BitsUsed != 0xff)
262 return (MinByte + I) * 8 + llvm::countr_zero(uint8_t(~BitsUsed));
263 }
264 } else {
265 // Find a free (Size/8) byte region in each member of Used.
266 // FIXME: see if alignment helps.
267 for (unsigned I = 0;; ++I) {
268 for (auto &&B : Used) {
269 unsigned Byte = 0;
270 while ((I + Byte) < B.size() && Byte < (Size / 8)) {
271 if (B[I + Byte])
272 goto NextI;
273 ++Byte;
274 }
275 }
276 // Rounding up ensures the constant is always stored at address we
277 // can directly load from without misalignment.
278 return alignTo((MinByte + I) * 8, Size);
279 NextI:;
280 }
281 }
282}
283
285 MutableArrayRef<VirtualCallTarget> Targets, uint64_t AllocBefore,
286 unsigned BitWidth, int64_t &OffsetByte, uint64_t &OffsetBit) {
287 if (BitWidth == 1)
288 OffsetByte = -(AllocBefore / 8 + 1);
289 else
290 OffsetByte = -((AllocBefore + 7) / 8 + (BitWidth + 7) / 8);
291 OffsetBit = AllocBefore % 8;
292
293 for (VirtualCallTarget &Target : Targets) {
294 if (BitWidth == 1)
295 Target.setBeforeBit(AllocBefore);
296 else
297 Target.setBeforeBytes(AllocBefore, (BitWidth + 7) / 8);
298 }
299}
300
302 MutableArrayRef<VirtualCallTarget> Targets, uint64_t AllocAfter,
303 unsigned BitWidth, int64_t &OffsetByte, uint64_t &OffsetBit) {
304 if (BitWidth == 1)
305 OffsetByte = AllocAfter / 8;
306 else
307 OffsetByte = (AllocAfter + 7) / 8;
308 OffsetBit = AllocAfter % 8;
309
310 for (VirtualCallTarget &Target : Targets) {
311 if (BitWidth == 1)
312 Target.setAfterBit(AllocAfter);
313 else
314 Target.setAfterBytes(AllocAfter, (BitWidth + 7) / 8);
315 }
316}
317
322
323namespace {
324
325// A slot in a set of virtual tables. The TypeID identifies the set of virtual
326// tables, and the ByteOffset is the offset in bytes from the address point to
327// the virtual function pointer.
328struct VTableSlot {
329 Metadata *TypeID;
330 uint64_t ByteOffset;
331};
332
333} // end anonymous namespace
334
335template <> struct llvm::DenseMapInfo<VTableSlot> {
336 static unsigned getHashValue(const VTableSlot &I) {
339 }
340 static bool isEqual(const VTableSlot &LHS,
341 const VTableSlot &RHS) {
342 return LHS.TypeID == RHS.TypeID && LHS.ByteOffset == RHS.ByteOffset;
343 }
344};
345
347 static unsigned getHashValue(const VTableSlotSummary &I) {
350 }
351 static bool isEqual(const VTableSlotSummary &LHS,
352 const VTableSlotSummary &RHS) {
353 return LHS.TypeID == RHS.TypeID && LHS.ByteOffset == RHS.ByteOffset;
354 }
355};
356
357// Returns true if the function must be unreachable based on ValueInfo.
358//
359// In particular, identifies a function as unreachable in the following
360// conditions
361// 1) All summaries are live.
362// 2) All function summaries indicate it's unreachable
363// 3) There is no non-function with the same GUID (which is rare)
366 return false;
367
368 if ((!TheFnVI) || TheFnVI.getSummaryList().empty()) {
369 // Returns false if ValueInfo is absent, or the summary list is empty
370 // (e.g., function declarations).
371 return false;
372 }
373
374 for (const auto &Summary : TheFnVI.getSummaryList()) {
375 // Conservatively returns false if any non-live functions are seen.
376 // In general either all summaries should be live or all should be dead.
377 if (!Summary->isLive())
378 return false;
379 if (auto *FS = dyn_cast<FunctionSummary>(Summary->getBaseObject())) {
380 if (!FS->fflags().MustBeUnreachable)
381 return false;
382 }
383 // Be conservative if a non-function has the same GUID (which is rare).
384 else
385 return false;
386 }
387 // All function summaries are live and all of them agree that the function is
388 // unreachble.
389 return true;
390}
391
392namespace {
393// A virtual call site. VTable is the loaded virtual table pointer, and CS is
394// the indirect virtual call.
395struct VirtualCallSite {
396 Value *VTable = nullptr;
397 CallBase &CB;
398
399 // If non-null, this field points to the associated unsafe use count stored in
400 // the DevirtModule::NumUnsafeUsesForTypeTest map below. See the description
401 // of that field for details.
402 unsigned *NumUnsafeUses = nullptr;
403
404 void
405 emitRemark(const StringRef OptName, const StringRef TargetName,
406 function_ref<OptimizationRemarkEmitter &(Function &)> OREGetter) {
407 Function *F = CB.getCaller();
408 DebugLoc DLoc = CB.getDebugLoc();
409 BasicBlock *Block = CB.getParent();
410
411 using namespace ore;
412 OREGetter(*F).emit(OptimizationRemark(DEBUG_TYPE, OptName, DLoc, Block)
413 << NV("Optimization", OptName)
414 << ": devirtualized a call to "
415 << NV("FunctionName", TargetName));
416 }
417
418 void replaceAndErase(
419 const StringRef OptName, const StringRef TargetName, bool RemarksEnabled,
420 function_ref<OptimizationRemarkEmitter &(Function &)> OREGetter,
421 Value *New) {
422 if (RemarksEnabled)
423 emitRemark(OptName, TargetName, OREGetter);
424 CB.replaceAllUsesWith(New);
425 if (auto *II = dyn_cast<InvokeInst>(&CB)) {
426 UncondBrInst::Create(II->getNormalDest(), CB.getIterator());
427 II->getUnwindDest()->removePredecessor(II->getParent());
428 }
429 CB.eraseFromParent();
430 // This use is no longer unsafe.
431 if (NumUnsafeUses)
432 --*NumUnsafeUses;
433 }
434};
435
436// Call site information collected for a specific VTableSlot and possibly a list
437// of constant integer arguments. The grouping by arguments is handled by the
438// VTableSlotInfo class.
439struct CallSiteInfo {
440 /// The set of call sites for this slot. Used during regular LTO and the
441 /// import phase of ThinLTO (as well as the export phase of ThinLTO for any
442 /// call sites that appear in the merged module itself); in each of these
443 /// cases we are directly operating on the call sites at the IR level.
444 std::vector<VirtualCallSite> CallSites;
445
446 /// Whether all call sites represented by this CallSiteInfo, including those
447 /// in summaries, have been devirtualized. This starts off as true because a
448 /// default constructed CallSiteInfo represents no call sites.
449 ///
450 /// If at the end of the pass there are still undevirtualized calls, we will
451 /// need to add a use of llvm.type.test to each of the function summaries in
452 /// the vector.
453 bool AllCallSitesDevirted = true;
454
455 // These fields are used during the export phase of ThinLTO and reflect
456 // information collected from function summaries.
457
458 /// CFI-specific: a vector containing the list of function summaries that use
459 /// the llvm.type.checked.load intrinsic and therefore will require
460 /// resolutions for llvm.type.test in order to implement CFI checks if
461 /// devirtualization was unsuccessful.
462 std::vector<FunctionSummary *> SummaryTypeCheckedLoadUsers;
463
464 /// A vector containing the list of function summaries that use
465 /// assume(llvm.type.test).
466 std::vector<FunctionSummary *> SummaryTypeTestAssumeUsers;
467
468 bool isExported() const {
469 return !SummaryTypeCheckedLoadUsers.empty() ||
470 !SummaryTypeTestAssumeUsers.empty();
471 }
472
473 void addSummaryTypeCheckedLoadUser(FunctionSummary *FS) {
474 SummaryTypeCheckedLoadUsers.push_back(FS);
475 AllCallSitesDevirted = false;
476 }
477
478 void addSummaryTypeTestAssumeUser(FunctionSummary *FS) {
479 SummaryTypeTestAssumeUsers.push_back(FS);
480 AllCallSitesDevirted = false;
481 }
482
483 void markDevirt() { AllCallSitesDevirted = true; }
484};
485
486// Call site information collected for a specific VTableSlot.
487struct VTableSlotInfo {
488 // The set of call sites which do not have all constant integer arguments
489 // (excluding "this").
490 CallSiteInfo CSInfo;
491
492 // The set of call sites with all constant integer arguments (excluding
493 // "this"), grouped by argument list.
494 std::map<std::vector<uint64_t>, CallSiteInfo> ConstCSInfo;
495
496 void addCallSite(Value *VTable, CallBase &CB, unsigned *NumUnsafeUses);
497
498private:
499 CallSiteInfo &findCallSiteInfo(CallBase &CB);
500};
501
502CallSiteInfo &VTableSlotInfo::findCallSiteInfo(CallBase &CB) {
503 std::vector<uint64_t> Args;
504 auto *CBType = dyn_cast<IntegerType>(CB.getType());
505 if (!CBType || CBType->getBitWidth() > 64 || CB.arg_empty())
506 return CSInfo;
507 for (auto &&Arg : drop_begin(CB.args())) {
508 auto *CI = dyn_cast<ConstantInt>(Arg);
509 if (!CI || CI->getBitWidth() > 64)
510 return CSInfo;
511 Args.push_back(CI->getZExtValue());
512 }
513 return ConstCSInfo[Args];
514}
515
516void VTableSlotInfo::addCallSite(Value *VTable, CallBase &CB,
517 unsigned *NumUnsafeUses) {
518 auto &CSI = findCallSiteInfo(CB);
519 CSI.AllCallSitesDevirted = false;
520 CSI.CallSites.push_back({VTable, CB, NumUnsafeUses});
521}
522
523struct DevirtModule {
524 const IPOOptions &Opts;
525 Module &M;
528
529 ModuleSummaryIndex *const ExportSummary;
530 const ModuleSummaryIndex *const ImportSummary;
531
532 IntegerType *const Int8Ty;
533 PointerType *const Int8PtrTy;
534 IntegerType *const Int32Ty;
535 IntegerType *const Int64Ty;
536 IntegerType *const IntPtrTy;
537 /// Sizeless array type, used for imported vtables. This provides a signal
538 /// to analyzers that these imports may alias, as they do for example
539 /// when multiple unique return values occur in the same vtable.
540 ArrayType *const Int8Arr0Ty;
541
542 const bool RemarksEnabled;
543 std::function<OptimizationRemarkEmitter &(Function &)> OREGetter;
544 MapVector<VTableSlot, VTableSlotInfo> CallSlots;
545
546 // Calls that have already been optimized. We may add a call to multiple
547 // VTableSlotInfos if vtable loads are coalesced and need to make sure not to
548 // optimize a call more than once.
549 SmallPtrSet<CallBase *, 8> OptimizedCalls;
550
551 // Store calls that had their ptrauth bundle removed. They are to be deleted
552 // at the end of the optimization.
553 SmallVector<CallBase *, 8> CallsWithPtrAuthBundleRemoved;
554
555 // This map keeps track of the number of "unsafe" uses of a loaded function
556 // pointer. The key is the associated llvm.type.test intrinsic call generated
557 // by this pass. An unsafe use is one that calls the loaded function pointer
558 // directly. Every time we eliminate an unsafe use (for example, by
559 // devirtualizing it or by applying virtual constant propagation), we
560 // decrement the value stored in this map. If a value reaches zero, we can
561 // eliminate the type check by RAUWing the associated llvm.type.test call with
562 // true.
563 std::map<CallInst *, unsigned> NumUnsafeUsesForTypeTest;
564 PatternList FunctionsToSkip;
565
566 const bool DevirtSpeculatively;
567 DevirtModule(Module &M, ModuleAnalysisManager &MAM,
568 ModuleSummaryIndex *ExportSummary,
569 const ModuleSummaryIndex *ImportSummary,
570 bool DevirtSpeculatively)
571 : Opts(getIPOOptions(M)), M(M), MAM(MAM),
572 FAM(MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager()),
573 ExportSummary(ExportSummary), ImportSummary(ImportSummary),
574 Int8Ty(Type::getInt8Ty(M.getContext())),
575 Int8PtrTy(PointerType::getUnqual(M.getContext())),
576 Int32Ty(Type::getInt32Ty(M.getContext())),
577 Int64Ty(Type::getInt64Ty(M.getContext())),
578 IntPtrTy(M.getDataLayout().getIntPtrType(M.getContext(), 0)),
579 Int8Arr0Ty(ArrayType::get(Type::getInt8Ty(M.getContext()), 0)),
580 RemarksEnabled(areRemarksEnabled()),
581 OREGetter([&](Function &F) -> OptimizationRemarkEmitter & {
582 return FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
583 }),
584 DevirtSpeculatively(DevirtSpeculatively) {
585 assert(!(ExportSummary && ImportSummary));
586 FunctionsToSkip.init(SkipFunctionNames);
587 }
588
589 bool areRemarksEnabled();
590
591 void
592 scanTypeTestUsers(Function *TypeTestFunc,
593 DenseMap<Metadata *, std::set<TypeMemberInfo>> &TypeIdMap);
594 void scanTypeCheckedLoadUsers(Function *TypeCheckedLoadFunc);
595
596 void buildTypeIdentifierMap(
597 std::vector<VTableBits> &Bits,
598 DenseMap<Metadata *, std::set<TypeMemberInfo>> &TypeIdMap);
599
600 bool
601 tryFindVirtualCallTargets(std::vector<VirtualCallTarget> &TargetsForSlot,
602 const std::set<TypeMemberInfo> &TypeMemberInfos,
603 uint64_t ByteOffset,
604 ModuleSummaryIndex *ExportSummary);
605
606 void applySingleImplDevirt(VTableSlotInfo &SlotInfo, Constant *TheFn,
607 bool &IsExported);
608 bool trySingleImplDevirt(ModuleSummaryIndex *ExportSummary,
610 VTableSlotInfo &SlotInfo,
611 WholeProgramDevirtResolution *Res);
612
613 void applyICallBranchFunnel(VTableSlotInfo &SlotInfo, Function &JT,
614 bool &IsExported);
615 void tryICallBranchFunnel(MutableArrayRef<VirtualCallTarget> TargetsForSlot,
616 VTableSlotInfo &SlotInfo,
617 WholeProgramDevirtResolution *Res, VTableSlot Slot);
618
619 bool tryEvaluateFunctionsWithArgs(
621 ArrayRef<uint64_t> Args);
622
623 void applyUniformRetValOpt(CallSiteInfo &CSInfo, StringRef FnName,
624 uint64_t TheRetVal);
625 bool tryUniformRetValOpt(MutableArrayRef<VirtualCallTarget> TargetsForSlot,
626 CallSiteInfo &CSInfo,
627 WholeProgramDevirtResolution::ByArg *Res);
628
629 // Returns the global symbol name that is used to export information about the
630 // given vtable slot and list of arguments.
631 std::string getGlobalName(VTableSlot Slot, ArrayRef<uint64_t> Args,
632 StringRef Name);
633
634 bool shouldExportConstantsAsAbsoluteSymbols();
635
636 // This function is called during the export phase to create a symbol
637 // definition containing information about the given vtable slot and list of
638 // arguments.
639 void exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args, StringRef Name,
640 Constant *C);
641 void exportConstant(VTableSlot Slot, ArrayRef<uint64_t> Args, StringRef Name,
642 uint32_t Const, uint32_t &Storage);
643
644 // This function is called during the import phase to create a reference to
645 // the symbol definition created during the export phase.
646 Constant *importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
647 StringRef Name);
648 Constant *importConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
649 StringRef Name, IntegerType *IntTy,
650 uint32_t Storage);
651
652 Constant *getMemberAddr(const TypeMemberInfo *M);
653
654 void applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName, bool IsOne,
655 Constant *UniqueMemberAddr);
656 bool tryUniqueRetValOpt(unsigned BitWidth,
658 CallSiteInfo &CSInfo,
659 WholeProgramDevirtResolution::ByArg *Res,
660 VTableSlot Slot, ArrayRef<uint64_t> Args);
661
662 void applyVirtualConstProp(CallSiteInfo &CSInfo, StringRef FnName,
663 Constant *Byte, Constant *Bit);
664 bool tryVirtualConstProp(MutableArrayRef<VirtualCallTarget> TargetsForSlot,
665 VTableSlotInfo &SlotInfo,
666 WholeProgramDevirtResolution *Res, VTableSlot Slot);
667
668 void rebuildGlobal(VTableBits &B);
669
670 // Apply the summary resolution for Slot to all virtual calls in SlotInfo.
671 void importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo);
672
673 // If we were able to eliminate all unsafe uses for a type checked load,
674 // eliminate the associated type tests by replacing them with true.
675 void removeRedundantTypeTests();
676
677 bool run();
678
679 // Look up the corresponding ValueInfo entry of `TheFn` in `ExportSummary`.
680 //
681 // Caller guarantees that `ExportSummary` is not nullptr.
682 static ValueInfo lookUpFunctionValueInfo(Function *TheFn,
683 ModuleSummaryIndex *ExportSummary);
684
685 // Returns true if the function definition must be unreachable.
686 //
687 // Note if this helper function returns true, `F` is guaranteed
688 // to be unreachable; if it returns false, `F` might still
689 // be unreachable but not covered by this helper function.
690 //
691 // Implementation-wise, if function definition is present, IR is analyzed; if
692 // not, look up function flags from ExportSummary as a fallback.
693 static bool mustBeUnreachableFunction(Function *const F,
694 ModuleSummaryIndex *ExportSummary);
695
696 // Lower the module using the action and summary passed as command line
697 // arguments. For testing purposes only.
698 static bool runForTesting(Module &M, ModuleAnalysisManager &MAM);
699};
700
701struct DevirtIndex {
702 ModuleSummaryIndex &ExportSummary;
703 // The set in which to record GUIDs exported from their module by
704 // devirtualization, used by client to ensure they are not internalized.
705 std::set<GlobalValue::GUID> &ExportedGUIDs;
706 // A map in which to record the information necessary to locate the WPD
707 // resolution for local targets in case they are exported by cross module
708 // importing.
709 std::map<ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap;
710 // We have hardcoded the promoted and renamed function name in the WPD
711 // summary, so we need to ensure that they will be renamed. Note this and
712 // that adding the current names to this set ensures we continue to rename
713 // them.
714 DenseSet<StringRef> *ExternallyVisibleSymbolNamesPtr;
715
716 MapVector<VTableSlotSummary, VTableSlotInfo> CallSlots;
717
718 PatternList FunctionsToSkip;
719
720 DevirtIndex(
721 ModuleSummaryIndex &ExportSummary,
722 std::set<GlobalValue::GUID> &ExportedGUIDs,
723 std::map<ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap,
724 DenseSet<StringRef> *ExternallyVisibleSymbolNamesPtr)
725 : ExportSummary(ExportSummary), ExportedGUIDs(ExportedGUIDs),
726 LocalWPDTargetsMap(LocalWPDTargetsMap),
727 ExternallyVisibleSymbolNamesPtr(ExternallyVisibleSymbolNamesPtr) {
728 FunctionsToSkip.init(SkipFunctionNames);
729 }
730
731 bool tryFindVirtualCallTargets(std::vector<ValueInfo> &TargetsForSlot,
732 const TypeIdCompatibleVtableInfo TIdInfo,
733 uint64_t ByteOffset);
734
735 bool trySingleImplDevirt(MutableArrayRef<ValueInfo> TargetsForSlot,
736 VTableSlotSummary &SlotSummary,
737 VTableSlotInfo &SlotInfo,
738 WholeProgramDevirtResolution *Res,
739 std::set<ValueInfo> &DevirtTargets);
740
741 void run();
742};
743} // end anonymous namespace
744
747 if (UseCommandLine) {
748 if (!DevirtModule::runForTesting(M, MAM))
749 return PreservedAnalyses::all();
751 }
752
753 std::optional<ModuleSummaryIndex> Index;
755 // Build the ExportSummary from the module.
757 "ExportSummary is expected to be empty in non-LTO mode");
758 ProfileSummaryInfo PSI(M);
759 Index.emplace(buildModuleSummaryIndex(M, nullptr, &PSI));
760 ExportSummary = Index.has_value() ? &Index.value() : nullptr;
761 }
762 if (!DevirtModule(M, MAM, ExportSummary, ImportSummary, DevirtSpeculatively)
763 .run())
764 return PreservedAnalyses::all();
766}
767
768// Enable whole program visibility if enabled by client (e.g. linker) or
769// internal option, and not force disabled.
770bool llvm::hasWholeProgramVisibility(bool WholeProgramVisibilityEnabledInLTO) {
771 return (WholeProgramVisibilityEnabledInLTO || WholeProgramVisibility) &&
773}
774
775static bool
777 function_ref<bool(StringRef)> IsVisibleToRegularObj) {
778 // TypeID for member function pointer type is an internal construct
779 // and won't exist in IsVisibleToRegularObj. The full TypeID
780 // will be present and participate in invalidation.
781 if (TypeID.ends_with(".virtual"))
782 return false;
783
784 // TypeID that doesn't start with Itanium mangling (_ZTS) will be
785 // non-externally visible types which cannot interact with
786 // external native files. See CodeGenModule::CreateMetadataIdentifierImpl.
787 if (!TypeID.consume_front("_ZTS"))
788 return false;
789
790 // TypeID is keyed off the type name symbol (_ZTS). However, the native
791 // object may not contain this symbol if it does not contain a key
792 // function for the base type and thus only contains a reference to the
793 // type info (_ZTI). To catch this case we query using the type info
794 // symbol corresponding to the TypeID.
795 std::string TypeInfo = ("_ZTI" + TypeID).str();
796 return IsVisibleToRegularObj(TypeInfo);
797}
798
799static bool
801 function_ref<bool(StringRef)> IsVisibleToRegularObj) {
803 GV.getMetadata(LLVMContext::MD_type, Types);
804
805 for (auto *Type : Types)
806 if (auto *TypeID = dyn_cast<MDString>(Type->getOperand(1).get()))
807 return typeIDVisibleToRegularObj(TypeID->getString(),
808 IsVisibleToRegularObj);
809
810 return false;
811}
812
813/// If whole program visibility asserted, then upgrade all public vcall
814/// visibility metadata on vtable definitions to linkage unit visibility in
815/// Module IR (for regular or hybrid LTO).
817 Module &M, bool WholeProgramVisibilityEnabledInLTO,
818 const DenseSet<GlobalValue::GUID> &DynamicExportSymbols,
819 bool ValidateAllVtablesHaveTypeInfos,
820 function_ref<bool(StringRef)> IsVisibleToRegularObj) {
821 if (!hasWholeProgramVisibility(WholeProgramVisibilityEnabledInLTO))
822 return;
823
824 for (GlobalVariable &GV : M.globals()) {
825 // Add linkage unit visibility to any variable with type metadata, which are
826 // the vtable definitions. We won't have an existing vcall_visibility
827 // metadata on vtable definitions with public visibility.
828 if (GV.hasMetadata(LLVMContext::MD_type) &&
830 // Don't upgrade the visibility for symbols exported to the dynamic
831 // linker, as we have no information on their eventual use.
832 !DynamicExportSymbols.count(GV.getGUID()) &&
833 // With validation enabled, we want to exclude symbols visible to
834 // regular objects. Local symbols will be in this group due to the
835 // current implementation but those with VCallVisibilityTranslationUnit
836 // will have already been marked in clang so are unaffected.
837 !(ValidateAllVtablesHaveTypeInfos &&
838 skipUpdateDueToValidation(GV, IsVisibleToRegularObj)))
840 }
841}
842
844 bool WholeProgramVisibilityEnabledInLTO) {
845 llvm::TimeTraceScope timeScope("Update public type test calls");
846 Function *PublicTypeTestFunc =
847 Intrinsic::getDeclarationIfExists(&M, Intrinsic::public_type_test);
848 if (!PublicTypeTestFunc)
849 return;
850 if (hasWholeProgramVisibility(WholeProgramVisibilityEnabledInLTO)) {
851 Function *TypeTestFunc =
852 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::type_test);
853 for (Use &U : make_early_inc_range(PublicTypeTestFunc->uses())) {
854 auto *CI = cast<CallInst>(U.getUser());
855 auto *NewCI = CallInst::Create(
856 TypeTestFunc, {CI->getArgOperand(0), CI->getArgOperand(1)}, {}, "",
857 CI->getIterator());
858 CI->replaceAllUsesWith(NewCI);
859 CI->eraseFromParent();
860 }
861 } else {
862 // TODO: Don't replace public type tests when speculative devirtualization
863 // gets enabled in LTO mode.
864 auto *True = ConstantInt::getTrue(M.getContext());
865 for (Use &U : make_early_inc_range(PublicTypeTestFunc->uses())) {
866 auto *CI = cast<CallInst>(U.getUser());
867 CI->replaceAllUsesWith(True);
868 CI->eraseFromParent();
869 }
870 }
871}
872
873/// Based on typeID string, get all associated vtable GUIDS that are
874/// visible to regular objects.
876 ModuleSummaryIndex &Index,
877 DenseSet<GlobalValue::GUID> &VisibleToRegularObjSymbols,
878 function_ref<bool(StringRef)> IsVisibleToRegularObj) {
879 for (const auto &TypeID : Index.typeIdCompatibleVtableMap()) {
880 if (typeIDVisibleToRegularObj(TypeID.first, IsVisibleToRegularObj))
881 for (const TypeIdOffsetVtableInfo &P : TypeID.second)
882 VisibleToRegularObjSymbols.insert(P.VTableVI.getGUID());
883 }
884}
885
886/// If whole program visibility asserted, then upgrade all public vcall
887/// visibility metadata on vtable definition summaries to linkage unit
888/// visibility in Module summary index (for ThinLTO).
890 ModuleSummaryIndex &Index, bool WholeProgramVisibilityEnabledInLTO,
891 const DenseSet<GlobalValue::GUID> &DynamicExportSymbols,
892 const DenseSet<GlobalValue::GUID> &VisibleToRegularObjSymbols) {
893 if (!hasWholeProgramVisibility(WholeProgramVisibilityEnabledInLTO))
894 return;
895 for (auto &P : Index) {
896 // Don't upgrade the visibility for symbols exported to the dynamic
897 // linker, as we have no information on their eventual use.
898 if (DynamicExportSymbols.count(P.first))
899 continue;
900 // With validation enabled, we want to exclude symbols visible to regular
901 // objects. Local symbols will be in this group due to the current
902 // implementation but those with VCallVisibilityTranslationUnit will have
903 // already been marked in clang so are unaffected.
904 if (VisibleToRegularObjSymbols.count(P.first))
905 continue;
906 for (auto &S : P.second.getSummaryList()) {
907 auto *GVar = dyn_cast<GlobalVarSummary>(S.get());
908 if (!GVar ||
909 GVar->getVCallVisibility() != GlobalObject::VCallVisibilityPublic)
910 continue;
911 GVar->setVCallVisibility(GlobalObject::VCallVisibilityLinkageUnit);
912 }
913 }
914}
915
917 ModuleSummaryIndex &Summary, std::set<GlobalValue::GUID> &ExportedGUIDs,
918 std::map<ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap,
919 DenseSet<StringRef> *ExternallyVisibleSymbolNamesPtr) {
920 DevirtIndex(Summary, ExportedGUIDs, LocalWPDTargetsMap,
921 ExternallyVisibleSymbolNamesPtr)
922 .run();
923}
924
926 ModuleSummaryIndex &Summary,
927 function_ref<bool(StringRef, ValueInfo)> IsExported,
928 std::map<ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap,
929 DenseSet<StringRef> *ExternallyVisibleSymbolNamesPtr) {
930 for (auto &T : LocalWPDTargetsMap) {
931 auto &VI = T.first;
932 // This was enforced earlier during trySingleImplDevirt.
933 assert(VI.getSummaryList().size() == 1 &&
934 "Devirt of local target has more than one copy");
935 auto &S = VI.getSummaryList()[0];
936 if (!IsExported(S->modulePath(), VI))
937 continue;
938
939 // It's been exported by a cross module import.
940 for (auto &SlotSummary : T.second) {
941 auto *TIdSum = Summary.getTypeIdSummary(SlotSummary.TypeID);
942 assert(TIdSum);
943 auto WPDRes = TIdSum->WPDRes.find(SlotSummary.ByteOffset);
944 assert(WPDRes != TIdSum->WPDRes.end());
945 if (ExternallyVisibleSymbolNamesPtr)
946 ExternallyVisibleSymbolNamesPtr->insert(WPDRes->second.SingleImplName);
947 WPDRes->second.SingleImplName = ModuleSummaryIndex::getGlobalNameForLocal(
948 WPDRes->second.SingleImplName,
949 Summary.getModuleHash(S->modulePath()));
950 }
951 }
952}
953
954static Error checkCombinedSummaryForTesting(const IPOOptions &Opts,
955 ModuleSummaryIndex *Summary) {
956 // Check that summary index contains regular LTO module when performing
957 // export to prevent occasional use of index from pure ThinLTO compilation
958 // (-fno-split-lto-module). This kind of summary index is passed to
959 // DevirtIndex::run, not to DevirtModule::run used by opt/runForTesting.
960 const auto &ModPaths = Summary->modulePaths();
961 if (Opts.wholeprogramdevirt_summary_action != PassSummaryAction::Import &&
963 return createStringError(
965 "combined summary should contain Regular LTO module");
966 return ErrorSuccess();
967}
968
969bool DevirtModule::runForTesting(Module &M, ModuleAnalysisManager &MAM) {
970 const IPOOptions &Opts = getIPOOptions(M);
971 StringRef ReadSummary = Opts.wholeprogramdevirt_read_summary;
972 StringRef WriteSummary = Opts.wholeprogramdevirt_write_summary;
973 PassSummaryAction SummaryAction = Opts.wholeprogramdevirt_summary_action;
974 std::unique_ptr<ModuleSummaryIndex> Summary =
975 std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
976
977 // Handle the command-line summary arguments. This code is for testing
978 // purposes only, so we handle errors directly.
979 if (!ReadSummary.empty()) {
980 ExitOnError ExitOnErr(
981 ("-wholeprogramdevirt-read-summary: " + ReadSummary + ": ").str());
982 auto ReadSummaryFile =
983 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(ReadSummary)));
984 if (Expected<std::unique_ptr<ModuleSummaryIndex>> SummaryOrErr =
985 getModuleSummaryIndex(*ReadSummaryFile)) {
986 Summary = std::move(*SummaryOrErr);
987 ExitOnErr(checkCombinedSummaryForTesting(Opts, Summary.get()));
988 } else {
989 // Try YAML if we've failed with bitcode.
990 consumeError(SummaryOrErr.takeError());
991 yaml::Input In(ReadSummaryFile->getBuffer());
992 In >> *Summary;
993 ExitOnErr(errorCodeToError(In.error()));
994 }
995 }
996
997 bool Changed =
998 DevirtModule(
999 M, MAM,
1000 SummaryAction == PassSummaryAction::Export ? Summary.get() : nullptr,
1001 SummaryAction == PassSummaryAction::Import ? Summary.get() : nullptr,
1002 Opts.devirtualize_speculatively)
1003 .run();
1004
1005 if (!WriteSummary.empty()) {
1006 ExitOnError ExitOnErr(
1007 ("-wholeprogramdevirt-write-summary: " + WriteSummary + ": ").str());
1008 std::error_code EC;
1009 if (WriteSummary.ends_with(".bc")) {
1010 raw_fd_ostream OS(WriteSummary, EC, sys::fs::OF_None);
1011 ExitOnErr(errorCodeToError(EC));
1012 writeIndexToFile(*Summary, OS);
1013 } else {
1014 raw_fd_ostream OS(WriteSummary, EC, sys::fs::OF_TextWithCRLF);
1015 ExitOnErr(errorCodeToError(EC));
1016 yaml::Output Out(OS);
1017 Out << *Summary;
1018 }
1019 }
1020
1021 return Changed;
1022}
1023
1024void DevirtModule::buildTypeIdentifierMap(
1025 std::vector<VTableBits> &Bits,
1026 DenseMap<Metadata *, std::set<TypeMemberInfo>> &TypeIdMap) {
1027 DenseMap<GlobalVariable *, VTableBits *> GVToBits;
1028 Bits.reserve(M.global_size());
1030 for (GlobalVariable &GV : M.globals()) {
1031 Types.clear();
1032 GV.getMetadata(LLVMContext::MD_type, Types);
1033 if (GV.isDeclaration() || Types.empty())
1034 continue;
1035
1036 VTableBits *&BitsPtr = GVToBits[&GV];
1037 if (!BitsPtr) {
1038 Bits.emplace_back();
1039 Bits.back().GV = &GV;
1040 Bits.back().ObjectSize =
1041 M.getDataLayout().getTypeAllocSize(GV.getInitializer()->getType());
1042 BitsPtr = &Bits.back();
1043 }
1044
1045 for (MDNode *Type : Types) {
1046 auto *TypeID = Type->getOperand(1).get();
1047
1050 cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
1051 ->getZExtValue();
1052
1053 TypeIdMap[TypeID].insert({BitsPtr, Offset});
1054 }
1055 }
1056}
1057
1058bool DevirtModule::tryFindVirtualCallTargets(
1059 std::vector<VirtualCallTarget> &TargetsForSlot,
1060 const std::set<TypeMemberInfo> &TypeMemberInfos, uint64_t ByteOffset,
1061 ModuleSummaryIndex *ExportSummary) {
1062 for (const TypeMemberInfo &TM : TypeMemberInfos) {
1063 if (!TM.Bits->GV->isConstant())
1064 return false;
1065
1066 // Without DevirtSpeculatively, we cannot perform whole program
1067 // devirtualization analysis on a vtable with public LTO visibility.
1068 if (!DevirtSpeculatively && TM.Bits->GV->getVCallVisibility() ==
1070 return false;
1071
1072 // A local vtable without live uses cannot be loaded from, so it does not
1073 // provide a call target.
1074 if (TM.Bits->GV->hasLocalLinkage() && TM.Bits->GV->hasZeroLiveUses())
1075 continue;
1076
1077 Function *Fn = nullptr;
1078 Constant *C = nullptr;
1079 std::tie(Fn, C) =
1080 getFunctionAtVTableOffset(TM.Bits->GV, TM.Offset + ByteOffset, M);
1081
1082 if (!Fn)
1083 return false;
1084
1085 if (FunctionsToSkip.match(Fn->getName()))
1086 return false;
1087
1088 // We can disregard __cxa_pure_virtual as a possible call target, as
1089 // calls to pure virtuals are UB.
1090 if (Fn->getName() == "__cxa_pure_virtual")
1091 continue;
1092
1093 // In most cases empty functions will be overridden by the
1094 // implementation of the derived class, so we can skip them.
1095 if (DevirtSpeculatively && Fn->getReturnType()->isVoidTy() &&
1096 Fn->getInstructionCount() <= 1)
1097 continue;
1098
1099 // We can disregard unreachable functions as possible call targets, as
1100 // unreachable functions shouldn't be called.
1101 if (mustBeUnreachableFunction(Fn, ExportSummary))
1102 continue;
1103
1104 // Save the symbol used in the vtable to use as the devirtualization
1105 // target.
1106 auto *GV = dyn_cast<GlobalValue>(C);
1107 assert(GV);
1108 if (auto *GA = dyn_cast<GlobalAlias>(GV))
1109 if (!GA->isInterposable() && !GA->getAliaseeObject()->isInterposable())
1110 GV = GA->getAliaseeObject();
1111 TargetsForSlot.push_back({GV, &TM});
1112 }
1113
1114 // Give up if we couldn't find any targets.
1115 return !TargetsForSlot.empty();
1116}
1117
1118bool DevirtIndex::tryFindVirtualCallTargets(
1119 std::vector<ValueInfo> &TargetsForSlot,
1120 const TypeIdCompatibleVtableInfo TIdInfo, uint64_t ByteOffset) {
1121 for (const TypeIdOffsetVtableInfo &P : TIdInfo) {
1122 // Find a representative copy of the vtable initializer.
1123 // We can have multiple available_externally, linkonce_odr and weak_odr
1124 // vtable initializers. We can also have multiple external vtable
1125 // initializers in the case of comdats, which we cannot check here.
1126 // The linker should give an error in this case.
1127 //
1128 // Also, handle the case of same-named local Vtables with the same path
1129 // and therefore the same GUID. This can happen if there isn't enough
1130 // distinguishing path when compiling the source file. In that case we
1131 // conservatively return false early.
1132 if (P.VTableVI.hasLocal() && P.VTableVI.getSummaryList().size() > 1)
1133 return false;
1134 const GlobalVarSummary *VS = nullptr;
1135 for (const auto &S : P.VTableVI.getSummaryList()) {
1136 auto *CurVS = cast<GlobalVarSummary>(S->getBaseObject());
1137 if (!CurVS->vTableFuncs().empty() ||
1138 // Previously clang did not attach the necessary type metadata to
1139 // available_externally vtables, in which case there would not
1140 // be any vtable functions listed in the summary and we need
1141 // to treat this case conservatively (in case the bitcode is old).
1142 // However, we will also not have any vtable functions in the
1143 // case of a pure virtual base class. In that case we do want
1144 // to set VS to avoid treating it conservatively.
1146 VS = CurVS;
1147 // We cannot perform whole program devirtualization analysis on a vtable
1148 // with public LTO visibility.
1149 if (VS->getVCallVisibility() == GlobalObject::VCallVisibilityPublic)
1150 return false;
1151 break;
1152 }
1153 }
1154 // There will be no VS if all copies are available_externally having no
1155 // type metadata. In that case we can't safely perform WPD.
1156 if (!VS)
1157 return false;
1158 if (!VS->isLive())
1159 continue;
1160 for (auto VTP : VS->vTableFuncs()) {
1161 if (VTP.VTableOffset != P.AddressPointOffset + ByteOffset)
1162 continue;
1163
1164 if (mustBeUnreachableFunction(VTP.FuncVI))
1165 continue;
1166
1167 TargetsForSlot.push_back(VTP.FuncVI);
1168 }
1169 }
1170
1171 // Give up if we couldn't find any targets.
1172 return !TargetsForSlot.empty();
1173}
1174
1175void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
1176 Constant *TheFn, bool &IsExported) {
1177 // Don't devirtualize function if we're told to skip it
1178 // in -wholeprogramdevirt-skip.
1179 if (FunctionsToSkip.match(TheFn->stripPointerCasts()->getName()))
1180 return;
1181 auto Apply = [&](CallSiteInfo &CSInfo) {
1182 for (auto &&VCallSite : CSInfo.CallSites) {
1183 if (!OptimizedCalls.insert(&VCallSite.CB).second)
1184 continue;
1185
1186 // Stop when the number of devirted calls reaches the cutoff.
1187 if (!DebugCounter::shouldExecute(CallsToDevirt))
1188 continue;
1189
1190 if (RemarksEnabled)
1191 VCallSite.emitRemark("single-impl",
1192 TheFn->stripPointerCasts()->getName(), OREGetter);
1193 NumSingleImpl++;
1194 auto &CB = VCallSite.CB;
1195 assert(!CB.getCalledFunction() && "devirtualizing direct call?");
1196 IRBuilder<> Builder(&CB);
1197 Value *Callee =
1198 Builder.CreateBitCast(TheFn, CB.getCalledOperand()->getType());
1199
1200 // If trap checking is enabled, add support to compare the virtual
1201 // function pointer to the devirtualized target. In case of a mismatch,
1202 // perform a debug trap.
1203 if (Opts.wholeprogramdevirt_check == WPDCheckMode::Trap) {
1204 auto *Cond = Builder.CreateICmpNE(CB.getCalledOperand(), Callee);
1206 Cond, &CB, /*Unreachable=*/false,
1207 MDBuilder(M.getContext()).createUnlikelyBranchWeights());
1208 Builder.SetInsertPoint(ThenTerm);
1209 Function *TrapFn =
1210 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::debugtrap);
1211 auto *CallTrap = Builder.CreateCall(TrapFn);
1212 CallTrap->setDebugLoc(CB.getDebugLoc());
1213 }
1214
1215 // If fallback checking or speculative devirtualization are enabled,
1216 // add support to compare the virtual function pointer to the
1217 // devirtualized target. In case of a mismatch, fall back to indirect
1218 // call.
1219 if (Opts.wholeprogramdevirt_check == WPDCheckMode::Fallback ||
1220 DevirtSpeculatively) {
1221 MDNode *Weights = MDBuilder(M.getContext()).createLikelyBranchWeights();
1222 // Version the indirect call site. If the called value is equal to the
1223 // given callee, 'NewInst' will be executed, otherwise the original call
1224 // site will be executed.
1225 CallBase &NewInst = versionCallSite(CB, Callee, Weights);
1226 NewInst.setCalledOperand(Callee);
1227 // Since the new call site is direct, we must clear metadata that
1228 // is only appropriate for indirect calls. This includes !prof and
1229 // !callees metadata.
1230 NewInst.setMetadata(LLVMContext::MD_prof, nullptr);
1231 NewInst.setMetadata(LLVMContext::MD_callees, nullptr);
1232 // Additionally, we should remove them from the fallback indirect call,
1233 // so that we don't attempt to perform indirect call promotion later.
1234 CB.setMetadata(LLVMContext::MD_prof, nullptr);
1235 CB.setMetadata(LLVMContext::MD_callees, nullptr);
1236 }
1237
1238 // In either trapping or non-checking mode, devirtualize original call.
1239 else {
1240 // Devirtualize unconditionally.
1241 CB.setCalledOperand(Callee);
1242 // Since the call site is now direct, we must clear metadata that
1243 // is only appropriate for indirect calls. This includes !prof and
1244 // !callees metadata.
1245 CB.setMetadata(LLVMContext::MD_prof, nullptr);
1246 CB.setMetadata(LLVMContext::MD_callees, nullptr);
1247 if (CB.getCalledOperand() &&
1249 auto *NewCS = CallBase::removeOperandBundle(
1251 CB.replaceAllUsesWith(NewCS);
1252 // Schedule for deletion at the end of pass run.
1253 CallsWithPtrAuthBundleRemoved.push_back(&CB);
1254 }
1255 }
1256
1257 // This use is no longer unsafe.
1258 if (VCallSite.NumUnsafeUses)
1259 --*VCallSite.NumUnsafeUses;
1260 }
1261 if (CSInfo.isExported())
1262 IsExported = true;
1263 CSInfo.markDevirt();
1264 };
1265 Apply(SlotInfo.CSInfo);
1266 for (auto &P : SlotInfo.ConstCSInfo)
1267 Apply(P.second);
1268}
1269
1270static bool addCalls(VTableSlotInfo &SlotInfo, const ValueInfo &Callee) {
1271 // We can't add calls if we haven't seen a definition
1272 if (Callee.getSummaryList().empty())
1273 return false;
1274
1275 // Insert calls into the summary index so that the devirtualized targets
1276 // are eligible for import.
1277 // FIXME: Annotate type tests with hotness. For now, mark these as hot
1278 // to better ensure we have the opportunity to inline them.
1279 bool IsExported = false;
1280 auto &S = Callee.getSummaryList()[0];
1281 CalleeInfo CI(CalleeInfo::HotnessType::Hot, /* HasTailCall = */ false);
1282 auto AddCalls = [&](CallSiteInfo &CSInfo) {
1283 for (auto *FS : CSInfo.SummaryTypeCheckedLoadUsers) {
1284 FS->addCall({Callee, CI});
1285 IsExported |= S->modulePath() != FS->modulePath();
1286 }
1287 for (auto *FS : CSInfo.SummaryTypeTestAssumeUsers) {
1288 FS->addCall({Callee, CI});
1289 IsExported |= S->modulePath() != FS->modulePath();
1290 }
1291 };
1292 AddCalls(SlotInfo.CSInfo);
1293 for (auto &P : SlotInfo.ConstCSInfo)
1294 AddCalls(P.second);
1295 return IsExported;
1296}
1297
1298bool DevirtModule::trySingleImplDevirt(
1299 ModuleSummaryIndex *ExportSummary,
1300 MutableArrayRef<VirtualCallTarget> TargetsForSlot, VTableSlotInfo &SlotInfo,
1301 WholeProgramDevirtResolution *Res) {
1302 // See if the program contains a single implementation of this virtual
1303 // function.
1304 auto *TheFn = TargetsForSlot[0].Fn;
1305 for (auto &&Target : TargetsForSlot)
1306 if (TheFn != Target.Fn)
1307 return false;
1308
1309 // If so, update each call site to call that implementation directly.
1310 if (RemarksEnabled || AreStatisticsEnabled())
1311 TargetsForSlot[0].WasDevirt = true;
1312
1313 bool IsExported = false;
1314 applySingleImplDevirt(SlotInfo, TheFn, IsExported);
1315 if (!IsExported)
1316 return false;
1317
1318 // If the only implementation has local linkage, we must promote to external
1319 // to make it visible to thin LTO objects. We can only get here during the
1320 // ThinLTO export phase.
1321 if (TheFn->hasLocalLinkage()) {
1322 std::string NewName = (TheFn->getName() + ".llvm.merged").str();
1323
1324 // Since we are renaming the function, any comdats with the same name must
1325 // also be renamed. This is required when targeting COFF, as the comdat name
1326 // must match one of the names of the symbols in the comdat.
1327 if (Comdat *C = TheFn->getComdat()) {
1328 if (C->getName() == TheFn->getName()) {
1329 Comdat *NewC = M.getOrInsertComdat(NewName);
1330 NewC->setSelectionKind(C->getSelectionKind());
1331 for (GlobalObject &GO : M.global_objects())
1332 if (GO.getComdat() == C)
1333 GO.setComdat(NewC);
1334 }
1335 }
1336
1337 TheFn->setLinkage(GlobalValue::ExternalLinkage);
1338 TheFn->setVisibility(GlobalValue::HiddenVisibility);
1339 TheFn->setName(NewName);
1340 }
1341 if (ValueInfo TheFnVI = ExportSummary->getValueInfo(TheFn->getGUID()))
1342 // Any needed promotion of 'TheFn' has already been done during
1343 // LTO unit split, so we can ignore return value of AddCalls.
1344 addCalls(SlotInfo, TheFnVI);
1345
1347 Res->SingleImplName = std::string(TheFn->getName());
1348
1349 return true;
1350}
1351
1352bool DevirtIndex::trySingleImplDevirt(MutableArrayRef<ValueInfo> TargetsForSlot,
1353 VTableSlotSummary &SlotSummary,
1354 VTableSlotInfo &SlotInfo,
1355 WholeProgramDevirtResolution *Res,
1356 std::set<ValueInfo> &DevirtTargets) {
1357 // See if the program contains a single implementation of this virtual
1358 // function.
1359 auto TheFn = TargetsForSlot[0];
1360 for (auto &&Target : TargetsForSlot)
1361 if (TheFn != Target)
1362 return false;
1363
1364 // Don't devirtualize if we don't have target definition.
1365 auto Size = TheFn.getSummaryList().size();
1366 if (!Size)
1367 return false;
1368
1369 // Don't devirtualize function if we're told to skip it
1370 // in -wholeprogramdevirt-skip.
1371 if (FunctionsToSkip.match(TheFn.name()))
1372 return false;
1373
1374 // If the summary list contains multiple summaries where at least one is
1375 // a local, give up, as we won't know which (possibly promoted) name to use.
1376 if (TheFn.hasLocal() && Size > 1)
1377 return false;
1378
1379 // Collect functions devirtualized at least for one call site for stats.
1381 DevirtTargets.insert(TheFn);
1382
1383 auto &S = TheFn.getSummaryList()[0];
1384 bool IsExported = addCalls(SlotInfo, TheFn);
1385 if (IsExported)
1386 ExportedGUIDs.insert(TheFn.getGUID());
1387
1388 // Record in summary for use in devirtualization during the ThinLTO import
1389 // step.
1391 if (GlobalValue::isLocalLinkage(S->linkage())) {
1392 if (IsExported) {
1393 // If target is a local function and we are exporting it by
1394 // devirtualizing a call in another module, we need to record the
1395 // promoted name.
1396 if (ExternallyVisibleSymbolNamesPtr)
1397 ExternallyVisibleSymbolNamesPtr->insert(TheFn.name());
1399 TheFn.name(), ExportSummary.getModuleHash(S->modulePath()));
1400 } else {
1401 LocalWPDTargetsMap[TheFn].push_back(SlotSummary);
1402 Res->SingleImplName = std::string(TheFn.name());
1403 }
1404 } else
1405 Res->SingleImplName = std::string(TheFn.name());
1406
1407 // Name will be empty if this thin link driven off of serialized combined
1408 // index (e.g. llvm-lto). However, WPD is not supported/invoked for the
1409 // legacy LTO API anyway.
1410 assert(!Res->SingleImplName.empty());
1411
1412 return true;
1413}
1414
1415void DevirtModule::tryICallBranchFunnel(
1416 MutableArrayRef<VirtualCallTarget> TargetsForSlot, VTableSlotInfo &SlotInfo,
1417 WholeProgramDevirtResolution *Res, VTableSlot Slot) {
1418 Triple T(M.getTargetTriple());
1419 if (T.getArch() != Triple::x86_64)
1420 return;
1421
1422 if (TargetsForSlot.size() > Opts.wholeprogramdevirt_branch_funnel_threshold)
1423 return;
1424
1425 bool HasNonDevirt = !SlotInfo.CSInfo.AllCallSitesDevirted;
1426 if (!HasNonDevirt)
1427 for (auto &P : SlotInfo.ConstCSInfo)
1428 if (!P.second.AllCallSitesDevirted) {
1429 HasNonDevirt = true;
1430 break;
1431 }
1432
1433 if (!HasNonDevirt)
1434 return;
1435
1436 // If any GV is AvailableExternally, not to generate branch.funnel.
1437 // NOTE: It is to avoid crash in LowerTypeTest.
1438 // If the branch.funnel is generated, because GV.isDeclarationForLinker(),
1439 // in LowerTypeTestsModule::lower(), its GlobalTypeMember would NOT
1440 // be saved in GlobalTypeMembers[&GV]. Then crash happens in
1441 // buildBitSetsFromDisjointSet due to GlobalTypeMembers[&GV] is NULL.
1442 // Even doing experiment to save it in GlobalTypeMembers[&GV] and
1443 // making GlobalTypeMembers[&GV] be not NULL, crash could avoid from
1444 // buildBitSetsFromDisjointSet. But still report_fatal_error in Verifier
1445 // or SelectionDAGBuilder later, because operands linkage type consistency
1446 // check of icall.branch.funnel can not pass.
1447 for (auto &T : TargetsForSlot) {
1448 if (T.TM->Bits->GV->hasAvailableExternallyLinkage())
1449 return;
1450 }
1451
1452 FunctionType *FT =
1453 FunctionType::get(Type::getVoidTy(M.getContext()), {Int8PtrTy}, true);
1454 Function *JT;
1455 if (isa<MDString>(Slot.TypeID)) {
1457 M.getDataLayout().getProgramAddressSpace(),
1458 getGlobalName(Slot, {}, "branch_funnel"), &M);
1460 } else {
1462 M.getDataLayout().getProgramAddressSpace(),
1463 "branch_funnel", &M);
1464 }
1465 JT->addParamAttr(0, Attribute::Nest);
1466
1467 std::vector<Value *> JTArgs;
1468 JTArgs.push_back(JT->arg_begin());
1469 for (auto &T : TargetsForSlot) {
1470 JTArgs.push_back(getMemberAddr(T.TM));
1471 JTArgs.push_back(T.Fn);
1472 }
1473
1474 BasicBlock *BB = BasicBlock::Create(M.getContext(), "", JT, nullptr);
1476 &M, llvm::Intrinsic::icall_branch_funnel, {});
1477
1478 auto *CI = CallInst::Create(Intr, JTArgs, "", BB);
1479 CI->setTailCallKind(CallInst::TCK_MustTail);
1480 ReturnInst::Create(M.getContext(), nullptr, BB);
1481
1482 bool IsExported = false;
1483 applyICallBranchFunnel(SlotInfo, *JT, IsExported);
1484 if (IsExported)
1486
1487 if (!JT->getEntryCount().has_value()) {
1488 // FIXME: we could pass through thinlto the necessary information.
1490 }
1491}
1492
1493void DevirtModule::applyICallBranchFunnel(VTableSlotInfo &SlotInfo,
1494 Function &JT, bool &IsExported) {
1495 DenseMap<Function *, double> FunctionEntryCounts;
1496 auto Apply = [&](CallSiteInfo &CSInfo) {
1497 if (CSInfo.isExported())
1498 IsExported = true;
1499 if (CSInfo.AllCallSitesDevirted)
1500 return;
1501
1502 std::map<CallBase *, CallBase *> CallBases;
1503 for (auto &&VCallSite : CSInfo.CallSites) {
1504 CallBase &CB = VCallSite.CB;
1505
1506 if (CallBases.find(&CB) != CallBases.end()) {
1507 // When finding devirtualizable calls, it's possible to find the same
1508 // vtable passed to multiple llvm.type.test or llvm.type.checked.load
1509 // calls, which can cause duplicate call sites to be recorded in
1510 // [Const]CallSites. If we've already found one of these
1511 // call instances, just ignore it. It will be replaced later.
1512 continue;
1513 }
1514
1515 // Jump tables are only profitable if the retpoline mitigation is enabled.
1516 Attribute FSAttr = CB.getCaller()->getFnAttribute("target-features");
1517 if (!FSAttr.isValid() ||
1518 !FSAttr.getValueAsString().contains("+retpoline"))
1519 continue;
1520
1521 NumBranchFunnel++;
1522 if (RemarksEnabled)
1523 VCallSite.emitRemark("branch-funnel", JT.getName(), OREGetter);
1524
1525 // Pass the address of the vtable in the nest register, which is r10 on
1526 // x86_64.
1527 std::vector<Type *> NewArgs;
1528 NewArgs.push_back(Int8PtrTy);
1529 append_range(NewArgs, CB.getFunctionType()->params());
1530 FunctionType *NewFT =
1532 CB.getFunctionType()->isVarArg());
1533 IRBuilder<> IRB(&CB);
1534 std::vector<Value *> Args;
1535 Args.push_back(VCallSite.VTable);
1536 llvm::append_range(Args, CB.args());
1537
1538 CallBase *NewCS = nullptr;
1539 if (!JT.isDeclaration()) {
1540 // Accumulate the call frequencies of the original call site, and use
1541 // that as total entry count for the funnel function.
1542 auto &F = *CB.getCaller();
1543 auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
1544 auto EC = BFI.getBlockFreq(&F.getEntryBlock());
1545 auto CC = F.getEntryCount();
1546 double CallCount = 0.0;
1547 if (EC.getFrequency() != 0 && CC && *CC != 0) {
1548 double CallFreq =
1549 static_cast<double>(
1550 BFI.getBlockFreq(CB.getParent()).getFrequency()) /
1551 EC.getFrequency();
1552 CallCount = CallFreq * *CC;
1553 }
1554 FunctionEntryCounts[&JT] += CallCount;
1555 }
1556 if (isa<CallInst>(CB))
1557 NewCS = IRB.CreateCall(NewFT, &JT, Args);
1558 else
1559 NewCS =
1560 IRB.CreateInvoke(NewFT, &JT, cast<InvokeInst>(CB).getNormalDest(),
1561 cast<InvokeInst>(CB).getUnwindDest(), Args);
1562 NewCS->setCallingConv(CB.getCallingConv());
1563
1564 AttributeList Attrs = CB.getAttributes();
1565 std::vector<AttributeSet> NewArgAttrs;
1566 NewArgAttrs.push_back(AttributeSet::get(
1567 M.getContext(), ArrayRef<Attribute>{Attribute::get(
1568 M.getContext(), Attribute::Nest)}));
1569 for (unsigned I = 0; I + 2 < Attrs.getNumAttrSets(); ++I)
1570 NewArgAttrs.push_back(Attrs.getParamAttrs(I));
1571 NewCS->setAttributes(
1572 AttributeList::get(M.getContext(), Attrs.getFnAttrs(),
1573 Attrs.getRetAttrs(), NewArgAttrs));
1574
1575 CallBases[&CB] = NewCS;
1576
1577 // This use is no longer unsafe.
1578 if (VCallSite.NumUnsafeUses)
1579 --*VCallSite.NumUnsafeUses;
1580 }
1581 // Don't mark as devirtualized because there may be callers compiled without
1582 // retpoline mitigation, which would mean that they are lowered to
1583 // llvm.type.test and therefore require an llvm.type.test resolution for the
1584 // type identifier.
1585
1586 for (auto &[Old, New] : CallBases) {
1587 Old->replaceAllUsesWith(New);
1588 Old->eraseFromParent();
1589 }
1590 };
1591 Apply(SlotInfo.CSInfo);
1592 for (auto &P : SlotInfo.ConstCSInfo)
1593 Apply(P.second);
1594 for (auto &[F, C] : FunctionEntryCounts) {
1595 assert(!F->getEntryCount() &&
1596 "Unexpected entry count for funnel that was freshly synthesized");
1597 F->setEntryCount(static_cast<uint64_t>(std::round(C)));
1598 }
1599}
1600
1601bool DevirtModule::tryEvaluateFunctionsWithArgs(
1603 ArrayRef<uint64_t> Args) {
1604 // Evaluate each function and store the result in each target's RetVal
1605 // field.
1606 for (VirtualCallTarget &Target : TargetsForSlot) {
1607 // TODO: Skip for now if the vtable symbol was an alias to a function,
1608 // need to evaluate whether it would be correct to analyze the aliasee
1609 // function for this optimization.
1610 auto *Fn = dyn_cast<Function>(Target.Fn);
1611 if (!Fn)
1612 return false;
1613
1614 if (Fn->arg_size() != Args.size() + 1)
1615 return false;
1616
1617 Evaluator Eval(M.getDataLayout(), nullptr);
1619 EvalArgs.push_back(
1621 for (unsigned I = 0; I != Args.size(); ++I) {
1622 auto *ArgTy =
1624 if (!ArgTy)
1625 return false;
1626 EvalArgs.push_back(ConstantInt::get(ArgTy, Args[I]));
1627 }
1628
1629 Constant *RetVal;
1630 if (!Eval.EvaluateFunction(Fn, RetVal, EvalArgs) ||
1631 !isa<ConstantInt>(RetVal))
1632 return false;
1633 Target.RetVal = cast<ConstantInt>(RetVal)->getZExtValue();
1634 }
1635 return true;
1636}
1637
1638void DevirtModule::applyUniformRetValOpt(CallSiteInfo &CSInfo, StringRef FnName,
1639 uint64_t TheRetVal) {
1640 for (auto Call : CSInfo.CallSites) {
1641 if (!OptimizedCalls.insert(&Call.CB).second)
1642 continue;
1643 NumUniformRetVal++;
1644 Call.replaceAndErase(
1645 "uniform-ret-val", FnName, RemarksEnabled, OREGetter,
1646 ConstantInt::get(cast<IntegerType>(Call.CB.getType()), TheRetVal));
1647 }
1648 CSInfo.markDevirt();
1649}
1650
1651bool DevirtModule::tryUniformRetValOpt(
1652 MutableArrayRef<VirtualCallTarget> TargetsForSlot, CallSiteInfo &CSInfo,
1653 WholeProgramDevirtResolution::ByArg *Res) {
1654 // Uniform return value optimization. If all functions return the same
1655 // constant, replace all calls with that constant.
1656 uint64_t TheRetVal = TargetsForSlot[0].RetVal;
1657 for (const VirtualCallTarget &Target : TargetsForSlot)
1658 if (Target.RetVal != TheRetVal)
1659 return false;
1660
1661 if (CSInfo.isExported()) {
1663 Res->Info = TheRetVal;
1664 }
1665
1666 applyUniformRetValOpt(CSInfo, TargetsForSlot[0].Fn->getName(), TheRetVal);
1667 if (RemarksEnabled || AreStatisticsEnabled())
1668 for (auto &&Target : TargetsForSlot)
1669 Target.WasDevirt = true;
1670 return true;
1671}
1672
1673std::string DevirtModule::getGlobalName(VTableSlot Slot,
1674 ArrayRef<uint64_t> Args,
1675 StringRef Name) {
1676 std::string FullName = "__typeid_";
1677 raw_string_ostream OS(FullName);
1678 OS << cast<MDString>(Slot.TypeID)->getString() << '_' << Slot.ByteOffset;
1679 for (uint64_t Arg : Args)
1680 OS << '_' << Arg;
1681 OS << '_' << Name;
1682 return FullName;
1683}
1684
1685bool DevirtModule::shouldExportConstantsAsAbsoluteSymbols() {
1686 Triple T(M.getTargetTriple());
1687 return T.isX86() && T.getObjectFormat() == Triple::ELF;
1688}
1689
1690void DevirtModule::exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
1691 StringRef Name, Constant *C) {
1692 GlobalAlias *GA = GlobalAlias::create(Int8Ty, 0, GlobalValue::ExternalLinkage,
1693 getGlobalName(Slot, Args, Name), C, &M);
1695}
1696
1697void DevirtModule::exportConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
1698 StringRef Name, uint32_t Const,
1699 uint32_t &Storage) {
1700 if (shouldExportConstantsAsAbsoluteSymbols()) {
1701 exportGlobal(
1702 Slot, Args, Name,
1703 ConstantExpr::getIntToPtr(ConstantInt::get(Int32Ty, Const), Int8PtrTy));
1704 return;
1705 }
1706
1707 Storage = Const;
1708}
1709
1710Constant *DevirtModule::importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
1711 StringRef Name) {
1712 GlobalVariable *GV =
1713 M.getOrInsertGlobal(getGlobalName(Slot, Args, Name), Int8Arr0Ty);
1715 return GV;
1716}
1717
1718Constant *DevirtModule::importConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
1719 StringRef Name, IntegerType *IntTy,
1720 uint32_t Storage) {
1721 if (!shouldExportConstantsAsAbsoluteSymbols())
1722 return ConstantInt::get(IntTy, Storage);
1723
1724 Constant *C = importGlobal(Slot, Args, Name);
1725 auto *GV = cast<GlobalVariable>(C->stripPointerCasts());
1726 C = ConstantExpr::getPtrToInt(C, IntTy);
1727
1728 // We only need to set metadata if the global is newly created, in which
1729 // case it would not have hidden visibility.
1730 if (GV->hasMetadata(LLVMContext::MD_absolute_symbol))
1731 return C;
1732
1733 auto SetAbsRange = [&](uint64_t Min, uint64_t Max) {
1734 auto *MinC = ConstantAsMetadata::get(ConstantInt::get(IntPtrTy, Min));
1735 auto *MaxC = ConstantAsMetadata::get(ConstantInt::get(IntPtrTy, Max));
1736 GV->setMetadata(LLVMContext::MD_absolute_symbol,
1737 MDNode::get(M.getContext(), {MinC, MaxC}));
1738 };
1739 unsigned AbsWidth = IntTy->getBitWidth();
1740 if (AbsWidth == IntPtrTy->getBitWidth()) {
1741 uint64_t AllOnes = IntTy->getBitMask();
1742 SetAbsRange(AllOnes, AllOnes); // Full set.
1743 } else {
1744 SetAbsRange(0, 1ull << AbsWidth);
1745 }
1746 return C;
1747}
1748
1749void DevirtModule::applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName,
1750 bool IsOne,
1751 Constant *UniqueMemberAddr) {
1752 for (auto &&Call : CSInfo.CallSites) {
1753 if (!OptimizedCalls.insert(&Call.CB).second)
1754 continue;
1755 IRBuilder<> B(&Call.CB);
1756 Value *Cmp =
1757 B.CreateICmp(IsOne ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE, Call.VTable,
1758 B.CreateBitCast(UniqueMemberAddr, Call.VTable->getType()));
1759 Cmp = B.CreateZExt(Cmp, Call.CB.getType());
1760 NumUniqueRetVal++;
1761 Call.replaceAndErase("unique-ret-val", FnName, RemarksEnabled, OREGetter,
1762 Cmp);
1763 }
1764 CSInfo.markDevirt();
1765}
1766
1767Constant *DevirtModule::getMemberAddr(const TypeMemberInfo *M) {
1768 return ConstantExpr::getPtrAdd(M->Bits->GV,
1769 ConstantInt::get(Int64Ty, M->Offset));
1770}
1771
1772bool DevirtModule::tryUniqueRetValOpt(
1773 unsigned BitWidth, MutableArrayRef<VirtualCallTarget> TargetsForSlot,
1774 CallSiteInfo &CSInfo, WholeProgramDevirtResolution::ByArg *Res,
1775 VTableSlot Slot, ArrayRef<uint64_t> Args) {
1776 // IsOne controls whether we look for a 0 or a 1.
1777 auto tryUniqueRetValOptFor = [&](bool IsOne) {
1778 const TypeMemberInfo *UniqueMember = nullptr;
1779 for (const VirtualCallTarget &Target : TargetsForSlot) {
1780 if (Target.RetVal == (IsOne ? 1 : 0)) {
1781 if (UniqueMember)
1782 return false;
1783 UniqueMember = Target.TM;
1784 }
1785 }
1786
1787 // We should have found a unique member or bailed out by now. We already
1788 // checked for a uniform return value in tryUniformRetValOpt.
1789 assert(UniqueMember);
1790
1791 Constant *UniqueMemberAddr = getMemberAddr(UniqueMember);
1792 if (CSInfo.isExported()) {
1794 Res->Info = IsOne;
1795
1796 exportGlobal(Slot, Args, "unique_member", UniqueMemberAddr);
1797 }
1798
1799 // Replace each call with the comparison.
1800 applyUniqueRetValOpt(CSInfo, TargetsForSlot[0].Fn->getName(), IsOne,
1801 UniqueMemberAddr);
1802
1803 // Update devirtualization statistics for targets.
1804 if (RemarksEnabled || AreStatisticsEnabled())
1805 for (auto &&Target : TargetsForSlot)
1806 Target.WasDevirt = true;
1807
1808 return true;
1809 };
1810
1811 if (BitWidth == 1) {
1812 if (tryUniqueRetValOptFor(true))
1813 return true;
1814 if (tryUniqueRetValOptFor(false))
1815 return true;
1816 }
1817 return false;
1818}
1819
1820void DevirtModule::applyVirtualConstProp(CallSiteInfo &CSInfo, StringRef FnName,
1821 Constant *Byte, Constant *Bit) {
1822 for (auto Call : CSInfo.CallSites) {
1823 if (!OptimizedCalls.insert(&Call.CB).second)
1824 continue;
1825 auto *RetType = cast<IntegerType>(Call.CB.getType());
1826 IRBuilder<> B(&Call.CB);
1827 Value *Addr = B.CreatePtrAddWithSExtOrTrunc(Call.VTable, Byte);
1828 if (RetType->getBitWidth() == 1) {
1829 Value *Bits = B.CreateLoad(Int8Ty, Addr);
1830 Value *BitsAndBit = B.CreateAnd(Bits, Bit);
1831 auto IsBitSet = B.CreateICmpNE(BitsAndBit, ConstantInt::get(Int8Ty, 0));
1832 NumVirtConstProp1Bit++;
1833 Call.replaceAndErase("virtual-const-prop-1-bit", FnName, RemarksEnabled,
1834 OREGetter, IsBitSet);
1835 } else {
1836 Value *Val = B.CreateLoad(RetType, Addr);
1837 NumVirtConstProp++;
1838 Call.replaceAndErase("virtual-const-prop", FnName, RemarksEnabled,
1839 OREGetter, Val);
1840 }
1841 }
1842 CSInfo.markDevirt();
1843}
1844
1845bool DevirtModule::tryVirtualConstProp(
1846 MutableArrayRef<VirtualCallTarget> TargetsForSlot, VTableSlotInfo &SlotInfo,
1847 WholeProgramDevirtResolution *Res, VTableSlot Slot) {
1848 // TODO: Skip for now if the vtable symbol was an alias to a function,
1849 // need to evaluate whether it would be correct to analyze the aliasee
1850 // function for this optimization.
1851 auto *Fn = dyn_cast<Function>(TargetsForSlot[0].Fn);
1852 if (!Fn)
1853 return false;
1854 // This only works if the function returns an integer.
1855 auto *RetType = dyn_cast<IntegerType>(Fn->getReturnType());
1856 if (!RetType)
1857 return false;
1858 unsigned BitWidth = RetType->getBitWidth();
1859
1860 // TODO: Since we can evaluated these constants at compile-time, we can save
1861 // some space by calculating the smallest range of values that all these
1862 // constants can fit in, then only allocate enough space to fit those values.
1863 // At each callsite, we can get the original type by doing a sign/zero
1864 // extension. For example, if we would store an i64, but we can see that all
1865 // the values fit into an i16, then we can store an i16 before/after the
1866 // vtable and at each callsite do a s/zext.
1867 if (BitWidth > 64)
1868 return false;
1869
1870 Align TypeAlignment = M.getDataLayout().getABIIntegerTypeAlignment(BitWidth);
1871
1872 // Make sure that each function is defined, does not access memory, takes at
1873 // least one argument, does not use its first argument (which we assume is
1874 // 'this'), and has the same return type.
1875 //
1876 // Note that we test whether this copy of the function is readnone, rather
1877 // than testing function attributes, which must hold for any copy of the
1878 // function, even a less optimized version substituted at link time. This is
1879 // sound because the virtual constant propagation optimizations effectively
1880 // inline all implementations of the virtual function into each call site,
1881 // rather than using function attributes to perform local optimization.
1882 for (VirtualCallTarget &Target : TargetsForSlot) {
1883 // TODO: Skip for now if the vtable symbol was an alias to a function,
1884 // need to evaluate whether it would be correct to analyze the aliasee
1885 // function for this optimization.
1886 auto *Fn = dyn_cast<Function>(Target.Fn);
1887 if (!Fn)
1888 return false;
1889
1890 if (Fn->isDeclaration() || Fn->isInterposable() ||
1891 !computeFunctionBodyMemoryAccess(*Fn, FAM.getResult<AAManager>(*Fn))
1893 Fn->arg_empty() || !Fn->arg_begin()->use_empty() ||
1894 Fn->getReturnType() != RetType)
1895 return false;
1896
1897 // This only works if the integer size is at most the alignment of the
1898 // vtable. If the table is underaligned, then we can't guarantee that the
1899 // constant will always be aligned to the integer type alignment. For
1900 // example, if the table is `align 1`, we can never guarantee that an i32
1901 // stored before/after the vtable is 32-bit aligned without changing the
1902 // alignment of the new global.
1903 GlobalVariable *GV = Target.TM->Bits->GV;
1904 Align TableAlignment = M.getDataLayout().getValueOrABITypeAlignment(
1905 GV->getAlign(), GV->getValueType());
1906 if (TypeAlignment > TableAlignment)
1907 return false;
1908 }
1909
1910 for (auto &&CSByConstantArg : SlotInfo.ConstCSInfo) {
1911 if (!tryEvaluateFunctionsWithArgs(TargetsForSlot, CSByConstantArg.first))
1912 continue;
1913
1914 WholeProgramDevirtResolution::ByArg *ResByArg = nullptr;
1915 if (Res)
1916 ResByArg = &Res->ResByArg[CSByConstantArg.first];
1917
1918 if (tryUniformRetValOpt(TargetsForSlot, CSByConstantArg.second, ResByArg))
1919 continue;
1920
1921 if (tryUniqueRetValOpt(BitWidth, TargetsForSlot, CSByConstantArg.second,
1922 ResByArg, Slot, CSByConstantArg.first))
1923 continue;
1924
1925 // Find an allocation offset in bits in all vtables associated with the
1926 // type.
1927 // TODO: If there would be "holes" in the vtable that were added by
1928 // padding, we could place i1s there to reduce any extra padding that
1929 // would be introduced by the i1s.
1930 uint64_t AllocBefore =
1931 findLowestOffset(TargetsForSlot, /*IsAfter=*/false, BitWidth);
1932 uint64_t AllocAfter =
1933 findLowestOffset(TargetsForSlot, /*IsAfter=*/true, BitWidth);
1934
1935 // Calculate the total amount of padding needed to store a value at both
1936 // ends of the object.
1937 uint64_t TotalPaddingBefore = 0, TotalPaddingAfter = 0;
1938 for (auto &&Target : TargetsForSlot) {
1939 TotalPaddingBefore += std::max<int64_t>(
1940 (AllocBefore + 7) / 8 - Target.allocatedBeforeBytes() - 1, 0);
1941 TotalPaddingAfter += std::max<int64_t>(
1942 (AllocAfter + 7) / 8 - Target.allocatedAfterBytes() - 1, 0);
1943 }
1944
1945 // If the amount of padding is too large, give up.
1946 // FIXME: do something smarter here.
1947 if (std::min(TotalPaddingBefore, TotalPaddingAfter) > 128)
1948 continue;
1949
1950 // Calculate the offset to the value as a (possibly negative) byte offset
1951 // and (if applicable) a bit offset, and store the values in the targets.
1952 int64_t OffsetByte;
1953 uint64_t OffsetBit;
1954 if (TotalPaddingBefore <= TotalPaddingAfter)
1955 setBeforeReturnValues(TargetsForSlot, AllocBefore, BitWidth, OffsetByte,
1956 OffsetBit);
1957 else
1958 setAfterReturnValues(TargetsForSlot, AllocAfter, BitWidth, OffsetByte,
1959 OffsetBit);
1960
1961 // In an earlier check we forbade constant propagation from operating on
1962 // tables whose alignment is less than the alignment needed for loading
1963 // the constant. Thus, the address we take the offset from will always be
1964 // aligned to at least this integer alignment. Now, we need to ensure that
1965 // the offset is also aligned to this integer alignment to ensure we always
1966 // have an aligned load.
1967 assert(OffsetByte % TypeAlignment.value() == 0);
1968
1969 if (RemarksEnabled || AreStatisticsEnabled())
1970 for (auto &&Target : TargetsForSlot)
1971 Target.WasDevirt = true;
1972
1973
1974 if (CSByConstantArg.second.isExported()) {
1976 ResByArg->Byte = OffsetByte;
1977 exportConstant(Slot, CSByConstantArg.first, "bit", 1ULL << OffsetBit,
1978 ResByArg->Bit);
1979 }
1980
1981 // Rewrite each call to a load from OffsetByte/OffsetBit.
1982 Constant *ByteConst = ConstantInt::getSigned(Int32Ty, OffsetByte);
1983 Constant *BitConst = ConstantInt::get(Int8Ty, 1ULL << OffsetBit);
1984 applyVirtualConstProp(CSByConstantArg.second,
1985 TargetsForSlot[0].Fn->getName(), ByteConst, BitConst);
1986 }
1987 return true;
1988}
1989
1990void DevirtModule::rebuildGlobal(VTableBits &B) {
1991 if (B.Before.Bytes.empty() && B.After.Bytes.empty())
1992 return;
1993
1994 // Align the before byte array to the global's minimum alignment so that we
1995 // don't break any alignment requirements on the global.
1996 Align Alignment = M.getDataLayout().getValueOrABITypeAlignment(
1997 B.GV->getAlign(), B.GV->getValueType());
1998 B.Before.Bytes.resize(alignTo(B.Before.Bytes.size(), Alignment));
1999
2000 // Before was stored in reverse order; flip it now.
2001 for (size_t I = 0, Size = B.Before.Bytes.size(); I != Size / 2; ++I)
2002 std::swap(B.Before.Bytes[I], B.Before.Bytes[Size - 1 - I]);
2003
2004 // Build an anonymous global containing the before bytes, followed by the
2005 // original initializer, followed by the after bytes.
2006 auto *NewInit = ConstantStruct::getAnon(
2007 {ConstantDataArray::get(M.getContext(), B.Before.Bytes),
2008 B.GV->getInitializer(),
2009 ConstantDataArray::get(M.getContext(), B.After.Bytes)});
2010 auto *NewGV =
2011 new GlobalVariable(M, NewInit->getType(), B.GV->isConstant(),
2012 GlobalVariable::PrivateLinkage, NewInit, "", B.GV);
2013 NewGV->setSection(B.GV->getSection());
2014 NewGV->setComdat(B.GV->getComdat());
2015 NewGV->setAlignment(B.GV->getAlign());
2016
2017 // Copy the original vtable's metadata to the anonymous global, adjusting
2018 // offsets as required.
2019 NewGV->copyMetadata(B.GV, B.Before.Bytes.size());
2020
2021 // Build an alias named after the original global, pointing at the second
2022 // element (the original initializer).
2023 auto *Alias = GlobalAlias::create(
2024 B.GV->getInitializer()->getType(), 0, B.GV->getLinkage(), "",
2026 M.getDataLayout(), NewInit->getType(), NewGV,
2027 {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 1)},
2029 &M);
2030 Alias->setVisibility(B.GV->getVisibility());
2031 Alias->takeName(B.GV);
2032
2033 B.GV->replaceAllUsesWith(Alias);
2034 B.GV->eraseFromParent();
2035}
2036
2037bool DevirtModule::areRemarksEnabled() {
2038 const auto &FL = M.getFunctionList();
2039 for (const Function &Fn : FL) {
2040 if (Fn.empty())
2041 continue;
2042 auto DI = OptimizationRemark(DEBUG_TYPE, "", DebugLoc(), &Fn.front());
2043 return DI.isEnabled();
2044 }
2045 return false;
2046}
2047
2048/// Find assumes whose conditions depend on this type test through phi or select
2049/// nodes. SimplifyCFG can produce these patterns by merging type test + assume
2050/// sequences from different predecessors.
2051static void
2053 CallInst &TypeTest,
2054 SmallPtrSetImpl<Value *> &VisitedMerges) {
2055 SmallVector<Value *, 4> Worklist;
2056#ifndef NDEBUG
2057 SmallPtrSet<CallInst *, 4> DirectAssumes(Assumes.begin(), Assumes.end());
2058#endif
2059
2060 auto GetMergeUser = [](User *U, Value *V) -> Value * {
2061 if (isa<PHINode>(U))
2062 return U;
2063 if (auto *Select = dyn_cast<SelectInst>(U);
2064 Select && (Select->getTrueValue() == V || Select->getFalseValue() == V))
2065 return Select;
2066 return nullptr;
2067 };
2068
2069 // Direct assume users were already collected by
2070 // findDevirtualizableCallsForTypeTest. Start from merge users so this search
2071 // finds only assumptions that depend on the type test through merges.
2072 for (User *U : TypeTest.users())
2073 if (Value *Merge = GetMergeUser(U, &TypeTest))
2074 Worklist.push_back(Merge);
2075
2076 while (!Worklist.empty()) {
2077 Value *V = Worklist.pop_back_val();
2078 if (!VisitedMerges.insert(V).second)
2079 continue;
2080
2081 for (User *U : V->users()) {
2082 if (auto *Assume = dyn_cast<AssumeInst>(U)) {
2083 if (Assume->getArgOperand(0) == V) {
2084 assert(!DirectAssumes.contains(Assume) &&
2085 "assume must not be both direct and merged");
2086 Assumes.push_back(Assume);
2087 }
2088 continue;
2089 }
2090
2091 if (Value *Merge = GetMergeUser(U, V))
2092 Worklist.push_back(Merge);
2093 }
2094 }
2095}
2096
2097void DevirtModule::scanTypeTestUsers(
2098 Function *TypeTestFunc,
2099 DenseMap<Metadata *, std::set<TypeMemberInfo>> &TypeIdMap) {
2100 // Cleanup removes every assume reachable through a merge, so each merge only
2101 // needs to be processed once even if multiple unresolved type tests reach it.
2102 SmallPtrSet<Value *, 8> VisitedMerges;
2103
2104 // Find all virtual calls via a virtual table pointer %p under an assumption
2105 // of the form llvm.assume(llvm.type.test(%p, %md)) or
2106 // llvm.assume(llvm.public.type.test(%p, %md)).
2107 // This indicates that %p points to a member of the type identifier %md.
2108 // Group calls by (type ID, offset) pair (effectively the identity of the
2109 // virtual function) and store to CallSlots.
2110 for (Use &U : llvm::make_early_inc_range(TypeTestFunc->uses())) {
2111 auto *CI = dyn_cast<CallInst>(U.getUser());
2112 if (!CI)
2113 continue;
2114 // Search for virtual calls based on %p and add them to DevirtCalls.
2117 auto &DT = FAM.getResult<DominatorTreeAnalysis>(*CI->getFunction());
2118 findDevirtualizableCallsForTypeTest(DevirtCalls, Assumes, CI, DT);
2119
2120 Metadata *TypeId =
2121 cast<MetadataAsValue>(CI->getArgOperand(1))->getMetadata();
2122 // If we found any, add them to CallSlots.
2123 if (!Assumes.empty()) {
2124 Value *Ptr = CI->getArgOperand(0)->stripPointerCasts();
2125 for (DevirtCallSite Call : DevirtCalls)
2126 CallSlots[{TypeId, Call.Offset}].addCallSite(Ptr, Call.CB, nullptr);
2127 }
2128
2129 auto RemoveTypeTestAssumes = [&]() {
2130 // A merge of type test results does not imply that any individual type
2131 // test can be assumed, so don't use these assumes to identify
2132 // devirtualizable calls. They still need to be removed when type
2133 // information is missing for any value contributing to the merge.
2134 findAssumesThroughMergesForTypeTest(Assumes, *CI, VisitedMerges);
2135
2136 // We no longer need the assumes or the type test.
2137 for (auto *Assume : Assumes)
2138 Assume->eraseFromParent();
2139 // We can't use RecursivelyDeleteTriviallyDeadInstructions here because we
2140 // may use the vtable argument later.
2141 if (CI->use_empty())
2142 CI->eraseFromParent();
2143 };
2144
2145 // At this point we could remove all type test assume sequences, as they
2146 // were originally inserted for WPD. However, we can keep these in the
2147 // code stream for later analysis (e.g. to help drive more efficient ICP
2148 // sequences). They will eventually be removed by a second LowerTypeTests
2149 // invocation that cleans them up. In order to do this correctly, the first
2150 // LowerTypeTests invocation needs to know that they have "Unknown" type
2151 // test resolution, so that they aren't treated as Unsat and lowered to
2152 // False, which will break any uses on assumes. Below we remove any type
2153 // test assumes that will not be treated as Unknown by LTT.
2154
2155 // The type test assumes will be treated by LTT as Unsat if the type id is
2156 // not used on a global (in which case it has no entry in the TypeIdMap).
2157 if (!TypeIdMap.count(TypeId))
2158 RemoveTypeTestAssumes();
2159
2160 // For ThinLTO importing, we need to remove the type test assumes if this is
2161 // an MDString type id without a corresponding TypeIdSummary. Any
2162 // non-MDString type ids are ignored and treated as Unknown by LTT, so their
2163 // type test assumes can be kept. If the MDString type id is missing a
2164 // TypeIdSummary (e.g. because there was no use on a vcall, preventing the
2165 // exporting phase of WPD from analyzing it), then it would be treated as
2166 // Unsat by LTT and we need to remove its type test assumes here. If not
2167 // used on a vcall we don't need them for later optimization use in any
2168 // case.
2169 else if (ImportSummary && isa<MDString>(TypeId)) {
2170 const TypeIdSummary *TidSummary =
2171 ImportSummary->getTypeIdSummary(cast<MDString>(TypeId)->getString());
2172 if (!TidSummary)
2173 RemoveTypeTestAssumes();
2174 else
2175 // If one was created it should not be Unsat, because if we reached here
2176 // the type id was used on a global.
2178 }
2179 }
2180}
2181
2182void DevirtModule::scanTypeCheckedLoadUsers(Function *TypeCheckedLoadFunc) {
2183 Function *TypeTestFunc =
2184 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::type_test);
2185
2186 for (Use &U : llvm::make_early_inc_range(TypeCheckedLoadFunc->uses())) {
2187 auto *CI = dyn_cast<CallInst>(U.getUser());
2188 if (!CI)
2189 continue;
2190
2191 Value *Ptr = CI->getArgOperand(0);
2192 Value *Offset = CI->getArgOperand(1);
2193 Value *TypeIdValue = CI->getArgOperand(2);
2194 Metadata *TypeId = cast<MetadataAsValue>(TypeIdValue)->getMetadata();
2195
2199 bool HasNonCallUses = false;
2200 auto &DT = FAM.getResult<DominatorTreeAnalysis>(*CI->getFunction());
2201 findDevirtualizableCallsForTypeCheckedLoad(DevirtCalls, LoadedPtrs, Preds,
2202 HasNonCallUses, CI, DT);
2203
2204 // Start by generating "pessimistic" code that explicitly loads the function
2205 // pointer from the vtable and performs the type check. If possible, we will
2206 // eliminate the load and the type check later.
2207
2208 // If possible, only generate the load at the point where it is used.
2209 // This helps avoid unnecessary spills.
2210 IRBuilder<> LoadB(
2211 (LoadedPtrs.size() == 1 && !HasNonCallUses) ? LoadedPtrs[0] : CI);
2212
2213 Value *LoadedValue = nullptr;
2214 if (TypeCheckedLoadFunc->getIntrinsicID() ==
2215 Intrinsic::type_checked_load_relative) {
2217 &M, Intrinsic::load_relative, {Int32Ty});
2218 LoadedValue = LoadB.CreateCall(LoadRelFunc, {Ptr, Offset});
2219 } else {
2220 Value *GEP = LoadB.CreatePtrAddWithSExtOrTrunc(Ptr, Offset);
2221 LoadedValue = LoadB.CreateLoad(Int8PtrTy, GEP);
2222 }
2223
2224 for (Instruction *LoadedPtr : LoadedPtrs) {
2225 LoadedPtr->replaceAllUsesWith(LoadedValue);
2226 LoadedPtr->eraseFromParent();
2227 }
2228
2229 // Likewise for the type test.
2230 IRBuilder<> CallB((Preds.size() == 1 && !HasNonCallUses) ? Preds[0] : CI);
2231 CallInst *TypeTestCall = CallB.CreateCall(TypeTestFunc, {Ptr, TypeIdValue});
2232
2233 for (Instruction *Pred : Preds) {
2234 Pred->replaceAllUsesWith(TypeTestCall);
2235 Pred->eraseFromParent();
2236 }
2237
2238 // We have already erased any extractvalue instructions that refer to the
2239 // intrinsic call, but the intrinsic may have other non-extractvalue uses
2240 // (although this is unlikely). In that case, explicitly build a pair and
2241 // RAUW it.
2242 if (!CI->use_empty()) {
2243 Value *Pair = PoisonValue::get(CI->getType());
2244 IRBuilder<> B(CI);
2245 Pair = B.CreateInsertValue(Pair, LoadedValue, {0});
2246 Pair = B.CreateInsertValue(Pair, TypeTestCall, {1});
2247 CI->replaceAllUsesWith(Pair);
2248 }
2249
2250 // The number of unsafe uses is initially the number of uses.
2251 auto &NumUnsafeUses = NumUnsafeUsesForTypeTest[TypeTestCall];
2252 NumUnsafeUses = DevirtCalls.size();
2253
2254 // If the function pointer has a non-call user, we cannot eliminate the type
2255 // check, as one of those users may eventually call the pointer. Increment
2256 // the unsafe use count to make sure it cannot reach zero.
2257 if (HasNonCallUses)
2258 ++NumUnsafeUses;
2259 for (DevirtCallSite Call : DevirtCalls) {
2260 CallSlots[{TypeId, Call.Offset}].addCallSite(Ptr, Call.CB,
2261 &NumUnsafeUses);
2262 }
2263
2264 CI->eraseFromParent();
2265 }
2266}
2267
2268void DevirtModule::importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo) {
2269 auto *TypeId = dyn_cast<MDString>(Slot.TypeID);
2270 if (!TypeId)
2271 return;
2272 const TypeIdSummary *TidSummary =
2273 ImportSummary->getTypeIdSummary(TypeId->getString());
2274 if (!TidSummary)
2275 return;
2276 auto ResI = TidSummary->WPDRes.find(Slot.ByteOffset);
2277 if (ResI == TidSummary->WPDRes.end())
2278 return;
2279 const WholeProgramDevirtResolution &Res = ResI->second;
2280
2282 assert(!Res.SingleImplName.empty());
2283 // The type of the function in the declaration is irrelevant because every
2284 // call site will cast it to the correct type.
2285 Value *SingleImplVal =
2286 M.getOrInsertFunction(Res.SingleImplName,
2287 Type::getVoidTy(M.getContext()))
2288 .getCallee();
2289 if (auto *A = dyn_cast<GlobalAlias>(SingleImplVal->stripPointerCasts()))
2290 if (!A->isInterposable() && !A->getAliaseeObject()->isInterposable())
2291 SingleImplVal = A->getAliaseeObject();
2292 Constant *SingleImpl = cast<Constant>(SingleImplVal);
2293
2294 // This is the import phase so we should not be exporting anything.
2295 bool IsExported = false;
2296 applySingleImplDevirt(SlotInfo, SingleImpl, IsExported);
2297 assert(!IsExported);
2298 }
2299
2300 for (auto &CSByConstantArg : SlotInfo.ConstCSInfo) {
2301 auto I = Res.ResByArg.find(CSByConstantArg.first);
2302 if (I == Res.ResByArg.end())
2303 continue;
2304 auto &ResByArg = I->second;
2305 // FIXME: We should figure out what to do about the "function name" argument
2306 // to the apply* functions, as the function names are unavailable during the
2307 // importing phase. For now we just pass the empty string. This does not
2308 // impact correctness because the function names are just used for remarks.
2309 switch (ResByArg.TheKind) {
2311 applyUniformRetValOpt(CSByConstantArg.second, "", ResByArg.Info);
2312 break;
2314 Constant *UniqueMemberAddr =
2315 importGlobal(Slot, CSByConstantArg.first, "unique_member");
2316 applyUniqueRetValOpt(CSByConstantArg.second, "", ResByArg.Info,
2317 UniqueMemberAddr);
2318 break;
2319 }
2321 Constant *Byte = ConstantInt::get(Int32Ty, ResByArg.Byte);
2322 Constant *Bit = importConstant(Slot, CSByConstantArg.first, "bit", Int8Ty,
2323 ResByArg.Bit);
2324 applyVirtualConstProp(CSByConstantArg.second, "", Byte, Bit);
2325 break;
2326 }
2327 default:
2328 break;
2329 }
2330 }
2331
2333 // The type of the function is irrelevant, because it's bitcast at calls
2334 // anyhow.
2335 auto *JT = cast<Function>(
2336 M.getOrInsertFunction(getGlobalName(Slot, {}, "branch_funnel"),
2337 Type::getVoidTy(M.getContext()))
2338 .getCallee());
2339 bool IsExported = false;
2340 applyICallBranchFunnel(SlotInfo, *JT, IsExported);
2341 assert(!IsExported);
2342 }
2343}
2344
2345void DevirtModule::removeRedundantTypeTests() {
2346 auto *True = ConstantInt::getTrue(M.getContext());
2347 for (auto &&U : NumUnsafeUsesForTypeTest) {
2348 if (U.second == 0) {
2349 U.first->replaceAllUsesWith(True);
2350 U.first->eraseFromParent();
2351 }
2352 }
2353}
2354
2355ValueInfo
2356DevirtModule::lookUpFunctionValueInfo(Function *TheFn,
2357 ModuleSummaryIndex *ExportSummary) {
2358 assert((ExportSummary != nullptr) &&
2359 "Caller guarantees ExportSummary is not nullptr");
2360
2361 const auto TheFnGUID = TheFn->getGUID();
2362 const auto TheFnGUIDWithExportedName =
2364 // Look up ValueInfo with the GUID in the current linkage.
2365 ValueInfo TheFnVI = ExportSummary->getValueInfo(TheFnGUID);
2366 // If no entry is found and GUID is different from GUID computed using
2367 // exported name, look up ValueInfo with the exported name unconditionally.
2368 // This is a fallback.
2369 //
2370 // The reason to have a fallback:
2371 // 1. LTO could enable global value internalization via
2372 // `enable-lto-internalization`.
2373 // 2. The GUID in ExportedSummary is computed using exported name.
2374 if ((!TheFnVI) && (TheFnGUID != TheFnGUIDWithExportedName)) {
2375 TheFnVI = ExportSummary->getValueInfo(TheFnGUIDWithExportedName);
2376 }
2377 return TheFnVI;
2378}
2379
2380bool DevirtModule::mustBeUnreachableFunction(
2381 Function *const F, ModuleSummaryIndex *ExportSummary) {
2383 return false;
2384 // First, learn unreachability by analyzing function IR.
2385 if (!F->isDeclaration()) {
2386 // A function must be unreachable if its entry block ends with an
2387 // 'unreachable'.
2388 return isa<UnreachableInst>(F->getEntryBlock().getTerminator());
2389 }
2390 // Learn unreachability from ExportSummary if ExportSummary is present.
2391 return ExportSummary &&
2393 DevirtModule::lookUpFunctionValueInfo(F, ExportSummary));
2394}
2395
2396bool DevirtModule::run() {
2397 // If only some of the modules were split, we cannot correctly perform
2398 // this transformation. We already checked for the presense of type tests
2399 // with partially split modules during the thin link, and would have emitted
2400 // an error if any were found, so here we can simply return.
2401 if ((ExportSummary && ExportSummary->partiallySplitLTOUnits()) ||
2402 (ImportSummary && ImportSummary->partiallySplitLTOUnits()))
2403 return false;
2404
2405 Function *PublicTypeTestFunc = nullptr;
2406 // If we are in speculative devirtualization mode, we can work on the public
2407 // type test intrinsics.
2408 if (DevirtSpeculatively)
2409 PublicTypeTestFunc =
2410 Intrinsic::getDeclarationIfExists(&M, Intrinsic::public_type_test);
2411 Function *TypeTestFunc =
2412 Intrinsic::getDeclarationIfExists(&M, Intrinsic::type_test);
2413 Function *TypeCheckedLoadFunc =
2414 Intrinsic::getDeclarationIfExists(&M, Intrinsic::type_checked_load);
2415 Function *TypeCheckedLoadRelativeFunc = Intrinsic::getDeclarationIfExists(
2416 &M, Intrinsic::type_checked_load_relative);
2417 Function *AssumeFunc =
2418 Intrinsic::getDeclarationIfExists(&M, Intrinsic::assume);
2419
2420 // Normally if there are no users of the devirtualization intrinsics in the
2421 // module, this pass has nothing to do. But if we are exporting, we also need
2422 // to handle any users that appear only in the function summaries.
2423 if (!ExportSummary &&
2424 (((!PublicTypeTestFunc || PublicTypeTestFunc->use_empty()) &&
2425 (!TypeTestFunc || TypeTestFunc->use_empty())) ||
2426 !AssumeFunc || AssumeFunc->use_empty()) &&
2427 (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty()) &&
2428 (!TypeCheckedLoadRelativeFunc ||
2429 TypeCheckedLoadRelativeFunc->use_empty()))
2430 return false;
2431
2432 // Rebuild type metadata into a map for easy lookup.
2433 std::vector<VTableBits> Bits;
2434 DenseMap<Metadata *, std::set<TypeMemberInfo>> TypeIdMap;
2435 buildTypeIdentifierMap(Bits, TypeIdMap);
2436
2437 if (PublicTypeTestFunc && AssumeFunc)
2438 scanTypeTestUsers(PublicTypeTestFunc, TypeIdMap);
2439
2440 if (TypeTestFunc && AssumeFunc)
2441 scanTypeTestUsers(TypeTestFunc, TypeIdMap);
2442
2443 if (TypeCheckedLoadFunc)
2444 scanTypeCheckedLoadUsers(TypeCheckedLoadFunc);
2445
2446 if (TypeCheckedLoadRelativeFunc)
2447 scanTypeCheckedLoadUsers(TypeCheckedLoadRelativeFunc);
2448
2449 if (ImportSummary) {
2450 for (auto &S : CallSlots)
2451 importResolution(S.first, S.second);
2452
2453 removeRedundantTypeTests();
2454
2455 // We have lowered or deleted the type intrinsics, so we will no longer have
2456 // enough information to reason about the liveness of virtual function
2457 // pointers in GlobalDCE.
2458 for (GlobalVariable &GV : M.globals())
2459 GV.eraseMetadata(LLVMContext::MD_vcall_visibility);
2460
2461 // The rest of the code is only necessary when exporting or during regular
2462 // LTO, so we are done.
2463 return true;
2464 }
2465
2466 if (TypeIdMap.empty())
2467 return true;
2468
2469 // Collect information from summary about which calls to try to devirtualize.
2470 if (ExportSummary) {
2471 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2472 for (auto &P : TypeIdMap) {
2473 if (auto *TypeId = dyn_cast<MDString>(P.first))
2475 TypeId->getString())]
2476 .push_back(TypeId);
2477 }
2478
2479 for (auto &P : *ExportSummary) {
2480 for (auto &S : P.second.getSummaryList()) {
2481 auto *FS = dyn_cast<FunctionSummary>(S.get());
2482 if (!FS)
2483 continue;
2484 // FIXME: Only add live functions.
2485 for (FunctionSummary::VFuncId VF : FS->type_test_assume_vcalls()) {
2486 for (Metadata *MD : MetadataByGUID[VF.GUID]) {
2487 CallSlots[{MD, VF.Offset}].CSInfo.addSummaryTypeTestAssumeUser(FS);
2488 }
2489 }
2490 for (FunctionSummary::VFuncId VF : FS->type_checked_load_vcalls()) {
2491 for (Metadata *MD : MetadataByGUID[VF.GUID]) {
2492 CallSlots[{MD, VF.Offset}].CSInfo.addSummaryTypeCheckedLoadUser(FS);
2493 }
2494 }
2495 for (const FunctionSummary::ConstVCall &VC :
2496 FS->type_test_assume_const_vcalls()) {
2497 for (Metadata *MD : MetadataByGUID[VC.VFunc.GUID]) {
2498 CallSlots[{MD, VC.VFunc.Offset}]
2499 .ConstCSInfo[VC.Args]
2500 .addSummaryTypeTestAssumeUser(FS);
2501 }
2502 }
2503 for (const FunctionSummary::ConstVCall &VC :
2504 FS->type_checked_load_const_vcalls()) {
2505 for (Metadata *MD : MetadataByGUID[VC.VFunc.GUID]) {
2506 CallSlots[{MD, VC.VFunc.Offset}]
2507 .ConstCSInfo[VC.Args]
2508 .addSummaryTypeCheckedLoadUser(FS);
2509 }
2510 }
2511 }
2512 }
2513 }
2514
2515 // For each (type, offset) pair:
2516 bool DidVirtualConstProp = false;
2517 std::map<std::string, GlobalValue *> DevirtTargets;
2518 for (auto &S : CallSlots) {
2519 // Search each of the members of the type identifier for the virtual
2520 // function implementation at offset S.first.ByteOffset, and add to
2521 // TargetsForSlot.
2522 std::vector<VirtualCallTarget> TargetsForSlot;
2523 WholeProgramDevirtResolution *Res = nullptr;
2524 const std::set<TypeMemberInfo> &TypeMemberInfos = TypeIdMap[S.first.TypeID];
2525 if (ExportSummary && isa<MDString>(S.first.TypeID) &&
2526 TypeMemberInfos.size())
2527 // For any type id used on a global's type metadata, create the type id
2528 // summary resolution regardless of whether we can devirtualize, so that
2529 // lower type tests knows the type id is not Unsat. If it was not used on
2530 // a global's type metadata, the TypeIdMap entry set will be empty, and
2531 // we don't want to create an entry (with the default Unknown type
2532 // resolution), which can prevent detection of the Unsat.
2533 Res = &ExportSummary
2534 ->getOrInsertTypeIdSummary(
2535 cast<MDString>(S.first.TypeID)->getString())
2536 .WPDRes[S.first.ByteOffset];
2537 if (tryFindVirtualCallTargets(TargetsForSlot, TypeMemberInfos,
2538 S.first.ByteOffset, ExportSummary)) {
2539 bool SingleImplDevirt =
2540 trySingleImplDevirt(ExportSummary, TargetsForSlot, S.second, Res);
2541 // Out of speculative devirtualization mode, Try to apply virtual constant
2542 // propagation or branch funneling.
2543 // TODO: This should eventually be enabled for non-public type tests.
2544 if (!SingleImplDevirt && !DevirtSpeculatively) {
2545 DidVirtualConstProp |=
2546 tryVirtualConstProp(TargetsForSlot, S.second, Res, S.first);
2547
2548 tryICallBranchFunnel(TargetsForSlot, S.second, Res, S.first);
2549 }
2550
2551 // Collect functions devirtualized at least for one call site for stats.
2552 if (RemarksEnabled || AreStatisticsEnabled())
2553 for (const auto &T : TargetsForSlot)
2554 if (T.WasDevirt)
2555 DevirtTargets[std::string(T.Fn->getName())] = T.Fn;
2556 }
2557
2558 // CFI-specific: if we are exporting and any llvm.type.checked.load
2559 // intrinsics were *not* devirtualized, we need to add the resulting
2560 // llvm.type.test intrinsics to the function summaries so that the
2561 // LowerTypeTests pass will export them.
2562 if (ExportSummary && isa<MDString>(S.first.TypeID)) {
2564 cast<MDString>(S.first.TypeID)->getString());
2565 auto AddTypeTestsForTypeCheckedLoads = [&](CallSiteInfo &CSI) {
2566 if (!CSI.AllCallSitesDevirted)
2567 for (auto *FS : CSI.SummaryTypeCheckedLoadUsers)
2568 FS->addTypeTest(GUID);
2569 };
2570 AddTypeTestsForTypeCheckedLoads(S.second.CSInfo);
2571 for (auto &CCS : S.second.ConstCSInfo)
2572 AddTypeTestsForTypeCheckedLoads(CCS.second);
2573 }
2574 }
2575
2576 if (RemarksEnabled) {
2577 // Generate remarks for each devirtualized function.
2578 for (const auto &DT : DevirtTargets) {
2579 GlobalValue *GV = DT.second;
2580 auto *F = dyn_cast<Function>(GV);
2581 if (!F) {
2582 auto *A = dyn_cast<GlobalAlias>(GV);
2583 assert(A && isa<Function>(A->getAliasee()));
2584 F = dyn_cast<Function>(A->getAliasee());
2585 assert(F);
2586 }
2587
2588 using namespace ore;
2589 OREGetter(*F).emit(OptimizationRemark(DEBUG_TYPE, "Devirtualized", F)
2590 << "devirtualized " << NV("FunctionName", DT.first));
2591 }
2592 }
2593
2594 NumDevirtTargets += DevirtTargets.size();
2595
2596 removeRedundantTypeTests();
2597
2598 // Rebuild each global we touched as part of virtual constant propagation to
2599 // include the before and after bytes.
2600 if (DidVirtualConstProp)
2601 for (VTableBits &B : Bits)
2602 rebuildGlobal(B);
2603
2604 // We have lowered or deleted the type intrinsics, so we will no longer have
2605 // enough information to reason about the liveness of virtual function
2606 // pointers in GlobalDCE.
2607 for (GlobalVariable &GV : M.globals())
2608 GV.eraseMetadata(LLVMContext::MD_vcall_visibility);
2609
2610 for (auto *CI : CallsWithPtrAuthBundleRemoved)
2611 CI->eraseFromParent();
2612
2613 return true;
2614}
2615
2616void DevirtIndex::run() {
2617 if (ExportSummary.typeIdCompatibleVtableMap().empty())
2618 return;
2619
2620 // Assert that we haven't made any changes that would affect the hasLocal()
2621 // flag on the GUID summary info.
2622 assert(!ExportSummary.withInternalizeAndPromote() &&
2623 "Expect index-based WPD to run before internalization and promotion");
2624
2625 DenseMap<GlobalValue::GUID, std::vector<StringRef>> NameByGUID;
2626 for (const auto &P : ExportSummary.typeIdCompatibleVtableMap()) {
2627 NameByGUID[GlobalValue::getGUIDAssumingExternalLinkage(P.first)].push_back(
2628 P.first);
2629 // Create the type id summary resolution regardlness of whether we can
2630 // devirtualize, so that lower type tests knows the type id is used on
2631 // a global and not Unsat. We do this here rather than in the loop over the
2632 // CallSlots, since that handling will only see type tests that directly
2633 // feed assumes, and we would miss any that aren't currently handled by WPD
2634 // (such as type tests that feed assumes via phis).
2635 ExportSummary.getOrInsertTypeIdSummary(P.first);
2636 }
2637
2638 // Collect information from summary about which calls to try to devirtualize.
2639 for (auto &P : ExportSummary) {
2640 for (auto &S : P.second.getSummaryList()) {
2641 auto *FS = dyn_cast<FunctionSummary>(S.get());
2642 if (!FS)
2643 continue;
2644 // FIXME: Only add live functions.
2645 for (FunctionSummary::VFuncId VF : FS->type_test_assume_vcalls()) {
2646 for (StringRef Name : NameByGUID[VF.GUID]) {
2647 CallSlots[{Name, VF.Offset}].CSInfo.addSummaryTypeTestAssumeUser(FS);
2648 }
2649 }
2650 for (FunctionSummary::VFuncId VF : FS->type_checked_load_vcalls()) {
2651 for (StringRef Name : NameByGUID[VF.GUID]) {
2652 CallSlots[{Name, VF.Offset}].CSInfo.addSummaryTypeCheckedLoadUser(FS);
2653 }
2654 }
2655 for (const FunctionSummary::ConstVCall &VC :
2656 FS->type_test_assume_const_vcalls()) {
2657 for (StringRef Name : NameByGUID[VC.VFunc.GUID]) {
2658 CallSlots[{Name, VC.VFunc.Offset}]
2659 .ConstCSInfo[VC.Args]
2660 .addSummaryTypeTestAssumeUser(FS);
2661 }
2662 }
2663 for (const FunctionSummary::ConstVCall &VC :
2664 FS->type_checked_load_const_vcalls()) {
2665 for (StringRef Name : NameByGUID[VC.VFunc.GUID]) {
2666 CallSlots[{Name, VC.VFunc.Offset}]
2667 .ConstCSInfo[VC.Args]
2668 .addSummaryTypeCheckedLoadUser(FS);
2669 }
2670 }
2671 }
2672 }
2673
2674 std::set<ValueInfo> DevirtTargets;
2675 // For each (type, offset) pair:
2676 for (auto &S : CallSlots) {
2677 // Search each of the members of the type identifier for the virtual
2678 // function implementation at offset S.first.ByteOffset, and add to
2679 // TargetsForSlot.
2680 std::vector<ValueInfo> TargetsForSlot;
2681 auto TidSummary = ExportSummary.getTypeIdCompatibleVtableSummary(S.first.TypeID);
2682 assert(TidSummary);
2683 // The type id summary would have been created while building the NameByGUID
2684 // map earlier.
2685 WholeProgramDevirtResolution *Res =
2686 &ExportSummary.getTypeIdSummary(S.first.TypeID)
2687 ->WPDRes[S.first.ByteOffset];
2688 if (tryFindVirtualCallTargets(TargetsForSlot, *TidSummary,
2689 S.first.ByteOffset)) {
2690
2691 if (!trySingleImplDevirt(TargetsForSlot, S.first, S.second, Res,
2692 DevirtTargets))
2693 continue;
2694 }
2695 }
2696
2697 // Optionally have the thin link print message for each devirtualized
2698 // function.
2700 for (const auto &DT : DevirtTargets)
2701 errs() << "Devirtualized call to " << DT << "\n";
2702
2703 NumDevirtTargets += DevirtTargets.size();
2704}
SDValue Pred
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
AMDGPU Register Bank Select
This is the interface for LLVM's primary stateless and local alias analysis.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
dxil translate DXIL Translate Metadata
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
@ CallSiteInfo
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
Provides passes for computing function attributes based on interprocedural analyses.
#define DEBUG_TYPE
static void emitRemark(const Function &F, OptimizationRemarkEmitter &ORE, bool Skip)
Hexagon Common GEP
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
This file contains the declarations for metadata subclasses.
Type::TypeID TypeID
#define T
static bool mustBeUnreachableFunction(const Function &F)
This is the interface to build a ModuleSummaryIndex for a module.
uint64_t IntrinsicInst * II
#define P(N)
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
This file contains the declarations for profiling metadata utility functions.
R600 Clause Merge
SmallVector< MachineOperand, 4 > Cond
RISCVCC::CondCode CC
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
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)
Definition Statistic.h:171
static void findAssumesThroughMergesForTypeTest(SmallVectorImpl< CallInst * > &Assumes, CallInst &TypeTest, SmallPtrSetImpl< Value * > &VisitedMerges)
Find assumes whose conditions depend on this type test through phi or select nodes.
static bool typeIDVisibleToRegularObj(StringRef TypeID, function_ref< bool(StringRef)> IsVisibleToRegularObj)
static bool addCalls(VTableSlotInfo &SlotInfo, const ValueInfo &Callee)
static cl::opt< bool > WholeProgramDevirtKeepUnreachableFunction("wholeprogramdevirt-keep-unreachable-function", cl::desc("Regard unreachable functions as possible devirtualize targets."), cl::Hidden, cl::init(true))
With Clang, a pure virtual class's deleting destructor is emitted as a llvm.trap intrinsic followed b...
static bool skipUpdateDueToValidation(GlobalVariable &GV, function_ref< bool(StringRef)> IsVisibleToRegularObj)
static Error checkCombinedSummaryForTesting(const IPOOptions &Opts, ModuleSummaryIndex *Summary)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
Definition ArrayRef.h:185
static LLVM_ABI AttributeSet get(LLVMContext &C, const AttrBuilder &B)
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:262
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
void setCallingConv(CallingConv::ID CC)
bool arg_empty() const
std::optional< OperandBundleUse > getOperandBundle(StringRef Name) const
Return an operand bundle by name, if present.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
CallingConv::ID getCallingConv() const
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the attributes for this call.
FunctionType * getFunctionType() const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
void setCalledOperand(Value *V)
static LLVM_ABI CallBase * removeOperandBundle(CallBase *CB, uint32_t ID, InsertPosition InsertPt=nullptr)
Create a clone of CB with operand bundle ID removed.
AttributeList getAttributes() const
Return the attributes for this call.
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
@ ICMP_NE
not equal
Definition InstrTypes.h:762
void setSelectionKind(SelectionKind Val)
Definition Comdat.h:48
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:548
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
Definition Constants.h:878
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getPtrAdd(Constant *Ptr, Constant *Offset, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReduced=nullptr)
Create a getelementptr i8, ptr, offset constant expression.
Definition Constants.h:1518
static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
Definition Constants.h:1477
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
Definition Constants.h:135
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
Definition Constants.h:643
const Constant * stripPointerCasts() const
Definition Constant.h:243
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
static bool shouldExecute(CounterInfo &Counter)
bool empty() const
Definition DenseMap.h:716
Implements a dense probed hash-table based set.
Definition DenseSet.h:283
Subclass of Error for the sole purpose of identifying the success path in the type system.
Definition Error.h:334
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
Type * getParamType(unsigned i) const
Parameter type accessors.
ArrayRef< Type * > params() const
bool isVarArg() const
Type * getReturnType() const
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:169
bool empty() const
Definition Function.h:844
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:212
bool arg_empty() const
Definition Function.h:887
const BasicBlock & front() const
Definition Function.h:845
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:766
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition Function.h:247
arg_iterator arg_begin()
Definition Function.h:853
std::optional< uint64_t > getEntryCount() const
Get the entry count for this function.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
adds the attribute to the list of attributes for the given arg.
Definition Function.cpp:669
size_t arg_size() const
Definition Function.h:886
Type * getReturnType() const
Returns the type of the ret val.
Definition Function.h:217
unsigned getInstructionCount() const
Returns the number of non-debug IR instructions in this function.
Definition Function.cpp:360
static GEPNoWrapFlags inBounds()
static LLVM_ABI Expected< GlobPattern > create(StringRef Pat, std::optional< size_t > MaxSubPatterns={}, bool SlashAgnostic=false)
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
Definition Globals.cpp:692
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set a particular kind of metadata attachment.
bool hasMetadata() const
Return true if this GlobalObject has any metadata attached to it.
LLVM_ABI VCallVisibility getVCallVisibility() const
LLVM_ABI bool eraseMetadata(unsigned KindID)
Erase all metadata attachments with the given kind.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this GlobalObject.
LLVM_ABI void setVCallVisibilityMetadata(VCallVisibility Visibility)
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
Definition Globals.cpp:80
static bool isLocalLinkage(LinkageTypes Linkage)
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:408
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
LLVM_ABI const GlobalObject * getAliaseeObject() const
Definition Globals.cpp:521
LLVM_ABI GUID getGUID() const
Return a 64-bit global unique ID for this value.
Definition Globals.cpp:103
@ HiddenVisibility
The GV is hidden.
Definition GlobalValue.h:69
void setVisibility(VisibilityTypes V)
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition GlobalValue.h:61
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
Type * getValueType() const
LLVM_ABI bool isInterposable(bool CheckNoIPA=true) const
Return true if this global's definition can be substituted with an arbitrary definition at link time ...
Definition Globals.cpp:178
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
uint64_t getBitMask() const
Return a bitmask with ones set for all of the bits that can be set by an unsigned version of this typ...
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1579
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
bool doesNotAccessMemory() const
Whether this function accesses no memory.
Definition ModRef.h:246
Root of the metadata hierarchy.
Definition Metadata.h:64
Class to hold module path string table and global value map, and encapsulate methods for operating on...
const TypeIdSummary * getTypeIdSummary(StringRef TypeId) const
This returns either a pointer to the type id summary (if present in the summary map) or null (if not ...
ValueInfo getValueInfo(const GlobalValueSummaryMapTy::value_type &R) const
Return a ValueInfo for the index value_type (convenient when iterating index).
const ModuleHash & getModuleHash(const StringRef ModPath) const
Get the module SHA1 hash recorded for the given module path.
static constexpr const char * getRegularLTOModuleName()
static std::string getGlobalNameForLocal(StringRef Name, ModuleHash ModHash)
Convenience method for creating a promoted global name for the given value name of a local,...
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
Analysis providing profile information.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
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 push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition StringRef.h:446
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition StringRef.h:270
Target - Wrapper for Target specific information.
The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:272
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:389
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:548
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:707
bool use_empty() const
Definition Value.h:348
LLVM_ABI bool eraseMetadata(unsigned KindID)
Erase all metadata attachments with the given kind.
iterator_range< use_iterator > uses()
Definition Value.h:382
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:314
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:210
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:188
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
CallInst * Call
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
bool match(Val *V, const Pattern &P)
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
DiagnosticInfoOptimizationBase::Argument NV
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
Definition FileSystem.h:802
LLVM_ABI uint64_t findLowestOffset(ArrayRef< VirtualCallTarget > Targets, bool IsAfter, uint64_t Size)
LLVM_ABI void setAfterReturnValues(MutableArrayRef< VirtualCallTarget > Targets, uint64_t AllocAfter, unsigned BitWidth, int64_t &OffsetByte, uint64_t &OffsetBit)
LLVM_ABI void setBeforeReturnValues(MutableArrayRef< VirtualCallTarget > Targets, uint64_t AllocBefore, unsigned BitWidth, int64_t &OffsetByte, uint64_t &OffsetBit)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Offset
Definition DWP.cpp:577
LLVM_ABI void runWholeProgramDevirtOnIndex(ModuleSummaryIndex &Summary, std::set< GlobalValue::GUID > &ExportedGUIDs, std::map< ValueInfo, std::vector< VTableSlotSummary > > &LocalWPDTargetsMap, DenseSet< StringRef > *ExternallyVisibleSymbolNamesPtr=nullptr)
Perform index-based whole program devirtualization on the Summary index.
LLVM_ABI MemoryEffects computeFunctionBodyMemoryAccess(Function &F, AAResults &AAR)
Returns the memory access properties of this copy of the function.
static cl::opt< bool > DisableWholeProgramVisibility("disable-whole-program-visibility", cl::Hidden, cl::desc("Disable whole program visibility (overrides enabling options)"))
Provide a way to force disable whole program for debugging or workarounds, when enabled via the linke...
static cl::opt< bool > WholeProgramVisibility("whole-program-visibility", cl::Hidden, cl::desc("Enable whole program visibility"))
Provide a way to force enable whole program visibility in tests.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
PassSummaryAction
What to do with the summary when running passes that operate on it.
Definition IPO.h:37
@ Export
Export information to summary.
Definition IPO.h:40
@ Import
Import information from summary.
Definition IPO.h:39
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
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...
Definition STLExtras.h:649
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI ModuleSummaryIndex buildModuleSummaryIndex(const Module &M, std::function< BlockFrequencyInfo *(const Function &F)> GetBFICallback, ProfileSummaryInfo *PSI, std::function< const StackSafetyInfo *(const Function &F)> GetSSICallback=[](const Function &F) -> const StackSafetyInfo *{ return nullptr;})
Direct function to compute a ModuleSummaryIndex from a given module.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI bool hasWholeProgramVisibility(bool WholeProgramVisibilityEnabledInLTO)
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
LLVM_ABI void writeIndexToFile(const ModuleSummaryIndex &Index, raw_ostream &Out, const ModuleToSummariesForIndexTy *ModuleToSummariesForIndex=nullptr, const GVSummaryPtrSet *DecSummaries=nullptr)
Write the specified module summary index to the given raw output stream, where it will be written in ...
LLVM_ABI Expected< std::unique_ptr< ModuleSummaryIndex > > getModuleSummaryIndex(MemoryBufferRef Buffer)
Parse the specified bitcode buffer, returning the module summary index.
@ invalid_argument
Definition Errc.h:56
const IPOOptions & getIPOOptions(const LLVMContext &C)
Definition IPOOptions.h:33
LLVM_ABI void updateIndexWPDForExports(ModuleSummaryIndex &Summary, function_ref< bool(StringRef, ValueInfo)> isExported, std::map< ValueInfo, std::vector< VTableSlotSummary > > &LocalWPDTargetsMap, DenseSet< StringRef > *ExternallyVisibleSymbolNamesPtr=nullptr)
Call after cross-module importing to update the recorded single impl devirt target names for any loca...
LLVM_ABI void updatePublicTypeTestCalls(Module &M, bool WholeProgramVisibilityEnabledInLTO)
LLVM_ABI void getVisibleToRegularObjVtableGUIDs(ModuleSummaryIndex &Index, DenseSet< GlobalValue::GUID > &VisibleToRegularObjSymbols, function_ref< bool(StringRef)> IsVisibleToRegularObj)
Based on typeID string, get all associated vtable GUIDS that are visible to regular objects.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
LLVM_ABI void findDevirtualizableCallsForTypeCheckedLoad(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< Instruction * > &LoadedPtrs, SmallVectorImpl< Instruction * > &Preds, bool &HasNonCallUses, const CallInst *CI, DominatorTree &DT)
Given a call to the intrinsic @llvm.type.checked.load, find all devirtualizable call sites based on t...
LLVM_ABI CallBase & versionCallSite(CallBase &CB, Value *Callee, MDNode *BranchWeights)
Predicate and clone the given call site.
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI void setExplicitlyUnknownFunctionEntryCount(Function &F, StringRef PassName)
Analogous to setExplicitlyUnknownBranchWeights, but for functions and their entry counts.
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
static cl::list< std::string > SkipFunctionNames("wholeprogramdevirt-skip", cl::desc("Prevent function(s) from being devirtualized"), cl::Hidden, cl::CommaSeparated)
Provide way to prevent certain function from being devirtualized.
IntPtrTy
Definition InstrProf.h:82
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
Definition Error.h:1261
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition Error.cpp:107
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
std::vector< TypeIdOffsetVtableInfo > TypeIdCompatibleVtableInfo
List of vtable definitions decorated by a particular type identifier, and their corresponding offsets...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
static cl::opt< bool > PrintSummaryDevirt("wholeprogramdevirt-print-index-based", cl::Hidden, cl::desc("Print index-based devirtualization messages"))
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
LLVM_ABI void findDevirtualizableCallsForTypeTest(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< CallInst * > &Assumes, const CallInst *CI, DominatorTree &DT)
Given a call to the intrinsic @llvm.type.test, find all devirtualizable call sites based on the call ...
LLVM_ABI void updateVCallVisibilityInModule(Module &M, bool WholeProgramVisibilityEnabledInLTO, const DenseSet< GlobalValue::GUID > &DynamicExportSymbols, bool ValidateAllVtablesHaveTypeInfos, function_ref< bool(StringRef)> IsVisibleToRegularObj)
If whole program visibility asserted, then upgrade all public vcall visibility metadata on vtable def...
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
LLVM_ABI std::pair< Function *, Constant * > getFunctionAtVTableOffset(GlobalVariable *GV, uint64_t Offset, Module &M)
Given a vtable and a specified offset, returns the function and the trivial pointer at the specified ...
LLVM_ABI void updateVCallVisibilityInIndex(ModuleSummaryIndex &Index, bool WholeProgramVisibilityEnabledInLTO, const DenseSet< GlobalValue::GUID > &DynamicExportSymbols, const DenseSet< GlobalValue::GUID > &VisibleToRegularObjSymbols)
If whole program visibility asserted, then upgrade all public vcall visibility metadata on vtable def...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:82
Class to accumulate and hold information about a callee.
static unsigned getHashValue(const VTableSlotSummary &I)
static bool isEqual(const VTableSlotSummary &LHS, const VTableSlotSummary &RHS)
static bool isEqual(const VTableSlot &LHS, const VTableSlot &RHS)
static unsigned getHashValue(const VTableSlot &I)
An information struct used to provide DenseMap with the various necessary components for a given valu...
The following data structures summarize type metadata information.
std::map< uint64_t, WholeProgramDevirtResolution > WPDRes
Mapping from byte offset to whole-program devirt resolution for that (typeid, byte offset) pair.
TypeTestResolution TTRes
@ Unsat
Unsatisfiable type (i.e. no global has this type metadata)
enum llvm::TypeTestResolution::Kind TheKind
Struct that holds a reference to a particular GUID in a global value summary.
ArrayRef< std::unique_ptr< GlobalValueSummary > > getSummaryList() const
const ModuleSummaryIndex * ImportSummary
ModuleSummaryIndex * ExportSummary
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
@ UniformRetVal
Uniform return value optimization.
@ VirtualConstProp
Virtual constant propagation.
@ UniqueRetVal
Unique return value optimization.
uint64_t Info
Additional information for the resolution:
enum llvm::WholeProgramDevirtResolution::ByArg::Kind TheKind
enum llvm::WholeProgramDevirtResolution::Kind TheKind
std::map< std::vector< uint64_t >, ByArg > ResByArg
Resolutions for calls with all constant integer arguments (excluding the first argument,...
@ SingleImpl
Single implementation devirtualization.
@ BranchFunnel
When retpoline mitigation is enabled, use a branch funnel that is defined in the merged module.
LLVM_ABI VirtualCallTarget(GlobalValue *Fn, const TypeMemberInfo *TM)