bool IfConversionPass2::ConvertArrayStoreIf(IfStatement* toConvert)
{
  Statement* thenPart = Denormalize(toConvert->get_then_part()) ;
  Statement* elsePart = Denormalize(toConvert->get_else_part()) ;
  StoreStatement* thenStore = dynamic_cast<StoreStatement*>(thenPart) ;
  StoreStatement* elseStore = dynamic_cast<StoreStatement*>(elsePart) ;
  
  assert(thenStore != NULL) ;
  assert(elseStore != NULL) ;

  ArrayReferenceExpression* thenRef = 
    dynamic_cast<ArrayReferenceExpression*>(thenStore->get_destination_address()) ;
  ArrayReferenceExpression* elseRef = 
    dynamic_cast<ArrayReferenceExpression*>(elseStore->get_destination_address()) ;

  assert(thenRef != NULL) ;
  assert(elseRef != NULL) ;

  // Verify that these array references are to the same location.
  if (!EquivalentExpressions(thenRef, elseRef))
  {
    return false ;
  }

  // This will hopefully be scalar replaced later, but for now we just need
  //  to do something...
  //  What I need is the qualified element type of the array.  
  QualifiedType* qualType = create_qualified_type(theEnv,
						  thenRef->get_result_type()) ;

  StoreStatement* replacement = CreateBoolCall(thenRef) ;

  // Append the arguments to the call expression
  CallExpression* callExpr = 
    dynamic_cast<CallExpression*>(replacement->get_value()) ;
  assert(callExpr != NULL) ;

  Expression* thenStoreValue = thenStore->get_value() ;
  thenStore->set_value(NULL) ;
  callExpr->append_argument(thenStoreValue) ;

  Expression* elseStoreValue = elseStore->get_value() ;
  elseStore->set_value(NULL) ;
  callExpr->append_argument(elseStoreValue) ;

  Expression* condition = toConvert->get_condition() ;
  toConvert->set_condition(NULL) ;
  callExpr->append_argument(condition) ;

  // Replace the if
  toConvert->get_parent()->replace(toConvert, replacement) ;
  return true ;
}
Example #2
0
static
String handle_static_array_reference_expression(CPrintStyleModule *state,
					      const SuifObject *obj)
{
  ArrayReferenceExpression *expr =
    to<ArrayReferenceExpression>(obj);

  String base = state->print_to_string(expr->get_base_array_address());
  String idx = state->print_to_string(expr->get_index());

  return(String("&(") + base + "[" + idx + "])");
}
Walker::ApplyStatus pp_array_reference_expression_walker::operator () (SuifObject *x) {

	SuifEnv *env = get_env();
	ArrayReferenceExpression *array_ref_expr = to<ArrayReferenceExpression>(x);

	if(array_ref_expr->lookup_annote_by_name("array_ref_info"))
	   delete (array_ref_expr->remove_annote_by_name("array_ref_info"));
	   
	BrickAnnote *array_ref_info_annote = create_brick_annote(env, "array_ref_info"); 
	// Removed by Jason to make my life a little easier
	// Reinstated to get systolic array working again...
	array_ref_expr->append_annote(array_ref_info_annote);

	// Also, create an annote to help me later...
	BrickAnnote* array_ref_info_annote2 = create_brick_annote(env,
								  "array_ref_info") ;

	// Added by Jason to make my life a little easier
	//dynamic_cast<SymbolAddressExpression*>(array_ref_expr->get_base_array_address())->get_addressed_symbol()->append_annote(array_ref_info_annote) ;

	// Modified by Jason on 3/24/2009
	//  The previous version did not work with multidimensional arrays
	ArrayReferenceExpression* currentCast = array_ref_expr ;
	while(dynamic_cast<SymbolAddressExpression*>(currentCast->get_base_array_address()) == NULL)
	  {
	    currentCast = dynamic_cast<ArrayReferenceExpression*>(currentCast->get_base_array_address()) ;
	    assert(currentCast != NULL) ;
	  }
	dynamic_cast<SymbolAddressExpression*>(currentCast->get_base_array_address())->get_addressed_symbol()->append_annote(array_ref_info_annote2) ;	

	// Unfortunately, this causes problems in the strip annotes phase
	//  so I need to change that as well.

	ArrayInfo *array_ref_info = new ArrayInfo();

	Expression *base_array_address = array_ref_expr; 
	Expression *index = NULL;

	int dimension = 0;

	do{

	   index = (to<ArrayReferenceExpression>(base_array_address))->get_index();
	   String var = get_var(index);
	   int a = get_a(index);
	   int c = get_c(index);

	   array_ref_info->push_front_index_var_name(var);
	   array_ref_info->push_front_a(a);
	   array_ref_info->push_front_c(c);
	   dimension++;

	   base_array_address = (to<ArrayReferenceExpression>(base_array_address))->get_base_array_address();

	}while(is_a<ArrayReferenceExpression>(base_array_address));
	
        SymbolAddressExpression *array_sym_expr = to<SymbolAddressExpression>(base_array_address);
        VariableSymbol *array_sym = to<VariableSymbol>(array_sym_expr->get_addressed_symbol());

	array_ref_info->set_array_symbol_name(array_sym->get_name());
	array_ref_info->set_dimension(dimension);

	array_ref_info_annote->append_brick(create_suif_object_brick(env, array_ref_info));

	// Added for my benefit
	array_ref_info_annote2->append_brick(create_suif_object_brick(env, array_ref_info)) ;

    	return Walker::Truncate;
}
void EliminateArrayConvertsPass::do_procedure_definition(ProcedureDefinition* proc_def){
    suif_hash_map<ParameterSymbol*, Type*> params;
    TypeBuilder *tb = (TypeBuilder*)
         get_suif_env()->get_object_factory(TypeBuilder::get_class_name());

    // collect all procedure parameters of pointer type into params list
    for(Iter<ParameterSymbol*> iter = proc_def->get_formal_parameter_iterator();
        iter.is_valid(); iter.next())
    {
        ParameterSymbol* par_sym = iter.current();
        Type* par_type = tb->unqualify_type(par_sym->get_type());

        if(is_kind_of<PointerType>(par_type)){
            // put NULLs into the map at first,
            // they will later be overwritten
            params[par_sym] = NULL;
        }
    }
    if(params.size()==0) return;    // nothing to do
    
    // walk thru all AREs and look for arrays that are in the param list
    {for(Iter<ArrayReferenceExpression> iter =
        object_iterator<ArrayReferenceExpression>(proc_def);
            iter.is_valid(); iter.next())
        {
            ArrayReferenceExpression* are = &iter.current();
            if(is_kind_of<UnaryExpression>(are->get_base_array_address())){
                UnaryExpression* ue = to<UnaryExpression>(are->get_base_array_address());
                if(ue->get_opcode() == k_convert){
                    if(is_kind_of<LoadVariableExpression>(ue->get_source())){
                        LoadVariableExpression* lve = 
                            to<LoadVariableExpression>(ue->get_source());
                        VariableSymbol* array = lve->get_source();
            
                        for(suif_hash_map<ParameterSymbol*, Type*>::iterator iter = params.begin();
                            iter!=params.end();iter++)
                        {
                            ParameterSymbol* par_sym = (*iter).first;
                            if(par_sym == array){
                                // match!
                                Type* array_type;
                                suif_hash_map<ParameterSymbol*, Type*>::iterator iter =
                                    params.find(par_sym);
                                
                                if(iter==params.end() || (*iter).second==NULL){
                                    //array_type = to<PointerType>(ue->get_result_type())->get_reference_type();
                                    array_type = tb->get_qualified_type(ue->get_result_type());
                                    params[par_sym] = array_type;
                                    //printf("%s has type ",par_sym->get_name().c_str());
                                    //array_type->print_to_default();
                                }else{
                                    array_type = params[par_sym].second;
                                    suif_assert(is_kind_of<QualifiedType>(array_type));
                                }

                                array->replace(array->get_type(), array_type);
                                remove_suif_object(ue);
                                remove_suif_object(lve);
                                lve->replace(lve->get_result_type(), tb->unqualify_type(array_type));
                                // put the LoadVar directly under ARE
                                are->set_base_array_address(lve);
                                //are->print_to_default();
                            }
                        }
                    } else {
                        suif_warning(ue->get_source(),
                            ("Expecting a LoadVariableExpression here"));
                    }
                } else {
                    suif_warning(ue, ("Disallow converts in AREs for "
                            "things other than procedure parameters"));
                }
            }
        }
    }
}
void One2MultiArrayExpressionPass::do_procedure_definition(ProcedureDefinition* proc_def)
{
    bool kill_all = !(_preserve_one_dim->is_set());
    // access all array type declarations and create corresponding multi array types
    SuifEnv* suif_env = proc_def->get_suif_env();
    TypeBuilder* tb = (TypeBuilder*)suif_env->
        get_object_factory(TypeBuilder::get_class_name());
    (void) tb; // avoid warning
#ifdef CONVERT_TYPES
    for (Iter<ArrayType> at_iter = object_iterator<ArrayType>(proc_def);
        at_iter.is_valid();at_iter.next())
    {
        MultiDimArrayType* multi_type = 
            converter->array_type2multi_array_type(&at_iter.current());
	}
#endif //CONVERT_TYPES

    // collect tops of array access chains into this list
    list<ArrayReferenceExpression*> ref_exprs;
    for (Iter<ArrayReferenceExpression> are_iter =
		object_iterator<ArrayReferenceExpression>(proc_def);
         are_iter.is_valid(); are_iter.next())
    {
        // itself an array and parent is *not* an array
        ArrayReferenceExpression* are = &are_iter.current();
        if((kill_all || is_kind_of<ArrayReferenceExpression>(are->get_base_array_address())) &&
           !is_kind_of<ArrayReferenceExpression>(are->get_parent()))
        {
            //printf("%p \t", are);are->print_to_default();
            ref_exprs.push_back(are);
	    }
    }

    // for top all expressions, convert them to multi-exprs
    for(list<ArrayReferenceExpression*>::iterator ref_iter = ref_exprs.begin();
        ref_iter != ref_exprs.end(); ref_iter++)
    {
        ArrayReferenceExpression* top_array = *ref_iter;
        converter->convert_array_expr2multi_array_expr(top_array);
    }
#ifdef CONVERT_TYPES    
    // replace the types of all array variables
    for (Iter<VariableSymbol> iter = object_iterator<VariableSymbol>(proc_def);
            iter.is_valid();iter.next())
    {
        VariableSymbol* vd = &iter.current();
        DataType *vtype = tb->unqualify_data_type(vd->get_type());
        if (is_kind_of<ArrayType>(vtype)) {
            MultiDimArrayType* multi_type =
                    converter->array_type2multi_array_type(to<ArrayType>(vtype));
            vd->replace(vd->get_type(), tb->get_qualified_type(multi_type));
        }
    }

    // remove the remaining one-dim array types
    converter->remove_all_one_dim_array_types();
#endif //CONVERT_TYPES
    // make sure no traces of single-dim arrays are left
    if(kill_all){
        {for(Iter<ArrayReferenceExpression> iter =
            object_iterator<ArrayReferenceExpression>(proc_def);
            iter.is_valid(); iter.next())
            {
                // ArrayReferenceExpression* are = &iter.current();
                //are->print_to_default(); printf("at %p \t", are);
                suif_assert_message(false, ("ARE not eliminated"));
            }
        }
#ifdef CONVERT_TYPES
        {for(Iter<ArrayType> iter =
            object_iterator<ArrayType>(proc_def);
            iter.is_valid(); iter.next())
        {suif_assert_message(false, ("ArrayType not eliminated"));}}
#endif
    }
}
/**
    Convert ArrayReferenceExpression \a top_array to a 
    MultiDimArrayExpression.
*/
void OneDimArrayConverter::
convert_array_expr2multi_array_expr(ArrayReferenceExpression* top_array){
    Expression* expr = top_array;
    unsigned int i = 0;

    suif_vector<Expression*> lower_bounds;
    suif_vector<Expression*> upper_bounds;
    list<Expression*> indices;
    IInteger bit_size, bit_alignment;
    suif_vector<ArrayReferenceExpression *> exprs;

    do{
        ArrayReferenceExpression* are = to<ArrayReferenceExpression>(expr);
        expr = are->get_base_array_address();
        exprs.push_back(are);
	} while(is_kind_of<ArrayReferenceExpression>(expr));

    // collect bounds and indeces
    for (unsigned int exp_ind = 0; exp_ind < exprs.size();exp_ind++)
    {
        ArrayReferenceExpression* are = exprs[exp_ind];
        DataType* type = are->get_base_array_address()->get_result_type();
        ArrayType* array_type;

		if(is_kind_of<ArrayType>(type)){
			array_type = to<ArrayType>(type);
		}else{
			array_type = to<ArrayType>(
				unwrap_ptr_ref_type(type)->get_base_type());
		}
        
        bit_size = array_type->get_element_type()->
                get_base_type()->get_bit_size();
        bit_alignment = array_type->get_element_type()->
                get_base_type()->get_bit_alignment();

        // What happens to ArrayType?? Does it become garbage?
        suif_assert(array_type->get_lower_bound());
        suif_assert(array_type->get_upper_bound());

        // clone bounds and add to the lists
        lower_bounds.push_back(array_type->get_lower_bound());
        upper_bounds.push_back(array_type->get_upper_bound());
        // save the index
        Expression* index = are->get_index();
        remove_suif_object(index); index->set_parent(NULL);
        indices.push_back(index);

        suif_assert(upper_bounds[i]);
        suif_assert(lower_bounds[i]);
        suif_assert(indices[i]);

        i++;
	}

    // Build the offset for the expression. We have to traverse upwards to do this
    Expression *top_expr_base = exprs[exprs.size()-1]->get_base_array_address();
    
	DataType* top_expr_base_type = top_expr_base->get_result_type();
	ArrayType* top_array_type;
	if(is_kind_of<ArrayType>(top_expr_base_type)){
		top_array_type = to<ArrayType>(top_expr_base_type);
	}else{
		top_array_type = to<ArrayType>(tb->unqualify_data_type(unwrap_ptr_ref_type(
			top_expr_base_type)));
	}
    
	Expression* inc    = create_int_constant(suif_env, 1);
    Expression* offset = create_int_constant(suif_env, 0);
    suif_vector<Expression *> elements;

    for (unsigned int ind = 0;ind < lower_bounds.size(); ind ++)
    {
        Expression *lower = lower_bounds[ind];
        Expression *upper = upper_bounds[ind];

        offset = 
            build_dyadic_expression(k_add, 
                offset,
                build_dyadic_expression(
                    k_multiply, 
                    deep_suif_clone(inc),
                    deep_suif_clone(lower)));
        
        Expression *element =
                    build_dyadic_expression(k_add, 
                        build_dyadic_expression(k_subtract,
                            deep_suif_clone(upper), 
                            deep_suif_clone(lower)),
                        create_int_constant(suif_env,1));

        inc = build_dyadic_expression(k_multiply, 
            inc, 
            deep_suif_clone(element));

	    elements.push_back(element);
    }
    // Now, inc and offset are ready

    // retrieve the multi-type
    MultiDimArrayType* multi_type;
	suif_map<ArrayType*, MultiDimArrayType*>::iterator type_iter =
	    type_map->find(top_array_type);
#ifdef CONVERT_TYPES
    suif_assert_message((type_iter != type_map->end()),
        ("Array type never translated"));
#else
    if(type_iter == type_map->end()){
        multi_type = array_type2multi_array_type(top_array_type);
    }else
#endif //CONVERT_TYPES
    multi_type = (*type_iter).second;

    remove_suif_object(top_expr_base);

    // add a convert to the necessary type
    top_expr_base = create_unary_expression(suif_env, 
            tb->get_pointer_type(multi_type), 
            k_convert, top_expr_base);
    //top_expr_base->print_to_default();

    // construct the expression to be returned 
    MultiDimArrayExpression* mae =
        create_multi_dim_array_expression(suif_env,
            top_array->get_result_type(), 
            top_expr_base, 
            offset);

    // now when we have the expression, set the indices
    for (list<Expression*>::iterator ind_iter = indices.begin();
        ind_iter!=indices.end(); ind_iter++)
    {
        Expression* index = *ind_iter;
        //printf("%p \t", index);index->print_to_default();
        mae->append_index(index);
    }

    for (suif_vector<Expression *>::iterator eiter = elements.begin();
        eiter != elements.end(); eiter ++)
    {
        Expression* element = *eiter;
        mae->append_element(element);
    }

    replace_expression(top_array, mae);
}
void ConstantArrayPropagationPass::ReplaceLoad(LoadExpression* load,
					       ArrayReferenceExpression* ref,
					       VariableSymbol* var,
					       ValueBlock* topBlock) 
{
  list<IntConstant*> allDimensions ;
  
  IntConstant* nextIndex = dynamic_cast<IntConstant*>(ref->get_index()) ;
  if (nextIndex == NULL)
  {   
    OutputWarning("Trying to access a constant array with a nonconstant index!") ;
    delete var->remove_annote_by_name("ConstPropArray") ;
    //    assert(0) ;
    return ;
  }
  allDimensions.push_front(nextIndex) ;
  
  ArrayReferenceExpression* nextDimension = 
    dynamic_cast<ArrayReferenceExpression*>(ref->get_base_array_address()) ;
  while (nextDimension != NULL)
  {
    nextIndex = dynamic_cast<IntConstant*>(nextDimension->get_index()) ;
    assert(nextIndex != NULL) ;
    allDimensions.push_front(nextIndex) ;
    nextDimension = dynamic_cast<ArrayReferenceExpression*>(nextDimension->get_base_array_address()) ;
  }

  ValueBlock* currentBlock = topBlock ;
  
  list<IntConstant*>::iterator dimIter = allDimensions.begin() ;

  for (int i = 0 ; i < allDimensions.size() ; ++i)
  {
    MultiValueBlock* multiBlock = dynamic_cast<MultiValueBlock*>(currentBlock);
    assert(multiBlock != NULL) ;
    currentBlock = multiBlock->lookup_sub_block((*dimIter)->get_value()) ;
    ++dimIter ;
  }
  
  ExpressionValueBlock* finalBlock = 
    dynamic_cast<ExpressionValueBlock*>(currentBlock) ;
  assert(finalBlock != NULL && 
	 "Attempted to use an uninitialized constant value!") ;
  Expression* replacementValue = finalBlock->get_expression() ;
  if (dynamic_cast<IntConstant*>(replacementValue) != NULL)
  {
    IntConstant* constInt = 
      dynamic_cast<IntConstant*>(replacementValue) ;
    IntConstant* replacement =
      create_int_constant(theEnv, 
			  constInt->get_result_type(),
			  constInt->get_value()) ;
    load->get_parent()->replace(load, replacement) ;
    delete load ;
  }
  else if (dynamic_cast<FloatConstant*>(replacementValue) != NULL)
  {
    FloatConstant* constFloat = 
      dynamic_cast<FloatConstant*>(replacementValue) ;
    FloatConstant* replacement = 
      create_float_constant(theEnv,
			    constFloat->get_result_type(),
			    constFloat->get_value()) ;
    load->get_parent()->replace(load, replacement) ;
    delete load ;
  }
  else
  {
    assert(0 && "Unknown constant") ;
  }

}