OpenASIP 2.2
Loading...
Searching...
No Matches
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"
40IGNORE_COMPILER_WARNING("-Wunused-parameter")
41IGNORE_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
60using namespace llvm;
61
62static 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
67static 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)
75INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
76INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
77INITIALIZE_PASS_DEPENDENCY(LCSSAWrapperPass)
78INITIALIZE_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
91char InnerLoopFinder::ID = 0;
92
94 LoopPass(ID) {
95 dump = DumpLoopInfo;
96}
97
98void
99InnerLoopFinder::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 */
126std::ostream&
127InnerLoopFinder::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 */
151std::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 */
169bool
170InnerLoopFinder::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 */
253unsigned
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}
#define assert(condition)
#define IGNORE_COMPILER_WARNING(X)
find Finds info of the inner loops in the program
INITIALIZE_PASS_BEGIN(InnerLoopFinder, "find-innerloops", "Finds info of the inner loops in the program.", false, true) INITIALIZE_PASS_END(InnerLoopFinder
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."))
static llvm::RegisterPass< InnerLoopFinder > X("find-innerloops-test", "Finds inner loops test.", false, true)
find Finds info of the inner loops in the false
find innerloops
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const
unsigned getSmallConstantTripCount(llvm::Loop *loop)
virtual std::string loopDescription(llvm::Loop *l)
DumpFileIndex dumpFiles
InnerLoopInfoIndex loopInfos_
std::ostream & out(llvm::Loop *l)
virtual bool runOnLoop(llvm::Loop *l, llvm::LPPassManager &LPM)