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

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

Next nodes for While statements must be declared similar to how Defined Vars are for Ifs. (Temporarily breaks multiplexing correctness.)

File size: 15.4 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    assert (assign->getName());
97    std::string name = assign->getName()->to_string() + "'";
98    return new Next(assign, createAssign(std::move(name), expr), this);
99}
100
101PabloAST * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass) {
102    assert (marker && charclass);
103    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
104        return marker;
105    }
106    return insertAtInsertionPoint(new MatchStar(marker, charclass, makeName("matchstar"), this));
107}
108
109PabloAST * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass, const std::string prefix) {
110    assert (marker && charclass);
111    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
112        return renameNonNamedNode(marker, std::move(prefix));
113    }
114    return insertAtInsertionPoint(new MatchStar(marker, charclass, makeName(prefix, false), this));
115}
116
117PabloAST * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru) {
118    assert (from && thru);
119    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {
120        return from;
121    }
122    return insertAtInsertionPoint(new ScanThru(from, thru, makeName("scanthru"), this));
123}
124
125PabloAST * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru, const std::string prefix) {
126    assert (from && thru);
127    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {       
128        return renameNonNamedNode(from, std::move(prefix));
129    }
130    return insertAtInsertionPoint(new ScanThru(from, thru, makeName(prefix, false), this));
131}
132
133PabloAST * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2) {
134    assert (expr1 && expr2);
135    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
136        return expr2;
137    }
138    else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
139        return expr1;
140    }
141    else if (Not * not1 = dyn_cast<Not>(expr1)) {
142        if (Not * not2 = dyn_cast<Not>(expr2)) {
143            return createNot(createOr(not1->getExpr(), not2->getExpr()));
144        }
145        else if (equals(not1->getExpr(), expr2)) {
146            return createZeroes();
147        }
148    }
149    else if (Not * not2 = dyn_cast<Not>(expr2)) {
150        if (equals(expr1, not2->getExpr())) {
151            return createZeroes();
152        }
153    }
154    if (isa<Not>(expr1)) {
155        std::swap(expr1, expr2);
156    }
157    return insertAtInsertionPoint(new And(expr1, expr2, makeName("and_"), this));
158}
159
160
161PabloAST * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
162    assert (expr1 && expr2);
163    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
164        return renameNonNamedNode(expr2, std::move(prefix));
165    }
166    else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
167        return renameNonNamedNode(expr1, std::move(prefix));
168    }
169    else if (Not * not1 = dyn_cast<Not>(expr1)) {
170        if (Not * not2 = dyn_cast<Not>(expr2)) {
171            return createNot(createOr(not1->getExpr(), not2->getExpr()), prefix);
172        }
173        else if (equals(not1->getExpr(), expr2)) {
174            return createZeroes();
175        }
176    }
177    else if (Not * not2 = dyn_cast<Not>(expr2)) {
178        if (equals(expr1, not2->getExpr())) {
179            return createZeroes();
180        }
181    }
182    if (isa<Not>(expr1)) {
183        std::swap(expr1, expr2);
184    }
185    return insertAtInsertionPoint(new And(expr1, expr2, makeName(prefix, false), this));
186}
187
188PabloAST * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2) {
189    assert (expr1 && expr2);
190    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
191        return expr2;
192    }
193    if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
194        return expr1;
195    }
196    else if (Not * not1 = dyn_cast<Not>(expr1)) {
197        // ¬a√b = ¬¬(¬a√b) = ¬(a ∧ ¬b)
198        return createNot(createAnd(not1->getExpr(), createNot(expr2)));
199    }
200    else if (Not * not2 = dyn_cast<Not>(expr2)) {
201        // a√¬b = ¬¬(¬b√a) = ¬(b ∧ ¬a)
202        return createNot(createAnd(not2->getExpr(), createNot(expr1)));
203    }
204    else if (equals(expr1, expr2)) {
205        return expr1;
206    }
207    else if (And * and_expr1 = dyn_cast<And>(expr1)) {
208        if (And * and_expr2 = dyn_cast<And>(expr2)) {
209            PabloAST * const expr1a = and_expr1->getExpr1();
210            PabloAST * const expr1b = and_expr1->getExpr2();
211            PabloAST * const expr2a = and_expr2->getExpr1();
212            PabloAST * const expr2b = and_expr2->getExpr2();
213            //These optimizations factor out common components that can occur when sets are formed by union
214            //(e.g., union of [a-z] and [A-Z].
215            if (equals(expr1a, expr2a)) {
216                return createAnd(expr1a, createOr(expr1b, expr2b));
217            }
218            else if (equals(expr1b, expr2b)) {
219                return createAnd(expr1b, createOr(expr1a, expr2a));
220            }
221            else if (equals(expr1a, expr2b)) {
222                return createAnd(expr1a, createOr(expr1b, expr2a));
223            }
224            else if (equals(expr1b, expr2a)) {
225                return createAnd(expr1b, createOr(expr1a, expr2b));
226            }
227        }
228    }
229    return insertAtInsertionPoint(new Or(expr1, expr2, makeName("or_"), this));
230}
231
232PabloAST * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
233    assert (expr1 && expr2);
234    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
235        return renameNonNamedNode(expr2, std::move(prefix));
236    }
237    if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
238        return renameNonNamedNode(expr1, std::move(prefix));
239    }
240    else if (Not * not1 = dyn_cast<Not>(expr1)) {
241        // ¬a√b = ¬¬(¬a√b) = ¬(a ∧ ¬b)
242        return createNot(createAnd(not1->getExpr(), createNot(expr2)), prefix);
243    }
244    else if (Not * not2 = dyn_cast<Not>(expr2)) {
245        // a√¬b = ¬¬(¬b√a) = ¬(b ∧ ¬a)
246        return createNot(createAnd(not2->getExpr(), createNot(expr1)), prefix);
247    }
248    else if (And * and_expr1 = dyn_cast<And>(expr1)) {
249        if (And * and_expr2 = dyn_cast<And>(expr2)) {
250            PabloAST * const expr1a = and_expr1->getExpr1();
251            PabloAST * const expr1b = and_expr1->getExpr2();
252            PabloAST * const expr2a = and_expr2->getExpr1();
253            PabloAST * const expr2b = and_expr2->getExpr2();
254            //These optimizations factor out common components that can occur when sets are formed by union
255            //(e.g., union of [a-z] and [A-Z].
256            if (equals(expr1a, expr2a)) {
257                return createAnd(expr1a, createOr(expr1b, expr2b), prefix);
258            }
259            else if (equals(expr1b, expr2b)) {
260                return createAnd(expr1b, createOr(expr1a, expr2a), prefix);
261            }
262            else if (equals(expr1a, expr2b)) {
263                return createAnd(expr1a, createOr(expr1b, expr2a), prefix);
264            }
265            else if (equals(expr1b, expr2a)) {
266                return createAnd(expr1b, createOr(expr1a, expr2b), prefix);
267            }
268        }
269    }
270    return insertAtInsertionPoint(new Or(expr1, expr2, makeName(prefix, false), this));
271}
272
273PabloAST * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2) {
274    assert (expr1 && expr2);
275    if (isa<Ones>(expr1)) {
276        return createNot(expr2);
277    }
278    else if (isa<Zeroes>(expr1)){
279        return expr2;
280    }
281    else if (isa<Ones>(expr2)) {
282        return createNot(expr1);
283    }
284    else if (isa<Zeroes>(expr2)){
285        return expr1;
286    }
287    else if (Not * not1 = dyn_cast<Not>(expr1)) {
288        if (Not * not2 = dyn_cast<Not>(expr2)) {
289            return createXor(not1->getExpr(), not2->getExpr());
290        }
291    }
292    return insertAtInsertionPoint(new Xor(expr1, expr2, makeName("xor_"), this));
293}
294
295PabloAST * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
296    assert (expr1 && expr2);
297    if (isa<Ones>(expr1)) {
298        return createNot(expr2, prefix);
299    }
300    else if (isa<Zeroes>(expr1)){
301        return expr2;
302    }
303    else if (isa<Ones>(expr2)) {
304        return createNot(expr1, prefix);
305    }
306    else if (isa<Zeroes>(expr2)){
307        return expr1;
308    }
309    else if (Not * not1 = dyn_cast<Not>(expr1)) {
310        if (Not * not2 = dyn_cast<Not>(expr2)) {
311            return createXor(not1->getExpr(), not2->getExpr(), prefix);
312        }
313    }
314    return insertAtInsertionPoint(new Xor(expr1, expr2, makeName(prefix, false), this));
315}
316
317/// TERNARY CREATE FUNCTION
318
319PabloAST * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr) {
320    assert (condition && trueExpr && falseExpr);
321
322    if (isa<Ones>(condition)) {
323        return trueExpr;
324    }
325    else if (isa<Zeroes>(condition)){
326        return falseExpr;
327    }
328    else if (isa<Ones>(trueExpr)) {
329        return createOr(condition, falseExpr);
330    }
331    else if (isa<Zeroes>(trueExpr)){
332        return createAnd(createNot(condition), falseExpr);
333    }
334    else if (isa<Ones>(falseExpr)) {
335        return createOr(createNot(condition), trueExpr);
336    }
337    else if (isa<Zeroes>(falseExpr)){
338        return createAnd(condition, trueExpr);
339    }
340    else if (equals(trueExpr, falseExpr)) {
341        return trueExpr;
342    }
343    else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getExpr(), falseExpr)) {
344        return createXor(condition, falseExpr);
345    }
346    else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getExpr())){
347        return createXor(condition, falseExpr);
348    }
349    return insertAtInsertionPoint(new Sel(condition, trueExpr, falseExpr, makeName("sel"), this));
350}
351
352PabloAST * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr, const std::string prefix) {
353    assert (condition && trueExpr && falseExpr);
354
355    if (isa<Zeroes>(condition)){
356        return renameNonNamedNode(falseExpr, std::move(prefix));
357    }
358    else if (isa<Ones>(condition) || equals(trueExpr, falseExpr)) {
359        return renameNonNamedNode(trueExpr, std::move(prefix));
360    }
361    else if (isa<Ones>(trueExpr)) {
362        return createOr(condition, falseExpr, prefix);
363    }
364    else if (isa<Zeroes>(trueExpr)){
365        return createAnd(createNot(condition), falseExpr, prefix);
366    }
367    else if (isa<Ones>(falseExpr)) {
368        return createOr(createNot(condition), trueExpr, prefix);
369    }
370    else if (isa<Zeroes>(falseExpr)){
371        return createAnd(condition, trueExpr, prefix);
372    }
373    else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getExpr(), falseExpr)) {
374        return createXor(condition, falseExpr, prefix);
375    }
376    else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getExpr())){
377        return createXor(condition, falseExpr, prefix);
378    }
379    return insertAtInsertionPoint(new Sel(condition, trueExpr, falseExpr, makeName(prefix, false), this));
380}
381
382If * PabloBlock::createIf(PabloAST * condition, const std::initializer_list<Assign *> definedVars, PabloBlock & body) {
383    assert (condition);
384    return insertAtInsertionPoint(new If(condition, definedVars, body, this));
385}
386
387If * PabloBlock::createIf(PabloAST * condition, const std::vector<Assign *> & definedVars, PabloBlock & body) {
388    assert (condition);
389    return insertAtInsertionPoint(new If(condition, definedVars, body, this));
390}
391
392If * PabloBlock::createIf(PabloAST * condition, std::vector<Assign *> && definedVars, PabloBlock & body) {
393    assert (condition);
394    return insertAtInsertionPoint(new If(condition, definedVars, body, this));
395}
396
397While * PabloBlock::createWhile(PabloAST * condition, const std::initializer_list<Next *> nextVars, PabloBlock & body) {
398    assert (condition);
399    return insertAtInsertionPoint(new While(condition, nextVars, body, this));
400}
401
402While * PabloBlock::createWhile(PabloAST * condition, const std::vector<Next *> & nextVars, PabloBlock & body) {
403    assert (condition);
404    return insertAtInsertionPoint(new While(condition, nextVars, body, this));
405}
406
407While * PabloBlock::createWhile(PabloAST * condition, std::vector<Next *> && nextVars, PabloBlock & body) {
408    assert (condition);
409    return insertAtInsertionPoint(new While(condition, nextVars, body, this));
410}
411
412/// CONSTRUCTOR
413
414PabloBlock::PabloBlock(SymbolGenerator & symbolGenerator)
415: PabloAST(PabloAST::ClassTypeId::Block)
416, mZeroes(new Zeroes())
417, mOnes(new Ones())
418, mSymbolGenerator(symbolGenerator)
419, mParent(nullptr)
420{
421
422}
423
424PabloBlock::PabloBlock(PabloBlock * predecessor)
425: PabloAST(PabloAST::ClassTypeId::Block)
426, mZeroes(predecessor->mZeroes) // inherit the original "Zeroes" variable for simplicity
427, mOnes(predecessor->mOnes) // inherit the original "Ones" variable for simplicity
428, mSymbolGenerator(predecessor->mSymbolGenerator)
429, mParent(predecessor) {
430
431}
432
433PabloBlock::~PabloBlock() {
434
435}
436
437}
Note: See TracBrowser for help on using the repository browser.