69 const DesignFlowManagerConstRef _design_flow_manager,
const ParameterConstRef _parameters)
81 switch(relationship_type)
85 relationships.insert(std::make_pair(BLOCK_FIX,
SAME_FUNCTION));
101 return relationships;
110 auto* fd = GetPointer<function_decl>(temp);
111 auto*
sl = GetPointer<statement_list>(
GET_NODE(fd->body));
112 auto& list_of_block = sl->list_of_bloc;
115 for(
const auto& basic_block : list_of_block)
118 const auto list_of_stmt = basic_block.second->CGetStmtList();
120 if(!list_of_stmt.empty() &&
GET_NODE(*(list_of_stmt.rbegin()))->get_kind() == gimple_switch_K)
122 const auto gs = GetPointer<const gimple_switch>(
GET_NODE(list_of_stmt.back()));
124 "-->BB" +
STR(basic_block.first) +
" ends with a switch");
126 "-->Checking if some successor has more than two gimple_label");
130 for(
const auto succ : basic_block.second->list_of_succ)
132 const auto succ_list_of_stmt = list_of_block.find(succ)->second->CGetStmtList();
133 auto next = succ_list_of_stmt.begin();
134 next = succ_list_of_stmt.size() > 1 ? ++next : next;
135 if(succ_list_of_stmt.size() > 1 and
GET_NODE(*next)->get_kind() == gimple_label_K)
138 multiple_labels_blocks.insert(succ);
144 multiple_labels_block_end = multiple_labels_blocks.end();
145 for(multiple_labels_block = multiple_labels_blocks.begin(); multiple_labels_block != multiple_labels_block_end;
146 ++multiple_labels_block)
153 std::vector<tree_nodeRef>::const_iterator it, it_end = tv->
list_of_op.end();
154 for(it = tv->
list_of_op.begin(); it != it_end; ++it)
159 blocRef current_block = list_of_block.find(*multiple_labels_block)->second;
160 const auto current_list_of_stmt = list_of_block.find(*multiple_labels_block)->second->CGetStmtList();
161 auto current_tree_node = current_list_of_stmt.front();
163 if(cases.find(ld) == cases.end())
167 auto stmt_index = current_list_of_stmt.begin();
168 THROW_ASSERT(current_list_of_stmt.size() > 1,
"expected more than one statement");
170 while(stmt_index != current_list_of_stmt.end())
173 current_tree_node = *stmt_index;
175 "An artificial label_decl has not been found at the beginning of the basic block");
177 if(cases.find(ld) != cases.end())
185 "An artificial label_decl has not been found at the beginning of the basic block");
186 const auto temp_label = *stmt_index;
187 list_of_block.find(*multiple_labels_block)->second->RemoveStmt(temp_label,
AppM);
188 list_of_block.find(*multiple_labels_block)->second->PushFront(temp_label,
AppM);
193 current_tree_node = current_list_of_stmt.front();
194 list_of_block.find(*multiple_labels_block)->second->RemoveStmt(*(current_list_of_stmt.begin()),
AppM);
197 blocRef new_bb = blocRef(
new bloc(list_of_block.rbegin()->first + 1));
198 new_bb->loop_id = current_block->loop_id;
200 list_of_block[new_bb->number] = new_bb;
201 new_bb->list_of_pred = current_block->list_of_pred;
203 for(
auto predecessor : current_block->list_of_pred)
205 if(predecessor != basic_block.first)
207 auto& successors = list_of_block.find(predecessor)->second->list_of_succ;
208 successors.erase(std::find(successors.begin(), successors.end(), *multiple_labels_block));
209 successors.push_back(new_bb->number);
212 new_bb->PushFront(current_tree_node,
AppM);
213 basic_block.second->list_of_succ.push_back(new_bb->number);
214 blocRef previous_block = new_bb;
215 auto next = current_list_of_stmt.begin();
216 next = current_list_of_stmt.size() > 1 ? ++next : next;
217 while(current_list_of_stmt.size() > 1 and
GET_NODE(*next)->get_kind() == gimple_label_K)
222 current_tree_node = current_list_of_stmt.front();
223 list_of_block.find(*multiple_labels_block)->second->RemoveStmt(current_tree_node,
AppM);
225 new_bb = blocRef(
new bloc(list_of_block.rbegin()->first + 1));
226 new_bb->loop_id = previous_block->loop_id;
228 list_of_block[new_bb->number] = new_bb;
229 new_bb->list_of_pred.push_back(previous_block->number);
230 previous_block->list_of_succ.push_back(new_bb->number);
231 new_bb->PushFront(current_tree_node,
AppM);
232 previous_block = new_bb;
235 if(cases.find(ld) != cases.end())
237 new_bb->list_of_pred.push_back(basic_block.first);
238 basic_block.second->list_of_succ.push_back(new_bb->number);
242 current_block->list_of_pred.clear();
243 current_block->list_of_pred.push_back(previous_block->number);
244 previous_block->list_of_succ.push_back(*multiple_labels_block);
248 current_tree_node = current_list_of_stmt.front();
251 if(cases.find(ld) == cases.end())
253 std::vector<unsigned int>& switch_list_of_succ = basic_block.second->list_of_succ;
255 THROW_ASSERT(std::find(switch_list_of_succ.begin(), switch_list_of_succ.end(), current_block->number) !=
256 switch_list_of_succ.end(),
257 "current block not found between successors of current one");
259 switch_list_of_succ.erase(
260 std::find(switch_list_of_succ.begin(), switch_list_of_succ.end(), current_block->number));
264 current_block->list_of_pred.push_back(basic_block.first);
273 (!
parameters->IsParameter(
"print-dot-FF") ||
parameters->GetParameter<
unsigned int>(
"print-dot-FF")))
278 for(
const auto succ : basic_block.second->list_of_succ)
280 if(list_of_block.find(succ)->second->list_of_pred.size() > 1)
282 to_be_fixed.insert(succ);
286 for(t = to_be_fixed.begin(); t != t_end; ++t)
290 blocRef new_bb = blocRef(
new bloc(list_of_block.rbegin()->first + 1));
291 new_bb->loop_id = basic_block.second->loop_id;
292 list_of_block[new_bb->number] = new_bb;
294 new_bb->list_of_pred.push_back(basic_block.first);
295 new_bb->list_of_succ.push_back(*t);
297 i_end = basic_block.second->list_of_succ.size();
298 for(i = 0; i != i_end; i++)
300 if(basic_block.second->list_of_succ[i] == *t)
302 basic_block.second->list_of_succ[i] = new_bb->number;
307 bool multiple_pred_switch =
false;
308 i_end = list_of_block.find(*t)->second->list_of_pred.size();
309 for(i = 0; i != i_end; i++)
311 if(list_of_block.find(*t)->second->list_of_pred[i] == basic_block.first)
313 list_of_block.find(*t)->second->list_of_pred[i] = new_bb->number;
314 for(
const auto&
phi : list_of_block.find(*t)->second->CGetPhiList())
316 auto* current_phi = GetPointer<gimple_phi>(
GET_NODE(
phi));
317 for(
const auto& def_edge : current_phi->CGetDefEdgesList())
319 if(def_edge.second == basic_block.first)
321 current_phi->ReplaceDefEdge(TM, def_edge,
329 if(list_of_block.find(list_of_block.find(*t)->second->list_of_pred[i])->second and
330 list_of_block.find(list_of_block.find(*t)->second->list_of_pred[i])->second->CGetStmtList().size())
332 if(
GET_NODE(list_of_block.find(list_of_block.find(*t)->second->list_of_pred[i])
333 ->second->CGetStmtList()
335 ->get_kind() == gimple_switch_K)
337 multiple_pred_switch =
true;
343 THROW_ASSERT(
GET_NODE(list_of_block.find(*t)->second->CGetStmtList().front())->get_kind() == gimple_label_K,
344 "BB" +
STR(*t) +
" follows switch " +
STR(basic_block.first) +
345 " but it does not start with a label");
346 if(multiple_pred_switch)
348 auto label_expr_node = list_of_block.find(*t)->second->CGetStmtList().front();
349 auto* le = GetPointer<gimple_label>(
GET_NODE(label_expr_node));
351 auto* ld = GetPointer<label_decl>(
GET_NODE(label_decl_node));
353 std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> IR_schema;
356 IR_schema[
TOK(
TOK_SRCP)] = ld->include_name +
":" +
STR(ld->line_number) +
":" +
STR(ld->column_number);
363 IR_schema[
TOK(
TOK_SRCP)] = le->include_name +
":" +
STR(le->line_number) +
":" +
STR(ld->column_number);
366 gl->bb_index = new_bb->number;
367 auto* te = GetPointer<tree_vec>(
GET_NODE(gs->op1));
368 std::vector<tree_nodeRef>& list_of_op = te->list_of_op;
369 for(
auto& ind : list_of_op)
371 auto* cl = GetPointer<case_label_expr>(
GET_NODE(ind));
375 cl->got = new_label_decl_reindex;
382 auto label = list_of_block.find(*t)->second->CGetStmtList().front();
383 list_of_block.find(*t)->second->RemoveStmt(label,
AppM);
384 new_bb->PushFront(label,
AppM);
393 (!
parameters->IsParameter(
"print-dot-FF") ||
parameters->GetParameter<
unsigned int>(
"print-dot-FF")))
397 if(
AppM->ApplyNewTransformation())
401 std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> IR_schema;
405 TM->
create_tree_node(gimple_multi_way_if_id, gimple_multi_way_if_K, IR_schema);
406 auto new_gwi = GetPointer<gimple_multi_way_if>(TM->
get_tree_node_const(gimple_multi_way_if_id));
410 const auto gotos = GetPointer<const tree_vec>(
GET_NODE(gs->op1));
411 for(
const auto& goto_ : gotos->list_of_op)
413 const auto cle = GetPointer<const case_label_expr>(
GET_NODE(goto_));
416 "---Destination: " +
STR(cle->got->index) +
" CLE " +
STR(cle->index));
417 case_labels[cle->got->index].insert(goto_);
421 unsigned int default_bb = 0;
424 for(
auto succ : basic_block.second->list_of_succ)
427 const auto succ_list_of_stmt = list_of_block.find(succ)->second->CGetStmtList();
428 const auto label = succ_list_of_stmt.front();
429 const auto gl = GetPointer<const gimple_label>(
GET_NODE(label));
432 for(
const auto& case_label : case_labels.find(gl->op->index)->second)
434 const auto cle = GetPointer<const case_label_expr>(
GET_CONST_NODE(case_label));
442 const auto eq = tree_man->CreateEqExpr(gs->op0, cle->op0, basic_block.second,
function_id);
446 cond = cond ? tree_man->CreateOrExpr(cond, eq, basic_block.second,
function_id) : eq;
449 cond = tree_man->CreateOrExpr(
451 tree_man->CreateEqExpr(
459 const auto eq = tree_man->CreateEqExpr(gs->op0, cle->op0, basic_block.second,
function_id);
460 cond = cond ? tree_man->CreateOrExpr(cond, eq, basic_block.second,
function_id) : eq;
472 new_gwi->add_cond(cond, succ);
474 list_of_block.find(succ)->second->RemoveStmt(list_of_block.find(succ)->second->CGetStmtList().front(),
479 basic_block.second->RemoveStmt(basic_block.second->CGetStmtList().back(),
AppM);
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
#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;.
File containing functions and utilities to support the printing of debug messagges.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Definition of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
std::string GetName() const override
Return the name of this design step.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
A simple interface to token object of the raw files.
void PrintTreeManager(const bool before) const
Dump the tree manager.
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
DesignFlowStep_Status InternalExec() override
Updates the tree to have a more compliant CFG.
Data structure describing a basic block at tree level.
#define TOK(token)
Macro used to convert a token symbol into a treeVocabularyTokenTypes.
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
#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.
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
~SwitchFix() override
Destructor.
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
unsigned int new_tree_node_id(const unsigned int ask=0)
Return a new node id in the intermediate representation.
void WriteBBGraphDot(const std::string &filename) const
Write the current version of statement list in dot format.
void create_tree_node(const unsigned int node_id, enum kind tree_node_type, std::map< TreeVocabularyTokenTypes_TokenEnum, std::string > &tree_node_schema)
Factory method.
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.
tree_nodeRef GetTreeReindex(const unsigned int i)
Return a tree_reindex wrapping the i-th tree_node.
#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.
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.
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 file collects some utility functions.
const unsigned int function_id
The index of the function to be analyzed.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
SwitchFix(const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager, const ParameterConstRef parameters)
Constructor.
std::vector< tree_nodeRef > list_of_op
list_of_op is the array of tree node stored in tree_vec node.(macro TREE_VEC_ELT) ...
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.
Analysis step that modifies the control flow graph to fix switches.
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.
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.
This struct specifies the tree_vec node.
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.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...