OpenASIP  2.0
InnerLoopFinder.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-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 InnerLoopFinder.cc
26  *
27  * LLVM pass for finding inner loops in the code.
28  *
29  * @author 2008-2015 Pekka Jääskeläinen
30  */
31 
32 #include <sstream>
33 #include <fstream>
34 #include <string>
35 #include <map>
36 
37 #include "tce_config.h"
38 
39 #include "CompilerWarnings.hh"
40 IGNORE_COMPILER_WARNING("-Wunused-parameter")
41 IGNORE_COMPILER_WARNING("-Wcomment")
42 
43 #include <llvm/Analysis/LoopPass.h>
44 #include <llvm/Analysis/ScalarEvolution.h>
45 #include <llvm/Support/CommandLine.h>
46 
47 #include "tce_config.h"
48 
49 #include <llvm/IR/Module.h>
50 #include <llvm/IR/Constants.h>
51 #include <llvm/Analysis/LoopInfo.h>
52 #include "llvm/Transforms/Scalar.h"
53 #include "llvm/Transforms/Utils.h"
54 #include <llvm/Pass.h>
55 #include "llvm/CodeGen/Passes.h"
56 #include "InnerLoopFinder.hh"
57 
58 #include "llvm/InitializePasses.h"
59 
60 using namespace llvm;
61 
62 static llvm::cl::opt<bool>
64 ("dump-loop-info", llvm::cl::init(false), llvm::cl::Hidden,
65  llvm::cl::desc("Dump information about loops to files named [modulename].loopinfo.txt."));
66 
67 static llvm::RegisterPass</*TCE::*/InnerLoopFinder> X(
68  "find-innerloops-test",
69  "Finds inner loops test.", false, true);
70 
72  InnerLoopFinder, "find-innerloops",
73  "Finds info of the inner loops in the program.",
74  false, true)
75 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
76 INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
77 INITIALIZE_PASS_DEPENDENCY(LCSSAWrapperPass)
78 INITIALIZE_PASS_END(
80  "Finds info of the inner loops in the program.",
81  false, true)
82 
83 // Publically exposed interface to pass...
84 //const llvm::PassInfo* InnerLoopFinderID = X.getPassInfo();
85 
86 // this causes duplicate TCE namespaces , both global and
87 // llvm::TCE which break plugin build, so this taken out from
88 // tce namespace to avoid having it
89 //namespace TCE {
90 
91 char InnerLoopFinder::ID = 0;
92 
94  LoopPass(ID) {
95  dump = DumpLoopInfo;
96 }
97 
98 void
99 InnerLoopFinder::getAnalysisUsage(llvm::AnalysisUsage &AU) const {
100  AU.setPreservesCFG();
101  AU.addRequiredID(llvm::LoopSimplifyID);
102  AU.addRequiredID(llvm::LCSSAID);
103  AU.addPreservedID(llvm::LCSSAID);
104  AU.addRequired<llvm::LoopInfoWrapperPass>();
105  AU.addRequired<llvm::ScalarEvolutionWrapperPass>();
106  AU.addPreserved<llvm::LoopInfoWrapperPass>();
107  AU.addPreserved<llvm::ScalarEvolutionWrapperPass>();
108 }
109 
111  // flush and close all loop info dump files
112  if (dump) {
113  for (DumpFileIndex::iterator i = dumpFiles.begin();
114  i != dumpFiles.end(); ++i) {
115  std::ostream* stream = (*i).second;
116  stream->flush();
117  delete stream;
118  }
119  dumpFiles.clear();
120  }
121 }
122 
123 /**
124  * Returns a stream to dump the loop info to.
125  */
126 std::ostream&
127 InnerLoopFinder::out(llvm::Loop* l) {
128 
129  assert(l != NULL);
130 
131  std::string moduleName =
132  l->getHeader()->getParent()->getParent()->getModuleIdentifier();
133  std::string fName = moduleName + ".loopinfo.txt";
134  if (moduleName == "<stdin>") {
135  fName = "loopinfo.txt";
136  }
137 
138  if (dumpFiles.find(moduleName) == dumpFiles.end()) {
139  std::fstream* outStream =
140  new std::fstream(
141  fName.c_str(),
142  std::ios_base::out | std::ios_base::trunc);
143  dumpFiles[moduleName] = outStream;
144  }
145  return *dumpFiles[moduleName];
146 }
147 
148 /**
149  * Returns a textual description for the given loop.
150  */
151 std::string
153 
154  if (l == NULL)
155  return "[none]";
156 
157  std::ostringstream ss;
158  assert(l->getHeader() != NULL);
159  assert(l->getHeader()->getParent() != NULL);
160  std::string curProcName = l->getHeader()->getParent()->getName().str();
161  ss << "in " << curProcName << "()";
162 
163  return ss.str();
164 }
165 
166 /**
167  * Saves trip counts of single basic block inner loops.
168  */
169 bool
170 InnerLoopFinder::runOnLoop(llvm::Loop* l, llvm::LPPassManager&) {
171 
172  const std::vector<llvm::Loop*>& subLoops = l->getSubLoops();
173 
174  unsigned subLoopCount = subLoops.size();
175  unsigned tripCount = getSmallConstantTripCount(l);
176  unsigned bbCount = l->getBlocks().size();
177 
178 
179  /// early exits?
180  llvm::SmallVector<llvm::BasicBlock*, 10> exitingBlocks;
181 
182 #if 0
183  /*
184  This caused an LLVM crash in test cases
185  llvm-frontend/tests/{FloatEmulationTest,NewLib,softloat_lowering,HelloWorld}:
186 
187  /home/visit0r/src/llvm-2.3/include/llvm/Support/Casting.h:199:
188  typename llvm::cast_retty<To, From>::ret_type llvm::cast(const Y&)
189  [with X = llvm::BasicBlock, Y = llvm::Value*]:
190  Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
191  */
192  l->getExitingBlocks(exitingBlocks);
193  unsigned exitingBlockCount = exitingBlocks.size();
194 #endif
195 
196  unsigned callCount = 0;
197  if (subLoopCount == 0) {
198  for (llvm::LoopBase<llvm::BasicBlock, llvm::Loop>::
199  block_iterator bb =
200  l->block_begin(); bb != l->block_end(); ++bb) {
201  llvm::BasicBlock& basicBlock = **bb;
202  for (llvm::BasicBlock::iterator i = basicBlock.begin();
203  i != basicBlock.end(); ++i) {
204  llvm::Instruction& instruction = *i;
205  if (instruction.getOpcode() == llvm::Instruction::Call)
206  ++callCount;
207  }
208  }
209  }
210 
211  const bool innerLoop =
212  bbCount == 1 && subLoopCount == 0 && callCount == 0;
213 
214  if (innerLoop) {
215  if (dump && tripCount > 0) {
216  out(l) << "found an inner loop with trip count "
217  << tripCount << std::endl;
218  }
219  assert(l->getBlocks().size() > 0);
220 
221  InnerLoopInfo loopInfo(tripCount);
222  loopInfos_[l->getBlocks()[0]] = loopInfo;
223  }
224 
225  if (dump) {
226  out(l) << "loop: " << loopDescription(l) << std::endl
227  << "depth: " << l->getLoopDepth() << std::endl;
228  out(l) << "sub loops: " << subLoopCount << std::endl;
229  out(l) << "trip count: ";
230  if (tripCount != 0) {
231  out(l) << "constant: " << tripCount;
232  } else {
233  out(l) << "unknown ";
234  }
235  out(l) << std::endl;
236  out(l) << "basic blocks: " << bbCount << std::endl;
237 // out(l) << "exiting blocks: " << exitingBlocks.size() << std::endl;
238  if (subLoopCount == 0)
239  out(l) << "calls: " << callCount << std::endl;
240  out(l) << std::endl;
241  }
242  return false; // loop not modified
243 }
244 
245 /**
246  * Returns the trip count of the loop as a normal unsigned value, if
247  * possible.
248  *
249  * Forwardported from LLVM 2.4. Returns 0 if the trip count is unknown
250  * or not constant. Will also return 0 if the trip count is very large
251  * (>= 2^32).
252  */
253 unsigned
255  ScalarEvolution *SE =
256  &getAnalysis<llvm::ScalarEvolutionWrapperPass>().getSE();
257  llvm::BasicBlock* loopLatch = loop->getLoopLatch();
258  // In case of the forever loop in the exit() the latch does
259  // not jump out of the loop and SE cannot analyze the trip count,
260  // which is infinite in that case.
261  if (loopLatch == NULL || !loop->isLoopExiting(loopLatch))
262  return 0;
263  return SE->getSmallConstantTripCount(loop, loopLatch);
264 }
llvm
Definition: InlineAsmParser.hh:49
DumpLoopInfo
static llvm::cl::opt< bool > DumpLoopInfo("dump-loop-info", llvm::cl::init(false), llvm::cl::Hidden, llvm::cl::desc("Dump information about loops to files named [modulename].loopinfo.txt."))
assert
#define assert(condition)
Definition: Application.hh:86
InnerLoopFinder.hh
InnerLoopFinder
Definition: InnerLoopFinder.hh:28
InnerLoopFinder::getSmallConstantTripCount
unsigned getSmallConstantTripCount(llvm::Loop *loop)
Definition: InnerLoopFinder.cc:254
InnerLoopFinder::InnerLoopInfo
Definition: InnerLoopFinder.hh:32
InnerLoopFinder::runOnLoop
virtual bool runOnLoop(llvm::Loop *l, llvm::LPPassManager &LPM)
Definition: InnerLoopFinder.cc:170
innerloops
find innerloops
Definition: InnerLoopFinder.cc:79
InnerLoopFinder::getAnalysisUsage
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const
Definition: InnerLoopFinder.cc:99
X
static llvm::RegisterPass< InnerLoopFinder > X("find-innerloops-test", "Finds inner loops test.", false, true)
IGNORE_COMPILER_WARNING
#define IGNORE_COMPILER_WARNING(X)
Definition: CompilerWarnings.hh:51
InnerLoopFinder::loopDescription
virtual std::string loopDescription(llvm::Loop *l)
Definition: InnerLoopFinder.cc:152
false
find Finds info of the inner loops in the false
Definition: InnerLoopFinder.cc:81
InnerLoopFinder::~InnerLoopFinder
~InnerLoopFinder()
Definition: InnerLoopFinder.cc:110
program
find Finds info of the inner loops in the program
Definition: InnerLoopFinder.cc:80
InnerLoopFinder::out
std::ostream & out(llvm::Loop *l)
Definition: InnerLoopFinder.cc:127
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(InnerLoopFinder, "find-innerloops", "Finds info of the inner loops in the program.", false, true) INITIALIZE_PASS_END(InnerLoopFinder
CompilerWarnings.hh