28 #define DEBUG_TYPE "called-value-propagation" 39 cl::desc(
"The maximum number of functions to track per lattice value"));
60 enum CVPLatticeStateTy { Undefined, FunctionSet, Overdefined, Untracked };
70 CVPLatticeVal() : LatticeState(Undefined) {}
71 CVPLatticeVal(CVPLatticeStateTy LatticeState) : LatticeState(LatticeState) {}
72 CVPLatticeVal(std::vector<Function *> &&Functions)
73 : LatticeState(FunctionSet), Functions(std::move(Functions)) {
74 assert(std::is_sorted(this->Functions.begin(), this->Functions.end(),
80 const std::vector<Function *> &getFunctions()
const {
85 bool isFunctionSet()
const {
return LatticeState == FunctionSet; }
87 bool operator==(
const CVPLatticeVal &RHS)
const {
88 return LatticeState == RHS.LatticeState && Functions == RHS.Functions;
91 bool operator!=(
const CVPLatticeVal &RHS)
const {
92 return LatticeState != RHS.LatticeState || Functions != RHS.Functions;
97 CVPLatticeStateTy LatticeState;
106 std::vector<Function *> Functions;
119 CVPLatticeVal(CVPLatticeVal::Overdefined),
120 CVPLatticeVal(CVPLatticeVal::Untracked)) {}
123 CVPLatticeVal ComputeLatticeVal(CVPLatticeKey
Key)
override {
124 switch (Key.getInt()) {
126 if (isa<Instruction>(Key.getPointer())) {
127 return getUndefVal();
128 }
else if (
auto *A = dyn_cast<Argument>(Key.getPointer())) {
130 return getUndefVal();
131 }
else if (
auto *
C = dyn_cast<Constant>(Key.getPointer())) {
132 return computeConstant(
C);
134 return getOverdefinedVal();
135 case IPOGrouping::Memory:
137 if (
auto *GV = dyn_cast<GlobalVariable>(Key.getPointer())) {
139 return computeConstant(GV->getInitializer());
140 }
else if (
auto *
F = cast<Function>(Key.getPointer()))
142 return getUndefVal();
144 return getOverdefinedVal();
152 CVPLatticeVal MergeValues(CVPLatticeVal
X, CVPLatticeVal
Y)
override {
153 if (X == getOverdefinedVal() || Y == getOverdefinedVal())
154 return getOverdefinedVal();
155 if (X == getUndefVal() && Y == getUndefVal())
156 return getUndefVal();
157 std::vector<Function *> Union;
159 Y.getFunctions().begin(), Y.getFunctions().end(),
162 return getOverdefinedVal();
163 return CVPLatticeVal(std::move(Union));
170 void ComputeInstructionState(
175 return visitCallSite(cast<CallInst>(&I), ChangedValues, SS);
176 case Instruction::Invoke:
177 return visitCallSite(cast<InvokeInst>(&I), ChangedValues, SS);
179 return visitLoad(*cast<LoadInst>(&I), ChangedValues, SS);
181 return visitReturn(*cast<ReturnInst>(&I), ChangedValues, SS);
183 return visitSelect(*cast<SelectInst>(&I), ChangedValues, SS);
185 return visitStore(*cast<StoreInst>(&I), ChangedValues, SS);
187 return visitInst(I, ChangedValues, SS);
192 void PrintLatticeVal(CVPLatticeVal LV,
raw_ostream &OS)
override {
193 if (LV == getUndefVal())
195 else if (LV == getOverdefinedVal())
197 else if (LV == getUntrackedVal())
204 void PrintLatticeKey(CVPLatticeKey Key,
raw_ostream &OS)
override {
207 else if (Key.getInt() == IPOGrouping::Memory)
211 if (isa<Function>(Key.getPointer()))
212 OS << Key.getPointer()->getName();
214 OS << *Key.getPointer();
231 CVPLatticeVal computeConstant(
Constant *
C) {
232 if (isa<ConstantPointerNull>(C))
233 return CVPLatticeVal(CVPLatticeVal::FunctionSet);
235 return CVPLatticeVal({
F});
236 return getOverdefinedVal();
249 ChangedValues[RetF] =
275 ChangedValues[RegI] = getOverdefinedVal();
287 ChangedValues[RegFormal] =
296 ChangedValues[RegI] =
308 ChangedValues[RegI] =
320 auto MemGV = CVPLatticeKey(GV, IPOGrouping::Memory);
321 ChangedValues[RegI] =
324 ChangedValues[RegI] = getOverdefinedVal();
338 auto MemGV = CVPLatticeKey(GV, IPOGrouping::Memory);
339 ChangedValues[MemGV] =
352 ChangedValues[RegI] = getOverdefinedVal();
363 return Key.getPointer();
373 CVPLatticeFunc Lattice;
388 bool Changed =
false;
394 if (!LV.isFunctionSet() || LV.getFunctions().empty())
396 MDNode *Callees = MDB.createCallees(LV.getFunctions());
411 class CalledValuePropagationLegacyPass :
public ModulePass {
419 CalledValuePropagationLegacyPass() :
ModulePass(ID) {
424 bool runOnModule(
Module &M)
override {
434 "Called Value Propagation",
false,
false)
437 return new CalledValuePropagationLegacyPass();
Return a value (possibly void), from a function.
Value * getValueOperand()
void initializeCalledValuePropagationLegacyPassPass(PassRegistry &)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents an incoming formal argument to a Function.
This class represents lattice values for constants.
A Module instance is used to store all the information related to an LLVM module. ...
bool canTrackArgumentsInterprocedurally(Function *F)
Determine if the values of the given function's arguments can be tracked interprocedurally.
This class provides various memory handling functions that manipulate MemoryBlock instances...
const Value * getTrueValue() const
An instruction for reading from memory.
IPOGrouping
To enable interprocedural analysis, we assign LLVM values to the following groups.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
This class represents the LLVM 'select' instruction.
InstrTy * getInstruction() const
static CVPLatticeKey getLatticeKeyFromValue(Value *V)
ValTy * getCalledValue() const
Return the pointer to function that is being called.
void Solve()
Solve - Solve for constants and executable blocks.
Type * getType() const
All values are typed, get the type of this value.
ModulePass * createCalledValuePropagationPass()
createCalledValuePropagationPass - Attach metadata to indirct call sites indicating the set of functi...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
An instruction for storing to memory.
bool canTrackReturnsInterprocedurally(Function *F)
Determine if the values of the given function's returns can be tracked interprocedurally.
bool isVoidTy() const
Return true if this is 'void'.
initializer< Ty > init(const Ty &Val)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
Type * getReturnType() const
Returns the type of the ret val.
A set of analyses that are preserved following a run of a transformation pass.
PointerIntPair - This class implements a pair of a pointer and small integer.
static bool runCVP(Module &M)
This is an important base class in LLVM.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Represent the analysis usage information of a pass.
Value * getPointerOperand()
static Value * getValueFromLatticeKey(CVPLatticeKey Key)
SparseSolver - This class is a general purpose solver for Sparse Conditional Propagation with a progr...
const Constant * stripPointerCasts() const
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
AbstractLatticeFunction - This class is implemented by the dataflow instance to specify what the latt...
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LatticeVal getExistingValueState(LatticeKey Key) const
getExistingValueState - Return the LatticeVal object corresponding to the given value from the ValueS...
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
ValTy * getArgument(unsigned ArgNo) const
static cl::opt< unsigned > MaxFunctionsPerValue("cvp-max-functions-per-value", cl::Hidden, cl::init(4), cl::desc("The maximum number of functions to track per lattice value"))
The maximum number of functions to track per lattice value.
bool canTrackGlobalVariableInterprocedurally(GlobalVariable *GV)
Determine if the value maintained in the given global variable can be tracked interprocedurally.
Promote Memory to Register
LatticeVal getValueState(LatticeKey Key)
getValueState - Return the LatticeVal object corresponding to the given value from the ValueState map...
void setPreservesAll()
Set by analyses that do not transform their input at all.
const Value * getFalseValue() const
bool operator!=(uint64_t V1, const APInt &V2)
StringRef getName() const
Return a constant reference to the value's name.
const Function * getParent() const
Return the enclosing method, or null if none.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
FunTy * getCalledFunction() const
Return the function being called if this is a direct call, otherwise return null (if it's an indirect...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const BasicBlock & front() const
void MarkBlockExecutable(BasicBlock *BB)
MarkBlockExecutable - This method can be used by clients to mark all of the blocks that are known to ...
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream...
A container for analyses that lazily runs them and caches their results.
bool operator==(uint64_t V1, const APInt &V2)
INITIALIZE_PASS(CalledValuePropagationLegacyPass, "called-value-propagation", "Called Value Propagation", false, false) ModulePass *llvm
Value * getPointerOperand()
bool set_union(S1Ty &S1, const S2Ty &S2)
set_union(A, B) - Compute A := A u B, return whether A changed.
iterator_range< arg_iterator > args()
const BasicBlock * getParent() const
A template for translating between LLVM Values and LatticeKeys.