Пример #1
0
  bool
  SubstitutionMap::UpdateSubstitutionMap(const ASTNode& e0, const ASTNode& e1)
  {
    int i = TermOrder(e0, e1);
    if (0 == i)
      return false;

    assert(e0 != e1);
    assert(e0.GetValueWidth() == e1.GetValueWidth());
    assert(e0.GetIndexWidth() == e1.GetIndexWidth());

    if (e0.GetKind() == SYMBOL)
      {
      if (CheckSubstitutionMap(e0))
        {
        // e0 and e1 might both be variables, e0 is already substituted for,
        // but maybe not e1.
        if (e1.GetKind() == SYMBOL)
          i = -1;
        else
          return false; // already in the map.
        }

      if (loops(e0, e1))
        return false; // loops.
      }

    if (e1.GetKind() == SYMBOL)
      {
      if (CheckSubstitutionMap(e1))
        return false; // already in the map.

      if (loops(e1, e0))
        return false; // loops
      }

    //e0 is of the form READ(Arr,const), and e1 is const, or
    //e0 is of the form var, and e1 is a function.
    if (1 == i && !CheckSubstitutionMap(e0))
      {
      buildDepends(e0, e1);
      (*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))
      {
      buildDepends(e1, e0);
      (*SolverMap)[e1] = e0;
      return true;
      }

    return false;
  }
Пример #2
0
void LetizeNode(const ASTNode& n, ASTNodeSet& PLPrintNodeSet, bool smtlib1)
{
  const Kind kind = n.GetKind();

  if (kind == SYMBOL || kind == BVCONST || kind == FALSE || kind == TRUE)
    return;

  const ASTVec& c = n.GetChildren();
  for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend;
       it++)
  {
    const ASTNode& ccc = *it;

    const Kind k = ccc.GetKind();
    if (k == SYMBOL || k == BVCONST || k == FALSE || k == TRUE)
      continue;

    if (PLPrintNodeSet.find(ccc) == PLPrintNodeSet.end())
    {
      // If branch: if *it is not in NodeSet then,
      //
      // 1. add it to NodeSet
      //
      // 2. Letize its childNodes
      PLPrintNodeSet.insert(ccc);
      LetizeNode(ccc, PLPrintNodeSet, smtlib1);
    }
    else
    {
      // 0. Else branch: Node has been seen before
      //
      // 1. Check if the node has a corresponding letvar in the
      // 1. NodeLetVarMap.
      //
      // 2. if no, then create a new var and add it to the
      // 2. NodeLetVarMap
      if ((!smtlib1 || ccc.GetType() == BITVECTOR_TYPE) &&
          NodeLetVarMap.find(ccc) == NodeLetVarMap.end())
      {
        // Create a new symbol. Get some name. if it conflicts with a
        // declared name, too bad.
        int sz = NodeLetVarMap.size();
        std::ostringstream oss;
        oss << "?let_k_" << sz;

        ASTNode CurrentSymbol = n.GetSTPMgr()->CreateSymbol(
            oss.str().c_str(), n.GetIndexWidth(), n.GetValueWidth());
        /* If for some reason the variable being created here is
         * already declared by the user then the printed output will
         * not be a legal input to the system. too bad. I refuse to
         * check for this.  [Vijay is the author of this comment.]
         */

        NodeLetVarMap[ccc] = CurrentSymbol;
        std::pair<ASTNode, ASTNode> node_letvar_pair(CurrentSymbol, ccc);
        NodeLetVarVec.push_back(node_letvar_pair);
      }
    }
  }
} // end of LetizeNode()
Пример #3
0
// Check that the transformations have occurred.
void ArrayTransformer::assertTransformPostConditions(const ASTNode& term,
                                                     ASTNodeSet& visited)
{

  // I haven't measure whether this is the quickest way to do it?
  std::pair<ASTNodeSet::iterator, bool> p = visited.insert(term);
  if (!p.second)
    return;

  const Kind k = term.GetKind();

  // Check the array reads / writes have been removed
  assert(READ != k);
  assert(WRITE != k);

  // There should be no nodes left of type array.
  assert(0 == term.GetIndexWidth());

  const ASTVec& c = term.GetChildren();
  ASTVec::const_iterator it = c.begin();
  const ASTVec::const_iterator itend = c.end();
  for (; it != itend; it++)
  {
    assertTransformPostConditions(*it, visited);
  }
} 
Пример #4
0
// True if any descendants are arrays.
bool containsArrayOps(const ASTNode& n)
{

  NodeIterator ni(n, n.GetSTPMgr()->ASTUndefined, *n.GetSTPMgr());
  ASTNode current;
  while ((current = ni.next()) != ni.end())
    if (current.GetIndexWidth() > 0)
      return true;

  return false;
}
Пример #5
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;
}
Пример #6
0
void CNFMgr::convertTermForCNF(const ASTNode& varphi, ClauseList* defs)
{
    CNFInfo* x = info[varphi];

    //########################################
    // step 1, done if we've already visited
    //########################################

    if (x->termforcnf != NULL)
    {
        return;
    }

    //########################################
    // step 2, ITE's always get renamed
    //########################################

    if (varphi.isITE())
    {
        x->termforcnf = doRenameITE(varphi, defs);
        reduceMemoryFootprintPos(varphi[0]);
        reduceMemoryFootprintNeg(varphi[0]);

    }
    else if (varphi.isAtom())
    {
        x->termforcnf = ASTNodeToASTNodePtr(varphi);
    }
    else
    {
        ASTVec psis;
        ASTVec::const_iterator it = varphi.GetChildren().begin();
        for (; it != varphi.GetChildren().end(); it++)
        {
            convertTermForCNF(*it, defs);
            psis.push_back(*(info[*it]->termforcnf));
        }

        ASTNode psi = bm->CreateNode(varphi.GetKind(), psis);
        psi.SetValueWidth(varphi.GetValueWidth());
        psi.SetIndexWidth(varphi.GetIndexWidth());
        x->termforcnf = ASTNodeToASTNodePtr(psi);
    }
} //End of convertTermForCNF()
bool containsArrayOps(const ASTNode& n, hash_set<int> & visited)
{
        if (n.GetIndexWidth() > 0)
            return true;

        if (n.Degree() ==0)
            return false;

        if (visited.find(n.GetNodeNum()) != visited.end())
            return false;

        visited.insert(n.GetNodeNum());

	for (int i =0; i < n.Degree();i++)
		if (containsArrayOps(n[i],visited))
			return true;

	return false;
}
Пример #8
0
  ASTNode
  SubstitutionMap::replace(const ASTNode& n, ASTNodeMap& fromTo, ASTNodeMap& cache, NodeFactory * nf, bool stopAtArrays,
      bool preventInfinite)
  {
    const Kind k = n.GetKind();
    if (k == BVCONST || k == TRUE || k == FALSE)
      return n;

    ASTNodeMap::const_iterator it;

    if ((it = cache.find(n)) != cache.end())
      return it->second;

    if ((it = fromTo.find(n)) != fromTo.end())
      {
      const ASTNode& r = it->second;
      assert(r.GetIndexWidth() == n.GetIndexWidth());

      if (preventInfinite)
        cache.insert(make_pair(n, r));

      ASTNode replaced = replace(r, fromTo, cache, nf, stopAtArrays, preventInfinite);
      if (replaced != r)
        {
          fromTo.erase(n);
          fromTo[n] = replaced;
        }

      if (preventInfinite)
        cache.erase(n);

      cache.insert(make_pair(n, replaced));
      return replaced;
      }

    // These can't be created like regular nodes are
    if (k == SYMBOL)
      return n;

    const unsigned int indexWidth = n.GetIndexWidth();
    if (stopAtArrays && indexWidth > 0) // is an array.
      {
      return n;
      }

    const ASTVec& children = n.GetChildren();
    assert(children.size() > 0);
    // Should have no leaves left here.

    ASTVec new_children;
    new_children.reserve(children.size());

    for (ASTVec::const_iterator it = children.begin(); it != children.end(); it++)
      {
      new_children.push_back(replace(*it, fromTo, cache, nf, stopAtArrays, preventInfinite));
      }

    assert(new_children.size() == children.size());

    // This code short-cuts if the children are the same. Nodes with the same children,
    // won't have necessarily given the same node if the simplifyingNodeFactory is enabled
    // now, but wasn't enabled when the node was created. Shortcutting saves lots of time.
    if (new_children == children)
      {
      cache.insert(make_pair(n, n));
      return n;
      }

    ASTNode result;
    const unsigned int valueWidth = n.GetValueWidth();

    if (valueWidth == 0) // n.GetType() == BOOLEAN_TYPE
      {
      result = nf->CreateNode(k, new_children);
      }
    else
      {
      // If the index and value width aren't saved, they are reset sometimes (??)
      result = nf->CreateArrayTerm(k, indexWidth, valueWidth, new_children);
      }

    // We may have created something that should be mapped. For instance,
    // if n is READ(A, x), and the fromTo is: {x==0, READ(A,0) == 1}, then
    // by here the result will be READ(A,0). Which needs to be mapped again..
    // I hope that this makes it idempotent.

    if (fromTo.find(result) != fromTo.end())
      {
      // map n->result, if running replace() on result gives us 'n', it will not infinite loop.
      // This is only currently required for the bitblast equivalence stuff.
      if (preventInfinite)
        cache.insert(make_pair(n, result));

      result = replace(result, fromTo, cache, nf, stopAtArrays, preventInfinite);
      }

    assert(result.GetValueWidth() == valueWidth);
    assert(result.GetIndexWidth() == indexWidth);

    // If there is already an "n" element in the cache, the maps semantics are to ignore the next insertion.
    if (preventInfinite)
      cache.erase(n);

    cache.insert(make_pair(n, result));
    return result;
  }
Пример #9
0
/* This function transforms Array Reads, Read over Writes, Read over
 * ITEs into flattened form.
 *
 * Transform1: Suppose there are two array reads in the input
 * Read(A,i) and Read(A,j) over the same array. Then Read(A,i) is
 * replaced with a symbolic constant, say v1, and Read(A,j) is
 * replaced with the following ITE:
 *
 * ITE(i=j,v1,v2)
 *
 */
ASTNode ArrayTransformer::TransformArrayRead(const ASTNode& term)
{
  assert(TransformMap != NULL);

  const unsigned int width = term.GetValueWidth();

  if (READ != term.GetKind())
    return term;

  ASTNodeMap::const_iterator iter;
  if ((iter = TransformMap->find(term)) != TransformMap->end())
    return iter->second;

  //'term' is of the form READ(arrName, readIndex)
  const ASTNode& arrName = term[0];
  const ASTNode& readIndex = TransformTerm(term[1]);

  ASTNode result;

  switch (arrName.GetKind())
  {
    case SYMBOL:
    {
      /* input is of the form: READ(A, readIndex)
       *
       * output is of the from: A1, if this is the first READ over A
       *
       *                        ITE(previous_readIndex=readIndex,A1,A2)
       *
       *                        .....
       */

      {
        ArrType::const_iterator it;
        if ((it = arrayToIndexToRead.find(arrName)) != arrayToIndexToRead.end())
        {
          std::map<ASTNode, ArrayRead>::const_iterator it2;
          if ((it2 = it->second.find(readIndex)) != it->second.end())
          {
            result = it2->second.ite;
            break;
          }
        }
      }

      // Make up a new abstract variable. Build symbolic name
      // corresponding to array read. The symbolic name has 2
      // components: stringname, and a count

      ASTNode CurrentSymbol =
          bm->CreateFreshVariable(term.GetIndexWidth(), term.GetValueWidth(),
                                  "array_" + std::string(arrName.GetName()));

      result = CurrentSymbol;

      if (!bm->UserFlags.ackermannisation)
      {
        // result is a variable here; it is an ite in the
        // else-branch
      }
      else if (bm->UserFlags.isSet("old_ack", "0"))
      {

        /* oops.
         * This version of ack. doesn't do what I thought it did. The STP 0.1
         * version of Ack. produces simpler
         * expressions. I've put that in the next block. Trevor's thesis
         * measures AckITE using this implementation,
         * rather than the next one like it should have!!!!
         */

        // Full Array transform if we're not doing read refinement.

        // list of array-read indices corresponding to arrName, seen while
        // traversing the AST tree. we need this list to construct the ITEs
        const arrTypeMap& new_read_Indices = arrayToIndexToRead[arrName];

        arrTypeMap::const_iterator it2 = new_read_Indices.begin();
        arrTypeMap::const_iterator it2end = new_read_Indices.end();
        for (; it2 != it2end; it2++)
        {
          ASTNode cond = simp->CreateSimplifiedEQ(readIndex, it2->first);
          if (ASTFalse == cond)
            continue;

          if (ASTTrue == cond)
          {
            result = it2->second.ite;
            break;
          }

          result = simp->CreateSimplifiedTermITE(cond, it2->second.ite, result);
        }
      }
      else
      {
        // Full Array transform if we're not doing read refinement.

        // list of array-read indices corresponding to arrName, seen while
        // traversing the AST tree. we need this list to construct the ITEs
        vector<std::pair<ASTNode, ASTNode>> p = ack_pair[arrName];

        vector<std::pair<ASTNode, ASTNode>>::const_reverse_iterator it2 =
            p.rbegin();
        vector<std::pair<ASTNode, ASTNode>>::const_reverse_iterator it2end =
            p.rend();
        for (; it2 != it2end; it2++)
        {
          ASTNode cond = simp->CreateSimplifiedEQ(readIndex, it2->first);
          if (ASTFalse == cond)
            continue;

          if (ASTTrue == cond)
          {
            result = it2->second;
            break;
          }

          result = simp->CreateSimplifiedTermITE(cond, it2->second, result);
        }

        ack_pair[arrName].push_back(make_pair(readIndex, CurrentSymbol));
      }

      assert(arrName.GetType() == ARRAY_TYPE);
      arrayToIndexToRead[arrName].insert(
          make_pair(readIndex, ArrayRead(result, CurrentSymbol)));
      break;
    }
    case WRITE:
    {
      /* The input to this case is: READ((WRITE A i val) j)
       *
       * The output of this case is: ITE( (= i j) val (READ A j))
       */

      /* 1. arrName or term[0] is infact a WRITE(A,i,val) expression
       *
       * 2. term[1] is the read-index j
       *
       * 3. arrName[0] is the new arrName i.e. A. A can be either a
       SYMBOL or a nested WRITE. no other possibility
       *
       * 4. arrName[1] is the WRITE index i.e. i
       *
       * 5. arrName[2] is the WRITE value i.e. val (val can inturn
       *    be an array read)
       */

      ASTNode writeIndex = TransformTerm(arrName[1]);
      ASTNode writeVal = TransformTerm(arrName[2]);

      if (ARRAY_TYPE != arrName[0].GetType())
        FatalError("TransformArray: "
                   "An array write is being attempted on a non-array:",
                   term);

      // if ((SYMBOL == arrName[0].GetKind()
      //|| WRITE == arrName[0].GetKind()))
      {
        ASTNode cond = simp->CreateSimplifiedEQ(writeIndex, readIndex);
        assert(BVTypeCheck(cond));

        // If the condition is true, it saves iteratively transforming through
        // all the (possibly nested) arrays.
        if (ASTTrue == cond)
        {
          result = writeVal;
        }
        else
        {
          ASTNode readTerm = nf->CreateTerm(READ, width, arrName[0], readIndex);
          assert(BVTypeCheck(readTerm));

          // The simplifying node factory may have produced
          // something that's not a READ.
          ASTNode readPushedIn = TransformTerm(readTerm);
          assert(BVTypeCheck(readPushedIn));

          result = simp->CreateSimplifiedTermITE(cond, writeVal, readPushedIn);
        }
      }

// Trevor: I've removed this code because I don't see the advantage in working
// inside out. i.e. transforming read(write(ite(p,A,B),i,j),k), into
// read(ite(p,write(A,i,j),write(B,i,j),k). That is bringing up the ite.
// Without this code it will become: ite(i=k, j, read(ite(p,A,B),k))

#if 0
          else if (ITE == arrName[0].GetKind())
            {
              // pull out the ite from the write // pushes the write
              // through.
              ASTNode writeTrue =
                nf->CreateNode(WRITE, (arrName[0][1]), writeIndex, writeVal);
              writeTrue.SetIndexWidth(writeIndex.GetValueWidth());
              writeTrue.SetValueWidth(writeVal.GetValueWidth());
              assert(ARRAY_TYPE == writeTrue.GetType());

              ASTNode writeFalse = 
                nf->CreateNode(WRITE, (arrName[0][2]), writeIndex, writeVal);
              writeFalse.SetIndexWidth(writeIndex.GetValueWidth());
              writeFalse.SetValueWidth(writeVal.GetValueWidth());
              assert(ARRAY_TYPE == writeFalse.GetType());

              result =  (writeTrue == writeFalse) ?
                writeTrue : simp->CreateSimplifiedTermITE(TransformFormula(arrName[0][0]),
                                              writeTrue, writeFalse);
              result.SetIndexWidth(writeIndex.GetValueWidth());
              result.SetValueWidth(writeVal.GetValueWidth());
              assert(ARRAY_TYPE == result.GetType());

              result = 
                nf->CreateTerm(READ, writeVal.GetValueWidth(),
                               result, readIndex);
              BVTypeCheck(result);
              result = TransformArrayRead(result);
            }
          else
            FatalError("TransformArray: Write over bad type.");
#endif
      break;
    }
    case ITE:
    {
      /* READ((ITE cond thn els) j)
       *
       * is transformed into
       *
       * (ITE cond (READ thn j) (READ els j))
       */

      // pull out the ite from the read // pushes the read through.

      //(ITE cond thn els)

      ASTNode cond = arrName[0];
      cond = TransformFormula(cond);

      const ASTNode& thn = arrName[1];
      const ASTNode& els = arrName[2];

      //(READ thn j)
      ASTNode thnRead = nf->CreateTerm(READ, width, thn, readIndex);
      assert(BVTypeCheck(thnRead));

      //(READ els j)
      ASTNode elsRead = nf->CreateTerm(READ, width, els, readIndex);
      assert(BVTypeCheck(elsRead));

      /* We try to call TransformTerm only if necessary, because it
       * introduces a new symbol for each read. The amount of work we
       * need to do later is based on the square of the number of symbols.
       */
      if (ASTTrue == cond)
      {
        result = TransformTerm(thnRead);
      }
      else if (ASTFalse == cond)
      {
        result = TransformTerm(elsRead);
      }
      else
      {
        thnRead = TransformTerm(thnRead);
        elsRead = TransformTerm(elsRead);

        //(ITE cond (READ thn j) (READ els j))
        result = simp->CreateSimplifiedTermITE(cond, thnRead, elsRead);
      }
      break;
    }
    default:
      FatalError("TransformArray: "
                 "The READ is NOT over SYMBOL/WRITE/ITE",
                 term);
      break;
  }
Пример #10
0
ASTNode ArrayTransformer::TransformTerm(const ASTNode& term)
{
  assert(TransformMap != NULL);

  const Kind k = term.GetKind();
  if (!is_Term_kind(k))
    FatalError("TransformTerm: Illegal kind: You have input a nonterm:", term,
               k);
  ASTNodeMap::const_iterator iter;
  if ((iter = TransformMap->find(term)) != TransformMap->end())
    return iter->second;

  ASTNode result;
  switch (k)
  {
    case SYMBOL:
    case BVCONST:
    {
      result = term;
      break;
    }
    case WRITE:
      FatalError("TransformTerm: this kind is not supported", term);
      break;
    case READ:
      result = TransformArrayRead(term);
      break;
    case ITE:
    {
      ASTNode cond = term[0];
      ASTNode thn = term[1];
      ASTNode els = term[2];
      cond = TransformFormula(cond);
      if (ASTTrue == cond)
        result = TransformTerm(thn);
      else if (ASTFalse == cond)
        result = TransformTerm(els);
      else
      {
        thn = TransformTerm(thn);
        els = TransformTerm(els);
        if (bm->UserFlags.optimize_flag)
          result = simp->CreateSimplifiedTermITE(cond, thn, els);
        else
          result = nf->CreateTerm(ITE, thn.GetValueWidth(), cond, thn, els);
      }
      assert(result.GetIndexWidth() == term.GetIndexWidth());
      break;
    }
    default:
    {
      const ASTVec& c = term.GetChildren();
      ASTVec::const_iterator it = c.begin();
      ASTVec::const_iterator itend = c.end();
      const unsigned width = term.GetValueWidth();
      const unsigned indexwidth = term.GetIndexWidth();
      ASTVec o;
      o.reserve(c.size());
      for (; it != itend; it++)
      {
        o.push_back(TransformTerm(*it));
      }

      if (c != o)
      {
        result = nf->CreateArrayTerm(k, indexwidth, width, o);
      }
      else
        result = term;
    }
    break;
  }

  if (term.Degree() > 0)
    (*TransformMap)[term] = result;
  if (term.GetValueWidth() != result.GetValueWidth())
    FatalError("TransformTerm: "
               "result and input terms are of different length",
               result);
  if (term.GetIndexWidth() != result.GetIndexWidth())
  {
    std::cerr << "TransformTerm: input term is : " << term << std::endl;
    FatalError("TransformTerm: "
               "result & input terms have different index length",
               result);
  }
  return result;
} 
Пример #11
0
  ASTNode ArrayTransformer::TransformTerm(const ASTNode& term)
  {
    assert(TransformMap != NULL);

    const Kind k = term.GetKind();
    if (!is_Term_kind(k))
      FatalError("TransformTerm: Illegal kind: You have input a nonterm:", 
                 term, k);
    ASTNodeMap::const_iterator iter;
    if ((iter = TransformMap->find(term)) != TransformMap->end())
      return iter->second;

    ASTNode result;
    switch (k)
      {
      case SYMBOL:
      case BVCONST:
      {
          result = term;
          break;
        }
      case WRITE:
        FatalError("TransformTerm: this kind is not supported", term);
        break;
      case READ:
        result = TransformArrayRead(term);
        break;
      case ITE:
        {
          ASTNode cond = term[0];
          ASTNode thn = term[1];
          ASTNode els = term[2];
          cond = TransformFormula(cond);
          if (ASTTrue == cond)
        	  result = TransformTerm(thn);
          else if (ASTFalse == cond)
        	  result = TransformTerm(els);
          else
          {
        	  thn = TransformTerm(thn);
        	  els = TransformTerm(els);
        	  result = simp->CreateSimplifiedTermITE(cond, thn, els);
          }
          assert(result.GetIndexWidth() ==term.GetIndexWidth());
          break;
        }
      default:
        {
          const ASTVec& c = term.GetChildren();
          ASTVec::const_iterator it = c.begin();
          ASTVec::const_iterator itend = c.end();
          const unsigned width = term.GetValueWidth();
          const unsigned indexwidth = term.GetIndexWidth();
          ASTVec o;
          o.reserve(c.size());
          for (; it != itend; it++)
            {
              o.push_back(TransformTerm(*it));
            }

          if (c!=o)
          {
        	  result = nf->CreateArrayTerm(k,indexwidth, width, o);
          }
          else
        	  result = term;

          const Kind k = result.GetKind();

          if (BVDIV == k 
              || BVMOD == k 
              || SBVDIV == k 
              || SBVREM == k 
              || SBVMOD == k)
            {

              // I had this as a reference, but that was wrong. Because
              // "result" gets over-written in the next block, result[1], may
              // get a reference count of zero, so be garbage collected.
              const ASTNode bottom = result[1];

              if (SBVDIV == result.GetKind() 
                  || SBVREM == result.GetKind() 
                  || SBVMOD == result.GetKind())
                {
                  result = TranslateSignedDivModRem(result);
                }

              if (bm->UserFlags.division_by_zero_returns_one_flag)
                {
                  // This is a difficult rule to introduce in other
                  // places because it's recursive. i.e.  result is
                  // embedded unchanged inside the result.

                  unsigned inputValueWidth = result.GetValueWidth();
                  ASTNode zero = bm->CreateZeroConst(inputValueWidth);
                  ASTNode one = bm->CreateOneConst(inputValueWidth);
                  result = 
                    nf->CreateTerm(ITE, inputValueWidth,
                                   nf->CreateNode(EQ, zero, bottom),
                                   one, result);

                  //return result;
                  if (bm->UserFlags.optimize_flag)
                      return simp->SimplifyTerm_TopLevel(result);
                  else
                  	return result;

                }
            }
        }
        break;
      }

    if (term.Degree() > 0)
      (*TransformMap)[term] = result;
    if (term.GetValueWidth() != result.GetValueWidth())
      FatalError("TransformTerm: "\
                 "result and input terms are of different length", result);
    if (term.GetIndexWidth() != result.GetIndexWidth())
      {
        cerr << "TransformTerm: input term is : " << term << endl;
        FatalError("TransformTerm: "\
                   "result & input terms have different index length", result);
      }
    return result;
  } //End of TransformTerm