//===- DeadArgumentElimination.cpp - Eliminate dead arguments -------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This pass deletes dead arguments from internal functions. Dead argument // elimination removes arguments which are directly dead, as well as arguments // only passed into function calls as dead arguments of other functions. This // pass also deletes dead return values in a similar way. // // This pass is often useful as a cleanup pass to run after aggressive // interprocedural passes, which add possibly-dead arguments or return values. // //===----------------------------------------------------------------------===// #include "llvm/Transforms/IPO/DeadArgumentElimination.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/IR/Argument.h" #include "llvm/IR/AttributeMask.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" #include "llvm/IR/NoFolder.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" #include "llvm/IR/User.h" #include "llvm/IR/Value.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include <cassert> #include <utility> #include <vector> usingnamespacellvm; #define DEBUG_TYPE … STATISTIC(NumArgumentsEliminated, "Number of unread args removed"); STATISTIC(NumRetValsEliminated, "Number of unused return values removed"); STATISTIC(NumArgumentsReplacedWithPoison, "Number of unread args replaced with poison"); namespace { /// The dead argument elimination pass. class DAE : public ModulePass { … }; bool isMustTailCalleeAnalyzable(const CallBase &CB) { … } } // end anonymous namespace char DAE::ID = …; INITIALIZE_PASS(…) namespace { /// The DeadArgumentHacking pass, same as dead argument elimination, but deletes /// arguments to functions which are external. This is only for use by bugpoint. struct DAH : public DAE { … }; } // end anonymous namespace char DAH::ID = …; INITIALIZE_PASS(…) /// This pass removes arguments from functions which are not used by the body of /// the function. ModulePass *llvm::createDeadArgEliminationPass() { … } ModulePass *llvm::createDeadArgHackingPass() { … } /// If this is an function that takes a ... list, and if llvm.vastart is never /// called, the varargs list is dead for the function. bool DeadArgumentEliminationPass::deleteDeadVarargs(Function &F) { … } /// Checks if the given function has any arguments that are unused, and changes /// the caller parameters to be poison instead. bool DeadArgumentEliminationPass::removeDeadArgumentsFromCallers(Function &F) { … } /// Convenience function that returns the number of return values. It returns 0 /// for void functions and 1 for functions not returning a struct. It returns /// the number of struct elements for functions returning a struct. static unsigned numRetVals(const Function *F) { … } /// Returns the sub-type a function will return at a given Idx. Should /// correspond to the result type of an ExtractValue instruction executed with /// just that one Idx (i.e. only top-level structure is considered). static Type *getRetComponentType(const Function *F, unsigned Idx) { … } /// Checks Use for liveness in LiveValues. If Use is not live, it adds Use to /// the MaybeLiveUses argument. Returns the determined liveness of Use. DeadArgumentEliminationPass::Liveness DeadArgumentEliminationPass::markIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses) { … } /// Looks at a single use of an argument or return value and determines if it /// should be alive or not. Adds this use to MaybeLiveUses if it causes the /// used value to become MaybeLive. /// /// RetValNum is the return value number to use when this use is used in a /// return instruction. This is used in the recursion, you should always leave /// it at 0. DeadArgumentEliminationPass::Liveness DeadArgumentEliminationPass::surveyUse(const Use *U, UseVector &MaybeLiveUses, unsigned RetValNum) { … } /// Looks at all the uses of the given value /// Returns the Liveness deduced from the uses of this value. /// /// Adds all uses that cause the result to be MaybeLive to MaybeLiveRetUses. If /// the result is Live, MaybeLiveUses might be modified but its content should /// be ignored (since it might not be complete). DeadArgumentEliminationPass::Liveness DeadArgumentEliminationPass::surveyUses(const Value *V, UseVector &MaybeLiveUses) { … } /// Performs the initial survey of the specified function, checking out whether /// it uses any of its incoming arguments or whether any callers use the return /// value. This fills in the LiveValues set and Uses map. /// /// We consider arguments of non-internal functions to be intrinsically alive as /// well as arguments to functions which have their "address taken". void DeadArgumentEliminationPass::surveyFunction(const Function &F) { … } /// Marks the liveness of RA depending on L. If L is MaybeLive, it also takes /// all uses in MaybeLiveUses and records them in Uses, such that RA will be /// marked live if any use in MaybeLiveUses gets marked live later on. void DeadArgumentEliminationPass::markValue(const RetOrArg &RA, Liveness L, const UseVector &MaybeLiveUses) { … } /// Mark the given Function as alive, meaning that it cannot be changed in any /// way. Additionally, mark any values that are used as this function's /// parameters or by its return values (according to Uses) live as well. void DeadArgumentEliminationPass::markLive(const Function &F) { … } /// Mark the given return value or argument as live. Additionally, mark any /// values that are used by this value (according to Uses) live as well. void DeadArgumentEliminationPass::markLive(const RetOrArg &RA) { … } bool DeadArgumentEliminationPass::isLive(const RetOrArg &RA) { … } /// Given that RA is a live value, propagate it's liveness to any other values /// it uses (according to Uses). void DeadArgumentEliminationPass::propagateLiveness(const RetOrArg &RA) { … } /// Remove any arguments and return values from F that are not in LiveValues. /// Transform the function and all the callees of the function to not have these /// arguments and return values. bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(Function *F) { … } void DeadArgumentEliminationPass::propagateVirtMustcallLiveness( const Module &M) { … } PreservedAnalyses DeadArgumentEliminationPass::run(Module &M, ModuleAnalysisManager &) { … }