Added subst hook in dead node elimination
[libfirm] / ir / lower / lower_intrinsics.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/lower/lower_intrinsics.c
4  * Purpose:     lowering of Calls of intrinsic functions
5  * Author:      Michael Beck
6  * Created:
7  * CVS-ID:      $Id$
8  * Copyright:   (c) 1998-2005 Universität Karlsruhe
9  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
10  */
11
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #ifdef HAVE_ALLOCA_H
17 #include <alloca.h>
18 #endif
19 #ifdef HAVE_MALLOC_H
20 #include <malloc.h>
21 #endif
22
23 #include "irprog_t.h"
24 #include "irnode_t.h"
25 #include "irgwalk.h"
26 #include "ircons.h"
27 #include "irgmod.h"
28 #include "lower_intrinsics.h"
29 #include "pmap.h"
30
31 /** Walker environment */
32 typedef struct _walker_env {
33   pmap     *map;              /**< the intrinsic map. */
34   unsigned nr_of_intrinsics;  /**< statistics */
35 } walker_env_t;
36
37 /**
38  * walker: do the call mapping
39  */
40 static void call_mapper(ir_node *call, void *env) {
41   walker_env_t *wenv = env;
42   ir_node *symconst;
43   pmap_entry *p;
44   const i_record *r;
45   entity *ent;
46
47   if (! is_Call(call))
48     return;
49
50   symconst = get_Call_ptr(call);
51   if (get_irn_op(symconst) != op_SymConst ||
52       get_SymConst_kind(symconst) != symconst_addr_ent)
53     return;
54
55   ent = get_SymConst_entity(symconst);
56   p   = pmap_find(wenv->map, ent);
57
58   if (p) {
59     r = p->value;
60     wenv->nr_of_intrinsics += r->i_mapper(call, r->ctx) ? 1 : 0;
61   }
62 }
63
64 /* Go through all graphs and map calls to intrinsic functions. */
65 unsigned lower_intrinsic_calls(const i_record *list, int length) {
66   int          i;
67   ir_graph     *irg;
68   pmap         *map = pmap_create_ex(length);
69   walker_env_t wenv;
70   unsigned     nr_of_intrinsics = 0;
71
72   /* fill a map for faster search */
73   for (i = length - 1; i >= 0; --i)
74     pmap_insert(map, list[i].i_ent, (void *)&list[i]);
75
76   wenv.map = map;
77
78   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
79     irg = get_irp_irg(i);
80
81     wenv.nr_of_intrinsics = 0;
82     irg_walk_graph(irg, NULL, call_mapper, map);
83
84     if (wenv.nr_of_intrinsics) {
85       /* changes detected */
86       set_irg_outs_inconsistent(irg);
87       set_irg_callee_info_state(irg, irg_callee_info_inconsistent);
88
89       /* exception control flow might have changed */
90       set_irg_doms_inconsistent(irg);
91       set_irg_loopinfo_inconsistent(irg);
92
93       nr_of_intrinsics += wenv.nr_of_intrinsics;
94     }
95   }
96   pmap_destroy(map);
97
98   return nr_of_intrinsics;
99 }
100
101 /* A mapper for the integer abs. */
102 int i_mapper_Abs(ir_node *call, void *ctx) {
103   ir_node *mem   = get_Call_mem(call);
104   ir_node *block = get_nodes_block(call);
105   ir_node *op    = get_Call_param(call, 0);
106   ir_node *irn;
107   dbg_info *dbg  = get_irn_dbg_info(call);
108
109   irn = new_rd_Abs(dbg, current_ir_graph, block, op, get_irn_mode(op));
110   irn = new_Tuple(1, &irn);
111
112   turn_into_tuple(call, pn_Call_max);
113   set_Tuple_pred(call, pn_Call_M_regular, mem);
114   set_Tuple_pred(call, pn_Call_X_except, new_Bad());
115   set_Tuple_pred(call, pn_Call_T_result, irn);
116   set_Tuple_pred(call, pn_Call_M_except, mem);
117   set_Tuple_pred(call, pn_Call_P_value_res_base, new_Bad());
118
119   return 1;
120 }
121
122 /* A mapper for the alloca() function. */
123 int i_mapper_Alloca(ir_node *call, void *ctx) {
124   ir_node *mem   = get_Call_mem(call);
125   ir_node *block = get_nodes_block(call);
126   ir_node *op    = get_Call_param(call, 0);
127   ir_node *irn, *exc;
128   dbg_info *dbg  = get_irn_dbg_info(call);
129
130   irn = new_rd_Alloc(dbg, current_ir_graph, block, mem, op, firm_unknown_type, stack_alloc);
131   mem = new_Proj(irn, mode_M, pn_Alloc_M);
132   exc = new_Proj(irn, mode_X, pn_Alloc_X_except);
133   irn = new_Proj(irn, get_modeP_data(), pn_Alloc_res);
134   irn = new_Tuple(1, &irn);
135
136   turn_into_tuple(call, pn_Call_max);
137   set_Tuple_pred(call, pn_Call_M_regular, mem);
138   set_Tuple_pred(call, pn_Call_X_except, exc);
139   set_Tuple_pred(call, pn_Call_T_result, irn);
140   set_Tuple_pred(call, pn_Call_M_except, mem);
141   set_Tuple_pred(call, pn_Call_P_value_res_base, new_Bad());
142
143   return 1;
144 }