1 /*******************************************************************************************
3 * Function: Part of the simd optimization. Provides functions to normalize a FIRM
4 * graph in order to increase the number of patterns matched.
5 * Author: Andreas Schoesser
7 *******************************************************************************************/
12 #include "simd_presets.h"
21 #include "normalize_t.h"
22 #include "firm_node_ext.h"
26 /************************************************************************
27 * Starts normalization of address calculations for Add and Store
28 * nodes. Folds Add-chains to one big MultipeAdd node.
29 ************************************************************************/
31 struct pmap *normalize_address_calculation(ir_graph *irg, int decomposition_possible)
33 normalize_info_t norm_info;
36 norm_info.replaced_ptrs = (decomposition_possible) ? pmap_create() : NULL;
38 irg_walk_graph(irg, ac_walk_pre, NULL, &norm_info);
40 return(norm_info.replaced_ptrs);
45 /************************************************************************
46 * Called for each ir_node, in which the main work for normalization
48 ************************************************************************/
50 static void ac_walk_pre(ir_node *n, void * env)
52 ir_node *addr, *multAdd;
53 normalize_info_t *norm_info = (normalize_info_t *) env;
54 ir_graph *irg = norm_info->irg;
57 switch(get_irn_opcode(n))
59 case iro_Load: addr = get_Load_ptr(n); break;
60 case iro_Store: addr = get_Store_ptr(n); break;
61 case iro_Proj: if(get_irn_opcode(get_irn_n(n, 0)) == iro_Cmp)
67 if(get_irn_opcode(addr) == iro_Add)
69 // Convert a ADD-chain to a single MultipleAdd node.
74 ir_node **ins = malloc(max_ins * sizeof(ir_node *));
76 if(add_add_preds(add, ins, &max_ins, &arity) == 0)
78 // We found no constant, add 0x0
79 ins[arity++] = new_Const(mode_Is, new_tarval_from_long(0, mode_Is));
81 multAdd = new_ir_node(NULL, irg, get_nodes_block(addr), op_MultipleAdd, get_irn_mode(addr), arity, ins);
83 switch(get_irn_opcode(n))
85 case iro_Load: set_Load_ptr(n, multAdd); break;
86 case iro_Store: set_Store_ptr(n, multAdd); break;
90 // exchange(add, multAdd); Exchange wouldn't work here since the original ADD node would be killed.
91 if(norm_info->replaced_ptrs != NULL)
92 pmap_insert(norm_info->replaced_ptrs, multAdd, add);
95 else if(get_irn_opcode(addr) != iro_MultipleAdd)
97 // Insert a new MultipleAdd node.
98 ir_node **ins = alloca(2 * sizeof(ir_node *));
101 ins[1] = new_Const(mode_Is, new_tarval_from_long(0, mode_Is));
102 multAdd = new_ir_node(NULL, irg, get_nodes_block(n), op_MultipleAdd, get_irn_mode(addr), 2, ins);
103 //exchange(addr, multAdd);
104 if(norm_info->replaced_ptrs != NULL)
105 pmap_insert(norm_info->replaced_ptrs, multAdd, addr);
107 switch(get_irn_opcode(n))
109 case iro_Load: set_Load_ptr(n, multAdd); break;
110 case iro_Store: set_Store_ptr(n, multAdd); break;
115 /* Order the MultAdd ins to be compared quickly later. Bubble Sort */
119 for(i = 0; i < get_irn_arity(multAdd) - 1; i++)
121 ir_node *n1 = get_irn_n(multAdd, i),
122 *n2 = get_irn_n(multAdd, i + 1);
124 // Move the Constant to pos0
125 if(is_Const(n2) && !is_Const(n1))
127 set_irn_n(multAdd, i, n2);
128 set_irn_n(multAdd, i + 1, n1);
133 // Otherwise order by pointer value
134 if(n1 > n2 && !is_Const(n1))
136 set_irn_n(multAdd, i, n2);
137 set_irn_n(multAdd, i + 1, n1);
147 /************************************************************************
148 * Recursive function. Collects all adds of an "add chain" and inserts
149 * all the predecessors of the add chain into one ins array
150 ************************************************************************/
152 int add_add_preds(ir_node *add, ir_node **ins, int *max_len, int *num_preds)
154 int i, found_constant = 0;
156 for(i = 0; i < 2; i++)
158 ir_node *pred = get_irn_n(add, i);
159 switch(get_irn_opcode(pred))
161 case iro_Add: found_constant |= add_add_preds(pred, ins, max_len, num_preds);
163 case iro_Const: found_constant |= 1;
165 default: assert(*num_preds < *max_len && "Reallocation of temp ins array not implemented yet!");
166 ins[*num_preds] = pred;
171 return(found_constant);
176 /*******************************************************
177 * Decompose the normalization, that is replace all
178 * introduced MultipleAdds by their original ADD-Chain.
179 *******************************************************/
181 void decompose_normalization(struct pmap *replaced_ptrs)
185 pmap_foreach(replaced_ptrs, entry)
187 ir_node *multAdd = (ir_node *) entry->key;
188 ir_node *orgAddr = (ir_node *) entry->value;
190 //if(get_irn_n_edges(multAdd) > 0)
191 /* switch(get_irn_opcode(loadStore))
193 case iro_Load: set_Load_ptr(loadStore, orgAddr); break;
194 case iro_Store: set_Store_ptr(loadStore, orgAddr); break;
195 default: break; //return; //assert(0 && "Wrong opcode!");
197 exchange(multAdd, orgAddr);
198 // edges_node_deleted(multAdd, get_irn_irg(multAdd));
201 pmap_destroy(replaced_ptrs);
205 /************************************************************************
206 * Returns the original address that was replaced by a multiple add
207 ************************************************************************/
209 ir_node *get_org_addr(ir_node *madd, struct pmap *replaced_ptrs)
211 assert(get_irn_opcode(madd) == iro_MultipleAdd);
212 return(pmap_get(replaced_ptrs, madd));
217 /************************************************************************
218 * Enforces all compares lt to be gt
219 ************************************************************************/
221 void enforce_cmp_gt(ir_node *proj)
223 if(get_Proj_proj(proj) == pn_Cmp_Lt)
225 pn_Cmp new_pnc = get_inversed_pnc(get_Proj_proj(proj));
226 ir_node *tmp, *cmp = get_irn_n(proj, 0);
228 tmp = get_Cmp_left(cmp);
229 set_Cmp_left(cmp, get_Cmp_right(cmp));
230 set_Cmp_right(cmp, tmp);
231 set_Proj_proj(proj, new_pnc);
236 /************************************************************************/
238 /************************************************************************/
240 void normalize_direct_jump(ir_node *block)
242 int block_arity = get_irn_arity(block);
247 for(i = 0; i < block_arity; i++)
249 ir_node *pred1 = get_irn_n(block, i);
251 if(get_irn_opcode(pred1) == iro_Proj && get_irn_mode(pred1) == mode_X && get_Proj_proj(pred1) == 0 /* False */)
253 cond = get_irn_n(pred1, 0);
254 assert(get_irn_op(cond) == iro_Cond);
256 for(j = 0; i < block_arity; j++)
258 ir_node *jmp = get_irn_n(block, j);
263 if(get_irn_opcode(jmp) == iro_Jmp)
265 ir_node *jmp_block = get_nodes_block(jmp);
266 if(get_irn_arity(jmp_block) == 1 && get_irn_n(jmp_block)