Cont_cpr_match_result cpr_match_hb_maxreduce (Compound_region* blk)
{
  // pattern match applies to superblock or hyperblock
  // predicates use must be static single assignment
  // scan the hyper block and build up a hb-descr
  HB_cont_cpr_descr hb_descr(blk);
  Hash_set<Operand> dn_defs(hash_operand, 223);
  if(dbg(cpr,5))
    {
      cout << "Matching control block: " << blk->id() << endl;
      cout << *blk << endl;
    }
  int num_branches=0; // count the branches as we go
  for (Region_ops_C0_order opc(blk); opc != 0; ++opc) {
    // perform the match analysis
    Op* op =  (*opc);
    if(is_cmpp(op)) {// for a compare
      if(dbg(cpr,4)) {cout << "op" << op->id() << " is a compare"<< endl;}
      hb_descr.insert_compare(op);
    } else
      if(is_conditional_branch(op) || is_brl(op) || is_bru(op) ) { //
        if(dbg(cpr,4)){cout << "op" << op->id() << " is a branch"<< endl;}
        hb_descr.insert_branch(op);
        num_branches++;
      }
  }
  //num_branches counts the number of branches in the cont_cpr_descr
  Cont_cpr_match_result result; //construct and initialize cpr_blk_list & cpr_blk_type
  Dlist< Pair<Op*, Op*> >  cpr_blk; // declare current cpr block
  Pair<Op* , Op*> curr_tuple; // tuple for potential inclusion into result
  int curr_br=0; //indicates last branch already in cpr block
  int cand_br; //indicates candidate for potentially joining block
  int prev_blk_last_br=0; //last branch in previous block
  El_Cpr_Match_Info blk_info;

  while(true){ // build new CPR block
    cpr_blk.clear();
    curr_br=prev_blk_last_br+1;
    if(curr_br>num_branches) break;
    curr_tuple=hb_descr.get_tuple(curr_br);
    cpr_blk.push_tail(curr_tuple); //always add first branch to cpr block
    if(dbg(cpr,4)) {
      cout << "pushing tuple into new cpr block: " ;
      print_tuple(cout, curr_tuple);
      cout << endl;
    }
    hb_descr.suitability_init(curr_br); //initialize compare suitability test
    hb_descr.blocking_init(curr_br);
    bool type=false; // initialize to fall_through list
    blk_info = EL_CPR_MATCH_UNKNOWN;
    while(true){ //may append additonal branches to CPR block
      cand_br=curr_br+1;
      if(cand_br > num_branches) {
          blk_info = EL_CPR_MATCH_END;
          break;
      }
      if (dbg(cpr,4))
        cout << "+Considering candidate to be appended: " << cand_br << endl;
      if(!hb_descr.suitability_test(cand_br)) {
        if (dbg(cpr,4))
          cout << "\tSuitability test failed on candidiate - not appended" << endl;
	blk_info = EL_CPR_MATCH_SUITABILITY;
        break;
      }
      if (!hb_descr.max_block_length_test(cand_br)) {
        if (dbg(cpr,4))
          cout << "\tMax block length exceeded  - cand not appended" << endl; 
	blk_info = EL_CPR_MATCH_MAX_BR;
        break;
      }
      //passed all tests
      curr_br=cand_br;
      curr_tuple = hb_descr.get_tuple(curr_br);
      cpr_blk.push_tail(curr_tuple); //append candidate branch to cpr block
      if(dbg(cpr,4))
        {
          cout << "pushing tuple into previous cpr block: " ;
          print_tuple(cout, curr_tuple);
          cout << endl;
        }
    }
    result.cpr_blk_list.push_tail(cpr_blk);
    type = hb_descr.predict_taken(curr_br);
    result.cpr_blk_type.push_tail(type);
    result.cpr_blk_info.push_tail(blk_info);
    prev_blk_last_br=curr_br;
  }
  return result;
}
Cont_cpr_match_result cpr_match_hb_original (Compound_region* blk){
  // pattern match applies to superblock or hyperblock
  // predicates use must be static single assignment
  // scan the hyper block and build up a hb-descr
  HB_cont_cpr_descr hb_descr(blk);
  Hash_set<Operand> dn_defs(hash_operand, 223);
  if(dbg(cpr,5))
    {
      cout << "Matching control block: " << blk->id() << endl;
      cout << *blk << endl;
    }
  int num_branches=0; // count the branches as we go
  for (Region_ops_C0_order opc(blk); opc != 0; ++opc) {
    // perform the match analysis
    Op* op =  (*opc);
    if(is_cmpp(op)) {// for a compare
      if(dbg(cpr,4)) {cout << "op" << op->id() << " is a compare"<< endl;}
      hb_descr.insert_compare(op);
    } else
      if(is_conditional_branch(op) || is_brl(op) || is_bru(op) ) { //
	if(dbg(cpr,4)){cout << "op" << op->id() << " is a branch"<< endl;}
	hb_descr.insert_branch(op);
	num_branches++;
      }     
  }
  //num_branches counts the number of branches in the cont_cpr_descr
  Cont_cpr_match_result result; //construct and initialize cpr_blk_list & cpr_blk_type
  Dlist< Pair<Op*, Op*> >  cpr_blk; // declare current cpr block
  Pair<Op* , Op*> curr_tuple; // tuple for potential inclusion into result
  int curr_br=0; //indicates last branch already in cpr block
  int cand_br; //indicates candidate for potentially joining block
  int prev_blk_last_br=0; //last branch in previous block
  bool blk_type=false;
  El_Cpr_Match_Info blk_info;
  while(true){
    cpr_blk.clear(); //begin building new CPR block 
    curr_br=prev_blk_last_br+1;
    if(curr_br>num_branches) break;
    curr_tuple=hb_descr.get_tuple(curr_br);
    cpr_blk.push_tail(curr_tuple); //always add first branch to cpr block
    if(dbg(cpr,4)) {
      cout << endl << "pushing tuple into new cpr block: " ;
      print_tuple(cout, curr_tuple);
      cout << endl;
    }
    hb_descr.suitability_init(curr_br); //initialize compare suitability test
    hb_descr.separability_init(curr_br);
    hb_descr.blocking_init(curr_br);
    bool predict_taken=false;
    bool predict_pausea=false;
    bool predict_break=false;
    blk_info = EL_CPR_MATCH_UNKNOWN;
    while(true){ //may append additonal branches to CPR block
      if(hb_descr.predict_taken(curr_br))  //complete tests which break after inclusion
	{
	  if (dbg(cpr,4)) { cout << "predict taken current\n";}
	  blk_type=true; //block of type taken block
	  blk_info = EL_CPR_MATCH_PRED_TAKEN;
	  break;
	}
      if( hb_descr.predict_break(curr_br) )
	{
	  if (dbg(cpr,4)) {cout<<"predicted break current"<<endl;}
	  blk_info = EL_CPR_MATCH_BREAK;
	  break;
	} 
      if(hb_descr.predict_pausea(curr_br))
	{
	  if (dbg(cpr,4)) { cout << "predict pausea current\n";}
	  blk_type=false;
	  blk_info = EL_CPR_MATCH_PAUSEA;
	  break;
	}
      cand_br=curr_br+1;
      if(cand_br > num_branches) 
        {
          blk_info = EL_CPR_MATCH_END;
          break;
	}
      if (dbg(cpr,4)) {cout<< "Considering candidate to be appended:" << cand_br << endl;}
      if(!hb_descr.suitability_test(cand_br)) {
        if (dbg(cpr,4))
	  {cout << "Suitability test failed -- candidiate not appended" << endl;} 
	blk_info = EL_CPR_MATCH_SUITABILITY;
        break; // preform suitability test and cut block if fails
      }
      if(!hb_descr.separability_test(cand_br)) {
        if (dbg(cpr,4))
          cout << "Separability test failed -- candidiate not appended" << endl; 
	blk_info = EL_CPR_MATCH_SEPARABILITY;
        break;
      }
      if(hb_descr.predict_taken(cand_br)&&hb_descr.can_move_back(prev_blk_last_br+1,cand_br))
      { // CPR to taken branch case
        if (dbg(cpr,4)) {cout << "Predict taken(cand_br)\n";}
	predict_taken=true;
      }

      if(!predict_taken && hb_descr.predict_break(cand_br)) {
	if (dbg(cpr,4)) {cout << "Predict break\n";} 
	predict_break=true; //preclude growth of next block
	blk_info = EL_CPR_MATCH_BREAK;
	break; 
      }

      //blocking test not applied in taken branch case
      if (!predict_taken && !predict_break && !hb_descr.sum_exit_freq_test(cand_br)) {
        if (dbg(cpr,4))  {cout << "Exit frequency exceeded" << endl;} 
	blk_info = EL_CPR_MATCH_EXIT_RATIO;
        break;
      }

      if(!predict_taken && hb_descr.predict_pauseb(cand_br)) {
        if (dbg(cpr,4)) {cout << "Predict pauseb\n";} 
	blk_info = EL_CPR_MATCH_PAUSEB;
	break; 
      }

      if(!predict_taken && hb_descr.predict_pausea(cand_br)) {
        if (dbg(cpr,4)) {cout << "Predict pausea\n";} 
	predict_pausea=true;
      }

      if (!hb_descr.max_block_length_test(cand_br)) {
        if (dbg(cpr,4)) {cout << "Max block length\n";} 
	blk_info = EL_CPR_MATCH_MAX_BR;
	break;
      }

      //passed all tests which break before inclusion
      curr_br=cand_br; 
      curr_tuple = hb_descr.get_tuple(curr_br);
      cpr_blk.push_tail(curr_tuple); //append candidate branch to cpr block
      if(dbg(cpr,4))
	{
	  cout << "Pushing tuple into previous cpr block. " ;
	  print_tuple(cout, curr_tuple);
	  cout << endl;
	} 
    }
    // add new cpr block to list if of appropriate size
    if((int) cpr_blk.size() >= El_cpr_min_block_length)
      {
     if(dbg(cpr,4))
	{
	  cout << "Adequate sized block pushed, type: " << blk_type << endl;
	}
	result.cpr_blk_list.push_tail(cpr_blk);
	result.cpr_blk_type.push_tail(blk_type);
	result.cpr_blk_info.push_tail(blk_info);
      }
    else
      {
	curr_br=prev_blk_last_br+1; // roll back to block of length one
	curr_tuple=cpr_blk.head();  //keep only the first tuple from the current block
	cpr_blk.clear(); cpr_blk.push_tail(curr_tuple);
	result.cpr_blk_list.push_tail(cpr_blk);
	result.cpr_blk_type.push_tail(false);
	result.cpr_blk_info.push_tail(blk_info);
        if (dbg(cpr,4)) 
	  {
	    cout << "Block too short, fabricating singleton cpr block. " ;
	    print_tuple(cout, curr_tuple);
	    cout << endl;
	  }
      }
    prev_blk_last_br=curr_br;
    if (dbg(cpr,4)) {
      cout << "prev_blk_last_br=" << prev_blk_last_br << endl;
    }
  }
  return result;
}