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