13 #include "../firm2arch_nodes_attr.h"
14 #include "../bearch_firm.h"
15 #include "transform.h"
16 #include "new_nodes.h"
20 /* determine if one operator is an Imm */
21 ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
23 return is_Imm(op1) ? op1 : (is_Imm(op2) ? op2 : NULL);
24 else return is_Imm(op2) ? op2 : NULL;
27 /* determine if one operator is not an Imm */
28 ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
29 return !is_Imm(op1) ? op1 : (!is_Imm(op2) ? op2 : NULL);
35 * Creates an ia32 Add with immediate.
38 * @param block the block the new node should belong to
39 * @param expr_op operator
40 * @param mode node mode
41 * @return the created ia23 Add_i node
43 ir_node *gen_imm_Add(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
45 tarval *tv = get_Immop_tarval(const_op);
47 tarval_classification_t class_tv, class_negtv;
49 /* const_op: tarval or SymConst? */
51 /* optimize tarvals */
52 class_tv = classify_tarval(tv);
53 class_negtv = classify_tarval(tarval_neg(tv));
55 if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
56 new_op = new_rd_ia32_Inc(dbg, current_ir_graph, block, expr_op, mode);
58 else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == Sub */
59 new_op = new_rd_ia32_Dec(dbg, current_ir_graph, block, expr_op, mode);
68 new_op = new_rd_ia32_Lea_i(dbg, current_ir_graph, block, expr_op, mode);
74 * Creates an ia32 Add.
76 * @param dbg firm node dbg
77 * @param block the block the new node should belong to
78 * @param op1 first operator
79 * @param op2 second operator
80 * @param mode node mode
81 * @return the created ia32 Add node
83 ir_node *gen_Add(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
84 /* try to optimize with LEA */
85 ir_node *shli_op = is_ia32_Shl_i(op1) ? op1 : (is_ia32_Shl_i(op2) ? op2 : NULL);
86 ir_node *expr_op = shli_op == op1 ? op2 : (shli_op == op2 ? op1 : NULL);
91 tarval *tv = get_Immop_tarval(shli_op);
94 switch (get_tarval_long(tv)) {
98 // If the other operand of the LEA is an LEA_i (that means LEA ofs(%regop1)),
99 // we can skip it and transform the whole sequence into LEA ofs(%regop1, %regop2, shl_val),
100 if (is_ia32_Lea_i(expr_op)) {
101 offs = get_Immop_tarval(expr_op);
102 expr_op = get_irn_n(expr_op, 0);
105 new_op = new_rd_ia32_Lea(dbg, current_ir_graph, block, expr_op, get_irn_n(shli_op, 0), mode);
106 set_Immop_attr_tv(new_op, tv);
109 set_ia32_Lea_offs(new_op, offs);
124 new_op = new_rd_ia32_Lea(dbg, current_ir_graph, block, op1, op2, mode);
125 set_Immop_attr_tv(new_op, get_tarval_one(mode));
126 set_ia32_Lea_offs(new_op, NULL);
135 * Creates an ia32 Mul with immediate.
137 * @param dbg firm dbg
138 * @param block the block the new node should belong to
139 * @param expr_op operator
140 * @param mode node mode
141 * @return the created ia23 Mul_i node
143 ir_node *gen_imm_Mul(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
144 return new_rd_ia32_Mul_i(dbg, current_ir_graph, block, expr_op, mode);
148 * Creates an ia32 Mul.
150 * @param dbg firm node dbg
151 * @param block the block the new node should belong to
152 * @param op1 first operator
153 * @param op2 second operator
154 * @param mode node mode
155 * @return the created ia32 Mul node
157 ir_node *gen_Mul(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
158 return new_rd_ia32_Mul(dbg, current_ir_graph, block, op1, op2, mode);
164 * Creates an ia32 And with immediate.
166 * @param dbg firm dbg
167 * @param block the block the new node should belong to
168 * @param expr_op operator
169 * @param mode node mode
170 * @return the created ia23 And_i node
172 ir_node *gen_imm_And(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
173 return new_rd_ia32_And_i(dbg, current_ir_graph, block, expr_op, mode);
177 * Creates an ia32 And.
179 * @param dbg firm node dbg
180 * @param block the block the new node should belong to
181 * @param op1 first operator
182 * @param op2 second operator
183 * @param mode node mode
184 * @return the created ia32 And node
186 ir_node *gen_And(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
187 return new_rd_ia32_And(dbg, current_ir_graph, block, op1, op2, mode);
193 * Creates an ia32 Or with immediate.
195 * @param dbg firm dbg
196 * @param block the block the new node should belong to
197 * @param expr_op operator
198 * @param mode node mode
199 * @return the created ia23 Or_i node
201 ir_node *gen_imm_Or(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
202 return new_rd_ia32_Or_i(dbg, current_ir_graph, block, expr_op, mode);
206 * Creates an ia32 Or.
208 * @param dbg firm node dbg
209 * @param block the block the new node should belong to
210 * @param op1 first operator
211 * @param op2 second operator
212 * @param mode node mode
213 * @return the created ia32 Or node
215 ir_node *gen_Or(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
216 return new_rd_ia32_Or(dbg, current_ir_graph, block, op1, op2, mode);
222 * Creates an ia32 Eor with immediate.
224 * @param dbg firm dbg
225 * @param block the block the new node should belong to
226 * @param expr_op operator
227 * @param mode node mode
228 * @return the created ia23 Eor_i node
230 ir_node *gen_imm_Eor(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
231 return new_rd_ia32_Eor_i(dbg, current_ir_graph, block, expr_op, mode);
235 * Creates an ia32 Eor.
237 * @param dbg firm node dbg
238 * @param block the block the new node should belong to
239 * @param op1 first operator
240 * @param op2 second operator
241 * @param mode node mode
242 * @return the created ia32 Eor node
244 ir_node *gen_Eor(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
245 return new_rd_ia32_Eor(dbg, current_ir_graph, block, op1, op2, mode);
251 * Creates an ia32 Cmp with immediate.
253 * @param dbg firm dbg
254 * @param block the block the new node should belong to
255 * @param expr_op operator
256 * @param mode node mode
257 * @return the created ia23 Cmp_i node
259 ir_node *gen_imm_Cmp(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
260 return new_rd_ia32_Cmp_i(dbg, current_ir_graph, block, expr_op, mode);
264 * Creates an ia32 Cmp.
266 * @param dbg firm node dbg
267 * @param block the block the new node should belong to
268 * @param op1 first operator
269 * @param op2 second operator
270 * @param mode node mode
271 * @return the created ia32 Cmp node
273 ir_node *gen_Cmp(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
274 return new_rd_ia32_Cmp(dbg, current_ir_graph, block, op1, op2, mode);
280 * Creates an ia32 Sub with immediate.
282 * @param dbg firm dbg
283 * @param block the block the new node should belong to
284 * @param expr_op operator
285 * @param mode node mode
286 * @return the created ia23 Sub_i node
288 ir_node *gen_imm_Sub(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
290 tarval *tv = get_Immop_tarval(const_op);
292 tarval_classification_t class_tv, class_negtv;
294 /* const_op: tarval or SymConst? */
296 /* optimize tarvals */
297 class_tv = classify_tarval(tv);
298 class_negtv = classify_tarval(tarval_neg(tv));
300 if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */
301 new_op = new_rd_ia32_Dec(dbg, current_ir_graph, block, expr_op, mode);
303 else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */
304 new_op = new_rd_ia32_Inc(dbg, current_ir_graph, block, expr_op, mode);
313 new_op = new_rd_ia32_Sub_i(dbg, current_ir_graph, block, expr_op, mode);
319 * Creates an ia32 Sub.
321 * @param dbg firm node dbg
322 * @param block the block the new node should belong to
323 * @param op1 first operator
324 * @param op2 second operator
325 * @param mode node mode
326 * @return the created ia32 Sub node
328 ir_node *gen_Sub(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
331 /* transform "const - expr" into "-expr + const" */
332 if (is_Imm(op1) && !is_Imm(op2)) {
333 DBG((mod, LEVEL_1, "optimizing c-e into -e+c ... "));
335 sub = new_rd_ia32_Minus(dbg, current_ir_graph, block, op2, mode);
336 sub = gen_imm_Add(dbg, block, sub, op1, mode);
337 set_Immop_attr(sub, op1);
340 sub = new_rd_ia32_Sub(dbg, current_ir_graph, block, op1, op2, mode);
349 * Creates an ia32 Mod with immediate.
351 * @param dbg firm dbg
352 * @param block the block the new node should belong to
353 * @param expr_op operator
354 * @param mode node mode
355 * @return the created ia23 Mod_i node
357 ir_node *gen_imm_Mod(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
358 return new_rd_ia32_Mod_i(dbg, current_ir_graph, block, expr_op, mode);
362 * Creates an ia32 Mod.
364 * @param dbg firm node dbg
365 * @param block the block the new node should belong to
366 * @param op1 first operator
367 * @param op2 second operator
368 * @param mode node mode
369 * @return the created ia32 Mod node
371 ir_node *gen_Mod(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
372 return new_rd_ia32_Mod(dbg, current_ir_graph, block, op1, op2, mode);
378 * Creates an ia32 Shl with immediate.
380 * @param dbg firm dbg
381 * @param block the block the new node should belong to
382 * @param expr_op operator
383 * @param mode node mode
384 * @return the created ia23 Shl_i node
386 ir_node *gen_imm_Shl(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
387 return new_rd_ia32_Shl_i(dbg, current_ir_graph, block, expr_op, mode);
391 * Creates an ia32 Shl.
393 * @param dbg firm node dbg
394 * @param block the block the new node should belong to
395 * @param op1 first operator
396 * @param op2 second operator
397 * @param mode node mode
398 * @return the created ia32 Shl node
400 ir_node *gen_Shl(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
401 return new_rd_ia32_Shl(dbg, current_ir_graph, block, op1, op2, mode);
407 * Creates an ia32 Shr with immediate.
409 * @param dbg firm dbg
410 * @param block the block the new node should belong to
411 * @param expr_op operator
412 * @param mode node mode
413 * @return the created ia23 Shr_i node
415 ir_node *gen_imm_Shr(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
416 return new_rd_ia32_Shr_i(dbg, current_ir_graph, block, expr_op, mode);
420 * Creates an ia32 Shr.
422 * @param dbg firm node dbg
423 * @param block the block the new node should belong to
424 * @param op1 first operator
425 * @param op2 second operator
426 * @param mode node mode
427 * @return the created ia32 Shr node
429 ir_node *gen_Shr(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
430 return new_rd_ia32_Shr(dbg, current_ir_graph, block, op1, op2, mode);
436 * Creates an ia32 Shrs with immediate.
438 * @param dbg firm dbg
439 * @param block the block the new node should belong to
440 * @param expr_op operator
441 * @param mode node mode
442 * @return the created ia23 Shrs_i node
444 ir_node *gen_imm_Shrs(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
445 return new_rd_ia32_Shrs_i(dbg, current_ir_graph, block, expr_op, mode);
449 * Creates an ia32 Shrs.
451 * @param dbg firm node dbg
452 * @param block the block the new node should belong to
453 * @param op1 first operator
454 * @param op2 second operator
455 * @param mode node mode
456 * @return the created ia32 Shrs node
458 ir_node *gen_Shrs(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
459 return new_rd_ia32_Shrs(dbg, current_ir_graph, block, op1, op2, mode);
465 * Creates an ia32 Rot with immediate.
467 * @param dbg firm dbg
468 * @param block the block the new node should belong to
469 * @param expr_op operator
470 * @param mode node mode
471 * @return the created ia23 Rot_i node
473 ir_node *gen_imm_Rot(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_node *const_op, ir_mode *mode) {
474 return new_rd_ia32_Rot_i(dbg, current_ir_graph, block, expr_op, mode);
478 * Creates an ia32 Rot.
480 * @param dbg firm node dbg
481 * @param block the block the new node should belong to
482 * @param op1 first operator
483 * @param op2 second operator
484 * @param mode node mode
485 * @return the created ia32 Rot node
487 ir_node *gen_Rot(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
488 return new_rd_ia32_Rot(dbg, current_ir_graph, block, op1, op2, mode);
494 * Transforms a Minus node.
496 * @param mod the debug module
497 * @param block the block the new node should belong to
498 * @param node the ir Minus node
500 * @param mode node mode
501 * @return the created ia32 Minus node
503 ir_node *gen_Minus(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
504 if (is_ia32_Minus(op)) {
505 DBG((mod, LEVEL_1, "optimizing --(e) to e ..."));
506 return get_irn_n(op, 0);
509 return new_rd_ia32_Minus(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
515 * Transforms a Conv node.
517 * @param mod the debug module
518 * @param block the block the new node should belong to
519 * @param node the ir Conv node
521 * @param mode node mode
522 * @return the created ia32 Conv node
524 ir_node *gen_Conv(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
525 return new_rd_ia32_Conv(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
531 * Transforms commutative operations (op_Add, op_Mul, op_And, op_Or, op_Eor, op_Cmp)
532 * and non-commutative operations with com == 0 (op_Sub, op_Mod, op_Shl, op_Shr, op_Shrs, op_Rot)
534 * @param mod the debug module
535 * @param block the block node belongs to
536 * @param node the node to transform
537 * @param op1 first operator
538 * @param op2 second operator
539 * @param mode node mode
540 * @param com flag if op is commutative
541 * @return the created assembler node
543 ir_node *gen_arith_Op(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op1, ir_node *op2, ir_mode *mode, int com) {
544 dbg_info *dbg = get_irn_dbg_info(node);
545 ir_node *imm_op = NULL;
546 ir_node *expr_op = NULL;
547 ir_node *asm_node = NULL;
549 #define GENOP(a) case iro_##a: asm_node = gen_##a(mod, dbg, block, op1, op2, mode); break
550 #define GENOPI(a) case iro_##a: asm_node = gen_imm_##a(dbg, block, expr_op, imm_op, mode); break
553 imm_op = get_immediate_op(op1, op2);
555 imm_op = get_immediate_op(NULL, op2);
557 expr_op = get_expr_op(op1, op2);
559 /* TODO: Op(Imm, Imm) support */
560 if (is_Imm(op1) && is_Imm(op2)) {
561 DBG((mod, LEVEL_1, "found unexpected %s(Imm, Imm), creating binop ... ", get_irn_opname(node)));
565 DBG((mod, LEVEL_1, "(op1: %s -- op2: %s) ... ", get_irn_opname(op1), get_irn_opname(op2)));
568 DBG((mod, LEVEL_1, "%s with imm ... ", get_irn_opname(node)));
570 switch(get_irn_opcode(node)) {
585 assert("binop_i: THIS SHOULD NOT HAPPEN");
588 set_Immop_attr(asm_node, imm_op);
591 DBG((mod, LEVEL_1, "%s as binop ... ", get_irn_opname(node)));
593 switch(get_irn_opcode(node)) {
608 assert("binop: THIS SHOULD NOT HAPPEN");
620 * @param mod the debug module
621 * @param block the block the new node should belong to
622 * @param node the ir Load node
623 * @param mode node mode
624 * @return the created ia32 Load node
626 ir_node *gen_Load(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
627 return new_rd_ia32_Load(get_irn_dbg_info(node), current_ir_graph, block, get_Load_mem(node), get_Load_ptr(node), mode);
633 * Transforms a Store.
635 * @param mod the debug module
636 * @param block the block the new node should belong to
637 * @param node the ir Store node
638 * @param mode node mode
639 * @return the created ia32 Store node
641 ir_node *gen_Store(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
642 return new_rd_ia32_Store(get_irn_dbg_info(node), current_ir_graph, block, get_Store_mem(node), get_Store_ptr(node), get_Store_value(node), mode);
648 * Transforms the given firm node (and maybe some other related nodes)
649 * into one or more assembler nodes.
651 * @param node the firm node
652 * @param env the debug module
654 void transform_node(ir_node *node, void *env) {
655 firm_dbg_module_t *mod = (firm_dbg_module_t *)env;
656 opcode code = get_irn_opcode(node);
657 ir_node *asm_node = NULL;
664 block = get_nodes_block(node);
665 mode = get_irn_mode(node);
667 #define BINOP_COM(a) case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 1); break
668 #define BINOP_NCOM(a) case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 0); break
669 #define UNOP(a) case iro_##a: asm_node = gen_##a(mod, block, node, get_irn_n(node, 0), mode); break
670 #define GEN(a) case iro_##a: asm_node = gen_##a(mod, block, node, mode); break
671 #define IGN(a) case iro_##a: break
673 DBG((mod, LEVEL_1, "transforming node %s (%ld) ... ", get_irn_opname(node), get_irn_node_nr(node)));
689 // BINOP_ARITH_NCOM(DivMod);
702 exchange(node, asm_node);
703 DBG((mod, LEVEL_1, "created node %u\n", get_irn_node_nr(asm_node)));
706 DBG((mod, LEVEL_1, "ignored\n"));