/******************************************************************** * 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