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

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

More work towards n-ary And/Or/Xor? functions.

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