1 /***************************************************************************
2 * Program: create_pattern.c
3 * Function: Transforms the given ir_graph into the pattern (search) graph.
4 * Extracts nodes to be dumped by the grgen_dumper and other
5 * information into a graph_ana structure.
6 * Author: Andreas Schoesser
8 ***************************************************************************/
16 #include "simd_presets.h"
26 #include "iroptimize.h"
30 #include "simd_presets.h"
31 #include "firm_node_ext.h"
32 #include "create_pattern_t.h"
33 #include "grgen_dumper.h"
34 #include "be_spec_dumper.h"
35 #include "normalize.h"
36 #include "rule_info_dumper.h"
40 /************************************************************************
41 * Generates pattern for one given function
42 * representing the C-specification of a complex instruction
43 ************************************************************************/
45 void ext_grs_create_pattern() {
46 graph_ana_info_t graph_ana_info;
47 char c, grgen_commandline[1000] = "";
48 int i, variants, rule_nr = 0;
49 struct obstack obst; // General obst for objects generated during analysis
50 int last_priority = 0;
52 // Environments of the used modules
53 be_spec_env_t *be_spec_env;
54 grgen_dumper_env_t *grgen_dumper_env;
55 rule_info_env_t *rule_info_env;
57 clock_t start_time, end_time;
59 #ifdef DUMP_EVERYTHING
60 for(i = 0; i < get_irp_n_irgs(); i++)
63 sprintf(filename, "%s.grg", get_entity_name(get_irg_entity(irg)));
64 dump_irgraph_complete_grgen(get_irp_irg(i), filename, 0);
69 // Generate Header of rule pointers file
70 rule_info_env = init_rule_info_dumper(get_irp_n_irgs() * MAX_ADDRESS_VARIANTS);
71 be_spec_env = init_be_spec();
72 grgen_dumper_env = init_grgen_dumper(GRGEN_GRAPH_FILE, 0);
74 // Create VProj FIRM nodes etc.
78 for(i = 0; i < get_irp_n_irgs(); i++)
80 struct pmap *nodes_to_dump = pmap_create(); // Saves all nodes that have to be dumped after analysis
81 struct pmap *register_access = pmap_create(); // Saves LOAD and STORE nodes that access registers instead of memory,
82 // along with their array index.
83 struct pmap *memory_access = pmap_create(); // Saves LOAD and STORE nodes that access memory along
84 struct pmap *argument_nodes = pmap_create(); // Saves nodes that deliver pointers for memory access
88 // Init the walker_info structure, which contains data needed or filled during
89 // the analysis of the graph
90 graph_ana_info.irg = get_irp_irg(i);
91 graph_ana_info.nodes_to_dump = nodes_to_dump;
92 graph_ana_info.register_access = register_access;
93 graph_ana_info.memory_access = memory_access;
94 graph_ana_info.argument_nodes = argument_nodes;
95 graph_ana_info.destroyed_regs = pmap_create();
96 graph_ana_info.obst = &obst;
97 graph_ana_info.num_simd_arguments = 0;
98 graph_ana_info.complex_operation_block = NULL;
99 graph_ana_info.node_to_match_block = NULL;
100 graph_ana_info.emit_statement = NULL;
101 graph_ana_info.has_result = 0;
102 graph_ana_info.variant_nr = 0;
103 graph_ana_info.priority = last_priority; // Maybe the user did not specify a priority in this pattern. Use the last priority then.
104 graph_ana_info.cost_savings = 3;
105 graph_ana_info.dump_everything = 0;
107 printf("*** %s ***:\n", get_entity_name(get_irg_entity(graph_ana_info.irg)));
109 // Dump the graph before we change anything
110 dump_ir_block_graph(graph_ana_info.irg, "-pre-create-pattern");
112 // Normalize the Address calculation for LOADs and STOREs
113 set_irg_memory_disambiguator_options(graph_ana_info.irg, aa_opt_no_alias);
114 optimize_load_store(graph_ana_info.irg);
115 remove_critical_cf_edges(graph_ana_info.irg);
116 normalize_address_calculation(graph_ana_info.irg, 0);
119 // Dump the graph before we change anything
120 dump_ir_block_graph(graph_ana_info.irg, "-post-norm-pattern");
124 irg_walk_graph(graph_ana_info.irg, walk_pre, walk_post, &graph_ana_info);
125 if(graph_ana_info.emit_statement == NULL)
126 assert(0 && "No emit statement given!");
128 edges_activate(graph_ana_info.irg);
129 for(variants = 0; variants < MAX_ADDRESS_VARIANTS; variants++)
131 int uses_memory; // TODO: Maybe find the out during analysis.
133 // Dump rule information
134 dump_rule_info(rule_info_env, &graph_ana_info, graph_ana_info.num_simd_arguments);
137 // Dump graph (that is pattern) in grGen format
138 uses_memory = dump_irgraph_grgen(grgen_dumper_env, &graph_ana_info);
140 // Dump the backend specification
141 dump_be_spec(be_spec_env, &graph_ana_info, uses_memory);
143 // Add an address variant
144 if(variants < MAX_ADDRESS_VARIANTS - 1)
146 if(!add_address_variant(&graph_ana_info))
148 graph_ana_info.variant_nr++;
152 // New code placement
153 // set_opt_global_cse(1);
154 // optimize_graph_df(walker_info.irg);
155 // place_code(walker_info.irg);
156 // set_opt_global_cse(0);
158 // Dump graph in .vcg format
159 dump_ir_block_graph(graph_ana_info.irg, "-post-create-pattern");
161 //dump_type_graph (walker_info.irg, "-TYPES");
164 pmap_destroy(nodes_to_dump);
165 pmap_destroy(register_access);
166 pmap_destroy(argument_nodes);
167 pmap_destroy(memory_access);
168 pmap_destroy(graph_ana_info.destroyed_regs);
170 obstack_free(&obst, NULL);
171 obstack_finish(&obst);
174 last_priority = graph_ana_info.priority;
177 deinit_rule_info_dumper(rule_info_env);
178 deinit_grgen_dumper(grgen_dumper_env);
179 deinit_be_spec(be_spec_env);
182 printf("*******************************\n* Pattern Creation Statistics *\n*******************************\n\n");
184 printf("Time elapsed: %g s\n", ((double) (end_time - start_time)) / CLOCKS_PER_SEC);
185 printf("Rules created: %d\n", rule_nr);
187 printf("\n\n ** Finished pattern creation **\n\n");
189 printf("Run grGen now? (Y/N) ");
191 if(c == 'y' || c == 'Y')
197 /************************************************************************
198 * Build a command line in order to run grgen
199 * Parameters for the GrGen call are globally set in simd_presets.h
200 ************************************************************************/
202 static void run_grgen()
204 char grgen_commandline[1000];
206 strcpy(grgen_commandline, "java -classpath \"");
207 strcat(grgen_commandline, GRGEN_LOCATION);
208 strcat(grgen_commandline, "grgen.jar;");
209 strcat(grgen_commandline, GRGEN_LOCATION);
210 strcat(grgen_commandline, "jars/jargs.jar;");
211 strcat(grgen_commandline, GRGEN_LOCATION);
212 strcat(grgen_commandline, "jars/antlr.jar\" de.unika.ipd.grgen.Main -n -j -i -b de.unika.ipd.grgen.be.C.SearchPlanBackend -o \"");
213 strcat(grgen_commandline, GENERATION_DEST);
214 strcat(grgen_commandline, "\" \"");
215 strcat(grgen_commandline, GRGEN_GRAPH_FILE);
216 strcat(grgen_commandline, "\"");
218 printf("%s\n", grgen_commandline);
220 // Call grGen to create C source for searching the pattern
221 system(grgen_commandline);
227 __ _ _ __ __ _ _ __ | |__ __ _ _ __ __ _| |_ _ ___(_)___
228 / _` | '__/ _` | '_ \| '_ \ / _` | '_ \ / _` | | | | / __| / __|
229 | (_| | | | (_| | |_) | | | | | (_| | | | | (_| | | |_| \__ \ \__ \
230 \__, |_| \__,_| .__/|_| |_| \__,_|_| |_|\__,_|_|\__, |___/_|___/
235 /************************************************************************
236 * Analyze LOAD and STORE nodes, mark nodes for dumping
237 ************************************************************************/
239 static void walk_pre(ir_node *n, void * env)
241 graph_ana_info_t *graph_ana_info = (graph_ana_info_t *) env;
242 struct pmap *nodes_to_dump = graph_ana_info->nodes_to_dump;
243 struct pmap *register_access = graph_ana_info->register_access;
244 struct pmap *memory_access = graph_ana_info->memory_access;
245 struct pmap *argument_nodes = graph_ana_info->argument_nodes;
247 ir_graph *host_irg = graph_ana_info->irg;
248 //nodes_list_t *node_to_dump;
250 // **** Special case: We have a Store Node
251 if(get_irn_opcode(n) == iro_Store)
253 ir_node *call_node = NULL, *add_node = NULL, *pointer_root = NULL;
254 unsigned int array_index = 0;
256 call_node = search_call(n, &array_index, &add_node, &pointer_root);
257 if(is_memory_access(call_node))
259 memory_access_descr_t *memory_access_descr = obstack_alloc(graph_ana_info->obst, sizeof(memory_access_descr_t));
261 // Operations on memory vectors HAVE to access the vector index 0!
263 mark_argument_node(graph_ana_info, call_node, pointer_root, add_node);
265 // Memory STORE, nothing has to be done
266 memory_access_descr->load_store = MEMORY_STORE;
267 memory_access_descr->array_index = array_index;
268 pmap_insert(memory_access, n, (void *) memory_access_descr);
272 register_access_descr_t *register_access_descr = obstack_alloc(graph_ana_info->obst, sizeof(register_access_descr_t));
274 // Store information about the argument node
275 mark_argument_node(graph_ana_info, call_node, pointer_root, add_node);
277 // Fill the register access descriptor
278 register_access_descr -> array_index = array_index;
279 register_access_descr -> load_store = REGISTER_STORE;
280 register_access_descr -> replace_node_name = NULL;
281 register_access_descr -> pointer_base = pointer_root;
283 // Mark the predecessor of the store node as the result to be stored in a register
284 if(get_irn_opcode(get_irn_n(n, 2)) == iro_Conv)
287 ir_node *conv = get_irn_n(n, 2);
288 exchange(conv, get_irn_n(conv, 0));
291 pmap_insert(register_access, get_irn_n(n, 2), (void *) register_access_descr);
293 // Prevent the Address of the STORE node to be dumped.
294 set_irn_visited(get_irn_n(n, 1), get_irg_visited(get_irn_irg(n)));
296 // Don't dump the STORE NODE
302 // **** Special case: We have a Load node
303 if(get_irn_opcode(n) == iro_Load)
305 ir_node *call_node = NULL, *add_node = NULL, *pointer_root = NULL;
306 unsigned int array_index = 0;
309 call_node = search_call(n, &array_index, &add_node, &pointer_root);
311 if(is_memory_access(call_node))
313 memory_access_descr_t *memory_access_descr = obstack_alloc(graph_ana_info->obst, sizeof(memory_access_descr_t));
315 // Operations on memory vectors HAVE to access the vector index 0!
317 mark_argument_node(graph_ana_info, call_node, pointer_root, add_node);
319 // Memory access, nothing has to be done
321 memory_access_descr->load_store = MEMORY_LOAD;
322 memory_access_descr->array_index = array_index;
323 pmap_insert(memory_access, n, (void *) memory_access_descr);
327 // Register access, save information about this load
328 register_access_descr_t *register_access_descr = obstack_alloc(graph_ana_info->obst, sizeof(register_access_descr_t));
330 mark_argument_node(graph_ana_info, call_node, pointer_root, add_node);
332 // Fill the register access descriptor
333 register_access_descr->load_store = REGISTER_LOAD;
334 register_access_descr->array_index = array_index;
335 register_access_descr -> replace_node_name = NULL;
336 register_access_descr -> pointer_base = pointer_root;
338 // Mark this LOAD node, which has to be exchanged by a VProj node
339 pmap_insert(register_access, n, (void *) (register_access_descr));
342 set_irn_visited(add_node, get_irg_visited(get_irn_irg(add_node)));
344 pmap_insert(nodes_to_dump, pointer_root, NULL); // TODO: If the value is already there, will it be overwritten?
346 // Don't dump this LOAD node.
351 // Mark the current node for Dumping
352 switch(get_irn_opcode(n))
356 search_emit_statement(n, graph_ana_info);
358 case iro_End: //We match also the end node.
369 if(get_irn_modecode(n) != irm_M)
370 mark_node_for_dumping(n, graph_ana_info);
374 // Proj's beyond LOADs and STOREs will be dumped in walk-post method
375 // to be sure that all information about the LOAD and STORE has been already computed.
376 if(get_irn_opcode(get_irn_n(n, 0)) == iro_Load || get_irn_opcode(get_irn_n(n, 0)) == iro_Store)
378 if(get_irn_opcode(get_irn_n(n, 0)) == iro_Call || get_irn_opcode(get_irn_n(n, 0)) == iro_Start)
380 if(get_irn_modecode(n) == irm_X && get_irg_start_block(graph_ana_info->irg) == get_nodes_block(n)) // We don't need the initial ProjX
381 break; // TODO: This is only valid of only one block is there!!!
386 mark_node_for_dumping(n, graph_ana_info);
393 /************************************************************************
394 * Take special care of Proj nodes beyond LOAD and STORE
395 * Here we can be sure that the LOAD or STORE node has already been
397 ************************************************************************/
399 static void walk_post(ir_node *n, void * env)
401 graph_ana_info_t *graph_ana_info = (graph_ana_info_t *) env;
402 struct pmap *nodes_to_dump = graph_ana_info->nodes_to_dump;
403 struct pmap *register_access = graph_ana_info->register_access;
404 struct pmap *memory_access = graph_ana_info->memory_access;
405 ir_graph *host_irg = graph_ana_info->irg;
407 if(get_irn_opcode(n) == iro_Proj)
409 ir_node *proj_pred = get_irn_n(n, 0);
412 if(get_irn_opcode(proj_pred) == iro_Store)
414 ir_mode *store_mode = get_irn_mode(get_Store_value(proj_pred));
416 if(pmap_contains(memory_access, proj_pred))
418 memory_access_descr_t *memory_access_descr = pmap_get(memory_access, proj_pred);
419 memory_access_descr->projm = n;
420 memory_access_descr->array_index /= get_mode_size_bytes(store_mode);
422 printf("MEMORY STORE at array index %d\n", memory_access_descr->array_index);
424 // Mark the current proj for dumping.
425 mark_node_for_dumping(n, graph_ana_info);
426 //pmap_insert(memory_access, n, memory_access_descr);
431 register_access_descr_t *register_access_descr = pmap_get(register_access, get_Store_value(proj_pred));
432 register_access_descr->array_index /= get_mode_size_bytes(store_mode);
433 printf("REGISTER STORE at array index %d\n", register_access_descr->array_index);
434 // Register STORE, don't dump it's ProjM
439 if(get_irn_opcode(proj_pred) == iro_Load)
441 ir_mode *load_mode = get_irn_mode(n);
443 if(pmap_contains(register_access, proj_pred))
445 // Register LOAD: Take special care of proj's
448 if(get_irn_modecode(n) != irm_M)
451 register_access_descr_t *register_access_descr = pmap_get(register_access, proj_pred);
452 register_access_descr -> array_index /= get_mode_size_bytes(load_mode);
453 printf("REGISTER LOAD at array index %d\n", register_access_descr->array_index);
455 // We cannot use 'exchange' here, because the node n could already be in
456 // the register_access or memory_access list. Exchanging would result in a wrong pointer
457 // in those lists. Luckily Proj an VProj use the same node data, so we can just
458 // retype the proh to vproj without danger.
460 set_irn_n(n, 0, register_access_descr->pointer_base);
461 set_irn_op(n, op_VProj);
463 set_VProj_proj(n, register_access_descr->array_index);
467 // It's the memory proj. Just don't dump it
473 if(get_irn_modecode(n) != irm_M)
475 memory_access_descr_t *memory_access_descr = pmap_get(memory_access, proj_pred);
476 memory_access_descr -> array_index /= get_mode_size_bytes(load_mode);
477 printf("MEMORY LOAD at array index %d\n", memory_access_descr->array_index);
481 // Mark the current proj for dumping.
482 mark_node_for_dumping(n, graph_ana_info);
487 void mark_node_for_dumping(ir_node *n, graph_ana_info_t *graph_ana_info)
489 analyze_complex_operation_block(n, graph_ana_info);
490 pmap_insert(graph_ana_info->nodes_to_dump, n, NULL);
491 if(get_irn_opcode(n) != iro_Block && get_irn_opcode(n) != iro_Const)
493 ir_node *block = get_nodes_block(n);
494 pmap_insert(graph_ana_info->nodes_to_dump, block, NULL);
500 /************************************************************************
501 * Analyzes the behavior of a LOAD or STORE node
502 * Also detects ConvP node and prevents further dumping
503 * start_node: LOAD or STORE node to analyze
504 * array_index: Returns the array index of the LOAD or STORE
505 * result: CALL node defining the behavior of the LOAD OR STORE
506 ************************************************************************/
508 static ir_node *search_call(ir_node *start_node, unsigned int *array_index, ir_node **add, ir_node **pointer_root)
511 //ir_node *convP_node; // If there's convP involved, replace proj_node by conP_node
514 ir_node *proj_pred_node;
517 assert(get_irn_opcode(start_node) == iro_Load || get_irn_opcode(start_node) == iro_Store);
519 add_node = get_irn_n(start_node, 1);
521 if(get_irn_opcode(add_node) != /*iro_Add*/ iro_MultipleAdd)
523 // Add node is not there if array Index is 0
524 proj_node = add_node;
526 assert(0); // Must not happen when multiple Adds are there
530 // Analyze MultipleAdd predecessors
531 if(get_irn_opcode(get_irn_n(add_node, 0)) == iro_Proj)
533 proj_node = get_irn_n(add_node, 0);
534 aindex = get_tarval_long(get_Const_tarval(get_irn_n(add_node, 1))); // get_mode_size_bytes(get_irn_mode()) /*4*/; // TODO: varibale TARVALS
538 proj_node = get_irn_n(add_node, 1);
539 aindex = get_tarval_long(get_Const_tarval(get_irn_n(add_node, 0)));// / 4; // TODO: varibale TARVALS
543 assert(get_irn_opcode(proj_node) == iro_Proj);
544 //call_node = get_irn_n(get_irn_n(get_irn_n(convP_node, 0), 0), 0); // ConvP -> ProjIs -> ProjT -> Call
545 call_node = get_irn_n(get_irn_n(proj_node, 0), 0); // ProjIs -> ProjT -> Call
546 assert(get_irn_opcode(call_node) == iro_Call && "Call node not found! Pattern not valid.");
548 *array_index = aindex;
550 *pointer_root = proj_node;
552 // Prevent further dumping of nodes starting from that convP Node
553 proj_pred_node = get_irn_n(proj_node, 0);
554 set_irn_visited(proj_pred_node, get_irg_visited(get_irn_irg(proj_pred_node)));
561 /************************************************************************
562 * Marks a vector base pointer to be used as an argument for the
563 * complex operation afterwards
564 ************************************************************************/
566 static void mark_argument_node(graph_ana_info_t *graph_ana_info, ir_node *call_node, ir_node *argument_node, ir_node *add_node)
568 const char *arg_name;
571 // Look if we marked that node already
572 if(!pmap_contains(graph_ana_info->argument_nodes, argument_node))
574 // No. Find out which argument number this node will be
575 // for complex operation
576 arg_name = get_entity_name(get_SymConst_entity(get_irn_n(call_node, 1)));
578 // Is it the result pointer?
579 if(strcmp(arg_name, RESULT_NAME) == 0)
581 // Arg nr is -1 since we don't know how much
582 char *register_class;
583 argument_descr_t *argument_descr = obstack_alloc(graph_ana_info->obst, sizeof(argument_descr_t));
585 register_class = obstack_alloc(graph_ana_info->obst, get_SymConst_strlen(get_irn_n(call_node, 4)));
586 get_SymConst_string(get_irn_n(call_node, 4), register_class);
588 argument_descr -> arg_nr = -1;
589 argument_descr -> argument_location = ARGUMENT_RESULT; // TODO: This is wrong, Memory or Register here
590 argument_descr -> argument_type = (is_vector(call_node) ? ARGUMENT_VECTOR : ARGUMENT_SCALAR);
591 argument_descr -> register_class = register_class;
592 argument_descr -> vec_op_input = add_node; // Only important for memory access nodes
594 pmap_insert(graph_ana_info->argument_nodes, argument_node, (void *) argument_descr);
595 graph_ana_info->has_result = 1;
599 for(i = 0; i < MAX_SIMD_ARGUMENTS; i++)
600 if(strcmp(arg_name, SIMD_ARGUMENTS[i]) == 0)
602 char *register_class;
603 argument_descr_t *argument_descr = obstack_alloc(graph_ana_info->obst, sizeof(argument_descr_t));
605 register_class = obstack_alloc(graph_ana_info->obst, get_SymConst_strlen(get_irn_n(call_node, 4)));
606 get_SymConst_string(get_irn_n(call_node, 4), register_class);
608 argument_descr -> arg_nr = i;
609 argument_descr -> argument_location = (!is_memory_access(call_node) ? ARGUMENT_SIMD_REGISTER : ARGUMENT_MEMORY);
610 argument_descr -> argument_type = (is_vector(call_node) ? ARGUMENT_VECTOR : ARGUMENT_SCALAR);
611 argument_descr -> register_class = register_class;
612 argument_descr -> vec_op_input = add_node;
614 pmap_insert(graph_ana_info->argument_nodes, argument_node, (void *) argument_descr);
615 graph_ana_info->num_simd_arguments = MAX(i, graph_ana_info->num_simd_arguments);
623 /************************************************************************
624 * Tests, if the given call_node is the emit-statement
625 * If so, saves the emit-statement for dumping later in the process.
626 ************************************************************************/
628 void search_emit_statement(ir_node *call_node, graph_ana_info_t *graph_ana_info)
632 const char *function_name;
635 assert(get_irn_opcode(call_node) == iro_Call);
637 // Prevent walker to consider arguments of the call node.
638 for(i = 1; i < get_irn_arity(call_node); i++)
639 set_irn_visited(get_irn_n(call_node, i), get_irg_visited(get_irn_irg(call_node)));
641 // Check the function name
642 symC_name = get_irn_n(call_node, 1);
643 function_name = get_entity_name(get_SymConst_entity(symC_name));
645 // Save the emit statement
646 if(strcmp(function_name, EMIT) == 0)
648 // Allocate space for the emit statement and save it.
649 char *emit_statement;
650 symC_arg = get_irn_n(call_node, 2);
651 emit_statement = obstack_alloc(graph_ana_info->obst, get_SymConst_strlen(symC_arg));
652 get_SymConst_string(symC_arg, emit_statement);
653 graph_ana_info->emit_statement = emit_statement;
657 // Save the extra registers, the complex operation destroys
658 if(strcmp(function_name, DESTROYS) == 0)
660 char *destroy_statement;
661 symC_arg = get_irn_n(call_node, 2);
662 destroy_statement = obstack_alloc(graph_ana_info->obst, get_SymConst_strlen(symC_arg));
664 get_SymConst_string(symC_arg, destroy_statement);
665 pmap_insert(graph_ana_info->destroyed_regs, call_node, destroy_statement);
668 if(strcmp(function_name, PRIORITY) == 0)
670 ir_node *c = get_irn_n(call_node, 2); // Get the constant argument
671 assert(get_irn_opcode(c) == iro_Const && "Something is wrong with the priority node");
672 graph_ana_info->priority = get_tarval_long(get_Const_tarval(c));
675 if(strcmp(function_name, COST_SAVINGS) == 0)
677 ir_node *c = get_irn_n(call_node, 2); // Get the constant argument
678 assert(get_irn_opcode(c) == iro_Const && "Something is wrong with the CostSavings node");
680 graph_ana_info->cost_savings = get_tarval_long(get_Const_tarval(c));
689 /************************************************************************/
690 /* Cut's of the Memory predecessor of a LOAD node */
691 /* We don't need that node in the final pattern. */
692 /************************************************************************/
694 static void kill_mem_pred(ir_node *load)
696 assert(get_irn_opcode(load) == iro_Load);
698 // TODO: Think about this. Is this really enough?
699 if(get_irn_opcode(get_irn_n(get_irn_n(load, 0), 0)) == iro_Call)
700 set_irn_visited(get_irn_n(load, 0), get_irg_visited(get_irn_irg(load)));
707 /************************************************************************
708 * Returns for a given call node if the underlying LOAD or STORE access
709 * memory (1) or not (0)
710 ************************************************************************/
711 static int is_memory_access(ir_node *call)
713 char symC_string[255];
716 assert(get_irn_opcode(call) == iro_Call);
717 symC = get_irn_n(call, 3);
718 assert(get_irn_opcode(symC) == iro_SymConst);
720 get_SymConst_string(symC, symC_string);
721 if(strstr(symC_string, MEMORY_ARRAY) != 0)
727 /************************************************************************/
728 /* Returns 1 if the given argument represents a vector */
729 /************************************************************************/
731 static int is_vector(ir_node *call)
733 char symC_string[255];
736 assert(get_irn_opcode(call) == iro_Call);
737 symC = get_irn_n(call, 2);
738 assert(get_irn_opcode(symC) == iro_SymConst);
739 get_SymConst_string(symC, symC_string);
740 if(strstr(symC_string, "vector") != 0)
747 /************************************************************************
748 * Analyze, if the current pattern node is in the immediate post
749 * dominator block of the start block
750 ************************************************************************/
753 Der Block jedes aufgenommenen Knotens wird ueberprueft.
754 Falls dieser der direkte Nachdominator des Startblocks ist, ist das der Block, in den der komplexe Befehl soll.
757 Wird der Block dann auch wirklich mit einem Knoten des Musters verbunden?
758 Beim Component-Fall anscheinend nicht.
761 void analyze_complex_operation_block(ir_node *n, graph_ana_info_t *graph_ana_info)
763 if(graph_ana_info->complex_operation_block == NULL && get_irn_opcode(n) != iro_Block)
765 ir_node *block = get_nodes_block(n);
766 if(block != get_irg_start_block(graph_ana_info->irg))
768 ir_node *block_pred = get_irn_n(block, 0);
769 if(get_irn_opcode(block_pred) != iro_Block)
770 block_pred = get_nodes_block(block_pred);
771 if(block_pred == get_irg_start_block(graph_ana_info->irg))
773 if(!pmap_contains(graph_ana_info->argument_nodes, n))
775 graph_ana_info->complex_operation_block = block;
776 graph_ana_info->node_to_match_block = n;
777 //pmap_insert(walker_info->nodes_to_dump, block, NULL);
787 __ ____ _ _ __(_) __ _ _ __ | |_ ___
788 \ \ / / _` | '__| |/ _` | '_ \| __/ __|
789 \ V / (_| | | | | (_| | | | | |_\__ \
790 \_/ \__,_|_| |_|\__,_|_| |_|\__|___/ */
792 /************************************************************************
793 * Generates an address mode variant
794 * Returns 0 if no variant was generated because no address calculation
796 ************************************************************************/
798 int add_address_variant(graph_ana_info_t *graph_ana_info)
801 struct pmap *argument_nodes = graph_ana_info->argument_nodes;
806 pmap_foreach(argument_nodes, entry)
808 ir_node *arg = (ir_node *) entry->key;
809 argument_descr_t *arg_descr = entry->value;
810 const ir_edge_t *edge;
811 ir_node *generic_node;
813 if(arg_descr -> argument_type == ARGUMENT_VECTOR && arg_descr -> argument_location == ARGUMENT_MEMORY)
815 generic_node = new_ir_node(NULL, graph_ana_info->irg, get_nodes_block(arg), op_IrNode, mode_ANY, 0, NULL);
816 set_irn_mode(generic_node, mode_ANY);
817 pmap_insert(graph_ana_info->nodes_to_dump, generic_node, NULL);
818 foreach_out_edge_kind(arg, edge, EDGE_KIND_NORMAL)
820 ir_node *mult_add = get_edge_src_irn(edge);
821 int new_arity = get_irn_arity(mult_add) + 1;
822 ir_node **new_ins = alloca(new_arity * sizeof(ir_node *));
825 assert(get_irn_opcode(mult_add) == iro_MultipleAdd);
827 for(i = 0; i < get_irn_arity(mult_add); i++)
828 new_ins[i] = get_irn_n(mult_add, i);
829 new_ins[i] = generic_node;
830 set_irn_in(mult_add, new_arity, new_ins);
842 | '_ ` _ \| / __|/ __|
843 | | | | | | \__ \ (__
844 |_| |_| |_|_|___/\___| */
847 /************************************************************************
848 * Concatenates the rule name out of the irg name and the variant
850 ************************************************************************/
852 void get_rule_name(graph_ana_info_t *graph_ana_info, char *rule_name)
854 ir_graph *irg = graph_ana_info->irg;
855 sprintf(rule_name, "%s_variant%d", get_entity_name(get_irg_entity(irg)), graph_ana_info->variant_nr);
860 /************************************************************************
861 * Gets the number of characters contained in a string SymConst
862 * including the trailing 0-Character
863 ************************************************************************/
865 int get_SymConst_strlen(ir_node *symC)
867 ir_entity *ent = get_SymConst_entity(symC);
868 return(get_compound_ent_n_values(ent) + 1);
873 /************************************************************************
874 * Reads the string assiciated with a sym_const and stores it in
876 ************************************************************************/
878 void get_SymConst_string(ir_node *symC, char *string)
880 ir_entity *ent = get_SymConst_entity(symC);
883 n = get_compound_ent_n_values(ent);
885 for (i = 0; i < n-1; i++) {
889 irn = get_compound_ent_value(ent, i);
890 c = (int) get_tarval_long(get_Const_tarval(irn));