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

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

More work on n-ary operations.

File size: 26.2 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#include <iostream>
9#include <pablo/printer_pablos.h>
10
11namespace pablo {
12
13Zeroes PabloBlock::mZeroes;
14
15Ones PabloBlock::mOnes;
16
17inline PabloAST * PabloBlock::renameNonNamedNode(PabloAST * expr, const std::string && prefix) {
18    if (Statement * stmt = dyn_cast<Statement>(expr)) {
19        if (stmt->getName()->isGenerated()) {
20            stmt->setName(makeName(prefix, false));
21        }
22    }
23    return expr;
24}
25
26void PabloBlock::insert(Statement * const statement) {
27    assert (statement);
28    if (LLVM_UNLIKELY(mInsertionPoint == nullptr)) {
29        if (mFirst) {
30            statement->insertBefore(mFirst);
31        } else {
32            statement->removeFromParent();
33            statement->mParent = this;
34            mFirst = mLast = statement;
35        }
36    } else if (LLVM_LIKELY(statement != mInsertionPoint)) {
37        statement->insertAfter(mInsertionPoint);
38        mLast = (mLast == mInsertionPoint) ? statement : mLast;
39        assert (statement->mPrev == mInsertionPoint);
40    }
41    mInsertionPoint = statement;
42}
43
44/// UNARY CREATE FUNCTIONS
45
46Assign * PabloBlock::createAssign(const std::string && prefix, PabloAST * expr)  {
47    return insertAtInsertionPoint(new Assign(expr, makeName(prefix, false)));
48}
49
50PabloAST * PabloBlock::createAdvance(PabloAST * expr, PabloAST * shiftAmount) {
51    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
52        return expr;
53    }
54    return insertAtInsertionPoint(new Advance(expr, shiftAmount, makeName("advance")));
55}
56
57PabloAST * PabloBlock::createAdvance(PabloAST * expr, PabloAST * shiftAmount, const std::string prefix) {
58    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
59        return expr;
60    }
61    return insertAtInsertionPoint(new Advance(expr, shiftAmount, makeName(prefix, false)));
62}
63
64PabloAST * PabloBlock::createAdvance(PabloAST * expr, const Integer::Type shiftAmount) {
65    if (isa<Zeroes>(expr) || shiftAmount == 0) {
66        return expr;
67    }
68    return insertAtInsertionPoint(new Advance(expr, getInteger(shiftAmount), makeName("advance")));
69}
70
71PabloAST * PabloBlock::createAdvance(PabloAST * expr, const Integer::Type shiftAmount, const std::string prefix) {
72    if (isa<Zeroes>(expr) || shiftAmount == 0) {
73        return renameNonNamedNode(expr, std::move(prefix));
74    }   
75    return insertAtInsertionPoint(new Advance(expr, getInteger(shiftAmount), makeName(prefix, false)));
76}
77
78Call * PabloBlock::createCall(PabloAST * prototype, const std::vector<PabloAST *> &) {
79    assert (prototype);
80    return insertAtInsertionPoint(new Call(prototype));
81}
82
83
84PabloAST * PabloBlock::createNot(PabloAST * expr) {
85    assert (expr);
86    if (isa<Ones>(expr)) {
87        return createZeroes();
88    }
89    else if (isa<Zeroes>(expr)){
90        return createOnes();
91    }
92    else if (Not * not1 = dyn_cast<Not>(expr)) {
93        return not1->getExpr();
94    }
95    return insertAtInsertionPoint(new Not(expr, makeName("not_")));
96}
97
98PabloAST * PabloBlock::createNot(PabloAST * expr, const std::string prefix) {
99    assert (expr);
100    if (isa<Ones>(expr)) {
101        return createZeroes();
102    }
103    else if (isa<Zeroes>(expr)){
104        return createOnes();
105    }
106    else if (Not * not1 = dyn_cast<Not>(expr)) {       
107        return renameNonNamedNode(not1->getExpr(), std::move(prefix));
108    }
109    return insertAtInsertionPoint(new Not(expr, makeName(prefix, false)));
110}
111
112Var * PabloBlock::createVar(PabloAST * name) {
113    assert (name);
114    return new Var(name);
115}
116
117PabloAST * PabloBlock::createMod64Advance(PabloAST * expr, PabloAST * shiftAmount) {
118    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
119        return expr;
120    }
121    return insertAtInsertionPoint(new Mod64Advance(expr, shiftAmount, makeName("advance")));
122}
123
124PabloAST * PabloBlock::createMod64Advance(PabloAST * expr, PabloAST * shiftAmount, const std::string prefix) {
125    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
126        return expr;
127    }
128    return insertAtInsertionPoint(new Mod64Advance(expr, shiftAmount, makeName(prefix, false)));
129}
130
131PabloAST * PabloBlock::createMod64Advance(PabloAST * expr, const Integer::Type shiftAmount) {
132    if (isa<Zeroes>(expr) || shiftAmount == 0) {
133        return expr;
134    }
135    return insertAtInsertionPoint(new Mod64Advance(expr, getInteger(shiftAmount), makeName("advance")));
136}
137
138PabloAST * PabloBlock::createMod64Advance(PabloAST * expr, const Integer::Type shiftAmount, const std::string prefix) {
139    if (isa<Zeroes>(expr) || shiftAmount == 0) {
140        return renameNonNamedNode(expr, std::move(prefix));
141    }   
142    return insertAtInsertionPoint(new Mod64Advance(expr, getInteger(shiftAmount), makeName(prefix, false)));
143}
144
145PabloAST * PabloBlock::createCount(PabloAST * expr) {
146    assert (expr);
147    return insertAtInsertionPoint(new Count(expr, makeName("count_")));
148}
149
150PabloAST * PabloBlock::createCount(PabloAST * expr, const std::string prefix) {
151    assert (expr);
152    return insertAtInsertionPoint(new Count(expr, makeName(prefix, false)));
153}
154
155   
156/// BINARY CREATE FUNCTIONS
157
158Next * PabloBlock::createNext(Assign * assign, PabloAST * expr) {
159    assert (assign && expr);
160    return insertAtInsertionPoint(new Next(assign, expr));
161}
162
163PabloAST * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass) {
164    assert (marker && charclass);
165    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
166        return marker;
167    }
168    return insertAtInsertionPoint(new MatchStar(marker, charclass, makeName("matchstar")));
169}
170
171PabloAST * PabloBlock::createMatchStar(PabloAST * marker, PabloAST * charclass, const std::string prefix) {
172    assert (marker && charclass);
173    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
174        return renameNonNamedNode(marker, std::move(prefix));
175    }
176    return insertAtInsertionPoint(new MatchStar(marker, charclass, makeName(prefix, false)));
177}
178
179PabloAST * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru) {
180    assert (from && thru);
181    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {
182        return from;
183    }
184    return insertAtInsertionPoint(new ScanThru(from, thru, makeName("scanthru")));
185}
186
187PabloAST * PabloBlock::createScanThru(PabloAST * from, PabloAST * thru, const std::string prefix) {
188    assert (from && thru);
189    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {       
190        return renameNonNamedNode(from, std::move(prefix));
191    }
192    return insertAtInsertionPoint(new ScanThru(from, thru, makeName(prefix, false)));
193}
194
195PabloAST * PabloBlock::createMod64MatchStar(PabloAST * marker, PabloAST * charclass) {
196    assert (marker && charclass);
197    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
198        return marker;
199    }
200    return insertAtInsertionPoint(new Mod64MatchStar(marker, charclass, makeName("matchstar")));
201}
202
203PabloAST * PabloBlock::createMod64MatchStar(PabloAST * marker, PabloAST * charclass, const std::string prefix) {
204    assert (marker && charclass);
205    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
206        return renameNonNamedNode(marker, std::move(prefix));
207    }
208    return insertAtInsertionPoint(new Mod64MatchStar(marker, charclass, makeName(prefix, false)));
209}
210
211PabloAST * PabloBlock::createMod64ScanThru(PabloAST * from, PabloAST * thru) {
212    assert (from && thru);
213    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {
214        return from;
215    }
216    return insertAtInsertionPoint(new Mod64ScanThru(from, thru, makeName("scanthru")));
217}
218
219PabloAST * PabloBlock::createMod64ScanThru(PabloAST * from, PabloAST * thru, const std::string prefix) {
220    assert (from && thru);
221    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {       
222        return renameNonNamedNode(from, std::move(prefix));
223    }
224    return insertAtInsertionPoint(new Mod64ScanThru(from, thru, makeName(prefix, false)));
225}
226
227PabloAST * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2) {
228    assert (expr1 && expr2);
229    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
230        return expr2;
231    } else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
232        return expr1;
233    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
234        if (equals(not1->getExpr(), expr2)) {
235            return createZeroes();
236        }
237    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
238        if (equals(expr1, not2->getExpr())) {
239            return createZeroes();
240        }
241    } else if (Or * or1 = dyn_cast<Or>(expr1)) {
242        if (equals(or1->getOperand(0), expr2) || equals(or1->getOperand(1), expr2)) {
243            return expr2;
244        }
245    } else if (Or * or2 = dyn_cast<Or>(expr2)) {
246        if (equals(or2->getOperand(0), expr1) || equals(or2->getOperand(1), expr1)) {
247            return expr1;
248        }
249    }
250    return insertAtInsertionPoint(new And(expr1, expr2, makeName("and_")));
251}
252
253And * PabloBlock::createAnd(const unsigned operands, PabloAST * value) {
254    return insertAtInsertionPoint(new And(operands, value, makeName("and_")));
255}
256
257PabloAST * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
258    assert (expr1 && expr2);
259    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
260        return expr2;
261    } else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
262        return expr1;
263    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
264        if (equals(not1->getExpr(), expr2)) {
265            return createZeroes();
266        }
267    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
268        if (equals(expr1, not2->getExpr())) {
269            return createZeroes();
270        }
271    } if (Or * or1 = dyn_cast<Or>(expr1)) {
272        if (equals(or1->getOperand(0), expr2) || equals(or1->getOperand(1), expr2)) {
273            return expr2; // (a √ b) ∧ a = a
274        }
275    } else if (Or * or2 = dyn_cast<Or>(expr2)) {
276        if (equals(or2->getOperand(0), expr1) || equals(or2->getOperand(1), expr1)) {
277            return expr1;
278        }
279    }
280    return insertAtInsertionPoint(new And(expr1, expr2, makeName(prefix, false)));
281}
282
283PabloAST * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2) {
284    assert (expr1 && expr2);
285    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
286        return expr2;
287    } else if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
288        return expr1;
289    } else if (And * and1 = dyn_cast<And>(expr1)) {
290        if (equals(and1->getOperand(0), expr2) || equals(and1->getOperand(1), expr2)){
291            return expr2; // (a ∧ b) √ a = a
292        }
293    } else if (And * and2 = dyn_cast<And>(expr2)) {
294        if (equals(and2->getOperand(0), expr1) || equals(and2->getOperand(1), expr1)) {
295            return expr1;
296        }
297    }
298    return insertAtInsertionPoint(new Or(expr1, expr2, makeName("or_")));
299}
300
301Or * PabloBlock::createOr(const unsigned operands, PabloAST * value) {
302    return insertAtInsertionPoint(new Or(operands, value, makeName("or_")));
303}
304
305PabloAST * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
306    assert (expr1 && expr2);
307    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
308        return expr2;
309    } else if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
310        return expr1;
311    } else if (And * and1 = dyn_cast<And>(expr1)) {
312        if (equals(and1->getOperand(0), expr2) || equals(and1->getOperand(1), expr2)){
313            return expr2; // (a ∧ b) √ a = a
314        }
315    } else if (And * and2 = dyn_cast<And>(expr2)) {
316        if (equals(and2->getOperand(0), expr1) || equals(and2->getOperand(1), expr1)) {
317            return expr1;
318        }
319    }
320    return insertAtInsertionPoint(new Or(expr1, expr2, makeName(prefix, false)));
321}
322
323PabloAST * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2) {
324    assert (expr1 && expr2);
325    if (expr1 == expr2) {
326        return PabloBlock::createZeroes();
327    } else if (isa<Zeroes>(expr1)){
328        return expr2;
329    } else if (isa<Zeroes>(expr2)){
330        return expr1;
331    } else if (isa<Not>(expr1) && isa<Not>(expr2)) {
332        return createXor(cast<Not>(expr1)->getExpr(), cast<Not>(expr2)->getExpr());
333    }
334    return insertAtInsertionPoint(new Xor(expr1, expr2, makeName("xor_")));
335}
336
337PabloAST * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
338    assert (expr1 && expr2);
339    if (expr1 == expr2) {
340        return PabloBlock::createZeroes();
341    } else if (isa<Zeroes>(expr1)){
342        return expr2;
343    } else if (isa<Zeroes>(expr2)){
344        return expr1;
345    } else if (isa<Not>(expr1) && isa<Not>(expr2)) {
346        return createXor(cast<Not>(expr1)->getExpr(), cast<Not>(expr2)->getExpr());
347    }
348    return insertAtInsertionPoint(new Xor(expr1, expr2, makeName(prefix, false)));
349}
350
351
352//PabloAST * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2) {
353//    assert (expr1 && expr2);
354//    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
355//        return expr2;
356//    } else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
357//        return expr1;
358//    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
359//        if (Not * not2 = dyn_cast<Not>(expr2)) {
360//            return createNot(createOr(not1->getExpr(), not2->getExpr()));
361//        } else if (equals(not1->getExpr(), expr2)) {
362//            return createZeroes();
363//        }
364//    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
365//        if (equals(expr1, not2->getExpr())) {
366//            return createZeroes();
367//        }
368//    } else if (Or * or1 = dyn_cast<Or>(expr1)) {
369//        if (equals(or1->getOperand(0), expr2) || equals(or1->getOperand(1), expr2)) {
370//            return expr2;
371//        }
372//    } else if (Or * or2 = dyn_cast<Or>(expr2)) {
373//        if (equals(or2->getOperand(0), expr1) || equals(or2->getOperand(1), expr1)) {
374//            return expr1;
375//        }
376//    }
377//    if (isa<Not>(expr1) || expr1 > expr2) {
378//        std::swap(expr1, expr2);
379//    }
380//    return insertAtInsertionPoint(new And(expr1, expr2, makeName("and_")));
381//}
382
383//PabloAST * PabloBlock::createAnd(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
384//    assert (expr1 && expr2);
385//    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
386//        return renameNonNamedNode(expr2, std::move(prefix));
387//    } else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
388//        return renameNonNamedNode(expr1, std::move(prefix));
389//    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
390//        if (Not * not2 = dyn_cast<Not>(expr2)) {
391//            return createNot(createOr(not1->getExpr(), not2->getExpr()), prefix);
392//        }
393//        else if (equals(not1->getExpr(), expr2)) {
394//            return createZeroes();
395//        }
396//    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
397//        if (equals(expr1, not2->getExpr())) {
398//            return createZeroes();
399//        }
400//    } else if (Or * or1 = dyn_cast<Or>(expr1)) {
401//        if (equals(or1->getOperand(0), expr2) || equals(or1->getOperand(1), expr2)) {
402//            return expr2;
403//        }
404//    } else if (Or * or2 = dyn_cast<Or>(expr2)) {
405//        if (equals(or2->getOperand(0), expr1) || equals(or2->getOperand(1), expr1)) {
406//            return expr1;
407//        }
408//    }
409//    if (isa<Not>(expr1) || expr1 > expr2) {
410//        std::swap(expr1, expr2);
411//    }
412//    return insertAtInsertionPoint(new And(expr1, expr2, makeName(prefix, false)));
413//}
414
415//PabloAST * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2) {
416//    assert (expr1 && expr2);
417//    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
418//        return expr2;
419//    }
420//    if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
421//        return expr1;
422//    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
423//        // ¬a√b = ¬¬(¬a√b) = ¬(a ∧ ¬b)
424//        return createNot(createAnd(not1->getExpr(), createNot(expr2)));
425//    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
426//        // a√¬b = ¬¬(¬b√a) = ¬(b ∧ ¬a)
427//        return createNot(createAnd(not2->getExpr(), createNot(expr1)));
428//    } else if (equals(expr1, expr2)) {
429//        return expr1;
430//    } else if (And * and1 = dyn_cast<And>(expr1)) {
431//        if (And * and2 = dyn_cast<And>(expr2)) {
432//            PabloAST * const expr1a = and1->getOperand(0);
433//            PabloAST * const expr1b = and1->getOperand(1);
434//            PabloAST * const expr2a = and2->getOperand(0);
435//            PabloAST * const expr2b = and2->getOperand(1);
436//            //These optimizations factor out common components that can occur when sets are formed by union
437//            //(e.g., union of [a-z] and [A-Z].
438//            if (equals(expr1a, expr2a)) {
439//                return createAnd(expr1a, createOr(expr1b, expr2b));
440//            } else if (equals(expr1b, expr2b)) {
441//                return createAnd(expr1b, createOr(expr1a, expr2a));
442//            } else if (equals(expr1a, expr2b)) {
443//                return createAnd(expr1a, createOr(expr1b, expr2a));
444//            } else if (equals(expr1b, expr2a)) {
445//                return createAnd(expr1b, createOr(expr1a, expr2b));
446//            }
447//        } else if (equals(and1->getOperand(0), expr2) || equals(and1->getOperand(1), expr2)){
448//            // (a∧b) √ a = a
449//            return expr2;
450//        }
451//    } else if (And * and2 = dyn_cast<And>(expr2)) {
452//        if (equals(and2->getOperand(0), expr1) || equals(and2->getOperand(1), expr1)) {
453//            return expr1;
454//        }
455//    }
456//    if (expr1 > expr2) {
457//        std::swap(expr1, expr2);
458//    }
459//    return insertAtInsertionPoint(new Or(expr1, expr2, makeName("or_")));
460//}
461
462//PabloAST * PabloBlock::createOr(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
463//    assert (expr1 && expr2);
464//    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
465//        return renameNonNamedNode(expr2, std::move(prefix));
466//    }
467//    else if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
468//        return renameNonNamedNode(expr1, std::move(prefix));
469//    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
470//        // ¬a√b = ¬¬(¬a√b) = ¬(a ∧ ¬b)
471//        return createNot(createAnd(not1->getExpr(), createNot(expr2)), prefix);
472//    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
473//        // a√¬b = ¬¬(¬b√a) = ¬(b ∧ ¬a)
474//        return createNot(createAnd(not2->getExpr(), createNot(expr1)), prefix);
475//    } else if (And * and1 = dyn_cast<And>(expr1)) {
476//        if (And * and2 = dyn_cast<And>(expr2)) {
477//            PabloAST * const expr1a = and1->getOperand(0);
478//            PabloAST * const expr1b = and1->getOperand(1);
479//            PabloAST * const expr2a = and2->getOperand(0);
480//            PabloAST * const expr2b = and2->getOperand(1);
481//            //These optimizations factor out common components that can occur when sets are formed by union
482//            //(e.g., union of [a-z] and [A-Z].
483//            if (equals(expr1a, expr2a)) {
484//                return createAnd(expr1a, createOr(expr1b, expr2b), prefix);
485//            } else if (equals(expr1b, expr2b)) {
486//                return createAnd(expr1b, createOr(expr1a, expr2a), prefix);
487//            } else if (equals(expr1a, expr2b)) {
488//                return createAnd(expr1a, createOr(expr1b, expr2a), prefix);
489//            } else if (equals(expr1b, expr2a)) {
490//                return createAnd(expr1b, createOr(expr1a, expr2b), prefix);
491//            }
492//        } else if (equals(and1->getOperand(0), expr2) || equals(and1->getOperand(1), expr2)) {
493//            // (a∧b) √ a = a
494//            return expr2;
495//        }
496//    } else if (And * and2 = dyn_cast<And>(expr2)) {
497//        if (equals(and2->getOperand(0), expr1) || equals(and2->getOperand(1), expr1)) {
498//            return expr1;
499//        }
500//    }
501//    if (expr1 > expr2) {
502//        std::swap(expr1, expr2);
503//    }
504//    return insertAtInsertionPoint(new Or(expr1, expr2, makeName(prefix, false)));
505//}
506
507//PabloAST * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2) {
508//    assert (expr1 && expr2);
509//    if (expr1 == expr2) {
510//        return PabloBlock::createZeroes();
511//    }
512//    if (isa<Ones>(expr1)) {
513//        return createNot(expr2);
514//    } else if (isa<Zeroes>(expr1)){
515//        return expr2;
516//    } else if (isa<Ones>(expr2)) {
517//        return createNot(expr1);
518//    } else if (isa<Zeroes>(expr2)){
519//        return expr1;
520//    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
521//        if (Not * not2 = dyn_cast<Not>(expr2)) {
522//            return createXor(not1->getExpr(), not2->getExpr());
523//        }
524//    }
525//    if (expr1 > expr2) {
526//        std::swap(expr1, expr2);
527//    }
528//    return insertAtInsertionPoint(new Xor(expr1, expr2, makeName("xor_")));
529//}
530
531//PabloAST * PabloBlock::createXor(PabloAST * expr1, PabloAST * expr2, const std::string prefix) {
532//    assert (expr1 && expr2);
533//    if (expr1 == expr2) {
534//        return PabloBlock::createZeroes();
535//    }
536//    if (isa<Ones>(expr1)) {
537//        return createNot(expr2, prefix);
538//    } else if (isa<Zeroes>(expr1)){
539//        return expr2;
540//    } else if (isa<Ones>(expr2)) {
541//        return createNot(expr1, prefix);
542//    } else if (isa<Zeroes>(expr2)){
543//        return expr1;
544//    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
545//        if (Not * not2 = dyn_cast<Not>(expr2)) {
546//            return createXor(not1->getExpr(), not2->getExpr(), prefix);
547//        }
548//    }
549//    if (expr1 > expr2) {
550//        std::swap(expr1, expr2);
551//    }
552//    return insertAtInsertionPoint(new Xor(expr1, expr2, makeName(prefix, false)));
553//}
554
555/// TERNARY CREATE FUNCTION
556
557PabloAST * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr) {
558    assert (condition && trueExpr && falseExpr);
559    if (isa<Ones>(condition)) {
560        return trueExpr;
561    } else if (isa<Zeroes>(condition)){
562        return falseExpr;
563    } else if (isa<Ones>(trueExpr)) {
564        return createOr(condition, falseExpr);
565    } else if (isa<Zeroes>(trueExpr)){
566        return createAnd(createNot(condition), falseExpr);
567    } else if (isa<Ones>(falseExpr)) {
568        return createOr(createNot(condition), trueExpr);
569    } else if (isa<Zeroes>(falseExpr)){
570        return createAnd(condition, trueExpr);
571    } else if (equals(trueExpr, falseExpr)) {
572        return trueExpr;
573    } else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getExpr(), falseExpr)) {
574        return createXor(condition, falseExpr);
575    } else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getExpr())){
576        return createXor(condition, falseExpr);
577    }
578    return insertAtInsertionPoint(new Sel(condition, trueExpr, falseExpr, makeName("sel")));
579}
580
581PabloAST * PabloBlock::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr, const std::string prefix) {
582    assert (condition && trueExpr && falseExpr);
583    if (isa<Zeroes>(condition)){
584        return renameNonNamedNode(falseExpr, std::move(prefix));
585    }
586    else if (isa<Ones>(condition) || equals(trueExpr, falseExpr)) {
587        return renameNonNamedNode(trueExpr, std::move(prefix));
588    }
589    else if (isa<Ones>(trueExpr)) {
590        return createOr(condition, falseExpr, prefix);
591    }
592    else if (isa<Zeroes>(trueExpr)){
593        return createAnd(createNot(condition), falseExpr, prefix);
594    }
595    else if (isa<Ones>(falseExpr)) {
596        return createOr(createNot(condition), trueExpr, prefix);
597    }
598    else if (isa<Zeroes>(falseExpr)){
599        return createAnd(condition, trueExpr, prefix);
600    }
601    else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getExpr(), falseExpr)) {
602        return createXor(condition, falseExpr, prefix);
603    }
604    else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getExpr())){
605        return createXor(condition, falseExpr, prefix);
606    }
607    return insertAtInsertionPoint(new Sel(condition, trueExpr, falseExpr, makeName(prefix, false)));
608}
609
610If * PabloBlock::createIf(PabloAST * condition, const std::initializer_list<Assign *> definedVars, PabloBlock * body) {
611    assert (condition);
612    return insertAtInsertionPoint(new If(condition, definedVars, body));
613}
614
615If * PabloBlock::createIf(PabloAST * condition, const std::vector<Assign *> & definedVars, PabloBlock * body) {
616    assert (condition);
617    return insertAtInsertionPoint(new If(condition, definedVars, body));
618}
619
620If * PabloBlock::createIf(PabloAST * condition, std::vector<Assign *> && definedVars, PabloBlock * body) {
621    assert (condition);
622    return insertAtInsertionPoint(new If(condition, definedVars, body));
623}
624
625While * PabloBlock::createWhile(PabloAST * condition, const std::initializer_list<Next *> nextVars, PabloBlock * body) {
626    assert (condition);
627    return insertAtInsertionPoint(new While(condition, nextVars, body));
628}
629
630While * PabloBlock::createWhile(PabloAST * condition, const std::vector<Next *> & nextVars, PabloBlock * body) {
631    assert (condition);
632    return insertAtInsertionPoint(new While(condition, nextVars, body));
633}
634
635While * PabloBlock::createWhile(PabloAST * condition, std::vector<Next *> && nextVars, PabloBlock * body) {
636    assert (condition);
637    return insertAtInsertionPoint(new While(condition, nextVars, body));
638}
639
640/** ------------------------------------------------------------------------------------------------------------- *
641 * @brief eraseFromParent
642 ** ------------------------------------------------------------------------------------------------------------- */
643void PabloBlock::eraseFromParent(const bool recursively) {
644    Statement * stmt = front();
645    // Note: by erasing the scope block, any Assign/Next nodes will be replaced with Zero and removed from
646    // the If/While node
647    while (stmt) {
648        stmt = stmt->eraseFromParent(recursively);
649    }
650    mAllocator.deallocate(reinterpret_cast<Allocator::pointer>(this));
651}
652
653
654// Assign sequential scope indexes, returning the next unassigned index   
655
656unsigned PabloBlock::enumerateScopes(unsigned baseScopeIndex) {
657    mScopeIndex = baseScopeIndex;
658    unsigned nextScopeIndex = baseScopeIndex + 1;
659    for (Statement * stmt : *this) {
660        if (If * ifStatement = dyn_cast<If>(stmt)) {
661            nextScopeIndex = ifStatement->getBody()->enumerateScopes(nextScopeIndex);
662        }
663        else if (While * whileStatement = dyn_cast<While>(stmt)) {
664            nextScopeIndex = whileStatement->getBody()->enumerateScopes(nextScopeIndex);
665        }
666    }
667    return nextScopeIndex;
668}   
669   
670/// CONSTRUCTOR
671
672PabloBlock::PabloBlock(SymbolGenerator * symbolGenerator) noexcept
673: PabloAST(PabloAST::ClassTypeId::Block)
674, mSymbolGenerator(symbolGenerator)
675, mParent(nullptr)
676, mScopeIndex(0)
677{
678
679}
680
681PabloBlock::~PabloBlock() {
682
683}
684
685}
Note: See TracBrowser for help on using the repository browser.