#ifndef LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
#define LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
#include <map>
#include <set>
#include <string>
#include <tuple>
namespace llvm {
class Module;
class Use;
class Value;
class DeadArgumentEliminationPass
: public PassInfoMixin<DeadArgumentEliminationPass> {
public:
struct RetOrArg {
const Function *F;
unsigned Idx;
bool IsArg;
RetOrArg(const Function *F, unsigned Idx, bool IsArg)
: F(F), Idx(Idx), IsArg(IsArg) {}
bool operator<(const RetOrArg &O) const {
return std::tie(F, Idx, IsArg) < std::tie(O.F, O.Idx, O.IsArg);
}
bool operator==(const RetOrArg &O) const {
return F == O.F && Idx == O.Idx && IsArg == O.IsArg;
}
std::string getDescription() const {
return (Twine(IsArg ? "Argument #" : "Return value #") + Twine(Idx) +
" of function " + F->getName())
.str();
}
};
enum Liveness { Live, MaybeLive };
DeadArgumentEliminationPass(bool ShouldHackArguments = false)
: ShouldHackArguments(ShouldHackArguments) {}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
RetOrArg createRet(const Function *F, unsigned Idx) {
return RetOrArg(F, Idx, false);
}
RetOrArg createArg(const Function *F, unsigned Idx) {
return RetOrArg(F, Idx, true);
}
using UseMap = std::multimap<RetOrArg, RetOrArg>;
UseMap Uses;
using LiveSet = std::set<RetOrArg>;
using LiveFuncSet = std::set<const Function *>;
LiveSet LiveValues;
LiveFuncSet LiveFunctions;
using UseVector = SmallVector<RetOrArg, 5>;
bool ShouldHackArguments = false;
private:
Liveness markIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses);
Liveness surveyUse(const Use *U, UseVector &MaybeLiveUses,
unsigned RetValNum = -1U);
Liveness surveyUses(const Value *V, UseVector &MaybeLiveUses);
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 &F);
bool removeDeadArgumentsFromCallers(Function &F);
};
}
#endif