source: icGREP/icgrep-devel/icgrep/pablo/pablo_toolchain.cpp @ 5267

Last change on this file since 5267 was 5267, checked in by nmedfort, 2 years ago

Code clean-up. Removed Pablo Call, SetIthBit? and Prototype.

File size: 12.8 KB
Line 
1/*
2 *  Copyright (c) 2015 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include "pablo_toolchain.h"
8#include <pablo/pablo_kernel.h>
9#include <pablo/optimizers/pablo_simplifier.hpp>
10#include <pablo/optimizers/codemotionpass.h>
11#include <pablo/passes/flattenassociativedfg.h>
12#include <pablo/passes/flattenif.hpp>
13#include <pablo/passes/factorizedfg.h>
14#ifdef ENABLE_MULTIPLEXING
15#include <pablo/optimizers/pablo_automultiplexing.hpp>
16#include <pablo/optimizers/pablo_bddminimization.h>
17#include <pablo/optimizers/booleanreassociationpass.h>
18#include <pablo/optimizers/distributivepass.h>
19#include <pablo/optimizers/schedulingprepass.h>
20#endif
21#include <pablo/analysis/pabloverifier.hpp>
22#include <pablo/printer_pablos.h>
23#include <llvm/Support/CommandLine.h>
24#include <llvm/Support/FileSystem.h>
25#include <llvm/Support/raw_ostream.h>
26#ifdef PRINT_TIMING_INFORMATION
27#include <hrtime.h>
28#endif
29
30
31using namespace llvm;
32
33namespace pablo {
34
35static cl::OptionCategory PabloOptions("Pablo Options", "These options control printing, generation and instrumentation of Pablo intermediate code.");
36
37const cl::OptionCategory * pablo_toolchain_flags() {
38    return &PabloOptions;
39}
40   
41   
42static cl::bits<PabloDebugFlags> 
43DebugOptions(cl::values(clEnumVal(PrintOptimizedREcode, "print final optimized Pablo code"),
44                        clEnumVal(PrintCompiledCCcode, "print Pablo output from character class compiler"),
45                        clEnumVal(PrintCompiledREcode, "print Pablo output from the regular expression compiler"),
46                        clEnumVal(DumpTrace, "Generate dynamic traces of executed Pablo assignments."),
47                        clEnumVal(PrintUnloweredCode, "print Pablo output prior to lowering."),
48                        clEnumValEnd), cl::cat(PabloOptions));
49   
50static cl::opt<std::string> PabloOutputFilename("print-pablo-output", cl::init(""), cl::desc("output Pablo filename"), cl::cat(PabloOptions));
51static cl::opt<bool> Flatten("flatten-if", cl::init(false), cl::desc("Flatten all the Ifs in the Pablo AST"), cl::cat(PabloOptions));
52
53static cl::bits<PabloCompilationFlags> 
54    PabloOptimizationsOptions(cl::values(clEnumVal(DisableSimplification, "Disable Pablo Simplification pass (not recommended)"),
55                                         clEnumVal(EnableCodeMotion, "Moves statements into the innermost legal If-scope and moves invariants out of While-loops."),
56#ifdef ENABLE_MULTIPLEXING
57                                         clEnumVal(EnableMultiplexing, "combine Advances whose inputs are mutual exclusive into the fewest number of advances possible (expensive)."),
58                                         clEnumVal(EnableLowering, "coalesce associative functions prior to optimization passes."),
59                                         clEnumVal(EnablePreDistribution, "apply distribution law optimization prior to multiplexing."),
60                                         clEnumVal(EnablePostDistribution, "apply distribution law optimization after multiplexing."),
61                                         clEnumVal(EnablePrePassScheduling, "apply pre-pass scheduling prior to LLVM IR generation."),
62#endif                                         
63                            clEnumValEnd), cl::cat(PabloOptions));
64
65bool DebugOptionIsSet(PabloDebugFlags flag) {return DebugOptions.isSet(flag);}
66   
67   
68   
69#ifdef PRINT_TIMING_INFORMATION
70#define READ_CYCLE_COUNTER(name) name = read_cycle_counter();
71#else
72#define READ_CYCLE_COUNTER(name)
73#endif
74
75#ifdef PRINT_TIMING_INFORMATION
76unsigned COUNT_STATEMENTS(const PabloKernel * const entry) {
77    std::stack<const Statement *> scope;
78    unsigned statements = 0;
79    // Scan through and collect all the advances, scanthrus and matchstars ...
80    for (const Statement * stmt = entry->getEntryBlock()->front(); ; ) {
81        while ( stmt ) {
82            ++statements;
83            if (LLVM_UNLIKELY(isa<If>(stmt) || isa<While>(stmt))) {
84                // Set the next statement to be the first statement of the inner scope and push the
85                // next statement of the current statement into the scope stack.
86                const PabloBlock * const nested = isa<If>(stmt) ? cast<If>(stmt)->getBody() : cast<While>(stmt)->getBody();
87                scope.push(stmt->getNextNode());
88                stmt = nested->front();
89                assert (stmt);
90                continue;
91            }
92            stmt = stmt->getNextNode();
93        }
94        if (scope.empty()) {
95            break;
96        }
97        stmt = scope.top();
98        scope.pop();
99    }
100    return statements;
101}
102
103unsigned COUNT_ADVANCES(const PabloKernel * const entry) {
104
105    std::stack<const Statement *> scope;
106    unsigned advances = 0;
107
108    // Scan through and collect all the advances, scanthrus and matchstars ...
109    for (const Statement * stmt = entry->getEntryBlock()->front(); ; ) {
110        while ( stmt ) {
111            if (isa<Advance>(stmt)) {
112                ++advances;
113            }
114            else if (LLVM_UNLIKELY(isa<If>(stmt) || isa<While>(stmt))) {
115                // Set the next statement to be the first statement of the inner scope and push the
116                // next statement of the current statement into the scope stack.
117                const PabloBlock * const nested = isa<If>(stmt) ? cast<If>(stmt)->getBody() : cast<While>(stmt)->getBody();
118                scope.push(stmt->getNextNode());
119                stmt = nested->front();
120                assert (stmt);
121                continue;
122            }
123            stmt = stmt->getNextNode();
124        }
125        if (scope.empty()) {
126            break;
127        }
128        stmt = scope.top();
129        scope.pop();
130    }
131    return advances;
132}
133
134using DistributionMap = boost::container::flat_map<unsigned, unsigned>;
135
136DistributionMap SUMMARIZE_VARIADIC_DISTRIBUTION(const PabloKernel * const entry) {
137    std::stack<const Statement *> scope;
138    DistributionMap distribution;
139    // Scan through and collect all the advances, scanthrus and matchstars ...
140    for (const Statement * stmt = entry->getEntryBlock()->front(); ; ) {
141        while ( stmt ) {
142            if (isa<Variadic>(stmt)) {
143                auto f = distribution.find(stmt->getNumOperands());
144                if (f == distribution.end()) {
145                    distribution.emplace(stmt->getNumOperands(), 1);
146                } else {
147                    f->second += 1;
148                }
149            }
150            else if (LLVM_UNLIKELY(isa<If>(stmt) || isa<While>(stmt))) {
151                // Set the next statement to be the first statement of the inner scope and push the
152                // next statement of the current statement into the scope stack.
153                const PabloBlock * const nested = isa<If>(stmt) ? cast<If>(stmt)->getBody() : cast<While>(stmt)->getBody();
154                scope.push(stmt->getNextNode());
155                stmt = nested->front();
156                assert (stmt);
157                continue;
158            }
159            stmt = stmt->getNextNode();
160        }
161        if (scope.empty()) {
162            break;
163        }
164        stmt = scope.top();
165        scope.pop();
166    }
167    return distribution;
168}
169#endif
170
171void pablo_function_passes(PabloKernel * kernel) {
172   
173    if (DebugOptions.isSet(PrintCompiledREcode)) {
174        //Print to the terminal the AST that was generated by the pararallel bit-stream compiler.
175        errs() << "Initial Pablo AST:\n";
176        PabloPrinter::print(kernel, errs());
177    }
178   
179    #ifndef NDEBUG
180    PabloVerifier::verify(kernel, "creation");
181    #endif
182
183    // Scan through the pablo code and perform DCE and CSE
184
185#ifdef PRINT_TIMING_INFORMATION
186    timestamp_t simplification_start = 0, simplification_end = 0;
187    timestamp_t flattenif_start = 0, flattenif_end = 0;
188    timestamp_t coalescing_start = 0, coalescing_end = 0;
189    timestamp_t sinking_start = 0, sinking_end = 0;
190    timestamp_t pre_distribution_start = 0, pre_distribution_end = 0;
191    timestamp_t multiplexing_start = 0, multiplexing_end = 0;
192    timestamp_t post_distribution_start = 0, post_distribution_end = 0;
193    timestamp_t lowering_start = 0, lowering_end = 0;
194    timestamp_t scheduling_start = 0, scheduling_end = 0;
195    DistributionMap distribution;
196    const timestamp_t optimization_start = read_cycle_counter();
197#endif
198    if (!PabloOptimizationsOptions.isSet(DisableSimplification)) {
199        READ_CYCLE_COUNTER(simplification_start);
200        Simplifier::optimize(kernel);
201        READ_CYCLE_COUNTER(simplification_end);
202    }
203    if (Flatten){
204        READ_CYCLE_COUNTER(flattenif_start);
205        FlattenIf::transform(kernel);
206        READ_CYCLE_COUNTER(flattenif_end);
207    }
208#ifdef ENABLE_MULTIPLEXING
209//    if (PabloOptimizationsOptions.isSet(EnableLowering) || PabloOptimizationsOptions.isSet(EnablePreDistribution) || PabloOptimizationsOptions.isSet(EnablePostDistribution)) {
210//        READ_CYCLE_COUNTER(coalescing_start);
211//        CanonicalizeDFG::transform(kernel);
212//        READ_CYCLE_COUNTER(coalescing_end);
213//    }
214    if (PabloOptimizationsOptions.isSet(EnablePreDistribution)) {
215        READ_CYCLE_COUNTER(pre_distribution_start);
216        BooleanReassociationPass::optimize(kernel);
217        READ_CYCLE_COUNTER(pre_distribution_end);
218    }
219    if (PabloOptimizationsOptions.isSet(EnableMultiplexing)) {
220        READ_CYCLE_COUNTER(multiplexing_start);
221        MultiplexingPass::optimize(kernel);
222        READ_CYCLE_COUNTER(multiplexing_end);
223//        if (PabloOptimizationsOptions.isSet(EnableLowering) || PabloOptimizationsOptions.isSet(EnablePreDistribution) || PabloOptimizationsOptions.isSet(EnablePostDistribution)) {
224//            CanonicalizeDFG::transform(kernel);
225//        }
226    }
227    if (PabloOptimizationsOptions.isSet(EnablePostDistribution)) {
228        READ_CYCLE_COUNTER(post_distribution_start);
229        BooleanReassociationPass::optimize(kernel);
230        READ_CYCLE_COUNTER(post_distribution_end);
231    }
232#endif
233    if (PabloOptimizationsOptions.isSet(EnableCodeMotion)) {
234        READ_CYCLE_COUNTER(sinking_start);
235        CodeMotionPass::optimize(kernel);
236        READ_CYCLE_COUNTER(sinking_end);
237    }
238#ifdef ENABLE_MULTIPLEXING
239    if (DebugOptions.isSet(PrintUnloweredCode)) {
240        //Print to the terminal the AST that was generated by the pararallel bit-stream compiler.
241        errs() << "Unlowered Pablo AST:\n";
242        PabloPrinter::print(kernel, errs());
243    }
244    #ifdef PRINT_TIMING_INFORMATION
245    distribution = SUMMARIZE_VARIADIC_DISTRIBUTION(function);
246    #endif
247//    if (PabloOptimizationsOptions.isSet(EnableLowering) || PabloOptimizationsOptions.isSet(EnablePreDistribution) || PabloOptimizationsOptions.isSet(EnablePostDistribution)) {
248//        READ_CYCLE_COUNTER(lowering_start);
249//        FactorizeDFG::transform(kernel);
250//        READ_CYCLE_COUNTER(lowering_end);
251//    }
252//    if (PabloOptimizationsOptions.isSet(EnablePrePassScheduling)) {
253//        READ_CYCLE_COUNTER(scheduling_start);
254//        SchedulingPrePass::optimize(kernel);
255//        READ_CYCLE_COUNTER(scheduling_end);
256//    }
257#endif
258#ifdef PRINT_TIMING_INFORMATION
259    const timestamp_t optimization_end = read_cycle_counter();
260#endif
261    if (DebugOptions.isSet(PrintOptimizedREcode)) {
262        if (PabloOutputFilename.empty()) {
263            //Print to the terminal the AST that was generated by the pararallel bit-stream compiler.
264            errs() << "Final Pablo AST:\n";
265            PabloPrinter::print(kernel, errs());
266        } else {
267            std::error_code error;
268            llvm::raw_fd_ostream out(PabloOutputFilename, error, sys::fs::OpenFlags::F_None);
269            PabloPrinter::print(kernel, out);
270        }
271    }
272#ifdef PRINT_TIMING_INFORMATION
273    errs() << "PABLO OPTIMIZATION TIME: " << (optimization_end - optimization_start) << "\n";
274    errs() << "  SIMPLIFICATION TIME: " << (simplification_end - simplification_start) << "\n";
275    errs() << "  COALESCING TIME: " << (coalescing_end - coalescing_start) << "\n";
276    errs() << "  SINKING TIME: " << (sinking_end - sinking_start) << "\n";
277    errs() << "  PRE-DISTRIBUTION TIME: " << (pre_distribution_end - pre_distribution_start) << "\n";
278    errs() << "  MULTIPLEXING TIME: " << (multiplexing_end - multiplexing_start) << "\n";
279    errs() << "  LOWERING TIME: " << (lowering_end - lowering_start) << "\n";
280    errs() << "  FLATTENIF TIME: " << (flattenif_end - flattenif_start) << "\n";
281    errs() << "  POST-DISTRIBUTION TIME: " << (post_distribution_end - post_distribution_start) << "\n";
282    errs() << "  SCHEDULING TIME: " << (scheduling_end - scheduling_start) << "\n";
283    errs() << "PABLO STATEMENTS: " << COUNT_STATEMENTS(function) << "\n";
284    errs() << "PABLO ADVANCES: " << COUNT_ADVANCES(function) << "\n";
285    errs() << "PRE-LOWERING VARIADIC DISTRIBUTION: ";
286    bool join = false;
287    for (auto dist : distribution) {
288        if (join) {
289            errs() << ';';
290        }
291        errs() << dist.first << '|' << dist.second;
292        join = true;
293    }
294    errs() << "\n";
295#endif
296}
297
298}
Note: See TracBrowser for help on using the repository browser.