Exemplo n.º 1
0
    // If the bits are totally fixed, then return a new matching ASTNode.
    ASTNode
    bitsToNode(const ASTNode& node, const FixedBits& bits)
    {
      ASTNode result;
      STPMgr & beev = *node.GetSTPMgr();

      assert (bits.isTotallyFixed());
      assert (!node.isConstant()); // Peformance. Shouldn't waste time calling it on constants.

      if (node.GetType() == BOOLEAN_TYPE)
        {
          if (bits.getValue(0))
            {
              result = beev.CreateNode(TRUE);
            }
          else
            {
              result = beev.CreateNode(FALSE);
            }
        }
      else if (node.GetType() == BITVECTOR_TYPE)
        {
          result = beev.CreateBVConst(bits.GetBVConst(), node.GetValueWidth());
        }
      else
        FatalError("sadf234s");

      assert(result.isConstant());
      return result;
    }
Exemplo n.º 2
0
// Adds to the dependency graph that n0 depends on the variables in n1.
// It's not the transitive closure of the dependencies. Just the variables in the expression "n1".
// This is only needed as long as all the substitution rules haven't been written through.
  void
  SubstitutionMap::buildDepends(const ASTNode& n0, const ASTNode& n1)
  {
    if (n0.GetKind() != SYMBOL)
      return;

    if (n1.isConstant())
      return;

    vector<Symbols*> av;
    vars.VarSeenInTerm(vars.getSymbol(n1), rhs_visited, rhs, av);

    sort(av.begin(), av.end());
    for (int i = 0; i < av.size(); i++)
      {
      if (i != 0 && av[i] == av[i - 1])
        continue; // Treat it like a set of Symbol* in effect.

      ASTNodeSet* sym = (vars.TermsAlreadySeenMap.find(av[i])->second);
      if (rhsAlreadyAdded.find(sym) != rhsAlreadyAdded.end())
        continue;
      rhsAlreadyAdded.insert(sym);

      //cout << loopCount++ << " ";
      //cout << "initial" << rhs.size() << " Adding: " <<sym->size();
      rhs.insert(sym->begin(), sym->end());
      //cout << "final:" << rhs.size();
      //cout << "added:" << sym << endl;

      }

    assert(dependsOn.find(n0) == dependsOn.end());
    dependsOn.insert(make_pair(n0, vars.getSymbol(n1)));
  }
Exemplo n.º 3
0
bool VariablesInExpression::VarSeenInTerm(const ASTNode& var,
		const ASTNode& term) {
	// This only returns true if we are searching for variables that aren't arrays.
	assert(var.GetKind() == SYMBOL && var.GetIndexWidth() == 0);
	if (term.isConstant())
		return false;

	getSymbol(term);

	SymbolPtrSet visited;
	ASTNodeSet *symbols = new ASTNodeSet();
	vector<Symbols*> av;
	VarSeenInTerm(symbol_graph[term.GetNodeNum()], visited, *symbols, av);

	bool result = (symbols->count(var) != 0);

	//cerr << "visited:" << visited.size() << endl;
	//cerr << "av:" << av.size() << endl;
	//cerr << "Term is const" << term.isConstant() << endl;


	if (visited.size() > 250) // No use caching it, unless we've done some work.
	{
		sort(av.begin(), av.end());

		//cout << "===" << endl;
		for (size_t i = 0; i < av.size(); i++) {
			if (i!=0 && av[i] == av[i-1])
				continue;

			const ASTNodeSet& sym = *TermsAlreadySeenMap.find(av[i])->second;
			//cout << "set: " << i << " " << sym.size() << endl;
			symbols->insert(sym.begin(), sym.end());
		}
		TermsAlreadySeenMap.insert(make_pair(symbol_graph[term.GetNodeNum()], symbols));
		//cout << "finish" << symbols->size() << endl;
		//cout << "===" << endl;
		result = (symbols->count(var) != 0);
	} else {
		const int size = av.size();
		for (int i = 0; i < size; i++) {
			if (result)
				break;
			const ASTNodeSet& sym = *TermsAlreadySeenMap.find(av[i])->second;
			result |= (sym.find(var) != sym.end());
		}
		delete symbols;
	}
	return result;
}
Exemplo n.º 4
0
// If n0 is replaced by n1 in the substitution map. Will it cause a loop?
// i.e. will the dependency graph be an acyclic graph still.
// For example, if we have x = F(y,z,w), it would make the substitutionMap loop
// if there's already z = F(x).
bool SubstitutionMap::loops(const ASTNode& n0, const ASTNode& n1)
{
  if (n0.GetKind() != SYMBOL)
    return false; // sometimes this function is called with constants on the
                  // lhs.

  if (n1.isConstant())
    return false; // constants contain no variables. Can't loop.

  // We are adding an edge FROM n0, so unless there is already an edge TO n0,
  // there is no change it can loop. Unless adding this would add a TO and FROM
  // edge.
  if (rhs.find(n0) == rhs.end())
  {
    return vars.VarSeenInTerm(n0, n1);
  }

  if (n1.GetKind() == SYMBOL && dependsOn.find(n1) == dependsOn.end())
    return false; // The rhs is a symbol and doesn't appear.

  if (debug_substn)
    cout << loopCount++ << endl;

  bool destruct = true;
  ASTNodeSet* dependN = vars.SetofVarsSeenInTerm(n1, destruct);

  if (debug_substn)
  {
    cout << n0 << " "
         << n1.GetNodeNum(); //<< " Expression size:" << bm->NodeSize(n1,true);
    cout << "Variables in expression: " << dependN->size() << endl;
  }

  set<ASTNode> depend(dependN->begin(), dependN->end());

  if (destruct)
    delete dependN;

  set<ASTNode> visited;
  loops_helper(depend, visited);

  bool loops = visited.find(n0) != visited.end();

  if (debug_substn)
    cout << "Visited:" << visited.size() << "Loops:" << loops << endl;

  return (loops);
}
void getSatVariables(const ASTNode& a, vector<unsigned>& v_a,
                     SATSolver& SatSolver, ToSATBase::ASTNodeToSATVar& satVar)
{
  ToSATBase::ASTNodeToSATVar::iterator it = satVar.find(a);
  if (it != satVar.end())
    v_a = it->second;
  else if (!a.isConstant())
  {
    assert(a.GetKind() == SYMBOL);
    // It was ommitted from the initial problem, so assign it freshly.
    for (unsigned i = 0; i < a.GetValueWidth(); i++)
    {
      uint32_t v = SatSolver.newVar();
      // We probably don't want the variable eliminated.
      SatSolver.setFrozen(v);
      v_a.push_back(v);
    }
    satVar.insert(make_pair(a, v_a));
  }
}
Exemplo n.º 6
0
void FindPureLiterals::build(const ASTNode& n, polarity_type polarity)
{
  if (n.isConstant())
    return;

  map<ASTNode, polarity_type>::iterator it = nodeToPolarity.find(n);
  if (it != nodeToPolarity.end())
  {
    int lookupPolarity = it->second;
    if ((polarity | lookupPolarity) == lookupPolarity)
      return; // already traversed.

    it->second |= polarity;
  }
  else
  {
    nodeToPolarity.insert(std::make_pair(n, polarity));
  }
  const Kind k = n.GetKind();
  switch (k)
  {
    case AND:
    case OR:
      for (size_t i = 0; i < n.Degree(); i++)
        build(n[i], polarity);
      break;

    case NOT:
      polarity = swap(polarity);
      build(n[0], polarity);
      break;

    default:
      polarity = bothPolarity; // both
      for (size_t i = 0; i < n.Degree(); i++)
        build(n[i], polarity);
      break;
  }
}
Exemplo n.º 7
0
  ASTNode
  RemoveUnconstrained::topLevel_other(const ASTNode &n, Simplifier *simplifier)
  {
    if (n.GetKind() == SYMBOL)
      return n; // top level is an unconstrained symbol/.

    simplifier_convenient = simplifier;

    ASTNodeSet noCheck; // We don't want to check some expensive nodes over and over again.

    vector<MutableASTNode*> variable_array;

    MutableASTNode* topMutable = MutableASTNode::build(n);

    vector<MutableASTNode*> extracts;
    topMutable->getDisjointExtractVariables(extracts);
    if (extracts.size() > 0)
      {
          splitExtractOnly(extracts);
      }

    topMutable->getAllUnconstrainedVariables(variable_array);

    for (int i =0; i < variable_array.size() ; i++)
      {
        // Don't make this is a reference. If the vector gets resized, it will point to
        // memory that no longer contains the object.
        MutableASTNode& muteNode = *variable_array[i];

        const ASTNode var = muteNode.n;
        assert(var.GetKind() == SYMBOL);

        if (!muteNode.isUnconstrained())
          continue;

        MutableASTNode& muteParent = muteNode.getParent();

        if (noCheck.find(muteParent.n) != noCheck.end())
          {
            continue;
          }

        vector <MutableASTNode*> mutable_children = muteParent.children;

        //nb. The children might be dirty. i.e. not have substitutions written through them yet.
        ASTVec children;
        children.reserve(mutable_children.size());
        for (int j = 0; j <mutable_children.size(); j++ )
          children.push_back(mutable_children[j]->n);

        const size_t numberOfChildren = children.size();
        const Kind kind = muteNode.getParent().n.GetKind();
        unsigned width = muteNode.getParent().n.GetValueWidth();
        unsigned indexWidth = muteNode.getParent().n.GetIndexWidth();

        ASTNode other;
        MutableASTNode* muteOther;

          if(numberOfChildren == 2)
          {
            if (children[0] != var)
              {
                other = children[0];
                muteOther = mutable_children[0];
              }
            else
              {
                other = children[1];
                muteOther = mutable_children[1];
              }

            if (kind != AND && kind != OR && kind != BVOR && kind != BVAND)
              if (other == var)
                continue; // Most rules don't like duplicate variables.
          }
        else
          {
            if (kind != AND && kind != OR && kind != BVOR && kind != BVAND)
              {
                  int found = 0;

                  for (int i = 0; i < numberOfChildren; i++)
                    {
                      if (children[i] == var)
                        found++;
                   }

                    if (found != 1)
                      continue; // Most rules don't like duplicate variables.
              }
          }

          /*
          cout << i << " " << kind << " " << variable_array.size() <<  " " << mutable_children.size() << endl;
          cout << "children[0]" << children[0] << endl;
          cout << "children[1]" << children[1] << endl;
          cout << muteParent.n << endl;

           */

        switch (kind)
          {
        case BVCONCAT:
          assert(numberOfChildren == 2);
          if (mutable_children[0]->isUnconstrained() && (mutable_children[1]->isUnconstrained()))
            {
              ASTNode v =replaceParentWithFresh(muteParent, variable_array);

              ASTNode top_lhs = bm.CreateBVConst(32, width - 1);
              ASTNode bottom_lhs = bm.CreateBVConst(32, children[1].GetValueWidth());

              ASTNode top_rhs = bm.CreateBVConst(32, children[1].GetValueWidth()- 1);
              ASTNode bottom_rhs = bm.CreateBVConst(32, 0);

              ASTNode lhs = nf->CreateTerm(BVEXTRACT, children[0].GetValueWidth(), v,top_lhs, bottom_lhs);
              ASTNode rhs = nf->CreateTerm(BVEXTRACT, children[1].GetValueWidth(), v,top_rhs, bottom_rhs);

              replace(children[0],lhs);
              replace(children[1],rhs);
            }
          break;
        case NOT:
          {
            ASTNode v =replaceParentWithFresh(muteParent, variable_array);
            replace(children[0], nf->CreateNode(NOT, v));
          }
          break;

        case BVUMINUS:
        case BVNEG:
          {
            assert(numberOfChildren ==1);
            ASTNode v =replaceParentWithFresh(muteParent, variable_array);
            replace(var, nf->CreateTerm(kind, width,v));
          }
          break;

        case BVSGT:
        case BVSGE:
        case BVGT:
        case BVGE:
          {
            width = var.GetValueWidth();
            if (width ==1)
              continue; // Hard to get right, not used often.

            ASTNode biggestNumber, smallestNumber;

            if (kind == BVSGT || kind == BVSGE)
              {
                // 011111111 (most positive number.)
                CBV max = CONSTANTBV::BitVector_Create(width, false);
                CONSTANTBV::BitVector_Fill(max);
                CONSTANTBV::BitVector_Bit_Off(max, width - 1);
                biggestNumber = bm.CreateBVConst(max, width);

                // 1000000000 (most negative number.)
                max = CONSTANTBV::BitVector_Create(width, true);
                CONSTANTBV::BitVector_Bit_On(max, width - 1);
                smallestNumber = bm.CreateBVConst(max, width);
              }
            else if (kind == BVGT || kind == BVGE)
              {
                biggestNumber = bm.CreateMaxConst(width);
                smallestNumber =  bm.CreateZeroConst(width);
              }
            else
              FatalError("SDFA!@S");


            ASTNode c1,c2;
            if (kind == BVSGT || kind == BVGT)
              {
                c1= biggestNumber;
                c2 = smallestNumber;
              }
            else if (kind == BVSGE || kind == BVGE)
              {
                c1= smallestNumber;
                c2 = biggestNumber;
              }
            else
              FatalError("SDFA!@S");

            if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained())
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode lhs = nf->CreateTerm(ITE, width, v, bm.CreateOneConst(width), bm.CreateZeroConst(width));
                ASTNode rhs = nf->CreateTerm(ITE, width, v, bm.CreateZeroConst(width), bm.CreateOneConst(width));
                replace(children[0], lhs);
                replace(children[1], rhs);
              }
            else if (children[0] == var && children[1].isConstant())
              {
                if (children[1] == c1)
                  continue; // always false. Or always false.

                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs = nf->CreateTerm(ITE, width, v,biggestNumber, smallestNumber);
                replace(var, rhs);
              }
            else if (children[1] == var && children[0].isConstant())
              {
                if (children[0] == c2)
                  continue;  // always false. Or always false.

                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs = nf->CreateTerm(ITE, width, v, smallestNumber, biggestNumber);
                replace(var, rhs);
              }
            else // One side is a variable. The other is anything.
              {
            	 bool varOnLHS = (var == children[0]);

                // All the ASTNode vars need to map to their existing MutableASTNodes. So we collect all the variables
                vector<MutableASTNode*> vars;
                set<MutableASTNode*> visited;
                muteOther->getAllVariablesRecursively(vars, visited);
                visited.clear();

                map<ASTNode, MutableASTNode *> create;
                for (vector<MutableASTNode*>::iterator it = vars.begin(); it != vars.end();it++)
                  create.insert(make_pair((*it)->n, *it));
                vars.clear();

                ASTNode v= bm.CreateFreshVariable(0, 0, "STP_INTERNAL_comparison");

                ASTNode rhs;
                ASTNode n;
                if (varOnLHS)
                  {
                    rhs = nf->CreateTerm(ITE, width, v, biggestNumber, smallestNumber);

                    if (kind == BVSGE || kind == BVGE)
                      n= nf->CreateNode(OR, v, nf->CreateNode(EQ, mutable_children[1]->toASTNode(nf), c1));
                    else
                      n= nf->CreateNode(AND, v, nf->CreateNode(NOT,nf->CreateNode(EQ, mutable_children[1]->toASTNode(nf), c1)));
                  }
                else
                  {
                    rhs = nf->CreateTerm(ITE, width, v, smallestNumber, biggestNumber);

                    if (kind == BVSGE || kind == BVGE)
                      n= nf->CreateNode(OR, v, nf->CreateNode(EQ, mutable_children[0]->toASTNode(nf), c2));
                    else
                      n= nf->CreateNode(AND, v, nf->CreateNode(NOT,nf->CreateNode(EQ, mutable_children[0]->toASTNode(nf), c2)));
                  }
                replace(var, rhs);
                MutableASTNode *newN = MutableASTNode::build(n,create);
                muteParent.replaceWithAnotherNode(newN);
                //assert(muteParent.checkInvariant());
              }
          }
          break;


        case AND:
        case OR:
        case BVOR:
        case BVAND:
          {
            if (allChildrenAreUnconstrained(mutable_children))
              {
                ASTNodeSet already;
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                for (int i =0; i < numberOfChildren;i++)
                  {
                    /* to avoid problems with:
                    734:(AND
                    732:unconstrained_4
                    716:unconstrained_2
                    732:unconstrained_4)
                    */
                    if (already.find(children[i]) == already.end())
                      {
                        replace(children[i], v);
                        already.insert(children[i]);
                      }
                  }
              }
            else
              {
                // Hack. ff.stp has a 325k node conjunction
                // So we check if all the children are unconstrained each time
                // we find a new unconstrained conjunct. This means that if
                // eventually all the nodes become unconstrained we will miss it
                // and not rewrite the AND to a fresh unconstrained variable.

                if (mutable_children.size() > 200)
                  noCheck.insert(muteParent.n);
              }
          }
          break;

        case XOR:
        case BVXOR:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTVec others;
                for (int i = 0; i < numberOfChildren; i++)
                {
                    if (children[i] !=var)
                        others.push_back(mutable_children[i]->toASTNode(nf));
                }
                assert(others.size() +1 == numberOfChildren);
                assert(others.size() >=1);

                if (kind == XOR)
              {
                ASTNode xorNode = nf->CreateNode(XOR, others);
                replace(var, nf->CreateNode(XOR, v, xorNode));
              }
            else
              {
                ASTNode xorNode ;
                if (others.size() > 1 )
                  xorNode = nf->CreateTerm(BVXOR, width, others);
                else
                  xorNode = others[0];

                replace(var, nf->CreateTerm(BVXOR, width, v, xorNode));
              }
              }
           break;

        case ITE:
              {
                if (indexWidth > 0)
                  continue; // don't do arrays.

                if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained() && children[0] != children[1])
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[0], bm.ASTTrue);
                    replace(children[1], v);

                  }
                else if (mutable_children[0]->isUnconstrained() && mutable_children[2]->isUnconstrained() && children[0] != children[2])
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[0], bm.ASTFalse);
                    replace(children[2], v);
                  }
                else if (mutable_children[1]->isUnconstrained() && mutable_children[2]->isUnconstrained())
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[1], v);
                    if (children[1] != children[2])
                      replace(children[2], v);
                  }
              }
              break;
        case BVLEFTSHIFT:
        case BVRIGHTSHIFT:
        case BVSRSHIFT:
             {
                 assert(numberOfChildren == 2);
                 if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained())
                  {
                     assert(children[0] != children[1]);
                     ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                     replace(children[1], bm.CreateZeroConst(width));
                     replace(children[0], v);
                  }
              }
             break;

        case BVMOD:
             {
                 assert(numberOfChildren == 2);
                 if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained() && bm.UserFlags.isSet("unconstrained-bvmod", "0") )
                  {
                     assert (children[0] != children[1]);
                     ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                     replace(children[1], bm.CreateZeroConst(width));
                     replace(children[0], v);
                  }
              }
             break;


        case BVDIV:
             {
                 assert(numberOfChildren == 2);
                 if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained())
                  {
                     assert (children[0] != children[1]);
                     ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                     replace(children[1], bm.CreateOneConst(width));
                     replace(children[0], v);
                  }
              }
             break;
        case BVMULT:
              {
                 assert(numberOfChildren == 2);

                if (mutable_children[1]->isUnconstrained() && mutable_children[0]->isUnconstrained()) // both are unconstrained
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[0], bm.CreateOneConst(width));
                    replace(children[1], v);
                  }

                if (other.isConstant() && simplifier->BVConstIsOdd(other))
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    ASTNode inverse = simplifier->MultiplicativeInverse(other);
                    ASTNode rhs = nf->CreateTerm(BVMULT, width, inverse, v);
                    replace(var, rhs);
                  }

                break;
        case IFF:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs = nf->CreateNode(ITE, v, muteOther->toASTNode(nf), nf->CreateNode(NOT, muteOther->toASTNode(nf)));
                replace(var, rhs);
              }
          break;
        case EQ:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                width = var.GetValueWidth();
                ASTNode rhs = nf->CreateTerm(ITE, width, v, muteOther->toASTNode(nf), nf->CreateTerm(BVPLUS, width, muteOther->toASTNode(nf),
                    bm.CreateOneConst(width)));

                replace(var, rhs);
              }
          break;
        case BVSUB:
          {
            assert(numberOfChildren == 2);

            ASTNode v =replaceParentWithFresh(muteParent, variable_array);

            ASTNode rhs;

            if (children[0] == var)
              rhs= nf->CreateTerm(BVPLUS, width, v, muteOther->toASTNode(nf));
            if (children[1] == var)
              rhs= nf->CreateTerm(BVSUB, width, muteOther->toASTNode(nf), v);

            replace(var, rhs);
          }
          break;

        case BVPLUS:
              {
                ASTVec other;
                for (int i = 0; i < children.size(); i++)
                  if (children[i] != var)
                    other.push_back(mutable_children[i]->toASTNode(nf));

                assert(other.size() == children.size()-1);
                assert(other.size() >=1);

                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs;
                if (other.size() > 1)
                  rhs = nf->CreateTerm(BVSUB, width, v, nf->CreateTerm(BVPLUS, width, other));
                else
                  rhs = nf->CreateTerm(BVSUB, width, v, other[0]);

                replace(var, rhs);
              }
           break;
        case BVEXTRACT:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                const unsigned resultWidth = width;
                const unsigned operandWidth = var.GetValueWidth();
                assert(children[0] == var); // It can't be anywhere else.

                // Create Fresh variables to pad the LHS and RHS.
                const unsigned high = children[1].GetUnsignedConst();
                const unsigned low = children[2].GetUnsignedConst();
                assert(high >=low);

                const int rhsSize = low;
                const int lhsSize = operandWidth - high - 1;

                ASTNode current = v;
                int newWidth = v.GetValueWidth();

                if (lhsSize > 0)
                  {
                    ASTNode lhsFresh = bm.CreateFreshVariable(0, lhsSize, "lhs_padding");
                    current = nf->CreateTerm(BVCONCAT, newWidth + lhsSize, lhsFresh, current);
                    newWidth += lhsSize;
                  }

                if (rhsSize > 0)
                  {
                    ASTNode rhsFresh = bm.CreateFreshVariable(0, rhsSize, "rhs_padding");
                    current = nf->CreateTerm(BVCONCAT, newWidth + rhsSize, current, rhsFresh);
                    newWidth += rhsSize;
                  }

                assert(newWidth == operandWidth);
                replace(var, current);
              }
        break;
        default:
          {
            //cerr << "!!!!" << kind << endl;
          }

            //        cerr << var;
              //      cerr << parent;

              }
          }
      }

    ASTNode result = topMutable->toASTNode(nf);
    topMutable->cleanup();
    //cout << result;
    return result;
  }
// This function adds the clauses to constrain that "a" and "b" equal a fresh
// variable
// (which it returns).
// Because it's used to create array axionms (a=b)-> (c=d), it can be
// used to only add one of the two polarities.
Minisat::Var getEquals(SATSolver& SatSolver, const ASTNode& a, const ASTNode& b,
                       ToSATBase::ASTNodeToSATVar& satVar,
                       Polarity polary = BOTH)
{
  const unsigned width = a.GetValueWidth();
  assert(width == b.GetValueWidth());
  assert(!a.isConstant() || !b.isConstant());

  vector<unsigned> v_a;
  vector<unsigned> v_b;

  getSatVariables(a, v_a, SatSolver, satVar);
  getSatVariables(b, v_b, SatSolver, satVar);

  // The only time v_a or v_b will be empty is if "a" resp. "b" is a constant.

  if (v_a.size() == width && v_b.size() == width)
  {
    SATSolver::vec_literals all;
    const int result = SatSolver.newVar();

    for (unsigned i = 0; i < width; i++)
    {
      SATSolver::vec_literals s;

      if (polary != RIGHT_ONLY)
      {
        int nv0 = SatSolver.newVar();
        s.push(SATSolver::mkLit(v_a[i], true));
        s.push(SATSolver::mkLit(v_b[i], true));
        s.push(SATSolver::mkLit(nv0, false));
        SatSolver.addClause(s);
        s.clear();

        s.push(SATSolver::mkLit(v_a[i], false));
        s.push(SATSolver::mkLit(v_b[i], false));
        s.push(SATSolver::mkLit(nv0, false));
        SatSolver.addClause(s);
        s.clear();

        all.push(SATSolver::mkLit(nv0, true));
      }

      if (polary != LEFT_ONLY)
      {
        s.push(SATSolver::mkLit(v_a[i], true));
        s.push(SATSolver::mkLit(v_b[i], false));
        s.push(SATSolver::mkLit(result, true));
        SatSolver.addClause(s);
        s.clear();

        s.push(SATSolver::mkLit(v_a[i], false));
        s.push(SATSolver::mkLit(v_b[i], true));
        s.push(SATSolver::mkLit(result, true));
        SatSolver.addClause(s);
        s.clear();
      }
    }
    if (all.size() > 0)
    {
      all.push(SATSolver::mkLit(result, false));
      SatSolver.addClause(all);
    }
    return result;
  }
  else if ((v_a.size() == 0) ^ (v_b.size() == 0))
  {
    ASTNode constant = a.isConstant() ? a : b;
    vector<unsigned> vec = v_a.size() == 0 ? v_b : v_a;
    assert(constant.isConstant());
    assert(vec.size() == width);

    SATSolver::vec_literals all;
    const int result = SatSolver.newVar();
    all.push(SATSolver::mkLit(result, false));

    CBV v = constant.GetBVConst();
    for (unsigned i = 0; i < width; i++)
    {
      if (polary != RIGHT_ONLY)
      {
        if (CONSTANTBV::BitVector_bit_test(v, i))
          all.push(SATSolver::mkLit(vec[i], true));
        else
          all.push(SATSolver::mkLit(vec[i], false));
      }

      if (polary != LEFT_ONLY)
      {
        SATSolver::vec_literals p;
        p.push(SATSolver::mkLit(result, true));
        if (CONSTANTBV::BitVector_bit_test(v, i))
          p.push(SATSolver::mkLit(vec[i], false));
        else
          p.push(SATSolver::mkLit(vec[i], true));

        SatSolver.addClause(p);
      }
    }
    if (all.size() > 1)
      SatSolver.addClause(all);
    return result;
  }
  else {
    FatalError("Unexpected, both must be constants..");
    exit(-1);
  }
}
 int numberOfConstants() const
 {
   return ((index0.isConstant() ? 1 : 0) + (index1.isConstant() ? 1 : 0) +
           (index0.isConstant() ? 1 : 0) + (index1.isConstant() ? 1 : 0));
 }
Exemplo n.º 10
0
void Gen68k::codeInstr(InstructionETPB* bInstr){



    registerStack->init();
    switch(bInstr->getNat()){
    case INS_DECLARATION:
        break;
    case INS_UNKNOWN:
        break;
    case INS_AFFECTATION:
        Operande68k* ExprArbrAff;   //=registerStack->front();
        Operande68k* ExprArbrAffected;
        int nG,nD;

        nG=getNbRegArith(bInstr->getAssignmentExprAssigned(),NO_REG);
        nD=getNbRegArith(bInstr->getAssignmentExprTree(),NO_REG);

        if (nD >= nG){
            codeArith(bInstr->getAssignmentExprTree(),NO_REG,&ExprArbrAff);
            registerStack->allocate(ExprArbrAff);
            codeArith(bInstr->getAssignmentExprAssigned(),NO_DADR,&ExprArbrAffected);
            registerStack->freeOperand(ExprArbrAff);
            ilCoder.add(MOVE,ExprArbrAff,ExprArbrAffected,getSize(bInstr->getAssignmentExprAssigned()));
        }
        else{
            codeArith(bInstr->getAssignmentExprAssigned(),NO_DADR,&ExprArbrAffected);
            registerStack->allocate(ExprArbrAffected);
            codeArith(bInstr->getAssignmentExprTree(),NO_REG,&ExprArbrAff);
            registerStack->freeOperand(ExprArbrAffected);
            ilCoder.add(MOVE,ExprArbrAff,ExprArbrAffected,getSize(bInstr->getAssignmentExprAssigned()));
        }
        break;
    case INS_RETURN:
        Operande68k* OpResReturn;
        if (bInstr->getExprReturn()){
            codeArith(bInstr->getExprReturn(),NO_REG,&OpResReturn);
            ilCoder.add(MOVE,OpResReturn,ilCoder.createOp(D0),getSize(bInstr->getExprReturn()));
        }

        if (currentStackVariablesSize)
            ilCoder.add(ADD,ilCoder.createOpVal(currentStackVariablesSize),ilCoder.createOp(SP_REG),SZ_L);
        ilCoder.add(RTS);
        returnInstrAsLastInstr = true;
        break;
    case INS_CALL:
        int somme;
        ASTNode* CallNoeud;

        somme=0;        // la somme des tailles de ce qui est pouss? dans la pile
        size_op68k SizeOfArgument;
        CallNoeud=bInstr->getExprFunctionCall();
        Operande68k* Op2;
        for (int i=CallNoeud->getSuccNmbr()-1;i>=0;i--){
            SizeOfArgument=getSize(*CallNoeud->getSuccPtr(i));
            somme+=(int)SizeOfArgument;
            codeArith(*CallNoeud->getSuccPtr(i),NO_REG,&Op2);
            ilCoder.add(MOVE,Op2,ilCoder.createOp(A7,false,true),SizeOfArgument);
            virtualStack.pushToStack(SizeOfArgument);
        }
        ilCoder.add(BSR,ilCoder.createOpLabel(CallNoeud->getTag()->GetIdentif()),SZ_NA);
        if (somme){
            ilCoder.add(ADD,ilCoder.createOpVal(somme),ilCoder.createOp(SP_REG),SZ_L);
        }
        //virtualStack.display();
        for (int i=CallNoeud->getSuccNmbr()-1;i>=0;i--){
            virtualStack.pop();
            //virtualStack.display();
        }
        break;
    case INS_STRUCT_FOR:
        ASTNode* initExpr;
        ASTNode* finExpr;
        ASTNode* stepExpr;
        ASTNode* varExpr;
        Operande68k* EtiqForDebTest;
        Operande68k* EtiqForFin;

        size_op68k SizeVarIter;
        Operande68k* TexpTO;
        Collection* CorpsFor;

        initExpr = bInstr->getForExprInitTree();
        finExpr = bInstr->getForExprToTree();
        stepExpr = bInstr->getForExprStepTree();
        varExpr = bInstr->getForExprAssigned();
        CorpsFor = bInstr->getForBody();
        SizeVarIter =getSize(varExpr);
        EtiqForDebTest = ilCoder.createOpLabel();
        EtiqForFin = ilCoder.createOpLabel();

        // ---------------------------------------------------
        // Affectation initiale
        // ---------------------------------------------------
        nG=getNbRegArith(varExpr,NO_REG);
        nD=getNbRegArith(initExpr,NO_REG);

        if (nD >= nG){
            codeArith(initExpr,NO_REG,&ExprArbrAff);
            registerStack->allocate(ExprArbrAff);
            codeArith(varExpr,NO_DADR,&ExprArbrAffected);
            registerStack->freeOperand(ExprArbrAff);
            ilCoder.add(MOVE,ExprArbrAff,ExprArbrAffected,SizeVarIter);
        }
        else{
            codeArith(varExpr,NO_DADR,&ExprArbrAffected);
            registerStack->allocate(ExprArbrAffected);
            codeArith(initExpr,NO_REG,&ExprArbrAff);
            registerStack->freeOperand(ExprArbrAffected);
            ilCoder.add(MOVE,ExprArbrAff,ExprArbrAffected,SizeVarIter);
        }

        // ---------------------------------------------------
        // Evaluation de l'expression d'arriv?e
        // ---------------------------------------------------

        // temporaire sur la pile qui va contenir la valeur de l'expression d'arriv?e TO
        TexpTO=registerStack->allocateTemp(SizeVarIter);
        codeArith(finExpr,NO_REG,&ExprArbrAff);
        //registerStack->allocate(ExprArbrAff);
        ilCoder.add(MOVE,ExprArbrAff,TexpTO,SizeVarIter);
        //registerStack->freeOperand(ExprArbrAff);


        // ---------------------------------------------------
        // Test de la condition d'arriv?
        // ---------------------------------------------------
        ilCoder.addLabel(EtiqForDebTest->val.valLabel);

        // cas 1: pas de step
        if (stepExpr == NULL){
            codeArith(varExpr,NO_REG,&ExprArbrAffected);
            ilCoder.add(CMP,TexpTO,ExprArbrAffected,SizeVarIter);
            ilCoder.add(BGT,EtiqForFin,SZ_NA);
            codeInstr(CorpsFor);
            // iterateur = iterateur+1 sous entendu
            codeArith(varExpr,NO_DADR,&ExprArbrAffected);
            ilCoder.add(ADD,ilCoder.createOpVal(1),ExprArbrAffected,SizeVarIter);
            ilCoder.add(BRA,EtiqForDebTest,SZ_NA);
        }
        // cas 2: step constante
        else if (stepExpr->isConstant()){
            int constStepVal;
            constStepVal = atoi(stepExpr->getTag()->GetIdentif());
            codeArith(varExpr,NO_REG,&ExprArbrAffected);
            ilCoder.add(CMP,TexpTO,ExprArbrAffected,SizeVarIter);
            if (constStepVal < 0){
                ilCoder.add(BLT,EtiqForFin,SZ_NA);
            }
            else {
                ilCoder.add(BGT,EtiqForFin,SZ_NA);
            }
            codeInstr(CorpsFor);
            // iterateur = iterateur+cte sous entendu
            codeArith(varExpr,NO_DADR,&ExprArbrAffected);
            ilCoder.add(ADD,ilCoder.createOpVal(constStepVal),ExprArbrAffected,SizeVarIter);
            ilCoder.add(BRA,EtiqForDebTest,SZ_NA);

        }
        // cas 3: step non-constante
        else {
            //Operande68k* EtiqNegStep;
            //Operande68k* EtiqForDebCorps;
            //EtiqForFin = ilCoder.createOpLabel();

        }
        ilCoder.addLabel(EtiqForFin->val.valLabel);
        registerStack->freeTemp(TexpTO,SizeVarIter);   // on libere le temporaire qui contient l'expression de fin
        break;
    case INS_STRUCT_DOLPWH:     // do ... loop while (condition)
        Collection* CorpsDo;
        ASTNode* exprDo;
        Operande68k* EtiqDebut;
        CorpsDo = bInstr->getDoBody();
        exprDo = bInstr->getDoExprCondition();
        EtiqDebut = ilCoder.createOpLabel();
        ilCoder.addLabel(EtiqDebut->val.valLabel);
        codeInstr(CorpsDo);
        codeBool(exprDo,true,true,EtiqDebut,false,false);
        break;
    case INS_STRUCT_DOWH:       // do while (condition) .... loop
        Collection* CorpsWhile;
        ASTNode* exprWhile;
        Operande68k* EtiqWhileDebut;
        Operande68k* EtiqWhileFin;

        CorpsWhile = bInstr->getDoBody();
        exprWhile = bInstr->getDoExprCondition();
        EtiqWhileDebut = ilCoder.createOpLabel();
        EtiqWhileFin = ilCoder.createOpLabel();      // juste avant le test de la condition

        ilCoder.add(BRA,EtiqWhileFin,SZ_NA);        // on va directement voir le test
        ilCoder.addLabel(EtiqWhileDebut->val.valLabel);
        codeInstr(CorpsWhile);
        ilCoder.addLabel(EtiqWhileFin->val.valLabel);
        codeBool(exprWhile,true,true,EtiqWhileDebut,false,false);

        break;
    case INS_IF:
        ASTNode* exprIf;
        exprIf = bInstr->getIfExprTree();
        //printf("codeInstr IF\n");
        //printf("Expression du If:\n");
        //exprIf->display();

        Operande68k* EtiqFinCorpsIF = ilCoder.createOpLabel();
        Operande68k* EtiqFinLocalCorpsElseIf;
        Operande68k* EtiqDebutElse=NULL;    // utilis? s'il y a des elseIf et un else
        Operande68k* EtiqFinBloc;


        Collection* InstrCorpsIf = bInstr->getIfIfBody();
        Collection* InstrCorpsElse = bInstr->getIfElseBody();
        Collection* listExprElseIf = bInstr->getIfExprElseIf();
        Collection* listCorpsElseIf = bInstr->getIfElseIfBody();

        ColIterator iterExprElseIf;
        ColIterator iterCorpsElseIf;

        listExprElseIf->bindIterator(&iterExprElseIf);
        listCorpsElseIf->bindIterator(&iterCorpsElseIf);
        Collection* InstrCorpsElseIf;
        ASTNode* exprElseIf;

        // -------------------------------------------------------
        // Codage de expression de IF
        // -------------------------------------------------------
        codeBool(exprIf,true,false,EtiqFinCorpsIF,false,false); // le dernier false n'a aucun impact normalement

        // -------------------------------------------------------
        // Codage de corps de IF
        // -------------------------------------------------------
        codeInstr(InstrCorpsIf);
        if (!InstrCorpsElse->estVide() || !listExprElseIf->estVide() ){
            EtiqFinBloc = ilCoder.createOpLabel();
            ilCoder.add(BRA,EtiqFinBloc,SZ_NA);     // on ajoute un saut ? tout ? la fin s'il y a un else ou des elseif
        }
        // -------------------------------------------------------
        //      label fin corps If
        // -------------------------------------------------------
        ilCoder.addLabel(EtiqFinCorpsIF->val.valLabel);


        // -------------------------------------------------------
        // Codage des ELSE IF
        // -------------------------------------------------------
        while(iterExprElseIf.elemExists()){
            exprElseIf=(ASTNode*)iterExprElseIf.getNext();
            InstrCorpsElseIf=(Collection*)iterCorpsElseIf.getNext();
            if (iterExprElseIf.elemExists()) {  // le suivant existe
                EtiqFinLocalCorpsElseIf = ilCoder.createOpLabel();   // donc nouvelle etiquette
            } else {        // dernier element
                EtiqDebutElse = ilCoder.createOpLabel();
                EtiqFinLocalCorpsElseIf=EtiqDebutElse;  // on utilise l'etiquette de fin de tout le bloc IF

            }

            // -------------------------------------------------------
            // Codage de expression de ElseIF
            // -------------------------------------------------------
            codeBool(exprElseIf,true,false,EtiqFinLocalCorpsElseIf,false,false);

            // -------------------------------------------------------
            // Codage de corps de ElseIF
            // -------------------------------------------------------
            codeInstr(InstrCorpsElseIf);

            if (!InstrCorpsElse->estVide()){            // il existe un Else, il ne faut pas executer son corps, donc saut ? la fin
                ilCoder.add(BRA,EtiqFinBloc,SZ_NA);
            }
            if (iterExprElseIf.elemExists()) {  // le suivant ElseIf existe, on avait cr?e une nouvelle ?tiquette
                ilCoder.addLabel(EtiqFinLocalCorpsElseIf->val.valLabel);  // label fin corps ElseIf
            }
        }

        // -------------------------------------------------------
        // Codage de corps de ELSE
        // -------------------------------------------------------
        if (EtiqDebutElse) {    // un elseif a cr?e une ?tiquette debut Else
            ilCoder.addLabel(EtiqDebutElse->val.valLabel);    // label fin corps ElseIf
        }
        codeInstr(InstrCorpsElse);

        // -------------------------------------------------------
        //      label fin Global
        // -------------------------------------------------------
        if (!InstrCorpsElse->estVide() || !listExprElseIf->estVide()){
            ilCoder.addLabel(EtiqFinBloc->val.valLabel);  // label fin corps Else
        }


        break;

    }
}
Exemplo n.º 11
0
    Result
    dispatchToTransferFunctions(const Kind k, vector<FixedBits*>& children,
        FixedBits& output, const ASTNode n, MultiplicationStatsMap * msm)
    {
      Result result = NO_CHANGE;

      assert(!n.isConstant());

      Result(*transfer)(vector<FixedBits*>&, FixedBits&);

      switch (k)
        {
          case READ:
          case WRITE:
          // do nothing. Seems difficult to track properly.
          return NO_CHANGE;
          break;

#define MAPTFN(caseV, FN) case caseV: transfer = FN; break;

          // Shifting
          MAPTFN(BVLEFTSHIFT, bvLeftShiftBothWays)
          MAPTFN(BVRIGHTSHIFT, bvRightShiftBothWays)
          MAPTFN(BVSRSHIFT, bvArithmeticRightShiftBothWays)

          // Unsigned Comparison.
          MAPTFN(BVLT,bvLessThanBothWays)
          MAPTFN(BVLE,bvLessThanEqualsBothWays)
          MAPTFN(BVGT, bvGreaterThanBothWays)
          MAPTFN(BVGE, bvGreaterThanEqualsBothWays)

          // Signed Comparison.
          MAPTFN(BVSLT, bvSignedLessThanBothWays)
          MAPTFN(BVSGT,bvSignedGreaterThanBothWays)
          MAPTFN(BVSLE, bvSignedLessThanEqualsBothWays)
          MAPTFN(BVSGE, bvSignedGreaterThanEqualsBothWays)

          // Logic.
          MAPTFN(XOR,bvXorBothWays)
          MAPTFN(BVXOR, bvXorBothWays)
          MAPTFN(OR, bvOrBothWays)
          MAPTFN(BVOR, bvOrBothWays)
          MAPTFN(AND,bvAndBothWays)
          MAPTFN(BVAND,bvAndBothWays)
          MAPTFN(IFF, bvEqualsBothWays)
          MAPTFN(EQ, bvEqualsBothWays)
          MAPTFN(IMPLIES,bvImpliesBothWays)
          MAPTFN(NOT,bvNotBothWays)
          MAPTFN(BVNEG, bvNotBothWays)

          // OTHER
          MAPTFN(BVZX, bvZeroExtendBothWays)
          MAPTFN(BVSX, bvSignExtendBothWays)
          MAPTFN(BVUMINUS,bvUnaryMinusBothWays)
          MAPTFN(BVEXTRACT,bvExtractBothWays)
          MAPTFN(BVPLUS, bvAddBothWays)
          MAPTFN(BVSUB, bvSubtractBothWays)
          MAPTFN(ITE,bvITEBothWays)
          MAPTFN(BVCONCAT, bvConcatBothWays)

#ifdef WITHCBITP
          case BVMULT: // handled specially later.
          case BVDIV:
          case BVMOD:
          case SBVDIV:
          case SBVREM:
          case SBVMOD:
          transfer = NULL;
          break;
#endif
          default:
            {
              notHandled(k);
              return NO_CHANGE;
            }
        }
#undef MAPTFN
      bool mult_like = false;

#ifdef WITHCBITP
      // safe approximation to no overflow multiplication.
      if (k == BVMULT)
        {
          MultiplicationStats ms;
          result = bvMultiplyBothWays(children, output, n.GetSTPMgr(),&ms);
          		if (CONFLICT != result)
          			msm->map[n] = ms;
          mult_like=true;
        }
      else if (k == BVDIV)
        {
          result = bvUnsignedDivisionBothWays(children, output, n.GetSTPMgr());
          mult_like=true;
        }
      else if (k == BVMOD)
        {
          result = bvUnsignedModulusBothWays(children, output, n.GetSTPMgr());
          mult_like=true;
        }
      else if (k == SBVDIV)
        {
          result = bvSignedDivisionBothWays(children, output, n.GetSTPMgr());
          mult_like=true;
        }
      else if (k == SBVREM)
        {
          result = bvSignedRemainderBothWays(children, output, n.GetSTPMgr());
          mult_like=true;
        }
      else if (k == SBVMOD)
        {
          result = bvSignedModulusBothWays(children, output, n.GetSTPMgr());
          mult_like=true;
        }
      else
#endif
      result = transfer(children, output);

      if (mult_like && output_mult_like)
        {
          cerr << output << "=";
          cerr << *children[0] << k;
          cerr << *children[1] << std::endl;
        }

      return result;

    }
Exemplo n.º 12
0
    // NB: This expects that the constructor was called with teh same node. Sorry.
    ASTNode
    ConstantBitPropagation::topLevelBothWays(const ASTNode& top)
    {
      assert(top.GetSTPMgr()->UserFlags.bitConstantProp_flag);
      assert (BOOLEAN_TYPE == top.GetType());

      propagate();
      status = NO_CHANGE;

      //Determine what must always be true.
      ASTNodeMap fromTo = getAllFixed();

      if (debug_cBitProp_messages)
        {
          cerr << "Number removed by bottom UP:" << fromTo.size() << endl;
        }

      setNodeToTrue(top);

      if (debug_cBitProp_messages)
        {
          cerr << "starting propagation" << endl;
          printNodeWithFixings();
          cerr << "Initial Tree:" << endl;
          cerr << top;
        }

      propagate();

      if (debug_cBitProp_messages)
        {
          cerr << "status:" << status <<endl;
          cerr << "ended propagation" << endl;
          printNodeWithFixings();
        }

      // propagate may have stopped with a conflict.
      if (CONFLICT == status)
          return top.GetSTPMgr()->CreateNode(FALSE);

      ASTVec toConjoin;

      // go through the fixedBits. If a node is entirely fixed.
      // "and" it onto the top. Creates redundancy. Check that the
      // node doesn't already depend on "top" directly.

      for (NodeToFixedBitsMap::NodeToFixedBitsMapType::iterator it = fixedMap->map->begin(); it != fixedMap->map->end(); it++) // iterates through all the pairs of node->fixedBits.
        {
          const FixedBits& bits = *it->second;

          if (!bits.isTotallyFixed())
            continue;

          const ASTNode& node = (it->first);

          // Don't constrain nodes we already know all about.
          if (node.isConstant())
            continue;

          // other nodes will contain the same information (the extract doesn't change the fixings).
          if (BVEXTRACT == node.GetKind() || BVCONCAT == node.GetKind())
            continue;

          // toAssign: conjoin it with the top level.
          // toReplace: replace all references to it (except the one conjoined to the top) with this.
          ASTNode propositionToAssert;
          ASTNode constantToReplaceWith;
          // skip the assigning and replacing.
          bool doAssign = true;

            {
              // If it is already contained in the fromTo map, then it's one of the values
              // that have fully been determined (previously). Not conjoined.
              if (fromTo.find(node) != fromTo.end())
                continue;

              ASTNode constNode = bitsToNode(node,bits);

              if (node.GetType() == BOOLEAN_TYPE)
                {
                  if (SYMBOL == node.GetKind())
                    {
                      bool r = simplifier->UpdateSubstitutionMap(node, constNode);
                      assert(r);
                      doAssign = false;
                    }
                  else if (bits.getValue(0))
                    {
                      propositionToAssert = node;
                      constantToReplaceWith = constNode;
                    }
                  else
                    {
                      propositionToAssert = nf->CreateNode(NOT, node);
                      constantToReplaceWith = constNode;
                    }
                }
              else if (node.GetType() == BITVECTOR_TYPE)
                {
                  assert(((unsigned)bits.getWidth()) == node.GetValueWidth());
                  if (SYMBOL == node.GetKind())
                    {
                      bool r = simplifier->UpdateSubstitutionMap(node, constNode);
                      assert(r);
                      doAssign = false;
                    }
                  else
                    {
                      propositionToAssert = nf->CreateNode(EQ, node, constNode);
                      constantToReplaceWith = constNode;
                    }
                }
              else
                FatalError("sadf234s");
            }

          if (doAssign && top != propositionToAssert
              && !dependents->nodeDependsOn(top, propositionToAssert))
            {
              assert(!constantToReplaceWith.IsNull());
              assert(constantToReplaceWith.isConstant());
              assert(propositionToAssert.GetType() == BOOLEAN_TYPE);
              assert(node.GetValueWidth() == constantToReplaceWith.GetValueWidth());

              fromTo.insert(make_pair(node, constantToReplaceWith));
              toConjoin.push_back(propositionToAssert);
            }
        }

     // Write the constants into the main graph.
      ASTNodeMap cache;
      ASTNode result = SubstitutionMap::replace(top, fromTo, cache,nf);

      if (0 != toConjoin.size())
        {
          // It doesn't happen very often. But the "toConjoin" might contain a variable
          // that was added to the substitution map (because the value was determined just now
          // during propagation.
          ASTNode conjunct = (1 == toConjoin.size())? toConjoin[0]: nf->CreateNode(AND,toConjoin);
          conjunct = simplifier->applySubstitutionMap(conjunct);

          result = nf->CreateNode(AND, result, conjunct); // conjoin the new conditions.
        }


  	if (debug_print_graph_after)
		{
			ofstream file;
			file.open("afterCbitp.gdl");
			PrintingHackfixedMap = fixedMap;
			printer::GDL_Print(file,top,&toString);
			file.close();
		}


      assert(BVTypeCheck(result));
      assert(status != CONFLICT); // conflict should have been seen earlier.
      return result;
    }