OpenASIP  2.0
MachineDCE.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2012-2020 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file MachineDCE.cc
26  *
27  * Implementation of MachineDCE class.
28  *
29  * @author Mikael Lepistö
30  */
31 
32 //===-- MachineDCE.cc - Find unreachable functions for codegen --===//
33 //
34 // The LLVM Compiler Infrastructure
35 //
36 // This file is distributed under the University of Illinois Open Source
37 // License. See LICENSE.TXT for details.
38 //
39 //===----------------------------------------------------------------------===//
40 //
41 // Simple symbol based bookkeeping of which functions are really referred in code.
42 // Analyse is used by code generator finalization. (Removes unneeded functions)
43 //
44 //===----------------------------------------------------------------------===//
45 
46 #include <iostream>
47 
48 #include "MachineDCE.hh"
49 
50 using namespace llvm;
51 
52 // register as analysis pass...
53 static RegisterPass<MachineDCE>
54 R("machinedce","Symbol string based machine DCE for removing not used emulation functions", false, true);
55 char MachineDCE::ID = 0;
56 
57 //#define DEBUG_MACHINE_DCE
58 
59 /**
60  * Returns true if can find startpoint.
61  */
62 bool MachineDCE::canFindStart(const std::string& user, AvoidRecursionSet& avoid_recursion) {
63  if (avoid_recursion.find(&user) != avoid_recursion.end()) {
64  return false;
65  } else {
66  avoid_recursion.insert(&user);
67  }
68 
69  // current function is actually the start point.. nice job.
70  if (baseUsers_.find(user) != baseUsers_.end()) {
71  return true;
72  }
73 
74  UserList &usesList = usersOfValue_[user];
75 
76  // check if this function is used by start point to be sure...
77  for (UserList::iterator i= usesList.begin(); i != usesList.end(); i++) {
78  if (canFindStart((*i), avoid_recursion)) {
79  return true;
80  }
81  }
82  return false;
83 }
84 
85 void MachineDCE::addInitializer(const Constant* init, std::string& name) {
86 
87  if (const GlobalValue* gv = dyn_cast<GlobalValue>(init)) {
88 #ifdef DEBUG_MACHINE_DCE
89  errs() << "Added data " << name
90  << " to uses of value: " << gv->getName()
91  << " and " << name << " to baseUsers."
92  << "\n";
93 #endif
94  baseUsers_.insert(name);
95  usersOfValue_[gv->getName().str()].insert(name);
96  }
97 
98  if ((dyn_cast<ConstantArray>(init) != NULL) ||
99  (dyn_cast<ConstantStruct>(init) != NULL) ||
100  (dyn_cast<ConstantVector>(init) != NULL) ||
101  (dyn_cast<ConstantExpr>(init) != NULL)) {
102 
103  for (unsigned i = 0, e = init->getNumOperands(); i != e; ++i) {
104  //init->getOperand(i)->dump();
105  //addInitializer(dyn_cast<const Constant*>(init->getOperand(i)), name);
106  addInitializer(cast<Constant>(init->getOperand(i)), name);
107  }
108  }
109 }
110 
112 
113 #ifdef DEBUG_MACHINE_DCE
114  std::cerr << "Initializing MachineDCE\n";
115 #endif
116 
117  for (Module::const_iterator f = M.begin(), e = M.end(); f != e; ++f) {
118  if (!(f->getName().equals("_start") ||
119  f->getName().equals("_exit")))
120  continue;
121  baseUsers_.insert(f->getName().data());
122 #ifdef DEBUG_MACHINE_DCE
123  std::cerr << "Added " << f->getName().str()
124  << " to entry/exit functions"
125  << std::endl;
126  f->dump();
127 #endif
128  continue;
129  }
130 
131  // Go through global variables to find out.
132  for (Module::const_global_iterator i = M.global_begin();
133  i != M.global_end(); i++) {
134  std::string name = i->getName().str();
135 
136  if (!i->hasInitializer()) {
137  continue;
138  assert(false && "No initializer. External linkage?");
139  }
140 
141  const Constant* initializer = i->getInitializer();
142 #if 0
143  const Type* type = initializer->getType();
144  errs() << "Data name: " << name
145  << "\ttype: " << type->getDescription() << "\n";
146 #endif
147  addInitializer(initializer, name);
148  }
149 
150  return true;
151 }
152 
153 bool MachineDCE::runOnMachineFunction(MachineFunction &F) {
154  std::string funcName = F.getFunction().getName().str();
155 
156  // add function to function map...
157  functionMappings_[funcName] = &F;
158 
159  for (MachineFunction::const_iterator i = F.begin();
160  i != F.end(); i++) {
161  for (MachineBasicBlock::const_iterator j = i->begin();
162  j != i->end(); j++) {
163 
164  for (unsigned k = 0; k < j->getNumOperands(); k++) {
165  const MachineOperand& mo = j->getOperand(k);
166 
167  std::string moName;
168 
169  if (mo.isGlobal()) {
170  moName = mo.getGlobal()->getName().str();
171  } else if (mo.isSymbol()) {
172  moName = mo.getSymbolName();
173  }
174 
175  if (!moName.empty()) {
176  usersOfValue_[moName].insert(funcName);
177  }
178  }
179  }
180  }
181  return true;
182 }
183 
184 
186 
187  // errs() << "Finalizing MachineDCE\n";
188 
189  // For all functions check that they are reached from entrypoint of module.
190  for (FunctionMap::iterator func = functionMappings_.begin();
191  func != functionMappings_.end(); ++func) {
192 
193  AvoidRecursionSet avoid_recursion;
194 
195  if (!canFindStart(func->first, avoid_recursion)) {
196 #ifdef DEBUG_MACHINE_DCE
197  std::cerr << "Function was not referred add it to dce data: "
198  << func->first << "\n";
199 #endif
200  removeableFunctions.insert(func->first);
201  }
202  }
203 
204  return true;
205 }
llvm::MachineDCE::doFinalization
virtual bool doFinalization(Module &M) override
Definition: MachineDCE.cc:185
llvm
Definition: InlineAsmParser.hh:49
llvm::MachineDCE::ID
static char ID
Definition: MachineDCE.hh:67
llvm::MachineDCE::baseUsers_
UserList baseUsers_
If users are traced to this list it means that function cannot be eliminated.
Definition: MachineDCE.hh:82
llvm::MachineDCE::canFindStart
bool canFindStart(const std::string &user, AvoidRecursionSet &avoid_recursion)
Definition: MachineDCE.cc:62
llvm::MachineDCE::functionMappings_
FunctionMap functionMappings_
Function name to MachineFunction map.
Definition: MachineDCE.hh:75
llvm::MachineDCE::runOnMachineFunction
virtual bool runOnMachineFunction(MachineFunction &F) override
Definition: MachineDCE.cc:153
assert
#define assert(condition)
Definition: Application.hh:86
llvm::MachineDCE::AvoidRecursionSet
std::set< const std::string * > AvoidRecursionSet
Definition: MachineDCE.hh:72
llvm::MachineDCE::addInitializer
void addInitializer(const Constant *init, std::string &name)
Definition: MachineDCE.cc:85
MachineDCE.hh
R
static RegisterPass< MachineDCE > R("machinedce","Symbol string based machine DCE for removing not used emulation functions", false, true)
llvm::MachineDCE::usersOfValue_
UserRelations usersOfValue_
List of users of a symbol.
Definition: MachineDCE.hh:78
llvm::MachineDCE::doInitialization
virtual bool doInitialization(Module &M) override
Definition: MachineDCE.cc:111
llvm::MachineDCE::removeableFunctions
UnusedFunctionsList removeableFunctions
Definition: MachineDCE.hh:97
llvm::MachineDCE::UserList
std::set< std::string > UserList
Definition: MachineDCE.hh:70