DeadArgumentElimination.h revision 303231
1303231Sdim//===- DeadArgumentElimination.h - Eliminate Dead Args ----------*- C++ -*-===//
2303231Sdim//
3303231Sdim//                     The LLVM Compiler Infrastructure
4303231Sdim//
5303231Sdim// This file is distributed under the University of Illinois Open Source
6303231Sdim// License. See LICENSE.TXT for details.
7303231Sdim//
8303231Sdim//===----------------------------------------------------------------------===//
9303231Sdim//
10303231Sdim// This pass deletes dead arguments from internal functions.  Dead argument
11303231Sdim// elimination removes arguments which are directly dead, as well as arguments
12303231Sdim// only passed into function calls as dead arguments of other functions.  This
13303231Sdim// pass also deletes dead return values in a similar way.
14303231Sdim//
15303231Sdim// This pass is often useful as a cleanup pass to run after aggressive
16303231Sdim// interprocedural passes, which add possibly-dead arguments or return values.
17303231Sdim//
18303231Sdim//===----------------------------------------------------------------------===//
19303231Sdim
20303231Sdim#ifndef LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
21303231Sdim#define LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
22303231Sdim
23303231Sdim#include "llvm/IR/Module.h"
24303231Sdim#include "llvm/IR/PassManager.h"
25303231Sdim
26303231Sdim#include <map>
27303231Sdim#include <set>
28303231Sdim#include <string>
29303231Sdim
30303231Sdimnamespace llvm {
31303231Sdim
32303231Sdim/// Eliminate dead arguments (and return values) from functions.
33303231Sdimclass DeadArgumentEliminationPass
34303231Sdim    : public PassInfoMixin<DeadArgumentEliminationPass> {
35303231Sdimpublic:
36303231Sdim  /// Struct that represents (part of) either a return value or a function
37303231Sdim  /// argument.  Used so that arguments and return values can be used
38303231Sdim  /// interchangeably.
39303231Sdim  struct RetOrArg {
40303231Sdim    RetOrArg(const Function *F, unsigned Idx, bool IsArg)
41303231Sdim        : F(F), Idx(Idx), IsArg(IsArg) {}
42303231Sdim    const Function *F;
43303231Sdim    unsigned Idx;
44303231Sdim    bool IsArg;
45303231Sdim
46303231Sdim    /// Make RetOrArg comparable, so we can put it into a map.
47303231Sdim    bool operator<(const RetOrArg &O) const {
48303231Sdim      return std::tie(F, Idx, IsArg) < std::tie(O.F, O.Idx, O.IsArg);
49303231Sdim    }
50303231Sdim
51303231Sdim    /// Make RetOrArg comparable, so we can easily iterate the multimap.
52303231Sdim    bool operator==(const RetOrArg &O) const {
53303231Sdim      return F == O.F && Idx == O.Idx && IsArg == O.IsArg;
54303231Sdim    }
55303231Sdim
56303231Sdim    std::string getDescription() const {
57303231Sdim      return (Twine(IsArg ? "Argument #" : "Return value #") + Twine(Idx) +
58303231Sdim              " of function " + F->getName())
59303231Sdim          .str();
60303231Sdim    }
61303231Sdim  };
62303231Sdim
63303231Sdim  /// Liveness enum - During our initial pass over the program, we determine
64303231Sdim  /// that things are either alive or maybe alive. We don't mark anything
65303231Sdim  /// explicitly dead (even if we know they are), since anything not alive
66303231Sdim  /// with no registered uses (in Uses) will never be marked alive and will
67303231Sdim  /// thus become dead in the end.
68303231Sdim  enum Liveness { Live, MaybeLive };
69303231Sdim
70303231Sdim  /// Convenience wrapper
71303231Sdim  RetOrArg CreateRet(const Function *F, unsigned Idx) {
72303231Sdim    return RetOrArg(F, Idx, false);
73303231Sdim  }
74303231Sdim  /// Convenience wrapper
75303231Sdim  RetOrArg CreateArg(const Function *F, unsigned Idx) {
76303231Sdim    return RetOrArg(F, Idx, true);
77303231Sdim  }
78303231Sdim
79303231Sdim  typedef std::multimap<RetOrArg, RetOrArg> UseMap;
80303231Sdim  /// This maps a return value or argument to any MaybeLive return values or
81303231Sdim  /// arguments it uses. This allows the MaybeLive values to be marked live
82303231Sdim  /// when any of its users is marked live.
83303231Sdim  /// For example (indices are left out for clarity):
84303231Sdim  ///  - Uses[ret F] = ret G
85303231Sdim  ///    This means that F calls G, and F returns the value returned by G.
86303231Sdim  ///  - Uses[arg F] = ret G
87303231Sdim  ///    This means that some function calls G and passes its result as an
88303231Sdim  ///    argument to F.
89303231Sdim  ///  - Uses[ret F] = arg F
90303231Sdim  ///    This means that F returns one of its own arguments.
91303231Sdim  ///  - Uses[arg F] = arg G
92303231Sdim  ///    This means that G calls F and passes one of its own (G's) arguments
93303231Sdim  ///    directly to F.
94303231Sdim  UseMap Uses;
95303231Sdim
96303231Sdim  typedef std::set<RetOrArg> LiveSet;
97303231Sdim  typedef std::set<const Function *> LiveFuncSet;
98303231Sdim
99303231Sdim  /// This set contains all values that have been determined to be live.
100303231Sdim  LiveSet LiveValues;
101303231Sdim  /// This set contains all values that are cannot be changed in any way.
102303231Sdim  LiveFuncSet LiveFunctions;
103303231Sdim
104303231Sdim  typedef SmallVector<RetOrArg, 5> UseVector;
105303231Sdim
106303231Sdim  /// This allows this pass to do double-duty as the dead arg hacking pass
107303231Sdim  /// (used only by bugpoint).
108303231Sdim  bool ShouldHackArguments = false;
109303231Sdim
110303231Sdimpublic:
111303231Sdim  DeadArgumentEliminationPass(bool ShouldHackArguments_ = false)
112303231Sdim      : ShouldHackArguments(ShouldHackArguments_) {}
113303231Sdim  PreservedAnalyses run(Module &M, ModuleAnalysisManager &);
114303231Sdim
115303231Sdimprivate:
116303231Sdim  Liveness MarkIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses);
117303231Sdim  Liveness SurveyUse(const Use *U, UseVector &MaybeLiveUses,
118303231Sdim                     unsigned RetValNum = -1U);
119303231Sdim  Liveness SurveyUses(const Value *V, UseVector &MaybeLiveUses);
120303231Sdim
121303231Sdim  void SurveyFunction(const Function &F);
122303231Sdim  void MarkValue(const RetOrArg &RA, Liveness L,
123303231Sdim                 const UseVector &MaybeLiveUses);
124303231Sdim  void MarkLive(const RetOrArg &RA);
125303231Sdim  void MarkLive(const Function &F);
126303231Sdim  void PropagateLiveness(const RetOrArg &RA);
127303231Sdim  bool RemoveDeadStuffFromFunction(Function *F);
128303231Sdim  bool DeleteDeadVarargs(Function &Fn);
129303231Sdim  bool RemoveDeadArgumentsFromCallers(Function &Fn);
130303231Sdim};
131303231Sdim}
132303231Sdim
133303231Sdim#endif // LLVM_TRANSFORMS_IPO_DEADARGUMENTELIMINATION_H
134