source: icGREP/icgrep-devel/icgrep/pablo/builder.cpp @ 5239

Last change on this file since 5239 was 5227, checked in by nmedfort, 3 years ago

Rewrite of the CarryManager? to support non-carry-collapsing loops.

File size: 19.7 KB
RevLine 
[4683]1#include <pablo/builder.hpp>
[5202]2// #include <boost/current_function.hpp> // BOOST_CURRENT_FUNCTION
[4443]3
4namespace pablo {
5
[4602]6#define MAKE_UNARY(NAME, TYPE, ARGS...) \
[4443]7struct __##NAME { \
[4602]8    inline PabloAST * operator()(PabloAST * arg) { \
[4641]9        return mPb->NAME(arg); \
[4443]10    } \
[4641]11    inline __##NAME(PabloBlock * pb) : mPb(pb) {} \
[4622]12private: \
[4641]13    PabloBlock * mPb; \
[4622]14}; \
15__##NAME functor(mPb); \
16PabloAST * result = mExprTable.findUnaryOrCall(std::move(functor), TYPE, ARGS)
[4443]17
[5202]18#define MAKE_NAMED_UNARY(NAME, TYPE, PREFIX, ARGS...) \
19struct __##NAME { \
20    inline PabloAST * operator()(PabloAST * arg) { \
21        return mPb->NAME(arg, mPrefix); \
22    } \
23    inline __##NAME(PabloBlock * pb, const std::string & prefix) : mPb(pb), mPrefix(prefix) {} \
24private: \
25    PabloBlock * mPb; \
26    const std::string & mPrefix; \
27}; \
28__##NAME functor(mPb, prefix); \
29PabloAST * result = mExprTable.findUnaryOrCall(std::move(functor), TYPE, ARGS)
30
[4602]31#define MAKE_BINARY(NAME, TYPE, ARGS...) \
[4443]32struct __##NAME { \
[4602]33    inline PabloAST * operator()(PabloAST * arg1, PabloAST * arg2) { \
[4641]34        return mPb->NAME(arg1, arg2); \
[4443]35    } \
[4641]36    inline __##NAME(PabloBlock * pb) : mPb(pb) {} \
[4603]37private: \
[4641]38    PabloBlock * mPb; \
[4603]39}; \
40__##NAME functor(mPb); \
41PabloAST * result = mExprTable.findBinaryOrCall(std::move(functor), TYPE, ARGS)
42
[5202]43#define MAKE_NAMED_BINARY(NAME, TYPE, PREFIX, ARGS...) \
44struct __##NAME { \
45    inline PabloAST * operator()(PabloAST * arg1, PabloAST * arg2) { \
46        return mPb->NAME(arg1, arg2, mPrefix); \
47    } \
48    inline __##NAME(PabloBlock * pb, const std::string & prefix) : mPb(pb), mPrefix(prefix) {} \
49private: \
50    PabloBlock * mPb; \
51    const std::string & mPrefix; \
52}; \
53__##NAME functor(mPb, PREFIX); \
54PabloAST * result = mExprTable.findBinaryOrCall(std::move(functor), TYPE, ARGS)
[4692]55
[4602]56#define MAKE_TERNARY(NAME, TYPE, ARGS...) \
[4443]57struct __##NAME { \
[4602]58    inline PabloAST * operator()(PabloAST * arg1, PabloAST * arg2, PabloAST * arg3) { \
[4641]59        return mPb->NAME(arg1, arg2, arg3); \
[4443]60    } \
[4641]61    inline __##NAME(PabloBlock * pb) : mPb(pb) {} \
[4622]62private: \
[4641]63    PabloBlock * mPb; \
[4622]64}; \
65__##NAME functor(mPb); \
66PabloAST * result = mExprTable.findTernaryOrCall(std::move(functor), TYPE, ARGS)
[4443]67
[5202]68#define MAKE_NAMED_TERNARY(NAME, TYPE, PREFIX, ARGS...) \
69struct __##NAME { \
70    inline PabloAST * operator()(PabloAST * arg1, PabloAST * arg2, PabloAST * arg3) { \
71        return mPb->NAME(arg1, arg2, arg3, mPrefix); \
72    } \
73    inline __##NAME(PabloBlock * pb, const std::string & prefix) : mPb(pb), mPrefix(prefix) {} \
74private: \
75    PabloBlock * mPb; \
76    const std::string & mPrefix; \
77}; \
78__##NAME functor(mPb, PREFIX); \
79PabloAST * result = mExprTable.findTernaryOrCall(std::move(functor), TYPE, ARGS)
80
[4692]81#define MAKE_VARIABLE(NAME, TYPE, ARGS...) \
[4681]82struct __##NAME { \
[4692]83    inline PabloAST * operator()(const std::vector<PabloAST *> & args, PabloAST * prototype) { \
84        return mPb->NAME(prototype, args); \
[4681]85    } \
86    inline __##NAME(PabloBlock * pb) : mPb(pb) {} \
87private: \
88    PabloBlock * mPb; \
89}; \
90__##NAME functor(mPb); \
[5202]91PabloAST * result = mExprTable.findVariadicOrCall(std::move(functor), TYPE, ARGS)
[4622]92
[5202]93template<typename Type>
94static inline Type * isBinary(PabloAST * expr) {
95    if (isa<Type>(expr) && cast<Type>(expr)->getNumOperands() == 2) {
96        return cast<Type>(expr);
97    }
98    return nullptr;
99}
100
101using TypeId = PabloAST::ClassTypeId;
102
[4692]103Call * PabloBuilder::createCall(Prototype * prototype, const std::vector<PabloAST *> & args) {
104    if (prototype == nullptr) {
105        throw std::runtime_error("Call object cannot be created with a Null prototype!");
106    }
[4681]107    if (args.size() != cast<Prototype>(prototype)->getNumOfParameters()) {
108        throw std::runtime_error("Invalid number of arguments passed into Call object!");
109    }
[5202]110    MAKE_VARIABLE(createCall, TypeId::Call, prototype->getName(), args, prototype);
[4602]111    return cast<Call>(result);
[4443]112}
113
114PabloAST * PabloBuilder::createAdvance(PabloAST * expr, PabloAST * shiftAmount) {
[5202]115    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
116        return expr;
117    }
118    MAKE_BINARY(createAdvance, TypeId::Advance, expr, shiftAmount);
[4602]119    return result;
[4443]120}
121
[5202]122PabloAST * PabloBuilder::createAdvance(PabloAST * expr, PabloAST * shiftAmount, const std::string & prefix) {
123    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
124        return expr;
125    }
126    MAKE_NAMED_BINARY(createAdvance, TypeId::Advance, prefix, expr, shiftAmount);
[4603]127    return result;
128}
129
[5202]130Extract * PabloBuilder::createExtract(PabloAST * value, not_null<PabloAST *> index) {
131    MAKE_BINARY(createExtract, TypeId::Extract, value, index);
132    return cast<Extract>(result);
133}
134
135Extract * PabloBuilder::createExtract(PabloAST * value, not_null<PabloAST *> index, const std::string & prefix) {
136    MAKE_NAMED_BINARY(createExtract, TypeId::Extract, prefix, value, index);
137    return cast<Extract>(result);
138}
139
[4959]140PabloAST * PabloBuilder::createLookahead(PabloAST * expr, PabloAST * shiftAmount) {
[5202]141    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
142        return expr;
143    }
144    MAKE_BINARY(createLookahead, TypeId::Lookahead, expr, shiftAmount);
[4959]145    return result;
146}
147
[5202]148PabloAST * PabloBuilder::createLookahead(PabloAST * expr, PabloAST * shiftAmount, const std::string & prefix) {
149    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
150        return expr;
151    }
152    MAKE_NAMED_BINARY(createLookahead, TypeId::Lookahead, prefix, expr, shiftAmount);
[4959]153    return result;
154}
155
[4443]156PabloAST * PabloBuilder::createNot(PabloAST * expr) {
[5202]157    if (isa<Ones>(expr)) {
158        return createZeroes(expr->getType());
159    }
160    else if (isa<Zeroes>(expr)){
161        return createOnes(expr->getType());
162    }
163    else if (Not * not1 = dyn_cast<Not>(expr)) {
164        return not1->getOperand(0);
165    }
166    MAKE_UNARY(createNot, TypeId::Not, expr);
[4602]167    return result;
[4443]168}
169
[5202]170PabloAST * PabloBuilder::createNot(PabloAST * expr, const std::string & prefix) {
171    if (isa<Ones>(expr)) {
172        return createZeroes(expr->getType());
173    }
174    else if (isa<Zeroes>(expr)){
175        return createOnes(expr->getType());
176    }
177    else if (Not * not1 = dyn_cast<Not>(expr)) {
178        return not1->getOperand(0);
179    }
180    MAKE_NAMED_UNARY(createNot, TypeId::Not, prefix, expr);
[4622]181    return result;
182}
183
[5202]184PabloAST * PabloBuilder::createCount(PabloAST * expr) {
185    MAKE_UNARY(createCount, TypeId::Count, expr);
186    return result;
187}
188
189PabloAST * PabloBuilder::createCount(PabloAST * expr, const std::string & prefix) {
190    MAKE_NAMED_UNARY(createCount, TypeId::Count, prefix, expr);
191    return result;
192}
193
194PabloAST * PabloBuilder::createAssign(PabloAST * const variable, PabloAST * const value) {
[5217]195    return mPb->createAssign(variable, value);
[5202]196}
197
[4443]198PabloAST * PabloBuilder::createAnd(PabloAST * expr1, PabloAST * expr2) {
[5202]199    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
200        return expr2;
201    } else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
202        return expr1;
203    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
204        if (Not * not2 = dyn_cast<Not>(expr2)) {
205            return createNot(createOr(not1->getOperand(0), not2->getOperand(0)));
206        } else if (equals(not1->getOperand(0), expr2)) {
207            return createZeroes(expr1->getType());
208        }
209    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
210        if (equals(expr1, not2->getOperand(0))) {
211            return createZeroes(expr1->getType());
212        }
213    } else if (Or * or1 = isBinary<Or>(expr1)) {
214        if (equals(or1->getOperand(0), expr2) || equals(or1->getOperand(1), expr2)) {
215            return expr2;
216        }
217    } else if (Or * or2 = isBinary<Or>(expr2)) {
218        if (equals(or2->getOperand(0), expr1) || equals(or2->getOperand(1), expr1)) {
219            return expr1;
220        }
221    }
222    if (expr1 > expr2) {
[4443]223        std::swap(expr1, expr2);
224    }
[5202]225    MAKE_BINARY(createAnd, TypeId::And, expr1, expr2);
[4602]226    return result;
[4443]227}
228
[5202]229PabloAST * PabloBuilder::createAnd(PabloAST * expr1, PabloAST * expr2, const std::string & prefix) {
230    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
231        return expr2;
232    } else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
233        return expr1;
234    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
235        if (Not * not2 = dyn_cast<Not>(expr2)) {
236            return createNot(createOr(not1->getOperand(0), not2->getOperand(0)), prefix);
237        } else if (equals(not1->getOperand(0), expr2)) {
238            return createZeroes(expr1->getType());
239        }
240    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
241        if (equals(expr1, not2->getOperand(0))) {
242            return createZeroes(expr1->getType());
243        }
244    } else if (Or * or1 = isBinary<Or>(expr1)) {
245        if (equals(or1->getOperand(0), expr2) || equals(or1->getOperand(1), expr2)) {
246            return expr2;
247        }
248    } else if (Or * or2 = isBinary<Or>(expr2)) {
249        if (equals(or2->getOperand(0), expr1) || equals(or2->getOperand(1), expr1)) {
250            return expr1;
251        }
252    }
253    if (expr1 > expr2) {
[4622]254        std::swap(expr1, expr2);
255    }
[5202]256    MAKE_NAMED_BINARY(createAnd, TypeId::And, prefix, expr1, expr2);
[4622]257    return result;
258}
259
[4443]260PabloAST * PabloBuilder::createOr(PabloAST * expr1, PabloAST * expr2) {
[5202]261    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
262        return expr2;
263    }
264    if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
265        return expr1;
266    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
267        // ¬a√b = ¬¬(¬a √ b) = ¬(a ∧ ¬b)
268        return createNot(createAnd(not1->getOperand(0), createNot(expr2)));
269    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
270        // a√¬b = ¬¬(¬b √ a) = ¬(b ∧ ¬a)
271        return createNot(createAnd(not2->getOperand(0), createNot(expr1)));
272    } else if (equals(expr1, expr2)) {
273        return expr1;
274    } else if (And * and1 = isBinary<And>(expr1)) {
275        PabloAST * const expr1a = and1->getOperand(0);
276        PabloAST * const expr1b = and1->getOperand(1);
277        if (And * and2 = isBinary<And>(expr2)) {
278            PabloAST * const expr2a = and2->getOperand(0);
279            PabloAST * const expr2b = and2->getOperand(1);
280            //These optimizations factor out common components that can occur when sets are formed by union
281            //(e.g., union of [a-z] and [A-Z].
282            if (equals(expr1a, expr2a)) {
283                return createAnd(expr1a, createOr(expr1b, expr2b));
284            } else if (equals(expr1b, expr2b)) {
285                return createAnd(expr1b, createOr(expr1a, expr2a));
286            } else if (equals(expr1a, expr2b)) {
287                return createAnd(expr1a, createOr(expr1b, expr2a));
288            } else if (equals(expr1b, expr2a)) {
289                return createAnd(expr1b, createOr(expr1a, expr2b));
290            }
291        } else if (equals(expr1a, expr2) || equals(expr1b, expr2)) {
292            // (a ∧ b) √ a = a
293            return expr2;
294        }
295    } else if (And * and2 = isBinary<And>(expr2)) {
296        if (equals(and2->getOperand(0), expr1) || equals(and2->getOperand(1), expr1)) {
297            return expr1;
298        }
299    }
[4695]300    if (expr1 > expr2) {
[4443]301        std::swap(expr1, expr2);
302    }
[5202]303    MAKE_BINARY(createOr, TypeId::Or, expr1, expr2);
[4602]304    return result;
[4443]305}
306
[5202]307PabloAST * PabloBuilder::createOr(PabloAST * expr1, PabloAST * expr2, const std::string & prefix) {
308    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
309        return expr2;
310    }
311    if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
312        return expr1;
313    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
314        // ¬a√b = ¬¬(¬a √ b) = ¬(a ∧ ¬b)
315        return createNot(createAnd(not1->getOperand(0), createNot(expr2)), prefix);
316    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
317        // a√¬b = ¬¬(¬b √ a) = ¬(b ∧ ¬a)
318        return createNot(createAnd(not2->getOperand(0), createNot(expr1)), prefix);
319    } else if (equals(expr1, expr2)) {
320        return expr1;
321    } else if (And * and1 = isBinary<And>(expr1)) {
322        PabloAST * const expr1a = and1->getOperand(0);
323        PabloAST * const expr1b = and1->getOperand(1);
324        if (And * and2 = isBinary<And>(expr2)) {
325            PabloAST * const expr2a = and2->getOperand(0);
326            PabloAST * const expr2b = and2->getOperand(1);
327            //These optimizations factor out common components that can occur when sets are formed by union
328            //(e.g., union of [a-z] and [A-Z].
329            if (equals(expr1a, expr2a)) {
330                return createAnd(expr1a, createOr(expr1b, expr2b), prefix);
331            } else if (equals(expr1b, expr2b)) {
332                return createAnd(expr1b, createOr(expr1a, expr2a), prefix);
333            } else if (equals(expr1a, expr2b)) {
334                return createAnd(expr1a, createOr(expr1b, expr2a), prefix);
335            } else if (equals(expr1b, expr2a)) {
336                return createAnd(expr1b, createOr(expr1a, expr2b), prefix);
337            }
338        } else if (equals(expr1a, expr2) || equals(expr1b, expr2)) {
339            // (a ∧ b) √ a = a
340            return expr2;
341        }
342    } else if (And * and2 = isBinary<And>(expr2)) {
343        if (equals(and2->getOperand(0), expr1) || equals(and2->getOperand(1), expr1)) {
344            return expr1;
345        }
346    }
[4695]347    if (expr1 > expr2) {
[4622]348        std::swap(expr1, expr2);
349    }
[5202]350    MAKE_NAMED_BINARY(createOr, TypeId::Or, prefix, expr1, expr2);
[4622]351    return result;
352}
353
[4443]354PabloAST * PabloBuilder::createXor(PabloAST * expr1, PabloAST * expr2) {
[5202]355    if (expr1 == expr2) {
356        return createZeroes(expr1->getType());
357    } else if (isa<Ones>(expr1)) {
358        return createNot(expr2);
359    } else if (isa<Zeroes>(expr1)){
360        return expr2;
361    } else if (isa<Ones>(expr2)) {
362        return createNot(expr1);
363    } else if (isa<Zeroes>(expr2)){
364        return expr1;
365    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
366        if (Not * not2 = dyn_cast<Not>(expr2)) {
367            return createXor(not1->getOperand(0), not2->getOperand(0));
368        }
369    }
[4695]370    if (expr1 > expr2) {
[4443]371        std::swap(expr1, expr2);
372    }
[5202]373    MAKE_BINARY(createXor, TypeId::Xor, expr1, expr2);
[4602]374    return result;
[4443]375}
376
[5202]377PabloAST * PabloBuilder::createXor(PabloAST * expr1, PabloAST * expr2, const std::string & prefix) {
378    if (expr1 == expr2) {
379        return createZeroes(expr1->getType());
380    } else if (isa<Ones>(expr1)) {
381        return createNot(expr2);
382    } else if (isa<Zeroes>(expr1)){
383        return expr2;
384    } else if (isa<Ones>(expr2)) {
385        return createNot(expr1);
386    } else if (isa<Zeroes>(expr2)){
387        return expr1;
388    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
389        if (Not * not2 = dyn_cast<Not>(expr2)) {
390            return createXor(not1->getOperand(0), not2->getOperand(0), prefix);
391        }
392    }
[4695]393    if (expr1 > expr2) {
[4622]394        std::swap(expr1, expr2);
395    }
[5202]396    MAKE_NAMED_BINARY(createXor, TypeId::Xor, prefix, expr1, expr2);
[4622]397    return result;
398}
399
[5217]400PabloAST * PabloBuilder::createAdd(PabloAST * expr1, PabloAST * expr2) {
401    if (isa<Integer>(expr1) && isa<Integer>(expr2)) {
402        return getInteger(cast<Integer>(expr1)->value() + cast<Integer>(expr2)->value());
[5227]403    } else if (isa<Integer>(expr1)) {
404        if (cast<Integer>(expr1)->value() == 0) {
405            return expr2;
406        }
407    } else if (isa<Integer>(expr2)) {
408        if (cast<Integer>(expr2)->value() == 0) {
409            return expr1;
410        }
[5217]411    }
412    MAKE_BINARY(createAdd, TypeId::Add, expr1, expr2);
413    return result;
414}
415
416PabloAST * PabloBuilder::createSubtract(PabloAST * expr1, PabloAST * expr2) {
417    if (isa<Integer>(expr1) && isa<Integer>(expr2)) {
418        return getInteger(cast<Integer>(expr1)->value() - cast<Integer>(expr2)->value());
[5227]419    } else if (isa<Integer>(expr1)) {
420        if (cast<Integer>(expr1)->value() == 0) {
421            return expr2;
422        }
423    } else if (isa<Integer>(expr2)) {
424        if (cast<Integer>(expr2)->value() == 0) {
425            return expr1;
426        }
[5217]427    }
428    MAKE_BINARY(createSubtract, TypeId::Subtract, expr1, expr2);
429    return result;
430}
431
[5227]432PabloAST * PabloBuilder::createLessThan(PabloAST * expr1, PabloAST * expr2) {
[5217]433    if (isa<Integer>(expr1) && isa<Integer>(expr2)) {
[5227]434        return getInteger(cast<Integer>(expr1)->value() < cast<Integer>(expr2)->value() ? 1 : 0);
[5217]435    }
[5227]436    MAKE_BINARY(createLessThan, TypeId::LessThan, expr1, expr2);
[5217]437    return result;
438}
439
[5023]440PabloAST * PabloBuilder::createInFile(PabloAST * expr) {
[5202]441    MAKE_UNARY(createInFile, TypeId::InFile, expr);
[5023]442    return result;
443}
444
[5202]445PabloAST * PabloBuilder::createInFile(PabloAST * expr, const std::string & prefix) {
446    MAKE_NAMED_UNARY(createInFile, TypeId::InFile, prefix, expr);
[5023]447    return result;
448}
[5042]449
450PabloAST * PabloBuilder::createAtEOF(PabloAST * expr) {
[5202]451    MAKE_UNARY(createAtEOF, TypeId::AtEOF, expr);
[4602]452    return result;
[4443]453}
454
[5202]455PabloAST * PabloBuilder::createAtEOF(PabloAST * expr, const std::string & prefix) {
456    MAKE_NAMED_UNARY(createAtEOF, TypeId::AtEOF, prefix, expr);
[5042]457    return result;
458}
459
460PabloAST * PabloBuilder::createMatchStar(PabloAST * marker, PabloAST * charclass) {
[5202]461    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
462        return marker;
463    }
464    MAKE_BINARY(createMatchStar, TypeId::MatchStar, marker, charclass);
465    return result;
[5042]466}
467
[5202]468PabloAST * PabloBuilder::createMatchStar(PabloAST * marker, PabloAST * charclass, const std::string & prefix) {
469    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
470        return marker;
471    }
472    MAKE_NAMED_BINARY(createMatchStar, TypeId::MatchStar, prefix, marker, charclass);
[4622]473    return result;
474}
475
[4443]476PabloAST * PabloBuilder::createScanThru(PabloAST * from, PabloAST * thru) {
[5202]477    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {
478        return from;
479    }
480    MAKE_BINARY(createScanThru, TypeId::ScanThru, from, thru);
[4602]481    return result;
[4443]482}
483
[5202]484PabloAST * PabloBuilder::createScanThru(PabloAST * from, PabloAST * thru, const std::string & prefix) {
485    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {
486        return from;
487    }
488    MAKE_NAMED_BINARY(createScanThru, TypeId::ScanThru, prefix, from, thru);
[4622]489    return result;
490}
491
492
[4602]493PabloAST * PabloBuilder::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr) {
[5202]494    if (isa<Ones>(condition)) {
495        return trueExpr;
496    } else if (isa<Zeroes>(condition)){
497        return falseExpr;
498    } else if (isa<Ones>(trueExpr)) {
499        return createOr(condition, falseExpr);
500    } else if (isa<Zeroes>(trueExpr)){
501        return createAnd(createNot(condition), falseExpr);
502    } else if (isa<Ones>(falseExpr)) {
503        return createOr(createNot(condition), trueExpr);
504    } else if (isa<Zeroes>(falseExpr)){
505        return createAnd(condition, trueExpr);
506    } else if (equals(trueExpr, falseExpr)) {
507        return trueExpr;
508    } else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getOperand(0), falseExpr)) {
509        return createXor(condition, falseExpr);
510    } else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getOperand(0))){
511        return createXor(condition, trueExpr);
512    }
513    MAKE_TERNARY(createSel, TypeId::Sel, condition, trueExpr, falseExpr);
[4602]514    return result;
[4443]515}
516
[5202]517PabloAST * PabloBuilder::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr, const std::string & prefix) {
518    if (isa<Ones>(condition)) {
519        return trueExpr;
520    } else if (isa<Zeroes>(condition)){
521        return falseExpr;
522    } else if (isa<Ones>(trueExpr)) {
523        return createOr(condition, falseExpr);
524    } else if (isa<Zeroes>(trueExpr)){
525        return createAnd(createNot(condition), falseExpr);
526    } else if (isa<Ones>(falseExpr)) {
527        return createOr(createNot(condition), trueExpr);
528    } else if (isa<Zeroes>(falseExpr)){
529        return createAnd(condition, trueExpr);
530    } else if (equals(trueExpr, falseExpr)) {
531        return trueExpr;
532    } else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getOperand(0), falseExpr)) {
533        return createXor(condition, falseExpr);
534    } else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getOperand(0))){
535        return createXor(condition, trueExpr);
536    }
537    MAKE_NAMED_TERNARY(createSel, TypeId::Sel, prefix, condition, trueExpr, falseExpr);
[4622]538    return result;
[4443]539}
[4622]540
[4718]541}
Note: See TracBrowser for help on using the repository browser.