1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
/************************************************************************
************************************************************************
FAUST compiler
Copyright (C) 2003-2018 GRAME, Centre National de Creation Musicale
---------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
************************************************************************
************************************************************************/
#ifndef _CODE_LOOP_H
#define _CODE_LOOP_H
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include "fir_function_builder.hh"
#include "garbageable.hh"
#include "list.hh"
#include "tree.hh"
// Loop internal code
/*
We have independent loops that will be "connected" with vectors
We would like to be able to connect loops and remove the intermediate vectors.
We start from a DAG of loops, we want to be able to:
- put this DAG on the form of a sequence of loops (topological sorting)
- merge all the loops into one, so basically extract the loops code and merge it
Scalarization of a loop:
- identify all input and output vectors
- transform the vectors into scalars
- transform the accesses (Load/Store) into scalar accesses
*/
class CodeLoop;
typedef std::set<CodeLoop*> lclset;
typedef std::vector<lclset> lclgraph;
class CodeLoop : public virtual Garbageable {
friend class CodeContainer;
private:
bool fIsRecursive; ///< recursive loops can't be SIMDed
Tree fRecSymbolSet; ///< recursive loops define a set of recursive symbol
CodeLoop* const fEnclosingLoop; ///< Loop from which this one originated
int fSize; ///< number of iterations of the loop
int fOrder; ///< used during topological sort
int fIndex;
BlockInst* fPreInst;
BlockInst* fComputeInst;
BlockInst* fPostInst;
std::string fLoopIndex;
int fUseCount; ///< how many loops depend on this one
std::list<CodeLoop*> fExtraLoops; ///< extra loops that where in sequences
std::set<Tree> fRecDependencies; ///< Loops having recursive dependencies must be merged
std::set<CodeLoop*> fBackwardLoopDependencies; ///< Loops that must be computed before this one
std::set<CodeLoop*> fForwardLoopDependencies; ///< Loops that will be computed after this one
void pushBlock(BlockInst* block, BlockInst* loop)
{
for (const auto& it : block->fCode) {
loop->pushBackInst(it);
}
}
bool isEmpty(); ///< true when the loop doesn't contain any line of code
void absorb(CodeLoop* l); ///< absorb a loop inside this one
void concat(CodeLoop* l);
// Graph sorting
static void setOrder(CodeLoop* l, int order, lclgraph& V);
static void setLevel(int order, const lclset& T1, lclset& T2, lclgraph& V);
static void resetOrder(CodeLoop* l, std::set<CodeLoop*>& visited);
public:
///< create a recursive loop
CodeLoop(Tree recsymbol, CodeLoop* encl, const std::string& index_name, int size = 0)
: fIsRecursive(true),
fRecSymbolSet(singleton(recsymbol)),
fEnclosingLoop(encl),
fSize(size),
fOrder(-1),
fIndex(-1),
fPreInst(new BlockInst()),
fComputeInst(new BlockInst()),
fPostInst(new BlockInst()),
fLoopIndex(index_name),
fUseCount(0)
{
}
///< create a non recursive loop
CodeLoop(CodeLoop* encl, const std::string& index_name, int size = 0)
: fIsRecursive(false),
fRecSymbolSet(gGlobal->nil),
fEnclosingLoop(encl),
fSize(size),
fOrder(-1),
fIndex(-1),
fPreInst(new BlockInst()),
fComputeInst(new BlockInst()),
fPostInst(new BlockInst()),
fLoopIndex(index_name),
fUseCount(0)
{
}
StatementInst* pushPreComputeDSPMethod(StatementInst* inst)
{
fPreInst->pushBackInst(inst);
return inst;
}
StatementInst* pushComputeDSPMethod(StatementInst* inst)
{
fComputeInst->pushBackInst(inst);
return inst;
}
StatementInst* pushPostComputeDSPMethod(StatementInst* inst)
{
fPostInst->pushBackInst(inst);
return inst;
}
bool isRecursive() { return fIsRecursive; }
int getIndex() { return fIndex; }
std::set<CodeLoop*>& getForwardLoopDependencies() { return fForwardLoopDependencies; }
std::set<CodeLoop*>& getBackwardLoopDependencies() { return fBackwardLoopDependencies; }
ValueInst* getLoopIndex() { return IB::genLoadLoopVar(fLoopIndex); }
ForLoopInst* generateScalarLoop(const std::string& counter, bool loop_var_in_bytes = false);
// For SYFALA : loop with a fixed size (known at compile time)
ForLoopInst* generateFixedScalarLoop();
// For Rust backend
SimpleForLoopInst* generateSimpleScalarLoop(const std::string& counter);
IteratorForLoopInst* generateSimpleScalarLoop(const std::vector<std::string>& iterators);
BlockInst* generateOneSample();
void generateDAGScalarLoop(BlockInst* block, ValueInst* count, bool omp);
void transform(DispatchVisitor* visitor)
{
// Transform extra loops
for (const auto& s : fExtraLoops) {
s->transform(visitor);
}
fPreInst->accept(visitor);
fComputeInst->accept(visitor);
fPostInst->accept(visitor);
}
bool hasRecDependencyIn(Tree S); ///< returns true is this loop has recursive dependencies
void addBackwardDependency(CodeLoop* ls) { fBackwardLoopDependencies.insert(ls); }
static void sortGraph(CodeLoop* root, lclgraph& V);
static void computeUseCount(CodeLoop* l);
static void groupSeqLoops(CodeLoop* l, std::set<CodeLoop*>& visited);
};
#endif
|