1 // Copyright (C) 2009 Free Software Foundation, Inc.
2 // Contributed by Jan Sjodin <jan.sjodin@amd.com>.
4 // This file is part of the Polyhedral Compilation Package Library (libpcp).
6 // Libpcp is free software; you can redistribute it and/or modify it
7 // under the terms of the GNU Lesser General Public License as published by
8 // the Free Software Foundation; either version 2.1 of the License, or
9 // (at your option) any later version.
11 // Libpcp is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with libpcp; see the file COPYING.LIB. If not, write to the
18 // Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 // MA 02110-1301, USA.
21 // As a special exception, if you link this library with other files, some
22 // of which are compiled with GCC, to produce an executable, this library
23 // does not by itself cause the resulting executable to be covered by the
24 // GNU General Public License. This exception does not however invalidate
25 // any other reasons why the executable file might be covered by the GNU
26 // General Public License.
28 #include "pcp_error.h"
29 #include "pcp_stack.h"
30 #include "pcp_expr_canonicalizer.h"
31 #include "pcp_emitter.h"
33 // Creates an expression:
34 // +(*(0, iv_0), ... *(0, iv_n), *(0, param_0), ..., *(0, param_m), 0)
36 PcpScalarContextStack::createBaseExpr()
38 int size
= this->getSize();
39 PcpArithBuilder
* builder
= new PcpArithBuilder();
40 builder
->setOperator(PcpArithOperator::add());
41 for(int i
= 0; i
< size
; i
++)
43 PcpExpr
* scalar
= this->peek(i
);
44 PcpArith
* mulZeroScalar
= PcpArith::pcpArithBinaryCreate(PcpArithOperator::multiply(),
47 builder
->addOperand(mulZeroScalar
);
49 builder
->addOperand(new PcpConstant(0));
50 PcpArith
* zeros
= builder
->createArith();
52 // printf("Zero expr: %s\n", PcpEmitter::pcpExprToString(zeros));
56 PcpScalarContextStack::PcpScalarContextStack(PcpScop
* scop
) : PcpListStack
<PcpExpr
*>()
58 PcpIterator
<PcpParameter
*>* iter
= scop
->getParametersIterator();
59 for(;iter
->hasNext(); iter
->next())
61 this->push(iter
->get());
67 PcpExprCanonicalizer::setScalarOrder(PcpScalarOrder
* scalarOrder
)
69 this->scalarOrder
= scalarOrder
;
73 PcpExprCanonicalizer::getScalarOrder()
75 return this->scalarOrder
;
79 PcpExprCanonicalizer::setScalarContextStack(PcpScalarContextStack
* scalarContextStack
)
81 this->scalarContextStack
= scalarContextStack
;
84 PcpScalarContextStack
*
85 PcpExprCanonicalizer::getScalarContextStack()
87 return this->scalarContextStack
;
92 PcpExprCanonicalizer::stripMultiplier(PcpExpr
* expr
)
94 pcpAssert(!expr
->isArith() || expr
->toArith()->getOperator().isMultiply());
95 return expr
->isArith() ? expr
->toArith()->getOperand(1) : expr
;
99 PcpExprCanonicalizer::equal(PcpExpr
* expr1
, PcpExpr
* expr2
)
101 return this->getScalarOrder()->equal(this->stripMultiplier(expr1
),
102 this->stripMultiplier(expr2
));
106 PcpExprCanonicalizer::less(PcpExpr
* expr1
, PcpExpr
* expr2
)
108 return this->getScalarOrder()->less(this->stripMultiplier(expr1
),
109 this->stripMultiplier(expr2
));
113 PcpExprCanonicalizer::negateConstant(PcpConstant
* constant
)
115 return new PcpConstant(-(constant
->getValue()));
119 PcpExprCanonicalizer::addConstants(PcpConstant
* constant1
,
120 PcpConstant
* constant2
)
122 return new PcpConstant(constant1
->getValue() +
123 constant2
->getValue());
127 PcpExprCanonicalizer::addConstants(PcpConstant
* constant1
,
130 return new PcpConstant(constant1
->getValue() +
135 PcpExprCanonicalizer::addConstants(int constant1
,
138 return new PcpConstant(constant1
+ constant2
);
142 PcpExprCanonicalizer::addTerms(PcpExpr
* expr1
, PcpExpr
* expr2
)
145 if(expr1
->isConstant())
147 result
= this->addConstants(expr1
->toConstant(), expr2
->toConstant());
149 else if(expr1
->isArith() && !expr2
->isArith())
150 result
= addTerms(expr2
, expr1
);
151 // else if(!expr1->isArith())
153 // pcpAssert(false); // This case is no longer used since we always create *(1,x)
154 // PcpExpr* multiplier = NULL;
155 // if(!expr2->isArith())
157 // multiplier = this->addConstants(1,1);
160 // multiplier = this->addConstants(expr2->toArith()->getOperand(0)->toConstant(), 1);
161 // result = PcpArith::pcpArithBinaryCreate(PcpArithOperator::multiply(),
165 else // Iv is multiply
167 PcpExpr
* multiplier
=
168 this->addConstants(expr1
->toArith()->getOperand(0)->toConstant(),
169 expr2
->toArith()->getOperand(0)->toConstant());
170 result
= PcpArith::pcpArithBinaryCreate(PcpArithOperator::multiply(),
172 expr1
->toArith()->getOperand(1));
178 // Merges normalized arithmetic expressions, where scalars are also
179 // wrapped with a + operator, e.g. +(42).
181 PcpExprCanonicalizer::addSums(PcpArith
* sum1
, PcpArith
* sum2
)
183 pcpAssert(sum1
!= NULL
&& sum2
!= NULL
);
184 pcpAssert(sum1
->getOperator().isAdd());
185 pcpAssert(sum2
->getOperator().isAdd());
187 // printf(" Sum1: %s\n", PcpEmitter::pcpArithToString(sum1));
188 // printf(" Sum2: %s\n", PcpEmitter::pcpArithToString(sum2));
190 PcpArithBuilder
* builder
= new PcpArithBuilder();
191 builder
->setOperator(PcpArithOperator::add());
193 PcpIterator
<PcpExpr
*>* iter1
= sum1
->getOperandsIterator();
194 PcpIterator
<PcpExpr
*>* iter2
= sum2
->getOperandsIterator();
196 while(iter1
->hasNext() || iter2
->hasNext())
198 PcpExpr
* newOperand
= NULL
;
199 if(!iter1
->hasNext())
201 newOperand
= iter2
->get();
204 else if(!iter2
->hasNext())
206 newOperand
= iter1
->get();
211 PcpExpr
* expr1
= iter1
->get();
212 PcpExpr
* expr2
= iter2
->get();
213 // printf("Expr1: %s\n", PcpEmitter::pcpExprToString(expr1));
214 // printf("Expr2: %s\n", PcpEmitter::pcpExprToString(expr2));
215 if(this->equal(expr1
, expr2
))
217 newOperand
= this->addTerms(expr1
, expr2
);
220 // printf("Equal: add them\n");
222 else if(this->less(expr1
, expr2
))
224 newOperand
= iter1
->get();
226 // printf("Less: Push expr 1\n");
230 newOperand
= iter2
->get();
232 // printf("Greater: Push expr 2\n");
236 // Add 0 to make expr complete (commented out expression)
237 if(newOperand
!= NULL
) // &&
238 //(!newOperand->isConstant() ||
239 //newOperand->toConstant()->getValue() != 0))
240 builder
->addOperand(newOperand
);
243 PcpArith
* result
= builder
->createArith();
248 // printf("Sum Result: %s\n", PcpEmitter::pcpArithToString(result));
253 PcpExprCanonicalizer::createUnaryArith(PcpArithOperator oper
, PcpExpr
* expr
)
255 PcpArithBuilder
* builder
= new PcpArithBuilder();
257 builder
->setOperator(oper
);
258 builder
->addOperand(expr
);
260 PcpArith
* result
= builder
->createArith();
266 PcpExprCanonicalizer::createUnaryPlus(PcpExpr
* expr
)
268 return createUnaryArith(PcpArithOperator::add(), expr
);
272 PcpExprCanonicalizer::createUnaryMinus(PcpExpr
* expr
)
274 return createUnaryArith(PcpArithOperator::subtract(), expr
);
278 PcpExprCanonicalizer::getCanonicalConstant(PcpArith
* expr
)
280 return (expr
->getOperator().isAdd() && expr
->getNumOperands() == 1 &&
281 expr
->getOperand(0)->isConstant())
282 ? expr
->getOperand(0)->toConstant()
287 PcpExprCanonicalizer::multiplyConstants(PcpConstant
* constant1
, PcpConstant
* constant2
)
289 return new PcpConstant(constant1
->getValue() * constant2
->getValue());
293 PcpExprCanonicalizer::multiplyConstMul(PcpConstant
* multiplier
, PcpArith
* multiply
)
295 pcpAssert(multiply
->getOperator().isMultiply());
296 PcpConstant
* constant
= multiply
->getOperand(0)->toConstant();
297 PcpConstant
* newConstant
= this->multiplyConstants(multiplier
, constant
);
298 return PcpArith::pcpArithBinaryCreate(PcpArithOperator::multiply(),
300 multiply
->getOperand(1));
304 PcpExprCanonicalizer::multiplyScalar(PcpConstant
* constant
, PcpExpr
* scalar
)
306 return PcpArith::pcpArithBinaryCreate(PcpArithOperator::multiply(),
312 PcpExprCanonicalizer::multiplyFactors(PcpConstant
* multiplier
, PcpArith
* sum
)
315 // Don't simplify anything since we want the full expressions
317 if(multiplier->getValue() == 0)
318 return this->createUnaryPlus(multiplier);
319 if(multiplier->getValue() == 1)
323 PcpIterator
<PcpExpr
*>* iter
= sum
->getOperandsIterator();
324 PcpArithBuilder
* builder
= new PcpArithBuilder();
326 builder
->setOperator(PcpArithOperator::add());
328 for(; iter
->hasNext(); iter
->next())
330 PcpExpr
* term
= iter
->get();
333 PcpArith
* newTerm
= this->multiplyConstMul(multiplier
, term
->toArith());
334 builder
->addOperand(newTerm
);
336 else if(term
->isConstant())
338 PcpConstant
* newConstant
= this->multiplyConstants(multiplier
, term
->toConstant());
339 builder
->addOperand(newConstant
);
343 PcpArith
* newTerm
= this->multiplyScalar(multiplier
, term
);
344 builder
->addOperand(newTerm
);
348 PcpArith
* result
= builder
->createArith();
354 PcpExprCanonicalizer::sameScalarBase(PcpArith
* factor1
, PcpArith
* factor2
)
356 return (factor1
->getNumOperands() == 2 &&
357 factor2
->getNumOperands() == 2 &&
358 factor1
->getOperator().isMultiply() &&
359 factor2
->getOperator().isMultiply() &&
360 factor1
->getOperand(0)->isConstant() &&
361 factor2
->getOperand(0)->isConstant() &&
362 factor1
->getOperand(1) == factor2
->getOperand(1));
366 PcpExprCanonicalizer::multiplyFactors(PcpArith
* factor1
, PcpArith
* factor2
)
368 PcpConstant
* constant1
= this->getCanonicalConstant(factor1
);
369 PcpConstant
* constant2
= this->getCanonicalConstant(factor2
);
371 pcpAssert(constant1
!= NULL
|| constant2
!= NULL
372 || sameScalarBase(factor1
, factor2
));
374 bool nonConstants
= constant1
== NULL
&& constant2
== NULL
;
375 bool factor1isConst
= constant1
!= NULL
;
376 bool factor2isConst
= constant2
!= NULL
;
378 PcpConstant
* multiplier
=
379 nonConstants
? factor1
->getOperand(0)->toConstant()
380 : factor1isConst
? constant1
383 PcpArith
* sum
= !factor2isConst
? factor2
: factor1
;
385 return this->multiplyFactors(multiplier
, sum
);
389 PcpExprCanonicalizer::negateExpr(PcpArith
* canonicalizedExpr
)
391 PcpIterator
<PcpExpr
*>* iter
= canonicalizedExpr
->getOperandsIterator();
392 PcpArithBuilder
* builder
= new PcpArithBuilder();
393 builder
->setOperator(PcpArithOperator::add());
394 for(;iter
->hasNext(); iter
->next())
396 PcpExpr
* operand
= iter
->get();
397 if(operand
->isArith())
399 PcpArith
* arith
= operand
->toArith();
400 PcpArithOperator oper
= arith
->getOperator();
401 pcpAssert(oper
.isMultiply());
402 builder
->addOperand(PcpArith::pcpArithBinaryCreate(PcpArithOperator::multiply(),
403 this->negateConstant(arith
->getOperand(0)->toConstant()),
404 arith
->getOperand(1)));
406 else if(operand
->isConstant())
407 builder
->addOperand(this->negateConstant(operand
->toConstant()));
409 builder
->addOperand(PcpArith::pcpArithBinaryCreate(PcpArithOperator::multiply(),
414 PcpArith
* result
= builder
->createArith();
421 PcpExprCanonicalizer::canonicalizeExpr(PcpExpr
* expr
)
424 return createUnaryPlus(expr
->isConstant()
426 : PcpArith::pcpArithBinaryCreate(PcpArithOperator::multiply(),
429 PcpArith
* arith
= expr
->toArith();
430 PcpArithOperator oper
= arith
->getOperator();
432 if(arith
->getNumOperands() == 1)
433 return oper
.isSubtract() ? negateExpr(canonicalizeExpr(arith
->getOperand(0)))
435 if(oper
.isSubtract() && arith
->getNumOperands() == 2)
437 PcpArith
* lhs
= this->negateExpr(this->canonicalizeExpr(arith
->getOperand(1)));
438 return addSums(this->canonicalizeExpr(arith
->getOperand(0)), lhs
);
442 PcpIterator
<PcpExpr
*>* iter
= arith
->getOperandsIterator();
443 PcpArith
* result
= this->canonicalizeExpr(iter
->get());
446 for(;iter
->hasNext();iter
->next())
448 PcpExpr
* operand
= iter
->get();
449 PcpArith
* canonicalizedOperand
= this->canonicalizeExpr(operand
);
451 result
= this->addSums(canonicalizedOperand
, result
);
452 else if(oper
.isMultiply())
453 result
= this->multiplyFactors(canonicalizedOperand
, result
);
462 PcpExprCanonicalizer::canonicalizeExprWithBase(PcpExpr
* expr
)
464 PcpExpr
* base
= this->getCanonicalizationBase();
466 expr
= PcpArith::pcpArithBinaryCreate(PcpArithOperator::add(), base
, expr
);
467 return canonicalizeExpr(expr
);
471 PcpExprCanonicalizer::canonicalizeCompare(PcpCompare
* compare
)
473 PcpCompareOperator oper
= compare
->getOperator();
474 PcpExpr
* lhs
= compare
->getLhs();
475 PcpExpr
* rhs
= compare
->getRhs();
477 // printf("Lhs: %s\n", PcpEmitter::pcpExprToString(lhs));
478 // printf("Rhs: %s\n", PcpEmitter::pcpExprToString(rhs));
480 PcpArith
* canonLhs
= canonicalizeExprWithBase(lhs
);
481 PcpArith
* canonRhs
= canonicalizeExprWithBase(rhs
);
483 // printf("canonLhs: %s\n", PcpEmitter::pcpExprToString(canonLhs));
484 // printf("canonRhs: %s\n", PcpEmitter::pcpExprToString(canonRhs));
486 if(canonRhs
->isConstant() && canonRhs
->toConstant()->getValue() == 0)
490 PcpArith
* negRhs
= negateExpr(canonRhs
);
491 PcpArith
* newLhs
= addSums(canonLhs
, negRhs
);
492 return new PcpCompare(compare
->getOperator(),
494 createUnaryPlus(new PcpConstant(0)));
499 PcpExprCanonicalizer::createUnaryOr(PcpBoolExpr
* boolExpr
)
501 PcpBoolArithBuilder
* builder
= new PcpBoolArithBuilder();
503 builder
->setOperator(PcpBoolArithOperator::boolOr());
504 builder
->addOperand(boolExpr
);
506 PcpBoolArith
* result
= builder
->createBoolArith();
512 PcpExprCanonicalizer::appendOperandsToBuilder(PcpBoolArithBuilder
* builder
,
513 PcpBoolArith
* boolArith
)
515 PcpIterator
<PcpBoolExpr
*>* iter
= boolArith
->getOperandsIterator();
516 for(;iter
->hasNext(); iter
->next())
518 builder
->addOperand(iter
->get());
524 PcpExprCanonicalizer::mergeOr(PcpBoolArith
* or1
, PcpBoolArith
* or2
)
526 pcpAssert(or1
!= NULL
&& or2
!= NULL
);
527 pcpAssert(or1
->getOperator().isBoolOr());
528 pcpAssert(or2
->getOperator().isBoolOr());
530 PcpBoolArithBuilder
* builder
= new PcpBoolArithBuilder();
531 builder
->setOperator(PcpBoolArithOperator::boolOr());
533 appendOperandsToBuilder(builder
, or1
);
534 appendOperandsToBuilder(builder
, or2
);
536 PcpBoolArith
* result
= builder
->createBoolArith();
542 PcpExprCanonicalizer::createFlattenedAnd(PcpBoolExpr
* boolExpr1
, PcpBoolExpr
* boolExpr2
)
544 PcpBoolArith
* result
;
545 if(!boolExpr1
->isBoolArith() && !boolExpr2
->isBoolArith())
546 result
= PcpBoolArith::pcpBoolArithBinaryCreate(PcpBoolArithOperator::boolAnd(),
549 else if(!boolExpr1
->isBoolArith() && boolExpr2
->isBoolArith())
550 result
= this->createFlattenedAnd(boolExpr2
, boolExpr1
);
553 PcpBoolArithBuilder
* builder
= new PcpBoolArithBuilder();
554 builder
->setOperator(PcpBoolArithOperator::boolAnd());
556 PcpBoolArith
* arith1
= boolExpr1
->toBoolArith();
557 pcpAssert(arith1
->getOperator().isBoolAnd());
559 this->appendOperandsToBuilder(builder
, boolExpr1
->toBoolArith());
561 if(boolExpr2
->isBoolArith())
563 PcpBoolArith
* arith2
= boolExpr2
->toBoolArith();
565 pcpAssert(arith2
->getOperator().isBoolAnd());
567 this->appendOperandsToBuilder(builder
, boolExpr2
->toBoolArith());
570 builder
->addOperand(boolExpr2
);
572 result
= builder
->createBoolArith();
579 PcpExprCanonicalizer::distributeAnd(PcpBoolArith
* or1
, PcpBoolArith
* or2
)
581 PcpBoolArithBuilder
* builder
= new PcpBoolArithBuilder();
582 builder
->setOperator(PcpBoolArithOperator::boolOr());
584 PcpIterator
<PcpBoolExpr
*>* iter1
= or1
->getOperandsIterator();
585 for(;iter1
->hasNext(); iter1
->next())
587 PcpBoolExpr
* expr1
= iter1
->get();
588 PcpIterator
<PcpBoolExpr
*>* iter2
= or2
->getOperandsIterator();
589 for(;iter2
->hasNext(); iter2
->next())
591 PcpBoolExpr
* expr2
= iter2
->get();
592 PcpBoolArith
* newAnd
= this->createFlattenedAnd(expr1
, expr2
);
593 builder
->addOperand(newAnd
);
596 PcpBoolArith
* result
= builder
->createBoolArith();
602 PcpExprCanonicalizer::canonicalizeBoolExpr(PcpBoolExpr
* boolExpr
)
604 if(!boolExpr
->isBoolArith())
605 return this->createUnaryOr(this->canonicalizeCompare(boolExpr
->toCompare()));
607 PcpBoolArith
* boolArith
= boolExpr
->toBoolArith();
608 if(boolArith
->getNumOperands() < 2)
612 PcpIterator
<PcpBoolExpr
*>* iter
= boolArith
->getOperandsIterator();
613 PcpBoolArithOperator oper
= boolArith
->getOperator();
614 PcpBoolArith
* result
= this->canonicalizeBoolExpr(iter
->get());
616 for(;iter
->hasNext(); iter
->next())
618 PcpBoolExpr
* operand
= iter
->get();
619 PcpBoolArith
* canonicalizedOperand
= this->canonicalizeBoolExpr(operand
);
622 result
= this->mergeOr(canonicalizedOperand
, result
);
624 else if(oper
.isBoolAnd())
626 result
= this->distributeAnd(canonicalizedOperand
, result
);
636 PcpExprCanonicalizer::visit(PcpScop
* scop
)
638 scop
->getBody()->accept(this);
642 PcpExprCanonicalizer::visit(PcpLoop
* loop
)
644 this->getScalarContextStack()->push(loop
->getIv()); // Iv(loop->getIv());
645 PcpExpr
* oldBase
= this->getCanonicalizationBase();
646 PcpExpr
* newBase
= this->getScalarContextStack()->createBaseExpr();
647 this->setCanonicalizationBase(newBase
);
648 PcpBoolExpr
* conditionBefore
= loop
->getCondition();
649 PcpBoolArith
* canonicalized
= this->canonicalizeBoolExpr(conditionBefore
);
650 PcpBoolExpr
* simplified
= canonicalized
->getNumOperands() == 1
651 ? canonicalized
->getOperand(0)
653 loop
->setCondition(simplified
);
654 loop
->getBody()->accept(this);
655 this->getScalarContextStack()->pop();
656 this->setCanonicalizationBase(oldBase
);
660 PcpExprCanonicalizer::visit(PcpSequence
* sequence
)
662 visitChildren(sequence
);
666 PcpExprCanonicalizer::visit(PcpGuard
* guard
)
668 visitChildren(guard
);
672 PcpExprCanonicalizer::visit(PcpCopy
* copy
)
678 PcpExprCanonicalizer::visit(PcpUserStmt
* userStmt
)
680 visitChildren(userStmt
);
684 PcpExprCanonicalizer::visit(PcpArrayAccess
* arrayAccess
)
686 PcpIterator
<PcpExpr
*>* iter
= arrayAccess
->getSubscriptsIterator();
688 for(i
= 0; i
< arrayAccess
->getNumSubscripts(); i
++)
690 PcpExpr
* expr
= arrayAccess
->getSubscript(i
);
691 PcpArith
* canonicalized
= canonicalizeExprWithBase(expr
);
692 PcpExpr
* simplified
= canonicalized
->getNumOperands() == 1
693 ? canonicalized
->getOperand(0)
696 arrayAccess
->setSubscript(i
, simplified
);
702 PcpExprCanonicalizer::setCanonicalizationBase(PcpExpr
* canonicalizationBase
)
704 this->canonicalizationBase
= canonicalizationBase
;
708 PcpExprCanonicalizer::getCanonicalizationBase()
710 return this->canonicalizationBase
;
715 PcpExprCanonicalizer::canonicalize(PcpScop
* scop
)
717 setScalarContextStack(new PcpScalarContextStack(scop
));
721 PcpExprCanonicalizer::PcpExprCanonicalizer(PcpScalarOrder
* scalarOrder
)
723 setScalarOrder(scalarOrder
);