LLVM 24.0.0git
WholeProgramDevirt.cpp File Reference
#include "llvm/Transforms/IPO/WholeProgramDevirt.h"
#include "IPOOptions.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TypeMetadataUtils.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSummaryIndexYAML.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DebugCounter.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/GlobPattern.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/FunctionAttrs.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/CallPromotionUtils.h"
#include "llvm/Transforms/Utils/Evaluator.h"
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <map>
#include <set>
#include <string>

Go to the source code of this file.

Classes

struct  llvm::DenseMapInfo< VTableSlot >
struct  llvm::DenseMapInfo< VTableSlotSummary >

Namespaces

namespace  llvm
 This is an optimization pass for GlobalISel generic memory operations.

Macros

#define DEBUG_TYPE   "wholeprogramdevirt"

Functions

 STATISTIC (NumDevirtTargets, "Number of whole program devirtualization targets")
 STATISTIC (NumSingleImpl, "Number of single implementation devirtualizations")
 STATISTIC (NumBranchFunnel, "Number of branch funnels")
 STATISTIC (NumUniformRetVal, "Number of uniform return value optimizations")
 STATISTIC (NumUniqueRetVal, "Number of unique return value optimizations")
 STATISTIC (NumVirtConstProp1Bit, "Number of 1 bit virtual constant propagations")
 STATISTIC (NumVirtConstProp, "Number of virtual constant propagations")
 DEBUG_COUNTER (CallsToDevirt, "calls-to-devirt", "Controls how many calls should be devirtualized.")
static bool mustBeUnreachableFunction (ValueInfo TheFnVI)
static bool typeIDVisibleToRegularObj (StringRef TypeID, function_ref< bool(StringRef)> IsVisibleToRegularObj)
static bool skipUpdateDueToValidation (GlobalVariable &GV, function_ref< bool(StringRef)> IsVisibleToRegularObj)
static Error checkCombinedSummaryForTesting (const IPOOptions &Opts, ModuleSummaryIndex *Summary)
static bool addCalls (VTableSlotInfo &SlotInfo, const ValueInfo &Callee)
static void findAssumesThroughMergesForTypeTest (SmallVectorImpl< CallInst * > &Assumes, CallInst &TypeTest, SmallPtrSetImpl< Value * > &VisitedMerges)
 Find assumes whose conditions depend on this type test through phi or select nodes.

Variables

static cl::opt< bool > llvm::PrintSummaryDevirt ("wholeprogramdevirt-print-index-based", cl::Hidden, cl::desc("Print index-based devirtualization messages"))
static cl::opt< bool > llvm::WholeProgramVisibility ("whole-program-visibility", cl::Hidden, cl::desc("Enable whole program visibility"))
 Provide a way to force enable whole program visibility in tests.
static cl::opt< bool > llvm::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 linker.
static cl::list< std::string > llvm::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< 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 by an unreachable IR instruction.

Macro Definition Documentation

◆ DEBUG_TYPE

#define DEBUG_TYPE   "wholeprogramdevirt"

Definition at line 126 of file WholeProgramDevirt.cpp.

Function Documentation

◆ addCalls()

bool addCalls ( VTableSlotInfo & SlotInfo,
const ValueInfo & Callee )
static

Definition at line 1270 of file WholeProgramDevirt.cpp.

References llvm::CalleeInfo::Hot, and P.

◆ checkCombinedSummaryForTesting()

Error checkCombinedSummaryForTesting ( const IPOOptions & Opts,
ModuleSummaryIndex * Summary )
static

◆ DEBUG_COUNTER()

DEBUG_COUNTER ( CallsToDevirt ,
"calls-to-devirt" ,
"Controls how many calls should be devirtualized."  )

◆ findAssumesThroughMergesForTypeTest()

void findAssumesThroughMergesForTypeTest ( SmallVectorImpl< CallInst * > & Assumes,
CallInst & TypeTest,
SmallPtrSetImpl< Value * > & VisitedMerges )
static

◆ mustBeUnreachableFunction()

bool mustBeUnreachableFunction ( ValueInfo TheFnVI)
static

◆ skipUpdateDueToValidation()

bool skipUpdateDueToValidation ( GlobalVariable & GV,
function_ref< bool(StringRef)> IsVisibleToRegularObj )
static

◆ STATISTIC() [1/7]

STATISTIC ( NumBranchFunnel ,
"Number of branch funnels"  )

◆ STATISTIC() [2/7]

STATISTIC ( NumDevirtTargets ,
"Number of whole program devirtualization targets"  )

◆ STATISTIC() [3/7]

STATISTIC ( NumSingleImpl ,
"Number of single implementation devirtualizations"  )

◆ STATISTIC() [4/7]

STATISTIC ( NumUniformRetVal ,
"Number of uniform return value optimizations"  )

◆ STATISTIC() [5/7]

STATISTIC ( NumUniqueRetVal ,
"Number of unique return value optimizations"  )

◆ STATISTIC() [6/7]

STATISTIC ( NumVirtConstProp ,
"Number of virtual constant propagations"  )

◆ STATISTIC() [7/7]

STATISTIC ( NumVirtConstProp1Bit ,
"Number of 1 bit virtual constant propagations"  )

◆ typeIDVisibleToRegularObj()

bool typeIDVisibleToRegularObj ( StringRef TypeID,
function_ref< bool(StringRef)> IsVisibleToRegularObj )
static

Variable Documentation

◆ WholeProgramDevirtKeepUnreachableFunction

cl::opt< bool > WholeProgramDevirtKeepUnreachableFunction("wholeprogramdevirt-keep-unreachable-function", cl::desc("Regard unreachable functions as possible devirtualize targets."), cl::Hidden, cl::init(true)) ( "wholeprogramdevirt-keep-unreachable-function" ,
cl::desc("Regard unreachable functions as possible devirtualize targets.") ,
cl::Hidden ,
cl::init(true)  )
static

With Clang, a pure virtual class's deleting destructor is emitted as a llvm.trap intrinsic followed by an unreachable IR instruction.

In the context of whole program devirtualization, the deleting destructor of a pure virtual class won't be invoked by the source code so safe to skip as a devirtualize target.

However, not all unreachable functions are safe to skip. In some cases, the program intends to run such functions and terminate, for instance, a unit test may run a death test. A non-test program might (or allowed to) invoke such functions to report failures (whether/when it's a good practice or not is a different topic).

This option is enabled to keep an unreachable function as a possible devirtualize target to conservatively keep the program behavior.

TODO: Make a pure virtual class's deleting destructor precisely identifiable in Clang's codegen for more devirtualization in LLVM.

Referenced by mustBeUnreachableFunction().