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