Example #1
0
void TheoryQuantifiers::assertExistential( Node n ){
  Assert( n.getKind()== NOT && n[0].getKind()==FORALL );
  if( !options::cbqi() || options::recurseCbqi() || !TermUtil::hasInstConstAttr(n[0]) ){
    getQuantifiersEngine()->assertQuantifier( n[0], false );
  }
}
Example #2
0
void InstGenProcess::calculateMatches( QuantifiersEngine* qe, Node f, std::vector< Node >& considerVal, bool useConsider ){
  Trace("inst-gen-cm") << "* Calculate matches " << d_node << std::endl;
  //whether we are doing a product or sum or matches
  bool doProduct = true;
  //get the model
  FirstOrderModel* fm = qe->getModel();

  //calculate terms we will consider
  std::vector< Node > considerTerms;
  std::vector< std::vector< Node > > newConsiderVal;
  std::vector< bool > newUseConsider;
  std::map< Node, InstMatch > considerTermsMatch[2];
  std::map< Node, bool > considerTermsSuccess[2];
  newConsiderVal.resize( d_children.size() );
  newUseConsider.resize( d_children.size(), useConsider );
  if( d_node.getKind()==APPLY_UF ){
    Node op = d_node.getOperator();
    if( useConsider ){
#ifndef CHILD_USE_CONSIDER
      for( size_t i=0; i<newUseConsider.size(); i++ ){
        newUseConsider[i] = false;
      }
#endif
      for( size_t i=0; i<considerVal.size(); i++ ){
        eq::EqClassIterator eqc( qe->getEqualityQuery()->getEngine()->getRepresentative( considerVal[i] ),
                                 qe->getEqualityQuery()->getEngine() );
        while( !eqc.isFinished() ){
          Node en = (*eqc);
          if( en.getKind()==APPLY_UF && en.getOperator()==op ){
              considerTerms.push_back( en );
          }
          ++eqc;
        }
      }
    }else{
      considerTerms.insert( considerTerms.begin(), fm->d_uf_terms[op].begin(), fm->d_uf_terms[op].end() );
    }
    //for each term we consider, calculate a current match
    for( size_t i=0; i<considerTerms.size(); i++ ){
      Node n = considerTerms[i];
      bool isSelected = qe->getModelEngine()->getModelBuilder()->isTermSelected( n );
      bool hadSuccess CVC4_UNUSED = false;
      for( int t=(isSelected ? 0 : 1); t<2; t++ ){
        if( t==0 || !n.getAttribute(NoMatchAttribute()) ){
          considerTermsMatch[t][n] = InstMatch();
          considerTermsSuccess[t][n] = true;
          for( size_t j=0; j<d_node.getNumChildren(); j++ ){
            if( d_children_map.find( j )==d_children_map.end() ){
              if( t!=0 || !n[j].getAttribute(ModelBasisAttribute()) ){
                if( d_node[j].getKind()==INST_CONSTANT ){
                  if( !considerTermsMatch[t][n].setMatch( qe->getEqualityQuery(), d_node[j], n[j] ) ){
                    Trace("inst-gen-cm") << "fail match: " << n[j] << " is not equal to ";
                    Trace("inst-gen-cm") << considerTermsMatch[t][n].getValue( d_node[j] ) << std::endl;
                    considerTermsSuccess[t][n] = false;
                    break;
                  }
                }else if( !qe->getEqualityQuery()->areEqual( d_node[j], n[j] ) ){
                  Trace("inst-gen-cm") << "fail arg: " << n[j] << " is not equal to " << d_node[j] << std::endl;
                  considerTermsSuccess[t][n] = false;
                  break;
                }
              }
            }
          }
          //if successful, store it
          if( considerTermsSuccess[t][n] ){
#ifdef CHILD_USE_CONSIDER
            if( !hadSuccess ){
              hadSuccess = true;
              for( size_t k=0; k<d_children.size(); k++ ){
                if( newUseConsider[k] ){
                  int childIndex = d_children_index[k];
                  //determine if we are restricted or not
                  if( t!=0 || !n[childIndex].getAttribute(ModelBasisAttribute()) ){
                    Node r = qe->getModel()->getRepresentative( n[childIndex] );
                    if( std::find( newConsiderVal[k].begin(), newConsiderVal[k].end(), r )==newConsiderVal[k].end() ){
                      newConsiderVal[k].push_back( r );
                      //check if we now need to consider the entire domain
                      TypeNode tn = r.getType();
                      if( qe->getModel()->d_rep_set.hasType( tn ) ){
                        if( (int)newConsiderVal[k].size()>=qe->getModel()->d_rep_set.getNumRepresentatives( tn ) ){
                          newConsiderVal[k].clear();
                          newUseConsider[k] = false;
                        }
                      }
                    }
                  }else{
                    //matching against selected term, will need to consider all values
                    newConsiderVal[k].clear();
                    newUseConsider[k] = false;
                  }
                }
              }
            }
#endif
          }
        }
      }
    }
  }else{
    //the interpretted case
    if( d_node.getType().isBoolean() ){
      if( useConsider ){
        //if( considerVal.size()!=1 ) { std::cout << "consider val = " << considerVal.size() << std::endl; }
        Assert( considerVal.size()==1 );
        bool reqPol = considerVal[0]==fm->d_true;
        Node ncv = considerVal[0];
        if( d_node.getKind()==NOT ){
          ncv = reqPol ? fm->d_false : fm->d_true;
        }
        if( d_node.getKind()==NOT || d_node.getKind()==AND || d_node.getKind()==OR ){
          for( size_t i=0; i<newConsiderVal.size(); i++ ){
            newConsiderVal[i].push_back( ncv );
          }
          //instead we will do a sum
          if( ( d_node.getKind()==AND && !reqPol ) || ( d_node.getKind()==OR && reqPol )  ){
            doProduct = false;
          }
        }else{
          //do not use consider
          for( size_t i=0; i<newUseConsider.size(); i++ ){
            newUseConsider[i] = false;
          }
        }
      }
    }
  }

  //calculate all matches for children
  for( int i=0; i<(int)d_children.size(); i++ ){
    d_children[i].calculateMatches( qe, f, newConsiderVal[i], newUseConsider[i] );
    if( doProduct && d_children[i].getNumMatches()==0 ){
      return;
    }
  }
  if( d_node.getKind()==APPLY_UF ){
    //if this is an uninterpreted function
    Node op = d_node.getOperator();
    //process all values
    for( size_t i=0; i<considerTerms.size(); i++ ){
      Node n = considerTerms[i];
      bool isSelected = qe->getModelEngine()->getModelBuilder()->isTermSelected( n );
      for( int t=(isSelected ? 0 : 1); t<2; t++ ){
        //do not consider ground case if it is already congruent to another ground term
        if( t==0 || !n.getAttribute(NoMatchAttribute()) ){
          Trace("inst-gen-cm") << "calculate for " << n << ", selected = " << (t==0) << std::endl;
          if( considerTermsSuccess[t][n] ){
            //try to find unifier for d_node = n
            calculateMatchesUninterpreted( qe, f, considerTermsMatch[t][n], n, 0, t==0 );
          }
        }
      }
    }
  }else{
    //if this is an interpreted function
    if( doProduct ){
      //combining children matches
      InstMatch curr;
      std::vector< Node > terms;
      calculateMatchesInterpreted( qe, f, curr, terms, 0 );
    }else{
      //summing children matches
      Assert( considerVal.size()==1 );
      for( int i=0; i<(int)d_children.size(); i++ ){
        for( int j=0; j<(int)d_children[ i ].getNumMatches(); j++ ){
          InstMatch m;
          if( d_children[ i ].getMatch( qe->getEqualityQuery(), j, m ) ){
            addMatchValue( qe, f, considerVal[0], m );
          }
        }
      }
    }
  }
  Trace("inst-gen-cm") << "done calculate matches" << std::endl;
  //can clear information used for finding duplicates
  d_inst_trie.clear();
}
Example #3
0
void BoundedIntegers::registerQuantifier( Node f ) {
  Trace("bound-int") << "Register quantifier " << f << std::endl;
  bool hasIntType = false;
  int finiteTypes = 0;
  std::map< Node, int > numMap;
  for( unsigned i=0; i<f[0].getNumChildren(); i++) {
    numMap[f[0][i]] = i;
    if( f[0][i].getType().isInteger() ){
      hasIntType = true;
    }
    else if( f[0][i].getType().isSort() || f[0][i].getType().getCardinality().isFinite() ){
      finiteTypes++;
    }
  }
  if( hasIntType ){
    bool success;
    do{
      std::map< int, std::map< Node, Node > > bound_lit_map;
      std::map< int, std::map< Node, bool > > bound_lit_pol_map;
      success = false;
      process( f, f[1], true, bound_lit_map, bound_lit_pol_map );
      for( std::map< Node, Node >::iterator it = d_bounds[0][f].begin(); it != d_bounds[0][f].end(); ++it ){
        Node v = it->first;
        if( !isBound(f,v) ){
          if( d_bounds[1][f].find(v)!=d_bounds[1][f].end() ){
            d_set[f].push_back(v);
            d_set_nums[f].push_back(numMap[v]);
            success = true;
            //set Attributes on literals
            for( unsigned b=0; b<2; b++ ){
              Assert( bound_lit_map[b].find( v )!=bound_lit_map[b].end() );
              Assert( bound_lit_pol_map[b].find( v )!=bound_lit_pol_map[b].end() );
              BoundIntLitAttribute bila;
              bound_lit_map[b][v].setAttribute( bila, bound_lit_pol_map[b][v] ? 1 : 0 );
            }
            Trace("bound-int") << "Variable " << v << " is bound because of literals " << bound_lit_map[0][v] << " and " << bound_lit_map[1][v] << std::endl;
          }
        }
      }
    }while( success );
    Trace("bound-int") << "Bounds are : " << std::endl;
    for( unsigned i=0; i<d_set[f].size(); i++) {
      Node v = d_set[f][i];
      Node r = NodeManager::currentNM()->mkNode( MINUS, d_bounds[1][f][v], d_bounds[0][f][v] );
      d_range[f][v] = Rewriter::rewrite( r );
      Trace("bound-int") << "  " << d_bounds[0][f][v] << " <= " << v << " <= " << d_bounds[1][f][v] << " (range is " << d_range[f][v] << ")" << std::endl;
    }
    if( d_set[f].size()==(f[0].getNumChildren()-finiteTypes) ){
      d_bound_quants.push_back( f );
      for( unsigned i=0; i<d_set[f].size(); i++) {
        Node v = d_set[f][i];
        Node r = d_range[f][v];
        if( r.hasBoundVar() ){
          //introduce a new bound
          Node new_range = NodeManager::currentNM()->mkSkolem( "bir_$$", r.getType(), "bound for term" );
          d_nground_range[f][v] = d_range[f][v];
          d_range[f][v] = new_range;
          r = new_range;
        }
        if( r.getKind()!=CONST_RATIONAL ){
          if( std::find(d_ranges.begin(), d_ranges.end(), r)==d_ranges.end() ){
            Trace("bound-int") << "For " << v << ", bounded Integer Module will try to minimize : " << r << " " << r.getKind() << std::endl;
            d_ranges.push_back( r );
            d_rms[r] = new RangeModel(this, r, d_quantEngine->getSatContext() );
            d_rms[r]->initialize();
          }
        }
      }
    }else{
      Trace("bound-int-warn") << "Warning : Bounded Integers : Could not find bounds for " << f << std::endl;
      //Message() << "Bound integers : Cannot infer bounds of " << f << std::endl;
    }
  }
}
PeepHoleOpt::Changed PeepHoleOpt::handleInst_MOV(Inst* inst)
{
    Node* node = inst->getNode();
    if (((BasicBlock*)node)->getLayoutSucc() == NULL)
    {
        Inst *next = inst->getNextInst();

        Node *currNode = node;
        bool methodMarkerOccur = false;
        MethodMarkerPseudoInst* methodMarker = NULL;
        // ignoring instructions that have no effect and saving method markers to correct them during optimizations
        while (next == NULL || next->getKind() == Inst::Kind_MethodEndPseudoInst || next->getMnemonic() == Mnemonic_JMP)
        {
            if (next == NULL)
            {
                currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode();
                if (currNode->getKind() == Node::Kind_Exit)
                    return Changed_Nothing;
                next = (Inst*) currNode->getFirstInst();
            }
            else
            {
                if (next->getKind() == Inst::Kind_MethodEndPseudoInst)
                {
                    //max 1 saved method marker
                    if (methodMarkerOccur)
                    {
                        return Changed_Nothing;
                    }
                    methodMarker = (MethodMarkerPseudoInst*)next;
                    methodMarkerOccur = true;
                }
                next = next->getNextInst();
            }
        }

        Inst *jump = next->getNextInst();


        bool step1 = true;
        currNode = node;
        while (currNode != next->getNode())
        {
            currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode();
            if (currNode->getInDegree()!=1)
            {
                step1 = false;
                break;
            }
        }

        // step1:
        // ---------------------------------------------
        // MOV opnd, opnd2             MOV opnd3, opnd2
        // MOV opnd3, opnd      ->
        // ---------------------------------------------
        // nb: applicable if opnd will not be used further
        if (step1 && next->getMnemonic() == Mnemonic_MOV)
        {
            Opnd *movopnd1, *movopnd2, *nextmovopnd1, *nextmovopnd2;
            bool isInstCopyPseudo = (inst->getKind() == Inst::Kind_CopyPseudoInst);
            if (isInstCopyPseudo)
            {
                movopnd1 = inst->getOpnd(0);
                movopnd2 = inst->getOpnd(1);
            }
            else
            {
                Inst::Opnds movuses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds movdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                movopnd1 = inst->getOpnd(movdefs.begin());
                movopnd2 = inst->getOpnd(movuses.begin());
            }
            bool isNextCopyPseudo = (next->getKind() == Inst::Kind_CopyPseudoInst);
            if (isNextCopyPseudo)
            {
                nextmovopnd1 = next->getOpnd(0);
                nextmovopnd2 = next->getOpnd(1);
            }
            else
            {
                Inst::Opnds nextmovuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds nextmovdefs(next, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                nextmovopnd1 = next->getOpnd(nextmovdefs.begin());
                nextmovopnd2 = next->getOpnd(nextmovuses.begin());
            }
            if (movopnd1->getId() == nextmovopnd2->getId() && 
                !isMem(movopnd2) && !isMem(nextmovopnd1) &&
                !isMem(movopnd1)
                )
            {
                BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
                irManager->updateLivenessInfo();
                irManager->getLiveAtExit(next->getNode(), ls);
                for (Inst* i = (Inst*)next->getNode()->getLastInst(); i!=next; i = i->getPrevInst()) {
                    irManager->updateLiveness(i, ls);
                }
                bool dstNotUsed = !ls.getBit(movopnd1->getId());
                if (dstNotUsed)
                {
                    if (isInstCopyPseudo && isNextCopyPseudo)
                        irManager->newCopyPseudoInst(Mnemonic_MOV, nextmovopnd1, movopnd2)->insertAfter(inst);
                    else
                        irManager->newInst(Mnemonic_MOV, nextmovopnd1, movopnd2)->insertAfter(inst);
                    inst->unlink();
                    next->unlink();
                    return Changed_Node;
                }
            }
        }

        // step2:
        // --------------------------------------------------------------
        // MOV opnd, 0/1                Jmp smwh/BB1            Jmp smwh/BB1
        // CMP opnd, 0           ->     CMP opnd, 0     v
        // Jcc smwh                     Jcc smwh
        // BB1:                         BB1:
        // --------------------------------------------------------------
        // nb: applicable if opnd will not be used further
        if (next->getMnemonic() == Mnemonic_CMP && jump!= NULL && (jump->getMnemonic() == Mnemonic_JE ||
            jump->getMnemonic() == Mnemonic_JNE))
        {
            Opnd *movopnd1, *movopnd2;
            if (inst->getKind() == Inst::Kind_CopyPseudoInst)
            {
                movopnd1 = inst->getOpnd(0);
                movopnd2 = inst->getOpnd(1);
            }
            else
            {
                Inst::Opnds movuses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds movdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                movopnd1 = inst->getOpnd(movdefs.begin());
                movopnd2 = inst->getOpnd(movuses.begin());
            }
            Inst::Opnds cmpuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
            Opnd* cmpopnd1 = next->getOpnd(cmpuses.begin());
            Opnd* cmpopnd2 = next->getOpnd(cmpuses.next(cmpuses.begin()));
            
            if (isImm(movopnd2) && (movopnd2->getImmValue() == 0 || movopnd2->getImmValue() == 1) &&
                movopnd1->getId() == cmpopnd1->getId() &&
                isImm(cmpopnd2) && cmpopnd2->getImmValue() == 0)
            {
                BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
                irManager->updateLivenessInfo();
                irManager->getLiveAtExit(jump->getNode(), ls);
                bool opndNotUsed = !ls.getBit(movopnd1->getId());
                if (opndNotUsed)
                {
                    ControlFlowGraph* cfg = irManager->getFlowGraph();
                    Node* destination = ((BranchInst*)jump)->getTrueTarget();
                    if ((jump->getMnemonic() == Mnemonic_JNE || movopnd2->getImmValue() == 1) && !(jump->getMnemonic() == Mnemonic_JNE && movopnd2->getImmValue() == 1))
                    {
                        destination = ((BranchInst*)jump)->getFalseTarget();
                    }
                    if (node->getId() != next->getNode()->getId())
                    {
                        if (methodMarkerOccur)
                        {
                            inst->getNode()->appendInst(irManager->newMethodEndPseudoInst(methodMarker->getMethodDesc()));
                        }
                        inst->unlink();
                        Edge *outEdge = node->getOutEdge(Edge::Kind_Unconditional);
                        cfg->replaceEdgeTarget(outEdge, destination, true);
                        cfg->purgeUnreachableNodes(); // previous successor may become unreachable
                    }
                    else
                    {
                        cfg->removeEdge(node->getOutEdge(Edge::Kind_True));
                        cfg->removeEdge(node->getOutEdge(Edge::Kind_False));
                        cfg->addEdge(node, destination);
                        inst->unlink();
                        next->unlink();
                        jump->unlink();
                    }

                    return Changed_Node;
                }
            }
        }
    }
    return Changed_Nothing;
}
Example #5
0
bool EqualityQueryInstProp::isLiteral( Node n ) {
  Kind ak = n.getKind()==NOT ? n[0].getKind() : n.getKind();
  Assert( ak!=NOT );
  return ak!=AND && ak!=OR && ak!=IFF && ak!=ITE;
}
Example #6
0
bool InstPropagator::update( unsigned id, InstInfo& ii, bool firstTime ) {
  Assert( !d_conflict );
  Assert( ii.d_active );
  Trace("qip-prop-debug") << "Update info [" << id << "]..." << std::endl;
  //update the evaluation of the current lemma
  std::map< Node, Node > visited;
  std::map< Node, bool > watch_list;
  std::vector< Node > props;
  Node eval = d_qy.evaluateTermExp( ii.d_curr, ii.d_curr_exp, visited, true, true, watch_list, props );
  if( eval.isNull() ){
    ii.d_active = false;
  }else if( firstTime || eval!=ii.d_curr ){
    if( EqualityQueryInstProp::isLiteral( eval ) ){
      props.push_back( eval );
      eval = d_qy.d_true;
      watch_list.clear();
    }
    if( Trace.isOn("qip-prop") ){
      Trace("qip-prop") << "Update info [" << id << "]..." << std::endl;
      Trace("qip-prop") << "...updated lemma " << ii.d_curr << " -> " << eval << ", exp = ";
      debugPrintExplanation( ii.d_curr_exp, "qip-prop" );
      Trace("qip-prop") << std::endl;
      Trace("qip-prop") << "...watch list: " << std::endl;
      for( std::map< Node, bool >::iterator itw = watch_list.begin(); itw!=watch_list.end(); ++itw ){
        Trace("qip-prop") << "  " << itw->first << std::endl;
      }
      Trace("qip-prop") << "...new propagations: " << std::endl;
      for( unsigned i=0; i<props.size(); i++ ){
        Trace("qip-prop") << "  " << props[i] << std::endl;
      }
      Trace("qip-prop") << std::endl;
    }
    //determine the status of eval
    if( eval==d_qy.d_false ){
      Assert( props.empty() );
      //we have inferred a conflict
      conflict( ii.d_curr_exp );
      return false;
    }else{
      for( unsigned i=0; i<props.size(); i++ ){
        Trace("qip-prop-debug2")  << "Process propagation " << props[i] << std::endl;
        //if we haven't propagated this literal yet
        if( cacheConclusion( id, props[i], 1 ) ){
          Node lit = props[i].getKind()==NOT ? props[i][0] : props[i];
          bool pol = props[i].getKind()!=NOT;
          if( lit.getKind()==EQUAL ){
            propagate( lit[0], lit[1], pol, ii.d_curr_exp );
          }else{
            propagate( lit, pol ? d_qy.d_true : d_qy.d_false, true, ii.d_curr_exp );
          }
          if( d_conflict ){
            return false;
          }
        }
        Trace("qip-prop-debug2")  << "Done process propagation " << props[i] << std::endl;
      }
      //if we have not inferred this conclusion yet
      if( cacheConclusion( id, eval ) ){
        ii.d_curr = eval;
        //update the watch list
        Trace("qip-prop-debug") << "...updating watch list for [" << id << "], curr is " << ii.d_curr << std::endl;
        //Here, we need to be notified of enough terms such that if we are not notified, then update( ii ) will return no propagations.
        //  Similar to two-watched literals, but since we are in UF, we need to watch all terms on a complete path of two terms.
        for( std::map< Node, bool >::iterator itw = watch_list.begin(); itw != watch_list.end(); ++itw ){
          d_watch_list[ itw->first ][ id ] = true;
        }
      }else{
        Trace("qip-prop-debug") << "...conclusion " << eval << " is duplicate." << std::endl;
        ii.d_active = false;
      }
    }
  }else{
    Trace("qip-prop-debug") << "...did not update." << std::endl;
  }
  Assert( !d_conflict );
  return true;
}
void FirstOrderPropagation::simplify( std::vector< Node >& assertions ) {
    for( unsigned i=0; i<assertions.size(); i++) {
        Trace("fo-rsn") << "Assert : " << assertions[i] << std::endl;
    }

    //process all assertions
    int num_processed;
    int num_true = 0;
    int num_rounds = 0;
    do {
        num_processed = 0;
        for( unsigned i=0; i<assertions.size(); i++ ) {
            if( d_assertion_true.find(assertions[i])==d_assertion_true.end() ) {
                std::vector< Node > fo_lits;
                collectLits( assertions[i], fo_lits );
                Node unitLit = process( assertions[i], fo_lits );
                if( !unitLit.isNull() ) {
                    Trace("fo-rsn-debug") << "...possible unit literal : " << unitLit << " from " << assertions[i] << std::endl;
                    bool pol = unitLit.getKind()!=NOT;
                    unitLit = unitLit.getKind()==NOT ? unitLit[0] : unitLit;
                    if( unitLit.getKind()==EQUAL ) {

                    } else if( unitLit.getKind()==APPLY_UF ) {
                        //make sure all are unique vars;
                        bool success = true;
                        std::vector< Node > unique_vars;
                        for( unsigned j=0; j<unitLit.getNumChildren(); j++) {
                            if( unitLit[j].getKind()==BOUND_VARIABLE ) {
                                if( std::find(unique_vars.begin(), unique_vars.end(), unitLit[j])==unique_vars.end() ) {
                                    unique_vars.push_back( unitLit[j] );
                                } else {
                                    success = false;
                                    break;
                                }
                            } else {
                                success = false;
                                break;
                            }
                        }
                        if( success ) {
                            d_const_def[unitLit.getOperator()] = NodeManager::currentNM()->mkConst(pol);
                            Trace("fo-rsn") << "Propagate : " << unitLit.getOperator() << " == " << pol << std::endl;
                            Trace("fo-rsn") << "    from : " << assertions[i] << std::endl;
                            d_assertion_true[assertions[i]] = true;
                            num_processed++;
                        }
                    } else if( unitLit.getKind()==VARIABLE ) {
                        d_const_def[unitLit] = NodeManager::currentNM()->mkConst(pol);
                        Trace("fo-rsn") << "Propagate variable : " << unitLit << " == " << pol << std::endl;
                        Trace("fo-rsn") << "    from : " << assertions[i] << std::endl;
                        d_assertion_true[assertions[i]] = true;
                        num_processed++;
                    }
                }
                if( d_assertion_true.find(assertions[i])!=d_assertion_true.end() ) {
                    num_true++;
                }
            }
        }
        num_rounds++;
    } while( num_processed>0 );
    Trace("fo-rsn-sum") << "Simplified " << num_true << " / " << assertions.size() << " in " << num_rounds << " rounds." << std::endl;
    for( unsigned i=0; i<assertions.size(); i++ ) {
        assertions[i] = theory::Rewriter::rewrite( simplify( assertions[i] ) );
    }
}
Example #8
0
//if evaluate( n ) = eVal,
// let n' = ri * n be the formula n instantiated with the current values in r_iter
// if eVal = 1, then n' is true, if eVal = -1, then n' is false,
// if eVal = 0, then n' cannot be proven to be equal to phaseReq
// if eVal is not 0, then
//   each n{ri->d_index[0]/x_0...ri->d_index[depIndex]/x_depIndex, */x_(depIndex+1) ... */x_n } is equivalent in the current model
int FirstOrderModel::evaluate( Node n, int& depIndex, RepSetIterator* ri ){
  ++d_eval_formulas;
  //Debug("fmf-eval-debug") << "Evaluate " << n << " " << phaseReq << std::endl;
  //Notice() << "Eval " << n << std::endl;
  if( n.getKind()==NOT ){
    int val = evaluate( n[0], depIndex, ri );
    return val==1 ? -1 : ( val==-1 ? 1 : 0 );
  }else if( n.getKind()==OR || n.getKind()==AND || n.getKind()==IMPLIES ){
    int baseVal = n.getKind()==AND ? 1 : -1;
    int eVal = baseVal;
    int posDepIndex = ri->getNumTerms();
    int negDepIndex = -1;
    for( int i=0; i<(int)n.getNumChildren(); i++ ){
      //evaluate subterm
      int childDepIndex;
      Node nn = ( i==0 && n.getKind()==IMPLIES ) ? n[i].notNode() : n[i];
      int eValT = evaluate( nn, childDepIndex, ri );
      if( eValT==baseVal ){
        if( eVal==baseVal ){
          if( childDepIndex>negDepIndex ){
            negDepIndex = childDepIndex;
          }
        }
      }else if( eValT==-baseVal ){
        eVal = -baseVal;
        if( childDepIndex<posDepIndex ){
          posDepIndex = childDepIndex;
          if( posDepIndex==-1 ){
            break;
          }
        }
      }else if( eValT==0 ){
        if( eVal==baseVal ){
          eVal = 0;
        }
      }
    }
    if( eVal!=0 ){
      depIndex = eVal==-baseVal ? posDepIndex : negDepIndex;
      return eVal;
    }else{
      return 0;
    }
  }else if( n.getKind()==IFF || n.getKind()==XOR ){
    int depIndex1;
    int eVal = evaluate( n[0], depIndex1, ri );
    if( eVal!=0 ){
      int depIndex2;
      int eVal2 = evaluate( n.getKind()==XOR ? n[1].notNode() : n[1], depIndex2, ri );
      if( eVal2!=0 ){
        depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
        return eVal==eVal2 ? 1 : -1;
      }
    }
    return 0;
  }else if( n.getKind()==ITE ){
    int depIndex1, depIndex2;
    int eVal = evaluate( n[0], depIndex1, ri );
    if( eVal==0 ){
      //evaluate children to see if they are the same value
      int eval1 = evaluate( n[1], depIndex1, ri );
      if( eval1!=0 ){
        int eval2 = evaluate( n[1], depIndex2, ri );
        if( eval1==eval2 ){
          depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
          return eval1;
        }
      }
    }else{
      int eValT = evaluate( n[eVal==1 ? 1 : 2], depIndex2, ri );
      depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
      return eValT;
    }
    return 0;
  }else if( n.getKind()==FORALL ){
    return 0;
  }else{
    ++d_eval_lits;
    ////if we know we will fail again, immediately return
    //if( d_eval_failed.find( n )!=d_eval_failed.end() ){
    //  if( d_eval_failed[n] ){
    //    return -1;
    //  }
    //}
    //Debug("fmf-eval-debug") << "Evaluate literal " << n << std::endl;
    int retVal = 0;
    depIndex = ri->getNumTerms()-1;
    Node val = evaluateTerm( n, depIndex, ri );
    if( !val.isNull() ){
      if( areEqual( val, d_true ) ){
        retVal = 1;
      }else if( areEqual( val, d_false ) ){
        retVal = -1;
      }else{
        if( val.getKind()==EQUAL ){
          if( areEqual( val[0], val[1] ) ){
            retVal = 1;
          }else if( areDisequal( val[0], val[1] ) ){
            retVal = -1;
          }
        }
      }
    }
    if( retVal!=0 ){
      Debug("fmf-eval-debug") << "Evaluate literal: return " << retVal << ", depIndex = " << depIndex << std::endl;
    }else{
      ++d_eval_lits_unknown;
      Trace("fmf-eval-amb") << "Neither true nor false : " << n << std::endl;
      Trace("fmf-eval-amb") << "   value : " << val << std::endl;
      //std::cout << "Neither true nor false : " << n << std::endl;
      //std::cout << "  Value : " << val << std::endl;
      //for( int i=0; i<(int)n.getNumChildren(); i++ ){
      //  std::cout << "   " << i << " : " << n[i].getType() << std::endl;
      //}
    }
    return retVal;
  }
}
Example #9
0
bool AlgebraicSolver::quickCheck(std::vector<Node>& facts) {
  SatValue res = d_quickSolver->checkSat(facts, d_budget);

  if (res == SAT_VALUE_UNKNOWN) {
    d_isComplete.set(false);
    Debug("bv-subtheory-algebraic") << " Unknown.\n";
    ++(d_statistics.d_numUnknown);
    return true;
  }
  
  if (res == SAT_VALUE_TRUE) {
    Debug("bv-subtheory-algebraic") << " Sat.\n";
    ++(d_statistics.d_numSat);
    ++(d_numSolved);
    d_isComplete.set(true);
    return true;
  }

  Assert (res == SAT_VALUE_FALSE);
  Assert (d_quickSolver->inConflict());
  d_isComplete.set(true);
  
  Debug("bv-subtheory-algebraic") << " Unsat.\n";
  ++(d_numSolved);
  ++(d_statistics.d_numUnsat);

  
  Node conflict = d_quickSolver->getConflict();
  Debug("bv-subtheory-algebraic") << " Conflict: " << conflict << "\n";

  // singleton conflict
  if (conflict.getKind() != kind::AND) {
    Assert (d_ids.find(conflict) != d_ids.end());
    unsigned id = d_ids[conflict]; 
    Assert (id < d_explanations.size()); 
    Node theory_confl = d_explanations[id];
    d_bv->setConflict(theory_confl);
    return false;
  }

  Assert (conflict.getKind() == kind::AND);
  if (options::bitvectorQuickXplain()) {
    d_quickSolver->popToZero();
    Debug("bv-quick-xplain") << "AlgebraicSolver::quickCheck original conflict size " << conflict.getNumChildren() << "\n";
    conflict = d_quickXplain->minimizeConflict(conflict);
    Debug("bv-quick-xplain") << "AlgebraicSolver::quickCheck minimized conflict size " << conflict.getNumChildren() << "\n";
  }
  
  vector<TNode> theory_confl;
  for (unsigned i = 0; i < conflict.getNumChildren(); ++i) {
    TNode c = conflict[i];

    Assert (d_ids.find(c) != d_ids.end()); 
    unsigned c_id = d_ids[c];
    Assert (c_id < d_explanations.size());
    TNode c_expl = d_explanations[c_id];
    theory_confl.push_back(c_expl);
  }
  
  Node confl = BooleanSimplification::simplify(utils::mkAnd(theory_confl));

  Debug("bv-subtheory-algebraic") << " Out Conflict: " << confl << "\n";
  setConflict(confl);
  return false;
}
Example #10
0
Node ExtractSkolemizer::mkSkolem(Node node) {
  Assert (node.getKind() == kind::BITVECTOR_EXTRACT &&
          node[0].getMetaKind() == kind::metakind::VARIABLE);
  Assert (!d_skolemSubst.hasSubstitution(node));
  return utils::mkVar(utils::getSize(node)); 
}
Example #11
0
//this isolates the atom into solved form
//     veq_c * pv <> val + vts_coeff_delta * delta + vts_coeff_inf * inf
//  ensures val is Int if pv is Int, and val does not contain vts symbols
int ArithInstantiator::solve_arith( CegInstantiator * ci, Node pv, Node atom, Node& veq_c, Node& val, Node& vts_coeff_inf, Node& vts_coeff_delta ) {
  int ires = 0;
  Trace("cbqi-inst-debug") << "isolate for " << pv << " in " << atom << std::endl;
  std::map< Node, Node > msum;
  if( QuantArith::getMonomialSumLit( atom, msum ) ){
    Trace("cbqi-inst-debug") << "got monomial sum: " << std::endl;
    if( Trace.isOn("cbqi-inst-debug") ){
      QuantArith::debugPrintMonomialSum( msum, "cbqi-inst-debug" );
    }
    TypeNode pvtn = pv.getType();
    //remove vts symbols from polynomial
    Node vts_coeff[2];
    for( unsigned t=0; t<2; t++ ){
      if( !d_vts_sym[t].isNull() ){
        std::map< Node, Node >::iterator itminf = msum.find( d_vts_sym[t] );
        if( itminf!=msum.end() ){
          vts_coeff[t] = itminf->second;
          if( vts_coeff[t].isNull() ){
            vts_coeff[t] = NodeManager::currentNM()->mkConst( Rational( 1 ) );
          }
          //negate if coefficient on variable is positive
          std::map< Node, Node >::iterator itv = msum.find( pv );
          if( itv!=msum.end() ){
            //multiply by the coefficient we will isolate for
            if( itv->second.isNull() ){
              vts_coeff[t] = QuantArith::negate(vts_coeff[t]);
            }else{
              if( !pvtn.isInteger() ){
                vts_coeff[t] = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(-1) / itv->second.getConst<Rational>() ), vts_coeff[t] );
                vts_coeff[t] = Rewriter::rewrite( vts_coeff[t] );
              }else if( itv->second.getConst<Rational>().sgn()==1 ){
                vts_coeff[t] = QuantArith::negate(vts_coeff[t]);
              }
            }
          }
          Trace("cbqi-inst-debug") << "vts[" << t << "] coefficient is " << vts_coeff[t] << std::endl;
          msum.erase( d_vts_sym[t] );
        }
      }
    }

    ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() );
    if( ires!=0 ){
      Node realPart;
      if( Trace.isOn("cbqi-inst-debug") ){
        Trace("cbqi-inst-debug") << "Isolate : ";
        if( !veq_c.isNull() ){
          Trace("cbqi-inst-debug") << veq_c << " * ";
        }
        Trace("cbqi-inst-debug") << pv << " " << atom.getKind() << " " << val << std::endl;
      }
      if( options::cbqiAll() ){
        // when not pure LIA/LRA, we must check whether the lhs contains pv
        if( TermDb::containsTerm( val, pv ) ){
          Trace("cbqi-inst-debug") << "fail : contains bad term" << std::endl;
          return 0;
        }
      }
      if( pvtn.isInteger() && ( ( !veq_c.isNull() && !veq_c.getType().isInteger() ) || !val.getType().isInteger() ) ){
        //redo, split integer/non-integer parts
        bool useCoeff = false;
        Integer coeff = ci->getQuantifiersEngine()->getTermDatabase()->d_one.getConst<Rational>().getNumerator();
        for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
          if( it->first.isNull() || it->first.getType().isInteger() ){
            if( !it->second.isNull() ){
              coeff = coeff.lcm( it->second.getConst<Rational>().getDenominator() );
              useCoeff = true;
            }
          }
        }
        //multiply everything by this coefficient
        Node rcoeff = NodeManager::currentNM()->mkConst( Rational( coeff ) );
        std::vector< Node > real_part;
        for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
          if( useCoeff ){
            if( it->second.isNull() ){
              msum[it->first] = rcoeff;
            }else{
              msum[it->first] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, it->second, rcoeff ) );
            }
          }
          if( !it->first.isNull() && !it->first.getType().isInteger() ){
            real_part.push_back( msum[it->first].isNull() ? it->first : NodeManager::currentNM()->mkNode( MULT, msum[it->first], it->first ) );
          }
        }
        //remove delta  TODO: check this
        vts_coeff[1] = Node::null();
        //multiply inf
        if( !vts_coeff[0].isNull() ){
          vts_coeff[0] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, rcoeff, vts_coeff[0] ) );
        }
        realPart = real_part.empty() ? ci->getQuantifiersEngine()->getTermDatabase()->d_zero : ( real_part.size()==1 ? real_part[0] : NodeManager::currentNM()->mkNode( PLUS, real_part ) );
        Assert( ci->getOutput()->isEligibleForInstantiation( realPart ) );
        //re-isolate
        Trace("cbqi-inst-debug") << "Re-isolate..." << std::endl;
        ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() );
        Trace("cbqi-inst-debug") << "Isolate for mixed Int/Real : " << veq_c << " * " << pv << " " << atom.getKind() << " " << val << std::endl;
        Trace("cbqi-inst-debug") << "                 real part : " << realPart << std::endl;
        if( ires!=0 ){
          int ires_use = ( msum[pv].isNull() || msum[pv].getConst<Rational>().sgn()==1 ) ? 1 : -1;
          val = Rewriter::rewrite( NodeManager::currentNM()->mkNode( ires_use==-1 ? PLUS : MINUS,
                                    NodeManager::currentNM()->mkNode( ires_use==-1 ? MINUS : PLUS, val, realPart ),
                                    NodeManager::currentNM()->mkNode( TO_INTEGER, realPart ) ) );  //TODO: round up for upper bounds?
          Trace("cbqi-inst-debug") << "result : " << val << std::endl;
          Assert( val.getType().isInteger() );
        }
      }
    }
    vts_coeff_inf = vts_coeff[0];
    vts_coeff_delta = vts_coeff[1];
    Trace("cbqi-inst-debug") << "Return " << veq_c << " * " << pv << " " << atom.getKind() << " " << val << ", vts = (" << vts_coeff_inf << ", " << vts_coeff_delta << ")" << std::endl;
  }else{
    Trace("cbqi-inst-debug") << "fail : could not get monomial sum" << std::endl;
  }
  return ires;
}
Example #12
0
bool ArithInstantiator::processAssertion( CegInstantiator * ci, SolvedForm& sf, Node pv, Node lit, unsigned effort ) {
  Trace("cbqi-inst-debug2") << "  look at " << lit << std::endl;
  Node atom = lit.getKind()==NOT ? lit[0] : lit;
  bool pol = lit.getKind()!=NOT;
  //arithmetic inequalities and disequalities
  if( atom.getKind()==GEQ || ( atom.getKind()==EQUAL && !pol && atom[0].getType().isReal() ) ){
    Assert( atom.getKind()!=GEQ || atom[1].isConst() );
    Node atom_lhs;
    Node atom_rhs;
    if( atom.getKind()==GEQ ){
      atom_lhs = atom[0];
      atom_rhs = atom[1];
    }else{
      atom_lhs = NodeManager::currentNM()->mkNode( MINUS, atom[0], atom[1] );
      atom_lhs = Rewriter::rewrite( atom_lhs );
      atom_rhs = ci->getQuantifiersEngine()->getTermDatabase()->d_zero;
    }
    //must be an eligible term
    if( ci->isEligible( atom_lhs ) ){
      //apply substitution to LHS of atom
      Node atom_lhs_coeff;
      atom_lhs = ci->applySubstitution( d_type, atom_lhs, sf, atom_lhs_coeff );
      if( !atom_lhs.isNull() ){
        if( !atom_lhs_coeff.isNull() ){
          atom_rhs = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, atom_lhs_coeff, atom_rhs ) );
        }
      }
      //if it contains pv, not infinity
      if( !atom_lhs.isNull() && ci->hasVariable( atom_lhs, pv ) ){
        Node pv_value = ci->getModelValue( pv );
        Node satom = NodeManager::currentNM()->mkNode( atom.getKind(), atom_lhs, atom_rhs );
        //cannot contain infinity?
        Trace("cbqi-inst-debug") << "..[3] From assertion : " << atom << ", pol = " << pol << std::endl;
        Trace("cbqi-inst-debug") << "         substituted : " << satom << ", pol = " << pol << std::endl;
        Node vts_coeff_inf;
        Node vts_coeff_delta;
        Node val;
        Node veq_c;
        //isolate pv in the inequality
        int ires = solve_arith( ci, pv, satom, veq_c, val, vts_coeff_inf, vts_coeff_delta );
        if( ires!=0 ){
          //disequalities are either strict upper or lower bounds
          unsigned rmax = ( atom.getKind()==GEQ || options::cbqiModel() ) ? 1 : 2;
          for( unsigned r=0; r<rmax; r++ ){
            int uires = ires;
            Node uval = val;
            if( atom.getKind()==GEQ ){
              //push negation downwards
              if( !pol ){
                uires = -ires;
                if( d_type.isInteger() ){
                  uval = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkConst( Rational( uires ) ) );
                  uval = Rewriter::rewrite( uval );
                }else{
                  Assert( d_type.isReal() );
                  //now is strict inequality
                  uires = uires*2;
                }
              }
            }else{
              bool is_upper;
              if( options::cbqiModel() ){
                // disequality is a disjunction : only consider the bound in the direction of the model
                //first check if there is an infinity...
                if( !vts_coeff_inf.isNull() ){
                  //coefficient or val won't make a difference, just compare with zero
                  Trace("cbqi-inst-debug") << "Disequality : check infinity polarity " << vts_coeff_inf << std::endl;
                  Assert( vts_coeff_inf.isConst() );
                  is_upper = ( vts_coeff_inf.getConst<Rational>().sgn()==1 );
                }else{
                  Node rhs_value = ci->getModelValue( val );
                  Node lhs_value = pv_value;
                  if( !veq_c.isNull() ){
                    lhs_value = NodeManager::currentNM()->mkNode( MULT, lhs_value, veq_c );
                    lhs_value = Rewriter::rewrite( lhs_value );
                  }
                  Trace("cbqi-inst-debug") << "Disequality : check model values " << lhs_value << " " << rhs_value << std::endl;
                  Assert( lhs_value!=rhs_value );
                  Node cmp = NodeManager::currentNM()->mkNode( GEQ, lhs_value, rhs_value );
                  cmp = Rewriter::rewrite( cmp );
                  Assert( cmp.isConst() );
                  is_upper = ( cmp!=ci->getQuantifiersEngine()->getTermDatabase()->d_true );
                }
              }else{
                is_upper = (r==0);
              }
              Assert( atom.getKind()==EQUAL && !pol );
              if( d_type.isInteger() ){
                uires = is_upper ? -1 : 1;
                uval = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkConst( Rational( uires ) ) );
                uval = Rewriter::rewrite( uval );
              }else{
                Assert( d_type.isReal() );
                uires = is_upper ? -2 : 2;
              }
            }
            Trace("cbqi-bound-inf") << "From " << lit << ", got : ";
            if( !veq_c.isNull() ){
              Trace("cbqi-bound-inf") << veq_c << " * ";
            }
            Trace("cbqi-bound-inf") << pv << " -> " << uval << ", styp = " << uires << std::endl;
            //take into account delta
            if( ci->useVtsDelta() && ( uires==2 || uires==-2 ) ){
              if( options::cbqiModel() ){
                Node delta_coeff = NodeManager::currentNM()->mkConst( Rational( uires > 0 ? 1 : -1 ) );
                if( vts_coeff_delta.isNull() ){
                  vts_coeff_delta = delta_coeff;
                }else{
                  vts_coeff_delta = NodeManager::currentNM()->mkNode( PLUS, vts_coeff_delta, delta_coeff );
                  vts_coeff_delta = Rewriter::rewrite( vts_coeff_delta );
                }
              }else{
                Node delta = ci->getQuantifiersEngine()->getTermDatabase()->getVtsDelta();
                uval = NodeManager::currentNM()->mkNode( uires==2 ? PLUS : MINUS, uval, delta );
                uval = Rewriter::rewrite( uval );
              }
            }
            if( options::cbqiModel() ){
              //just store bounds, will choose based on tighest bound
              unsigned index = uires>0 ? 0 : 1;
              d_mbp_bounds[index].push_back( uval );
              d_mbp_coeff[index].push_back( veq_c );
              Trace("cbqi-inst-debug") << "Store bound " << index << " " << uval << " " << veq_c << " " << vts_coeff_inf << " " << vts_coeff_delta << " " << lit << std::endl;
              for( unsigned t=0; t<2; t++ ){
                d_mbp_vts_coeff[index][t].push_back( t==0 ? vts_coeff_inf : vts_coeff_delta );
              }
              d_mbp_lit[index].push_back( lit );
            }else{
              //try this bound
              if( ci->doAddInstantiationInc( pv, uval, veq_c, uires>0 ? 1 : -1, sf, effort ) ){
                return true;
              }
            }
          }
        }
      }
    }
  }


  return false;
}
PeepHoleOpt::Changed PeepHoleOpt::handleInst_SETcc(Inst* inst)
{
    if (((BasicBlock*)inst->getNode())->getLayoutSucc() == NULL)
    {
        Mnemonic mn = inst->getMnemonic();
        
        Inst* prev = inst->getPrevInst();
        Inst *next = inst->getNextInst();

        Node *currNode = inst->getNode();
        bool methodMarkerOccur = false;
        MethodMarkerPseudoInst* methodMarker = NULL;
        // ignoring instructions that have no effect and saving method markers to correct them during optimizations
        while (next == NULL || next->getKind() == Inst::Kind_MethodEndPseudoInst || next->getMnemonic() == Mnemonic_JMP)
        {
            if (next == NULL)
            {
                currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode();
                if (currNode->getKind() == Node::Kind_Exit)
                    return Changed_Nothing;
                next = (Inst*) currNode->getFirstInst();
            }
            else
            {
                if (next->getKind() == Inst::Kind_MethodEndPseudoInst)
                {
                    //max 1 saved method marker
                    if (methodMarkerOccur)
                    {
                        return Changed_Nothing;
                    }
                    methodMarker = (MethodMarkerPseudoInst*)next;
                    methodMarkerOccur = true;
                }
                next = next->getNextInst();
            }
        }

        Inst *next2 = next->getNextInst();

        bool step1 = true;
        currNode = inst->getNode();
        while (currNode != next->getNode())
        {
            currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode();
            if (currNode->getInDegree()!=1)
            {
                step1 = false;
                break;
            }
        }

        // step1:
        // ------------------------------------------
        // MOV opnd, 0                  MOV opnd2, 0
        // SETcc opnd           ->      SETcc opnd2
        // MOV opnd2, opnd
        // ------------------------------------------
        // nb: applicable if opnd will not be used further
        if (step1 && prev!= NULL && prev->getMnemonic() == Mnemonic_MOV &&
            next!= NULL && next->getMnemonic() == Mnemonic_MOV)
        {
            Opnd *prevopnd1, *prevopnd2, *nextopnd1, *nextopnd2, *setopnd;
            if (prev->getKind() == Inst::Kind_CopyPseudoInst)
            {
                prevopnd1 = prev->getOpnd(0);
                prevopnd2 = prev->getOpnd(1);
            }
            else
            {
                Inst::Opnds prevuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds prevdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                prevopnd1 = prev->getOpnd(prevdefs.begin());
                prevopnd2 = prev->getOpnd(prevuses.begin());
            }
            if (next->getKind() == Inst::Kind_CopyPseudoInst)
            {
                nextopnd1 = next->getOpnd(0);
                nextopnd2 = next->getOpnd(1);
            }
            else
            {
                Inst::Opnds nextuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds nextdefs(next, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                nextopnd1 = next->getOpnd(nextdefs.begin());
                nextopnd2 = next->getOpnd(nextuses.begin());
            }
            Inst::Opnds setdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
            setopnd = inst->getOpnd(setdefs.begin());

            if (isReg(nextopnd1) &&
                prevopnd1->getId() == setopnd->getId() &&
                setopnd->getId() == nextopnd2->getId() &&
                isImm(prevopnd2) && prevopnd2->getImmValue() == 0
                )
            {
                BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
                irManager->updateLivenessInfo();
                irManager->getLiveAtExit(next->getNode(), ls);
                for (Inst* i = (Inst*)next->getNode()->getLastInst(); i!=next; i = i->getPrevInst()) {
                    irManager->updateLiveness(i, ls);
                }
                bool opndNotUsed = !ls.getBit(setopnd->getId());
                if (opndNotUsed)
                {
                    if (nextopnd1->getRegName() != RegName_Null &&
                        Constraint::getAliasRegName(nextopnd1->getRegName(), OpndSize_8) == RegName_Null)
                    {
                        nextopnd1->assignRegName(setopnd->getRegName());
                    }
                    irManager->newInst(Mnemonic_MOV, nextopnd1, prevopnd2)->insertBefore(inst);
                    irManager->newInst(mn, nextopnd1)->insertBefore(inst);
                    prev->unlink();
                    inst->unlink();
                    next->unlink();
                    return Changed_Node;
                }
            }
        }

        // step2:
        // --------------------------------------------------------------
        // MOV opnd, 0                  Jcc smwh                Jcc smwh
        // SETcc opnd           ->      BB1:            v       BB1:
        // CMP opnd, 0                  ...
        // Jcc smwh                     CMP opnd, 0
        // BB1:                         Jcc smwh
        // --------------------------------------------------------------
        // nb: applicable if opnd will not be used further
        // nb: conditions of new jumps are calculated from conditions of old jump and set instructions
	    if (prev!= NULL && prev->getMnemonic() == Mnemonic_MOV &&
            next!= NULL && (next->getMnemonic() == Mnemonic_CMP || next->getMnemonic() == Mnemonic_TEST) &&
            next2!= NULL && (next2->getMnemonic() == Mnemonic_JG || next2->getMnemonic() == Mnemonic_JE || next2->getMnemonic() == Mnemonic_JNE) )
	    {
            Opnd* movopnd1;
            Opnd* movopnd2;
            if (prev->getKind() == Inst::Kind_CopyPseudoInst)
            {
                movopnd1 = prev->getOpnd(0);
                movopnd2 = prev->getOpnd(1);
            }
            else
            {
                Inst::Opnds movuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds movdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                movopnd1 = prev->getOpnd(movdefs.begin());
                movopnd2 = prev->getOpnd(movuses.begin());
            }
            Inst::Opnds cmpuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
            Opnd* cmpopnd1 = next->getOpnd(cmpuses.begin());
            Opnd* cmpopnd2 = next->getOpnd(cmpuses.next(cmpuses.begin()));

            if (
                isImm(movopnd2) && movopnd2->getImmValue() == 0 &&
                movopnd1->getId() == cmpopnd1->getId() &&
                //case CMP:
                (next->getMnemonic() != Mnemonic_CMP || (isImm(cmpopnd2) && cmpopnd2->getImmValue() == 0)) &&
                //case TEST:
                (next->getMnemonic() != Mnemonic_TEST || cmpopnd1->getId() == cmpopnd2->getId())
                )
            {
                BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
                irManager->updateLivenessInfo();
                irManager->getLiveAtExit(next2->getNode(), ls);
                bool opndNotUsed = !ls.getBit(movopnd1->getId());
                if (opndNotUsed)
                {
                    BranchInst* br = (BranchInst*) next2;

                    Mnemonic newjumpmn = Mnemonic_JZ;
                    if (next2->getMnemonic() == Mnemonic_JE)
                    {
                        switch (mn)
                        {
                        case Mnemonic_SETG:
                            newjumpmn = Mnemonic_JLE; break;
                        case Mnemonic_SETE:
                            newjumpmn = Mnemonic_JNE; break;
                        case Mnemonic_SETL:
                            newjumpmn = Mnemonic_JGE; break;
                        case Mnemonic_SETNE:
                            newjumpmn = Mnemonic_JE; break;
                        default:
                            assert(0); break;
                        }
                    }
                    else
                    {
                        switch (mn)
                        {
                        case Mnemonic_SETG:
                            newjumpmn = Mnemonic_JG; break;
                        case Mnemonic_SETE:
                            newjumpmn = Mnemonic_JE; break;
                        case Mnemonic_SETL:
                            newjumpmn = Mnemonic_JL; break;
                        case Mnemonic_SETNE:
                            newjumpmn = Mnemonic_JNE; break;
                        default:
                            assert(0); break;
                        }
                    }

                    if (inst->getNode()->getId() != next->getNode()->getId())
                    {
                        ControlFlowGraph* cfg = irManager->getFlowGraph();
                        cfg->removeEdge(inst->getNode()->getOutEdge(Edge::Kind_Unconditional));

                        double trueEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_True)->getEdgeProb();
                        double falseEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_False)->getEdgeProb();
                        cfg->addEdge(inst->getNode(), br->getTrueTarget(), trueEdgeProb);
                        cfg->addEdge(inst->getNode(), br->getFalseTarget(), falseEdgeProb);
                        irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(inst);
                        if (methodMarkerOccur)
                        {
                            inst->getNode()->appendInst(irManager->newMethodEndPseudoInst(methodMarker->getMethodDesc()));
                        }
		                prev->unlink();
		                inst->unlink();
                        cfg->purgeUnreachableNodes();
                    }
                    else
                    {
                        irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(next2);
                        prev->unlink();
		                inst->unlink();
		                next->unlink();
                        next2->unlink();
                    }
		            return Changed_Node;
                }// endif opndNotUsed
            }
        }
    }
	return Changed_Nothing;
}
Example #14
0
Node Rewriter::rewriteTo(theory::TheoryId theoryId, Node node) {

#ifdef CVC4_ASSERTIONS
  bool isEquality = node.getKind() == kind::EQUAL && (!node[0].getType().isBoolean());

  if(s_rewriteStack == NULL) {
    s_rewriteStack = new std::unordered_set<Node, NodeHashFunction>();
  }
#endif

  Trace("rewriter") << "Rewriter::rewriteTo(" << theoryId << "," << node << ")"<< std::endl;

  // Check if it's been cached already
  Node cached = getPostRewriteCache(theoryId, node);
  if (!cached.isNull()) {
    return cached;
  }

  // Put the node on the stack in order to start the "recursive" rewrite
  vector<RewriteStackElement> rewriteStack;
  rewriteStack.push_back(RewriteStackElement(node, theoryId));

  ResourceManager* rm = NULL;
  bool hasSmtEngine = smt::smtEngineInScope();
  if (hasSmtEngine) {
    rm = NodeManager::currentResourceManager();
  }
  // Rewrite until the stack is empty
  for (;;){

    if (hasSmtEngine &&
		d_iterationCount % ResourceManager::getFrequencyCount() == 0) {
      rm->spendResource(options::rewriteStep());
      d_iterationCount = 0;
    }

    // Get the top of the recursion stack
    RewriteStackElement& rewriteStackTop = rewriteStack.back();

    Trace("rewriter") << "Rewriter::rewriting: " << (TheoryId) rewriteStackTop.theoryId << "," << rewriteStackTop.node << std::endl;

    // Before rewriting children we need to do a pre-rewrite of the node
    if (rewriteStackTop.nextChild == 0) {

      // Check if the pre-rewrite has already been done (it's in the cache)
      Node cached = Rewriter::getPreRewriteCache((TheoryId) rewriteStackTop.theoryId, rewriteStackTop.node);
      if (cached.isNull()) {
        // Rewrite until fix-point is reached
        for(;;) {
          // Perform the pre-rewrite
          RewriteResponse response = Rewriter::callPreRewrite((TheoryId) rewriteStackTop.theoryId, rewriteStackTop.node);
          // Put the rewritten node to the top of the stack
          rewriteStackTop.node = response.node;
          TheoryId newTheory = theoryOf(rewriteStackTop.node);
          // In the pre-rewrite, if changing theories, we just call the other theories pre-rewrite
          if (newTheory == (TheoryId) rewriteStackTop.theoryId && response.status == REWRITE_DONE) {
            break;
          }
          rewriteStackTop.theoryId = newTheory;
        }
        // Cache the rewrite
        Rewriter::setPreRewriteCache((TheoryId) rewriteStackTop.originalTheoryId, rewriteStackTop.original, rewriteStackTop.node);
      }
      // Otherwise we're have already been pre-rewritten (in pre-rewrite cache)
      else {
        // Continue with the cached version
        rewriteStackTop.node = cached;
        rewriteStackTop.theoryId = theoryOf(cached);
      }
    }

    rewriteStackTop.original =rewriteStackTop.node;
    // Now it's time to rewrite the children, check if this has already been done
    Node cached = Rewriter::getPostRewriteCache((TheoryId) rewriteStackTop.theoryId, rewriteStackTop.node);
    // If not, go through the children
    if(cached.isNull()) {

      // The child we need to rewrite
      unsigned child = rewriteStackTop.nextChild++;

      // To build the rewritten expression we set up the builder
      if(child == 0) {
        if (rewriteStackTop.node.getNumChildren() > 0) {
          // The children will add themselves to the builder once they're done
          rewriteStackTop.builder << rewriteStackTop.node.getKind();
          kind::MetaKind metaKind = rewriteStackTop.node.getMetaKind();
          if (metaKind == kind::metakind::PARAMETERIZED) {
            rewriteStackTop.builder << rewriteStackTop.node.getOperator();
          }
        }
      }

      // Process the next child
      if(child < rewriteStackTop.node.getNumChildren()) {
        // The child node
        Node childNode = rewriteStackTop.node[child];
        // Push the rewrite request to the stack (NOTE: rewriteStackTop might be a bad reference now)
        rewriteStack.push_back(RewriteStackElement(childNode, theoryOf(childNode)));
        // Go on with the rewriting
        continue;
      }

      // Incorporate the children if necessary
      if (rewriteStackTop.node.getNumChildren() > 0) {
        Node rewritten = rewriteStackTop.builder;
        rewriteStackTop.node = rewritten;
        rewriteStackTop.theoryId = theoryOf(rewriteStackTop.node);
      }

      // Done with all pre-rewriting, so let's do the post rewrite
      for(;;) {
        // Do the post-rewrite
        RewriteResponse response = Rewriter::callPostRewrite((TheoryId) rewriteStackTop.theoryId, rewriteStackTop.node);
        // We continue with the response we got
        TheoryId newTheoryId = theoryOf(response.node);
        if (newTheoryId != (TheoryId) rewriteStackTop.theoryId || response.status == REWRITE_AGAIN_FULL) {
          // In the post rewrite if we've changed theories, we must do a full rewrite
          Assert(response.node != rewriteStackTop.node);
          //TODO: this is not thread-safe - should make this assertion dependent on sequential build
#ifdef CVC4_ASSERTIONS
          Assert(s_rewriteStack->find(response.node) == s_rewriteStack->end());
          s_rewriteStack->insert(response.node);
#endif
          Node rewritten = rewriteTo(newTheoryId, response.node);
          rewriteStackTop.node = rewritten;
#ifdef CVC4_ASSERTIONS
          s_rewriteStack->erase(response.node);
#endif
          break;
        } else if (response.status == REWRITE_DONE) {
#ifdef CVC4_ASSERTIONS
	  RewriteResponse r2 = Rewriter::callPostRewrite(newTheoryId, response.node);
	  Assert(r2.node == response.node);
#endif
	  rewriteStackTop.node = response.node;
          break;
        }
        // Check for trivial rewrite loops of size 1 or 2
        Assert(response.node != rewriteStackTop.node);
        Assert(Rewriter::callPostRewrite((TheoryId) rewriteStackTop.theoryId, response.node).node != rewriteStackTop.node);
	rewriteStackTop.node = response.node;
      }
      // We're done with the post rewrite, so we add to the cache
      Rewriter::setPostRewriteCache((TheoryId) rewriteStackTop.originalTheoryId, rewriteStackTop.original, rewriteStackTop.node);

    } else {
      // We were already in cache, so just remember it
      rewriteStackTop.node = cached;
      rewriteStackTop.theoryId = theoryOf(cached);
    }

    // If this is the last node, just return
    if (rewriteStack.size() == 1) {
      Assert(!isEquality || rewriteStackTop.node.getKind() == kind::EQUAL || rewriteStackTop.node.isConst());
      return rewriteStackTop.node;
    }

    // We're done with this node, append it to the parent
    rewriteStack[rewriteStack.size() - 2].builder << rewriteStackTop.node;
    rewriteStack.pop_back();
  }

  Unreachable();
}/* Rewriter::rewriteTo() */
Example #15
0
//if possible, returns a formula n' such that n' => ( n <=> polarity ), and n' is true in the current context,
//   and NULL otherwise
Node QModelBuilderInstGen::getSelectionFormula( Node fn, Node n, bool polarity, int useOption ){
  Trace("sel-form-debug") << "Looking for selection formula " << n << " " << polarity << std::endl;
  Node ret;
  if( n.getKind()==NOT ){
    ret = getSelectionFormula( fn[0], n[0], !polarity, useOption );
  }else if( n.getKind()==OR || n.getKind()==AND ){
    //whether we only need to find one or all
    bool favorPol = ( n.getKind()!=AND && polarity ) || ( n.getKind()==AND && !polarity );
    std::vector< Node > children;
    for( int i=0; i<(int)n.getNumChildren(); i++ ){
      Node fnc = fn[i];
      Node nc = n[i];
      Node nn = getSelectionFormula( fnc, nc, polarity, useOption );
      if( nn.isNull() && !favorPol ){
        //cannot make selection formula
        children.clear();
        break;
      }
      if( !nn.isNull() ){
        //if( favorPol ){   //temporary
        //  return nn;      //
        //}                 //
        if( std::find( children.begin(), children.end(), nn )==children.end() ){
          children.push_back( nn );
        }
      }
    }
    if( !children.empty() ){
      if( favorPol ){
        //filter which formulas we wish to keep, make disjunction
        Node min_lit;
        int min_score = -1;
        for( size_t i=0; i<children.size(); i++ ){
          //if it is constant apply uf application, return it for sure
          if( hasConstantDefinition( children[i] ) ){
            min_lit = children[i];
            break;
          }else{
            int score = getSelectionFormulaScore( children[i] );
            if( min_score<0 || score<min_score ){
              min_score = score;
              min_lit = children[i];
            }
          }
        }
        //currently just return the best single literal
        ret = min_lit;
      }else{
        //selection formula must be conjunction of children
        ret = mkAndSelectionFormula( children );
      }
    }else{
      ret = Node::null();
    }
  }else if( n.getKind()==ITE ){
    Node nn;
    Node nc[2];
    //get selection formula for the
    for( int i=0; i<2; i++ ){
      nn = getSelectionFormula( fn[0], n[0], i==0, useOption );
      nc[i] = getSelectionFormula( fn[i+1], n[i+1], polarity, useOption );
      if( !nn.isNull() && !nc[i].isNull() ){
        ret = mkAndSelectionFormula( nn, nc[i] );
        break;
      }
    }
    if( ret.isNull() && !nc[0].isNull() && !nc[1].isNull() ){
      ret = mkAndSelectionFormula( nc[0], nc[1] );
    }
  }else if( n.getKind()==IFF ){
    bool opPol = !polarity;
    for( int p=0; p<2; p++ ){
      Node nn[2];
      for( int i=0; i<2; i++ ){
        bool pol = i==0 ? p==0 : ( opPol ? p!=0 : p==0 );
        nn[i] = getSelectionFormula( fn[i], n[i], pol, useOption );
        if( nn[i].isNull() ){
          break;
        }
      }
      if( !nn[0].isNull() && !nn[1].isNull() ){
        ret = mkAndSelectionFormula( nn[0], nn[1] );
      }
    }
  }else{
    //literal case
    //first, check if it is a usable selection literal
    if( isUsableSelectionLiteral( n, useOption ) ){
      bool value;
      if( d_qe->getValuation().hasSatValue( n, value ) ){
        if( value==polarity ){
          ret = fn;
          if( !polarity ){
            ret = ret.negate();
          }
        }else{
          Trace("sel-form-debug") << "  (wrong polarity)" << std::endl;
        }
      }else{
        Trace("sel-form-debug") << "  (does not have sat value)" << std::endl;
      }
    }else{
      Trace("sel-form-debug") << "  (is not usable literal)" << std::endl;
    }
  }
  Trace("sel-form-debug") << "   return " << ret << std::endl;
  return ret;
}
Example #16
0
 void TermDb::reset( Theory::Effort effort ){
   int nonCongruentCount = 0;
   int congruentCount = 0;
   int alreadyCongruentCount = 0;
   //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
   for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
     d_op_count[ it->first ] = 0;
     if( !it->second.empty() ){
       if( it->second[0].getType().isBoolean() ){
         d_pred_map_trie[ 0 ][ it->first ].d_data.clear();
         d_pred_map_trie[ 1 ][ it->first ].d_data.clear();
       }else{
         d_func_map_trie[ it->first ].d_data.clear();
         for( int i=0; i<(int)it->second.size(); i++ ){
           Node n = it->second[i];
           computeModelBasisArgAttribute( n );
           if( !n.getAttribute(NoMatchAttribute()) ){
             if( !d_func_map_trie[ it->first ].addTerm( d_quantEngine, n ) ){
               NoMatchAttribute nma;
               n.setAttribute(nma,true);
               congruentCount++;
             }else{
               nonCongruentCount++;
               d_op_count[ it->first ]++;
             }
           }else{
             congruentCount++;
             alreadyCongruentCount++;
           }
         }
       }
     }
   }
   for( int i=0; i<2; i++ ){
     Node n = NodeManager::currentNM()->mkConst( i==1 );
     if( d_quantEngine->getEqualityQuery()->getEngine()->hasTerm( n ) ){
       eq::EqClassIterator eqc( d_quantEngine->getEqualityQuery()->getEngine()->getRepresentative( n ),
                                d_quantEngine->getEqualityQuery()->getEngine() );
       while( !eqc.isFinished() ){
         Node en = (*eqc);
         computeModelBasisArgAttribute( en );
         if( en.getKind()==APPLY_UF && !en.hasAttribute(InstConstantAttribute()) ){
           if( !en.getAttribute(NoMatchAttribute()) ){
             Node op = en.getOperator();
             if( !d_pred_map_trie[i][op].addTerm( d_quantEngine, en ) ){
               NoMatchAttribute nma;
               en.setAttribute(nma,true);
               congruentCount++;
             }else{
               nonCongruentCount++;
               d_op_count[ op ]++;
             }
           }else{
             alreadyCongruentCount++;
           }
         }
         ++eqc;
       }
     }
   }
   Debug("term-db-cong") << "TermDb: Reset" << std::endl;
   Debug("term-db-cong") << "Congruent/Non-Congruent = ";
   Debug("term-db-cong") << congruentCount << "(" << alreadyCongruentCount << ") / " << nonCongruentCount << std::endl;
}
Example #17
0
bool PseudoBooleanProcessor::decomposeAssertion(Node assertion, bool negated)
{
  if (assertion.getKind() != kind::GEQ)
  {
    return false;
  }
  Assert(assertion.getKind() == kind::GEQ);

  Debug("pbs::rewrites") << "decomposeAssertion" << assertion << std::endl;

  Node l = assertion[0];
  Node r = assertion[1];

  if (r.getKind() != kind::CONST_RATIONAL)
  {
    Debug("pbs::rewrites") << "not rhs constant" << assertion << std::endl;
    return false;
  }
  // don't bother matching on anything other than + on the left hand side
  if (l.getKind() != kind::PLUS)
  {
    Debug("pbs::rewrites") << "not plus" << assertion << std::endl;
    return false;
  }

  if (!Polynomial::isMember(l))
  {
    Debug("pbs::rewrites") << "not polynomial" << assertion << std::endl;
    return false;
  }

  Polynomial p = Polynomial::parsePolynomial(l);
  clear();
  if (negated)
  {
    // (not (>= p r))
    // (< p r)
    // (> (-p) (-r))
    // (>= (-p) (-r +1))
    d_off = (-r.getConst<Rational>());

    if (d_off.value().isIntegral())
    {
      d_off = d_off.value() + Rational(1);
    }
    else
    {
      d_off = Rational(d_off.value().ceiling());
    }
  }
  else
  {
    // (>= p r)
    d_off = r.getConst<Rational>();
    d_off = Rational(d_off.value().ceiling());
  }
  Assert(d_off.value().isIntegral());

  int adj = negated ? -1 : 1;
  for (Polynomial::iterator i = p.begin(), end = p.end(); i != end; ++i)
  {
    Monomial m = *i;
    const Rational& coeff = m.getConstant().getValue();
    if (!(coeff.isOne() || coeff.isNegativeOne()))
    {
      return false;
    }
    Assert(coeff.sgn() != 0);

    const VarList& vl = m.getVarList();
    Node v = vl.getNode();

    if (!isPseudoBoolean(v))
    {
      return false;
    }
    int sgn = adj * coeff.sgn();
    if (sgn > 0)
    {
      d_pos.push_back(v);
    }
    else
    {
      d_neg.push_back(v);
    }
  }
  // all of the variables are pseudoboolean
  // with coefficients +/- and the offsetoff
  return true;
}
Example #18
0
Node FirstOrderModel::evaluateTerm( Node n, int& depIndex, RepSetIterator* ri ){
  //Message() << "Eval term " << n << std::endl;
  Node val;
  depIndex = ri->getNumTerms()-1;
  //check the type of n
  if( n.getKind()==INST_CONSTANT ){
    int v = n.getAttribute(InstVarNumAttribute());
    depIndex = ri->d_var_order[ v ];
    val = ri->getTerm( v );
  }else if( n.getKind()==ITE ){
    int depIndex1, depIndex2;
    int eval = evaluate( n[0], depIndex1, ri );
    if( eval==0 ){
      //evaluate children to see if they are the same
      Node val1 = evaluateTerm( n[ 1 ], depIndex1, ri );
      Node val2 = evaluateTerm( n[ 2 ], depIndex2, ri );
      if( val1==val2 ){
        val = val1;
        depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
      }else{
        return Node::null();
      }
    }else{
      val = evaluateTerm( n[ eval==1 ? 1 : 2 ], depIndex2, ri );
      depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
    }
  }else{
    std::vector< int > children_depIndex;
    //for select, pre-process read over writes
    if( n.getKind()==SELECT ){
#if 0
      //std::cout << "Evaluate " << n << std::endl;
      Node sel = evaluateTerm( n[1], depIndex, ri );
      if( sel.isNull() ){
        depIndex = ri->getNumTerms()-1;
        return Node::null();
      }
      Node arr = getRepresentative( n[0] );
      //if( n[0]!=getRepresentative( n[0] ) ){
      //  std::cout << n[0] << " is " << getRepresentative( n[0] ) << std::endl;
      //}
      int tempIndex;
      int eval = 1;
      while( arr.getKind()==STORE && eval!=0 ){
        eval = evaluate( sel.eqNode( arr[1] ), tempIndex, ri );
        depIndex = tempIndex > depIndex ? tempIndex : depIndex;
        if( eval==1 ){
          val = evaluateTerm( arr[2], tempIndex, ri );
          depIndex = tempIndex > depIndex ? tempIndex : depIndex;
          return val;
        }else if( eval==-1 ){
          arr = arr[0];
        }
      }
      arr = evaluateTerm( arr, tempIndex, ri );
      depIndex = tempIndex > depIndex ? tempIndex : depIndex;
      val = NodeManager::currentNM()->mkNode( SELECT, arr, sel );
#else
      val = evaluateTermDefault( n, depIndex, children_depIndex, ri );
#endif
    }else{
      //default term evaluate : evaluate all children, recreate the value
      val = evaluateTermDefault( n, depIndex, children_depIndex, ri );
    }
    if( !val.isNull() ){
      bool setVal = false;
      //custom ways of evaluating terms
      if( n.getKind()==APPLY_UF ){
        Node op = n.getOperator();
        //Debug("fmf-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;
        //if it is a defined UF, then consult the interpretation
        if( d_uf_model_tree.find( op )!=d_uf_model_tree.end() ){
          ++d_eval_uf_terms;
          int argDepIndex = 0;
          //make the term model specifically for n
          makeEvalUfModel( n );
          //now, consult the model
          if( d_eval_uf_use_default[n] ){
            val = d_uf_model_tree[ op ].getValue( this, val, argDepIndex );
          }else{
            val = d_eval_uf_model[ n ].getValue( this, val, argDepIndex );
          }
          //Debug("fmf-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;
          //d_eval_uf_model[ n ].debugPrint("fmf-eval-debug", d_qe );
          Assert( !val.isNull() );
          //recalculate the depIndex
          depIndex = -1;
          for( int i=0; i<argDepIndex; i++ ){
            int index = d_eval_uf_use_default[n] ? i : d_eval_term_index_order[n][i];
            Debug("fmf-eval-debug") << "Add variables from " << index << "..." << std::endl;
            if( children_depIndex[index]>depIndex ){
              depIndex = children_depIndex[index];
            }
          }
          setVal = true;
        }
      }else if( n.getKind()==SELECT ){
        //we are free to interpret this term however we want
      }
      //if not set already, rewrite and consult model for interpretation
      if( !setVal ){
        val = Rewriter::rewrite( val );
        if( val.getMetaKind()!=kind::metakind::CONSTANT ){
          //FIXME: we cannot do this until we trust all theories collectModelInfo!
          //val = getInterpretedValue( val );
          //val = getRepresentative( val );
        }
      }
      Trace("fmf-eval-debug") << "Evaluate term " << n << " = ";
      printRepresentativeDebug( "fmf-eval-debug", val );
      Trace("fmf-eval-debug") << ", depIndex = " << depIndex << std::endl;
    }
  }
  return val;
}
Example #19
0
static bool isInSwiftModule(Node *node) {
  Node *context = node->getFirstChild();
  return (context->getKind() == Node::Kind::Module &&
          context->getText() == STDLIB_NAME);
};
Example #20
0
//this is identical to TermDb::evaluateTerm2, but tracks more information
Node EqualityQueryInstProp::evaluateTermExp( Node n, std::vector< Node >& exp, std::map< Node, Node >& visited, bool hasPol, bool pol,
                                             std::map< Node, bool >& watch_list_out, std::vector< Node >& props ) {
  std::map< Node, Node >::iterator itv = visited.find( n );
  if( itv != visited.end() ){
    return itv->second;
  }else{
    visited[n] = n;
    Trace("qip-eval") << "evaluate term : " << n << std::endl;
    std::vector< Node > exp_n;
    Node ret = getRepresentativeExp( n, exp_n );
    if( ret.isNull() ){
      //term is not known to be equal to a representative in equality engine, evaluate it
      Kind k = n.getKind();
      if( k==FORALL ){
        ret = Node::null();
      }else{
        std::map< Node, bool > watch_list_out_curr;
        TNode f = d_qe->getTermDatabase()->getMatchOperator( n );
        std::vector< Node > args;
        bool ret_set = false;
        bool childChanged = false;
        int abort_i = -1;
        //get the child entailed polarity
        Assert( n.getKind()!=IMPLIES );
        bool newHasPol, newPol;
        QuantPhaseReq::getEntailPolarity( n, 0, hasPol, pol, newHasPol, newPol );
        //for each child
        for( unsigned i=0; i<n.getNumChildren(); i++ ){
          Node c = evaluateTermExp( n[i], exp, visited, newHasPol, newPol, watch_list_out_curr, props );
          if( c.isNull() ){
            ret = Node::null();
            ret_set = true;
            break;
          }else if( c==d_true || c==d_false ){
            //short-circuiting
            if( k==kind::AND || k==kind::OR ){
              if( (k==kind::AND)==(c==d_false) ){
                ret = c;
                ret_set = true;
                break;
              }else{
                //redundant
                c = Node::null();
                childChanged = true;
              }
            }else if( k==kind::ITE && i==0 ){
              Assert( watch_list_out_curr.empty() );
              ret = evaluateTermExp( n[ c==d_true ? 1 : 2], exp, visited, hasPol, pol, watch_list_out_curr, props );
              ret_set = true;
              break;
            }else if( k==kind::NOT ){
              ret = c==d_true ? d_false : d_true;
              ret_set = true;
              break;
            }
          }
          if( !c.isNull() ){
            childChanged = childChanged || n[i]!=c;
            if( !f.isNull() && !watch_list_out_curr.empty() ){
              // we are done if this is an UF application and an argument is unevaluated
              args.push_back( c );
              abort_i = i;
              break;
            }else if( ( k==kind::AND || k==kind::OR ) ){
              if( c.getKind()==k ){
                //flatten
                for( unsigned j=0; j<c.getNumChildren(); j++ ){
                  addArgument( args, props, c[j], newHasPol, newPol );
                }
              }else{
                addArgument( args, props, c, newHasPol, newPol );
              }
              //if we are in a branching position
              if( hasPol && !newHasPol && args.size()>=2 ){
                //we are done if at least two args are unevaluated
                abort_i = i;
                break;
              }
            }else if( k==kind::ITE ){
              //we are done if we are ITE and condition is unevaluated
              Assert( i==0 );
              args.push_back( c );
              abort_i = i;
              break;
            }else{
              args.push_back( c );
            }
          }
        }
        //add remaining children if we aborted
        if( abort_i!=-1 ){
          for( int i=(abort_i+1); i<(int)n.getNumChildren(); i++ ){
            args.push_back( n[i] );
          }
        }
        //copy over the watch list
        for( std::map< Node, bool >::iterator itc = watch_list_out_curr.begin(); itc != watch_list_out_curr.end(); ++itc ){
          watch_list_out[itc->first] = itc->second;
        }

        //if we have not short-circuited evaluation
        if( !ret_set ){
          //if it is an indexed term, return the congruent term
          if( !f.isNull() && watch_list_out.empty() ){
            std::vector< TNode > t_args;
            for( unsigned i=0; i<args.size(); i++ ) {
              t_args.push_back( args[i] );
            }
            Assert( args.size()==n.getNumChildren() );
            //args contains terms known by the equality engine
            TNode nn = getCongruentTerm( f, t_args );
            Trace("qip-eval") << "  got congruent term " << nn << " from DB for " << n << std::endl;
            if( !nn.isNull() ){
              //successfully constructed representative in EE
              Assert( exp_n.empty() );
              ret = getRepresentativeExp( nn, exp_n );
              Trace("qip-eval") << "return rep, exp size = " << exp_n.size() << std::endl;
              merge_exp( exp, exp_n );
              ret_set = true;
              Assert( !ret.isNull() );
            }
          }
          if( !ret_set ){
            if( childChanged ){
              Trace("qip-eval") << "return rewrite" << std::endl;
              if( ( k==kind::AND || k==kind::OR ) ){
                if( args.empty() ){
                  ret = k==kind::AND ? d_true : d_false;
                  ret_set = true;
                }else if( args.size()==1 ){
                  ret = args[0];
                  ret_set = true;
                }
              }else{
                Assert( args.size()==n.getNumChildren() );
              }
              if( !ret_set ){
                if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){
                  args.insert( args.begin(), n.getOperator() );
                }
                ret = NodeManager::currentNM()->mkNode( k, args );
                ret = Rewriter::rewrite( ret );
                //re-evaluate
                Node ret_eval = getRepresentativeExp( ret, exp_n );
                if( !ret_eval.isNull() ){
                  ret = ret_eval;
                  watch_list_out.clear();
                }else{            
                  watch_list_out[ret] = true;
                }
              }
            }else{
              ret = n;
              watch_list_out[ret] = true;
            }
          }
        }
      }
    }else{
      Trace("qip-eval") << "...exists in ee, return rep, exp size = " << exp_n.size() << std::endl;
      merge_exp( exp, exp_n );
    }
    Trace("qip-eval") << "evaluated term : " << n << ", got : " << ret << ", exp size = " << exp.size() << std::endl;
    visited[n] = ret;
    return ret;
  }
}
Example #21
0
void QModelBuilderDefault::analyzeQuantifier( FirstOrderModel* fm, Node f ) {
    FirstOrderModelIG* fmig = fm->asFirstOrderModelIG();
    Debug("fmf-model-prefs") << "Analyze quantifier " << f << std::endl;
    //the pro/con preferences for this quantifier
    std::vector< Node > pro_con[2];
    //the terms in the selection literal we choose
    std::vector< Node > selectionLitTerms;
    Trace("inst-gen-debug-quant") << "Inst-gen analyze " << f << std::endl;
    //for each asserted quantifier f,
    // - determine selection literals
    // - check which function/predicates have good and bad definitions for satisfying f
    if( d_phase_reqs.find( f )==d_phase_reqs.end() ) {
        d_phase_reqs[f].initialize( d_qe->getTermDatabase()->getInstConstantBody( f ), true );
    }
    int selectLitScore = -1;
    for( std::map< Node, bool >::iterator it = d_phase_reqs[f].d_phase_reqs.begin(); it != d_phase_reqs[f].d_phase_reqs.end(); ++it ) {
        //the literal n is phase-required for quantifier f
        Node n = it->first;
        Node gn = d_qe->getTermDatabase()->getModelBasis( f, n );
        Debug("fmf-model-req") << "   Req: " << n << " -> " << it->second << std::endl;
        bool value;
        //if the corresponding ground abstraction literal has a SAT value
        if( d_qe->getValuation().hasSatValue( gn, value ) ) {
            //collect the non-ground uf terms that this literal contains
            //  and compute if all of the symbols in this literal have
            //  constant definitions.
            bool isConst = true;
            std::vector< Node > uf_terms;
            if( TermDb::hasInstConstAttr(n) ) {
                isConst = false;
                if( gn.getKind()==APPLY_UF ) {
                    uf_terms.push_back( gn );
                    isConst = hasConstantDefinition( gn );
                } else if( gn.getKind()==EQUAL ) {
                    isConst = true;
                    for( int j=0; j<2; j++ ) {
                        if( TermDb::hasInstConstAttr(n[j]) ) {
                            if( n[j].getKind()==APPLY_UF &&
                                    fmig->d_uf_model_tree.find( gn[j].getOperator() )!=fmig->d_uf_model_tree.end() ) {
                                uf_terms.push_back( gn[j] );
                                isConst = isConst && hasConstantDefinition( gn[j] );
                            } else {
                                isConst = false;
                            }
                        }
                    }
                }
            }
            //check if the value in the SAT solver matches the preference according to the quantifier
            int pref = 0;
            if( value!=it->second ) {
                //we have a possible selection literal
                bool selectLit = d_quant_selection_lit[f].isNull();
                bool selectLitConstraints = true;
                //it is a constantly defined selection literal : the quantifier is sat
                if( isConst ) {
                    selectLit = selectLit || d_quant_sat.find( f )==d_quant_sat.end();
                    d_quant_sat[f] = true;
                    //check if choosing this literal would add any additional constraints to default definitions
                    selectLitConstraints = false;
                    for( int j=0; j<(int)uf_terms.size(); j++ ) {
                        Node op = uf_terms[j].getOperator();
                        if( d_uf_prefs[op].d_reconsiderModel ) {
                            selectLitConstraints = true;
                        }
                    }
                    if( !selectLitConstraints ) {
                        selectLit = true;
                    }
                }
                //also check if it is naturally a better literal
                if( !selectLit ) {
                    int score = getSelectionScore( uf_terms );
                    //Trace("inst-gen-debug") << "Check " << score << " < " << selectLitScore << std::endl;
                    selectLit = score<selectLitScore;
                }
                //see if we wish to choose this as a selection literal
                d_quant_selection_lit_candidates[f].push_back( value ? n : n.notNode() );
                if( selectLit ) {
                    selectLitScore = getSelectionScore( uf_terms );
                    Trace("inst-gen-debug") << "Choose selection literal " << gn << std::endl;
                    Trace("inst-gen-debug") << "  flags: " << isConst << " " << selectLitConstraints << " " << selectLitScore << std::endl;
                    d_quant_selection_lit[f] = value ? n : n.notNode();
                    selectionLitTerms.clear();
                    selectionLitTerms.insert( selectionLitTerms.begin(), uf_terms.begin(), uf_terms.end() );
                    if( !selectLitConstraints ) {
                        break;
                    }
                }
                pref = 1;
            } else {
                pref = -1;
            }
            //if we are not yet SAT, so we will add to preferences
            if( d_quant_sat.find( f )==d_quant_sat.end() ) {
                Debug("fmf-model-prefs") << "  It is " << ( pref==1 ? "pro" : "con" );
                Debug("fmf-model-prefs") << " the definition of " << n << std::endl;
                for( int j=0; j<(int)uf_terms.size(); j++ ) {
                    pro_con[ pref==1 ? 0 : 1 ].push_back( uf_terms[j] );
                }
            }
        }
    }
    //process information about selection literal for f
    if( !d_quant_selection_lit[f].isNull() ) {
        d_quant_selection_lit_terms[f].insert( d_quant_selection_lit_terms[f].begin(), selectionLitTerms.begin(), selectionLitTerms.end() );
        for( int i=0; i<(int)selectionLitTerms.size(); i++ ) {
            d_term_selection_lit[ selectionLitTerms[i] ] = d_quant_selection_lit[f];
            d_op_selection_terms[ selectionLitTerms[i].getOperator() ].push_back( selectionLitTerms[i] );
        }
    } else {
        Trace("inst-gen-warn") << "WARNING: " << f << " has no selection literals" << std::endl;
    }
    //process information about requirements and preferences of quantifier f
    if( d_quant_sat.find( f )!=d_quant_sat.end() ) {
        Debug("fmf-model-prefs") << "  * Constant SAT due to definition of ops: ";
        for( int i=0; i<(int)selectionLitTerms.size(); i++ ) {
            Debug("fmf-model-prefs") << selectionLitTerms[i] << " ";
            d_uf_prefs[ selectionLitTerms[i].getOperator() ].d_reconsiderModel = false;
        }
        Debug("fmf-model-prefs") << std::endl;
    } else {
        //note quantifier's value preferences to models
        for( int k=0; k<2; k++ ) {
            for( int j=0; j<(int)pro_con[k].size(); j++ ) {
                Node op = pro_con[k][j].getOperator();
                Node r = fmig->getRepresentative( pro_con[k][j] );
                d_uf_prefs[op].setValuePreference( f, pro_con[k][j], r, k==0 );
            }
        }
    }
}
Example #22
0
Node DtInstantiator::solve_dt(Node v, Node a, Node b, Node sa, Node sb)
{
  Trace("cegqi-arith-debug2") << "Solve dt : " << v << " " << a << " " << b
                              << " " << sa << " " << sb << std::endl;
  Node ret;
  if (!a.isNull() && a == v)
  {
    ret = sb;
  }
  else if (!b.isNull() && b == v)
  {
    ret = sa;
  }
  else if (!a.isNull() && a.getKind() == APPLY_CONSTRUCTOR)
  {
    if (!b.isNull() && b.getKind() == APPLY_CONSTRUCTOR)
    {
      if (a.getOperator() == b.getOperator())
      {
        for (unsigned i = 0, nchild = a.getNumChildren(); i < nchild; i++)
        {
          Node s = solve_dt(v, a[i], b[i], sa[i], sb[i]);
          if (!s.isNull())
          {
            return s;
          }
        }
      }
    }
    else
    {
      NodeManager* nm = NodeManager::currentNM();
      unsigned cindex = Datatype::indexOf(a.getOperator().toExpr());
      TypeNode tn = a.getType();
      const Datatype& dt = static_cast<DatatypeType>(tn.toType()).getDatatype();
      for (unsigned i = 0, nchild = a.getNumChildren(); i < nchild; i++)
      {
        Node nn = nm->mkNode(
            APPLY_SELECTOR_TOTAL,
            Node::fromExpr(dt[cindex].getSelectorInternal(tn.toType(), i)),
            sb);
        Node s = solve_dt(v, a[i], Node::null(), sa[i], nn);
        if (!s.isNull())
        {
          return s;
        }
      }
    }
  }
  else if (!b.isNull() && b.getKind() == APPLY_CONSTRUCTOR)
  {
    // flip sides
    return solve_dt(v, b, a, sb, sa);
  }
  if (!ret.isNull())
  {
    // ensure does not contain v
    if (expr::hasSubterm(ret, v))
    {
      ret = Node::null();
    }
  }
  return ret;
}
Example #23
0
void TheoryQuantifiers::assertUniversal( Node n ){
  Assert( n.getKind()==FORALL );
  if( !options::cbqi() || options::recurseCbqi() || !TermUtil::hasInstConstAttr(n) ){
    getQuantifiersEngine()->assertQuantifier( n, true );
  }
}
Example #24
0
Node QuantifiersRewriter::computeCNF( Node n, std::vector< Node >& args, NodeBuilder<>& defs, bool forcePred ){
  if( isLiteral( n ) ){
    return n;
  }else if( !forcePred && isClause( n ) ){
    return computeClause( n );
  }else{
    Kind k = n.getKind();
    NodeBuilder<> t(k);
    for( int i=0; i<(int)n.getNumChildren(); i++ ){
      Node nc = n[i];
      Node ncnf = computeCNF( nc, args, defs, k!=OR );
      if( k==OR ){
        addNodeToOrBuilder( ncnf, t );
      }else{
        t << ncnf;
      }
    }
    if( !forcePred && k==OR ){
      return t.constructNode();
    }else{
      //compute the free variables
      Node nt = t;
      std::vector< Node > activeArgs;
      computeArgs( args, activeArgs, nt );
      std::vector< TypeNode > argTypes;
      for( int i=0; i<(int)activeArgs.size(); i++ ){
        argTypes.push_back( activeArgs[i].getType() );
      }
      //create the predicate
      Assert( argTypes.size()>0 );
      TypeNode typ = NodeManager::currentNM()->mkFunctionType( argTypes, NodeManager::currentNM()->booleanType() );
      std::stringstream ss;
      ss << "cnf_" << n.getKind() << "_" << n.getId();
      Node op = NodeManager::currentNM()->mkSkolem( ss.str(), typ, "was created by the quantifiers rewriter" );
      std::vector< Node > predArgs;
      predArgs.push_back( op );
      predArgs.insert( predArgs.end(), activeArgs.begin(), activeArgs.end() );
      Node pred = NodeManager::currentNM()->mkNode( APPLY_UF, predArgs );
      Trace("quantifiers-rewrite-cnf-debug") << "Made predicate " << pred << " for " << nt << std::endl;
      //create the bound var list
      Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, activeArgs );
      //now, look at the structure of nt
      if( nt.getKind()==NOT ){
        //case for NOT
        for( int i=0; i<2; i++ ){
          NodeBuilder<> tt(OR);
          tt << ( i==0 ? nt[0].notNode() : nt[0] );
          tt << ( i==0 ? pred.notNode() : pred );
          defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
        }
      }else if( nt.getKind()==OR ){
        //case for OR
        for( int i=0; i<(int)nt.getNumChildren(); i++ ){
          NodeBuilder<> tt(OR);
          tt << nt[i].notNode() << pred;
          defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
        }
        NodeBuilder<> tt(OR);
        for( int i=0; i<(int)nt.getNumChildren(); i++ ){
          tt << nt[i];
        }
        tt << pred.notNode();
        defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
      }else if( nt.getKind()==AND ){
        //case for AND
        for( int i=0; i<(int)nt.getNumChildren(); i++ ){
          NodeBuilder<> tt(OR);
          tt << nt[i] << pred.notNode();
          defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
        }
        NodeBuilder<> tt(OR);
        for( int i=0; i<(int)nt.getNumChildren(); i++ ){
          tt << nt[i].notNode();
        }
        tt << pred;
        defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
      }else if( nt.getKind()==IFF ){
        //case for IFF
        for( int i=0; i<4; i++ ){
          NodeBuilder<> tt(OR);
          tt << ( ( i==0 || i==3 ) ? nt[0].notNode() : nt[0] );
          tt << ( ( i==1 || i==3 ) ? nt[1].notNode() : nt[1] );
          tt << ( ( i==0 || i==1 ) ? pred.notNode() : pred );
          defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
        }
      }else if( nt.getKind()==ITE ){
        //case for ITE
        for( int j=1; j<=2; j++ ){
          for( int i=0; i<2; i++ ){
            NodeBuilder<> tt(OR);
            tt << ( ( j==1 ) ? nt[0].notNode() : nt[0] );
            tt << ( ( i==1 ) ? nt[j].notNode() : nt[j] );
            tt << ( ( i==0 ) ? pred.notNode() : pred );
            defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
          }
        }
        for( int i=0; i<2; i++ ){
          NodeBuilder<> tt(OR);
          tt << ( i==0 ? nt[1].notNode() : nt[1] );
          tt << ( i==0 ? nt[2].notNode() : nt[2] );
          tt << ( i==1 ? pred.notNode() : pred );
          defs << NodeManager::currentNM()->mkNode( FORALL, bvl, tt.constructNode() );
        }
      }else{
        Notice() << "Unhandled Quantifiers CNF: " << nt << std::endl;
      }
      return pred;
    }
  }
}
Node TheoryStringsRewriter::prerewriteConcatRegExp( TNode node ) {
	Assert( node.getKind() == kind::REGEXP_CONCAT );
    Trace("strings-prerewrite") << "Strings::prerewriteConcatRegExp start " << node << std::endl;
    Node retNode = node;
    std::vector<Node> node_vec;
    Node preNode = Node::null();
    for(unsigned int i=0; i<node.getNumChildren(); ++i) {
		Trace("strings-prerewrite") << "Strings::prerewriteConcatRegExp preNode: " << preNode << std::endl;
        Node tmpNode = node[i];
        if(node[i].getKind() == kind::REGEXP_CONCAT) {
            tmpNode = prerewriteConcatRegExp(node[i]);
            if(tmpNode.getKind() == kind::REGEXP_CONCAT) {
                unsigned int j=0;
                if(!preNode.isNull()) {
                    if(tmpNode[0].getKind() == kind::STRING_TO_REGEXP) {
                        preNode = rewriteConcatString(
							NodeManager::currentNM()->mkNode( kind::STRING_CONCAT, preNode, tmpNode[0][0] ) );
                        node_vec.push_back( NodeManager::currentNM()->mkNode( kind::STRING_TO_REGEXP, preNode ) );
                        preNode = Node::null();
                        ++j;
                    } else {
                        node_vec.push_back( NodeManager::currentNM()->mkNode( kind::STRING_TO_REGEXP, preNode ) );
                        preNode = Node::null();
                        node_vec.push_back( tmpNode[0] );
                        ++j;
                    }
                }
                for(; j<tmpNode.getNumChildren() - 1; ++j) {
                    node_vec.push_back( tmpNode[j] );
                }
                tmpNode = tmpNode[j];
            }
        }
        if( tmpNode.getKind() == kind::STRING_TO_REGEXP ) {
            if(preNode.isNull()) {
                preNode = tmpNode[0];
            } else {
				preNode = rewriteConcatString(
							NodeManager::currentNM()->mkNode( kind::STRING_CONCAT, preNode, tmpNode[0] ) );
            }
        } else {
            if(!preNode.isNull()) {
                if(preNode.getKind() == kind::CONST_STRING && preNode.getConst<String>().isEmptyString() ) {
                    preNode = Node::null();
                } else {
                    node_vec.push_back( NodeManager::currentNM()->mkNode( kind::STRING_TO_REGEXP, preNode ) );
                    preNode = Node::null();
                }
            }
            node_vec.push_back( tmpNode );
        }
    }
    if(!preNode.isNull()) {
        node_vec.push_back( NodeManager::currentNM()->mkNode( kind::STRING_TO_REGEXP, preNode ) );
    }
    if(node_vec.size() > 1) {
        retNode = NodeManager::currentNM()->mkNode(kind::REGEXP_CONCAT, node_vec);
    } else {
        retNode = node_vec[0];
    }
    Trace("strings-prerewrite") << "Strings::prerewriteConcatRegExp end " << retNode << std::endl;
    return retNode;
}