70 #include "config_HAVE_PRAGMA_BUILT.hpp" 96 unsigned int _function_id,
97 const DesignFlowManagerConstRef _design_flow_manager)
99 TM(_AppM->get_tree_manager()),
111 switch(relationship_type)
115 relationships.insert(std::make_pair(CHECK_SYSTEM_TYPE,
SAME_FUNCTION));
116 relationships.insert(std::make_pair(IR_LOWERING,
SAME_FUNCTION));
118 relationships.insert(std::make_pair(FIX_STRUCTS_PASSED_BY_VALUE,
SAME_FUNCTION));
119 relationships.insert(std::make_pair(USE_COUNTING,
SAME_FUNCTION));
135 return relationships;
141 const auto fd = GetPointer<function_decl>(node);
147 bool changed =
false;
148 std::list<std::pair<tree_nodeRef, unsigned int>> to_be_lowered_memset;
153 unsigned int max_loop_id = 0;
155 const auto sl = GetPointer<statement_list>(
GET_NODE(fd->body));
157 for(
const auto& bb :
sl->list_of_bloc)
163 max_loop_id =
std::max(max_loop_id, bb.second->loop_id);
165 const std::list<tree_nodeRef> const_sl = bb.second->CGetStmtList();
166 for(
const auto& stmt : const_sl)
169 if(tn->get_kind() == gimple_assign_K)
171 const auto gm = GetPointer<gimple_assign>(tn);
180 bool is_a_vector_bitfield =
false;
181 if(op1->get_kind() == bit_field_ref_K)
183 const auto bfr = GetPointer<bit_field_ref>(op1);
186 is_a_vector_bitfield =
true;
190 bool load_candidate = (op1->get_kind() == bit_field_ref_K && !is_a_vector_bitfield) ||
191 op1->get_kind() == component_ref_K || op1->get_kind() == indirect_ref_K ||
192 op1->get_kind() == misaligned_indirect_ref_K || op1->get_kind() == mem_ref_K ||
193 op1->get_kind() == array_ref_K || op1->get_kind() == target_mem_ref_K ||
194 op1->get_kind() == target_mem_ref461_K;
195 if(op1->get_kind() == realpart_expr_K || op1->get_kind() == imagpart_expr_K)
197 const auto code1 =
GET_NODE(GetPointer<unary_expr>(op1)->op)->get_kind();
198 if((code1 == bit_field_ref_K && !is_a_vector_bitfield) || code1 == component_ref_K ||
199 code1 == indirect_ref_K || code1 == bit_field_ref_K || code1 == misaligned_indirect_ref_K ||
200 code1 == mem_ref_K || code1 == array_ref_K || code1 == target_mem_ref_K ||
201 code1 == target_mem_ref461_K)
203 load_candidate =
true;
205 if(code1 == var_decl_K)
207 load_candidate =
true;
210 bool store_candidate = op0->get_kind() == bit_field_ref_K || op0->get_kind() == component_ref_K ||
211 op0->get_kind() == indirect_ref_K || op0->get_kind() == misaligned_indirect_ref_K ||
212 op0->get_kind() == mem_ref_K || op0->get_kind() == array_ref_K ||
213 op0->get_kind() == target_mem_ref_K || op0->get_kind() == target_mem_ref461_K;
214 if(op0->get_kind() == realpart_expr_K || op0->get_kind() == imagpart_expr_K)
216 const auto code0 =
GET_NODE(GetPointer<unary_expr>(op0)->op)->get_kind();
217 if(code0 == component_ref_K || code0 == indirect_ref_K || code0 == bit_field_ref_K ||
218 code0 == misaligned_indirect_ref_K || code0 == mem_ref_K || code0 == array_ref_K ||
219 code0 == target_mem_ref_K || code0 == target_mem_ref461_K)
221 store_candidate =
true;
223 if(code0 == var_decl_K)
225 store_candidate =
true;
228 if(!gm->clobber && !gm->init_assignment && op0_type && op1_type && op1->get_kind() != insertvalue_expr_K &&
229 op1->get_kind() != extractvalue_expr_K &&
231 GET_CONST_NODE(op1_type)->get_kind() == record_type_K && op1->get_kind() != view_convert_expr_K) ||
233 GET_CONST_NODE(op1_type)->get_kind() == union_type_K && op1->get_kind() != view_convert_expr_K) ||
234 (
GET_CONST_NODE(op0_type)->get_kind() == array_type_K) || (store_candidate && load_candidate)))
237 const auto mr = GetPointer<mem_ref>(op0);
238 THROW_ASSERT(mr,
"unexpected condition " + gm->ToString());
241 const auto dst_ptr_t = GetPointer<const pointer_type>(
GET_CONST_NODE(dst_type));
246 if(op1->get_kind() == constructor_K && GetPointer<constructor>(op1) &&
247 GetPointer<constructor>(op1)->list_of_idx_valu.size() == 0)
250 bool do_lowering = var !=
nullptr;
258 const auto element_type_kind =
GET_CONST_NODE(element_type)->get_kind();
259 if(!(element_type_kind == boolean_type_K || element_type_kind == CharType_K ||
260 element_type_kind == enumeral_type_K || element_type_kind == integer_type_K ||
261 element_type_kind == pointer_type_K or element_type_kind == record_type_K))
265 element_type_kind == array_type_K || element_type_kind == nullptr_type_K ||
266 element_type_kind == type_pack_expansion_K || element_type_kind == real_type_K ||
267 element_type_kind == complex_type_K or element_type_kind == function_type_K ||
268 element_type_kind == lang_type_K || element_type_kind == method_type_K ||
269 element_type_kind == offset_type_K || element_type_kind == qual_union_type_K or
270 element_type_kind == record_type_K || element_type_kind == reference_type_K ||
271 element_type_kind == set_type_K || element_type_kind == template_type_parm_K ||
272 element_type_kind == typename_type_K or element_type_kind == union_type_K ||
273 element_type_kind == vector_type_K || element_type_kind == void_type_K,
280 to_be_lowered_memset.push_front(std::make_pair(stmt, bb.second->number));
285 "inconsistent behavioral helper");
293 "inconsistent behavioral helper");
300 bb.second->RemoveStmt(stmt,
AppM);
310 for(
const auto& stmt_bb_pair : to_be_lowered_memset)
313 "-->Transforming (" +
STR(stmt_bb_pair.first->index) +
") " +
STR(stmt_bb_pair.first));
314 const auto BB1_block =
sl->list_of_bloc.at(stmt_bb_pair.second);
317 const auto BBN1_block = blocRef(
new bloc((
sl->list_of_bloc.rbegin())->first + 1));
319 sl->add_bloc(BBN1_block);
322 BBN1_block->loop_id = max_loop_id;
323 BBN1_block->schedule = BB1_block->schedule;
324 BBN1_block->SetSSAUsesComputed();
327 BBN1_block->add_pred(BB1_block->number);
328 BBN1_block->add_pred(BBN1_block->number);
329 BBN1_block->add_succ(BBN1_block->number);
330 BBN1_block->true_edge = BBN1_block->number;
333 const auto BBN2_block = blocRef(
new bloc((
sl->list_of_bloc.rbegin())->first + 1));
335 sl->add_bloc(BBN2_block);
337 BBN2_block->loop_id = BB1_block->loop_id;
338 BBN2_block->schedule = BB1_block->schedule;
339 BBN2_block->SetSSAUsesComputed();
342 BBN2_block->add_pred(BBN1_block->number);
344 BBN2_block->list_of_succ = BB1_block->list_of_succ;
346 BBN2_block->true_edge = BB1_block->true_edge;
347 BBN2_block->false_edge = BB1_block->false_edge;
348 BB1_block->true_edge = 0;
349 BB1_block->false_edge = 0;
350 BB1_block->list_of_succ.clear();
351 BB1_block->add_succ(BBN1_block->number);
354 BBN1_block->add_succ(BBN2_block->number);
355 BBN1_block->false_edge = BBN2_block->number;
358 for(
const auto& succ : BBN2_block->list_of_succ)
360 const auto succ_block =
sl->list_of_bloc.at(succ);
361 succ_block->list_of_pred.erase(
362 std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), BB1_block->number));
363 succ_block->add_pred(BBN2_block->number);
365 for(
const auto&
phi : succ_block->CGetPhiList())
368 for(
const auto& def_edge : gp->CGetDefEdgesList())
370 if(def_edge.second == BB1_block->number)
379 const auto ga = GetPointerS<gimple_assign>(
GET_NODE(stmt_bb_pair.first));
380 const auto mr = GetPointerS<mem_ref>(
GET_NODE(ga->op0));
382 auto init_var = mr->op0;
383 const auto srcp_default = ga->include_name +
":" +
STR(ga->line_number) +
":" +
STR(ga->column_number);
385 const auto algn = GetPointerS<const type_node>(
GET_CONST_NODE(type_node1))->algn;
391 const auto offset_type = tree_man->GetSizeType();
392 const auto pt = tree_man->GetPointerType(type_node1, algn);
395 const auto nop_init_var = tree_man->create_unary_operation(pt, init_var, srcp_default, nop_expr_K);
396 const auto nop_init_var_ga =
398 init_var = GetPointerS<gimple_assign>(
GET_NODE(nop_init_var_ga))->op0;
405 std::vector<std::pair<tree_nodeRef, unsigned int>> list_of_def_edge;
406 list_of_def_edge.push_back(std::make_pair(init_var, BB1_block->number));
407 const auto phi = tree_man->create_phi_node(new_induction_var, list_of_def_edge,
function_id);
408 const auto gp = GetPointerS<gimple_phi>(
GET_NODE(
phi));
410 phi_res_use_set->Add(var);
411 GetPointerS<ssa_name>(
GET_NODE(gp->res))->use_set = phi_res_use_set;
412 BBN1_block->AddPhi(
phi);
416 const auto dst_ptr_t = GetPointer<const pointer_type>(
GET_CONST_NODE(dst_type));
419 THROW_ASSERT(dst_size % 8 == 0,
"unexpected condition");
420 const auto copy_byte_size = dst_size / 8;
421 const auto copy_byte_size_node =
424 tree_man->create_binary_operation(pt, init_var, copy_byte_size_node, srcp_default, pointer_plus_expr_K);
427 GetPointerS<gimple_assign>(
GET_NODE(pp_ga))->temporary_address =
true;
428 const auto vd_limit = GetPointerS<gimple_assign>(
GET_NODE(pp_ga))->op0;
430 vd_limit_use_set->Add(var);
431 GetPointerS<ssa_name>(
GET_NODE(vd_limit))->use_set = vd_limit_use_set;
434 const auto size_node =
436 const auto pp_ind = tree_man->create_binary_operation(pt, gp->res, size_node, srcp_default, pointer_plus_expr_K);
437 const auto pp_ga_ind =
439 GetPointerS<gimple_assign>(
GET_NODE(pp_ga_ind))->temporary_address =
true;
440 const auto vd_ind = GetPointerS<gimple_assign>(
GET_NODE(pp_ga_ind))->op0;
442 vd_ind_use_set->Add(var);
443 GetPointerS<ssa_name>(
GET_NODE(vd_ind))->use_set = vd_ind_use_set;
445 BBN1_block->PushBack(pp_ga_ind,
AppM);
449 const auto boolean_type = tree_man->GetBooleanType();
450 const auto comparison =
451 tree_man->create_binary_operation(boolean_type, vd_ind, vd_limit, srcp_default, ne_expr_K);
455 BBN1_block->PushBack(comp_ga,
AppM);
459 const auto comp_res = GetPointerS<gimple_assign>(
GET_NODE(comp_ga))->op0;
460 const auto gc = tree_man->create_gimple_cond(comp_res, function_id, srcp_default);
465 const auto new_mem_ref =
466 tree_man->create_binary_operation(type_node1, gp->res, zero_offset, srcp_default, mem_ref_K);
471 const auto list_of_stmt = BB1_block->CGetStmtList();
472 bool found_memset_statement =
false;
474 for(
auto statement = list_of_stmt.begin(); statement != list_of_stmt.end(); statement++)
479 found_memset_statement =
true;
480 const auto temp_statement = *statement;
482 auto tmp_it = statement;
485 BB1_block->RemoveStmt(temp_statement,
AppM);
486 BBN1_block->PushBack(temp_statement,
AppM);
491 else if(found_memset_statement)
494 const auto temp_statement = *statement;
496 auto tmp_it = statement;
499 BB1_block->RemoveStmt(temp_statement,
AppM);
500 BBN2_block->PushBack(temp_statement,
AppM);
506 THROW_ASSERT(found_memset_statement,
"unexpected condition");
507 BB1_block->PushBack(nop_init_var_ga,
AppM);
508 BB1_block->PushBack(pp_ga,
AppM);
509 BBN1_block->PushBack(gc,
AppM);
513 (!
parameters->IsParameter(
"print-dot-FF") ||
parameters->GetParameter<
unsigned int>(
"print-dot-FF")))
515 AppM->CGetCallGraphManager()->CGetCallGraph()->WriteDot(
"compute_implicit_calls" +
GetSignature() +
".dot");
527 const auto ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(stmt));
530 lhs_node->get_kind() == mem_ref_K,
531 "unexpected condition: " +
AppM->CGetFunctionBehavior(
function_id)->CGetBehavioralHelper()->get_function_name() +
532 " calls function " +
MEMCPY +
" in operation " + ga->ToString() +
" but lhs " + lhs_node->ToString() +
533 " is not a mem_ref: it's a " + lhs_node->get_kind_text());
534 const auto mr_lhs = GetPointer<const mem_ref>(lhs_node);
539 const auto rhs_kind = rhs_node->get_kind();
542 const std::string current_srcp =
543 s ? (s->include_name +
":" +
STR(s->line_number) +
":" +
STR(s->column_number)) :
"";
545 unsigned long int copy_byte_size = 0;
548 std::vector<tree_nodeRef>
args = {mr_lhs->op0};
551 rhs_kind == mem_ref_K || rhs_kind == parm_decl_K || rhs_kind == string_cst_K,
552 "unexpected condition: " +
AppM->CGetFunctionBehavior(
function_id)->CGetBehavioralHelper()->get_function_name() +
553 " calls function " +
MEMCPY +
" in operation " + ga->ToString() +
" but rhs " + rhs_node->ToString() +
554 " is not a mem_ref: it's a " + rhs_node->get_kind_text());
555 if(rhs_kind == mem_ref_K)
557 const auto mr_rhs = GetPointer<const mem_ref>(rhs_node);
563 args.push_back(mr_rhs->op0);
568 const auto dst_ptr_t = GetPointer<const pointer_type>(
GET_CONST_NODE(dst_type));
569 const auto src_ptr_t = GetPointer<const pointer_type>(
GET_CONST_NODE(src_type));
570 unsigned long long dst_size;
577 const auto dst_rptr_t = GetPointer<const reference_type>(
GET_CONST_NODE(dst_type));
580 unsigned long long src_size;
587 const auto src_rptr_t = GetPointer<const reference_type>(
GET_CONST_NODE(src_type));
590 if(src_size != dst_size)
593 "---WARNING: src_size = " +
STR(src_size) +
"; dst_size = " +
STR(dst_size));
596 copy_byte_size = src_size / 8
U;
598 else if(rhs_kind == string_cst_K)
606 block->PushBefore(memcpy_src_ga, stmt,
AppM);
608 const auto new_ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(memcpy_src_ga));
609 args.push_back(new_ga->op0);
613 const auto dst_ptr_t = GetPointer<const pointer_type>(
GET_CONST_NODE(dst_type));
617 const auto dst_size = dst_bitsize / 8
U;
618 const auto sc = GetPointer<const string_cst>(rhs_node);
619 const auto src_strlen = sc->strg.length();
620 if((src_strlen + 1) != dst_size)
623 "---WARNING: src_strlen = " +
STR(src_strlen) +
"; dst_size = " +
STR(dst_size));
625 copy_byte_size = src_strlen;
635 block->PushBefore(memcpy_src_ga, stmt,
AppM);
637 const auto new_ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(memcpy_src_ga));
638 args.push_back(new_ga->op0);
643 const auto dst_ptr_t = GetPointer<const pointer_type>(
GET_CONST_NODE(dst_type));
644 const auto src_ptr_t = GetPointer<const pointer_type>(src_type);
649 if(src_size != dst_size)
652 "---WARNING: src_size = " +
STR(src_size) +
"; dst_size = " +
STR(dst_size));
655 copy_byte_size = src_size / 8;
669 block->Replace(stmt, new_gimple_call,
true,
AppM);
672 "---Replaced hidden call " +
STR(ga) +
" with call " +
STR(new_gimple_call) +
673 " id: " +
STR(new_gimple_call->index));
679 const auto ga = GetPointer<const gimple_assign>(
GET_CONST_NODE(stmt));
682 lhs_node->get_kind() == mem_ref_K,
683 "unexpected condition: " +
AppM->CGetFunctionBehavior(
function_id)->CGetBehavioralHelper()->get_function_name() +
684 " calls function " +
MEMSET +
" in operation " + ga->ToString() +
" but lhs " + lhs_node->ToString() +
685 " is not a mem_ref: it's a " + lhs_node->get_kind_text());
686 const auto mr_lhs = GetPointer<const mem_ref>(lhs_node);
692 const auto current_srcp = s ? (s->include_name +
":" +
STR(s->line_number) +
":" +
STR(s->column_number)) :
"";
694 unsigned long int copy_byte_size = 0
U;
697 std::vector<tree_nodeRef>
args = {mr_lhs->op0};
708 const auto dst_ptr_t = GetPointer<const pointer_type>(
GET_CONST_NODE(dst_type));
712 copy_byte_size = dst_size / 8
U;
724 block->Replace(stmt, new_gimple_call,
true,
AppM);
727 "<--Replaced hidden call " +
STR(ga) +
" with call " +
STR(new_gimple_call) +
728 " id: " +
STR(new_gimple_call->index));
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
This struct specifies a point-to solution.
static tree_nodeConstRef GetFormalIth(const tree_nodeConstRef &obj, unsigned int parm_index)
Return the type of the ith formal parameter in case index_obj is a call_expr.
refcount< PointToSolution > PointToSolutionRef
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
This struct specifies the field bloc (basic block).
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define MEMCPY
constant string identifying the operation performed when two objects are memcopied.
File containing functions and utilities to support the printing of debug messagges.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
const CustomUnorderedSet< std::pair< FrontendFlowStepType, FunctionRelationship > > ComputeFrontendRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Return the set of analyses in relationship with this design step.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
Step successfully executed.
const tree_nodeRef CGetTreeReindex(const unsigned int i) const
Return a tree_reindex wrapping the i-th tree_node.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
void ReplaceTreeNode(const tree_nodeRef &stmt, const tree_nodeRef &old_node, const tree_nodeRef &new_node)
Replace the occurrences of tree node old_node with new_node in statement identified by tn...
This struct specifies the statement_list node.
#define BB_EXIT
constant identifying the basic block node of type exit
Definition of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
RelationshipType
The relationship type.
Source must be executed to satisfy target.
static std::string GetString(const enum kind k)
Given a kind, return the corresponding string.
static tree_nodeConstRef CGetElements(const tree_nodeConstRef &type)
Given an array or a vector return the element type.
Base class to model interfaces for high-level synthesis.
std::map< unsigned int, blocRef > list_of_bloc
list_of_bloc field is the list of basic block. If this field is null then the list_of_stmt field is n...
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
void replace_with_memset(tree_nodeRef stmt, const statement_list *sl, tree_manipulationRef tree_man) const
Data structure describing a basic block at tree level.
~compute_implicit_calls() override
Destructor.
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
std::string GetSignature() const override
Return the signature of this step.
#define MEMSET
constant string identifying the operation performed when two objects are memsetted.
const tree_nodeRef get_tree_node_const(unsigned int i) const
Return the reference to the i-th tree_node Constant version of get_tree_node.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
tree_nodeRef GetPointerType(const tree_nodeConstRef &ptd, unsigned long long algn=0) const
Function that creates a pointer type if it is not already present, otherwise it returns the one that ...
const unsigned int index
Represent the index read from the raw file and the index-1 of the vector of tree_node associated to t...
tree_nodeRef CreateUniqueIntegerCst(integer_cst_t value, const tree_nodeConstRef &type)
memoization of integer constants
Target must be reexecuted.
std::pair< tree_nodeRef, unsigned int > DefEdge
The type of the def edge.
compute_implicit_calls(const ParameterConstRef parameters, const application_managerRef AppM, unsigned int _function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
#define BB_ENTRY
constant identifying the basic block node of type entry
static bool IsVectorType(const tree_nodeConstRef &type)
Return true if the treenode is a vector.
#define GET_CONST_NODE(t)
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
This struct specifies the block node.
This file collects some utility functions.
const unsigned int function_id
The index of the function to be analyzed.
static tree_nodeConstRef GetBaseVariable(const tree_nodeConstRef &mem)
Retrun the base variable of a memory access.
const application_managerRef AppM
The application manager.
struct definition of the type node structures.
Class specification of the tree_reindex support class.
tree_nodeRef create_gimple_call(const tree_nodeConstRef &called_function, const std::vector< tree_nodeRef > &args, unsigned int function_decl_nid, const std::string &srcp) const
GIMPLE_CALL.
Data structures used in operations graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
Classes specification of the tree_node data structures not present in the gcc.
this class is used to manage the command-line or XML options.
void replace_with_memcpy(tree_nodeRef stmt, const statement_list *sl, tree_manipulationRef tree_man) const
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
tree_managerRef TM
The tree manager.
tree_nodeRef CreateGimpleAssignAddrExpr(const tree_nodeConstRef &tn, unsigned int function_decl_nid, const std::string &srcp) const
Create a gimple_assign with op0 a new ssa_name, and op1 an addr_expr which takes the address of the t...
Determine variables to be stored in memory.
#define GET_INDEX_CONST_NODE(t)
DesignFlowStep_Status InternalExec() override
Determines the variables that require a memory access.
tree_nodeRef GetFunction(const std::string &function_name) const
Return the index of a function given its name.
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
Class specification of the manager of the tree structures extracted from the raw file.
A brief description of the C++ Header File.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...