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

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

Initial modifications to Pablo Compiler and Kernel Builder to support circular buffers for Lookahead.

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