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 for (GlobalVariable &GV : M.globals()) {
882 // Add linkage unit visibility to any variable with type metadata, which are
883 // the vtable definitions. We won't have an existing vcall_visibility
884 // metadata on vtable definitions with public visibility.
885 if (GV.hasMetadata(LLVMContext::MD_type) &&
887 // Don't upgrade the visibility for symbols exported to the dynamic
888 // linker, as we have no information on their eventual use.
889 !DynamicExportSymbols.count(GV.getGUID()) &&
890 // With validation enabled, we want to exclude symbols visible to
891 // regular objects. Local symbols will be in this group due to the
892 // current implementation but those with VCallVisibilityTranslationUnit
893 // will have already been marked in clang so are unaffected.
894 !(ValidateAllVtablesHaveTypeInfos &&
895 skipUpdateDueToValidation(GV, IsVisibleToRegularObj)))
897 }
898}
899
901 bool WholeProgramVisibilityEnabledInLTO) {
902 llvm::TimeTraceScope timeScope("Update public type test calls");
903 Function *PublicTypeTestFunc =
904 Intrinsic::getDeclarationIfExists(&M, Intrinsic::public_type_test);
905 if (!PublicTypeTestFunc)
906 return;
907 if (hasWholeProgramVisibility(WholeProgramVisibilityEnabledInLTO)) {
908 Function *TypeTestFunc =
909 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::type_test);
910 for (Use &U : make_early_inc_range(PublicTypeTestFunc->uses())) {
911 auto *CI = cast<CallInst>(U.getUser());
912 auto *NewCI = CallInst::Create(
913 TypeTestFunc, {CI->getArgOperand(0), CI->getArgOperand(1)}, {}, "",
914 CI->getIterator());
915 CI->replaceAllUsesWith(NewCI);
916 CI->eraseFromParent();
917 }
918 } else {
919 // TODO: Don't replace public type tests when speculative devirtualization
920 // gets enabled in LTO mode.
921 auto *True = ConstantInt::getTrue(M.getContext());
922 for (Use &U : make_early_inc_range(PublicTypeTestFunc->uses())) {
923 auto *CI = cast<CallInst>(U.getUser());
924 CI->replaceAllUsesWith(True);
925 CI->eraseFromParent();
926 }
927 }
928}
929
930/// Based on typeID string, get all associated vtable GUIDS that are
931/// visible to regular objects.
933 ModuleSummaryIndex &Index,
934 DenseSet<GlobalValue::GUID> &VisibleToRegularObjSymbols,
935 function_ref<bool(StringRef)> IsVisibleToRegularObj) {
936 for (const auto &TypeID : Index.typeIdCompatibleVtableMap()) {
937 if (typeIDVisibleToRegularObj(TypeID.first, IsVisibleToRegularObj))
938 for (const TypeIdOffsetVtableInfo &P : TypeID.second)
939 VisibleToRegularObjSymbols.insert(P.VTableVI.getGUID());
940 }
941}
942
943/// If whole program visibility asserted, then upgrade all public vcall
944/// visibility metadata on vtable definition summaries to linkage unit
945/// visibility in Module summary index (for ThinLTO).
947 ModuleSummaryIndex &Index, bool WholeProgramVisibilityEnabledInLTO,
948 const DenseSet<GlobalValue::GUID> &DynamicExportSymbols,
949 const DenseSet<GlobalValue::GUID> &VisibleToRegularObjSymbols) {
950 if (!hasWholeProgramVisibility(WholeProgramVisibilityEnabledInLTO))
951 return;
952 for (auto &P : Index) {
953 // Don't upgrade the visibility for symbols exported to the dynamic
954 // linker, as we have no information on their eventual use.
955 if (DynamicExportSymbols.count(P.first))
956 continue;
957 // With validation enabled, we want to exclude symbols visible to regular
958 // objects. Local symbols will be in this group due to the current
959 // implementation but those with VCallVisibilityTranslationUnit will have
960 // already been marked in clang so are unaffected.
961 if (VisibleToRegularObjSymbols.count(P.first))
962 continue;
963 for (auto &S : P.second.getSummaryList()) {
964 auto *GVar = dyn_cast<GlobalVarSummary>(S.get());
965 if (!GVar ||
966 GVar->getVCallVisibility() != GlobalObject::VCallVisibilityPublic)
967 continue;
968 GVar->setVCallVisibility(GlobalObject::VCallVisibilityLinkageUnit);
969 }
970 }
971}
972
974 ModuleSummaryIndex &Summary, std::set<GlobalValue::GUID> &ExportedGUIDs,
975 std::map<ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap,
976 DenseSet<StringRef> *ExternallyVisibleSymbolNamesPtr) {
977 DevirtIndex(Summary, ExportedGUIDs, LocalWPDTargetsMap,
978 ExternallyVisibleSymbolNamesPtr)
979 .run();
980}
981
983 ModuleSummaryIndex &Summary,
984 function_ref<bool(StringRef, ValueInfo)> IsExported,
985 std::map<ValueInfo, std::vector<VTableSlotSummary>> &LocalWPDTargetsMap,
986 DenseSet<StringRef> *ExternallyVisibleSymbolNamesPtr) {
987 for (auto &T : LocalWPDTargetsMap) {
988 auto &VI = T.first;
989 // This was enforced earlier during trySingleImplDevirt.
990 assert(VI.getSummaryList().size() == 1 &&
991 "Devirt of local target has more than one copy");
992 auto &S = VI.getSummaryList()[0];
993 if (!IsExported(S->modulePath(), VI))
994 continue;
995
996 // It's been exported by a cross module import.
997 for (auto &SlotSummary : T.second) {
998 auto *TIdSum = Summary.getTypeIdSummary(SlotSummary.TypeID);
999 assert(TIdSum);
1000 auto WPDRes = TIdSum->WPDRes.find(SlotSummary.ByteOffset);
1001 assert(WPDRes != TIdSum->WPDRes.end());
1002 if (ExternallyVisibleSymbolNamesPtr)
1003 ExternallyVisibleSymbolNamesPtr->insert(WPDRes->second.SingleImplName);
1004 WPDRes->second.SingleImplName = ModuleSummaryIndex::getGlobalNameForLocal(
1005 WPDRes->second.SingleImplName,
1006 Summary.getModuleHash(S->modulePath()));
1007 }
1008 }
1009}
1010
1012 // Check that summary index contains regular LTO module when performing
1013 // export to prevent occasional use of index from pure ThinLTO compilation
1014 // (-fno-split-lto-module). This kind of summary index is passed to
1015 // DevirtIndex::run, not to DevirtModule::run used by opt/runForTesting.
1016 const auto &ModPaths = Summary->modulePaths();
1018 !ModPaths.contains(ModuleSummaryIndex::getRegularLTOModuleName()))
1019 return createStringError(
1021 "combined summary should contain Regular LTO module");
1022 return ErrorSuccess();
1023}
1024
1025bool DevirtModule::runForTesting(Module &M, ModuleAnalysisManager &MAM,
1026 bool DevirtSpeculatively) {
1027 std::unique_ptr<ModuleSummaryIndex> Summary =
1028 std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
1029
1030 // Handle the command-line summary arguments. This code is for testing
1031 // purposes only, so we handle errors directly.
1032 if (!ClReadSummary.empty()) {
1033 ExitOnError ExitOnErr("-wholeprogramdevirt-read-summary: " + ClReadSummary +
1034 ": ");
1035 auto ReadSummaryFile =
1037 if (Expected<std::unique_ptr<ModuleSummaryIndex>> SummaryOrErr =
1038 getModuleSummaryIndex(*ReadSummaryFile)) {
1039 Summary = std::move(*SummaryOrErr);
1040 ExitOnErr(checkCombinedSummaryForTesting(Summary.get()));
1041 } else {
1042 // Try YAML if we've failed with bitcode.
1043 consumeError(SummaryOrErr.takeError());
1044 yaml::Input In(ReadSummaryFile->getBuffer());
1045 In >> *Summary;
1046 ExitOnErr(errorCodeToError(In.error()));
1047 }
1048 }
1049
1050 bool Changed =
1051 DevirtModule(M, MAM,
1053 : nullptr,
1055 : nullptr,
1056 DevirtSpeculatively)
1057 .run();
1058
1059 if (!ClWriteSummary.empty()) {
1060 ExitOnError ExitOnErr(
1061 "-wholeprogramdevirt-write-summary: " + ClWriteSummary + ": ");
1062 std::error_code EC;
1063 if (StringRef(ClWriteSummary).ends_with(".bc")) {
1064 raw_fd_ostream OS(ClWriteSummary, EC, sys::fs::OF_None);
1065 ExitOnErr(errorCodeToError(EC));
1066 writeIndexToFile(*Summary, OS);
1067 } else {
1068 raw_fd_ostream OS(ClWriteSummary, EC, sys::fs::OF_TextWithCRLF);
1069 ExitOnErr(errorCodeToError(EC));
1070 yaml::Output Out(OS);
1071 Out << *Summary;
1072 }
1073 }
1074
1075 return Changed;
1076}
1077
1078void DevirtModule::buildTypeIdentifierMap(
1079 std::vector<VTableBits> &Bits,
1080 DenseMap<Metadata *, std::set<TypeMemberInfo>> &TypeIdMap) {
1081 DenseMap<GlobalVariable *, VTableBits *> GVToBits;
1082 Bits.reserve(M.global_size());
1084 for (GlobalVariable &GV : M.globals()) {
1085 Types.clear();
1086 GV.getMetadata(LLVMContext::MD_type, Types);
1087 if (GV.isDeclaration() || Types.empty())
1088 continue;
1089
1090 VTableBits *&BitsPtr = GVToBits[&GV];
1091 if (!BitsPtr) {
1092 Bits.emplace_back();
1093 Bits.back().GV = &GV;
1094 Bits.back().ObjectSize =
1095 M.getDataLayout().getTypeAllocSize(GV.getInitializer()->getType());
1096 BitsPtr = &Bits.back();
1097 }
1098
1099 for (MDNode *Type : Types) {
1100 auto *TypeID = Type->getOperand(1).get();
1101
1102 uint64_t Offset =
1104 cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
1105 ->getZExtValue();
1106
1107 TypeIdMap[TypeID].insert({BitsPtr, Offset});
1108 }
1109 }
1110}
1111
1112bool DevirtModule::tryFindVirtualCallTargets(
1113 std::vector<VirtualCallTarget> &TargetsForSlot,
1114 const std::set<TypeMemberInfo> &TypeMemberInfos, uint64_t ByteOffset,
1115 ModuleSummaryIndex *ExportSummary) {
1116 for (const TypeMemberInfo &TM : TypeMemberInfos) {
1117 if (!TM.Bits->GV->isConstant())
1118 return false;
1119
1120 // Without DevirtSpeculatively, we cannot perform whole program
1121 // devirtualization analysis on a vtable with public LTO visibility.
1122 if (!DevirtSpeculatively && TM.Bits->GV->getVCallVisibility() ==
1124 return false;
1125
1126 Function *Fn = nullptr;
1127 Constant *C = nullptr;
1128 std::tie(Fn, C) =
1129 getFunctionAtVTableOffset(TM.Bits->GV, TM.Offset + ByteOffset, M);
1130
1131 if (!Fn)
1132 return false;
1133
1134 if (FunctionsToSkip.match(Fn->getName()))
1135 return false;
1136
1137 // We can disregard __cxa_pure_virtual as a possible call target, as
1138 // calls to pure virtuals are UB.
1139 if (Fn->getName() == "__cxa_pure_virtual")
1140 continue;
1141
1142 // In most cases empty functions will be overridden by the
1143 // implementation of the derived class, so we can skip them.
1144 if (DevirtSpeculatively && Fn->getReturnType()->isVoidTy() &&
1145 Fn->getInstructionCount() <= 1)
1146 continue;
1147
1148 // We can disregard unreachable functions as possible call targets, as
1149 // unreachable functions shouldn't be called.
1150 if (mustBeUnreachableFunction(Fn, ExportSummary))
1151 continue;
1152
1153 // Save the symbol used in the vtable to use as the devirtualization
1154 // target.
1155 auto *GV = dyn_cast<GlobalValue>(C);
1156 assert(GV);
1157 TargetsForSlot.push_back({GV, &TM});
1158 }
1159
1160 // Give up if we couldn't find any targets.
1161 return !TargetsForSlot.empty();
1162}
1163
1164bool DevirtIndex::tryFindVirtualCallTargets(
1165 std::vector<ValueInfo> &TargetsForSlot,
1166 const TypeIdCompatibleVtableInfo TIdInfo, uint64_t ByteOffset) {
1167 for (const TypeIdOffsetVtableInfo &P : TIdInfo) {
1168 // Find a representative copy of the vtable initializer.
1169 // We can have multiple available_externally, linkonce_odr and weak_odr
1170 // vtable initializers. We can also have multiple external vtable
1171 // initializers in the case of comdats, which we cannot check here.
1172 // The linker should give an error in this case.
1173 //
1174 // Also, handle the case of same-named local Vtables with the same path
1175 // and therefore the same GUID. This can happen if there isn't enough
1176 // distinguishing path when compiling the source file. In that case we
1177 // conservatively return false early.
1178 if (P.VTableVI.hasLocal() && P.VTableVI.getSummaryList().size() > 1)
1179 return false;
1180 const GlobalVarSummary *VS = nullptr;
1181 for (const auto &S : P.VTableVI.getSummaryList()) {
1182 auto *CurVS = cast<GlobalVarSummary>(S->getBaseObject());
1183 if (!CurVS->vTableFuncs().empty() ||
1184 // Previously clang did not attach the necessary type metadata to
1185 // available_externally vtables, in which case there would not
1186 // be any vtable functions listed in the summary and we need
1187 // to treat this case conservatively (in case the bitcode is old).
1188 // However, we will also not have any vtable functions in the
1189 // case of a pure virtual base class. In that case we do want
1190 // to set VS to avoid treating it conservatively.
1192 VS = CurVS;
1193 // We cannot perform whole program devirtualization analysis on a vtable
1194 // with public LTO visibility.
1195 if (VS->getVCallVisibility() == GlobalObject::VCallVisibilityPublic)
1196 return false;
1197 break;
1198 }
1199 }
1200 // There will be no VS if all copies are available_externally having no
1201 // type metadata. In that case we can't safely perform WPD.
1202 if (!VS)
1203 return false;
1204 if (!VS->isLive())
1205 continue;
1206 for (auto VTP : VS->vTableFuncs()) {
1207 if (VTP.VTableOffset != P.AddressPointOffset + ByteOffset)
1208 continue;
1209
1210 if (mustBeUnreachableFunction(VTP.FuncVI))
1211 continue;
1212
1213 TargetsForSlot.push_back(VTP.FuncVI);
1214 }
1215 }
1216
1217 // Give up if we couldn't find any targets.
1218 return !TargetsForSlot.empty();
1219}
1220
1221void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
1222 Constant *TheFn, bool &IsExported) {
1223 // Don't devirtualize function if we're told to skip it
1224 // in -wholeprogramdevirt-skip.
1225 if (FunctionsToSkip.match(TheFn->stripPointerCasts()->getName()))
1226 return;
1227 auto Apply = [&](CallSiteInfo &CSInfo) {
1228 for (auto &&VCallSite : CSInfo.CallSites) {
1229 if (!OptimizedCalls.insert(&VCallSite.CB).second)
1230 continue;
1231
1232 // Stop when the number of devirted calls reaches the cutoff.
1233 if (!DebugCounter::shouldExecute(CallsToDevirt))
1234 continue;
1235
1236 if (RemarksEnabled)
1237 VCallSite.emitRemark("single-impl",
1238 TheFn->stripPointerCasts()->getName(), OREGetter);
1239 NumSingleImpl++;
1240 auto &CB = VCallSite.CB;
1241 assert(!CB.getCalledFunction() && "devirtualizing direct call?");
1242 IRBuilder<> Builder(&CB);
1243 Value *Callee =
1244 Builder.CreateBitCast(TheFn, CB.getCalledOperand()->getType());
1245
1246 // If trap checking is enabled, add support to compare the virtual
1247 // function pointer to the devirtualized target. In case of a mismatch,
1248 // perform a debug trap.
1250 auto *Cond = Builder.CreateICmpNE(CB.getCalledOperand(), Callee);
1252 Cond, &CB, /*Unreachable=*/false,
1253 MDBuilder(M.getContext()).createUnlikelyBranchWeights());
1254 Builder.SetInsertPoint(ThenTerm);
1255 Function *TrapFn =
1256 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::debugtrap);
1257 auto *CallTrap = Builder.CreateCall(TrapFn);
1258 CallTrap->setDebugLoc(CB.getDebugLoc());
1259 }
1260
1261 // If fallback checking or speculative devirtualization are enabled,
1262 // add support to compare the virtual function pointer to the
1263 // devirtualized target. In case of a mismatch, fall back to indirect
1264 // call.
1265 if (DevirtCheckMode == WPDCheckMode::Fallback || DevirtSpeculatively) {
1266 MDNode *Weights = MDBuilder(M.getContext()).createLikelyBranchWeights();
1267 // Version the indirect call site. If the called value is equal to the
1268 // given callee, 'NewInst' will be executed, otherwise the original call
1269 // site will be executed.
1270 CallBase &NewInst = versionCallSite(CB, Callee, Weights);
1271 NewInst.setCalledOperand(Callee);
1272 // Since the new call site is direct, we must clear metadata that
1273 // is only appropriate for indirect calls. This includes !prof and
1274 // !callees metadata.
1275 NewInst.setMetadata(LLVMContext::MD_prof, nullptr);
1276 NewInst.setMetadata(LLVMContext::MD_callees, nullptr);
1277 // Additionally, we should remove them from the fallback indirect call,
1278 // so that we don't attempt to perform indirect call promotion later.
1279 CB.setMetadata(LLVMContext::MD_prof, nullptr);
1280 CB.setMetadata(LLVMContext::MD_callees, nullptr);
1281 }
1282
1283 // In either trapping or non-checking mode, devirtualize original call.
1284 else {
1285 // Devirtualize unconditionally.
1286 CB.setCalledOperand(Callee);
1287 // Since the call site is now direct, we must clear metadata that
1288 // is only appropriate for indirect calls. This includes !prof and
1289 // !callees metadata.
1290 CB.setMetadata(LLVMContext::MD_prof, nullptr);
1291 CB.setMetadata(LLVMContext::MD_callees, nullptr);
1292 if (CB.getCalledOperand() &&
1294 auto *NewCS = CallBase::removeOperandBundle(
1296 CB.replaceAllUsesWith(NewCS);
1297 // Schedule for deletion at the end of pass run.
1298 CallsWithPtrAuthBundleRemoved.push_back(&CB);
1299 }
1300 }
1301
1302 // This use is no longer unsafe.
1303 if (VCallSite.NumUnsafeUses)
1304 --*VCallSite.NumUnsafeUses;
1305 }
1306 if (CSInfo.isExported())
1307 IsExported = true;
1308 CSInfo.markDevirt();
1309 };
1310 Apply(SlotInfo.CSInfo);
1311 for (auto &P : SlotInfo.ConstCSInfo)
1312 Apply(P.second);
1313}
1314
1315static bool addCalls(VTableSlotInfo &SlotInfo, const ValueInfo &Callee) {
1316 // We can't add calls if we haven't seen a definition
1317 if (Callee.getSummaryList().empty())
1318 return false;
1319
1320 // Insert calls into the summary index so that the devirtualized targets
1321 // are eligible for import.
1322 // FIXME: Annotate type tests with hotness. For now, mark these as hot
1323 // to better ensure we have the opportunity to inline them.
1324 bool IsExported = false;
1325 auto &S = Callee.getSummaryList()[0];
1326 CalleeInfo CI(CalleeInfo::HotnessType::Hot, /* HasTailCall = */ false);
1327 auto AddCalls = [&](CallSiteInfo &CSInfo) {
1328 for (auto *FS : CSInfo.SummaryTypeCheckedLoadUsers) {
1329 FS->addCall({Callee, CI});
1330 IsExported |= S->modulePath() != FS->modulePath();
1331 }
1332 for (auto *FS : CSInfo.SummaryTypeTestAssumeUsers) {
1333 FS->addCall({Callee, CI});
1334 IsExported |= S->modulePath() != FS->modulePath();
1335 }
1336 };
1337 AddCalls(SlotInfo.CSInfo);
1338 for (auto &P : SlotInfo.ConstCSInfo)
1339 AddCalls(P.second);
1340 return IsExported;
1341}
1342
1343bool DevirtModule::trySingleImplDevirt(
1344 ModuleSummaryIndex *ExportSummary,
1345 MutableArrayRef<VirtualCallTarget> TargetsForSlot, VTableSlotInfo &SlotInfo,
1346 WholeProgramDevirtResolution *Res) {
1347 // See if the program contains a single implementation of this virtual
1348 // function.
1349 auto *TheFn = TargetsForSlot[0].Fn;
1350 for (auto &&Target : TargetsForSlot)
1351 if (TheFn != Target.Fn)
1352 return false;
1353
1354 // If so, update each call site to call that implementation directly.
1355 if (RemarksEnabled || AreStatisticsEnabled())
1356 TargetsForSlot[0].WasDevirt = true;
1357
1358 bool IsExported = false;
1359 applySingleImplDevirt(SlotInfo, TheFn, IsExported);
1360 if (!IsExported)
1361 return false;
1362
1363 // If the only implementation has local linkage, we must promote to external
1364 // to make it visible to thin LTO objects. We can only get here during the
1365 // ThinLTO export phase.
1366 if (TheFn->hasLocalLinkage()) {
1367 std::string NewName = (TheFn->getName() + ".llvm.merged").str();
1368
1369 // Since we are renaming the function, any comdats with the same name must
1370 // also be renamed. This is required when targeting COFF, as the comdat name
1371 // must match one of the names of the symbols in the comdat.
1372 if (Comdat *C = TheFn->getComdat()) {
1373 if (C->getName() == TheFn->getName()) {
1374 Comdat *NewC = M.getOrInsertComdat(NewName);
1375 NewC->setSelectionKind(C->getSelectionKind());
1376 for (GlobalObject &GO : M.global_objects())
1377 if (GO.getComdat() == C)
1378 GO.setComdat(NewC);
1379 }
1380 }
1381
1382 TheFn->setLinkage(GlobalValue::ExternalLinkage);
1383 TheFn->setVisibility(GlobalValue::HiddenVisibility);
1384 TheFn->setName(NewName);
1385 }
1386 if (ValueInfo TheFnVI = ExportSummary->getValueInfo(TheFn->getGUID()))
1387 // Any needed promotion of 'TheFn' has already been done during
1388 // LTO unit split, so we can ignore return value of AddCalls.
1389 addCalls(SlotInfo, TheFnVI);
1390
1392 Res->SingleImplName = std::string(TheFn->getName());
1393
1394 return true;
1395}
1396
1397bool DevirtIndex::trySingleImplDevirt(MutableArrayRef<ValueInfo> TargetsForSlot,
1398 VTableSlotSummary &SlotSummary,
1399 VTableSlotInfo &SlotInfo,
1400 WholeProgramDevirtResolution *Res,
1401 std::set<ValueInfo> &DevirtTargets) {
1402 // See if the program contains a single implementation of this virtual
1403 // function.
1404 auto TheFn = TargetsForSlot[0];
1405 for (auto &&Target : TargetsForSlot)
1406 if (TheFn != Target)
1407 return false;
1408
1409 // Don't devirtualize if we don't have target definition.
1410 auto Size = TheFn.getSummaryList().size();
1411 if (!Size)
1412 return false;
1413
1414 // Don't devirtualize function if we're told to skip it
1415 // in -wholeprogramdevirt-skip.
1416 if (FunctionsToSkip.match(TheFn.name()))
1417 return false;
1418
1419 // If the summary list contains multiple summaries where at least one is
1420 // a local, give up, as we won't know which (possibly promoted) name to use.
1421 if (TheFn.hasLocal() && Size > 1)
1422 return false;
1423
1424 // Collect functions devirtualized at least for one call site for stats.
1426 DevirtTargets.insert(TheFn);
1427
1428 auto &S = TheFn.getSummaryList()[0];
1429 bool IsExported = addCalls(SlotInfo, TheFn);
1430 if (IsExported)
1431 ExportedGUIDs.insert(TheFn.getGUID());
1432
1433 // Record in summary for use in devirtualization during the ThinLTO import
1434 // step.
1436 if (GlobalValue::isLocalLinkage(S->linkage())) {
1437 if (IsExported) {
1438 // If target is a local function and we are exporting it by
1439 // devirtualizing a call in another module, we need to record the
1440 // promoted name.
1441 if (ExternallyVisibleSymbolNamesPtr)
1442 ExternallyVisibleSymbolNamesPtr->insert(TheFn.name());
1444 TheFn.name(), ExportSummary.getModuleHash(S->modulePath()));
1445 } else {
1446 LocalWPDTargetsMap[TheFn].push_back(SlotSummary);
1447 Res->SingleImplName = std::string(TheFn.name());
1448 }
1449 } else
1450 Res->SingleImplName = std::string(TheFn.name());
1451
1452 // Name will be empty if this thin link driven off of serialized combined
1453 // index (e.g. llvm-lto). However, WPD is not supported/invoked for the
1454 // legacy LTO API anyway.
1455 assert(!Res->SingleImplName.empty());
1456
1457 return true;
1458}
1459
1460void DevirtModule::tryICallBranchFunnel(
1461 MutableArrayRef<VirtualCallTarget> TargetsForSlot, VTableSlotInfo &SlotInfo,
1462 WholeProgramDevirtResolution *Res, VTableSlot Slot) {
1463 Triple T(M.getTargetTriple());
1464 if (T.getArch() != Triple::x86_64)
1465 return;
1466
1467 if (TargetsForSlot.size() > ClThreshold)
1468 return;
1469
1470 bool HasNonDevirt = !SlotInfo.CSInfo.AllCallSitesDevirted;
1471 if (!HasNonDevirt)
1472 for (auto &P : SlotInfo.ConstCSInfo)
1473 if (!P.second.AllCallSitesDevirted) {
1474 HasNonDevirt = true;
1475 break;
1476 }
1477
1478 if (!HasNonDevirt)
1479 return;
1480
1481 // If any GV is AvailableExternally, not to generate branch.funnel.
1482 // NOTE: It is to avoid crash in LowerTypeTest.
1483 // If the branch.funnel is generated, because GV.isDeclarationForLinker(),
1484 // in LowerTypeTestsModule::lower(), its GlobalTypeMember would NOT
1485 // be saved in GlobalTypeMembers[&GV]. Then crash happens in
1486 // buildBitSetsFromDisjointSet due to GlobalTypeMembers[&GV] is NULL.
1487 // Even doing experiment to save it in GlobalTypeMembers[&GV] and
1488 // making GlobalTypeMembers[&GV] be not NULL, crash could avoid from
1489 // buildBitSetsFromDisjointSet. But still report_fatal_error in Verifier
1490 // or SelectionDAGBuilder later, because operands linkage type consistency
1491 // check of icall.branch.funnel can not pass.
1492 for (auto &T : TargetsForSlot) {
1493 if (T.TM->Bits->GV->hasAvailableExternallyLinkage())
1494 return;
1495 }
1496
1497 FunctionType *FT =
1498 FunctionType::get(Type::getVoidTy(M.getContext()), {Int8PtrTy}, true);
1499 Function *JT;
1500 if (isa<MDString>(Slot.TypeID)) {
1502 M.getDataLayout().getProgramAddressSpace(),
1503 getGlobalName(Slot, {}, "branch_funnel"), &M);
1505 } else {
1507 M.getDataLayout().getProgramAddressSpace(),
1508 "branch_funnel", &M);
1509 }
1510 JT->addParamAttr(0, Attribute::Nest);
1511
1512 std::vector<Value *> JTArgs;
1513 JTArgs.push_back(JT->arg_begin());
1514 for (auto &T : TargetsForSlot) {
1515 JTArgs.push_back(getMemberAddr(T.TM));
1516 JTArgs.push_back(T.Fn);
1517 }
1518
1519 BasicBlock *BB = BasicBlock::Create(M.getContext(), "", JT, nullptr);
1521 &M, llvm::Intrinsic::icall_branch_funnel, {});
1522
1523 auto *CI = CallInst::Create(Intr, JTArgs, "", BB);
1524 CI->setTailCallKind(CallInst::TCK_MustTail);
1525 ReturnInst::Create(M.getContext(), nullptr, BB);
1526
1527 bool IsExported = false;
1528 applyICallBranchFunnel(SlotInfo, *JT, IsExported);
1529 if (IsExported)
1531
1532 if (!JT->getEntryCount().has_value()) {
1533 // FIXME: we could pass through thinlto the necessary information.
1535 }
1536}
1537
1538void DevirtModule::applyICallBranchFunnel(VTableSlotInfo &SlotInfo,
1539 Function &JT, bool &IsExported) {
1540 DenseMap<Function *, double> FunctionEntryCounts;
1541 auto Apply = [&](CallSiteInfo &CSInfo) {
1542 if (CSInfo.isExported())
1543 IsExported = true;
1544 if (CSInfo.AllCallSitesDevirted)
1545 return;
1546
1547 std::map<CallBase *, CallBase *> CallBases;
1548 for (auto &&VCallSite : CSInfo.CallSites) {
1549 CallBase &CB = VCallSite.CB;
1550
1551 if (CallBases.find(&CB) != CallBases.end()) {
1552 // When finding devirtualizable calls, it's possible to find the same
1553 // vtable passed to multiple llvm.type.test or llvm.type.checked.load
1554 // calls, which can cause duplicate call sites to be recorded in
1555 // [Const]CallSites. If we've already found one of these
1556 // call instances, just ignore it. It will be replaced later.
1557 continue;
1558 }
1559
1560 // Jump tables are only profitable if the retpoline mitigation is enabled.
1561 Attribute FSAttr = CB.getCaller()->getFnAttribute("target-features");
1562 if (!FSAttr.isValid() ||
1563 !FSAttr.getValueAsString().contains("+retpoline"))
1564 continue;
1565
1566 NumBranchFunnel++;
1567 if (RemarksEnabled)
1568 VCallSite.emitRemark("branch-funnel", JT.getName(), OREGetter);
1569
1570 // Pass the address of the vtable in the nest register, which is r10 on
1571 // x86_64.
1572 std::vector<Type *> NewArgs;
1573 NewArgs.push_back(Int8PtrTy);
1574 append_range(NewArgs, CB.getFunctionType()->params());
1575 FunctionType *NewFT =
1577 CB.getFunctionType()->isVarArg());
1578 IRBuilder<> IRB(&CB);
1579 std::vector<Value *> Args;
1580 Args.push_back(VCallSite.VTable);
1581 llvm::append_range(Args, CB.args());
1582
1583 CallBase *NewCS = nullptr;
1585 // Accumulate the call frequencies of the original call site, and use
1586 // that as total entry count for the funnel function.
1587 auto &F = *CB.getCaller();
1588 auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
1589 auto EC = BFI.getBlockFreq(&F.getEntryBlock());
1590 auto CC = F.getEntryCount(/*AllowSynthetic=*/true);
1591 double CallCount = 0.0;
1592 if (EC.getFrequency() != 0 && CC && CC->getCount() != 0) {
1593 double CallFreq =
1594 static_cast<double>(
1595 BFI.getBlockFreq(CB.getParent()).getFrequency()) /
1596 EC.getFrequency();
1597 CallCount = CallFreq * CC->getCount();
1598 }
1599 FunctionEntryCounts[&JT] += CallCount;
1600 }
1601 if (isa<CallInst>(CB))
1602 NewCS = IRB.CreateCall(NewFT, &JT, Args);
1603 else
1604 NewCS =
1605 IRB.CreateInvoke(NewFT, &JT, cast<InvokeInst>(CB).getNormalDest(),
1606 cast<InvokeInst>(CB).getUnwindDest(), Args);
1607 NewCS->setCallingConv(CB.getCallingConv());
1608
1609 AttributeList Attrs = CB.getAttributes();
1610 std::vector<AttributeSet> NewArgAttrs;
1611 NewArgAttrs.push_back(AttributeSet::get(
1612 M.getContext(), ArrayRef<Attribute>{Attribute::get(
1613 M.getContext(), Attribute::Nest)}));
1614 for (unsigned I = 0; I + 2 < Attrs.getNumAttrSets(); ++I)
1615 NewArgAttrs.push_back(Attrs.getParamAttrs(I));
1616 NewCS->setAttributes(
1617 AttributeList::get(M.getContext(), Attrs.getFnAttrs(),
1618 Attrs.getRetAttrs(), NewArgAttrs));
1619
1620 CallBases[&CB] = NewCS;
1621
1622 // This use is no longer unsafe.
1623 if (VCallSite.NumUnsafeUses)
1624 --*VCallSite.NumUnsafeUses;
1625 }
1626 // Don't mark as devirtualized because there may be callers compiled without
1627 // retpoline mitigation, which would mean that they are lowered to
1628 // llvm.type.test and therefore require an llvm.type.test resolution for the
1629 // type identifier.
1630
1631 for (auto &[Old, New] : CallBases) {
1632 Old->replaceAllUsesWith(New);
1633 Old->eraseFromParent();
1634 }
1635 };
1636 Apply(SlotInfo.CSInfo);
1637 for (auto &P : SlotInfo.ConstCSInfo)
1638 Apply(P.second);
1639 for (auto &[F, C] : FunctionEntryCounts) {
1640 assert(!F->getEntryCount(/*AllowSynthetic=*/true) &&
1641 "Unexpected entry count for funnel that was freshly synthesized");
1642 F->setEntryCount(static_cast<uint64_t>(std::round(C)));
1643 }
1644}
1645
1646bool DevirtModule::tryEvaluateFunctionsWithArgs(
1648 ArrayRef<uint64_t> Args) {
1649 // Evaluate each function and store the result in each target's RetVal
1650 // field.
1651 for (VirtualCallTarget &Target : TargetsForSlot) {
1652 // TODO: Skip for now if the vtable symbol was an alias to a function,
1653 // need to evaluate whether it would be correct to analyze the aliasee
1654 // function for this optimization.
1655 auto *Fn = dyn_cast<Function>(Target.Fn);
1656 if (!Fn)
1657 return false;
1658
1659 if (Fn->arg_size() != Args.size() + 1)
1660 return false;
1661
1662 Evaluator Eval(M.getDataLayout(), nullptr);
1664 EvalArgs.push_back(
1666 for (unsigned I = 0; I != Args.size(); ++I) {
1667 auto *ArgTy =
1669 if (!ArgTy)
1670 return false;
1671 EvalArgs.push_back(ConstantInt::get(ArgTy, Args[I]));
1672 }
1673
1674 Constant *RetVal;
1675 if (!Eval.EvaluateFunction(Fn, RetVal, EvalArgs) ||
1676 !isa<ConstantInt>(RetVal))
1677 return false;
1678 Target.RetVal = cast<ConstantInt>(RetVal)->getZExtValue();
1679 }
1680 return true;
1681}
1682
1683void DevirtModule::applyUniformRetValOpt(CallSiteInfo &CSInfo, StringRef FnName,
1684 uint64_t TheRetVal) {
1685 for (auto Call : CSInfo.CallSites) {
1686 if (!OptimizedCalls.insert(&Call.CB).second)
1687 continue;
1688 NumUniformRetVal++;
1689 Call.replaceAndErase(
1690 "uniform-ret-val", FnName, RemarksEnabled, OREGetter,
1691 ConstantInt::get(cast<IntegerType>(Call.CB.getType()), TheRetVal));
1692 }
1693 CSInfo.markDevirt();
1694}
1695
1696bool DevirtModule::tryUniformRetValOpt(
1697 MutableArrayRef<VirtualCallTarget> TargetsForSlot, CallSiteInfo &CSInfo,
1698 WholeProgramDevirtResolution::ByArg *Res) {
1699 // Uniform return value optimization. If all functions return the same
1700 // constant, replace all calls with that constant.
1701 uint64_t TheRetVal = TargetsForSlot[0].RetVal;
1702 for (const VirtualCallTarget &Target : TargetsForSlot)
1703 if (Target.RetVal != TheRetVal)
1704 return false;
1705
1706 if (CSInfo.isExported()) {
1708 Res->Info = TheRetVal;
1709 }
1710
1711 applyUniformRetValOpt(CSInfo, TargetsForSlot[0].Fn->getName(), TheRetVal);
1712 if (RemarksEnabled || AreStatisticsEnabled())
1713 for (auto &&Target : TargetsForSlot)
1714 Target.WasDevirt = true;
1715 return true;
1716}
1717
1718std::string DevirtModule::getGlobalName(VTableSlot Slot,
1719 ArrayRef<uint64_t> Args,
1720 StringRef Name) {
1721 std::string FullName = "__typeid_";
1722 raw_string_ostream OS(FullName);
1723 OS << cast<MDString>(Slot.TypeID)->getString() << '_' << Slot.ByteOffset;
1724 for (uint64_t Arg : Args)
1725 OS << '_' << Arg;
1726 OS << '_' << Name;
1727 return FullName;
1728}
1729
1730bool DevirtModule::shouldExportConstantsAsAbsoluteSymbols() {
1731 Triple T(M.getTargetTriple());
1732 return T.isX86() && T.getObjectFormat() == Triple::ELF;
1733}
1734
1735void DevirtModule::exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
1736 StringRef Name, Constant *C) {
1737 GlobalAlias *GA = GlobalAlias::create(Int8Ty, 0, GlobalValue::ExternalLinkage,
1738 getGlobalName(Slot, Args, Name), C, &M);
1740}
1741
1742void DevirtModule::exportConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
1743 StringRef Name, uint32_t Const,
1744 uint32_t &Storage) {
1745 if (shouldExportConstantsAsAbsoluteSymbols()) {
1746 exportGlobal(
1747 Slot, Args, Name,
1748 ConstantExpr::getIntToPtr(ConstantInt::get(Int32Ty, Const), Int8PtrTy));
1749 return;
1750 }
1751
1752 Storage = Const;
1753}
1754
1755Constant *DevirtModule::importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
1756 StringRef Name) {
1757 GlobalVariable *GV =
1758 M.getOrInsertGlobal(getGlobalName(Slot, Args, Name), Int8Arr0Ty);
1760 return GV;
1761}
1762
1763Constant *DevirtModule::importConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
1764 StringRef Name, IntegerType *IntTy,
1765 uint32_t Storage) {
1766 if (!shouldExportConstantsAsAbsoluteSymbols())
1767 return ConstantInt::get(IntTy, Storage);
1768
1769 Constant *C = importGlobal(Slot, Args, Name);
1770 auto *GV = cast<GlobalVariable>(C->stripPointerCasts());
1771 C = ConstantExpr::getPtrToInt(C, IntTy);
1772
1773 // We only need to set metadata if the global is newly created, in which
1774 // case it would not have hidden visibility.
1775 if (GV->hasMetadata(LLVMContext::MD_absolute_symbol))
1776 return C;
1777
1778 auto SetAbsRange = [&](uint64_t Min, uint64_t Max) {
1779 auto *MinC = ConstantAsMetadata::get(ConstantInt::get(IntPtrTy, Min));
1780 auto *MaxC = ConstantAsMetadata::get(ConstantInt::get(IntPtrTy, Max));
1781 GV->setMetadata(LLVMContext::MD_absolute_symbol,
1782 MDNode::get(M.getContext(), {MinC, MaxC}));
1783 };
1784 unsigned AbsWidth = IntTy->getBitWidth();
1785 if (AbsWidth == IntPtrTy->getBitWidth()) {
1786 uint64_t AllOnes = IntTy->getBitMask();
1787 SetAbsRange(AllOnes, AllOnes); // Full set.
1788 } else {
1789 SetAbsRange(0, 1ull << AbsWidth);
1790 }
1791 return C;
1792}
1793
1794void DevirtModule::applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName,
1795 bool IsOne,
1796 Constant *UniqueMemberAddr) {
1797 for (auto &&Call : CSInfo.CallSites) {
1798 if (!OptimizedCalls.insert(&Call.CB).second)
1799 continue;
1800 IRBuilder<> B(&Call.CB);
1801 Value *Cmp =
1802 B.CreateICmp(IsOne ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE, Call.VTable,
1803 B.CreateBitCast(UniqueMemberAddr, Call.VTable->getType()));
1804 Cmp = B.CreateZExt(Cmp, Call.CB.getType());
1805 NumUniqueRetVal++;
1806 Call.replaceAndErase("unique-ret-val", FnName, RemarksEnabled, OREGetter,
1807 Cmp);
1808 }
1809 CSInfo.markDevirt();
1810}
1811
1812Constant *DevirtModule::getMemberAddr(const TypeMemberInfo *M) {
1813 return ConstantExpr::getPtrAdd(M->Bits->GV,
1814 ConstantInt::get(Int64Ty, M->Offset));
1815}
1816
1817bool DevirtModule::tryUniqueRetValOpt(
1818 unsigned BitWidth, MutableArrayRef<VirtualCallTarget> TargetsForSlot,
1819 CallSiteInfo &CSInfo, WholeProgramDevirtResolution::ByArg *Res,
1820 VTableSlot Slot, ArrayRef<uint64_t> Args) {
1821 // IsOne controls whether we look for a 0 or a 1.
1822 auto tryUniqueRetValOptFor = [&](bool IsOne) {
1823 const TypeMemberInfo *UniqueMember = nullptr;
1824 for (const VirtualCallTarget &Target : TargetsForSlot) {
1825 if (Target.RetVal == (IsOne ? 1 : 0)) {
1826 if (UniqueMember)
1827 return false;
1828 UniqueMember = Target.TM;
1829 }
1830 }
1831
1832 // We should have found a unique member or bailed out by now. We already
1833 // checked for a uniform return value in tryUniformRetValOpt.
1834 assert(UniqueMember);
1835
1836 Constant *UniqueMemberAddr = getMemberAddr(UniqueMember);
1837 if (CSInfo.isExported()) {
1839 Res->Info = IsOne;
1840
1841 exportGlobal(Slot, Args, "unique_member", UniqueMemberAddr);
1842 }
1843
1844 // Replace each call with the comparison.
1845 applyUniqueRetValOpt(CSInfo, TargetsForSlot[0].Fn->getName(), IsOne,
1846 UniqueMemberAddr);
1847
1848 // Update devirtualization statistics for targets.
1849 if (RemarksEnabled || AreStatisticsEnabled())
1850 for (auto &&Target : TargetsForSlot)
1851 Target.WasDevirt = true;
1852
1853 return true;
1854 };
1855
1856 if (BitWidth == 1) {
1857 if (tryUniqueRetValOptFor(true))
1858 return true;
1859 if (tryUniqueRetValOptFor(false))
1860 return true;
1861 }
1862 return false;
1863}
1864
1865void DevirtModule::applyVirtualConstProp(CallSiteInfo &CSInfo, StringRef FnName,
1866 Constant *Byte, Constant *Bit) {
1867 for (auto Call : CSInfo.CallSites) {
1868 if (!OptimizedCalls.insert(&Call.CB).second)
1869 continue;
1870 auto *RetType = cast<IntegerType>(Call.CB.getType());
1871 IRBuilder<> B(&Call.CB);
1872 Value *Addr = B.CreatePtrAdd(Call.VTable, Byte);
1873 if (RetType->getBitWidth() == 1) {
1874 Value *Bits = B.CreateLoad(Int8Ty, Addr);
1875 Value *BitsAndBit = B.CreateAnd(Bits, Bit);
1876 auto IsBitSet = B.CreateICmpNE(BitsAndBit, ConstantInt::get(Int8Ty, 0));
1877 NumVirtConstProp1Bit++;
1878 Call.replaceAndErase("virtual-const-prop-1-bit", FnName, RemarksEnabled,
1879 OREGetter, IsBitSet);
1880 } else {
1881 Value *Val = B.CreateLoad(RetType, Addr);
1882 NumVirtConstProp++;
1883 Call.replaceAndErase("virtual-const-prop", FnName, RemarksEnabled,
1884 OREGetter, Val);
1885 }
1886 }
1887 CSInfo.markDevirt();
1888}
1889
1890bool DevirtModule::tryVirtualConstProp(
1891 MutableArrayRef<VirtualCallTarget> TargetsForSlot, VTableSlotInfo &SlotInfo,
1892 WholeProgramDevirtResolution *Res, VTableSlot Slot) {
1893 // TODO: Skip for now if the vtable symbol was an alias to a function,
1894 // need to evaluate whether it would be correct to analyze the aliasee
1895 // function for this optimization.
1896 auto *Fn = dyn_cast<Function>(TargetsForSlot[0].Fn);
1897 if (!Fn)
1898 return false;
1899 // This only works if the function returns an integer.
1900 auto *RetType = dyn_cast<IntegerType>(Fn->getReturnType());
1901 if (!RetType)
1902 return false;
1903 unsigned BitWidth = RetType->getBitWidth();
1904
1905 // TODO: Since we can evaluated these constants at compile-time, we can save
1906 // some space by calculating the smallest range of values that all these
1907 // constants can fit in, then only allocate enough space to fit those values.
1908 // At each callsite, we can get the original type by doing a sign/zero
1909 // extension. For example, if we would store an i64, but we can see that all
1910 // the values fit into an i16, then we can store an i16 before/after the
1911 // vtable and at each callsite do a s/zext.
1912 if (BitWidth > 64)
1913 return false;
1914
1915 Align TypeAlignment = M.getDataLayout().getABIIntegerTypeAlignment(BitWidth);
1916
1917 // Make sure that each function is defined, does not access memory, takes at
1918 // least one argument, does not use its first argument (which we assume is
1919 // 'this'), and has the same return type.
1920 //
1921 // Note that we test whether this copy of the function is readnone, rather
1922 // than testing function attributes, which must hold for any copy of the
1923 // function, even a less optimized version substituted at link time. This is
1924 // sound because the virtual constant propagation optimizations effectively
1925 // inline all implementations of the virtual function into each call site,
1926 // rather than using function attributes to perform local optimization.
1927 for (VirtualCallTarget &Target : TargetsForSlot) {
1928 // TODO: Skip for now if the vtable symbol was an alias to a function,
1929 // need to evaluate whether it would be correct to analyze the aliasee
1930 // function for this optimization.
1931 auto *Fn = dyn_cast<Function>(Target.Fn);
1932 if (!Fn)
1933 return false;
1934
1935 if (Fn->isDeclaration() ||
1936 !computeFunctionBodyMemoryAccess(*Fn, FAM.getResult<AAManager>(*Fn))
1938 Fn->arg_empty() || !Fn->arg_begin()->use_empty() ||
1939 Fn->getReturnType() != RetType)
1940 return false;
1941
1942 // This only works if the integer size is at most the alignment of the
1943 // vtable. If the table is underaligned, then we can't guarantee that the
1944 // constant will always be aligned to the integer type alignment. For
1945 // example, if the table is `align 1`, we can never guarantee that an i32
1946 // stored before/after the vtable is 32-bit aligned without changing the
1947 // alignment of the new global.
1948 GlobalVariable *GV = Target.TM->Bits->GV;
1949 Align TableAlignment = M.getDataLayout().getValueOrABITypeAlignment(
1950 GV->getAlign(), GV->getValueType());
1951 if (TypeAlignment > TableAlignment)
1952 return false;
1953 }
1954
1955 for (auto &&CSByConstantArg : SlotInfo.ConstCSInfo) {
1956 if (!tryEvaluateFunctionsWithArgs(TargetsForSlot, CSByConstantArg.first))
1957 continue;
1958
1959 WholeProgramDevirtResolution::ByArg *ResByArg = nullptr;
1960 if (Res)
1961 ResByArg = &Res->ResByArg[CSByConstantArg.first];
1962
1963 if (tryUniformRetValOpt(TargetsForSlot, CSByConstantArg.second, ResByArg))
1964 continue;
1965
1966 if (tryUniqueRetValOpt(BitWidth, TargetsForSlot, CSByConstantArg.second,
1967 ResByArg, Slot, CSByConstantArg.first))
1968 continue;
1969
1970 // Find an allocation offset in bits in all vtables associated with the
1971 // type.
1972 // TODO: If there would be "holes" in the vtable that were added by
1973 // padding, we could place i1s there to reduce any extra padding that
1974 // would be introduced by the i1s.
1975 uint64_t AllocBefore =
1976 findLowestOffset(TargetsForSlot, /*IsAfter=*/false, BitWidth);
1977 uint64_t AllocAfter =
1978 findLowestOffset(TargetsForSlot, /*IsAfter=*/true, BitWidth);
1979
1980 // Calculate the total amount of padding needed to store a value at both
1981 // ends of the object.
1982 uint64_t TotalPaddingBefore = 0, TotalPaddingAfter = 0;
1983 for (auto &&Target : TargetsForSlot) {
1984 TotalPaddingBefore += std::max<int64_t>(
1985 (AllocBefore + 7) / 8 - Target.allocatedBeforeBytes() - 1, 0);
1986 TotalPaddingAfter += std::max<int64_t>(
1987 (AllocAfter + 7) / 8 - Target.allocatedAfterBytes() - 1, 0);
1988 }
1989
1990 // If the amount of padding is too large, give up.
1991 // FIXME: do something smarter here.
1992 if (std::min(TotalPaddingBefore, TotalPaddingAfter) > 128)
1993 continue;
1994
1995 // Calculate the offset to the value as a (possibly negative) byte offset
1996 // and (if applicable) a bit offset, and store the values in the targets.
1997 int64_t OffsetByte;
1998 uint64_t OffsetBit;
1999 if (TotalPaddingBefore <= TotalPaddingAfter)
2000 setBeforeReturnValues(TargetsForSlot, AllocBefore, BitWidth, OffsetByte,
2001 OffsetBit);
2002 else
2003 setAfterReturnValues(TargetsForSlot, AllocAfter, BitWidth, OffsetByte,
2004 OffsetBit);
2005
2006 // In an earlier check we forbade constant propagation from operating on
2007 // tables whose alignment is less than the alignment needed for loading
2008 // the constant. Thus, the address we take the offset from will always be
2009 // aligned to at least this integer alignment. Now, we need to ensure that
2010 // the offset is also aligned to this integer alignment to ensure we always
2011 // have an aligned load.
2012 assert(OffsetByte % TypeAlignment.value() == 0);
2013
2014 if (RemarksEnabled || AreStatisticsEnabled())
2015 for (auto &&Target : TargetsForSlot)
2016 Target.WasDevirt = true;
2017
2018
2019 if (CSByConstantArg.second.isExported()) {
2021 ResByArg->Byte = OffsetByte;
2022 exportConstant(Slot, CSByConstantArg.first, "bit", 1ULL << OffsetBit,
2023 ResByArg->Bit);
2024 }
2025
2026 // Rewrite each call to a load from OffsetByte/OffsetBit.
2027 Constant *ByteConst = ConstantInt::getSigned(Int32Ty, OffsetByte);
2028 Constant *BitConst = ConstantInt::get(Int8Ty, 1ULL << OffsetBit);
2029 applyVirtualConstProp(CSByConstantArg.second,
2030 TargetsForSlot[0].Fn->getName(), ByteConst, BitConst);
2031 }
2032 return true;
2033}
2034
2035void DevirtModule::rebuildGlobal(VTableBits &B) {
2036 if (B.Before.Bytes.empty() && B.After.Bytes.empty())
2037 return;
2038
2039 // Align the before byte array to the global's minimum alignment so that we
2040 // don't break any alignment requirements on the global.
2041 Align Alignment = M.getDataLayout().getValueOrABITypeAlignment(
2042 B.GV->getAlign(), B.GV->getValueType());
2043 B.Before.Bytes.resize(alignTo(B.Before.Bytes.size(), Alignment));
2044
2045 // Before was stored in reverse order; flip it now.
2046 for (size_t I = 0, Size = B.Before.Bytes.size(); I != Size / 2; ++I)
2047 std::swap(B.Before.Bytes[I], B.Before.Bytes[Size - 1 - I]);
2048
2049 // Build an anonymous global containing the before bytes, followed by the
2050 // original initializer, followed by the after bytes.
2051 auto *NewInit = ConstantStruct::getAnon(
2052 {ConstantDataArray::get(M.getContext(), B.Before.Bytes),
2053 B.GV->getInitializer(),
2054 ConstantDataArray::get(M.getContext(), B.After.Bytes)});
2055 auto *NewGV =
2056 new GlobalVariable(M, NewInit->getType(), B.GV->isConstant(),
2057 GlobalVariable::PrivateLinkage, NewInit, "", B.GV);
2058 NewGV->setSection(B.GV->getSection());
2059 NewGV->setComdat(B.GV->getComdat());
2060 NewGV->setAlignment(B.GV->getAlign());
2061
2062 // Copy the original vtable's metadata to the anonymous global, adjusting
2063 // offsets as required.
2064 NewGV->copyMetadata(B.GV, B.Before.Bytes.size());
2065
2066 // Build an alias named after the original global, pointing at the second
2067 // element (the original initializer).
2068 auto *Alias = GlobalAlias::create(
2069 B.GV->getInitializer()->getType(), 0, B.GV->getLinkage(), "",
2071 NewInit->getType(), NewGV,
2072 ArrayRef<Constant *>{ConstantInt::get(Int32Ty, 0),
2073 ConstantInt::get(Int32Ty, 1)}),
2074 &M);
2075 Alias->setVisibility(B.GV->getVisibility());
2076 Alias->takeName(B.GV);
2077
2078 B.GV->replaceAllUsesWith(Alias);
2079 B.GV->eraseFromParent();
2080}
2081
2082bool DevirtModule::areRemarksEnabled() {
2083 const auto &FL = M.getFunctionList();
2084 for (const Function &Fn : FL) {
2085 if (Fn.empty())
2086 continue;
2087 auto DI = OptimizationRemark(DEBUG_TYPE, "", DebugLoc(), &Fn.front());
2088 return DI.isEnabled();
2089 }
2090 return false;
2091}
2092
2093void DevirtModule::scanTypeTestUsers(
2094 Function *TypeTestFunc,
2095 DenseMap<Metadata *, std::set<TypeMemberInfo>> &TypeIdMap) {
2096 // Find all virtual calls via a virtual table pointer %p under an assumption
2097 // of the form llvm.assume(llvm.type.test(%p, %md)) or
2098 // llvm.assume(llvm.public.type.test(%p, %md)).
2099 // This indicates that %p points to a member of the type identifier %md.
2100 // Group calls by (type ID, offset) pair (effectively the identity of the
2101 // virtual function) and store to CallSlots.
2102 for (Use &U : llvm::make_early_inc_range(TypeTestFunc->uses())) {
2103 auto *CI = dyn_cast<CallInst>(U.getUser());
2104 if (!CI)
2105 continue;
2106 // Search for virtual calls based on %p and add them to DevirtCalls.
2109 auto &DT = FAM.getResult<DominatorTreeAnalysis>(*CI->getFunction());
2110 findDevirtualizableCallsForTypeTest(DevirtCalls, Assumes, CI, DT);
2111
2112 Metadata *TypeId =
2113 cast<MetadataAsValue>(CI->getArgOperand(1))->getMetadata();
2114 // If we found any, add them to CallSlots.
2115 if (!Assumes.empty()) {
2116 Value *Ptr = CI->getArgOperand(0)->stripPointerCasts();
2117 for (DevirtCallSite Call : DevirtCalls)
2118 CallSlots[{TypeId, Call.Offset}].addCallSite(Ptr, Call.CB, nullptr);
2119 }
2120
2121 auto RemoveTypeTestAssumes = [&]() {
2122 // We no longer need the assumes or the type test.
2123 for (auto *Assume : Assumes)
2124 Assume->eraseFromParent();
2125 // We can't use RecursivelyDeleteTriviallyDeadInstructions here because we
2126 // may use the vtable argument later.
2127 if (CI->use_empty())
2128 CI->eraseFromParent();
2129 };
2130
2131 // At this point we could remove all type test assume sequences, as they
2132 // were originally inserted for WPD. However, we can keep these in the
2133 // code stream for later analysis (e.g. to help drive more efficient ICP
2134 // sequences). They will eventually be removed by a second LowerTypeTests
2135 // invocation that cleans them up. In order to do this correctly, the first
2136 // LowerTypeTests invocation needs to know that they have "Unknown" type
2137 // test resolution, so that they aren't treated as Unsat and lowered to
2138 // False, which will break any uses on assumes. Below we remove any type
2139 // test assumes that will not be treated as Unknown by LTT.
2140
2141 // The type test assumes will be treated by LTT as Unsat if the type id is
2142 // not used on a global (in which case it has no entry in the TypeIdMap).
2143 if (!TypeIdMap.count(TypeId))
2144 RemoveTypeTestAssumes();
2145
2146 // For ThinLTO importing, we need to remove the type test assumes if this is
2147 // an MDString type id without a corresponding TypeIdSummary. Any
2148 // non-MDString type ids are ignored and treated as Unknown by LTT, so their
2149 // type test assumes can be kept. If the MDString type id is missing a
2150 // TypeIdSummary (e.g. because there was no use on a vcall, preventing the
2151 // exporting phase of WPD from analyzing it), then it would be treated as
2152 // Unsat by LTT and we need to remove its type test assumes here. If not
2153 // used on a vcall we don't need them for later optimization use in any
2154 // case.
2155 else if (ImportSummary && isa<MDString>(TypeId)) {
2156 const TypeIdSummary *TidSummary =
2157 ImportSummary->getTypeIdSummary(cast<MDString>(TypeId)->getString());
2158 if (!TidSummary)
2159 RemoveTypeTestAssumes();
2160 else
2161 // If one was created it should not be Unsat, because if we reached here
2162 // the type id was used on a global.
2164 }
2165 }
2166}
2167
2168void DevirtModule::scanTypeCheckedLoadUsers(Function *TypeCheckedLoadFunc) {
2169 Function *TypeTestFunc =
2170 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::type_test);
2171
2172 for (Use &U : llvm::make_early_inc_range(TypeCheckedLoadFunc->uses())) {
2173 auto *CI = dyn_cast<CallInst>(U.getUser());
2174 if (!CI)
2175 continue;
2176
2177 Value *Ptr = CI->getArgOperand(0);
2178 Value *Offset = CI->getArgOperand(1);
2179 Value *TypeIdValue = CI->getArgOperand(2);
2180 Metadata *TypeId = cast<MetadataAsValue>(TypeIdValue)->getMetadata();
2181
2185 bool HasNonCallUses = false;
2186 auto &DT = FAM.getResult<DominatorTreeAnalysis>(*CI->getFunction());
2187 findDevirtualizableCallsForTypeCheckedLoad(DevirtCalls, LoadedPtrs, Preds,
2188 HasNonCallUses, CI, DT);
2189
2190 // Start by generating "pessimistic" code that explicitly loads the function
2191 // pointer from the vtable and performs the type check. If possible, we will
2192 // eliminate the load and the type check later.
2193
2194 // If possible, only generate the load at the point where it is used.
2195 // This helps avoid unnecessary spills.
2196 IRBuilder<> LoadB(
2197 (LoadedPtrs.size() == 1 && !HasNonCallUses) ? LoadedPtrs[0] : CI);
2198
2199 Value *LoadedValue = nullptr;
2200 if (TypeCheckedLoadFunc->getIntrinsicID() ==
2201 Intrinsic::type_checked_load_relative) {
2203 &M, Intrinsic::load_relative, {Int32Ty});
2204 LoadedValue = LoadB.CreateCall(LoadRelFunc, {Ptr, Offset});
2205 } else {
2206 Value *GEP = LoadB.CreatePtrAdd(Ptr, Offset);
2207 LoadedValue = LoadB.CreateLoad(Int8PtrTy, GEP);
2208 }
2209
2210 for (Instruction *LoadedPtr : LoadedPtrs) {
2211 LoadedPtr->replaceAllUsesWith(LoadedValue);
2212 LoadedPtr->eraseFromParent();
2213 }
2214
2215 // Likewise for the type test.
2216 IRBuilder<> CallB((Preds.size() == 1 && !HasNonCallUses) ? Preds[0] : CI);
2217 CallInst *TypeTestCall = CallB.CreateCall(TypeTestFunc, {Ptr, TypeIdValue});
2218
2219 for (Instruction *Pred : Preds) {
2220 Pred->replaceAllUsesWith(TypeTestCall);
2221 Pred->eraseFromParent();
2222 }
2223
2224 // We have already erased any extractvalue instructions that refer to the
2225 // intrinsic call, but the intrinsic may have other non-extractvalue uses
2226 // (although this is unlikely). In that case, explicitly build a pair and
2227 // RAUW it.
2228 if (!CI->use_empty()) {
2229 Value *Pair = PoisonValue::get(CI->getType());
2230 IRBuilder<> B(CI);
2231 Pair = B.CreateInsertValue(Pair, LoadedValue, {0});
2232 Pair = B.CreateInsertValue(Pair, TypeTestCall, {1});
2233 CI->replaceAllUsesWith(Pair);
2234 }
2235
2236 // The number of unsafe uses is initially the number of uses.
2237 auto &NumUnsafeUses = NumUnsafeUsesForTypeTest[TypeTestCall];
2238 NumUnsafeUses = DevirtCalls.size();
2239
2240 // If the function pointer has a non-call user, we cannot eliminate the type
2241 // check, as one of those users may eventually call the pointer. Increment
2242 // the unsafe use count to make sure it cannot reach zero.
2243 if (HasNonCallUses)
2244 ++NumUnsafeUses;
2245 for (DevirtCallSite Call : DevirtCalls) {
2246 CallSlots[{TypeId, Call.Offset}].addCallSite(Ptr, Call.CB,
2247 &NumUnsafeUses);
2248 }
2249
2250 CI->eraseFromParent();
2251 }
2252}
2253
2254void DevirtModule::importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo) {
2255 auto *TypeId = dyn_cast<MDString>(Slot.TypeID);
2256 if (!TypeId)
2257 return;
2258 const TypeIdSummary *TidSummary =
2259 ImportSummary->getTypeIdSummary(TypeId->getString());
2260 if (!TidSummary)
2261 return;
2262 auto ResI = TidSummary->WPDRes.find(Slot.ByteOffset);
2263 if (ResI == TidSummary->WPDRes.end())
2264 return;
2265 const WholeProgramDevirtResolution &Res = ResI->second;
2266
2268 assert(!Res.SingleImplName.empty());
2269 // The type of the function in the declaration is irrelevant because every
2270 // call site will cast it to the correct type.
2271 Constant *SingleImpl =
2272 cast<Constant>(M.getOrInsertFunction(Res.SingleImplName,
2273 Type::getVoidTy(M.getContext()))
2274 .getCallee());
2275
2276 // This is the import phase so we should not be exporting anything.
2277 bool IsExported = false;
2278 applySingleImplDevirt(SlotInfo, SingleImpl, IsExported);
2279 assert(!IsExported);
2280 }
2281
2282 for (auto &CSByConstantArg : SlotInfo.ConstCSInfo) {
2283 auto I = Res.ResByArg.find(CSByConstantArg.first);
2284 if (I == Res.ResByArg.end())
2285 continue;
2286 auto &ResByArg = I->second;
2287 // FIXME: We should figure out what to do about the "function name" argument
2288 // to the apply* functions, as the function names are unavailable during the
2289 // importing phase. For now we just pass the empty string. This does not
2290 // impact correctness because the function names are just used for remarks.
2291 switch (ResByArg.TheKind) {
2293 applyUniformRetValOpt(CSByConstantArg.second, "", ResByArg.Info);
2294 break;
2296 Constant *UniqueMemberAddr =
2297 importGlobal(Slot, CSByConstantArg.first, "unique_member");
2298 applyUniqueRetValOpt(CSByConstantArg.second, "", ResByArg.Info,
2299 UniqueMemberAddr);
2300 break;
2301 }
2303 Constant *Byte = ConstantInt::get(Int32Ty, ResByArg.Byte);
2304 Constant *Bit = importConstant(Slot, CSByConstantArg.first, "bit", Int8Ty,
2305 ResByArg.Bit);
2306 applyVirtualConstProp(CSByConstantArg.second, "", Byte, Bit);
2307 break;
2308 }
2309 default:
2310 break;
2311 }
2312 }
2313
2315 // The type of the function is irrelevant, because it's bitcast at calls
2316 // anyhow.
2317 auto *JT = cast<Function>(
2318 M.getOrInsertFunction(getGlobalName(Slot, {}, "branch_funnel"),
2319 Type::getVoidTy(M.getContext()))
2320 .getCallee());
2321 bool IsExported = false;
2322 applyICallBranchFunnel(SlotInfo, *JT, IsExported);
2323 assert(!IsExported);
2324 }
2325}
2326
2327void DevirtModule::removeRedundantTypeTests() {
2328 auto *True = ConstantInt::getTrue(M.getContext());
2329 for (auto &&U : NumUnsafeUsesForTypeTest) {
2330 if (U.second == 0) {
2331 U.first->replaceAllUsesWith(True);
2332 U.first->eraseFromParent();
2333 }
2334 }
2335}
2336
2337ValueInfo
2338DevirtModule::lookUpFunctionValueInfo(Function *TheFn,
2339 ModuleSummaryIndex *ExportSummary) {
2340 assert((ExportSummary != nullptr) &&
2341 "Caller guarantees ExportSummary is not nullptr");
2342
2343 const auto TheFnGUID = TheFn->getGUID();
2344 const auto TheFnGUIDWithExportedName =
2346 // Look up ValueInfo with the GUID in the current linkage.
2347 ValueInfo TheFnVI = ExportSummary->getValueInfo(TheFnGUID);
2348 // If no entry is found and GUID is different from GUID computed using
2349 // exported name, look up ValueInfo with the exported name unconditionally.
2350 // This is a fallback.
2351 //
2352 // The reason to have a fallback:
2353 // 1. LTO could enable global value internalization via
2354 // `enable-lto-internalization`.
2355 // 2. The GUID in ExportedSummary is computed using exported name.
2356 if ((!TheFnVI) && (TheFnGUID != TheFnGUIDWithExportedName)) {
2357 TheFnVI = ExportSummary->getValueInfo(TheFnGUIDWithExportedName);
2358 }
2359 return TheFnVI;
2360}
2361
2362bool DevirtModule::mustBeUnreachableFunction(
2363 Function *const F, ModuleSummaryIndex *ExportSummary) {
2365 return false;
2366 // First, learn unreachability by analyzing function IR.
2367 if (!F->isDeclaration()) {
2368 // A function must be unreachable if its entry block ends with an
2369 // 'unreachable'.
2370 return isa<UnreachableInst>(F->getEntryBlock().getTerminator());
2371 }
2372 // Learn unreachability from ExportSummary if ExportSummary is present.
2373 return ExportSummary &&
2375 DevirtModule::lookUpFunctionValueInfo(F, ExportSummary));
2376}
2377
2378bool DevirtModule::run() {
2379 // If only some of the modules were split, we cannot correctly perform
2380 // this transformation. We already checked for the presense of type tests
2381 // with partially split modules during the thin link, and would have emitted
2382 // an error if any were found, so here we can simply return.
2383 if ((ExportSummary && ExportSummary->partiallySplitLTOUnits()) ||
2384 (ImportSummary && ImportSummary->partiallySplitLTOUnits()))
2385 return false;
2386
2387 Function *PublicTypeTestFunc = nullptr;
2388 // If we are in speculative devirtualization mode, we can work on the public
2389 // type test intrinsics.
2390 if (DevirtSpeculatively)
2391 PublicTypeTestFunc =
2392 Intrinsic::getDeclarationIfExists(&M, Intrinsic::public_type_test);
2393 Function *TypeTestFunc =
2394 Intrinsic::getDeclarationIfExists(&M, Intrinsic::type_test);
2395 Function *TypeCheckedLoadFunc =
2396 Intrinsic::getDeclarationIfExists(&M, Intrinsic::type_checked_load);
2397 Function *TypeCheckedLoadRelativeFunc = Intrinsic::getDeclarationIfExists(
2398 &M, Intrinsic::type_checked_load_relative);
2399 Function *AssumeFunc =
2400 Intrinsic::getDeclarationIfExists(&M, Intrinsic::assume);
2401
2402 // Normally if there are no users of the devirtualization intrinsics in the
2403 // module, this pass has nothing to do. But if we are exporting, we also need
2404 // to handle any users that appear only in the function summaries.
2405 if (!ExportSummary &&
2406 (((!PublicTypeTestFunc || PublicTypeTestFunc->use_empty()) &&
2407 (!TypeTestFunc || TypeTestFunc->use_empty())) ||
2408 !AssumeFunc || AssumeFunc->use_empty()) &&
2409 (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->use_empty()) &&
2410 (!TypeCheckedLoadRelativeFunc ||
2411 TypeCheckedLoadRelativeFunc->use_empty()))
2412 return false;
2413
2414 // Rebuild type metadata into a map for easy lookup.
2415 std::vector<VTableBits> Bits;
2416 DenseMap<Metadata *, std::set<TypeMemberInfo>> TypeIdMap;
2417 buildTypeIdentifierMap(Bits, TypeIdMap);
2418
2419 if (PublicTypeTestFunc && AssumeFunc)
2420 scanTypeTestUsers(PublicTypeTestFunc, TypeIdMap);
2421
2422 if (TypeTestFunc && AssumeFunc)
2423 scanTypeTestUsers(TypeTestFunc, TypeIdMap);
2424
2425 if (TypeCheckedLoadFunc)
2426 scanTypeCheckedLoadUsers(TypeCheckedLoadFunc);
2427
2428 if (TypeCheckedLoadRelativeFunc)
2429 scanTypeCheckedLoadUsers(TypeCheckedLoadRelativeFunc);
2430
2431 if (ImportSummary) {
2432 for (auto &S : CallSlots)
2433 importResolution(S.first, S.second);
2434
2435 removeRedundantTypeTests();
2436
2437 // We have lowered or deleted the type intrinsics, so we will no longer have
2438 // enough information to reason about the liveness of virtual function
2439 // pointers in GlobalDCE.
2440 for (GlobalVariable &GV : M.globals())
2441 GV.eraseMetadata(LLVMContext::MD_vcall_visibility);
2442
2443 // The rest of the code is only necessary when exporting or during regular
2444 // LTO, so we are done.
2445 return true;
2446 }
2447
2448 if (TypeIdMap.empty())
2449 return true;
2450
2451 // Collect information from summary about which calls to try to devirtualize.
2452 if (ExportSummary) {
2453 DenseMap<GlobalValue::GUID, TinyPtrVector<Metadata *>> MetadataByGUID;
2454 for (auto &P : TypeIdMap) {
2455 if (auto *TypeId = dyn_cast<MDString>(P.first))
2457 TypeId->getString())]
2458 .push_back(TypeId);
2459 }
2460
2461 for (auto &P : *ExportSummary) {
2462 for (auto &S : P.second.getSummaryList()) {
2463 auto *FS = dyn_cast<FunctionSummary>(S.get());
2464 if (!FS)
2465 continue;
2466 // FIXME: Only add live functions.
2467 for (FunctionSummary::VFuncId VF : FS->type_test_assume_vcalls()) {
2468 for (Metadata *MD : MetadataByGUID[VF.GUID]) {
2469 CallSlots[{MD, VF.Offset}].CSInfo.addSummaryTypeTestAssumeUser(FS);
2470 }
2471 }
2472 for (FunctionSummary::VFuncId VF : FS->type_checked_load_vcalls()) {
2473 for (Metadata *MD : MetadataByGUID[VF.GUID]) {
2474 CallSlots[{MD, VF.Offset}].CSInfo.addSummaryTypeCheckedLoadUser(FS);
2475 }
2476 }
2477 for (const FunctionSummary::ConstVCall &VC :
2478 FS->type_test_assume_const_vcalls()) {
2479 for (Metadata *MD : MetadataByGUID[VC.VFunc.GUID]) {
2480 CallSlots[{MD, VC.VFunc.Offset}]
2481 .ConstCSInfo[VC.Args]
2482 .addSummaryTypeTestAssumeUser(FS);
2483 }
2484 }
2485 for (const FunctionSummary::ConstVCall &VC :
2486 FS->type_checked_load_const_vcalls()) {
2487 for (Metadata *MD : MetadataByGUID[VC.VFunc.GUID]) {
2488 CallSlots[{MD, VC.VFunc.Offset}]
2489 .ConstCSInfo[VC.Args]
2490 .addSummaryTypeCheckedLoadUser(FS);
2491 }
2492 }
2493 }
2494 }
2495 }
2496
2497 // For each (type, offset) pair:
2498 bool DidVirtualConstProp = false;
2499 std::map<std::string, GlobalValue *> DevirtTargets;
2500 for (auto &S : CallSlots) {
2501 // Search each of the members of the type identifier for the virtual
2502 // function implementation at offset S.first.ByteOffset, and add to
2503 // TargetsForSlot.
2504 std::vector<VirtualCallTarget> TargetsForSlot;
2505 WholeProgramDevirtResolution *Res = nullptr;
2506 const std::set<TypeMemberInfo> &TypeMemberInfos = TypeIdMap[S.first.TypeID];
2507 if (ExportSummary && isa<MDString>(S.first.TypeID) &&
2508 TypeMemberInfos.size())
2509 // For any type id used on a global's type metadata, create the type id
2510 // summary resolution regardless of whether we can devirtualize, so that
2511 // lower type tests knows the type id is not Unsat. If it was not used on
2512 // a global's type metadata, the TypeIdMap entry set will be empty, and
2513 // we don't want to create an entry (with the default Unknown type
2514 // resolution), which can prevent detection of the Unsat.
2515 Res = &ExportSummary
2516 ->getOrInsertTypeIdSummary(
2517 cast<MDString>(S.first.TypeID)->getString())
2518 .WPDRes[S.first.ByteOffset];
2519 if (tryFindVirtualCallTargets(TargetsForSlot, TypeMemberInfos,
2520 S.first.ByteOffset, ExportSummary)) {
2521 bool SingleImplDevirt =
2522 trySingleImplDevirt(ExportSummary, TargetsForSlot, S.second, Res);
2523 // Out of speculative devirtualization mode, Try to apply virtual constant
2524 // propagation or branch funneling.
2525 // TODO: This should eventually be enabled for non-public type tests.
2526 if (!SingleImplDevirt && !DevirtSpeculatively) {
2527 DidVirtualConstProp |=
2528 tryVirtualConstProp(TargetsForSlot, S.second, Res, S.first);
2529
2530 tryICallBranchFunnel(TargetsForSlot, S.second, Res, S.first);
2531 }
2532
2533 // Collect functions devirtualized at least for one call site for stats.
2534 if (RemarksEnabled || AreStatisticsEnabled())
2535 for (const auto &T : TargetsForSlot)
2536 if (T.WasDevirt)
2537 DevirtTargets[std::string(T.Fn->getName())] = T.Fn;
2538 }
2539
2540 // CFI-specific: if we are exporting and any llvm.type.checked.load
2541 // intrinsics were *not* devirtualized, we need to add the resulting
2542 // llvm.type.test intrinsics to the function summaries so that the
2543 // LowerTypeTests pass will export them.
2544 if (ExportSummary && isa<MDString>(S.first.TypeID)) {
2546 cast<MDString>(S.first.TypeID)->getString());
2547 auto AddTypeTestsForTypeCheckedLoads = [&](CallSiteInfo &CSI) {
2548 if (!CSI.AllCallSitesDevirted)
2549 for (auto *FS : CSI.SummaryTypeCheckedLoadUsers)
2550 FS->addTypeTest(GUID);
2551 };
2552 AddTypeTestsForTypeCheckedLoads(S.second.CSInfo);
2553 for (auto &CCS : S.second.ConstCSInfo)
2554 AddTypeTestsForTypeCheckedLoads(CCS.second);
2555 }
2556 }
2557
2558 if (RemarksEnabled) {
2559 // Generate remarks for each devirtualized function.
2560 for (const auto &DT : DevirtTargets) {
2561 GlobalValue *GV = DT.second;
2562 auto *F = dyn_cast<Function>(GV);
2563 if (!F) {
2564 auto *A = dyn_cast<GlobalAlias>(GV);
2565 assert(A && isa<Function>(A->getAliasee()));
2566 F = dyn_cast<Function>(A->getAliasee());
2567 assert(F);
2568 }
2569
2570 using namespace ore;
2571 OREGetter(*F).emit(OptimizationRemark(DEBUG_TYPE, "Devirtualized", F)
2572 << "devirtualized " << NV("FunctionName", DT.first));
2573 }
2574 }
2575
2576 NumDevirtTargets += DevirtTargets.size();
2577
2578 removeRedundantTypeTests();
2579
2580 // Rebuild each global we touched as part of virtual constant propagation to
2581 // include the before and after bytes.
2582 if (DidVirtualConstProp)
2583 for (VTableBits &B : Bits)
2584 rebuildGlobal(B);
2585
2586 // We have lowered or deleted the type intrinsics, so we will no longer have
2587 // enough information to reason about the liveness of virtual function
2588 // pointers in GlobalDCE.
2589 for (GlobalVariable &GV : M.globals())
2590 GV.eraseMetadata(LLVMContext::MD_vcall_visibility);
2591
2592 for (auto *CI : CallsWithPtrAuthBundleRemoved)
2593 CI->eraseFromParent();
2594
2595 return true;
2596}
2597
2598void DevirtIndex::run() {
2599 if (ExportSummary.typeIdCompatibleVtableMap().empty())
2600 return;
2601
2602 // Assert that we haven't made any changes that would affect the hasLocal()
2603 // flag on the GUID summary info.
2604 assert(!ExportSummary.withInternalizeAndPromote() &&
2605 "Expect index-based WPD to run before internalization and promotion");
2606
2607 DenseMap<GlobalValue::GUID, std::vector<StringRef>> NameByGUID;
2608 for (const auto &P : ExportSummary.typeIdCompatibleVtableMap()) {
2609 NameByGUID[GlobalValue::getGUIDAssumingExternalLinkage(P.first)].push_back(
2610 P.first);
2611 // Create the type id summary resolution regardlness of whether we can
2612 // devirtualize, so that lower type tests knows the type id is used on
2613 // a global and not Unsat. We do this here rather than in the loop over the
2614 // CallSlots, since that handling will only see type tests that directly
2615 // feed assumes, and we would miss any that aren't currently handled by WPD
2616 // (such as type tests that feed assumes via phis).
2617 ExportSummary.getOrInsertTypeIdSummary(P.first);
2618 }
2619
2620 // Collect information from summary about which calls to try to devirtualize.
2621 for (auto &P : ExportSummary) {
2622 for (auto &S : P.second.getSummaryList()) {
2623 auto *FS = dyn_cast<FunctionSummary>(S.get());
2624 if (!FS)
2625 continue;
2626 // FIXME: Only add live functions.
2627 for (FunctionSummary::VFuncId VF : FS->type_test_assume_vcalls()) {
2628 for (StringRef Name : NameByGUID[VF.GUID]) {
2629 CallSlots[{Name, VF.Offset}].CSInfo.addSummaryTypeTestAssumeUser(FS);
2630 }
2631 }
2632 for (FunctionSummary::VFuncId VF : FS->type_checked_load_vcalls()) {
2633 for (StringRef Name : NameByGUID[VF.GUID]) {
2634 CallSlots[{Name, VF.Offset}].CSInfo.addSummaryTypeCheckedLoadUser(FS);
2635 }
2636 }
2637 for (const FunctionSummary::ConstVCall &VC :
2638 FS->type_test_assume_const_vcalls()) {
2639 for (StringRef Name : NameByGUID[VC.VFunc.GUID]) {
2640 CallSlots[{Name, VC.VFunc.Offset}]
2641 .ConstCSInfo[VC.Args]
2642 .addSummaryTypeTestAssumeUser(FS);
2643 }
2644 }
2645 for (const FunctionSummary::ConstVCall &VC :
2646 FS->type_checked_load_const_vcalls()) {
2647 for (StringRef Name : NameByGUID[VC.VFunc.GUID]) {
2648 CallSlots[{Name, VC.VFunc.Offset}]
2649 .ConstCSInfo[VC.Args]
2650 .addSummaryTypeCheckedLoadUser(FS);
2651 }
2652 }
2653 }
2654 }
2655
2656 std::set<ValueInfo> DevirtTargets;
2657 // For each (type, offset) pair:
2658 for (auto &S : CallSlots) {
2659 // Search each of the members of the type identifier for the virtual
2660 // function implementation at offset S.first.ByteOffset, and add to
2661 // TargetsForSlot.
2662 std::vector<ValueInfo> TargetsForSlot;
2663 auto TidSummary = ExportSummary.getTypeIdCompatibleVtableSummary(S.first.TypeID);
2664 assert(TidSummary);
2665 // The type id summary would have been created while building the NameByGUID
2666 // map earlier.
2667 WholeProgramDevirtResolution *Res =
2668 &ExportSummary.getTypeIdSummary(S.first.TypeID)
2669 ->WPDRes[S.first.ByteOffset];
2670 if (tryFindVirtualCallTargets(TargetsForSlot, *TidSummary,
2671 S.first.ByteOffset)) {
2672
2673 if (!trySingleImplDevirt(TargetsForSlot, S.first, S.second, Res,
2674 DevirtTargets))
2675 continue;
2676 }
2677 }
2678
2679 // Optionally have the thin link print message for each devirtualized
2680 // function.
2682 for (const auto &DT : DevirtTargets)
2683 errs() << "Devirtualized call to " << DT << "\n";
2684
2685 NumDevirtTargets += DevirtTargets.size();
2686}
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:173
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:621
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:337
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
GUID getGUID() const
Return a 64-bit global unique ID constructed from global value name (i.e.
@ HiddenVisibility
The GV is hidden.
Definition GlobalValue.h:69
void setVisibility(VisibilityTypes V)
@ 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:67
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)