-static void optimize_lea(ir_node *irn, void *env) {
- ia32_code_gen_t *cg = env;
- ir_node *block, *noreg_gp, *left, *right;
-
- if (! is_ia32_irn(irn))
- return;
-
- /* Following cases can occur: */
- /* - Sub (l, imm) -> LEA [base - offset] */
- /* - Sub (l, r == LEA with ia32_am_O) -> LEA [base - offset] */
- /* - Add (l, imm) -> LEA [base + offset] */
- /* - Add (l, r == LEA with ia32_am_O) -> LEA [base + offset] */
- /* - Add (l == LEA with ia32_am_O, r) -> LEA [base + offset] */
- /* - Add (l, r) -> LEA [base + index * scale] */
- /* with scale > 1 iff l/r == shl (1,2,3) */
-
- if (is_ia32_Sub(irn) || is_ia32_Add(irn)) {
- left = get_irn_n(irn, 2);
- right = get_irn_n(irn, 3);
- block = get_nodes_block(irn);
- noreg_gp = ia32_new_NoReg_gp(cg);
-
- /* Do not try to create a LEA if one of the operands is a Load. */
- /* check is irn is a candidate for address calculation */
- if (is_addr_candidate(block, irn)) {
- ir_node *res;
-
- DBG((cg->mod, LEVEL_1, "\tfound address calculation candidate %+F ... ", irn));
- res = fold_addr(cg, irn, noreg_gp);
-
- if (res != irn)
- DB((cg->mod, LEVEL_1, "transformed into %+F\n", res));
- else
- DB((cg->mod, LEVEL_1, "not transformed\n"));
- }
- }
- else if (is_ia32_Ld(irn) || is_ia32_St(irn) || is_ia32_Store8Bit(irn)) {
- /* - Load -> LEA into Load } TODO: If the LEA is used by more than one Load/Store */
- /* - Store -> LEA into Store } it might be better to keep the LEA */
- left = get_irn_n(irn, 0);
-
- if (is_ia32_Lea(left)) {
- const ir_edge_t *edge, *ne;
- ir_node *src;
-
- /* merge all Loads/Stores connected to this LEA with the LEA */
- foreach_out_edge_safe(left, edge, ne) {
- src = get_edge_src_irn(edge);
-
- if (src && (is_ia32_Ld(src) || is_ia32_St(src) || is_ia32_Store8Bit(src))) {
- DBG((cg->mod, LEVEL_1, "\nmerging %+F into %+F\n", left, irn));
- if (! is_ia32_got_lea(src))
- merge_loadstore_lea(src, left);
- set_ia32_got_lea(src);
- }
- }
- }
- }