File: code_loop.hh

package info (click to toggle)
faust 2.81.10%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 431,496 kB
  • sloc: cpp: 283,941; ansic: 116,215; javascript: 18,529; sh: 14,356; vhdl: 14,052; java: 5,900; python: 5,091; objc: 3,852; makefile: 2,725; cs: 1,672; lisp: 1,146; ruby: 954; yacc: 586; xml: 471; lex: 247; awk: 111; tcl: 26
file content (193 lines) | stat: -rw-r--r-- 6,617 bytes parent folder | download | duplicates (2)
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