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

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

First attempt to add arguments to Call objects. Currently non-functioning in Pablo_Compiler.

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