source: icGREP/icgrep-devel/icgrep/pablo/codegenstate.cpp @ 4612

Last change on this file since 4612 was 4612, checked in by nmedfort, 4 years ago

Multiplexing bug fix and some CC changes.

File size: 14.9 KB
Line 
1/*
2 *  Copyright (c) 2014 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/codegenstate.h>
8
9namespace pablo {
10
11inline PabloAST * PabloBlock::renameNonNamedNode(PabloAST * expr, const std::string && prefix) {
12    if (Statement * stmt = dyn_cast<Statement>(expr)) {
13        if (stmt->getName()->isGenerated()) {
14            stmt->setName(makeName(prefix, false));
15        }
16    }
17    return expr;
18}
19
20/// UNARY CREATE FUNCTIONS
21
22Assign * PabloBlock::createAssign(const std::string && prefix, PabloAST * expr, const int outputIndex)  {
23    return insertAtInsertionPoint(new Assign(expr, outputIndex, makeName(prefix, false), this));
24}
25
26PabloAST * PabloBlock::createAdvance(PabloAST * expr, PabloAST * shiftAmount) {
27    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
28        return expr;
29    }
30    return insertAtInsertionPoint(new Advance(expr, shiftAmount, makeName("advance"), this));
31}
32
33PabloAST * PabloBlock::createAdvance(PabloAST * expr, PabloAST * shiftAmount, const std::string prefix) {
34    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
35        return expr;
36    }
37    return insertAtInsertionPoint(new Advance(expr, shiftAmount, makeName(prefix, false), this));
38}
39
40PabloAST * PabloBlock::createAdvance(PabloAST * expr, const Integer::integer_t shiftAmount) {
41    if (isa<Zeroes>(expr) || shiftAmount == 0) {
42        return expr;
43    }
44    return insertAtInsertionPoint(new Advance(expr, getInteger(shiftAmount), makeName("advance"), this));
45}
46
47PabloAST * PabloBlock::createAdvance(PabloAST * expr, const Integer::integer_t shiftAmount, const std::string prefix) {
48    if (isa<Zeroes>(expr) || shiftAmount == 0) {
49        return renameNonNamedNode(expr, std::move(prefix));
50    }   
51    return insertAtInsertionPoint(new Advance(expr, getInteger(shiftAmount), makeName(prefix, false), this));
52}
53
54Call * PabloBlock::createCall(PabloAST * name) {
55    assert (name);
56    return insertAtInsertionPoint(new Call(name, this));
57}
58
59PabloAST * PabloBlock::createNot(PabloAST * expr) {
60    assert (expr);
61    if (isa<Ones>(expr)) {
62        return createZeroes();
63    }
64    else if (isa<Zeroes>(expr)){
65        return createOnes();
66    }
67    else if (Not * not1 = dyn_cast<Not>(expr)) {
68        return not1->getExpr();
69    }
70    return insertAtInsertionPoint(new Not(expr, makeName("not_"), this));
71}
72
73PabloAST * PabloBlock::createNot(PabloAST * expr, const std::string prefix) {
74    assert (expr);
75    if (isa<Ones>(expr)) {
76        return createZeroes();
77    }
78    else if (isa<Zeroes>(expr)){
79        return createOnes();
80    }
81    else if (Not * not1 = dyn_cast<Not>(expr)) {       
82        return renameNonNamedNode(not1->getExpr(), std::move(prefix));
83    }
84    return insertAtInsertionPoint(new Not(expr, makeName(prefix, false), this));
85}
86
87Var * PabloBlock::createVar(PabloAST * name) {
88    assert (name);
89    return new Var(name, this);
90}
91
92/// BINARY CREATE FUNCTIONS
93
94Next * PabloBlock::createNext(Assign * assign, PabloAST * expr) {
95    assert (assign && expr);
96    return insertAtInsertionPoint(new Next(assign, expr, this));
97}
98
99PabloAST * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass) {
100    assert (marker && charclass);
101    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
102        return marker;
103    }
104    return insertAtInsertionPoint(new MatchStar(marker, charclass, makeName("matchstar"), this));
105}
106
107PabloAST * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass, const std::string prefix) {
108    assert (marker && charclass);
109    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
110        return renameNonNamedNode(marker, std::move(prefix));
111    }
112    return insertAtInsertionPoint(new MatchStar(marker, charclass, makeName(prefix, false), this));
113}
114
115PabloAST * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru) {
116    assert (from && thru);
117    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {
118        return from;
119    }
120    return insertAtInsertionPoint(new ScanThru(from, thru, makeName("scanthru"), this));
121}
122
123PabloAST * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru, const std::string prefix) {
124    assert (from && thru);
125    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {       
126        return renameNonNamedNode(from, std::move(prefix));
127    }
128    return insertAtInsertionPoint(new ScanThru(from, thru, makeName(prefix, false), this));
129}
130
131PabloAST * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2) {
132    assert (expr1 && expr2);
133    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
134        return expr2;
135    }
136    else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
137        return expr1;
138    }
139    else if (Not * not1 = dyn_cast<Not>(expr1)) {
140        if (Not * not2 = dyn_cast<Not>(expr2)) {
141            return createNot(createOr(not1->getExpr(), not2->getExpr()));
142        }
143        else if (equals(not1->getExpr(), expr2)) {
144            return createZeroes();
145        }
146    }
147    else if (Not * not2 = dyn_cast<Not>(expr2)) {
148        if (equals(expr1, not2->getExpr())) {
149            return createZeroes();
150        }
151    }
152    if (isa<Not>(expr1)) {
153        std::swap(expr1, expr2);
154    }
155    return insertAtInsertionPoint(new And(expr1, expr2, makeName("and_"), this));
156}
157
158
159PabloAST * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
160    assert (expr1 && expr2);
161    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
162        return renameNonNamedNode(expr2, std::move(prefix));
163    }
164    else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
165        return renameNonNamedNode(expr1, std::move(prefix));
166    }
167    else if (Not * not1 = dyn_cast<Not>(expr1)) {
168        if (Not * not2 = dyn_cast<Not>(expr2)) {
169            return createNot(createOr(not1->getExpr(), not2->getExpr()), prefix);
170        }
171        else if (equals(not1->getExpr(), expr2)) {
172            return createZeroes();
173        }
174    }
175    else if (Not * not2 = dyn_cast<Not>(expr2)) {
176        if (equals(expr1, not2->getExpr())) {
177            return createZeroes();
178        }
179    }
180    if (isa<Not>(expr1)) {
181        std::swap(expr1, expr2);
182    }
183    return insertAtInsertionPoint(new And(expr1, expr2, makeName(prefix, false), this));
184}
185
186PabloAST * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2) {
187    assert (expr1 && expr2);
188    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
189        return expr2;
190    }
191    if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
192        return expr1;
193    }
194    else if (Not * not1 = dyn_cast<Not>(expr1)) {
195        // ¬a√b = ¬¬(¬a√b) = ¬(a ∧ ¬b)
196        return createNot(createAnd(not1->getExpr(), createNot(expr2)));
197    }
198    else if (Not * not2 = dyn_cast<Not>(expr2)) {
199        // a√¬b = ¬¬(¬b√a) = ¬(b ∧ ¬a)
200        return createNot(createAnd(not2->getExpr(), createNot(expr1)));
201    }
202    else if (equals(expr1, expr2)) {
203        return expr1;
204    }
205    else if (And * and_expr1 = dyn_cast<And>(expr1)) {
206        if (And * and_expr2 = dyn_cast<And>(expr2)) {
207            PabloAST * const expr1a = and_expr1->getExpr1();
208            PabloAST * const expr1b = and_expr1->getExpr2();
209            PabloAST * const expr2a = and_expr2->getExpr1();
210            PabloAST * const expr2b = and_expr2->getExpr2();
211            //These optimizations factor out common components that can occur when sets are formed by union
212            //(e.g., union of [a-z] and [A-Z].
213            if (equals(expr1a, expr2a)) {
214                return createAnd(expr1a, createOr(expr1b, expr2b));
215            }
216            else if (equals(expr1b, expr2b)) {
217                return createAnd(expr1b, createOr(expr1a, expr2a));
218            }
219            else if (equals(expr1a, expr2b)) {
220                return createAnd(expr1a, createOr(expr1b, expr2a));
221            }
222            else if (equals(expr1b, expr2a)) {
223                return createAnd(expr1b, createOr(expr1a, expr2b));
224            }
225        }
226    }
227    return insertAtInsertionPoint(new Or(expr1, expr2, makeName("or_"), this));
228}
229
230PabloAST * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
231    assert (expr1 && expr2);
232    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
233        return renameNonNamedNode(expr2, std::move(prefix));
234    }
235    if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
236        return renameNonNamedNode(expr1, std::move(prefix));
237    }
238    else if (Not * not1 = dyn_cast<Not>(expr1)) {
239        // ¬a√b = ¬¬(¬a√b) = ¬(a ∧ ¬b)
240        return createNot(createAnd(not1->getExpr(), createNot(expr2)), prefix);
241    }
242    else if (Not * not2 = dyn_cast<Not>(expr2)) {
243        // a√¬b = ¬¬(¬b√a) = ¬(b ∧ ¬a)
244        return createNot(createAnd(not2->getExpr(), createNot(expr1)), prefix);
245    }
246    else if (And * and_expr1 = dyn_cast<And>(expr1)) {
247        if (And * and_expr2 = dyn_cast<And>(expr2)) {
248            PabloAST * const expr1a = and_expr1->getExpr1();
249            PabloAST * const expr1b = and_expr1->getExpr2();
250            PabloAST * const expr2a = and_expr2->getExpr1();
251            PabloAST * const expr2b = and_expr2->getExpr2();
252            //These optimizations factor out common components that can occur when sets are formed by union
253            //(e.g., union of [a-z] and [A-Z].
254            if (equals(expr1a, expr2a)) {
255                return createAnd(expr1a, createOr(expr1b, expr2b), prefix);
256            }
257            else if (equals(expr1b, expr2b)) {
258                return createAnd(expr1b, createOr(expr1a, expr2a), prefix);
259            }
260            else if (equals(expr1a, expr2b)) {
261                return createAnd(expr1a, createOr(expr1b, expr2a), prefix);
262            }
263            else if (equals(expr1b, expr2a)) {
264                return createAnd(expr1b, createOr(expr1a, expr2b), prefix);
265            }
266        }
267    }
268    return insertAtInsertionPoint(new Or(expr1, expr2, makeName(prefix, false), this));
269}
270
271PabloAST * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2) {
272    assert (expr1 && expr2);
273    if (isa<Ones>(expr1)) {
274        return createNot(expr2);
275    }
276    else if (isa<Zeroes>(expr1)){
277        return expr2;
278    }
279    else if (isa<Ones>(expr2)) {
280        return createNot(expr1);
281    }
282    else if (isa<Zeroes>(expr2)){
283        return expr1;
284    }
285    else if (Not * not1 = dyn_cast<Not>(expr1)) {
286        if (Not * not2 = dyn_cast<Not>(expr2)) {
287            return createXor(not1->getExpr(), not2->getExpr());
288        }
289    }
290    return insertAtInsertionPoint(new Xor(expr1, expr2, makeName("xor_"), this));
291}
292
293PabloAST * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
294    assert (expr1 && expr2);
295    if (isa<Ones>(expr1)) {
296        return createNot(expr2, prefix);
297    }
298    else if (isa<Zeroes>(expr1)){
299        return expr2;
300    }
301    else if (isa<Ones>(expr2)) {
302        return createNot(expr1, prefix);
303    }
304    else if (isa<Zeroes>(expr2)){
305        return expr1;
306    }
307    else if (Not * not1 = dyn_cast<Not>(expr1)) {
308        if (Not * not2 = dyn_cast<Not>(expr2)) {
309            return createXor(not1->getExpr(), not2->getExpr(), prefix);
310        }
311    }
312    return insertAtInsertionPoint(new Xor(expr1, expr2, makeName(prefix, false), this));
313}
314
315/// TERNARY CREATE FUNCTION
316
317PabloAST * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr) {
318    assert (condition && trueExpr && falseExpr);
319
320    if (isa<Ones>(condition)) {
321        return trueExpr;
322    }
323    else if (isa<Zeroes>(condition)){
324        return falseExpr;
325    }
326    else if (isa<Ones>(trueExpr)) {
327        return createOr(condition, falseExpr);
328    }
329    else if (isa<Zeroes>(trueExpr)){
330        return createAnd(createNot(condition), falseExpr);
331    }
332    else if (isa<Ones>(falseExpr)) {
333        return createOr(createNot(condition), trueExpr);
334    }
335    else if (isa<Zeroes>(falseExpr)){
336        return createAnd(condition, trueExpr);
337    }
338    else if (equals(trueExpr, falseExpr)) {
339        return trueExpr;
340    }
341    else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getExpr(), falseExpr)) {
342        return createXor(condition, falseExpr);
343    }
344    else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getExpr())){
345        return createXor(condition, falseExpr);
346    }
347    return insertAtInsertionPoint(new Sel(condition, trueExpr, falseExpr, makeName("sel"), this));
348}
349
350PabloAST * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr, const std::string prefix) {
351    assert (condition && trueExpr && falseExpr);
352
353    if (isa<Zeroes>(condition)){
354        return renameNonNamedNode(falseExpr, std::move(prefix));
355    }
356    else if (isa<Ones>(condition) || equals(trueExpr, falseExpr)) {
357        return renameNonNamedNode(trueExpr, std::move(prefix));
358    }
359    else if (isa<Ones>(trueExpr)) {
360        return createOr(condition, falseExpr, prefix);
361    }
362    else if (isa<Zeroes>(trueExpr)){
363        return createAnd(createNot(condition), falseExpr, prefix);
364    }
365    else if (isa<Ones>(falseExpr)) {
366        return createOr(createNot(condition), trueExpr, prefix);
367    }
368    else if (isa<Zeroes>(falseExpr)){
369        return createAnd(condition, trueExpr, prefix);
370    }
371    else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getExpr(), falseExpr)) {
372        return createXor(condition, falseExpr, prefix);
373    }
374    else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getExpr())){
375        return createXor(condition, falseExpr, prefix);
376    }
377    return insertAtInsertionPoint(new Sel(condition, trueExpr, falseExpr, makeName(prefix, false), this));
378}
379
380If * PabloBlock::createIf(PabloAST * condition, const std::initializer_list<Assign *> definedVars, PabloBlock & body) {
381    assert (condition);
382    return insertAtInsertionPoint(new If(condition, definedVars, body, this));
383}
384
385If * PabloBlock::createIf(PabloAST * condition, const std::vector<Assign *> & definedVars, PabloBlock & body) {
386    assert (condition);
387    return insertAtInsertionPoint(new If(condition, definedVars, body, this));
388}
389
390If * PabloBlock::createIf(PabloAST * condition, std::vector<Assign *> && definedVars, PabloBlock & body) {
391    assert (condition);
392    return insertAtInsertionPoint(new If(condition, definedVars, body, this));
393}
394
395While * PabloBlock::createWhile(PabloAST * condition, PabloBlock & body) {
396    assert (condition);
397    return insertAtInsertionPoint(new While(condition, body, this));
398}
399
400/// CONSTRUCTOR
401
402PabloBlock::PabloBlock(SymbolGenerator & symbolGenerator)
403: PabloAST(PabloAST::ClassTypeId::Block)
404, mZeroes(new Zeroes())
405, mOnes(new Ones())
406, mSymbolGenerator(symbolGenerator)
407, mParent(nullptr)
408{
409
410}
411
412PabloBlock::PabloBlock(PabloBlock * predecessor)
413: PabloAST(PabloAST::ClassTypeId::Block)
414, mZeroes(predecessor->mZeroes) // inherit the original "Zeroes" variable for simplicity
415, mOnes(predecessor->mOnes) // inherit the original "Ones" variable for simplicity
416, mSymbolGenerator(predecessor->mSymbolGenerator)
417, mParent(predecessor) {
418
419}
420
421PabloBlock::~PabloBlock() {
422
423}
424
425}
Note: See TracBrowser for help on using the repository browser.