diff --git a/llvm/include/llvm/Transforms/IPO/DeadArgumentElimination.h b/llvm/include/llvm/Transforms/IPO/DeadArgumentElimination.h --- a/llvm/include/llvm/Transforms/IPO/DeadArgumentElimination.h +++ b/llvm/include/llvm/Transforms/IPO/DeadArgumentElimination.h @@ -66,25 +66,24 @@ } }; - /// Liveness enum - During our initial pass over the program, we determine - /// that things are either alive or maybe alive. We don't mark anything - /// explicitly dead (even if we know they are), since anything not alive - /// with no registered uses (in Uses) will never be marked alive and will - /// thus become dead in the end. + /// During our initial pass over the program, we determine that things are + /// either alive or maybe alive. We don't mark anything explicitly dead (even + /// if we know they are), since anything not alive with no registered uses + /// (in Uses) will never be marked alive and will thus become dead in the end. enum Liveness { Live, MaybeLive }; - DeadArgumentEliminationPass(bool ShouldHackArguments_ = false) - : ShouldHackArguments(ShouldHackArguments_) {} + DeadArgumentEliminationPass(bool ShouldHackArguments = false) + : ShouldHackArguments(ShouldHackArguments) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &); /// Convenience wrapper - RetOrArg CreateRet(const Function *F, unsigned Idx) { + RetOrArg createRet(const Function *F, unsigned Idx) { return RetOrArg(F, Idx, false); } /// Convenience wrapper - RetOrArg CreateArg(const Function *F, unsigned Idx) { + RetOrArg createArg(const Function *F, unsigned Idx) { return RetOrArg(F, Idx, true); } @@ -122,21 +121,21 @@ bool ShouldHackArguments = false; private: - Liveness MarkIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses); - Liveness SurveyUse(const Use *U, UseVector &MaybeLiveUses, + Liveness markIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses); + Liveness surveyUse(const Use *U, UseVector &MaybeLiveUses, unsigned RetValNum = -1U); - Liveness SurveyUses(const Value *V, UseVector &MaybeLiveUses); + Liveness surveyUses(const Value *V, UseVector &MaybeLiveUses); - void SurveyFunction(const Function &F); - bool IsLive(const RetOrArg &RA); - void MarkValue(const RetOrArg &RA, Liveness L, + void surveyFunction(const Function &F); + bool isLive(const RetOrArg &RA); + void markValue(const RetOrArg &RA, Liveness L, const UseVector &MaybeLiveUses); - void MarkLive(const RetOrArg &RA); - void MarkLive(const Function &F); - void PropagateLiveness(const RetOrArg &RA); - bool RemoveDeadStuffFromFunction(Function *F); - bool DeleteDeadVarargs(Function &Fn); - bool RemoveDeadArgumentsFromCallers(Function &Fn); + void markLive(const RetOrArg &RA); + void markLive(const Function &F); + void propagateLiveness(const RetOrArg &RA); + bool removeDeadStuffFromFunction(Function *F); + bool deleteDeadVarargs(Function &F); + bool removeDeadArgumentsFromCallers(Function &F); }; } // end namespace llvm diff --git a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp --- a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -16,7 +16,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Transforms/IPO/DeadArgumentElimination.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/Argument.h" @@ -44,6 +43,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/DeadArgumentElimination.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include #include @@ -54,36 +54,36 @@ #define DEBUG_TYPE "deadargelim" STATISTIC(NumArgumentsEliminated, "Number of unread args removed"); -STATISTIC(NumRetValsEliminated , "Number of unused return values removed"); +STATISTIC(NumRetValsEliminated, "Number of unused return values removed"); STATISTIC(NumArgumentsReplacedWithPoison, "Number of unread args replaced with poison"); namespace { - /// DAE - The dead argument elimination pass. - class DAE : public ModulePass { - protected: - // DAH uses this to specify a different ID. - explicit DAE(char &ID) : ModulePass(ID) {} +/// The dead argument elimination pass. +class DAE : public ModulePass { +protected: + // DAH uses this to specify a different ID. + explicit DAE(char &ID) : ModulePass(ID) {} - public: - static char ID; // Pass identification, replacement for typeid +public: + static char ID; // Pass identification, replacement for typeid - DAE() : ModulePass(ID) { - initializeDAEPass(*PassRegistry::getPassRegistry()); - } + DAE() : ModulePass(ID) { + initializeDAEPass(*PassRegistry::getPassRegistry()); + } - bool runOnModule(Module &M) override { - if (skipModule(M)) - return false; - DeadArgumentEliminationPass DAEP(ShouldHackArguments()); - ModuleAnalysisManager DummyMAM; - PreservedAnalyses PA = DAEP.run(M, DummyMAM); - return !PA.areAllPreserved(); - } + bool runOnModule(Module &M) override { + if (skipModule(M)) + return false; + DeadArgumentEliminationPass DAEP(shouldHackArguments()); + ModuleAnalysisManager DummyMAM; + PreservedAnalyses PA = DAEP.run(M, DummyMAM); + return !PA.areAllPreserved(); + } - virtual bool ShouldHackArguments() const { return false; } - }; + virtual bool shouldHackArguments() const { return false; } +}; } // end anonymous namespace @@ -93,51 +93,51 @@ namespace { - /// DAH - 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 { - static char ID; +/// 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 { + static char ID; - DAH() : DAE(ID) {} + DAH() : DAE(ID) {} - bool ShouldHackArguments() const override { return true; } - }; + bool shouldHackArguments() const override { return true; } +}; } // end anonymous namespace char DAH::ID = 0; INITIALIZE_PASS(DAH, "deadarghaX0r", - "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)", - false, false) + "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)", false, + false) -/// createDeadArgEliminationPass - This pass removes arguments from functions -/// which are not used by the body of the function. +/// This pass removes arguments from functions which are not used by the body of +/// the function. ModulePass *llvm::createDeadArgEliminationPass() { return new DAE(); } ModulePass *llvm::createDeadArgHackingPass() { return new DAH(); } -/// DeleteDeadVarargs - 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 &Fn) { - assert(Fn.getFunctionType()->isVarArg() && "Function isn't varargs!"); - if (Fn.isDeclaration() || !Fn.hasLocalLinkage()) return false; +/// 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) { + assert(F.getFunctionType()->isVarArg() && "Function isn't varargs!"); + if (F.isDeclaration() || !F.hasLocalLinkage()) + return false; // Ensure that the function is only directly called. - if (Fn.hasAddressTaken()) + if (F.hasAddressTaken()) return false; // Don't touch naked functions. The assembly might be using an argument, or // otherwise rely on the frame layout in a way that this analysis will not // see. - if (Fn.hasFnAttribute(Attribute::Naked)) { + if (F.hasFnAttribute(Attribute::Naked)) { return false; } // Okay, we know we can transform this function if safe. Scan its body // looking for calls marked musttail or calls to llvm.vastart. - for (BasicBlock &BB : Fn) { + for (BasicBlock &BB : F) { for (Instruction &I : BB) { CallInst *CI = dyn_cast(&I); if (!CI) @@ -156,25 +156,24 @@ // Start by computing a new prototype for the function, which is the same as // the old function, but doesn't have isVarArg set. - FunctionType *FTy = Fn.getFunctionType(); + FunctionType *FTy = F.getFunctionType(); std::vector Params(FTy->param_begin(), FTy->param_end()); - FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), - Params, false); + FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false); unsigned NumArgs = Params.size(); // Create the new function body and insert it into the module... - Function *NF = Function::Create(NFTy, Fn.getLinkage(), Fn.getAddressSpace()); - NF->copyAttributesFrom(&Fn); - NF->setComdat(Fn.getComdat()); - Fn.getParent()->getFunctionList().insert(Fn.getIterator(), NF); - NF->takeName(&Fn); + Function *NF = Function::Create(NFTy, F.getLinkage(), F.getAddressSpace()); + NF->copyAttributesFrom(&F); + NF->setComdat(F.getComdat()); + F.getParent()->getFunctionList().insert(F.getIterator(), NF); + NF->takeName(&F); - // Loop over all of the callers of the function, transforming the call sites + // Loop over all the callers of the function, transforming the call sites // to pass in a smaller number of arguments into the new function. // std::vector Args; - for (User *U : llvm::make_early_inc_range(Fn.users())) { + for (User *U : llvm::make_early_inc_range(F.users())) { CallBase *CB = dyn_cast(U); if (!CB) continue; @@ -188,7 +187,7 @@ SmallVector ArgAttrs; for (unsigned ArgNo = 0; ArgNo < NumArgs; ++ArgNo) ArgAttrs.push_back(PAL.getParamAttrs(ArgNo)); - PAL = AttributeList::get(Fn.getContext(), PAL.getFnAttrs(), + PAL = AttributeList::get(F.getContext(), PAL.getFnAttrs(), PAL.getRetAttrs(), ArgAttrs); } @@ -223,38 +222,38 @@ // Since we have now created the new function, splice the body of the old // function right into the new function, leaving the old rotting hulk of the // function empty. - NF->getBasicBlockList().splice(NF->begin(), Fn.getBasicBlockList()); + NF->getBasicBlockList().splice(NF->begin(), F.getBasicBlockList()); // Loop over the argument list, transferring uses of the old arguments over to - // the new arguments, also transferring over the names as well. While we're at - // it, remove the dead arguments from the DeadArguments list. - for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(), - I2 = NF->arg_begin(); I != E; ++I, ++I2) { + // the new arguments, also transferring over the names as well. While we're + // at it, remove the dead arguments from the DeadArguments list. + for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(), + I2 = NF->arg_begin(); + I != E; ++I, ++I2) { // Move the name and users over to the new version. I->replaceAllUsesWith(&*I2); I2->takeName(&*I); } - // Clone metadatas from the old function, including debug info descriptor. + // Clone metadata from the old function, including debug info descriptor. SmallVector, 1> MDs; - Fn.getAllMetadata(MDs); + F.getAllMetadata(MDs); for (auto MD : MDs) NF->addMetadata(MD.first, *MD.second); // Fix up any BlockAddresses that refer to the function. - Fn.replaceAllUsesWith(ConstantExpr::getBitCast(NF, Fn.getType())); + F.replaceAllUsesWith(ConstantExpr::getBitCast(NF, F.getType())); // Delete the bitcast that we just created, so that NF does not // appear to be address-taken. NF->removeDeadConstantUsers(); // Finally, nuke the old function. - Fn.eraseFromParent(); + F.eraseFromParent(); return true; } -/// RemoveDeadArgumentsFromCallers - Checks if the given function has any -/// arguments that are unused, and changes the caller parameters to be poison -/// instead. -bool DeadArgumentEliminationPass::RemoveDeadArgumentsFromCallers(Function &Fn) { +/// 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) { // We cannot change the arguments if this TU does not define the function or // if the linker may choose a function body from another TU, even if the // nominal linkage indicates that other copies of the function have the same @@ -266,24 +265,24 @@ // %v = load i32 %p // ret void // } - if (!Fn.hasExactDefinition()) + if (!F.hasExactDefinition()) return false; // Functions with local linkage should already have been handled, except if // they are fully alive (e.g., called indirectly) and except for the fragile // (variadic) ones. In these cases, we may still be able to improve their // statically known call sites. - if ((Fn.hasLocalLinkage() && !LiveFunctions.count(&Fn)) && - !Fn.getFunctionType()->isVarArg()) + if ((F.hasLocalLinkage() && !LiveFunctions.count(&F)) && + !F.getFunctionType()->isVarArg()) return false; // Don't touch naked functions. The assembly might be using an argument, or // otherwise rely on the frame layout in a way that this analysis will not // see. - if (Fn.hasFnAttribute(Attribute::Naked)) + if (F.hasFnAttribute(Attribute::Naked)) return false; - if (Fn.use_empty()) + if (F.use_empty()) return false; SmallVector UnusedArgs; @@ -291,7 +290,7 @@ AttributeMask UBImplyingAttributes = AttributeFuncs::getUBImplyingAttributes(); - for (Argument &Arg : Fn.args()) { + for (Argument &Arg : F.args()) { if (!Arg.hasSwiftErrorAttr() && Arg.use_empty() && !Arg.hasPassPointeeByValueCopyAttr()) { if (Arg.isUsedByMetadata()) { @@ -299,17 +298,17 @@ Changed = true; } UnusedArgs.push_back(Arg.getArgNo()); - Fn.removeParamAttrs(Arg.getArgNo(), UBImplyingAttributes); + F.removeParamAttrs(Arg.getArgNo(), UBImplyingAttributes); } } if (UnusedArgs.empty()) return false; - for (Use &U : Fn.uses()) { + for (Use &U : F.uses()) { CallBase *CB = dyn_cast(U.getUser()); if (!CB || !CB->isCallee(&U) || - CB->getFunctionType() != Fn.getFunctionType()) + CB->getFunctionType() != F.getFunctionType()) continue; // Now go through all unused args and replace them with poison. @@ -331,16 +330,15 @@ /// 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) { +static unsigned numRetVals(const Function *F) { Type *RetTy = F->getReturnType(); if (RetTy->isVoidTy()) return 0; - else if (StructType *STy = dyn_cast(RetTy)) + if (StructType *STy = dyn_cast(RetTy)) return STy->getNumElements(); - else if (ArrayType *ATy = dyn_cast(RetTy)) + if (ArrayType *ATy = dyn_cast(RetTy)) return ATy->getNumElements(); - else - return 1; + return 1; } /// Returns the sub-type a function will return at a given Idx. Should @@ -352,20 +350,18 @@ if (StructType *STy = dyn_cast(RetTy)) return STy->getElementType(Idx); - else if (ArrayType *ATy = dyn_cast(RetTy)) + if (ArrayType *ATy = dyn_cast(RetTy)) return ATy->getElementType(); - else - return RetTy; + return RetTy; } -/// MarkIfNotLive - This checks Use for liveness in LiveValues. If Use is not -/// live, it adds Use to the MaybeLiveUses argument. Returns the determined -/// liveness of Use. +/// 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, +DeadArgumentEliminationPass::markIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses) { // We're live if our use or its Function is already marked as live. - if (IsLive(Use)) + if (isLive(Use)) return Live; // We're maybe live otherwise, but remember that we must become live if @@ -374,127 +370,127 @@ return MaybeLive; } -/// SurveyUse - This 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. +/// 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, +DeadArgumentEliminationPass::surveyUse(const Use *U, UseVector &MaybeLiveUses, unsigned RetValNum) { - const User *V = U->getUser(); - if (const ReturnInst *RI = dyn_cast(V)) { - // The value is returned from a function. It's only live when the - // function's return value is live. We use RetValNum here, for the case - // that U is really a use of an insertvalue instruction that uses the - // original Use. - const Function *F = RI->getParent()->getParent(); - if (RetValNum != -1U) { - RetOrArg Use = CreateRet(F, RetValNum); - // We might be live, depending on the liveness of Use. - return MarkIfNotLive(Use, MaybeLiveUses); - } else { - DeadArgumentEliminationPass::Liveness Result = MaybeLive; - for (unsigned Ri = 0; Ri < NumRetVals(F); ++Ri) { - RetOrArg Use = CreateRet(F, Ri); - // We might be live, depending on the liveness of Use. If any - // sub-value is live, then the entire value is considered live. This - // is a conservative choice, and better tracking is possible. - DeadArgumentEliminationPass::Liveness SubResult = - MarkIfNotLive(Use, MaybeLiveUses); - if (Result != Live) - Result = SubResult; - } - return Result; - } + const User *V = U->getUser(); + if (const ReturnInst *RI = dyn_cast(V)) { + // The value is returned from a function. It's only live when the + // function's return value is live. We use RetValNum here, for the case + // that U is really a use of an insertvalue instruction that uses the + // original Use. + const Function *F = RI->getParent()->getParent(); + if (RetValNum != -1U) { + RetOrArg Use = createRet(F, RetValNum); + // We might be live, depending on the liveness of Use. + return markIfNotLive(Use, MaybeLiveUses); } - if (const InsertValueInst *IV = dyn_cast(V)) { - if (U->getOperandNo() != InsertValueInst::getAggregateOperandIndex() - && IV->hasIndices()) - // The use we are examining is inserted into an aggregate. Our liveness - // depends on all uses of that aggregate, but if it is used as a return - // value, only index at which we were inserted counts. - RetValNum = *IV->idx_begin(); - - // Note that if we are used as the aggregate operand to the insertvalue, - // we don't change RetValNum, but do survey all our uses. - - Liveness Result = MaybeLive; - for (const Use &UU : IV->uses()) { - Result = SurveyUse(&UU, MaybeLiveUses, RetValNum); - if (Result == Live) - break; - } - return Result; + + DeadArgumentEliminationPass::Liveness Result = MaybeLive; + for (unsigned Ri = 0; Ri < numRetVals(F); ++Ri) { + RetOrArg Use = createRet(F, Ri); + // We might be live, depending on the liveness of Use. If any + // sub-value is live, then the entire value is considered live. This + // is a conservative choice, and better tracking is possible. + DeadArgumentEliminationPass::Liveness SubResult = + markIfNotLive(Use, MaybeLiveUses); + if (Result != Live) + Result = SubResult; + } + return Result; + } + + if (const InsertValueInst *IV = dyn_cast(V)) { + if (U->getOperandNo() != InsertValueInst::getAggregateOperandIndex() && + IV->hasIndices()) + // The use we are examining is inserted into an aggregate. Our liveness + // depends on all uses of that aggregate, but if it is used as a return + // value, only index at which we were inserted counts. + RetValNum = *IV->idx_begin(); + + // Note that if we are used as the aggregate operand to the insertvalue, + // we don't change RetValNum, but do survey all our uses. + + Liveness Result = MaybeLive; + for (const Use &UU : IV->uses()) { + Result = surveyUse(&UU, MaybeLiveUses, RetValNum); + if (Result == Live) + break; } + return Result; + } - if (const auto *CB = dyn_cast(V)) { - const Function *F = CB->getCalledFunction(); - if (F) { - // Used in a direct call. + if (const auto *CB = dyn_cast(V)) { + const Function *F = CB->getCalledFunction(); + if (F) { + // Used in a direct call. - // The function argument is live if it is used as a bundle operand. - if (CB->isBundleOperand(U)) - return Live; + // The function argument is live if it is used as a bundle operand. + if (CB->isBundleOperand(U)) + return Live; - // Find the argument number. We know for sure that this use is an - // argument, since if it was the function argument this would be an - // indirect call and the we know can't be looking at a value of the - // label type (for the invoke instruction). - unsigned ArgNo = CB->getArgOperandNo(U); + // Find the argument number. We know for sure that this use is an + // argument, since if it was the function argument this would be an + // indirect call and that we know can't be looking at a value of the + // label type (for the invoke instruction). + unsigned ArgNo = CB->getArgOperandNo(U); - if (ArgNo >= F->getFunctionType()->getNumParams()) - // The value is passed in through a vararg! Must be live. - return Live; + if (ArgNo >= F->getFunctionType()->getNumParams()) + // The value is passed in through a vararg! Must be live. + return Live; - assert(CB->getArgOperand(ArgNo) == CB->getOperand(U->getOperandNo()) && - "Argument is not where we expected it"); + assert(CB->getArgOperand(ArgNo) == CB->getOperand(U->getOperandNo()) && + "Argument is not where we expected it"); - // Value passed to a normal call. It's only live when the corresponding - // argument to the called function turns out live. - RetOrArg Use = CreateArg(F, ArgNo); - return MarkIfNotLive(Use, MaybeLiveUses); - } + // Value passed to a normal call. It's only live when the corresponding + // argument to the called function turns out live. + RetOrArg Use = createArg(F, ArgNo); + return markIfNotLive(Use, MaybeLiveUses); } - // Used in any other way? Value must be live. - return Live; + } + // Used in any other way? Value must be live. + return Live; } -/// SurveyUses - This looks at all the uses of the given value +/// 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, +DeadArgumentEliminationPass::surveyUses(const Value *V, UseVector &MaybeLiveUses) { // Assume it's dead (which will only hold if there are no uses at all..). Liveness Result = MaybeLive; // Check each use. for (const Use &U : V->uses()) { - Result = SurveyUse(&U, MaybeLiveUses); + Result = surveyUse(&U, MaybeLiveUses); if (Result == Live) break; } return Result; } -// SurveyFunction - This performs the initial survey of the specified function, -// checking out whether or not 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) { +/// 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) { // Functions with inalloca/preallocated parameters are expecting args in a // particular register and memory layout. if (F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) || F.getAttributes().hasAttrSomewhere(Attribute::Preallocated)) { - MarkLive(F); + markLive(F); return; } @@ -502,11 +498,11 @@ // otherwise rely on the frame layout in a way that this analysis will not // see. if (F.hasFnAttribute(Attribute::Naked)) { - MarkLive(F); + markLive(F); return; } - unsigned RetCount = NumRetVals(&F); + unsigned RetCount = numRetVals(&F); // Assume all return values are dead using RetVals = SmallVector; @@ -534,7 +530,7 @@ } if (!F.hasLocalLinkage() && (!ShouldHackArguments || F.isIntrinsic())) { - MarkLive(F); + markLive(F); return; } @@ -554,7 +550,7 @@ const auto *CB = dyn_cast(U.getUser()); if (!CB || !CB->isCallee(&U) || CB->getFunctionType() != F.getFunctionType()) { - MarkLive(F); + markLive(F); return; } @@ -571,13 +567,13 @@ continue; // Check all uses of the return value. - for (const Use &U : CB->uses()) { - if (ExtractValueInst *Ext = dyn_cast(U.getUser())) { + for (const Use &UU : CB->uses()) { + if (ExtractValueInst *Ext = dyn_cast(UU.getUser())) { // This use uses a part of our return value, survey the uses of // that part and store the results for this index only. unsigned Idx = *Ext->idx_begin(); if (RetValLiveness[Idx] != Live) { - RetValLiveness[Idx] = SurveyUses(Ext, MaybeLiveRetUses[Idx]); + RetValLiveness[Idx] = surveyUses(Ext, MaybeLiveRetUses[Idx]); if (RetValLiveness[Idx] == Live) NumLiveRetVals++; } @@ -585,16 +581,16 @@ // Used by something else than extractvalue. Survey, but assume that the // result applies to all sub-values. UseVector MaybeLiveAggregateUses; - if (SurveyUse(&U, MaybeLiveAggregateUses) == Live) { + if (surveyUse(&UU, MaybeLiveAggregateUses) == Live) { NumLiveRetVals = RetCount; RetValLiveness.assign(RetCount, Live); break; - } else { - for (unsigned Ri = 0; Ri != RetCount; ++Ri) { - if (RetValLiveness[Ri] != Live) - MaybeLiveRetUses[Ri].append(MaybeLiveAggregateUses.begin(), - MaybeLiveAggregateUses.end()); - } + } + + for (unsigned Ri = 0; Ri != RetCount; ++Ri) { + if (RetValLiveness[Ri] != Live) + MaybeLiveRetUses[Ri].append(MaybeLiveAggregateUses.begin(), + MaybeLiveAggregateUses.end()); } } } @@ -607,7 +603,7 @@ // Now we've inspected all callers, record the liveness of our return values. for (unsigned Ri = 0; Ri != RetCount; ++Ri) - MarkValue(CreateRet(&F, Ri), RetValLiveness[Ri], MaybeLiveRetUses[Ri]); + markValue(createRet(&F, Ri), RetValLiveness[Ri], MaybeLiveRetUses[Ri]); LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Inspecting args for fn: " << F.getName() << "\n"); @@ -635,81 +631,77 @@ } else { // See what the effect of this use is (recording any uses that cause // MaybeLive in MaybeLiveArgUses). - Result = SurveyUses(&*AI, MaybeLiveArgUses); + Result = surveyUses(&*AI, MaybeLiveArgUses); } // Mark the result. - MarkValue(CreateArg(&F, ArgI), Result, MaybeLiveArgUses); + markValue(createArg(&F, ArgI), Result, MaybeLiveArgUses); // Clear the vector again for the next iteration. MaybeLiveArgUses.clear(); } } -/// MarkValue - This function 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, +/// 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) { switch (L) { - case Live: - MarkLive(RA); - break; - case MaybeLive: - assert(!IsLive(RA) && "Use is already live!"); - for (const auto &MaybeLiveUse : MaybeLiveUses) { - if (IsLive(MaybeLiveUse)) { - // A use is live, so this value is live. - MarkLive(RA); - break; - } else { - // Note any uses of this value, so this value can be - // marked live whenever one of the uses becomes live. - Uses.insert(std::make_pair(MaybeLiveUse, RA)); - } + case Live: + markLive(RA); + break; + case MaybeLive: + assert(!isLive(RA) && "Use is already live!"); + for (const auto &MaybeLiveUse : MaybeLiveUses) { + if (isLive(MaybeLiveUse)) { + // A use is live, so this value is live. + markLive(RA); + break; } - break; + // Note any uses of this value, so this value can be + // marked live whenever one of the uses becomes live. + Uses.insert(std::make_pair(MaybeLiveUse, RA)); + } + break; } } -/// MarkLive - 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 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) { LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Intrinsically live fn: " << F.getName() << "\n"); // Mark the function as live. LiveFunctions.insert(&F); // Mark all arguments as live. for (unsigned ArgI = 0, E = F.arg_size(); ArgI != E; ++ArgI) - PropagateLiveness(CreateArg(&F, ArgI)); + propagateLiveness(createArg(&F, ArgI)); // Mark all return values as live. - for (unsigned Ri = 0, E = NumRetVals(&F); Ri != E; ++Ri) - PropagateLiveness(CreateRet(&F, Ri)); + for (unsigned Ri = 0, E = numRetVals(&F); Ri != E; ++Ri) + propagateLiveness(createRet(&F, Ri)); } -/// MarkLive - 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) { - if (IsLive(RA)) +/// 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) { + if (isLive(RA)) return; // Already marked Live. LiveValues.insert(RA); LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Marking " << RA.getDescription() << " live\n"); - PropagateLiveness(RA); + propagateLiveness(RA); } -bool DeadArgumentEliminationPass::IsLive(const RetOrArg &RA) { +bool DeadArgumentEliminationPass::isLive(const RetOrArg &RA) { return LiveFunctions.count(RA.F) || LiveValues.count(RA); } -/// PropagateLiveness - 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) { +/// 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) { // We don't use upper_bound (or equal_range) here, because our recursive call // to ourselves is likely to cause the upper_bound (which is the first value // not belonging to RA) to become erased and the iterator invalidated. @@ -717,18 +709,17 @@ UseMap::iterator E = Uses.end(); UseMap::iterator I; for (I = Begin; I != E && I->first == RA; ++I) - MarkLive(I->second); + markLive(I->second); // Erase RA from the Uses map (from the lower bound to wherever we ended up // after the loop). Uses.erase(Begin, I); } -// RemoveDeadStuffFromFunction - Remove any arguments and return values from F -// that are not in LiveValues. Transform the function and all of the callees of -// the function to not have these arguments and return values. -// -bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) { +/// 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) { // Don't modify fully live functions if (LiveFunctions.count(F)) return false; @@ -736,7 +727,7 @@ // Start by computing a new prototype for the function, which is the same as // the old function, but has fewer arguments and a different return type. FunctionType *FTy = F->getFunctionType(); - std::vector Params; + std::vector Params; // Keep track of if we have a live 'returned' argument bool HasLiveReturnedArg = false; @@ -753,7 +744,7 @@ unsigned ArgI = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++ArgI) { - RetOrArg Arg = CreateArg(F, ArgI); + RetOrArg Arg = createArg(F, ArgI); if (LiveValues.erase(Arg)) { Params.push_back(I->getType()); ArgAlive[ArgI] = true; @@ -770,11 +761,11 @@ // Find out the new return value. Type *RetTy = FTy->getReturnType(); Type *NRetTy = nullptr; - unsigned RetCount = NumRetVals(F); + unsigned RetCount = numRetVals(F); // -1 means unused, other numbers are the new index SmallVector NewRetIdxs(RetCount, -1); - std::vector RetTypes; + std::vector RetTypes; // If there is a function with a live 'returned' argument but a dead return // value, then there are two possible actions: @@ -786,9 +777,9 @@ // It's not clear in the general case which option is more profitable because, // even in the absence of explicit uses of the return value, code generation // is free to use the 'returned' attribute to do things like eliding - // save/restores of registers across calls. Whether or not this happens is - // target and ABI-specific as well as depending on the amount of register - // pressure, so there's no good way for an IR-level pass to figure this out. + // save/restores of registers across calls. Whether this happens is target and + // ABI-specific as well as depending on the amount of register pressure, so + // there's no good way for an IR-level pass to figure this out. // // Fortunately, the only places where 'returned' is currently generated by // the FE are places where 'returned' is basically free and almost always a @@ -800,7 +791,7 @@ } else { // Look at each of the original return values individually. for (unsigned Ri = 0; Ri != RetCount; ++Ri) { - RetOrArg Ret = CreateRet(F, Ri); + RetOrArg Ret = createRet(F, Ri); if (LiveValues.erase(Ret)) { RetTypes.push_back(getRetComponentType(F, Ri)); NewRetIdxs[Ri] = RetTypes.size() - 1; @@ -873,9 +864,9 @@ F->getParent()->getFunctionList().insert(F->getIterator(), NF); NF->takeName(F); - // Loop over all of the callers of the function, transforming the call sites - // to pass in a smaller number of arguments into the new function. - std::vector Args; + // Loop over all the callers of the function, transforming the call sites to + // pass in a smaller number of arguments into the new function. + std::vector Args; while (!F->use_empty()) { CallBase &CB = cast(*F->user_back()); @@ -890,7 +881,7 @@ // Declare these outside of the loops, so we can reuse them for the second // loop, which loops the varargs. - auto I = CB.arg_begin(); + auto *I = CB.arg_begin(); unsigned Pi = 0; // Loop over those operands, corresponding to the normal arguments to the // original function, and add those that are still alive. @@ -903,11 +894,11 @@ // If the return type has changed, then get rid of 'returned' on the // call site. The alternative is to make all 'returned' attributes on // call sites keep the return value alive just like 'returned' - // attributes on function declaration but it's less clearly a win and + // attributes on function declaration, but it's less clearly a win and // this is not an expected case anyway ArgAttrVec.push_back(AttributeSet::get( - F->getContext(), - AttrBuilder(F->getContext(), Attrs).removeAttribute(Attribute::Returned))); + F->getContext(), AttrBuilder(F->getContext(), Attrs) + .removeAttribute(Attribute::Returned))); } else { // Otherwise, use the original attributes. ArgAttrVec.push_back(Attrs); @@ -915,7 +906,7 @@ } // Push any varargs arguments on the list. Don't forget their attributes. - for (auto E = CB.arg_end(); I != E; ++I, ++Pi) { + for (auto *E = CB.arg_end(); I != E; ++I, ++Pi) { Args.push_back(*I); ArgAttrVec.push_back(CallPAL.getParamAttrs(Pi)); } @@ -928,8 +919,8 @@ AttributeSet FnAttrs = CallPAL.getFnAttrs().removeAttribute( F->getContext(), Attribute::AllocSize); - AttributeList NewCallPAL = AttributeList::get( - F->getContext(), FnAttrs, RetAttrs, ArgAttrVec); + AttributeList NewCallPAL = + AttributeList::get(F->getContext(), FnAttrs, RetAttrs, ArgAttrVec); SmallVector OpBundles; CB.getOperandBundlesAsDefs(OpBundles); @@ -1068,16 +1059,16 @@ BB.getInstList().erase(RI); } - // Clone metadatas from the old function, including debug info descriptor. + // Clone metadata from the old function, including debug info descriptor. SmallVector, 1> MDs; F->getAllMetadata(MDs); for (auto MD : MDs) NF->addMetadata(MD.first, *MD.second); // If either the return value(s) or argument(s) are removed, then probably the - // function does not follow standard calling conventions anymore. Hence add - // DW_CC_nocall to DISubroutineType to inform debugger that it may not safe to - // call this function or try to interpret the return value. + // function does not follow standard calling conventions anymore. Hence, add + // DW_CC_nocall to DISubroutineType to inform debugger that it may not be safe + // to call this function or try to interpret the return value. if (NFTy != FTy && NF->getSubprogram()) { DISubprogram *SP = NF->getSubprogram(); auto Temp = SP->getType()->cloneWithCC(llvm::dwarf::DW_CC_nocall); @@ -1101,26 +1092,25 @@ LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Deleting dead varargs\n"); for (Function &F : llvm::make_early_inc_range(M)) if (F.getFunctionType()->isVarArg()) - Changed |= DeleteDeadVarargs(F); + Changed |= deleteDeadVarargs(F); - // Second phase:loop through the module, determining which arguments are live. - // We assume all arguments are dead unless proven otherwise (allowing us to - // determine that dead arguments passed into recursive functions are dead). - // + // Second phase: Loop through the module, determining which arguments are + // live. We assume all arguments are dead unless proven otherwise (allowing us + // to determine that dead arguments passed into recursive functions are dead). LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Determining liveness\n"); for (auto &F : M) - SurveyFunction(F); + surveyFunction(F); // Now, remove all dead arguments and return values from each function in // turn. We use make_early_inc_range here because functions will probably get // removed (i.e. replaced by new ones). for (Function &F : llvm::make_early_inc_range(M)) - Changed |= RemoveDeadStuffFromFunction(&F); + Changed |= removeDeadStuffFromFunction(&F); // Finally, look for any unused parameters in functions with non-local // linkage and replace the passed in parameters with poison. for (auto &F : M) - Changed |= RemoveDeadArgumentsFromCallers(F); + Changed |= removeDeadArgumentsFromCallers(F); if (!Changed) return PreservedAnalyses::all();