10b57cec5SDimitry Andric //===- CalledValuePropagation.cpp - Propagate called values -----*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements a transformation that attaches !callees metadata to 100b57cec5SDimitry Andric // indirect call sites. For a given call site, the metadata, if present, 110b57cec5SDimitry Andric // indicates the set of functions the call site could possibly target at 120b57cec5SDimitry Andric // run-time. This metadata is added to indirect call sites when the set of 130b57cec5SDimitry Andric // possible targets can be determined by analysis and is known to be small. The 140b57cec5SDimitry Andric // analysis driving the transformation is similar to constant propagation and 150b57cec5SDimitry Andric // makes uses of the generic sparse propagation solver. 160b57cec5SDimitry Andric // 170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "llvm/Transforms/IPO/CalledValuePropagation.h" 200b57cec5SDimitry Andric #include "llvm/Analysis/SparsePropagation.h" 210b57cec5SDimitry Andric #include "llvm/Analysis/ValueLatticeUtils.h" 2281ad6265SDimitry Andric #include "llvm/IR/Constants.h" 230b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h" 24*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h" 25480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 260b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h" 2781ad6265SDimitry Andric 280b57cec5SDimitry Andric using namespace llvm; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric #define DEBUG_TYPE "called-value-propagation" 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric /// The maximum number of functions to track per lattice value. Once the number 330b57cec5SDimitry Andric /// of functions a call site can possibly target exceeds this threshold, it's 340b57cec5SDimitry Andric /// lattice value becomes overdefined. The number of possible lattice values is 350b57cec5SDimitry Andric /// bounded by Ch(F, M), where F is the number of functions in the module and M 360b57cec5SDimitry Andric /// is MaxFunctionsPerValue. As such, this value should be kept very small. We 370b57cec5SDimitry Andric /// likely can't do anything useful for call sites with a large number of 380b57cec5SDimitry Andric /// possible targets, anyway. 390b57cec5SDimitry Andric static cl::opt<unsigned> MaxFunctionsPerValue( 400b57cec5SDimitry Andric "cvp-max-functions-per-value", cl::Hidden, cl::init(4), 410b57cec5SDimitry Andric cl::desc("The maximum number of functions to track per lattice value")); 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric namespace { 440b57cec5SDimitry Andric /// To enable interprocedural analysis, we assign LLVM values to the following 450b57cec5SDimitry Andric /// groups. The register group represents SSA registers, the return group 460b57cec5SDimitry Andric /// represents the return values of functions, and the memory group represents 470b57cec5SDimitry Andric /// in-memory values. An LLVM Value can technically be in more than one group. 480b57cec5SDimitry Andric /// It's necessary to distinguish these groups so we can, for example, track a 490b57cec5SDimitry Andric /// global variable separately from the value stored at its location. 500b57cec5SDimitry Andric enum class IPOGrouping { Register, Return, Memory }; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric /// Our LatticeKeys are PointerIntPairs composed of LLVM values and groupings. 530b57cec5SDimitry Andric using CVPLatticeKey = PointerIntPair<Value *, 2, IPOGrouping>; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric /// The lattice value type used by our custom lattice function. It holds the 560b57cec5SDimitry Andric /// lattice state, and a set of functions. 570b57cec5SDimitry Andric class CVPLatticeVal { 580b57cec5SDimitry Andric public: 590b57cec5SDimitry Andric /// The states of the lattice values. Only the FunctionSet state is 600b57cec5SDimitry Andric /// interesting. It indicates the set of functions to which an LLVM value may 610b57cec5SDimitry Andric /// refer. 620b57cec5SDimitry Andric enum CVPLatticeStateTy { Undefined, FunctionSet, Overdefined, Untracked }; 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric /// Comparator for sorting the functions set. We want to keep the order 650b57cec5SDimitry Andric /// deterministic for testing, etc. 660b57cec5SDimitry Andric struct Compare { 670b57cec5SDimitry Andric bool operator()(const Function *LHS, const Function *RHS) const { 680b57cec5SDimitry Andric return LHS->getName() < RHS->getName(); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric }; 710b57cec5SDimitry Andric 7281ad6265SDimitry Andric CVPLatticeVal() = default; 730b57cec5SDimitry Andric CVPLatticeVal(CVPLatticeStateTy LatticeState) : LatticeState(LatticeState) {} 740b57cec5SDimitry Andric CVPLatticeVal(std::vector<Function *> &&Functions) 750b57cec5SDimitry Andric : LatticeState(FunctionSet), Functions(std::move(Functions)) { 765ffd83dbSDimitry Andric assert(llvm::is_sorted(this->Functions, Compare())); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// Get a reference to the functions held by this lattice value. The number 800b57cec5SDimitry Andric /// of functions will be zero for states other than FunctionSet. 810b57cec5SDimitry Andric const std::vector<Function *> &getFunctions() const { 820b57cec5SDimitry Andric return Functions; 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric /// Returns true if the lattice value is in the FunctionSet state. 860b57cec5SDimitry Andric bool isFunctionSet() const { return LatticeState == FunctionSet; } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric bool operator==(const CVPLatticeVal &RHS) const { 890b57cec5SDimitry Andric return LatticeState == RHS.LatticeState && Functions == RHS.Functions; 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric bool operator!=(const CVPLatticeVal &RHS) const { 930b57cec5SDimitry Andric return LatticeState != RHS.LatticeState || Functions != RHS.Functions; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric private: 970b57cec5SDimitry Andric /// Holds the state this lattice value is in. 9881ad6265SDimitry Andric CVPLatticeStateTy LatticeState = Undefined; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric /// Holds functions indicating the possible targets of call sites. This set 1010b57cec5SDimitry Andric /// is empty for lattice values in the undefined, overdefined, and untracked 1020b57cec5SDimitry Andric /// states. The maximum size of the set is controlled by 1030b57cec5SDimitry Andric /// MaxFunctionsPerValue. Since most LLVM values are expected to be in 1040b57cec5SDimitry Andric /// uninteresting states (i.e., overdefined), CVPLatticeVal objects should be 1050b57cec5SDimitry Andric /// small and efficiently copyable. 1060b57cec5SDimitry Andric // FIXME: This could be a TinyPtrVector and/or merge with LatticeState. 1070b57cec5SDimitry Andric std::vector<Function *> Functions; 1080b57cec5SDimitry Andric }; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric /// The custom lattice function used by the generic sparse propagation solver. 1110b57cec5SDimitry Andric /// It handles merging lattice values and computing new lattice values for 1120b57cec5SDimitry Andric /// constants, arguments, values returned from trackable functions, and values 1130b57cec5SDimitry Andric /// located in trackable global variables. It also computes the lattice values 1140b57cec5SDimitry Andric /// that change as a result of executing instructions. 1150b57cec5SDimitry Andric class CVPLatticeFunc 1160b57cec5SDimitry Andric : public AbstractLatticeFunction<CVPLatticeKey, CVPLatticeVal> { 1170b57cec5SDimitry Andric public: 1180b57cec5SDimitry Andric CVPLatticeFunc() 1190b57cec5SDimitry Andric : AbstractLatticeFunction(CVPLatticeVal(CVPLatticeVal::Undefined), 1200b57cec5SDimitry Andric CVPLatticeVal(CVPLatticeVal::Overdefined), 1210b57cec5SDimitry Andric CVPLatticeVal(CVPLatticeVal::Untracked)) {} 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric /// Compute and return a CVPLatticeVal for the given CVPLatticeKey. 1240b57cec5SDimitry Andric CVPLatticeVal ComputeLatticeVal(CVPLatticeKey Key) override { 1250b57cec5SDimitry Andric switch (Key.getInt()) { 1260b57cec5SDimitry Andric case IPOGrouping::Register: 1270b57cec5SDimitry Andric if (isa<Instruction>(Key.getPointer())) { 1280b57cec5SDimitry Andric return getUndefVal(); 1290b57cec5SDimitry Andric } else if (auto *A = dyn_cast<Argument>(Key.getPointer())) { 1300b57cec5SDimitry Andric if (canTrackArgumentsInterprocedurally(A->getParent())) 1310b57cec5SDimitry Andric return getUndefVal(); 1320b57cec5SDimitry Andric } else if (auto *C = dyn_cast<Constant>(Key.getPointer())) { 1330b57cec5SDimitry Andric return computeConstant(C); 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric return getOverdefinedVal(); 1360b57cec5SDimitry Andric case IPOGrouping::Memory: 1370b57cec5SDimitry Andric case IPOGrouping::Return: 1380b57cec5SDimitry Andric if (auto *GV = dyn_cast<GlobalVariable>(Key.getPointer())) { 1390b57cec5SDimitry Andric if (canTrackGlobalVariableInterprocedurally(GV)) 1400b57cec5SDimitry Andric return computeConstant(GV->getInitializer()); 1410b57cec5SDimitry Andric } else if (auto *F = cast<Function>(Key.getPointer())) 1420b57cec5SDimitry Andric if (canTrackReturnsInterprocedurally(F)) 1430b57cec5SDimitry Andric return getUndefVal(); 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric return getOverdefinedVal(); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric /// Merge the two given lattice values. The interesting cases are merging two 1490b57cec5SDimitry Andric /// FunctionSet values and a FunctionSet value with an Undefined value. For 1500b57cec5SDimitry Andric /// these cases, we simply union the function sets. If the size of the union 1510b57cec5SDimitry Andric /// is greater than the maximum functions we track, the merged value is 1520b57cec5SDimitry Andric /// overdefined. 1530b57cec5SDimitry Andric CVPLatticeVal MergeValues(CVPLatticeVal X, CVPLatticeVal Y) override { 1540b57cec5SDimitry Andric if (X == getOverdefinedVal() || Y == getOverdefinedVal()) 1550b57cec5SDimitry Andric return getOverdefinedVal(); 1560b57cec5SDimitry Andric if (X == getUndefVal() && Y == getUndefVal()) 1570b57cec5SDimitry Andric return getUndefVal(); 1580b57cec5SDimitry Andric std::vector<Function *> Union; 1590b57cec5SDimitry Andric std::set_union(X.getFunctions().begin(), X.getFunctions().end(), 1600b57cec5SDimitry Andric Y.getFunctions().begin(), Y.getFunctions().end(), 1610b57cec5SDimitry Andric std::back_inserter(Union), CVPLatticeVal::Compare{}); 1620b57cec5SDimitry Andric if (Union.size() > MaxFunctionsPerValue) 1630b57cec5SDimitry Andric return getOverdefinedVal(); 1640b57cec5SDimitry Andric return CVPLatticeVal(std::move(Union)); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric /// Compute the lattice values that change as a result of executing the given 1680b57cec5SDimitry Andric /// instruction. The changed values are stored in \p ChangedValues. We handle 1690b57cec5SDimitry Andric /// just a few kinds of instructions since we're only propagating values that 1700b57cec5SDimitry Andric /// can be called. 1710b57cec5SDimitry Andric void ComputeInstructionState( 1720b57cec5SDimitry Andric Instruction &I, DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues, 1730b57cec5SDimitry Andric SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) override { 1740b57cec5SDimitry Andric switch (I.getOpcode()) { 1750b57cec5SDimitry Andric case Instruction::Call: 1760b57cec5SDimitry Andric case Instruction::Invoke: 1775ffd83dbSDimitry Andric return visitCallBase(cast<CallBase>(I), ChangedValues, SS); 1780b57cec5SDimitry Andric case Instruction::Load: 1790b57cec5SDimitry Andric return visitLoad(*cast<LoadInst>(&I), ChangedValues, SS); 1800b57cec5SDimitry Andric case Instruction::Ret: 1810b57cec5SDimitry Andric return visitReturn(*cast<ReturnInst>(&I), ChangedValues, SS); 1820b57cec5SDimitry Andric case Instruction::Select: 1830b57cec5SDimitry Andric return visitSelect(*cast<SelectInst>(&I), ChangedValues, SS); 1840b57cec5SDimitry Andric case Instruction::Store: 1850b57cec5SDimitry Andric return visitStore(*cast<StoreInst>(&I), ChangedValues, SS); 1860b57cec5SDimitry Andric default: 1870b57cec5SDimitry Andric return visitInst(I, ChangedValues, SS); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric /// Print the given CVPLatticeVal to the specified stream. 1920b57cec5SDimitry Andric void PrintLatticeVal(CVPLatticeVal LV, raw_ostream &OS) override { 1930b57cec5SDimitry Andric if (LV == getUndefVal()) 1940b57cec5SDimitry Andric OS << "Undefined "; 1950b57cec5SDimitry Andric else if (LV == getOverdefinedVal()) 1960b57cec5SDimitry Andric OS << "Overdefined"; 1970b57cec5SDimitry Andric else if (LV == getUntrackedVal()) 1980b57cec5SDimitry Andric OS << "Untracked "; 1990b57cec5SDimitry Andric else 2000b57cec5SDimitry Andric OS << "FunctionSet"; 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric /// Print the given CVPLatticeKey to the specified stream. 2040b57cec5SDimitry Andric void PrintLatticeKey(CVPLatticeKey Key, raw_ostream &OS) override { 2050b57cec5SDimitry Andric if (Key.getInt() == IPOGrouping::Register) 2060b57cec5SDimitry Andric OS << "<reg> "; 2070b57cec5SDimitry Andric else if (Key.getInt() == IPOGrouping::Memory) 2080b57cec5SDimitry Andric OS << "<mem> "; 2090b57cec5SDimitry Andric else if (Key.getInt() == IPOGrouping::Return) 2100b57cec5SDimitry Andric OS << "<ret> "; 2110b57cec5SDimitry Andric if (isa<Function>(Key.getPointer())) 2120b57cec5SDimitry Andric OS << Key.getPointer()->getName(); 2130b57cec5SDimitry Andric else 2140b57cec5SDimitry Andric OS << *Key.getPointer(); 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric /// We collect a set of indirect calls when visiting call sites. This method 2180b57cec5SDimitry Andric /// returns a reference to that set. 2195ffd83dbSDimitry Andric SmallPtrSetImpl<CallBase *> &getIndirectCalls() { return IndirectCalls; } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric private: 2220b57cec5SDimitry Andric /// Holds the indirect calls we encounter during the analysis. We will attach 2230b57cec5SDimitry Andric /// metadata to these calls after the analysis indicating the functions the 2240b57cec5SDimitry Andric /// calls can possibly target. 2255ffd83dbSDimitry Andric SmallPtrSet<CallBase *, 32> IndirectCalls; 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric /// Compute a new lattice value for the given constant. The constant, after 2280b57cec5SDimitry Andric /// stripping any pointer casts, should be a Function. We ignore null 2290b57cec5SDimitry Andric /// pointers as an optimization, since calling these values is undefined 2300b57cec5SDimitry Andric /// behavior. 2310b57cec5SDimitry Andric CVPLatticeVal computeConstant(Constant *C) { 2320b57cec5SDimitry Andric if (isa<ConstantPointerNull>(C)) 2330b57cec5SDimitry Andric return CVPLatticeVal(CVPLatticeVal::FunctionSet); 2340b57cec5SDimitry Andric if (auto *F = dyn_cast<Function>(C->stripPointerCasts())) 2350b57cec5SDimitry Andric return CVPLatticeVal({F}); 2360b57cec5SDimitry Andric return getOverdefinedVal(); 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric /// Handle return instructions. The function's return state is the merge of 2400b57cec5SDimitry Andric /// the returned value state and the function's return state. 2410b57cec5SDimitry Andric void visitReturn(ReturnInst &I, 2420b57cec5SDimitry Andric DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues, 2430b57cec5SDimitry Andric SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) { 2440b57cec5SDimitry Andric Function *F = I.getParent()->getParent(); 2450b57cec5SDimitry Andric if (F->getReturnType()->isVoidTy()) 2460b57cec5SDimitry Andric return; 2470b57cec5SDimitry Andric auto RegI = CVPLatticeKey(I.getReturnValue(), IPOGrouping::Register); 2480b57cec5SDimitry Andric auto RetF = CVPLatticeKey(F, IPOGrouping::Return); 2490b57cec5SDimitry Andric ChangedValues[RetF] = 2500b57cec5SDimitry Andric MergeValues(SS.getValueState(RegI), SS.getValueState(RetF)); 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric /// Handle call sites. The state of a called function's formal arguments is 2540b57cec5SDimitry Andric /// the merge of the argument state with the call sites corresponding actual 2550b57cec5SDimitry Andric /// argument state. The call site state is the merge of the call site state 2560b57cec5SDimitry Andric /// with the returned value state of the called function. 2575ffd83dbSDimitry Andric void visitCallBase(CallBase &CB, 2580b57cec5SDimitry Andric DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues, 2590b57cec5SDimitry Andric SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) { 2605ffd83dbSDimitry Andric Function *F = CB.getCalledFunction(); 2615ffd83dbSDimitry Andric auto RegI = CVPLatticeKey(&CB, IPOGrouping::Register); 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric // If this is an indirect call, save it so we can quickly revisit it when 2640b57cec5SDimitry Andric // attaching metadata. 2650b57cec5SDimitry Andric if (!F) 2665ffd83dbSDimitry Andric IndirectCalls.insert(&CB); 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric // If we can't track the function's return values, there's nothing to do. 2690b57cec5SDimitry Andric if (!F || !canTrackReturnsInterprocedurally(F)) { 2700b57cec5SDimitry Andric // Void return, No need to create and update CVPLattice state as no one 2710b57cec5SDimitry Andric // can use it. 2725ffd83dbSDimitry Andric if (CB.getType()->isVoidTy()) 2730b57cec5SDimitry Andric return; 2740b57cec5SDimitry Andric ChangedValues[RegI] = getOverdefinedVal(); 2750b57cec5SDimitry Andric return; 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric // Inform the solver that the called function is executable, and perform 2790b57cec5SDimitry Andric // the merges for the arguments and return value. 2800b57cec5SDimitry Andric SS.MarkBlockExecutable(&F->front()); 2810b57cec5SDimitry Andric auto RetF = CVPLatticeKey(F, IPOGrouping::Return); 2820b57cec5SDimitry Andric for (Argument &A : F->args()) { 2830b57cec5SDimitry Andric auto RegFormal = CVPLatticeKey(&A, IPOGrouping::Register); 2840b57cec5SDimitry Andric auto RegActual = 2855ffd83dbSDimitry Andric CVPLatticeKey(CB.getArgOperand(A.getArgNo()), IPOGrouping::Register); 2860b57cec5SDimitry Andric ChangedValues[RegFormal] = 2870b57cec5SDimitry Andric MergeValues(SS.getValueState(RegFormal), SS.getValueState(RegActual)); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric // Void return, No need to create and update CVPLattice state as no one can 2910b57cec5SDimitry Andric // use it. 2925ffd83dbSDimitry Andric if (CB.getType()->isVoidTy()) 2930b57cec5SDimitry Andric return; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric ChangedValues[RegI] = 2960b57cec5SDimitry Andric MergeValues(SS.getValueState(RegI), SS.getValueState(RetF)); 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric /// Handle select instructions. The select instruction state is the merge the 3000b57cec5SDimitry Andric /// true and false value states. 3010b57cec5SDimitry Andric void visitSelect(SelectInst &I, 3020b57cec5SDimitry Andric DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues, 3030b57cec5SDimitry Andric SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) { 3040b57cec5SDimitry Andric auto RegI = CVPLatticeKey(&I, IPOGrouping::Register); 3050b57cec5SDimitry Andric auto RegT = CVPLatticeKey(I.getTrueValue(), IPOGrouping::Register); 3060b57cec5SDimitry Andric auto RegF = CVPLatticeKey(I.getFalseValue(), IPOGrouping::Register); 3070b57cec5SDimitry Andric ChangedValues[RegI] = 3080b57cec5SDimitry Andric MergeValues(SS.getValueState(RegT), SS.getValueState(RegF)); 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric /// Handle load instructions. If the pointer operand of the load is a global 3120b57cec5SDimitry Andric /// variable, we attempt to track the value. The loaded value state is the 3130b57cec5SDimitry Andric /// merge of the loaded value state with the global variable state. 3140b57cec5SDimitry Andric void visitLoad(LoadInst &I, 3150b57cec5SDimitry Andric DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues, 3160b57cec5SDimitry Andric SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) { 3170b57cec5SDimitry Andric auto RegI = CVPLatticeKey(&I, IPOGrouping::Register); 3180b57cec5SDimitry Andric if (auto *GV = dyn_cast<GlobalVariable>(I.getPointerOperand())) { 3190b57cec5SDimitry Andric auto MemGV = CVPLatticeKey(GV, IPOGrouping::Memory); 3200b57cec5SDimitry Andric ChangedValues[RegI] = 3210b57cec5SDimitry Andric MergeValues(SS.getValueState(RegI), SS.getValueState(MemGV)); 3220b57cec5SDimitry Andric } else { 3230b57cec5SDimitry Andric ChangedValues[RegI] = getOverdefinedVal(); 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric /// Handle store instructions. If the pointer operand of the store is a 3280b57cec5SDimitry Andric /// global variable, we attempt to track the value. The global variable state 3290b57cec5SDimitry Andric /// is the merge of the stored value state with the global variable state. 3300b57cec5SDimitry Andric void visitStore(StoreInst &I, 3310b57cec5SDimitry Andric DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues, 3320b57cec5SDimitry Andric SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) { 3330b57cec5SDimitry Andric auto *GV = dyn_cast<GlobalVariable>(I.getPointerOperand()); 3340b57cec5SDimitry Andric if (!GV) 3350b57cec5SDimitry Andric return; 3360b57cec5SDimitry Andric auto RegI = CVPLatticeKey(I.getValueOperand(), IPOGrouping::Register); 3370b57cec5SDimitry Andric auto MemGV = CVPLatticeKey(GV, IPOGrouping::Memory); 3380b57cec5SDimitry Andric ChangedValues[MemGV] = 3390b57cec5SDimitry Andric MergeValues(SS.getValueState(RegI), SS.getValueState(MemGV)); 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric /// Handle all other instructions. All other instructions are marked 3430b57cec5SDimitry Andric /// overdefined. 3440b57cec5SDimitry Andric void visitInst(Instruction &I, 3450b57cec5SDimitry Andric DenseMap<CVPLatticeKey, CVPLatticeVal> &ChangedValues, 3460b57cec5SDimitry Andric SparseSolver<CVPLatticeKey, CVPLatticeVal> &SS) { 3470b57cec5SDimitry Andric // Simply bail if this instruction has no user. 3480b57cec5SDimitry Andric if (I.use_empty()) 3490b57cec5SDimitry Andric return; 3500b57cec5SDimitry Andric auto RegI = CVPLatticeKey(&I, IPOGrouping::Register); 3510b57cec5SDimitry Andric ChangedValues[RegI] = getOverdefinedVal(); 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric }; 3540b57cec5SDimitry Andric } // namespace 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric namespace llvm { 3570b57cec5SDimitry Andric /// A specialization of LatticeKeyInfo for CVPLatticeKeys. The generic solver 3580b57cec5SDimitry Andric /// must translate between LatticeKeys and LLVM Values when adding Values to 3590b57cec5SDimitry Andric /// its work list and inspecting the state of control-flow related values. 3600b57cec5SDimitry Andric template <> struct LatticeKeyInfo<CVPLatticeKey> { 3610b57cec5SDimitry Andric static inline Value *getValueFromLatticeKey(CVPLatticeKey Key) { 3620b57cec5SDimitry Andric return Key.getPointer(); 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric static inline CVPLatticeKey getLatticeKeyFromValue(Value *V) { 3650b57cec5SDimitry Andric return CVPLatticeKey(V, IPOGrouping::Register); 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric }; 3680b57cec5SDimitry Andric } // namespace llvm 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric static bool runCVP(Module &M) { 3710b57cec5SDimitry Andric // Our custom lattice function and generic sparse propagation solver. 3720b57cec5SDimitry Andric CVPLatticeFunc Lattice; 3730b57cec5SDimitry Andric SparseSolver<CVPLatticeKey, CVPLatticeVal> Solver(&Lattice); 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric // For each function in the module, if we can't track its arguments, let the 3760b57cec5SDimitry Andric // generic solver assume it is executable. 3770b57cec5SDimitry Andric for (Function &F : M) 3780b57cec5SDimitry Andric if (!F.isDeclaration() && !canTrackArgumentsInterprocedurally(&F)) 3790b57cec5SDimitry Andric Solver.MarkBlockExecutable(&F.front()); 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric // Solver our custom lattice. In doing so, we will also build a set of 3820b57cec5SDimitry Andric // indirect call sites. 3830b57cec5SDimitry Andric Solver.Solve(); 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric // Attach metadata to the indirect call sites that were collected indicating 3860b57cec5SDimitry Andric // the set of functions they can possibly target. 3870b57cec5SDimitry Andric bool Changed = false; 3880b57cec5SDimitry Andric MDBuilder MDB(M.getContext()); 3895ffd83dbSDimitry Andric for (CallBase *C : Lattice.getIndirectCalls()) { 3905ffd83dbSDimitry Andric auto RegI = CVPLatticeKey(C->getCalledOperand(), IPOGrouping::Register); 3910b57cec5SDimitry Andric CVPLatticeVal LV = Solver.getExistingValueState(RegI); 3920b57cec5SDimitry Andric if (!LV.isFunctionSet() || LV.getFunctions().empty()) 3930b57cec5SDimitry Andric continue; 3940b57cec5SDimitry Andric MDNode *Callees = MDB.createCallees(LV.getFunctions()); 3950b57cec5SDimitry Andric C->setMetadata(LLVMContext::MD_callees, Callees); 3960b57cec5SDimitry Andric Changed = true; 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric return Changed; 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric PreservedAnalyses CalledValuePropagationPass::run(Module &M, 4030b57cec5SDimitry Andric ModuleAnalysisManager &) { 4040b57cec5SDimitry Andric runCVP(M); 4050b57cec5SDimitry Andric return PreservedAnalyses::all(); 4060b57cec5SDimitry Andric } 407