Esempio n. 1
0
static
String handle_static_mark_statement(CPrintStyleModule *state,
				    const SuifObject *obj)
{
  MarkStatement *stmt = to<MarkStatement>(obj);
  String return_str;
  BrickAnnote *br = to<BrickAnnote>(stmt->peek_annote("line"));
  return_str = "Mark";
  if (br != 0) {
    String file = to<StringBrick>(br->get_brick(1))->get_value();
    IInteger line = to<IntegerBrick>(br->get_brick(0))->get_value();
    return_str += " ";
    return_str += file + ":" + line.to_String();
  }
  return(return_str);
}
bool CopyPropagationPass2::IsOnlyDefinition(StoreVariableStatement* def,
					    LoadVariableExpression* use)
{
  BrickAnnote* defAnnote =
    to<BrickAnnote>(use->lookup_annote_by_name("reaching_defs")) ;
  assert(defAnnote != NULL) ;

  if (defAnnote->get_brick_count() != 1)
  {
    return false ;
  }

  SuifBrick* defBrick = defAnnote->get_brick(0) ;
  SuifObjectBrick* sob = dynamic_cast<SuifObjectBrick*>(defBrick) ;
  assert(sob != NULL) ;

  if (def == sob->get_object())
  {
    return true ;
  }
  else
  {
    return false ;
  }
}
Esempio n. 3
0
void ExportPass::execute()
{
  assert(theEnv != NULL) ;

  OutputInformation("Export pass begins") ;

  // Get the information regarding the current procedure by looking at
  //  the first procedure from the first file in the file set block.

  Iter<FileBlock*> temp =
    theEnv->get_file_set_block()->get_file_block_iterator() ;
  Iter<ProcedureDefinition*> temp2 = (temp.current())->get_definition_block()->get_procedure_definition_iterator() ;

  originalProcedure = temp2.current() ;
  assert(originalProcedure != NULL) ;

  // Modules have been transformed into structs so all the previous 
  //  passes work, and here we have to do a little bit of backtracking
  //  and convert them to the straight model.
  BrickAnnote* rocccType = 
    dynamic_cast<BrickAnnote*>(originalProcedure->lookup_annote_by_name("FunctionType")) ;
  assert(rocccType != NULL) ;
  IntegerBrick* valueBrick = 
    dynamic_cast<IntegerBrick*>(rocccType->get_brick(0)) ;
  assert(valueBrick != NULL) ;
  int functionType = valueBrick->get_value().c_int() ;
  delete rocccType->remove_brick(0) ;
  delete originalProcedure->remove_annote_by_name("FunctionType") ;

  if (functionType == 1) // Module
  {
    // De-modulize it
    ConstructModuleSymbols() ;
  }
  else if (functionType == 2 || functionType == 3) // Systems
  {
    // Just create clones
    ConstructSystemSymbols() ;
  }
  else
  {
    assert(0 && "Trying to export something unknown") ;
  }

  ReadRepository() ;  
  AddSymbols() ;

  DumpRepository() ;

  OutputInformation("Export pass ends") ;
}
void CopyPropagationPass2::HandleFeedbackVariables(LoadVariableExpression* n,
						   VariableSymbol* replacement)
{
  assert(n != NULL) ;
  assert(replacement != NULL) ;

  VariableSymbol* toReplace = n->get_source() ;

  // Go through all the feedback variables
  list<VariableSymbol*>::iterator feedbackIter = feedbackVariables.begin() ;
  while (feedbackIter != feedbackVariables.end())
  {
    BrickAnnote* nextAnnote = 
      to<BrickAnnote>((*feedbackIter)->lookup_annote_by_name("FeedbackVariable")) ;
    assert(nextAnnote != NULL) ;

    SuifBrick* one = nextAnnote->get_brick(0) ;
    SuifBrick* two = nextAnnote->get_brick(1) ;

    SuifObjectBrick* firstObj = dynamic_cast<SuifObjectBrick*>(one) ;
    SuifObjectBrick* secondObj = dynamic_cast<SuifObjectBrick*>(two) ;
    assert(firstObj != NULL) ;
    assert(secondObj != NULL) ;

    VariableSymbol* dest = 
      dynamic_cast<VariableSymbol*>(firstObj->get_object()) ;
    VariableSymbol* source = 
      dynamic_cast<VariableSymbol*>(secondObj->get_object()) ;
    
    assert(dest != NULL) ;
    assert(source != NULL) ;

    if (dest == toReplace)
    {
      firstObj->set_object(replacement) ;
    }

    if (source == toReplace)
    {
      secondObj->set_object(replacement) ;
    }

    ++feedbackIter ;
  }

}
void CleanupBoolSelsPass::do_procedure_definition(ProcedureDefinition* p)
{
  procDef = p ;
  assert(procDef != NULL) ;

  OutputInformation("Cleanup Boolean Select Pass Begins") ;
  
  // Find all of the locations that have been marked as "UndefinedPath"
  Annote* functionAnnote = procDef->lookup_annote_by_name("FunctionType") ;
  BrickAnnote* functionBrickAnnote = 
    dynamic_cast<BrickAnnote*>(functionAnnote) ;
  assert(functionBrickAnnote != NULL) ;
  IntegerBrick* valueBrick = 
    dynamic_cast<IntegerBrick*>(functionBrickAnnote->get_brick(0)) ;
  assert(valueBrick != NULL) ;
  
  int myType = valueBrick->get_value().c_int() ;

  if (myType == MODULE)
  {
    // Find all of the expressions marked "UndefinedPath" and replace with
    //  the integer constant zero.
    list<Expression*>* allExpr = 
      collect_objects<Expression>(procDef->get_body()) ;
    list<Expression*>::iterator exprIter = allExpr->begin() ;
    while (exprIter != allExpr->end())
    {
      if ((*exprIter)->lookup_annote_by_name("UndefinedPath") != NULL)
      {
	Expression* zero = 
	  create_int_constant(theEnv,
			      (*exprIter)->get_result_type(),
			      IInteger(0)) ;
	(*exprIter)->get_parent()->replace((*exprIter), zero) ; 
      }
      ++exprIter ;
    }
    delete allExpr ;
  }

  OutputInformation("Cleanup Boolean Select Pass Ends") ;
}
Esempio n. 6
0
void ExportPass::ConstructSystemSymbols()
{
  ProcedureSymbol* originalSymbol = originalProcedure->get_procedure_symbol() ;
  assert(originalSymbol != NULL) ;
  CProcedureType* originalType = 
    dynamic_cast<CProcedureType*>(originalSymbol->get_type()) ;
  assert(originalType != NULL) ;

  constructedType = create_c_procedure_type(theEnv,
    dynamic_cast<DataType*>(originalType->get_result_type()->deep_clone()),
					    false, // has variable arguments
					    false, // arguments known
					    0) ; // bit alignment

  // The system has been written in one of two ways, either the old
  //  way where there are no arguments, or the new way where everything
  //  is put into the arguments.
  
  if (originalType->get_argument_count() > 0)
  {
    for (int i = 0 ; i < originalType->get_argument_count() ; ++i)
    {
      QualifiedType* originalArgument = originalType->get_argument(i) ;
      DataType* originalBase = originalArgument->get_base_type() ;
      DataType* constructedBase = CloneDataType(originalBase) ;
      QualifiedType* constructedArgument = 
	create_qualified_type(theEnv, constructedBase) ;
      constructedType->append_argument(constructedArgument) ;

      // Go through the symbol table and find the parameter symbol 
      //  that matches the parameter number, and check to see if it
      //  is an output or not...
      SymbolTable* symTab = originalProcedure->get_symbol_table() ;
      ParameterSymbol* correspondingSymbol = NULL ;
      for (int j = 0 ; j < symTab->get_symbol_table_object_count() ; ++j)
      {
	ParameterSymbol* currentSym = 
	  dynamic_cast<ParameterSymbol*>(symTab->get_symbol_table_object(j)) ;
	if (currentSym != NULL)
	{
	  BrickAnnote* orderAnnote = dynamic_cast<BrickAnnote*>(currentSym->lookup_annote_by_name("ParameterOrder")) ;
	  assert(orderAnnote != NULL) ;
	  IntegerBrick* orderBrick = 
	    dynamic_cast<IntegerBrick*>(orderAnnote->get_brick(0)) ;
	  assert(orderBrick != NULL) ;
	  if (orderBrick->get_value().c_int() == i)
	  {
	    correspondingSymbol = currentSym ;
	    break ;
	  }
	}
      }
      if (correspondingSymbol != NULL)
      {
        if (correspondingSymbol->lookup_annote_by_name("OutputScalar") != NULL ||
	    correspondingSymbol->lookup_annote_by_name("OutputVariable") != NULL ||
	    correspondingSymbol->lookup_annote_by_name("OutputFifo") != NULL)
        {
	  constructedArgument->append_annote(create_brick_annote(theEnv,
								 "Output")) ;
        }
      }
      //      if (dynamic_cast<ReferenceType*>(originalBase) != NULL)
      //{
      //	constructedArgument->append_annote(create_brick_annote(theEnv,
      //						       "Output")) ;
      //      }
    }
  }
  else
  {   
    SymbolTable* symTab = originalProcedure->get_symbol_table() ;
    assert(symTab != NULL) ;
    list<VariableSymbol*> inputScalars ;
    list<VariableSymbol*> inputFifos ; 
    list<VariableSymbol*> outputScalars ;
    list<VariableSymbol*> outputFifos ;

    for (int i = 0 ; i < symTab->get_symbol_table_object_count() ; ++i)
    {
      VariableSymbol* currentVar = 
	dynamic_cast<VariableSymbol*>(symTab->get_symbol_table_object(i)) ;
      if (currentVar != NULL &&
	  currentVar->lookup_annote_by_name("InputScalar") != NULL &&
	  currentVar->lookup_annote_by_name("TemporalFeedback") == NULL &&
	  currentVar->lookup_annote_by_name("NormalFeedback") == NULL &&
	  currentVar->lookup_annote_by_name("DebugRegister") == NULL)
      {
	inputScalars.push_back(currentVar) ;
      }
      if (currentVar != NULL &&
	  currentVar->lookup_annote_by_name("InputFifo") != NULL)
      {
	inputFifos.push_back(currentVar) ;
      }
      if (currentVar != NULL &&
	  currentVar->lookup_annote_by_name("OutputVariable") != NULL &&
	  currentVar->lookup_annote_by_name("Dummy") == NULL &&
	  currentVar->lookup_annote_by_name("FeedbackSource") == NULL)
      {
	outputScalars.push_back(currentVar) ;
      }
      if (currentVar != NULL &&
	  currentVar->lookup_annote_by_name("OutputFifo") != NULL)
      {
	outputFifos.push_back(currentVar) ;
      }
    }
    // Add the types of the input scalars, then the input fifos, 
    //  then the output scalars, and finally the output fifos.
    list<VariableSymbol*>::iterator varIter = inputScalars.begin() ;
    while (varIter != inputScalars.end())
    {
      QualifiedType* originalQual = (*varIter)->get_type() ;
      assert(originalQual != NULL) ;
      DataType* originalBase = originalQual->get_base_type() ;
      assert(originalBase != NULL) ;
      DataType* constructedBase = 
	dynamic_cast<DataType*>(originalBase->deep_clone()) ;
      QualifiedType* constructedQual = 
	create_qualified_type(theEnv, constructedBase) ;
      constructedType->append_argument(constructedQual) ;
      ++varIter ;
    }
    varIter = inputFifos.begin() ;
    while (varIter != inputFifos.end())
    {
      QualifiedType* originalQual = (*varIter)->get_type() ;
      assert(originalQual != NULL) ;
      DataType* originalBase = originalQual->get_base_type() ;
      assert(originalBase != NULL) ;
      // Fifos will have pointer types or reference types.  A 
      //  simple deep clone will not suffice, I need to build up a
      //  new type from the bottom up.
      DataType* constructedBase = CloneDataType(originalBase) ;
      assert(constructedBase != NULL) ;
      QualifiedType* constructedQual = 
	create_qualified_type(theEnv, constructedBase) ;
      assert(constructedBase != NULL) ;
      assert(constructedType != NULL) ;
      constructedType->append_argument(constructedQual) ;
      ++varIter ;
    }
    varIter = outputScalars.begin() ;
    while (varIter != outputScalars.end())
    {
      QualifiedType* originalQual = (*varIter)->get_type() ;
      DataType* originalBase = originalQual->get_base_type() ;
      DataType* constructedBase = CloneDataType(originalBase) ;
      QualifiedType* constructedQual = 
	create_qualified_type(theEnv, constructedBase) ;
      constructedQual->append_annote(create_brick_annote(theEnv, "Output")) ;
      constructedType->append_argument(constructedQual) ;
      ++varIter ;
    }
    varIter = outputFifos.begin() ;
    while (varIter != outputFifos.end())
    {
      QualifiedType* originalQual = (*varIter)->get_type() ;
      assert(originalQual != NULL) ;
      DataType* originalBase = originalQual->get_base_type() ;
      assert(originalBase != NULL) ;
      DataType* constructedBase = CloneDataType(originalBase) ;
      assert(constructedBase != NULL) ;
      QualifiedType* constructedQual = 
	create_qualified_type(theEnv, constructedBase) ;
      assert(constructedQual != NULL) ;
      constructedQual->append_annote(create_brick_annote(theEnv, "Output")) ;
      assert(constructedType != NULL) ;
      constructedType->append_argument(constructedQual) ;
      ++varIter ;
    }
    
  }
  constructedSymbol = create_procedure_symbol(theEnv, constructedType,
					      originalProcedure->get_procedure_symbol()->get_name()) ;
}
void TransformSystemsToModules::Transform()
{
  assert(procDef != NULL) ;

  // Collect all the input scalars and output scalars
  list<VariableSymbol*> ports ;
  
  SymbolTable* procSymTab = procDef->get_symbol_table() ;
  bool foundInputs = false ;
  bool foundOutputs = false ;
 
  for (int i = 0 ; i < procSymTab->get_symbol_table_object_count() ; ++i)
  {
    SymbolTableObject* nextObject = procSymTab->get_symbol_table_object(i) ;

    if (nextObject->lookup_annote_by_name("InputScalar") != NULL)
    {
      VariableSymbol* toConvert = 
	dynamic_cast<VariableSymbol*>(nextObject) ;
      assert(toConvert != NULL) ;
      LString inputName = toConvert->get_name() ;
      inputName = inputName + "_in" ;
      toConvert->set_name(inputName) ;
      ports.push_back(toConvert) ;
      foundInputs = true ;
    }
    if (nextObject->lookup_annote_by_name("OutputVariable") != NULL)
    {
      VariableSymbol* toConvert = 
	dynamic_cast<VariableSymbol*>(nextObject) ;
      assert(toConvert != NULL) ;
      LString outputName = toConvert->get_name() ;
      outputName = outputName + "_out" ;
      toConvert->set_name(outputName) ;
      ports.push_back(toConvert) ;
      foundOutputs = true ;
    }
  }
  assert(foundInputs && 
	 "Could not identify inputs.  Were they removed via optimizations?") ;
  assert(foundOutputs && 
	 "Could not identify outputs.  Were they removed via optimizations?") ;

  // Determine the bit size and add everything to a new symbol table
  int bitSize = 0 ;
  GroupSymbolTable* structTable = 
    create_group_symbol_table(theEnv,
			      procDef->get_symbol_table()) ;

  std::map<VariableSymbol*, FieldSymbol*> replacementFields ;

  bool portsRemoved = false ;
  // If this was actually a new style module, we should make sure to
  //  put these in the correct order.
  if (isModule(procDef))
  {
    // Go through the original symbol table and remove any parameter 
    //  symbols that originally existed
    SymbolTable* originalSymTab = procDef->get_symbol_table() ;
    Iter<SymbolTableObject*> originalIter = 
      originalSymTab->get_symbol_table_object_iterator() ;
    while (originalIter.is_valid())
    {
      SymbolTableObject* currentObj = originalIter.current() ;
      originalIter.next() ;
      if (dynamic_cast<ParameterSymbol*>(currentObj) != NULL)
      {
	originalSymTab->remove_symbol_table_object(currentObj) ;
      }
    }
    portsRemoved = true ;

    // Sort the variable symbols in parameter order.  This is just an 
    //  insertion sort, so it could be done faster.
    list<VariableSymbol*> sortedPorts ;
    for (int i = 0 ; i < ports.size() ; ++i)
    {
      list<VariableSymbol*>::iterator portIter = ports.begin() ;
      while (portIter != ports.end())
      {
	BrickAnnote* orderAnnote = 
	  dynamic_cast<BrickAnnote*>((*portIter)->
				     lookup_annote_by_name("ParameterOrder")) ;
	if (orderAnnote == NULL)
	{
	  ++portIter ;
	  continue ;
	}
	IntegerBrick* orderBrick = 
	  dynamic_cast<IntegerBrick*>(orderAnnote->get_brick(0)) ;
	assert(orderBrick != NULL) ;
	if (orderBrick->get_value().c_int() == i)
	{
	  sortedPorts.push_back(*portIter) ;
	  break ;
	}
	++portIter ;
      }
    }
    if (sortedPorts.size() != ports.size())
    {
      OutputWarning("Warning! Analysis detected some input scalars not in"
		    " the parameter list") ;
    }
    // Replace ports with sortedPorts
    ports = sortedPorts ;
  }

  list<VariableSymbol*>::iterator portIter = ports.begin() ;  
  while (portIter != ports.end()) 
  {
    bitSize += 
      (*portIter)->get_type()->get_base_type()->get_bit_size().c_int() ;

    LString dupeName = (*portIter)->get_name() ;

    // Create offset expression:
    IntConstant* offset = 
      create_int_constant(theEnv,
			  create_data_type(theEnv,
					   IInteger(32),
					   0),
			  IInteger(bitSize)) ;


    QualifiedType* dupeType = (*portIter)->get_type() ;
    // Deal with the case where reference types were passed in
    ReferenceType* refType = 
      dynamic_cast<ReferenceType*>(dupeType->get_base_type()) ;
    while (refType != NULL)
    {
      dupeType = dynamic_cast<QualifiedType*>(refType->get_reference_type()) ;
      assert(dupeType != NULL) ;
      refType = dynamic_cast<ReferenceType*>(dupeType->get_base_type()) ;
    }

    // Create a new variable symbol clone
    FieldSymbol* dupe = 
      create_field_symbol(theEnv,
			  dupeType,
			  offset,
			  dupeName) ;
        
    structTable->append_symbol_table_object(dupe) ;

    // Make the connection with the duplicated symbol
    replacementFields[(*portIter)] = dupe ;

    // Remove the original variable symbol from the procedure definition
    //  symbol table.
    if (!portsRemoved)
    {
      procDef->get_symbol_table()->remove_symbol_table_object(*portIter) ;
    }
    
    ++portIter ;
  }
  assert(bitSize != 0);

  StructType* moduleStruct = 
    create_struct_type(theEnv,
		       IInteger(bitSize),
		       0, // bit_alignment
		       TempName(procDef->get_procedure_symbol()->get_name()),
		       0, // is_complete
		       structTable) ;

  
  Iter<FileBlock*> fBlocks = 
    theEnv->get_file_set_block()->get_file_block_iterator() ;
  
  assert(fBlocks.is_valid()) ;
  (fBlocks.current())->get_symbol_table()->append_symbol_table_object(moduleStruct) ;
  
  // This is commented out because it is in the file state block
  //procDef->get_symbol_table()->append_symbol_table_object(moduleStruct) ;

  QualifiedType* qualifiedModuleStruct =
    create_qualified_type(theEnv,
			  moduleStruct,
			  TempName(LString("qualifiedModuleStruct"))) ;
  
  procDef->get_symbol_table()->append_symbol_table_object(qualifiedModuleStruct) ;

  // Create an instance of this type and add it to the symbol table.
  ParameterSymbol* structInstance = 
    create_parameter_symbol(theEnv,
			   qualifiedModuleStruct,
			   TempName(LString("structInstance"))) ;

  procDef->get_symbol_table()->append_symbol_table_object(structInstance) ;

  // Now, set up the procedure symbol to take the struct and return the 
  //  struct.
  assert(procDef != NULL) ;
  ProcedureSymbol* procSym = procDef->get_procedure_symbol() ;
  assert(procSym != NULL) ;
  ProcedureType* procType = procSym->get_type() ;
  assert(procType != NULL) ;
  CProcedureType* cProcType = dynamic_cast<CProcedureType*>(procType) ;
  assert(cProcType != NULL) ;

  // Instead of appending the struct argument, we need to replace all of the 
  //  arguments with the struct.

  while (cProcType->get_argument_count() > 0)
  {
    cProcType->remove_argument(0) ;
  }

  cProcType->set_result_type(moduleStruct) ;
  cProcType->append_argument(qualifiedModuleStruct) ;

  // Now go through all load variable expressions and replace them all with
  //  field symbol values if appropriate
  
  list<LoadVariableExpression*>* allLoads = 
    collect_objects<LoadVariableExpression>(procDef->get_body()) ;

  list<LoadVariableExpression*>::iterator loadIter = allLoads->begin() ;
  while (loadIter != allLoads->end())
  {
    VariableSymbol* currentVariable = (*loadIter)->get_source() ;
    if (replacementFields.find(currentVariable) != replacementFields.end())
    {
      (*loadIter)->set_source(replacementFields[currentVariable]) ;
    }
    ++loadIter ;
  }
  delete allLoads ;

  // Also replace all of the definitions with the field symbol
  list<StoreVariableStatement*>* allStoreVars = 
    collect_objects<StoreVariableStatement>(procDef->get_body()) ;
  list<StoreVariableStatement*>::iterator storeVarIter = allStoreVars->begin();
  while (storeVarIter != allStoreVars->end())
  {
    VariableSymbol* currentDest = (*storeVarIter)->get_destination() ;
    if (replacementFields.find(currentDest) != replacementFields.end())
    {
      (*storeVarIter)->set_destination(replacementFields[currentDest]) ;
    }
    ++storeVarIter ;
  }
  delete allStoreVars ;

  list<SymbolAddressExpression*>* allSymAddr = 
    collect_objects<SymbolAddressExpression>(procDef->get_body()) ;
  list<SymbolAddressExpression*>::iterator symAddrIter = allSymAddr->begin() ;
  while (symAddrIter != allSymAddr->end())
  {
    VariableSymbol* currentVar = 
      dynamic_cast<VariableSymbol*>((*symAddrIter)->get_addressed_symbol()) ;
    if (currentVar != NULL &&
	replacementFields.find(currentVar) != replacementFields.end())
    {
      (*symAddrIter)->set_addressed_symbol(replacementFields[currentVar]) ;
    }
    ++symAddrIter ;
  }
  delete allSymAddr ;
  // One final for bool selects
  list<CallStatement*>* allCalls = 
    collect_objects<CallStatement>(procDef->get_body()) ;
  list<CallStatement*>::iterator callIter = allCalls->begin() ;
  while(callIter != allCalls->end())
  {
    VariableSymbol* currentVar = (*callIter)->get_destination() ;
    if (currentVar != NULL &&
	replacementFields.find(currentVar) != replacementFields.end())
    {
      (*callIter)->set_destination(replacementFields[currentVar]) ;
    }
    ++callIter ;
  }
  delete allCalls ;
}
Walker::ApplyStatus fle_c_for_statement_walker::operator () (SuifObject *x) {
    SuifEnv *env = get_env();
    CForStatement *c_for_stmt = to<CForStatement>(x);

    //    if(!is_stmt_within_begin_end_hw_marks(c_for_stmt))
    //    return Walker::Continue;

    Statement *body = c_for_stmt->get_body();

    Iter<CForStatement> iter = object_iterator<CForStatement>(body); 
    if(iter.is_valid())
       return Walker::Continue;

    BrickAnnote* c_for_info = to<BrickAnnote>(c_for_stmt->lookup_annote_by_name("c_for_info"));
    String c_for_loop_counter_name = (to<StringBrick>(c_for_info->get_brick(1)))->get_value();
    int c_for_loop_step_size = (to<IntegerBrick>(c_for_info->get_brick(4)))->get_value().c_int();

    if(body){

       list<StoreStatement*>* stores_list = collect_objects<StoreStatement>(body);
           
       if(stores_list->size() <= 0){
          delete stores_list;
          return Walker::Continue;
       }

       ProcedureDefinition* proc_def = get_procedure_definition(c_for_stmt);

       VariableSymbol *c_for_stmt_index_var = get_c_for_basic_induction_variable(c_for_stmt);
       Expression *c_for_stmt_lower_bound_expr = get_c_for_lower_bound_expr(c_for_stmt);

       BrickAnnote *ba = to<BrickAnnote>(c_for_stmt->lookup_annote_by_name("end_of_mem_reads"));
       SuifObjectBrick *sob = to<SuifObjectBrick>(ba->get_brick(0));
       MarkStatement *end_of_mem_reads = to<MarkStatement>(sob->get_object());

       ba = to<BrickAnnote>(c_for_stmt->lookup_annote_by_name("beg_of_mem_writes"));
       sob = to<SuifObjectBrick>(ba->get_brick(0));
       MarkStatement *beg_of_mem_writes = to<MarkStatement>(sob->get_object());
        
       list<VariableSymbol*>* array_names_in_load_exprs = collect_array_name_symbols_used_in_loads(body);
       suif_map<LoadExpression*, ArrayInfo*>* load_expr_array_info_map =  new suif_map<LoadExpression*, ArrayInfo*>;

       list<LoadExpression*>* loads_list = collect_objects<LoadExpression>(body); 
       for(list<LoadExpression*>::iterator iter2 = loads_list->begin(); 
           iter2 != loads_list->end(); iter2++) {
	
           LoadExpression *load_expr = *iter2;
	   StoreVariableStatement *load_parent = to<StoreVariableStatement>(get_expression_owner(load_expr)); 
	   if(!is_a<ArrayReferenceExpression>(load_expr->get_source_address()))
	      continue; 
           ArrayReferenceExpression *source_address_expr = to<ArrayReferenceExpression>(load_expr->get_source_address());
	   
	   BrickAnnote *source_address_info_annote = to<BrickAnnote>(source_address_expr->lookup_annote_by_name("array_ref_info"));
	   sob = to<SuifObjectBrick>(source_address_info_annote->get_brick(0));
	   ArrayInfo *source_address_info = (ArrayInfo*)(sob->get_object());
	
	   load_expr_array_info_map->enter_value(load_expr, source_address_info);
       }
       delete loads_list;

       StatementList* before_beg_of_mem_writes = create_statement_list(env);
       StatementList* after_end_of_mem_reads = create_statement_list(env);
       StatementList* load_inits = create_statement_list(env);
       list<Statement*>* to_be_removed = new list<Statement*>;

       for(list<StoreStatement*>::iterator iter = stores_list->begin(); 
           iter != stores_list->end(); iter++) {

	   StoreStatement *store_stmt = *iter;
	   if(!is_a<ArrayReferenceExpression>(store_stmt->get_destination_address()))
	      continue; 
           ArrayReferenceExpression *destination_address_expr = to<ArrayReferenceExpression>(store_stmt->get_destination_address());

	   BrickAnnote *destination_address_info_annote = to<BrickAnnote>(destination_address_expr->lookup_annote_by_name("array_ref_info"));
  	   SuifObjectBrick *sob = to<SuifObjectBrick>(destination_address_info_annote->get_brick(0));
	   ArrayInfo *destination_address_info = (ArrayInfo*)(sob->get_object());

	   VariableSymbol *array_sym = get_array_name_symbol(destination_address_expr);
           Type *t = get_base_type(destination_address_expr->get_result_type());
           VariableSymbol *feedback_var = NULL;

           for(suif_map<LoadExpression*, ArrayInfo*>::iterator iter2 = load_expr_array_info_map->begin(); 
               iter2 != load_expr_array_info_map->end(); ) {

	       ArrayInfo *source_address_info = (*iter2).second;

      	       if(destination_address_info->get_array_symbol_name() != source_address_info->get_array_symbol_name()){
		  iter2++;
	          continue;
	       }
	
	       if(is_a_feedback_pair(destination_address_info, source_address_info, c_for_loop_counter_name, c_for_loop_step_size)){
  
		  if(!feedback_var){
		
                     feedback_var = new_anonymous_variable(env, find_scope(proc_def->get_body()), retrieve_qualified_type(to<DataType>(t)));
		     name_variable(feedback_var);
		     
                     StoreVariableStatement *feedback_var_set = create_store_variable_statement(env, feedback_var,
							to<LoadVariableExpression>(deep_suif_clone(store_stmt->get_value())));

		     before_beg_of_mem_writes->append_statement(feedback_var_set);
		  }

                  LoadExpression *load_expr = (*iter2).first;
	          StoreVariableStatement *load_parent = to<StoreVariableStatement>(get_expression_owner(load_expr)); 

                  StoreVariableStatement *feedback_var_get = create_store_variable_statement(env, load_parent->get_destination(), 
							create_load_variable_expression(env, to<DataType>(t), feedback_var));
		
		  after_end_of_mem_reads->append_statement(feedback_var_get);

		  suif_map<LoadExpression*, ArrayInfo*>::iterator iter_temp = iter2;
		  iter2++;
		  load_expr_array_info_map->erase(iter_temp);

		  to_be_removed->push_back(load_parent);
		  load_parent->set_parent(0);

		  load_parent->set_destination(feedback_var);
                  load_inits->append_statement(load_parent);

	       }else iter2++;
           }
       }

       int i = 0;
       StatementList* the_list = to<StatementList>(body);
       while(i < the_list->get_statement_count()){
	    if(is_in_list(the_list->get_statement(i), to_be_removed))
	       the_list->remove_statement(i);
	    else i++;	 
       }

       fle_load_variable_expression_walker walker(env, c_for_stmt_index_var, c_for_stmt_lower_bound_expr);
       load_inits->walk(walker);

       insert_statement_before(beg_of_mem_writes, before_beg_of_mem_writes);
       insert_statement_after(end_of_mem_reads, after_end_of_mem_reads);
       insert_statement_before(c_for_stmt, load_inits);

       delete stores_list;
       delete array_names_in_load_exprs;
       delete load_expr_array_info_map;
       delete to_be_removed;
    }

    return Walker::Continue;
}
void CopyPropagationPass2::ProcessPossibleCopy(StoreVariableStatement* c)
{
  assert(c != NULL) ;
  // If this isn't a straight copy, just return
  LoadVariableExpression* replacement = 
    dynamic_cast<LoadVariableExpression*>(c->get_value()) ;
  if (replacement == NULL)
  {
    return ;
  }

  // If the variables are different types, don't propagate this away 
  //  (it is a cast)
  DataType* destType = c->get_destination()->get_type()->get_base_type() ;
  DataType* sourceType = replacement->get_source()->get_type()->get_base_type();
  if (!EquivalentTypes(destType, sourceType))
  {
    return ;
  }
     
  // Find all the reached uses
  BrickAnnote* reachedUses = 
    to<BrickAnnote>(c->lookup_annote_by_name("reached_uses")) ;

  assert(reachedUses != NULL) ;

  // Just in case we have no reached uses, we don't want to do 
  //  dead code elimination in this pass as well...
  bool removable = false ;

  Iter<SuifBrick*> useIter = reachedUses->get_brick_iterator() ;

  // First verify that we are the only definition for all of our uses.
  //  If we aren't then we can't make the replacement
  while(useIter.is_valid())
  {
    SuifObjectBrick* sob = to<SuifObjectBrick>(useIter.current()) ;
    assert (sob != NULL) ;
    LoadVariableExpression* nextLoad = 
      dynamic_cast<LoadVariableExpression*>(sob->get_object()) ;
    assert(nextLoad != NULL) ;
    if (IsOnlyDefinition(c, nextLoad) == false)
    {
      return ;
    }
    useIter.next() ;
  }

  // We also need to make sure that for each reached use, the copy is
  //  not redefined.  We do this by checking to make sure all of the
  //  definitions associated with it in the kill map are identical.
  //  This is a little conservative, but will make sure that no incorrect
  //  code is created.


  // Get the bit vector associated with all the reaching definitions
  //  coming into this statement
  BrickAnnote* inStatements = 
    dynamic_cast<BrickAnnote*>(c->lookup_annote_by_name("in_stmts")) ;
  assert(inStatements != NULL) ;
  SuifBrick* inBrick = inStatements->get_brick(0) ;
  assert(inBrick != NULL) ;
  SuifObjectBrick* inSOB = dynamic_cast<SuifObjectBrick*>(inBrick) ;
  assert(inSOB != NULL) ;
  SuifObject* inObj = inSOB->get_object() ;
  assert(inObj != NULL) ;
  BitVector2* inBits = dynamic_cast<BitVector2*>(inObj) ;
  assert(inBits != NULL) ;

  VariableSymbol* replacementVariable = replacement->get_source() ;
  assert(replacementVariable != NULL) ;

  list<std::pair<Statement*, int> >* definitions =killMap[replacementVariable];
  assert(definitions != NULL) ;

  list<bool> activeDefinitions ;
  list<std::pair<Statement*, int> >::iterator defIter = definitions->begin() ;
  while (defIter != definitions->end())
  {
    activeDefinitions.push_back(inBits->isMarked((*defIter).second)) ;
    ++defIter ;
  }

  useIter = reachedUses->get_brick_iterator() ;
  while (useIter.is_valid())
  {
    SuifObjectBrick* sob = to<SuifObjectBrick>(useIter.current()) ;
    assert(sob != NULL) ;
    LoadVariableExpression* nextLoad = 
      dynamic_cast<LoadVariableExpression*>(sob->get_object()) ;
    assert(nextLoad != NULL) ;
    SuifObject* loadParent = nextLoad->get_parent() ;
    while (dynamic_cast<Statement*>(loadParent) == NULL && loadParent != NULL)
    {
      loadParent = loadParent->get_parent() ;
    }
    assert(loadParent != NULL) ;
    Statement* parentStatement = dynamic_cast<Statement*>(loadParent) ;
    assert(parentStatement != NULL) ;
    BrickAnnote* parentInAnnote = dynamic_cast<BrickAnnote*>
      (parentStatement->lookup_annote_by_name("in_stmts")) ;
    assert(parentInAnnote != NULL) ;
    SuifBrick* parentInBrick = parentInAnnote->get_brick(0) ;
    assert(parentInBrick != NULL) ;
    SuifObjectBrick* parentInSOB = 
      dynamic_cast<SuifObjectBrick*>(parentInBrick) ;
    assert(parentInSOB != NULL) ;
    SuifObject* parentInObj = parentInSOB->get_object() ;
    assert(parentInObj != NULL) ;
    BitVector2* parentInBits = dynamic_cast<BitVector2*>(parentInObj) ;
    assert(parentInBits != NULL) ;

    defIter = definitions->begin() ;
    list<bool>::iterator activeIter = activeDefinitions.begin() ;
    while (defIter != definitions->end())
    {
      if ((*activeIter) != parentInBits->isMarked((*defIter).second))
      {
	// They are different, so don't do the replacement.
	return ;
      }
      ++activeIter ;
      ++defIter ;
    }

    useIter.next() ; 
  }
  
  // Now go through each reached use and replace it with the copy.
  //  Each reached use should be a load variable expression.
  //  We also have to deal with any feedback variables
  useIter = reachedUses->get_brick_iterator() ;
  while (useIter.is_valid())
  {
    SuifObjectBrick* sob = to<SuifObjectBrick>(useIter.current()) ;
    assert(sob != NULL) ;
    LoadVariableExpression* nextLoad = 
      dynamic_cast<LoadVariableExpression*>(sob->get_object()) ;
    assert(nextLoad != NULL) ;

    // Keep track of if we need to handle feedback variables
    HandleFeedbackVariables(nextLoad, replacement->get_source()) ;
    
    nextLoad->set_source(replacement->get_source()) ;

    removable = true ;

    useIter.next() ;
  }

  if (removable)
  {
    toBeRemoved.push_back(c) ;
  }  

}