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

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

Merged PabloFunction? and PabloKernel? classes. Updated projects where necessary.

File size: 20.4 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
[5217]101inline void printType(const Type * type, raw_string_ostream & out) {
102    if (auto st = dyn_cast<IDISA::StreamType>(type)) {
103        out << "<" << st->getNumElements() << " x s" << st->getFieldWidth() << ">";
104    } else {
105        type->print(out);
106    }
107}
108
[5202]109using TypeId = PabloAST::ClassTypeId;
110
[4692]111Call * PabloBuilder::createCall(Prototype * prototype, const std::vector<PabloAST *> & args) {
112    if (prototype == nullptr) {
113        throw std::runtime_error("Call object cannot be created with a Null prototype!");
114    }
[4681]115    if (args.size() != cast<Prototype>(prototype)->getNumOfParameters()) {
116        throw std::runtime_error("Invalid number of arguments passed into Call object!");
117    }
[5202]118    MAKE_VARIABLE(createCall, TypeId::Call, prototype->getName(), args, prototype);
[4602]119    return cast<Call>(result);
[4443]120}
121
122PabloAST * PabloBuilder::createAdvance(PabloAST * expr, PabloAST * shiftAmount) {
[5202]123    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
124        return expr;
125    }
126    MAKE_BINARY(createAdvance, TypeId::Advance, expr, shiftAmount);
[4602]127    return result;
[4443]128}
129
[5202]130PabloAST * PabloBuilder::createAdvance(PabloAST * expr, PabloAST * shiftAmount, const std::string & prefix) {
131    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
132        return expr;
133    }
134    MAKE_NAMED_BINARY(createAdvance, TypeId::Advance, prefix, expr, shiftAmount);
[4603]135    return result;
136}
137
[5202]138Extract * PabloBuilder::createExtract(PabloAST * value, not_null<PabloAST *> index) {
139    MAKE_BINARY(createExtract, TypeId::Extract, value, index);
140    return cast<Extract>(result);
141}
142
143Extract * PabloBuilder::createExtract(PabloAST * value, not_null<PabloAST *> index, const std::string & prefix) {
144    MAKE_NAMED_BINARY(createExtract, TypeId::Extract, prefix, value, index);
145    return cast<Extract>(result);
146}
147
[4959]148PabloAST * PabloBuilder::createLookahead(PabloAST * expr, PabloAST * shiftAmount) {
[5202]149    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
150        return expr;
151    }
152    MAKE_BINARY(createLookahead, TypeId::Lookahead, expr, shiftAmount);
[4959]153    return result;
154}
155
[5202]156PabloAST * PabloBuilder::createLookahead(PabloAST * expr, PabloAST * shiftAmount, const std::string & prefix) {
157    if (isa<Zeroes>(expr) || cast<Integer>(shiftAmount)->value() == 0) {
158        return expr;
159    }
160    MAKE_NAMED_BINARY(createLookahead, TypeId::Lookahead, prefix, expr, shiftAmount);
[4959]161    return result;
162}
163
[4443]164PabloAST * PabloBuilder::createNot(PabloAST * expr) {
[5202]165    if (isa<Ones>(expr)) {
166        return createZeroes(expr->getType());
167    }
168    else if (isa<Zeroes>(expr)){
169        return createOnes(expr->getType());
170    }
171    else if (Not * not1 = dyn_cast<Not>(expr)) {
172        return not1->getOperand(0);
173    }
174    MAKE_UNARY(createNot, TypeId::Not, expr);
[4602]175    return result;
[4443]176}
177
[5202]178PabloAST * PabloBuilder::createNot(PabloAST * expr, const std::string & prefix) {
179    if (isa<Ones>(expr)) {
180        return createZeroes(expr->getType());
181    }
182    else if (isa<Zeroes>(expr)){
183        return createOnes(expr->getType());
184    }
185    else if (Not * not1 = dyn_cast<Not>(expr)) {
186        return not1->getOperand(0);
187    }
188    MAKE_NAMED_UNARY(createNot, TypeId::Not, prefix, expr);
[4622]189    return result;
190}
191
[5202]192PabloAST * PabloBuilder::createCount(PabloAST * expr) {
193    MAKE_UNARY(createCount, TypeId::Count, expr);
194    return result;
195}
196
197PabloAST * PabloBuilder::createCount(PabloAST * expr, const std::string & prefix) {
198    MAKE_NAMED_UNARY(createCount, TypeId::Count, prefix, expr);
199    return result;
200}
201
202PabloAST * PabloBuilder::createAssign(PabloAST * const variable, PabloAST * const value) {
[5217]203    if (variable->getType() != value->getType()) {
204        std::string tmp;
205        raw_string_ostream out(tmp);
206        out << "Cannot assign ";
207        value->print(out);
208        out << " to ";
209        variable->print(out);
210        out << ": type of ";
211        value->print(out);
212        out << " ";
213        printType(value->getType(), out);
214        out << " does not match ";
215        variable->print(out);
216        out << " ";
217        printType(variable->getType(), out);
218        throw std::runtime_error(out.str());
219    }
220    return mPb->createAssign(variable, value);
[5202]221}
222
[4443]223PabloAST * PabloBuilder::createAnd(PabloAST * expr1, PabloAST * expr2) {
[5202]224    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
225        return expr2;
226    } else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
227        return expr1;
228    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
229        if (Not * not2 = dyn_cast<Not>(expr2)) {
230            return createNot(createOr(not1->getOperand(0), not2->getOperand(0)));
231        } else if (equals(not1->getOperand(0), expr2)) {
232            return createZeroes(expr1->getType());
233        }
234    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
235        if (equals(expr1, not2->getOperand(0))) {
236            return createZeroes(expr1->getType());
237        }
238    } else if (Or * or1 = isBinary<Or>(expr1)) {
239        if (equals(or1->getOperand(0), expr2) || equals(or1->getOperand(1), expr2)) {
240            return expr2;
241        }
242    } else if (Or * or2 = isBinary<Or>(expr2)) {
243        if (equals(or2->getOperand(0), expr1) || equals(or2->getOperand(1), expr1)) {
244            return expr1;
245        }
246    }
247    if (expr1 > expr2) {
[4443]248        std::swap(expr1, expr2);
249    }
[5202]250    MAKE_BINARY(createAnd, TypeId::And, expr1, expr2);
[4602]251    return result;
[4443]252}
253
[5202]254PabloAST * PabloBuilder::createAnd(PabloAST * expr1, PabloAST * expr2, const std::string & prefix) {
255    if (isa<Zeroes>(expr2) || isa<Ones>(expr1)) {
256        return expr2;
257    } else if (isa<Zeroes>(expr1) || isa<Ones>(expr2) || equals(expr1, expr2)){
258        return expr1;
259    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
260        if (Not * not2 = dyn_cast<Not>(expr2)) {
261            return createNot(createOr(not1->getOperand(0), not2->getOperand(0)), prefix);
262        } else if (equals(not1->getOperand(0), expr2)) {
263            return createZeroes(expr1->getType());
264        }
265    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
266        if (equals(expr1, not2->getOperand(0))) {
267            return createZeroes(expr1->getType());
268        }
269    } else if (Or * or1 = isBinary<Or>(expr1)) {
270        if (equals(or1->getOperand(0), expr2) || equals(or1->getOperand(1), expr2)) {
271            return expr2;
272        }
273    } else if (Or * or2 = isBinary<Or>(expr2)) {
274        if (equals(or2->getOperand(0), expr1) || equals(or2->getOperand(1), expr1)) {
275            return expr1;
276        }
277    }
278    if (expr1 > expr2) {
[4622]279        std::swap(expr1, expr2);
280    }
[5202]281    MAKE_NAMED_BINARY(createAnd, TypeId::And, prefix, expr1, expr2);
[4622]282    return result;
283}
284
[4443]285PabloAST * PabloBuilder::createOr(PabloAST * expr1, PabloAST * expr2) {
[5202]286    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
287        return expr2;
288    }
289    if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
290        return expr1;
291    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
292        // ¬a√b = ¬¬(¬a √ b) = ¬(a ∧ ¬b)
293        return createNot(createAnd(not1->getOperand(0), createNot(expr2)));
294    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
295        // a√¬b = ¬¬(¬b √ a) = ¬(b ∧ ¬a)
296        return createNot(createAnd(not2->getOperand(0), createNot(expr1)));
297    } else if (equals(expr1, expr2)) {
298        return expr1;
299    } else if (And * and1 = isBinary<And>(expr1)) {
300        PabloAST * const expr1a = and1->getOperand(0);
301        PabloAST * const expr1b = and1->getOperand(1);
302        if (And * and2 = isBinary<And>(expr2)) {
303            PabloAST * const expr2a = and2->getOperand(0);
304            PabloAST * const expr2b = and2->getOperand(1);
305            //These optimizations factor out common components that can occur when sets are formed by union
306            //(e.g., union of [a-z] and [A-Z].
307            if (equals(expr1a, expr2a)) {
308                return createAnd(expr1a, createOr(expr1b, expr2b));
309            } else if (equals(expr1b, expr2b)) {
310                return createAnd(expr1b, createOr(expr1a, expr2a));
311            } else if (equals(expr1a, expr2b)) {
312                return createAnd(expr1a, createOr(expr1b, expr2a));
313            } else if (equals(expr1b, expr2a)) {
314                return createAnd(expr1b, createOr(expr1a, expr2b));
315            }
316        } else if (equals(expr1a, expr2) || equals(expr1b, expr2)) {
317            // (a ∧ b) √ a = a
318            return expr2;
319        }
320    } else if (And * and2 = isBinary<And>(expr2)) {
321        if (equals(and2->getOperand(0), expr1) || equals(and2->getOperand(1), expr1)) {
322            return expr1;
323        }
324    }
[4695]325    if (expr1 > expr2) {
[4443]326        std::swap(expr1, expr2);
327    }
[5202]328    MAKE_BINARY(createOr, TypeId::Or, expr1, expr2);
[4602]329    return result;
[4443]330}
331
[5202]332PabloAST * PabloBuilder::createOr(PabloAST * expr1, PabloAST * expr2, const std::string & prefix) {
333    if (isa<Zeroes>(expr1) || isa<Ones>(expr2)){
334        return expr2;
335    }
336    if (isa<Zeroes>(expr2) || isa<Ones>(expr1) || equals(expr1, expr2)) {
337        return expr1;
338    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
339        // ¬a√b = ¬¬(¬a √ b) = ¬(a ∧ ¬b)
340        return createNot(createAnd(not1->getOperand(0), createNot(expr2)), prefix);
341    } else if (Not * not2 = dyn_cast<Not>(expr2)) {
342        // a√¬b = ¬¬(¬b √ a) = ¬(b ∧ ¬a)
343        return createNot(createAnd(not2->getOperand(0), createNot(expr1)), prefix);
344    } else if (equals(expr1, expr2)) {
345        return expr1;
346    } else if (And * and1 = isBinary<And>(expr1)) {
347        PabloAST * const expr1a = and1->getOperand(0);
348        PabloAST * const expr1b = and1->getOperand(1);
349        if (And * and2 = isBinary<And>(expr2)) {
350            PabloAST * const expr2a = and2->getOperand(0);
351            PabloAST * const expr2b = and2->getOperand(1);
352            //These optimizations factor out common components that can occur when sets are formed by union
353            //(e.g., union of [a-z] and [A-Z].
354            if (equals(expr1a, expr2a)) {
355                return createAnd(expr1a, createOr(expr1b, expr2b), prefix);
356            } else if (equals(expr1b, expr2b)) {
357                return createAnd(expr1b, createOr(expr1a, expr2a), prefix);
358            } else if (equals(expr1a, expr2b)) {
359                return createAnd(expr1a, createOr(expr1b, expr2a), prefix);
360            } else if (equals(expr1b, expr2a)) {
361                return createAnd(expr1b, createOr(expr1a, expr2b), prefix);
362            }
363        } else if (equals(expr1a, expr2) || equals(expr1b, expr2)) {
364            // (a ∧ b) √ a = a
365            return expr2;
366        }
367    } else if (And * and2 = isBinary<And>(expr2)) {
368        if (equals(and2->getOperand(0), expr1) || equals(and2->getOperand(1), expr1)) {
369            return expr1;
370        }
371    }
[4695]372    if (expr1 > expr2) {
[4622]373        std::swap(expr1, expr2);
374    }
[5202]375    MAKE_NAMED_BINARY(createOr, TypeId::Or, prefix, expr1, expr2);
[4622]376    return result;
377}
378
[4443]379PabloAST * PabloBuilder::createXor(PabloAST * expr1, PabloAST * expr2) {
[5202]380    if (expr1 == expr2) {
381        return createZeroes(expr1->getType());
382    } else if (isa<Ones>(expr1)) {
383        return createNot(expr2);
384    } else if (isa<Zeroes>(expr1)){
385        return expr2;
386    } else if (isa<Ones>(expr2)) {
387        return createNot(expr1);
388    } else if (isa<Zeroes>(expr2)){
389        return expr1;
390    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
391        if (Not * not2 = dyn_cast<Not>(expr2)) {
392            return createXor(not1->getOperand(0), not2->getOperand(0));
393        }
394    }
[4695]395    if (expr1 > expr2) {
[4443]396        std::swap(expr1, expr2);
397    }
[5202]398    MAKE_BINARY(createXor, TypeId::Xor, expr1, expr2);
[4602]399    return result;
[4443]400}
401
[5202]402PabloAST * PabloBuilder::createXor(PabloAST * expr1, PabloAST * expr2, const std::string & prefix) {
403    if (expr1 == expr2) {
404        return createZeroes(expr1->getType());
405    } else if (isa<Ones>(expr1)) {
406        return createNot(expr2);
407    } else if (isa<Zeroes>(expr1)){
408        return expr2;
409    } else if (isa<Ones>(expr2)) {
410        return createNot(expr1);
411    } else if (isa<Zeroes>(expr2)){
412        return expr1;
413    } else if (Not * not1 = dyn_cast<Not>(expr1)) {
414        if (Not * not2 = dyn_cast<Not>(expr2)) {
415            return createXor(not1->getOperand(0), not2->getOperand(0), prefix);
416        }
417    }
[4695]418    if (expr1 > expr2) {
[4622]419        std::swap(expr1, expr2);
420    }
[5202]421    MAKE_NAMED_BINARY(createXor, TypeId::Xor, prefix, expr1, expr2);
[4622]422    return result;
423}
424
[5217]425PabloAST * PabloBuilder::createAdd(PabloAST * expr1, PabloAST * expr2) {
426    if (isa<Integer>(expr1) && isa<Integer>(expr2)) {
427        return getInteger(cast<Integer>(expr1)->value() + cast<Integer>(expr2)->value());
428    }
429    MAKE_BINARY(createAdd, TypeId::Add, expr1, expr2);
430    return result;
431}
432
433PabloAST * PabloBuilder::createAdd(PabloAST * expr1, PabloAST * expr2, const std::string & prefix) {
434    if (isa<Integer>(expr1) && isa<Integer>(expr2)) {
435        return getInteger(cast<Integer>(expr1)->value() + cast<Integer>(expr2)->value());
436    }
437    MAKE_NAMED_BINARY(createAdd, TypeId::Add, prefix, expr1, expr2);
438    return result;
439}
440
441PabloAST * PabloBuilder::createSubtract(PabloAST * expr1, PabloAST * expr2) {
442    if (isa<Integer>(expr1) && isa<Integer>(expr2)) {
443        return getInteger(cast<Integer>(expr1)->value() - cast<Integer>(expr2)->value());
444    }
445    MAKE_BINARY(createSubtract, TypeId::Subtract, expr1, expr2);
446    return result;
447}
448
449PabloAST * PabloBuilder::createSubtract(PabloAST * expr1, PabloAST * expr2, const std::string & prefix) {
450    if (isa<Integer>(expr1) && isa<Integer>(expr2)) {
451        return getInteger(cast<Integer>(expr1)->value() - cast<Integer>(expr2)->value());
452    }
453    MAKE_NAMED_BINARY(createSubtract, TypeId::Subtract, prefix, expr1, expr2);
454    return result;
455}
456
[5023]457PabloAST * PabloBuilder::createInFile(PabloAST * expr) {
[5202]458    MAKE_UNARY(createInFile, TypeId::InFile, expr);
[5023]459    return result;
460}
461
[5202]462PabloAST * PabloBuilder::createInFile(PabloAST * expr, const std::string & prefix) {
463    MAKE_NAMED_UNARY(createInFile, TypeId::InFile, prefix, expr);
[5023]464    return result;
465}
[5042]466
467PabloAST * PabloBuilder::createAtEOF(PabloAST * expr) {
[5202]468    MAKE_UNARY(createAtEOF, TypeId::AtEOF, expr);
[4602]469    return result;
[4443]470}
471
[5202]472PabloAST * PabloBuilder::createAtEOF(PabloAST * expr, const std::string & prefix) {
473    MAKE_NAMED_UNARY(createAtEOF, TypeId::AtEOF, prefix, expr);
[5042]474    return result;
475}
476
477PabloAST * PabloBuilder::createMatchStar(PabloAST * marker, PabloAST * charclass) {
[5202]478    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
479        return marker;
480    }
481    MAKE_BINARY(createMatchStar, TypeId::MatchStar, marker, charclass);
482    return result;
[5042]483}
484
[5202]485PabloAST * PabloBuilder::createMatchStar(PabloAST * marker, PabloAST * charclass, const std::string & prefix) {
486    if (isa<Zeroes>(marker) || isa<Zeroes>(charclass)) {
487        return marker;
488    }
489    MAKE_NAMED_BINARY(createMatchStar, TypeId::MatchStar, prefix, marker, charclass);
[4622]490    return result;
491}
492
[4443]493PabloAST * PabloBuilder::createScanThru(PabloAST * from, PabloAST * thru) {
[5202]494    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {
495        return from;
496    }
497    MAKE_BINARY(createScanThru, TypeId::ScanThru, from, thru);
[4602]498    return result;
[4443]499}
500
[5202]501PabloAST * PabloBuilder::createScanThru(PabloAST * from, PabloAST * thru, const std::string & prefix) {
502    if (isa<Zeroes>(from) || isa<Zeroes>(thru)) {
503        return from;
504    }
505    MAKE_NAMED_BINARY(createScanThru, TypeId::ScanThru, prefix, from, thru);
[4622]506    return result;
507}
508
509
[4602]510PabloAST * PabloBuilder::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr) {
[5202]511    if (isa<Ones>(condition)) {
512        return trueExpr;
513    } else if (isa<Zeroes>(condition)){
514        return falseExpr;
515    } else if (isa<Ones>(trueExpr)) {
516        return createOr(condition, falseExpr);
517    } else if (isa<Zeroes>(trueExpr)){
518        return createAnd(createNot(condition), falseExpr);
519    } else if (isa<Ones>(falseExpr)) {
520        return createOr(createNot(condition), trueExpr);
521    } else if (isa<Zeroes>(falseExpr)){
522        return createAnd(condition, trueExpr);
523    } else if (equals(trueExpr, falseExpr)) {
524        return trueExpr;
525    } else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getOperand(0), falseExpr)) {
526        return createXor(condition, falseExpr);
527    } else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getOperand(0))){
528        return createXor(condition, trueExpr);
529    }
530    MAKE_TERNARY(createSel, TypeId::Sel, condition, trueExpr, falseExpr);
[4602]531    return result;
[4443]532}
533
[5202]534PabloAST * PabloBuilder::createSel(PabloAST * condition, PabloAST * trueExpr, PabloAST * falseExpr, const std::string & prefix) {
535    if (isa<Ones>(condition)) {
536        return trueExpr;
537    } else if (isa<Zeroes>(condition)){
538        return falseExpr;
539    } else if (isa<Ones>(trueExpr)) {
540        return createOr(condition, falseExpr);
541    } else if (isa<Zeroes>(trueExpr)){
542        return createAnd(createNot(condition), falseExpr);
543    } else if (isa<Ones>(falseExpr)) {
544        return createOr(createNot(condition), trueExpr);
545    } else if (isa<Zeroes>(falseExpr)){
546        return createAnd(condition, trueExpr);
547    } else if (equals(trueExpr, falseExpr)) {
548        return trueExpr;
549    } else if (isa<Not>(trueExpr) && equals(cast<Not>(trueExpr)->getOperand(0), falseExpr)) {
550        return createXor(condition, falseExpr);
551    } else if (isa<Not>(falseExpr) && equals(trueExpr, cast<Not>(falseExpr)->getOperand(0))){
552        return createXor(condition, trueExpr);
553    }
554    MAKE_NAMED_TERNARY(createSel, TypeId::Sel, prefix, condition, trueExpr, falseExpr);
[4622]555    return result;
[4443]556}
[4622]557
[4718]558}
Note: See TracBrowser for help on using the repository browser.