aboutsummaryrefslogtreecommitdiffhomepage
path: root/stp/simplifier/simplifier.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'stp/simplifier/simplifier.cpp')
-rw-r--r--stp/simplifier/simplifier.cpp2495
1 files changed, 0 insertions, 2495 deletions
diff --git a/stp/simplifier/simplifier.cpp b/stp/simplifier/simplifier.cpp
deleted file mode 100644
index c0519e83..00000000
--- a/stp/simplifier/simplifier.cpp
+++ /dev/null
@@ -1,2495 +0,0 @@
-/********************************************************************
- * AUTHORS: Vijay Ganesh, David L. Dill
- *
- * BEGIN DATE: November, 2005
- *
- * LICENSE: Please view LICENSE file in the home dir of this Program
- ********************************************************************/
-// -*- c++ -*-
-
-#include "../AST/AST.h"
-#include "../AST/ASTUtil.h"
-namespace BEEV {
-
- bool BeevMgr::CheckSimplifyMap(const ASTNode& key,
- ASTNode& output, bool pushNeg) {
- ASTNodeMap::iterator it, itend;
- it = pushNeg ? SimplifyNegMap.find(key) : SimplifyMap.find(key);
- itend = pushNeg ? SimplifyNegMap.end() : SimplifyMap.end();
-
- if(it != itend) {
- output = it->second;
- CountersAndStats("Successful_CheckSimplifyMap");
- return true;
- }
-
- if(pushNeg && (it = SimplifyMap.find(key)) != SimplifyMap.end()) {
- output =
- (ASTFalse == it->second) ?
- ASTTrue :
- (ASTTrue == it->second) ? ASTFalse : CreateNode(NOT, it->second);
- CountersAndStats("2nd_Successful_CheckSimplifyMap");
- return true;
- }
-
- return false;
- }
-
- void BeevMgr::UpdateSimplifyMap(const ASTNode& key, const ASTNode& value, bool pushNeg) {
- if(pushNeg)
- SimplifyNegMap[key] = value;
- else
- SimplifyMap[key] = value;
- }
-
- bool BeevMgr::CheckSubstitutionMap(const ASTNode& key, ASTNode& output) {
- ASTNodeMap::iterator it;
- if((it = SolverMap.find(key)) != SolverMap.end()) {
- output = it->second;
- return true;
- }
- return false;
- }
-
- bool BeevMgr::CheckSubstitutionMap(const ASTNode& key) {
- if(SolverMap.find(key) != SolverMap.end())
- return true;
- else
- return false;
- }
-
- bool BeevMgr::UpdateSubstitutionMap(const ASTNode& e0, const ASTNode& e1) {
- int i = TermOrder(e0,e1);
- if(0 == i)
- return false;
-
- //e0 is of the form READ(Arr,const), and e1 is const, or
- //e0 is of the form var, and e1 is const
- if(1 == i && !CheckSubstitutionMap(e0)) {
- SolverMap[e0] = e1;
- return true;
- }
-
- //e1 is of the form READ(Arr,const), and e0 is const, or
- //e1 is of the form var, and e0 is const
- if (-1 == i && !CheckSubstitutionMap(e1)) {
- SolverMap[e1] = e0;
- return true;
- }
-
- return false;
- }
-
- bool BeevMgr::CheckMultInverseMap(const ASTNode& key, ASTNode& output) {
- ASTNodeMap::iterator it;
- if((it = MultInverseMap.find(key)) != MultInverseMap.end()) {
- output = it->second;
- return true;
- }
- return false;
- }
-
- void BeevMgr::UpdateMultInverseMap(const ASTNode& key, const ASTNode& value) {
- MultInverseMap[key] = value;
- }
-
-
- bool BeevMgr::CheckAlwaysTrueFormMap(const ASTNode& key) {
- ASTNodeSet::iterator it = AlwaysTrueFormMap.find(key);
- ASTNodeSet::iterator itend = AlwaysTrueFormMap.end();
-
- if(it != itend) {
- //cerr << "found:" << *it << endl;
- CountersAndStats("Successful_CheckAlwaysTrueFormMap");
- return true;
- }
-
- return false;
- }
-
- void BeevMgr::UpdateAlwaysTrueFormMap(const ASTNode& key) {
- AlwaysTrueFormMap.insert(key);
- }
-
- //if a is READ(Arr,const) or SYMBOL, and b is BVCONST then return 1
- //if b is READ(Arr,const) or SYMBOL, and a is BVCONST then return -1
- //
- //else return 0 by default
- int BeevMgr::TermOrder(const ASTNode& a, const ASTNode& b) {
- Kind k1 = a.GetKind();
- Kind k2 = b.GetKind();
-
- //a is of the form READ(Arr,const), and b is const, or
- //a is of the form var, and b is const
- if((k1 == READ
- &&
- a[0].GetKind() == SYMBOL &&
- a[1].GetKind() == BVCONST
- )
- &&
- (k2 == BVCONST)
- )
- return 1;
-
- if(k1 == SYMBOL)
- return 1;
-
- //b is of the form READ(Arr,const), and a is const, or
- //b is of the form var, and a is const
- if((k1 == BVCONST)
- &&
- ((k2 == READ
- &&
- b[0].GetKind() == SYMBOL &&
- b[1].GetKind() == BVCONST
- )
- ||
- k2 == SYMBOL
- ))
- return -1;
- return 0;
- }
-
- //This function records all the const-indices seen so far for each
- //array. It populates the map '_arrayname_readindices' whose key is
- //the arrayname, and vlaue is a vector of read-indices.
- //
- //fill the arrayname_readindices vector if e0 is a READ(Arr,index)
- //and index is a BVCONST.
- //
- //Since these arrayreads are being nuked and recorded in the
- //substitutionmap, we have to also record the fact that each
- //arrayread (e0 is of the form READ(Arr,const) here is represented
- //by a BVCONST (e1). This is necessary for later Leibnitz Axiom
- //generation
- void BeevMgr::FillUp_ArrReadIndex_Vec(const ASTNode& e0, const ASTNode& e1) {
- int i = TermOrder(e0,e1);
- if(0 == i) return;
-
- if(1 == i && e0.GetKind() != SYMBOL && !CheckSubstitutionMap(e0)) {
- _arrayname_readindices[e0[0]].push_back(e0[1]);
- //e0 is the array read : READ(A,i) and e1 is a bvconst
- _arrayread_symbol[e0] = e1;
- return;
- }
- if(-1 == i && e1.GetKind() != SYMBOL && !CheckSubstitutionMap(e1)) {
- _arrayname_readindices[e1[0]].push_back(e1[1]);
- //e0 is the array read : READ(A,i) and e1 is a bvconst
- _arrayread_symbol[e1] = e0;
- return;
- }
- }
-
- ASTNode BeevMgr::SimplifyFormula_NoRemoveWrites(const ASTNode& b, bool pushNeg) {
- Begin_RemoveWrites = false;
- ASTNode out = SimplifyFormula(b,pushNeg);
- return out;
- }
-
- ASTNode BeevMgr::SimplifyFormula_TopLevel(const ASTNode& b, bool pushNeg) {
- SimplifyMap.clear();
- SimplifyNegMap.clear();
- ASTNode out = SimplifyFormula(b,pushNeg);
- SimplifyMap.clear();
- SimplifyNegMap.clear();
- return out;
- }
-
- ASTNode BeevMgr::SimplifyFormula(const ASTNode& b, bool pushNeg){
- if(!optimize)
- return b;
-
- Kind kind = b.GetKind();
- if(BOOLEAN_TYPE != b.GetType()) {
- FatalError(" SimplifyFormula: You have input a nonformula kind: ",ASTUndefined,kind);
- }
-
- ASTNode a = b;
- ASTVec ca = a.GetChildren();
- if(!(IMPLIES == kind ||
- ITE == kind ||
- isAtomic(kind))) {
- SortByExprNum(ca);
- a = CreateNode(kind,ca);
- }
-
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- switch(kind){
- case AND:
- case OR:
- output = SimplifyAndOrFormula(a,pushNeg);
- break;
- case NOT:
- output = SimplifyNotFormula(a,pushNeg);
- break;
- case XOR:
- output = SimplifyXorFormula(a,pushNeg);
- break;
- case NAND:
- output = SimplifyNandFormula(a,pushNeg);
- break;
- case NOR:
- output = SimplifyNorFormula(a,pushNeg);
- break;
- case IFF:
- output = SimplifyIffFormula(a,pushNeg);
- break;
- case IMPLIES:
- output = SimplifyImpliesFormula(a,pushNeg);
- break;
- case ITE:
- output = SimplifyIteFormula(a,pushNeg);
- break;
- default:
- //kind can be EQ,NEQ,BVLT,BVLE,... or a propositional variable
- output = SimplifyAtomicFormula(a,pushNeg);
- //output = pushNeg ? CreateNode(NOT,a) : a;
- break;
- }
-
- //memoize
- UpdateSimplifyMap(a,output, pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyAtomicFormula(const ASTNode& a, bool pushNeg) {
- if(!optimize) {
- return a;
- }
-
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg)) {
- return output;
- }
-
- ASTNode left,right;
- if(a.Degree() == 2) {
- //cerr << "Input to simplifyterm: left: " << a[0] << endl;
- left = SimplifyTerm(a[0]);
- //cerr << "Output of simplifyterm:left: " << left << endl;
- //cerr << "Input to simplifyterm: right: " << a[1] << endl;
- right = SimplifyTerm(a[1]);
- //cerr << "Output of simplifyterm:left: " << right << endl;
- }
-
- Kind kind = a.GetKind();
- switch(kind) {
- case TRUE:
- output = pushNeg ? ASTFalse : ASTTrue;
- break;
- case FALSE:
- output = pushNeg ? ASTTrue : ASTFalse;
- break;
- case SYMBOL:
- if(!CheckSolverMap(a,output)) {
- output = a;
- }
- output = pushNeg ? CreateNode(NOT,output) : output;
- break;
- case BVGETBIT: {
- ASTNode term = SimplifyTerm(a[0]);
- ASTNode thebit = a[1];
- ASTNode zero = CreateZeroConst(1);
- ASTNode one = CreateOneConst(1);
- ASTNode getthebit = SimplifyTerm(CreateTerm(BVEXTRACT,1,term,thebit,thebit));
- if(getthebit == zero)
- output = pushNeg ? ASTTrue : ASTFalse;
- else if(getthebit == one)
- output = pushNeg ? ASTFalse : ASTTrue;
- else {
- output = CreateNode(BVGETBIT,term,thebit);
- output = pushNeg ? CreateNode(NOT,output) : output;
- }
- break;
- }
- case EQ:{
- output = CreateSimplifiedEQ(left,right);
- output = LhsMinusRhs(output);
- output = ITEOpt_InEqs(output);
- if(output == ASTTrue)
- output = pushNeg ? ASTFalse : ASTTrue;
- else if (output == ASTFalse)
- output = pushNeg ? ASTTrue : ASTFalse;
- else
- output = pushNeg ? CreateNode(NOT,output) : output;
- break;
- }
- case NEQ: {
- output = CreateSimplifiedEQ(left,right);
- output = LhsMinusRhs(output);
- if(output == ASTTrue)
- output = pushNeg ? ASTTrue : ASTFalse;
- else if (output == ASTFalse)
- output = pushNeg ? ASTFalse : ASTTrue;
- else
- output = pushNeg ? output : CreateNode(NOT,output);
- break;
- }
- case BVLT:
- case BVLE:
- case BVGT:
- case BVGE:
- case BVSLT:
- case BVSLE:
- case BVSGT:
- case BVSGE: {
- //output = CreateNode(kind,left,right);
- //output = pushNeg ? CreateNode(NOT,output) : output;
- output = CreateSimplifiedINEQ(kind,left,right,pushNeg);
- break;
- }
- default:
- FatalError("SimplifyAtomicFormula: NO atomic formula of the kind: ",ASTUndefined,kind);
- break;
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- } //end of SimplifyAtomicFormula()
-
- ASTNode BeevMgr::CreateSimplifiedINEQ(Kind k,
- const ASTNode& left,
- const ASTNode& right,
- bool pushNeg) {
- ASTNode output;
- if(BVCONST == left.GetKind() && BVCONST == right.GetKind()) {
- output = BVConstEvaluator(CreateNode(k,left,right));
- output = pushNeg ? (ASTFalse == output) ? ASTTrue : ASTFalse : output;
- return output;
- }
-
- unsigned len = left.GetValueWidth();
- ASTNode zero = CreateZeroConst(len);
- ASTNode one = CreateOneConst(len);
- ASTNode max = CreateMaxConst(len);
- switch(k){
- case BVLT:
- if(right == zero) {
- output = pushNeg ? ASTTrue : ASTFalse;
- }
- else if(left == right) {
- output = pushNeg ? ASTTrue : ASTFalse;
- }
- else if(one == right) {
- output = CreateSimplifiedEQ(left,zero);
- output = pushNeg ? CreateNode(NOT,output) : output;
- }
- else {
- output = pushNeg ? CreateNode(BVLE,right,left) : CreateNode(BVLT,left,right);
- }
- break;
- case BVLE:
- if(left == zero) {
- output = pushNeg ? ASTFalse : ASTTrue;
- }
- else if(left == right) {
- output = pushNeg ? ASTFalse : ASTTrue;
- }
- else if(max == right) {
- output = pushNeg ? ASTFalse : ASTTrue;
- }
- else if(zero == right) {
- output = CreateSimplifiedEQ(left,zero);
- output = pushNeg ? CreateNode(NOT,output) : output;
- }
- else {
- output = pushNeg ? CreateNode(BVLT,right,left) : CreateNode(BVLE,left,right);
- }
- break;
- case BVGT:
- if(left == zero) {
- output = pushNeg ? ASTTrue : ASTFalse;
- }
- else if(left == right) {
- output = pushNeg ? ASTTrue : ASTFalse;
- }
- else {
- output = pushNeg ? CreateNode(BVLE,left,right) : CreateNode(BVLT,right,left);
- }
- break;
- case BVGE:
- if(right == zero) {
- output = pushNeg ? ASTFalse : ASTTrue;
- }
- else if(left == right) {
- output = pushNeg ? ASTFalse : ASTTrue;
- }
- else {
- output = pushNeg ? CreateNode(BVLT,left,right) : CreateNode(BVLE,right,left);
- }
- break;
- case BVSLT:
- case BVSLE:
- case BVSGE:
- case BVSGT: {
- output = CreateNode(k,left,right);
- output = pushNeg ? CreateNode(NOT,output) : output;
- }
- break;
- default:
- FatalError("Wrong Kind");
- break;
- }
-
- return output;
- }
-
- //takes care of some simple ITE Optimizations in the context of equations
- ASTNode BeevMgr::ITEOpt_InEqs(const ASTNode& in) {
- CountersAndStats("ITEOpts_InEqs");
-
- if(!(EQ == in.GetKind() && optimize)) {
- return in;
- }
-
- ASTNode output;
- if(CheckSimplifyMap(in,output,false)) {
- return output;
- }
-
- ASTNode in1 = in[0];
- ASTNode in2 = in[1];
- Kind k1 = in1.GetKind();
- Kind k2 = in2.GetKind();
- if(in1 == in2) {
- //terms are syntactically the same
- output = ASTTrue;
- }
- else if(BVCONST == k1 && BVCONST == k2) {
- //here the terms are definitely not syntactically equal but may
- //be semantically equal.
- output = ASTFalse;
- }
- else if(ITE == k1 &&
- BVCONST == in1[1].GetKind() &&
- BVCONST == in1[2].GetKind() && BVCONST == k2) {
- //if one side is a BVCONST and the other side is an ITE over
- //BVCONST then we can do the following optimization:
- //
- // c = ITE(cond,c,d) <=> cond
- //
- // similarly ITE(cond,c,d) = c <=> cond
- //
- // c = ITE(cond,d,c) <=> NOT(cond)
- //
- //similarly ITE(cond,d,c) = d <=> NOT(cond)
- ASTNode cond = in1[0];
- if(in1[1] == in2) {
- //ITE(cond, c, d) = c <=> cond
- output = cond;
- }
- else if(in1[2] == in2) {
- cond = SimplifyFormula(cond,true);
- output = cond;
- }
- else {
- //last resort is to CreateNode
- output = CreateNode(EQ,in1,in2);
- }
- }
- else if(ITE == k2 &&
- BVCONST == in2[1].GetKind() &&
- BVCONST == in2[2].GetKind() && BVCONST == k1) {
- ASTNode cond = in2[0];
- if(in2[1] == in1) {
- //ITE(cond, c, d) = c <=> cond
- output = cond;
- }
- else if(in2[2] == in1) {
- cond = SimplifyFormula(cond,true);
- output = cond;
- }
- else {
- //last resort is to CreateNode
- output = CreateNode(EQ,in1,in2);
- }
- }
- else {
- //last resort is to CreateNode
- output = CreateNode(EQ,in1,in2);
- }
-
- UpdateSimplifyMap(in,output,false);
- return output;
- } //End of ITEOpts_InEqs()
-
- //Tries to simplify the input to TRUE/FALSE. if it fails, then
- //return the constructed equality
- ASTNode BeevMgr::CreateSimplifiedEQ(const ASTNode& in1, const ASTNode& in2) {
- CountersAndStats("CreateSimplifiedEQ");
- Kind k1 = in1.GetKind();
- Kind k2 = in2.GetKind();
-
- if(!optimize) {
- return CreateNode(EQ,in1,in2);
- }
-
- if(in1 == in2)
- //terms are syntactically the same
- return ASTTrue;
-
- //here the terms are definitely not syntactically equal but may be
- //semantically equal.
- if(BVCONST == k1 && BVCONST == k2)
- return ASTFalse;
-
- //last resort is to CreateNode
- return CreateNode(EQ,in1,in2);
- }
-
- //accepts cond == t1, then part is t2, and else part is t3
- ASTNode BeevMgr::CreateSimplifiedTermITE(const ASTNode& in0,
- const ASTNode& in1, const ASTNode& in2) {
- ASTNode t0 = in0;
- ASTNode t1 = in1;
- ASTNode t2 = in2;
- CountersAndStats("CreateSimplifiedITE");
- if(!optimize) {
- if(t1.GetValueWidth() != t2.GetValueWidth()) {
- cerr << "t2 is : = " << t2;
- FatalError("CreateSimplifiedTermITE: the lengths of then and else branches don't match",t1);
- }
- if(t1.GetIndexWidth() != t2.GetIndexWidth()) {
- cerr << "t2 is : = " << t2;
- FatalError("CreateSimplifiedTermITE: the lengths of then and else branches don't match",t1);
- }
- return CreateTerm(ITE,t1.GetValueWidth(),t0,t1,t2);
- }
-
- if(t0 == ASTTrue)
- return t1;
- if (t0 == ASTFalse)
- return t2;
- if(t1 == t2)
- return t1;
- if(CheckAlwaysTrueFormMap(t0)) {
- return t1;
- }
- if(CheckAlwaysTrueFormMap(CreateNode(NOT,t0)) ||
- (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0]))) {
- return t2;
- }
-
- return CreateTerm(ITE,t1.GetValueWidth(),t0,t1,t2);
- }
-
- ASTNode BeevMgr::SimplifyAndOrFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output;
- //cerr << "input:\n" << a << endl;
-
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- ASTVec c, outvec;
- c = a.GetChildren();
- ASTNode flat = FlattenOneLevel(a);
- c = flat.GetChildren();
- SortByExprNum(c);
-
- Kind k = a.GetKind();
- bool isAnd = (k == AND) ? true : false;
-
- ASTNode annihilator = isAnd ?
- (pushNeg ? ASTTrue : ASTFalse):
- (pushNeg ? ASTFalse : ASTTrue);
-
- ASTNode identity = isAnd ?
- (pushNeg ? ASTFalse : ASTTrue):
- (pushNeg ? ASTTrue : ASTFalse);
-
- //do the work
- ASTVec::const_iterator next_it;
- for(ASTVec::const_iterator i=c.begin(),iend=c.end();i!=iend;i++) {
- ASTNode aaa = *i;
- next_it = i+1;
- bool nextexists = (next_it < iend);
-
- aaa = SimplifyFormula(aaa,pushNeg);
- if(annihilator == aaa) {
- //memoize
- UpdateSimplifyMap(*i,annihilator,pushNeg);
- UpdateSimplifyMap(a, annihilator,pushNeg);
- //cerr << "annihilator1: output:\n" << annihilator << endl;
- return annihilator;
- }
- ASTNode bbb = ASTFalse;
- if(nextexists) {
- bbb = SimplifyFormula(*next_it,pushNeg);
- }
- if(nextexists && bbb == aaa) {
- //skip the duplicate aaa. *next_it will be included
- }
- else if(nextexists &&
- ((bbb.GetKind() == NOT && bbb[0] == aaa))) {
- //memoize
- UpdateSimplifyMap(a, annihilator,pushNeg);
- //cerr << "annihilator2: output:\n" << annihilator << endl;
- return annihilator;
- }
- else if(identity == aaa) {
- // //drop identites
- }
- else if((!isAnd && !pushNeg) ||
- (isAnd && pushNeg)) {
- outvec.push_back(aaa);
- }
- else if((isAnd && !pushNeg) ||
- (!isAnd && pushNeg)) {
- outvec.push_back(aaa);
- }
- else {
- outvec.push_back(aaa);
- }
- }
-
- switch(outvec.size()) {
- case 0: {
- //only identities were dropped
- output = identity;
- break;
- }
- case 1: {
- output = SimplifyFormula(outvec[0],false);
- break;
- }
- default: {
- output = (isAnd) ?
- (pushNeg ? CreateNode(OR,outvec) : CreateNode(AND,outvec)):
- (pushNeg ? CreateNode(AND,outvec) : CreateNode(OR,outvec));
- //output = FlattenOneLevel(output);
- break;
- }
- }
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- //cerr << "output:\n" << output << endl;
- return output;
- } //end of SimplifyAndOrFormula
-
-
- ASTNode BeevMgr::SimplifyNotFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- if(!(a.Degree() == 1 && NOT == a.GetKind()))
- FatalError("SimplifyNotFormula: input vector with more than 1 node",ASTUndefined);
-
- //if pushNeg is set then there is NOT on top
- unsigned int NotCount = pushNeg ? 1 : 0;
- ASTNode o = a;
- //count the number of NOTs in 'a'
- while(NOT == o.GetKind()) {
- o = o[0];
- NotCount++;
- }
-
- //pushnegation if there are odd number of NOTs
- bool pn = (NotCount % 2 == 0) ? false : true;
-
- if(CheckAlwaysTrueFormMap(o)) {
- output = pn ? ASTFalse : ASTTrue;
- return output;
- }
-
- if(CheckSimplifyMap(o,output,pn)) {
- return output;
- }
-
- if (ASTTrue == o) {
- output = pn ? ASTFalse : ASTTrue;
- }
- else if (ASTFalse == o) {
- output = pn ? ASTTrue : ASTFalse;
- }
- else {
- output = SimplifyFormula(o,pn);
- }
- //memoize
- UpdateSimplifyMap(o,output,pn);
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyXorFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- if (a.GetChildren().size() > 2) {
- FatalError("Simplify got an XOR with more than two children.");
- }
-
- ASTNode a0 = SimplifyFormula(a[0],false);
- ASTNode a1 = SimplifyFormula(a[1],false);
- output = pushNeg ? CreateNode(IFF,a0,a1) : CreateNode(XOR,a0,a1);
-
- if(XOR == output.GetKind()) {
- a0 = output[0];
- a1 = output[1];
- if(a0 == a1)
- output = ASTFalse;
- else if((a0 == ASTTrue && a1 == ASTFalse) ||
- (a0 == ASTFalse && a1 == ASTTrue))
- output = ASTTrue;
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyNandFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output,a0,a1;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- //the two NOTs cancel out
- if(pushNeg) {
- a0 = SimplifyFormula(a[0],false);
- a1 = SimplifyFormula(a[1],false);
- output = CreateNode(AND,a0,a1);
- }
- else {
- //push the NOT implicit in the NAND
- a0 = SimplifyFormula(a[0],true);
- a1 = SimplifyFormula(a[1],true);
- output = CreateNode(OR,a0,a1);
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyNorFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output,a0,a1;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- //the two NOTs cancel out
- if(pushNeg) {
- a0 = SimplifyFormula(a[0],false);
- a1 = SimplifyFormula(a[1],false);
- output = CreateNode(OR,a0,a1);
- }
- else {
- //push the NOT implicit in the NAND
- a0 = SimplifyFormula(a[0],true);
- a1 = SimplifyFormula(a[1],true);
- output = CreateNode(AND,a0,a1);
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyImpliesFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- if(!(a.Degree()==2 && IMPLIES==a.GetKind()))
- FatalError("SimplifyImpliesFormula: vector with wrong num of nodes",ASTUndefined);
-
- ASTNode c0,c1;
- if(pushNeg) {
- c0 = SimplifyFormula(a[0],false);
- c1 = SimplifyFormula(a[1],true);
- output = CreateNode(AND,c0,c1);
- }
- else {
- c0 = SimplifyFormula(a[0],false);
- c1 = SimplifyFormula(a[1],false);
- if(ASTFalse == c0) {
- output = ASTTrue;
- }
- else if (ASTTrue == c0) {
- output = c1;
- }
- else if (c0 == c1) {
- output = ASTTrue;
- }
- else if(CheckAlwaysTrueFormMap(c0)) {
- // c0 AND (~c0 OR c1) <==> c1
- //
- //applying modus ponens
- output = c1;
- }
- else if(CheckAlwaysTrueFormMap(c1) ||
- CheckAlwaysTrueFormMap(CreateNode(NOT,c0)) ||
- (NOT == c0.GetKind() && CheckAlwaysTrueFormMap(c0[0]))) {
- //(~c0 AND (~c0 OR c1)) <==> TRUE
- //
- //(c0 AND ~c0->c1) <==> TRUE
- output = ASTTrue;
- }
- else if (CheckAlwaysTrueFormMap(CreateNode(NOT,c1)) ||
- (NOT == c1.GetKind() && CheckAlwaysTrueFormMap(c1[0]))) {
- //(~c1 AND c0->c1) <==> (~c1 AND ~c1->~c0) <==> ~c0
- //(c1 AND c0->~c1) <==> (c1 AND c1->~c0) <==> ~c0
- output = CreateNode(NOT,c0);
- }
- else {
- if(NOT == c0.GetKind()) {
- output = CreateNode(OR,c0[0],c1);
- }
- else {
- output = CreateNode(OR,CreateNode(NOT,c0),c1);
- }
- }
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyIffFormula(const ASTNode& a, bool pushNeg) {
- ASTNode output;
- if(CheckSimplifyMap(a,output,pushNeg))
- return output;
-
- if(!(a.Degree()==2 && IFF==a.GetKind()))
- FatalError("SimplifyIffFormula: vector with wrong num of nodes",ASTUndefined);
-
- ASTNode c0 = a[0];
- ASTNode c1 = SimplifyFormula(a[1],false);
-
- if(pushNeg)
- c0 = SimplifyFormula(c0,true);
- else
- c0 = SimplifyFormula(c0,false);
-
- if(ASTTrue == c0) {
- output = c1;
- }
- else if (ASTFalse == c0) {
- output = SimplifyFormula(c1,true);
- }
- else if (ASTTrue == c1) {
- output = c0;
- }
- else if (ASTFalse == c1) {
- output = SimplifyFormula(c0,true);
- }
- else if (c0 == c1) {
- output = ASTTrue;
- }
- else if((NOT == c0.GetKind() && c0[0] == c1) ||
- (NOT == c1.GetKind() && c0 == c1[0])) {
- output = ASTFalse;
- }
- else if(CheckAlwaysTrueFormMap(c0)) {
- output = c1;
- }
- else if(CheckAlwaysTrueFormMap(c1)) {
- output = c0;
- }
- else if(CheckAlwaysTrueFormMap(CreateNode(NOT,c0))) {
- output = CreateNode(NOT,c1);
- }
- else if(CheckAlwaysTrueFormMap(CreateNode(NOT,c1))) {
- output = CreateNode(NOT,c0);
- }
- else {
- output = CreateNode(IFF,c0,c1);
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- ASTNode BeevMgr::SimplifyIteFormula(const ASTNode& b, bool pushNeg) {
- if(!optimize)
- return b;
-
- ASTNode output;
- if(CheckSimplifyMap(b,output,pushNeg))
- return output;
-
- if(!(b.Degree() == 3 && ITE == b.GetKind()))
- FatalError("SimplifyIteFormula: vector with wrong num of nodes",ASTUndefined);
-
- ASTNode a = b;
- ASTNode t0 = SimplifyFormula(a[0],false);
- ASTNode t1,t2;
- if(pushNeg) {
- t1 = SimplifyFormula(a[1],true);
- t2 = SimplifyFormula(a[2],true);
- }
- else {
- t1 = SimplifyFormula(a[1],false);
- t2 = SimplifyFormula(a[2],false);
- }
-
- if(ASTTrue == t0) {
- output = t1;
- }
- else if (ASTFalse == t0) {
- output = t2;
- }
- else if (t1 == t2) {
- output = t1;
- }
- else if(ASTTrue == t1 && ASTFalse == t2) {
- output = t0;
- }
- else if(ASTFalse == t1 && ASTTrue == t2) {
- output = SimplifyFormula(t0,true);
- }
- else if(ASTTrue == t1) {
- output = CreateNode(OR,t0,t2);
- }
- else if(ASTFalse == t1) {
- output = CreateNode(AND,CreateNode(NOT,t0),t2);
- }
- else if(ASTTrue == t2) {
- output = CreateNode(OR,CreateNode(NOT,t0),t1);
- }
- else if(ASTFalse == t2) {
- output = CreateNode(AND,t0,t1);
- }
- else if(CheckAlwaysTrueFormMap(t0)) {
- output = t1;
- }
- else if(CheckAlwaysTrueFormMap(CreateNode(NOT,t0)) ||
- (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0]))) {
- output = t2;
- }
- else {
- output = CreateNode(ITE,t0,t1,t2);
- }
-
- //memoize
- UpdateSimplifyMap(a,output,pushNeg);
- return output;
- }
-
- //one level deep flattening
- ASTNode BeevMgr::FlattenOneLevel(const ASTNode& a) {
- Kind k = a.GetKind();
- if(!(BVPLUS == k ||
- AND == k || OR == k
- //|| BVAND == k
- //|| BVOR == k
- )
- ) {
- return a;
- }
-
- ASTNode output;
- // if(CheckSimplifyMap(a,output,false)) {
- // //check memo table
- // //cerr << "output of SimplifyTerm Cache: " << output << endl;
- // return output;
- // }
-
- ASTVec c = a.GetChildren();
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = *it;
- if(k == aaa.GetKind()) {
- ASTVec ac = aaa.GetChildren();
- o.insert(o.end(),ac.begin(),ac.end());
- }
- else
- o.push_back(aaa);
- }
-
- if(is_Form_kind(k))
- output = CreateNode(k,o);
- else
- output = CreateTerm(k,a.GetValueWidth(),o);
-
- //UpdateSimplifyMap(a,output,false);
- return output;
- //memoize
- } //end of flattenonelevel()
-
- ASTNode BeevMgr::SimplifyTerm_TopLevel(const ASTNode& b) {
- SimplifyMap.clear();
- SimplifyNegMap.clear();
- ASTNode out = SimplifyTerm(b);
- SimplifyNegMap.clear();
- SimplifyMap.clear();
- return out;
- }
-
- //This function simplifies terms based on their kind
- ASTNode BeevMgr::SimplifyTerm(const ASTNode& inputterm) {
- //cout << "SimplifyTerm: input: " << a << endl;
- if(!optimize) {
- return inputterm;
- }
-
- BVTypeCheck(inputterm);
- ASTNode output;
- if(wordlevel_solve && CheckSolverMap(inputterm,output)) {
- //cout << "SimplifyTerm: output: " << output << endl;
- return SimplifyTerm(output);
- }
-
- if(CheckSimplifyMap(inputterm,output,false)) {
- //cerr << "output of SimplifyTerm Cache: " << output << endl;
- return output;
- }
-
- Kind k = inputterm.GetKind();
- if(!is_Term_kind(k)) {
- FatalError("SimplifyTerm: You have input a Non-term",ASTUndefined);
- }
-
- unsigned int inputValueWidth = inputterm.GetValueWidth();
- switch(k) {
- case BVCONST:
- output = inputterm;
- break;
- case SYMBOL:
- if(CheckSolverMap(inputterm,output)) {
- return SimplifyTerm(output);
- }
- output = inputterm;
- break;
- case BVMULT:
- case BVPLUS:{
- if(BVMULT == k && 2 != inputterm.Degree()) {
- FatalError("SimplifyTerm: We assume that BVMULT is binary",inputterm);
- }
-
- ASTVec c = FlattenOneLevel(inputterm).GetChildren();
- SortByExprNum(c);
- ASTVec constkids, nonconstkids;
-
- //go through the childnodes, and separate constant and
- //nonconstant nodes. combine the constant nodes using the
- //constevaluator. if the resultant constant is zero and k ==
- //BVPLUS, then ignore it (similarily for 1 and BVMULT). else,
- //add the computed constant to the nonconst vector, flatten,
- //sort, and create BVPLUS/BVMULT and return
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- if(BVCONST == aaa.GetKind()) {
- constkids.push_back(aaa);
- }
- else {
- nonconstkids.push_back(aaa);
- }
- }
-
- ASTNode one = CreateOneConst(inputValueWidth);
- ASTNode max = CreateMaxConst(inputValueWidth);
- ASTNode zero = CreateZeroConst(inputValueWidth);
-
- //initialize constoutput to zero, in case there are no elements
- //in constkids
- ASTNode constoutput = (k == BVPLUS) ? zero : one;
-
- if(1 == constkids.size()) {
- //only one element in constkids
- constoutput = constkids[0];
- }
- else if (1 < constkids.size()) {
- //many elements in constkids. simplify it
- constoutput = CreateTerm(k,inputterm.GetValueWidth(),constkids);
- constoutput = BVConstEvaluator(constoutput);
- }
-
- if(BVMULT == k && zero == constoutput) {
- output = zero;
- }
- else if(BVMULT == k &&
- 1 == nonconstkids.size() &&
- constoutput == max) {
- //useful special case opt: when input is BVMULT(max_const,t),
- //then output = BVUMINUS(t). this is easier on the bitblaster
- output = CreateTerm(BVUMINUS,inputValueWidth,nonconstkids);
- }
- else {
- if(0 < nonconstkids.size()) {
- //nonconstkids is not empty. First, combine const and
- //nonconstkids
- if(BVPLUS == k && constoutput != zero) {
- nonconstkids.push_back(constoutput);
- }
- else if(BVMULT == k && constoutput != one) {
- nonconstkids.push_back(constoutput);
- }
-
- if(1 == nonconstkids.size()) {
- //exactly one element in nonconstkids. output is exactly
- //nonconstkids[0]
- output = nonconstkids[0];
- }
- else {
- //more than 1 element in nonconstkids. create BVPLUS term
- SortByExprNum(nonconstkids);
- output = CreateTerm(k,inputValueWidth,nonconstkids);
- output = FlattenOneLevel(output);
- output = DistributeMultOverPlus(output,true);
- output = CombineLikeTerms(output);
- }
- }
- else {
- //nonconstkids was empty, all childnodes were constant, hence
- //constoutput is the output.
- output = constoutput;
- }
- }
- if(BVMULT == output.GetKind()
- || BVPLUS == output.GetKind()
- ) {
- ASTVec d = output.GetChildren();
- SortByExprNum(d);
- output = CreateTerm(output.GetKind(),output.GetValueWidth(),d);
- }
- break;
- }
- case BVSUB: {
- ASTVec c = inputterm.GetChildren();
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- ASTNode a1 = SimplifyTerm(inputterm[1]);
- unsigned int l = inputValueWidth;
- if(a0 == a1)
- output = CreateZeroConst(l);
- else {
- //covert x-y into x+(-y) and simplify. this transformation
- //triggers more simplifications
- a1 = SimplifyTerm(CreateTerm(BVUMINUS,l,a1));
- output = SimplifyTerm(CreateTerm(BVPLUS,l,a0,a1));
- }
- break;
- }
- case BVUMINUS: {
- //important to treat BVUMINUS as a special case, because it
- //helps in arithmetic transformations. e.g. x + BVUMINUS(x) is
- //actually 0. One way to reveal this fact is to strip bvuminus
- //out, and replace with something else so that combineliketerms
- //can catch this fact.
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- Kind k1 = a0.GetKind();
- unsigned int l = a0.GetValueWidth();
- ASTNode one = CreateOneConst(l);
- switch(k1) {
- case BVUMINUS:
- output = a0[0];
- break;
- case BVCONST: {
- output = BVConstEvaluator(CreateTerm(BVUMINUS,l,a0));
- break;
- }
- case BVNEG: {
- output = SimplifyTerm(CreateTerm(BVPLUS,l,a0[0],one));
- break;
- }
- case BVMULT: {
- if(BVUMINUS == a0[0].GetKind()) {
- output = CreateTerm(BVMULT,l,a0[0][0],a0[1]);
- }
- else if(BVUMINUS == a0[1].GetKind()) {
- output = CreateTerm(BVMULT,l,a0[0],a0[1][0]);
- }
- else {
- ASTNode a00 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[0]));
- output = CreateTerm(BVMULT,l,a00,a0[1]);
- }
- break;
- }
- case BVPLUS: {
- //push BVUMINUS over all the monomials of BVPLUS. Simplify
- //along the way
- //
- //BVUMINUS(a1x1 + a2x2 + ...) <=> BVPLUS(BVUMINUS(a1x1) +
- //BVUMINUS(a2x2) + ...
- ASTVec c = a0.GetChildren();
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- //Simplify(BVUMINUS(a1x1))
- ASTNode aaa = SimplifyTerm(CreateTerm(BVUMINUS,l,*it));
- o.push_back(aaa);
- }
- //simplify the bvplus
- output = SimplifyTerm(CreateTerm(BVPLUS,l,o));
- break;
- }
- case BVSUB: {
- //BVUMINUS(BVSUB(x,y)) <=> BVSUB(y,x)
- output = SimplifyTerm(CreateTerm(BVSUB,l,a0[1],a0[0]));
- break;
- }
- case ITE: {
- //BVUMINUS(ITE(c,t1,t2)) <==> ITE(c,BVUMINUS(t1),BVUMINUS(t2))
- ASTNode c = a0[0];
- ASTNode t1 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[1]));
- ASTNode t2 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[2]));
- output = CreateSimplifiedTermITE(c,t1,t2);
- break;
- }
- default: {
- output = CreateTerm(BVUMINUS,l,a0);
- break;
- }
- }
- break;
- }
- case BVEXTRACT:{
- //it is important to take care of wordlevel transformation in
- //BVEXTRACT. it exposes oppurtunities for later simplification
- //and solving (variable elimination)
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- Kind k1 = a0.GetKind();
- unsigned int a_len = inputValueWidth;
-
- //indices for BVEXTRACT
- ASTNode i = inputterm[1];
- ASTNode j = inputterm[2];
- ASTNode zero = CreateBVConst(32,0);
- //recall that the indices of BVEXTRACT are always 32 bits
- //long. therefore doing a GetBVUnsigned is ok.
- unsigned int i_val = GetUnsignedConst(i);
- unsigned int j_val = GetUnsignedConst(j);
-
- // a0[i:0] and len(a0)=i+1, then return a0
- if(0 == j_val && a_len == a0.GetValueWidth())
- return a0;
-
- switch(k1) {
- case BVCONST: {
- //extract the constant
- output = BVConstEvaluator(CreateTerm(BVEXTRACT,a_len,a0,i,j));
- break;
- }
- case BVCONCAT:{
- //assumes concatenation is binary
- //
- //input is of the form a0[i:j]
- //
- //a0 is the conatentation t@u, and a0[0] is t, and a0[1] is u
- ASTNode t = a0[0];
- ASTNode u = a0[1];
- unsigned int len_a0 = a0.GetValueWidth();
- unsigned int len_u = u.GetValueWidth();
-
- if(len_u > i_val) {
- //Apply the following rule:
- // (t@u)[i:j] <==> u[i:j], if len(u) > i
- //
- output = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,u,i,j));
- }
- else if(len_a0 > i_val && j_val >= len_u) {
- //Apply the rule:
- // (t@u)[i:j] <==> t[i-len_u:j-len_u], if len(t@u) > i >= j >= len(u)
- i = CreateBVConst(32, i_val - len_u);
- j = CreateBVConst(32, j_val - len_u);
- output = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
- }
- else {
- //Apply the rule:
- // (t@u)[i:j] <==> t[i-len_u:0] @ u[len_u-1:j]
- i = CreateBVConst(32,i_val-len_u);
- ASTNode m = CreateBVConst(32, len_u-1);
- t = SimplifyTerm(CreateTerm(BVEXTRACT,i_val-len_u+1,t,i,zero));
- u = SimplifyTerm(CreateTerm(BVEXTRACT,len_u-j_val,u,m,j));
- output = CreateTerm(BVCONCAT,a_len,t,u);
- }
- break;
- }
- case BVPLUS:
- case BVMULT: {
- // (BVMULT(n,t,u))[i:j] <==> BVMULT(i+1,t[i:0],u[i:0])[i:j]
- //similar rule for BVPLUS
- ASTVec c = a0.GetChildren();
- ASTVec o;
- for(ASTVec::iterator jt=c.begin(),jtend=c.end();jt!=jtend;jt++) {
- ASTNode aaa = *jt;
- aaa = SimplifyTerm(CreateTerm(BVEXTRACT,i_val+1,aaa,i,zero));
- o.push_back(aaa);
- }
- output = CreateTerm(a0.GetKind(),i_val+1,o);
- if(j_val != 0) {
- //add extraction only if j is not zero
- output = CreateTerm(BVEXTRACT,a_len,output,i,j);
- }
- break;
- }
- case BVAND:
- case BVOR:
- case BVXOR: {
- //assumes these operators are binary
- //
- // (t op u)[i:j] <==> t[i:j] op u[i:j]
- ASTNode t = a0[0];
- ASTNode u = a0[1];
- t = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
- u = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,u,i,j));
- BVTypeCheck(t);
- BVTypeCheck(u);
- output = CreateTerm(k1,a_len,t,u);
- break;
- }
- case BVNEG:{
- // (~t)[i:j] <==> ~(t[i:j])
- ASTNode t = a0[0];
- t = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
- output = CreateTerm(BVNEG,a_len,t);
- break;
- }
- // case BVSX:{
-// //(BVSX(t,n)[i:j] <==> BVSX(t,i+1), if n >= i+1 and j=0
-// ASTNode t = a0[0];
-// unsigned int bvsx_len = a0.GetValueWidth();
-// if(bvsx_len < a_len) {
-// FatalError("SimplifyTerm: BVEXTRACT over BVSX:"
-// "the length of BVSX term must be greater than extract-len",inputterm);
-// }
-// if(j != zero) {
-// output = CreateTerm(BVEXTRACT,a_len,a0,i,j);
-// }
-// else {
-// output = CreateTerm(BVSX,a_len,t,CreateBVConst(32,a_len));
-// }
-// break;
-// }
- case ITE: {
- ASTNode t0 = a0[0];
- ASTNode t1 = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,a0[1],i,j));
- ASTNode t2 = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,a0[2],i,j));
- output = CreateSimplifiedTermITE(t0,t1,t2);
- break;
- }
- default: {
- output = CreateTerm(BVEXTRACT,a_len,a0,i,j);
- break;
- }
- }
- break;
- }
- case BVNEG: {
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- unsigned len = inputValueWidth;
- switch(a0.GetKind()) {
- case BVCONST:
- output = BVConstEvaluator(CreateTerm(BVNEG,len,a0));
- break;
- case BVNEG:
- output = a0[0];
- break;
- // case ITE: {
-// ASTNode cond = a0[0];
-// ASTNode thenpart = SimplifyTerm(CreateTerm(BVNEG,len,a0[1]));
-// ASTNode elsepart = SimplifyTerm(CreateTerm(BVNEG,len,a0[2]));
-// output = CreateSimplifiedTermITE(cond,thenpart,elsepart);
-// break;
-// }
- default:
- output = CreateTerm(BVNEG,len,a0);
- break;
- }
- break;
- }
- case BVSX:{
- //a0 is the expr which is being sign extended
- ASTNode a0 = SimplifyTerm(inputterm[0]);
- //a1 represents the length of the term BVSX(a0)
- ASTNode a1 = inputterm[1];
- //output length of the BVSX term
- unsigned len = inputValueWidth;
-
- if(a0.GetValueWidth() == len) {
- //nothing to signextend
- return a0;
- }
-
- switch(a0.GetKind()) {
- case BVCONST:
- output = BVConstEvaluator(CreateTerm(BVSX,len,a0,a1));
- break;
- case BVNEG:
- output = CreateTerm(a0.GetKind(),len,CreateTerm(BVSX,len,a0[0],a1));
- break;
- case BVAND:
- case BVOR:
- //assuming BVAND and BVOR are binary
- output = CreateTerm(a0.GetKind(),len,
- CreateTerm(BVSX,len,a0[0],a1),
- CreateTerm(BVSX,len,a0[1],a1));
- break;
- case BVPLUS: {
- //BVSX(m,BVPLUS(n,BVSX(t1),BVSX(t2))) <==> BVPLUS(m,BVSX(m,t1),BVSX(m,t2))
- ASTVec c = a0.GetChildren();
- bool returnflag = false;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- if(BVSX != it->GetKind()) {
- returnflag = true;
- break;
- }
- }
- if(returnflag) {
- output = CreateTerm(BVSX,len,a0,a1);
- }
- else {
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(CreateTerm(BVSX,len,*it,a1));
- o.push_back(aaa);
- }
- output = CreateTerm(a0.GetKind(),len,o);
- }
- break;
- }
- case BVSX: {
- //if you have BVSX(m,BVSX(n,a)) then you can drop the inner
- //BVSX provided m is greater than n.
- a0 = SimplifyTerm(a0[0]);
- output = CreateTerm(BVSX,len,a0,a1);
- break;
- }
- case ITE: {
- ASTNode cond = a0[0];
- ASTNode thenpart = SimplifyTerm(CreateTerm(BVSX,len,a0[1],a1));
- ASTNode elsepart = SimplifyTerm(CreateTerm(BVSX,len,a0[2],a1));
- output = CreateSimplifiedTermITE(cond,thenpart,elsepart);
- break;
- }
- default:
- output = CreateTerm(BVSX,len,a0,a1);
- break;
- }
- break;
- }
- case BVAND:
- case BVOR:{
- ASTNode max = CreateMaxConst(inputValueWidth);
- ASTNode zero = CreateZeroConst(inputValueWidth);
-
- ASTNode identity = (BVAND == k) ? max : zero;
- ASTNode annihilator = (BVAND == k) ? zero : max;
- ASTVec c = FlattenOneLevel(inputterm).GetChildren();
- SortByExprNum(c);
- ASTVec o;
- bool constant = true;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- if(BVCONST != aaa.GetKind()) {
- constant = false;
- }
-
- if(aaa == annihilator) {
- output = annihilator;
- //memoize
- UpdateSimplifyMap(inputterm,output,false);
- //cerr << "output of SimplifyTerm: " << output << endl;
- return output;
- }
-
- if(aaa != identity) {
- o.push_back(aaa);
- }
- }
-
- switch(o.size()) {
- case 0:
- output = identity;
- break;
- case 1:
- output = o[0];
- break;
- default:
- SortByExprNum(o);
- output = CreateTerm(k,inputValueWidth,o);
- if(constant) {
- output = BVConstEvaluator(output);
- }
- break;
- }
- break;
- }
- case BVCONCAT:{
- ASTNode t = SimplifyTerm(inputterm[0]);
- ASTNode u = SimplifyTerm(inputterm[1]);
- Kind tkind = t.GetKind();
- Kind ukind = u.GetKind();
-
-
- if(BVCONST == tkind && BVCONST == ukind) {
- output = BVConstEvaluator(CreateTerm(BVCONCAT,inputValueWidth,t,u));
- }
- else if(BVEXTRACT == tkind &&
- BVEXTRACT == ukind &&
- t[0] == u[0]) {
- //to handle the case x[m:n]@x[n-1:k] <==> x[m:k]
- ASTNode t_hi = t[1];
- ASTNode t_low = t[2];
- ASTNode u_hi = u[1];
- ASTNode u_low = u[2];
- ASTNode c = BVConstEvaluator(CreateTerm(BVPLUS,32,u_hi,CreateOneConst(32)));
- if(t_low == c) {
- output = CreateTerm(BVEXTRACT,inputValueWidth,t[0],t_hi,u_low);
- }
- else {
- output = CreateTerm(BVCONCAT,inputValueWidth,t,u);
- }
- }
- else {
- output = CreateTerm(BVCONCAT,inputValueWidth,t,u);
- }
- break;
- }
- case BVXOR:
- case BVXNOR:
- case BVNAND:
- case BVNOR:
- case BVLEFTSHIFT:
- case BVRIGHTSHIFT:
- case BVVARSHIFT:
- case BVSRSHIFT:
- case BVDIV:
- case BVMOD: {
- ASTVec c = inputterm.GetChildren();
- ASTVec o;
- bool constant = true;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- if(BVCONST != aaa.GetKind()) {
- constant = false;
- }
- o.push_back(aaa);
- }
- output = CreateTerm(k,inputValueWidth,o);
- if(constant)
- output = BVConstEvaluator(output);
- break;
- }
- case READ: {
- ASTNode out1;
- //process only if not in the substitution map. simplifymap
- //has been checked already
- if(!CheckSubstitutionMap(inputterm,out1)) {
- if(WRITE == inputterm[0].GetKind()) {
- //get rid of all writes
- ASTNode nowrites = RemoveWrites_TopLevel(inputterm);
- out1 = nowrites;
- }
- else if (ITE == inputterm[0].GetKind()){
- ASTNode cond = SimplifyFormula(inputterm[0][0],false);
- ASTNode arr1 = SimplifyTerm(inputterm[0][1]);
- ASTNode arr2 = SimplifyTerm(inputterm[0][2]);
-
- ASTNode index = SimplifyTerm(inputterm[1]);
-
- ASTNode read1 = CreateTerm(READ,inputValueWidth,arr1,index);
- ASTNode read2 = CreateTerm(READ,inputValueWidth,arr2,index);
- out1 = CreateSimplifiedTermITE(cond,read1,read2);
- }
- else {
- //arr is a SYMBOL for sure
- ASTNode arr = inputterm[0];
- ASTNode index = SimplifyTerm(inputterm[1]);
- out1 = CreateTerm(READ,inputValueWidth,arr,index);
- }
- }
- //it is possible that after all the procesing the READ term
- //reduces to READ(Symbol,const) and hence we should check the
- //substitutionmap once again.
- if(!CheckSubstitutionMap(out1,output))
- output = out1;
- break;
- }
- case ITE: {
- ASTNode t0 = SimplifyFormula(inputterm[0],false);
- ASTNode t1 = SimplifyTerm(inputterm[1]);
- ASTNode t2 = SimplifyTerm(inputterm[2]);
- output = CreateSimplifiedTermITE(t0,t1,t2);
- break;
- }
- case SBVMOD:
- case SBVDIV: {
- ASTVec c = inputterm.GetChildren();
- ASTVec o;
- for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
- ASTNode aaa = SimplifyTerm(*it);
- o.push_back(aaa);
- }
- output = CreateTerm(k,inputValueWidth,o);
- break;
- }
- case WRITE:
- default:
- FatalError("SimplifyTerm: Control should never reach here:", inputterm, k);
- return inputterm;
- break;
- }
-
- //memoize
- UpdateSimplifyMap(inputterm,output,false);
- //cerr << "SimplifyTerm: output" << output << endl;
- return output;
- } //end of SimplifyTerm()
-
-
- //At the end of each simplification call, we want the output to be
- //always smaller or equal to the input in size.
- void BeevMgr::CheckSimplifyInvariant(const ASTNode& a, const ASTNode& output) {
- //Don't do the check in optimized mode
- if(optimize)
- return;
-
- if(NodeSize(a,true) < NodeSize(output,true)) {
- cerr << "lhs := " << a << endl;
- cerr << "NodeSize of lhs is: " << NodeSize(a, true) << endl;
- cerr << endl;
- cerr << "rhs := " << output << endl;
- cerr << "NodeSize of rhs is: " << NodeSize(output, true) << endl;
- FatalError("SimplifyFormula: The nodesize shoudl decrease from lhs to rhs: ",ASTUndefined);
- }
- }
-
- //this function assumes that the input is a vector of childnodes of
- //a BVPLUS term. it combines like terms and returns a bvplus
- //term. e.g. 1.x + 2.x is converted to 3.x
- ASTNode BeevMgr::CombineLikeTerms(const ASTNode& a) {
- if(BVPLUS != a.GetKind())
- return a;
-
- ASTNode output;
- if(CheckSimplifyMap(a,output,false)) {
- //check memo table
- //cerr << "output of SimplifyTerm Cache: " << output << endl;
- return output;
- }
-
- ASTVec c = a.GetChildren();
- //map from variables to vector of constants
- ASTNodeToVecMap vars_to_consts;
- //vector to hold constants
- ASTVec constkids;
- ASTVec outputvec;
-
- //useful constants
- unsigned int len = c[0].GetValueWidth();
- ASTNode one = CreateOneConst(len);
- ASTNode zero = CreateZeroConst(len);
- ASTNode max = CreateMaxConst(len);
-
- //go over the childnodes of the input bvplus, and collect like
- //terms in a map. the key of the map are the variables, and the
- //values are stored in a ASTVec
- for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++){
- ASTNode aaa = *it;
- if(SYMBOL == aaa.GetKind()) {
- vars_to_consts[aaa].push_back(one);
- }
- else if(BVMULT == aaa.GetKind() &&
- BVUMINUS == aaa[0].GetKind() &&
- BVCONST == aaa[0][0].GetKind()) {
- //(BVUMINUS(c))*(y) <==> compute(BVUMINUS(c))*y
- ASTNode compute_const = BVConstEvaluator(aaa[0]);
- vars_to_consts[aaa[1]].push_back(compute_const);
- }
- else if(BVMULT == aaa.GetKind() &&
- BVUMINUS == aaa[1].GetKind() &&
- BVCONST == aaa[0].GetKind()) {
- //c*(BVUMINUS(y)) <==> compute(BVUMINUS(c))*y
- ASTNode cccc = BVConstEvaluator(CreateTerm(BVUMINUS,len,aaa[0]));
- vars_to_consts[aaa[1][0]].push_back(cccc);
- }
- else if(BVMULT == aaa.GetKind() && BVCONST == aaa[0].GetKind()) {
- //assumes that BVMULT is binary
- vars_to_consts[aaa[1]].push_back(aaa[0]);
- }
- else if(BVMULT == aaa.GetKind() && BVUMINUS == aaa[0].GetKind()) {
- //(-1*x)*(y) <==> -1*(xy)
- ASTNode cccc = CreateTerm(BVMULT,len,aaa[0][0],aaa[1]);
- ASTVec cNodes = cccc.GetChildren();
- SortByExprNum(cNodes);
- vars_to_consts[cccc].push_back(max);
- }
- else if(BVMULT == aaa.GetKind() && BVUMINUS == aaa[1].GetKind()) {
- //x*(-1*y) <==> -1*(xy)
- ASTNode cccc = CreateTerm(BVMULT,len,aaa[0],aaa[1][0]);
- ASTVec cNodes = cccc.GetChildren();
- SortByExprNum(cNodes);
- vars_to_consts[cccc].push_back(max);
- }
- else if(BVCONST == aaa.GetKind()) {
- constkids.push_back(aaa);
- }
- else if(BVUMINUS == aaa.GetKind()) {
- //helps to convert BVUMINUS into a BVMULT. here the max
- //constant represents -1. this transformation allows us to
- //conclude that x + BVUMINUS(x) is 0.
- vars_to_consts[aaa[0]].push_back(max);
- }
- else
- vars_to_consts[aaa].push_back(one);
- } //end of for loop
-
- //go over the map from variables to vector of values. combine the
- //vector of values, multiply to the variable, and put the
- //resultant monomial in the output BVPLUS.
- for(ASTNodeToVecMap::iterator it=vars_to_consts.begin(),itend=vars_to_consts.end();
- it!=itend;it++){
- ASTVec ccc = it->second;
-
- ASTNode constant;
- if(1 < ccc.size()) {
- constant = CreateTerm(BVPLUS,ccc[0].GetValueWidth(),ccc);
- constant = BVConstEvaluator(constant);
- }
- else
- constant = ccc[0];
-
- //constant * var
- ASTNode monom;
- if(zero == constant)
- monom = zero;
- else if (one == constant)
- monom = it->first;
- else
- monom =
- SimplifyTerm(CreateTerm(BVMULT,constant.GetValueWidth(),constant,it->first));
- if(zero != monom) {
- outputvec.push_back(monom);
- }
- } //end of for loop
-
- if(constkids.size() > 1) {
- ASTNode output = CreateTerm(BVPLUS,constkids[0].GetValueWidth(),constkids);
- output = BVConstEvaluator(output);
- if(output != zero)
- outputvec.push_back(output);
- }
- else if (constkids.size() == 1) {
- if(constkids[0] != zero)
- outputvec.push_back(constkids[0]);
- }
-
- if (outputvec.size() > 1) {
- output = CreateTerm(BVPLUS,len,outputvec);
- }
- else if(outputvec.size() == 1) {
- output = outputvec[0];
- }
- else {
- output = zero;
- }
-
- //memoize
- //UpdateSimplifyMap(a,output,false);
- return output;
- } //end of CombineLikeTerms()
-
- //accepts lhs and rhs, and returns lhs - rhs = 0. The function
- //assumes that lhs and rhs have already been simplified. although
- //this assumption is not needed for correctness, it is essential for
- //performance. The function also assumes that lhs is a BVPLUS
- ASTNode BeevMgr::LhsMinusRhs(const ASTNode& eq) {
- //if input is not an equality, simply return it
- if(EQ != eq.GetKind())
- return eq;
-
- ASTNode lhs = eq[0];
- ASTNode rhs = eq[1];
- Kind k_lhs = lhs.GetKind();
- Kind k_rhs = rhs.GetKind();
- //either the lhs has to be a BVPLUS or the rhs has to be a
- //BVPLUS
- if(!(BVPLUS == k_lhs ||
- BVPLUS == k_rhs ||
- (BVMULT == k_lhs &&
- BVMULT == k_rhs)
- )) {
- return eq;
- }
-
- ASTNode output;
- if(CheckSimplifyMap(eq,output,false)) {
- //check memo table
- //cerr << "output of SimplifyTerm Cache: " << output << endl;
- return output;
- }
-
- //if the lhs is not a BVPLUS, but the rhs is a BVPLUS, then swap
- //the lhs and rhs
- bool swap_flag = false;
- if(BVPLUS != k_lhs && BVPLUS == k_rhs) {
- ASTNode swap = lhs;
- lhs = rhs;
- rhs = swap;
- swap_flag = true;
- }
-
- unsigned int len = lhs.GetValueWidth();
- ASTNode zero = CreateZeroConst(len);
- //right is -1*(rhs): Simplify(-1*rhs)
- rhs = SimplifyTerm(CreateTerm(BVUMINUS,len,rhs));
-
- ASTVec lvec = lhs.GetChildren();
- ASTVec rvec = rhs.GetChildren();
- ASTNode lhsplusrhs;
- if(BVPLUS != lhs.GetKind() && BVPLUS != rhs.GetKind()) {
- lhsplusrhs = CreateTerm(BVPLUS,len,lhs,rhs);
- }
- else if(BVPLUS == lhs.GetKind() && BVPLUS == rhs.GetKind()) {
- //combine the childnodes of the left and the right
- lvec.insert(lvec.end(),rvec.begin(),rvec.end());
- lhsplusrhs = CreateTerm(BVPLUS,len,lvec);
- }
- else if(BVPLUS == lhs.GetKind() && BVPLUS != rhs.GetKind()){
- lvec.push_back(rhs);
- lhsplusrhs = CreateTerm(BVPLUS,len,lvec);
- }
- else {
- //Control should never reach here
- FatalError("LhsMinusRhs: Control should never reach here\n");
- }
-
- //combine like terms
- output = CombineLikeTerms(lhsplusrhs);
- output = SimplifyTerm(output);
- //
- //Now make output into: lhs-rhs = 0
- output = CreateSimplifiedEQ(output,zero);
- //sort if BVPLUS
- if(BVPLUS == output.GetKind()) {
- ASTVec outv = output.GetChildren();
- SortByExprNum(outv);
- output = CreateTerm(BVPLUS,len,outv);
- }
-
- //memoize
- //UpdateSimplifyMap(eq,output,false);
- return output;
- } //end of LhsMinusRHS()
-
- //THis function accepts a BVMULT(t1,t2) and distributes the mult
- //over plus if either or both t1 and t2 are BVPLUSes.
- //
- // x*(y1 + y2 + ...+ yn) <==> x*y1 + x*y2 + ... + x*yn
- //
- // (y1 + y2 + ...+ yn)*x <==> x*y1 + x*y2 + ... + x*yn
- //
- // The function assumes that the BVPLUSes have been flattened
- ASTNode BeevMgr::DistributeMultOverPlus(const ASTNode& a, bool startdistribution) {
- if(!startdistribution)
- return a;
- Kind k = a.GetKind();
- if(BVMULT != k)
- return a;
-
- ASTNode left = a[0];
- ASTNode right = a[1];
- Kind left_kind = left.GetKind();
- Kind right_kind = right.GetKind();
-
- ASTNode output;
- if(CheckSimplifyMap(a,output,false)) {
- //check memo table
- //cerr << "output of SimplifyTerm Cache: " << output << endl;
- return output;
- }
-
- //special case optimization: c1*(c2*t1) <==> (c1*c2)*t1
- if(BVCONST == left_kind &&
- BVMULT == right_kind &&
- BVCONST == right[0].GetKind()) {
- ASTNode c = BVConstEvaluator(CreateTerm(BVMULT,a.GetValueWidth(),left,right[0]));
- c = CreateTerm(BVMULT,a.GetValueWidth(),c,right[1]);
- return c;
- left = c[0];
- right = c[1];
- left_kind = left.GetKind();
- right_kind = right.GetKind();
- }
-
- //special case optimization: c1*(t1*c2) <==> (c1*c2)*t1
- if(BVCONST == left_kind &&
- BVMULT == right_kind &&
- BVCONST == right[1].GetKind()) {
- ASTNode c = BVConstEvaluator(CreateTerm(BVMULT,a.GetValueWidth(),left,right[1]));
- c = CreateTerm(BVMULT,a.GetValueWidth(),c,right[0]);
- return c;
- left = c[0];
- right = c[1];
- left_kind = left.GetKind();
- right_kind = right.GetKind();
- }
-
- //atleast one of left or right have to be BVPLUS
- if(!(BVPLUS == left_kind || BVPLUS == right_kind)) {
- return a;
- }
-
- //if left is BVPLUS and right is not, then swap left and right. we
- //can do this since BVMULT is communtative
- ASTNode swap;
- if(BVPLUS == left_kind && BVPLUS != right_kind) {
- swap = left;
- left = right;
- right = swap;
- }
- left_kind = left.GetKind();
- right_kind = right.GetKind();
-
- //by this point we are gauranteed that right is a BVPLUS, but left
- //may not be
- ASTVec rightnodes = right.GetChildren();
- ASTVec outputvec;
- unsigned len = a.GetValueWidth();
- ASTNode zero = CreateZeroConst(len);
- ASTNode one = CreateOneConst(len);
- if(BVPLUS != left_kind) {
- //if the multiplier is not a BVPLUS then we have a special case
- // x*(y1 + y2 + ...+ yn) <==> x*y1 + x*y2 + ... + x*yn
- if(zero == left) {
- outputvec.push_back(zero);
- }
- else if(one == left) {
- outputvec.push_back(left);
- }
- else {
- for(ASTVec::iterator j=rightnodes.begin(),jend=rightnodes.end();
- j!=jend;j++) {
- ASTNode out = SimplifyTerm(CreateTerm(BVMULT,len,left,*j));
- outputvec.push_back(out);
- }
- }
- }
- else {
- ASTVec leftnodes = left.GetChildren();
- // (x1 + x2 + ... + xm)*(y1 + y2 + ...+ yn) <==> x1*y1 + x1*y2 +
- // ... + x2*y1 + ... + xm*yn
- for(ASTVec::iterator i=leftnodes.begin(),iend=leftnodes.end();
- i!=iend;i++) {
- ASTNode multiplier = *i;
- for(ASTVec::iterator j=rightnodes.begin(),jend=rightnodes.end();
- j!=jend;j++) {
- ASTNode out = SimplifyTerm(CreateTerm(BVMULT,len,multiplier,*j));
- outputvec.push_back(out);
- }
- }
- }
-
- //compute output here
- if(outputvec.size() > 1) {
- output = CombineLikeTerms(CreateTerm(BVPLUS,len,outputvec));
- output = SimplifyTerm(output);
- }
- else
- output = SimplifyTerm(outputvec[0]);
-
- //memoize
- //UpdateSimplifyMap(a,output,false);
- return output;
- } //end of distributemultoverplus()
-
- //converts the BVSX(len, a0) operator into ITE( check top bit,
- //extend a0 by 1, extend a0 by 0)
- ASTNode BeevMgr::ConvertBVSXToITE(const ASTNode& a) {
- if(BVSX != a.GetKind())
- return a;
-
- ASTNode output;
- if(CheckSimplifyMap(a,output,false)) {
- //check memo table
- //cerr << "output of ConvertBVSXToITE Cache: " << output << endl;
- return output;
- }
-
- ASTNode a0 = a[0];
- unsigned a_len = a.GetValueWidth();
- unsigned a0_len = a0.GetValueWidth();
-
- if(a0_len > a_len){
- FatalError("Trying to sign_extend a larger BV into a smaller BV");
- return ASTUndefined; //to stop the compiler from producing bogus warnings
- }
-
- //sign extend
- unsigned extensionlen = a_len-a0_len;
- if(0 == extensionlen) {
- UpdateSimplifyMap(a,output,false);
- return a;
- }
-
- std::string ones;
- for(unsigned c=0; c < extensionlen;c++)
- ones += '1';
- std::string zeros;
- for(unsigned c=0; c < extensionlen;c++)
- zeros += '0';
-
- //string of oness of length extensionlen
- BEEV::ASTNode BVOnes = CreateBVConst(ones.c_str(),2);
- //string of zeros of length extensionlen
- BEEV::ASTNode BVZeros = CreateBVConst(zeros.c_str(),2);
-
- //string of ones BVCONCAT a0
- BEEV::ASTNode concatOnes = CreateTerm(BEEV::BVCONCAT,a_len,BVOnes,a0);
- //string of zeros BVCONCAT a0
- BEEV::ASTNode concatZeros = CreateTerm(BEEV::BVCONCAT,a_len,BVZeros,a0);
-
- //extract top bit of a0
- BEEV::ASTNode hi = CreateBVConst(32,a0_len-1);
- BEEV::ASTNode low = CreateBVConst(32,a0_len-1);
- BEEV::ASTNode topBit = CreateTerm(BEEV::BVEXTRACT,1,a0,hi,low);
-
- //compare topBit of a0 with 0bin1
- BEEV::ASTNode condition = CreateSimplifiedEQ(CreateBVConst(1,1),topBit);
-
- //ITE(topbit = 0bin1, 0bin1111...a0, 0bin000...a0)
- output = CreateSimplifiedTermITE(condition,concatOnes,concatZeros);
- UpdateSimplifyMap(a,output,false);
- return output;
- } //end of ConvertBVSXToITE()
-
-
- ASTNode BeevMgr::RemoveWrites_TopLevel(const ASTNode& term) {
- if(READ != term.GetKind() && WRITE != term[0].GetKind()) {
- FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
- }
-
- if(!Begin_RemoveWrites &&
- !SimplifyWrites_InPlace_Flag &&
- !start_abstracting) {
- return term;
- }
- else if(!Begin_RemoveWrites &&
- SimplifyWrites_InPlace_Flag &&
- !start_abstracting) {
- //return term;
- return SimplifyWrites_InPlace(term);
- }
- else {
- return RemoveWrites(term);
- }
- } //end of RemoveWrites_TopLevel()
-
- ASTNode BeevMgr::SimplifyWrites_InPlace(const ASTNode& term) {
- ASTNodeMultiSet WriteIndicesSeenSoFar;
- bool SeenNonConstWriteIndex = false;
-
- if(READ != term.GetKind() &&
- WRITE != term[0].GetKind()) {
- FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
- }
-
- ASTNode output;
- if(CheckSimplifyMap(term,output,false)) {
- return output;
- }
-
- ASTVec writeIndices, writeValues;
- unsigned int width = term.GetValueWidth();
- ASTNode write = term[0];
- unsigned indexwidth = write.GetIndexWidth();
- ASTNode readIndex = SimplifyTerm(term[1]);
-
- do {
- ASTNode writeIndex = SimplifyTerm(write[1]);
- ASTNode writeVal = SimplifyTerm(write[2]);
-
- //compare the readIndex and the current writeIndex and see if they
- //simplify to TRUE or FALSE or UNDETERMINABLE at this stage
- ASTNode compare_readwrite_indices =
- SimplifyFormula(CreateSimplifiedEQ(writeIndex,readIndex),false);
-
- //if readIndex and writeIndex are equal
- if(ASTTrue == compare_readwrite_indices && !SeenNonConstWriteIndex) {
- UpdateSimplifyMap(term,writeVal,false);
- return writeVal;
- }
-
- if(!(ASTTrue == compare_readwrite_indices ||
- ASTFalse == compare_readwrite_indices)) {
- SeenNonConstWriteIndex = true;
- }
-
- //if (readIndex=writeIndex <=> FALSE)
- if(ASTFalse == compare_readwrite_indices
- ||
- (WriteIndicesSeenSoFar.find(writeIndex) != WriteIndicesSeenSoFar.end())
- ) {
- //drop the current level write
- //do nothing
- }
- else {
- writeIndices.push_back(writeIndex);
- writeValues.push_back(writeVal);
- }
-
- //record the write indices seen so far
- //if(BVCONST == writeIndex.GetKind()) {
- WriteIndicesSeenSoFar.insert(writeIndex);
- //}
-
- //Setup the write for the new iteration, one level inner write
- write = write[0];
- }while (SYMBOL != write.GetKind());
-
- ASTVec::reverse_iterator it_index = writeIndices.rbegin();
- ASTVec::reverse_iterator itend_index = writeIndices.rend();
- ASTVec::reverse_iterator it_values = writeValues.rbegin();
- ASTVec::reverse_iterator itend_values = writeValues.rend();
-
- //"write" must be a symbol at the control point before the
- //begining of the "for loop"
-
- for(;it_index!=itend_index;it_index++,it_values++) {
- write = CreateTerm(WRITE,width,write,*it_index,*it_values);
- write.SetIndexWidth(indexwidth);
- }
-
- output = CreateTerm(READ,width,write,readIndex);
- UpdateSimplifyMap(term,output,false);
- return output;
- } //end of SimplifyWrites_In_Place()
-
- //accepts a read over a write and returns a term without the write
- //READ(WRITE(A i val) j) <==> ITE(i=j,val,READ(A,j)). We use a memo
- //table for this function called RemoveWritesMemoMap
- ASTNode BeevMgr::RemoveWrites(const ASTNode& input) {
- //unsigned int width = input.GetValueWidth();
- if(READ != input.GetKind() || WRITE != input[0].GetKind()) {
- FatalError("RemovesWrites: Input must be a READ over a WRITE",input);
- }
-
- ASTNodeMap::iterator it;
- ASTNode output = input;
- if(CheckSimplifyMap(input,output,false)) {
- return output;
- }
-
- if(!start_abstracting && Begin_RemoveWrites) {
- output= ReadOverWrite_To_ITE(input);
- }
-
- if(start_abstracting) {
- ASTNode newVar;
- if(!CheckSimplifyMap(input,newVar,false)) {
- newVar = NewVar(input.GetValueWidth());
- ReadOverWrite_NewName_Map[input] = newVar;
- NewName_ReadOverWrite_Map[newVar] = input;
-
- UpdateSimplifyMap(input,newVar,false);
- ASTNodeStats("New Var Name which replace Read_Over_Write: ", newVar);
- }
- output = newVar;
- } //end of start_abstracting if condition
-
- //memoize
- UpdateSimplifyMap(input,output,false);
- return output;
- } //end of RemoveWrites()
-
- ASTNode BeevMgr::ReadOverWrite_To_ITE(const ASTNode& term) {
- unsigned int width = term.GetValueWidth();
- ASTNode input = term;
- if(READ != term.GetKind() || WRITE != term[0].GetKind()) {
- FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
- }
-
- ASTNodeMap::iterator it;
- ASTNode output;
- // if(CheckSimplifyMap(term,output,false)) {
- // return output;
- // }
-
- ASTNode partialITE = term;
- ASTNode writeA = ASTTrue;
- ASTNode oldRead = term;
- //iteratively expand read-over-write
- do {
- ASTNode write = input[0];
- ASTNode readIndex = SimplifyTerm(input[1]);
- //DO NOT CALL SimplifyTerm() on write[0]. You will go into an
- //infinite loop
- writeA = write[0];
- ASTNode writeIndex = SimplifyTerm(write[1]);
- ASTNode writeVal = SimplifyTerm(write[2]);
-
- ASTNode cond = SimplifyFormula(CreateSimplifiedEQ(writeIndex,readIndex),false);
- ASTNode newRead = CreateTerm(READ,width,writeA,readIndex);
- ASTNode newRead_memoized = newRead;
- if(CheckSimplifyMap(newRead, newRead_memoized,false)) {
- newRead = newRead_memoized;
- }
-
- if(ASTTrue == cond && (term == partialITE)) {
- //found the write-value in the first iteration itself. return
- //it
- output = writeVal;
- UpdateSimplifyMap(term,output,false);
- return output;
- }
-
- if(READ == partialITE.GetKind() && WRITE == partialITE[0].GetKind()) {
- //first iteration or (previous cond==ASTFALSE and partialITE is a "READ over WRITE")
- partialITE = CreateSimplifiedTermITE(cond, writeVal, newRead);
- }
- else if (ITE == partialITE.GetKind()){
- //ITE(i1 = j, v1, R(A,j))
- ASTNode ElseITE = CreateSimplifiedTermITE(cond, writeVal, newRead);
- //R(W(A,i1,v1),j) <==> ITE(i1 = j, v1, R(A,j))
- UpdateSimplifyMap(oldRead,ElseITE,false);
- //ITE(i2 = j, v2, R(W(A,i1,v1),j)) <==> ITE(i2 = j, v2, ITE(i1 = j, v1, R(A,j)))
- partialITE = SimplifyTerm(partialITE);
- }
- else {
- FatalError("RemoveWrites: Control should not reach here\n");
- }
-
- if(ASTTrue == cond) {
- //no more iterations required
- output = partialITE;
- UpdateSimplifyMap(term,output,false);
- return output;
- }
-
- input = newRead;
- oldRead = newRead;
- } while(READ == input.GetKind() && WRITE == input[0].GetKind());
-
- output = partialITE;
-
- //memoize
- //UpdateSimplifyMap(term,output,false);
- return output;
- } //ReadOverWrite_To_ITE()
-
- //compute the multiplicative inverse of the input
- ASTNode BeevMgr::MultiplicativeInverse(const ASTNode& d) {
- ASTNode c = d;
- if(BVCONST != c.GetKind()) {
- FatalError("Input must be a constant", c);
- }
-
- if(!BVConstIsOdd(c)) {
- FatalError("MultiplicativeInverse: Input must be odd: ",c);
- }
-
- //cerr << "input to multinverse function is: " << d << endl;
- ASTNode inverse;
- if(CheckMultInverseMap(d,inverse)) {
- //cerr << "found the inverse of: " << d << "and it is: " << inverse << endl;
- return inverse;
- }
-
- inverse = c;
- unsigned inputwidth = c.GetValueWidth();
-
-#ifdef NATIVE_C_ARITH
- ASTNode one = CreateOneConst(inputwidth);
- while(c != one) {
- //c = c*c
- c = BVConstEvaluator(CreateTerm(BVMULT,inputwidth,c,c));
- //inverse = invsere*c
- inverse = BVConstEvaluator(CreateTerm(BVMULT,inputwidth,inverse,c));
- }
-#else
- //Compute the multiplicative inverse of c using the extended
- //euclidian algorithm
- //
- //create a '0' which is 1 bit long
- ASTNode onebit_zero = CreateZeroConst(1);
- //zero pad t0, i.e. 0 @ t0
- c = BVConstEvaluator(CreateTerm(BVCONCAT,inputwidth+1,onebit_zero,c));
-
- //construct 2^(inputwidth), i.e. a bitvector of length
- //'inputwidth+1', which is max(inputwidth)+1
- //
- //all 1's
- ASTNode max = CreateMaxConst(inputwidth);
- //zero pad max
- max = BVConstEvaluator(CreateTerm(BVCONCAT,inputwidth+1,onebit_zero,max));
- //Create a '1' which has leading zeros of length 'inputwidth'
- ASTNode inputwidthplusone_one = CreateOneConst(inputwidth+1);
- //add 1 to max
- max = CreateTerm(BVPLUS,inputwidth+1,max,inputwidthplusone_one);
- max = BVConstEvaluator(max);
-
- ASTNode zero = CreateZeroConst(inputwidth+1);
- ASTNode max_bvgt_0 = CreateNode(BVGT,max,zero);
- ASTNode quotient, remainder;
- ASTNode x, x1, x2;
-
- //x1 initialized to zero
- x1 = zero;
- //x2 initialized to one
- x2 = CreateOneConst(inputwidth+1);
- while (ASTTrue == BVConstEvaluator(max_bvgt_0)) {
- //quotient = (c divided by max)
- quotient = BVConstEvaluator(CreateTerm(BVDIV,inputwidth+1, c, max));
-
- //remainder of (c divided by max)
- remainder = BVConstEvaluator(CreateTerm(BVMOD,inputwidth+1, c, max));
-
- //x = x2 - q*x1
- x = CreateTerm(BVSUB,inputwidth+1,x2,CreateTerm(BVMULT,inputwidth+1,quotient,x1));
- x = BVConstEvaluator(x);
-
- //fix the inputs to the extended euclidian algo
- c = max;
- max = remainder;
- max_bvgt_0 = CreateNode(BVGT,max,zero);
-
- x2 = x1;
- x1 = x;
- }
-
- ASTNode hi = CreateBVConst(32,inputwidth-1);
- ASTNode low = CreateZeroConst(32);
- inverse = CreateTerm(BVEXTRACT,inputwidth,x2,hi,low);
- inverse = BVConstEvaluator(inverse);
-#endif
-
- UpdateMultInverseMap(d,inverse);
- //cerr << "output of multinverse function is: " << inverse << endl;
- return inverse;
- } //end of MultiplicativeInverse()
-
- //returns true if the input is odd
- bool BeevMgr::BVConstIsOdd(const ASTNode& c) {
- if(BVCONST != c.GetKind()) {
- FatalError("Input must be a constant", c);
- }
-
- ASTNode zero = CreateZeroConst(1);
- ASTNode hi = CreateZeroConst(32);
- ASTNode low = hi;
- ASTNode lowestbit = CreateTerm(BVEXTRACT,1,c,hi,low);
- lowestbit = BVConstEvaluator(lowestbit);
-
- if(lowestbit == zero) {
- return false;
- }
- else {
- return true;
- }
- } //end of BVConstIsOdd()
-
- //The big substitution function
- ASTNode BeevMgr::CreateSubstitutionMap(const ASTNode& a){
- if(!optimize)
- return a;
-
- ASTNode output = a;
- //if the variable has been solved for, then simply return it
- if(CheckSolverMap(a,output))
- return output;
-
- //traverse a and populate the SubstitutionMap
- Kind k = a.GetKind();
- if(SYMBOL == k && BOOLEAN_TYPE == a.GetType()) {
- bool updated = UpdateSubstitutionMap(a,ASTTrue);
- output = updated ? ASTTrue : a;
- return output;
- }
- if(NOT == k
- && SYMBOL == a[0].GetKind()) {
- bool updated = UpdateSubstitutionMap(a[0],ASTFalse);
- output = updated ? ASTTrue : a;
- return output;
- }
-
- if(IFF == k) {
- ASTVec c = a.GetChildren();
- SortByExprNum(c);
- if(SYMBOL != c[0].GetKind() ||
- VarSeenInTerm(c[0],SimplifyFormula_NoRemoveWrites(c[1],false))) {
- return a;
- }
- bool updated = UpdateSubstitutionMap(c[0],c[1]);
- output = updated ? ASTTrue : a;
- return output;
- }
-
- if(EQ == k) {
- //fill the arrayname readindices vector if e0 is a
- //READ(Arr,index) and index is a BVCONST
- ASTVec c = a.GetChildren();
- SortByExprNum(c);
- FillUp_ArrReadIndex_Vec(c[0],c[1]);
-
- if(SYMBOL == c[0].GetKind() &&
- VarSeenInTerm(c[0],SimplifyTerm(c[1]))) {
- return a;
- }
-
- if(1 == TermOrder(c[0],c[1]) &&
- READ == c[0].GetKind() &&
- VarSeenInTerm(c[0][0],SimplifyTerm(c[1]))) {
- return a;
- }
- bool updated = UpdateSubstitutionMap(c[0],c[1]);
- output = updated ? ASTTrue : a;
- return output;
- }
-
- if(AND == k){
- ASTVec o;
- ASTVec c = a.GetChildren();
- for(ASTVec::iterator it = c.begin(),itend=c.end();it!=itend;it++) {
- UpdateAlwaysTrueFormMap(*it);
- ASTNode aaa = CreateSubstitutionMap(*it);
-
- if(ASTTrue != aaa) {
- if(ASTFalse == aaa)
- return ASTFalse;
- else
- o.push_back(aaa);
- }
- }
- if(o.size() == 0)
- return ASTTrue;
-
- if(o.size() == 1)
- return o[0];
-
- return CreateNode(AND,o);
- }
- return output;
- } //end of CreateSubstitutionMap()
-
-
- bool BeevMgr::VarSeenInTerm(const ASTNode& var, const ASTNode& term) {
- if(READ == term.GetKind() &&
- WRITE == term[0].GetKind() && !Begin_RemoveWrites) {
- return false;
- }
-
- if(READ == term.GetKind() &&
- WRITE == term[0].GetKind() && Begin_RemoveWrites) {
- return true;
- }
-
- ASTNodeMap::iterator it;
- if((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end()) {
- if(it->second == var) {
- return false;
- }
- }
-
- if(var == term) {
- return true;
- }
-
- for(ASTVec::const_iterator it=term.begin(),itend=term.end();it!=itend;it++){
- if(VarSeenInTerm(var,*it)) {
- return true;
- }
- else {
- TermsAlreadySeenMap[*it] = var;
- }
- }
-
- TermsAlreadySeenMap[term] = var;
- return false;
- }
-} //end of namespace