1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19 
20 /**
21  * @file
22  * @brief   Debug macros used in iropt.
23  * @author  Goetz Lindenmaier, Michael Beck
24  */
25 #ifndef FIRM_IR_IROPT_DBG_H
26 #define FIRM_IR_IROPT_DBG_H
27 
28 #include "dbginfo_t.h"
29 #include "irhooks.h"
30 #include "firmstat.h"
31 #include "util.h"
32 
33 /**
34  * Merge the debug info due to dead block elimination.
35  *
36  * @param oldn  the block that it is eliminated
37  * @param n     the new node for this block, may be equal to oldn
38  */
39 #define DBG_OPT_DEAD_BLOCK(oldn, n)                           \
40 	do {                                                      \
41 	  hook_merge_nodes(&n, 1, &oldn, 1, HOOK_OPT_DEAD_BLOCK); \
42 	  __dbg_info_merge_pair(n, oldn, dbg_dead_code);          \
43 	} while(0)
44 
45 
46 /**
47  * Merge the debug info due to a straightening optimization.
48  * Block oldn is merged with n.
49  *
50  * @param oldn  the old block
51  * @param n     the new block the merges with oldn
52  */
53 #define DBG_OPT_STG(oldn, n)                                                 \
54 	do {                                                                     \
55 	  ir_node *ons[2];                                                       \
56 	  ons[0] = oldn;                                                         \
57 	  ons[1] = get_Block_cfgpred(oldn, 0);                                   \
58 	  hook_merge_nodes(&n, 1, ons, ARRAY_SIZE(ons), HOOK_OPT_STG);           \
59 	  __dbg_info_merge_sets(&n, 1, ons, ARRAY_SIZE(ons), dbg_straightening); \
60 	} while(0)
61 
62 /**
63  * Merge the debug info due to an if simplification.
64  *
65  * @param oldn   the old Block
66  * @param proj1  the first ProjX predecessor
67  * @param proj2  the second ProjX predecessor
68  * @param n      the new Block
69  */
70 #define DBG_OPT_IFSIM1(oldn, proj1, proj2, n)                        \
71 	do {                                                             \
72 	  ir_node *ons[4];                                               \
73 	  ons[0] = oldn;                                                 \
74 	  ons[1] = proj1;                                                \
75 	  ons[2] = proj2;                                                \
76 	  ons[3] = get_Proj_pred(proj1);                                 \
77 	  hook_merge_nodes(&n, 1, ons, ARRAY_SIZE(ons), HOOK_OPT_IFSIM); \
78 	  __dbg_info_merge_sets(&n, 1, ons, ARRAY_SIZE(ons), dbg_if_simplification); \
79 	} while(0)
80 
81 /**
82  * Merge the debug info due to an if simplification.
83  * @param oldn   the old Cond
84  * @param n      the new Jmp
85  */
86 #define DBG_OPT_IFSIM2(oldn, n)                              \
87 	do {                                                     \
88 	  hook_merge_nodes(&n, 1, &oldn, 1, HOOK_OPT_IFSIM);     \
89 	  __dbg_info_merge_pair(n, oldn, dbg_if_simplification); \
90 	} while(0)
91 
92 /**
93  * Merge the debug info due to an algebraic_simplification.
94  * A node could be evaluated into a Constant.
95  *
96  * @param oldn  the node
97  * @param n     the new constant holding the value
98  */
99 #define DBG_OPT_CSTEVAL(oldn, n)                                  \
100 	do {                                                          \
101 	  hook_merge_nodes(&n, 1, &oldn, 1, HOOK_OPT_CONST_EVAL);     \
102 	  __dbg_info_merge_pair(n, oldn, dbg_const_eval);             \
103 	} while(0)
104 
105 /**
106  * Merge the debug info due to an algebraic_simplification.
107  *
108  * @param oldn  the old node
109  * @param n     the new node replacing oldn
110  * @param flag  firm statistics option
111  */
112 #define DBG_OPT_ALGSIM0(oldn, n, flag)                              \
113 	do {                                                            \
114 	  hook_merge_nodes(&n, 1, &oldn, 1, (hook_opt_kind)flag);       \
115 	  __dbg_info_merge_pair(n, oldn, dbg_algebraic_simplification); \
116 	} while(0)
117 
118 /**
119  * Merge the debug info due to an algebraic_simplification.
120  *
121  * @param oldn  the old node
122  * @param a     a predecessor of oldn
123  * @param b     a predecessor of oldn
124  * @param n     the new node replacing oldn
125  * @param flag  firm statistics option
126  */
127 #define DBG_OPT_ALGSIM1(oldn, a, b, n, flag)                      \
128 	do {                                                          \
129 	  ir_node *ons[3];                                            \
130 	  ons[0] = oldn;                                              \
131 	  ons[1] = a;                                                 \
132 	  ons[2] = b;                                                 \
133 	  hook_merge_nodes(&n, 1, ons, ARRAY_SIZE(ons), (hook_opt_kind)flag); \
134 	  __dbg_info_merge_sets(&n, 1, ons, ARRAY_SIZE(ons), dbg_algebraic_simplification); \
135 	} while(0)
136 
137 /**
138  * Merge the debug info due to an algebraic_simplification.
139  *
140  * @param oldn  the old node
141  * @param pred  the predecessor of oldn
142  * @param n     the new node replacing oldn
143  * @param flag  firm statistics option
144  */
145 #define DBG_OPT_ALGSIM2(oldn, pred, n, flag)                      \
146 	do {                                                          \
147 	  ir_node *ons[3];                                            \
148 	  ons[0] = oldn;                                              \
149 	  ons[1] = pred;                                              \
150 	  ons[2] = n;                                                 \
151 	  hook_merge_nodes(&n, 1, ons, ARRAY_SIZE(ons), (hook_opt_kind)flag); \
152 	  __dbg_info_merge_sets(&n, 1, ons, ARRAY_SIZE(ons), dbg_algebraic_simplification); \
153 	} while(0)
154 
155 /**
156  * Merge the debug info due to an algebraic_simplification.
157  */
158 #define DBG_OPT_ALGSIM3(oldn, a, n, flag)                         \
159 	do {                                                          \
160 	  ir_node *ons[2];                                            \
161 	  ons[0] = oldn;                                              \
162 	  ons[1] = a;                                                 \
163 	  hook_merge_nodes(&n, 1, ons, ARRAY_SIZE(ons), flag);        \
164 	  __dbg_info_merge_sets(&n, 1, ons, ARRAY_SIZE(ons), dbg_algebraic_simplification); \
165 	} while(0)
166 
167 /**
168  * Merge the debug info due to a Phi optimization.
169  * A Phi node was replaced by one of its input (the only meaningful)
170  *
171  * @param phi  the Phi node that will be replaced
172  * @param n    in Phi Input that will replace Phi
173  */
174 #define DBG_OPT_PHI(phi, n)                                      \
175 	do {                                                         \
176 	  hook_merge_nodes(&n, 1, &phi, 1, HOOK_OPT_PHI);            \
177 	  __dbg_info_merge_sets(&n, 1, &phi, 1, dbg_opt_ssa);        \
178 	} while(0)
179 
180 
181 /**
182  * Merge the debug info due to a Sync optimization.
183  * A Sync node was replaced by one of its input (the only meaningful)
184  *
185  * @param sync  the Sync node that will be replaced
186  * @param n     in Sync Input that will replace Sync
187  */
188 #define DBG_OPT_SYNC(sync, n)                                     \
189 	do {                                                          \
190 	  hook_merge_nodes(&n, 1, &sync, 1, HOOK_OPT_SYNC);           \
191 	  __dbg_info_merge_sets(&n, 1, &sync, 1, dbg_opt_ssa);        \
192 	} while(0)
193 
194 
195 /**
196  * Merge the debug info due to Write-after-Write optimization:
197  * Store oldst will be removed, because Store st overwrites it.
198  *
199  * @param oldst  the old store that will be removed
200  * @param st     the other store that overwrites oldst
201  */
202 #define DBG_OPT_WAW(oldst, st)                                      \
203 	do {                                                            \
204 	  ir_node *ons[2];                                              \
205 	  ons[0] = oldst;                                               \
206 	  ons[1] = st;                                                  \
207 	  hook_merge_nodes(&st, 1, ons, ARRAY_SIZE(ons), HOOK_OPT_WAW); \
208 	  __dbg_info_merge_sets(&st, 1, ons, ARRAY_SIZE(ons), dbg_write_after_write); \
209 	} while(0)
210 
211 /**
212  * Merge the debug info due to Write-after-Read optimization:
213  * A store will be removed because it rite a value just read back.
214  *
215  * @param store  the store that will be removed
216  * @param load   the load that produces the value that store will write back
217  */
218 #define DBG_OPT_WAR(store, load)                                      \
219 	do {                                                              \
220 	  ir_node *ons[2];                                                \
221 	  ons[0] = store;                                                 \
222 	  ons[1] = load;                                                  \
223 	  hook_merge_nodes(&load, 1, ons, ARRAY_SIZE(ons), HOOK_OPT_WAR); \
224 	  __dbg_info_merge_sets(&load, 1, ons, ARRAY_SIZE(ons), dbg_write_after_read); \
225 	} while(0)
226 
227 /**
228  * Merge the debug info due to Read-after-Write optimization:
229  * A load will be replaced by a value that was just stored.
230  *
231  * @param load   the load that will be replaced
232  * @param value  the value that will replace the load
233  */
234 #define DBG_OPT_RAW(load, value)                                       \
235 	do {                                                               \
236 	  ir_node *ons[2];                                                 \
237 	  ons[0] = load;                                                   \
238 	  ons[1] = value;                                                  \
239 	  hook_merge_nodes(&value, 1, ons, ARRAY_SIZE(ons), HOOK_OPT_RAW); \
240 	  __dbg_info_merge_sets(&value, 1, ons, ARRAY_SIZE(ons), dbg_read_after_write); \
241 	} while(0)
242 
243 /**
244  * Merge the debug info due to Read-after-Read optimization:
245  * Load oldld will be replace by a reference to Load ld.
246  *
247  * @param oldld  the old load that can be replaced
248  * @param ld     the load that produces the same values
249  */
250 #define DBG_OPT_RAR(oldld, ld)                                      \
251 	do {                                                            \
252 	  ir_node *ons[2];                                              \
253 	  ons[0] = oldld;                                               \
254 	  ons[1] = ld;                                                  \
255 	  hook_merge_nodes(&ld, 1, ons, ARRAY_SIZE(ons), HOOK_OPT_RAR); \
256 	  __dbg_info_merge_sets(&ld, 1, ons, ARRAY_SIZE(ons), dbg_read_after_read); \
257 	} while(0)
258 
259 /**
260  * Merge the debug info due to Read-a-Const optimization:
261  * Load ld will be replace by a Constant if the value that
262  * will be loaded is known and immutable.
263  *
264  * @param ld  the load
265  * @param c   the constant value that will replace the load's result
266  */
267 #define DBG_OPT_RC(ld, c)                                         \
268 	do {                                                          \
269 	  ir_node *ons[2];                                            \
270 	  ons[0] = ld;                                                \
271 	  ons[1] = c;                                                 \
272 	  hook_merge_nodes(&c, 1, ons, ARRAY_SIZE(ons), HOOK_OPT_RC); \
273 	  __dbg_info_merge_sets(&ld, 1, ons, ARRAY_SIZE(ons), dbg_read_a_const); \
274 	} while(0)
275 
276 /**
277  * Merge the debug info after a tuple optimization.
278  * a Proj(Tuple) is replaced by the associated tuple value.
279  *
280  * @param proj   the Proj node
281  * @param tuple  the Tuple node
282  * @param n      the Proj(Tuple) value
283  */
284 #define DBG_OPT_TUPLE(proj, tuple, n)                                      \
285 	do {                                                                   \
286 	  ir_node *ons[3];                                                     \
287 	  ons[0] = proj;                                                       \
288 	  ons[1] = tuple;                                                      \
289 	  ons[2] = n;                                                          \
290 	  hook_merge_nodes(&n, 1, ons, ARRAY_SIZE(ons), HOOK_OPT_TUPLE);       \
291 	  __dbg_info_merge_sets(&n, 1, ons, ARRAY_SIZE(ons), dbg_opt_auxnode); \
292 	} while(0)
293 
294 /**
295  * Merge the debug info after an Id optimization.
296  * An Id node was replaced by its non-Id predecessor.
297  *
298  * @param id  the Id node
299  * @param n   the predecessor
300  */
301 #define DBG_OPT_ID(id, n)                                                  \
302 	do {                                                                   \
303 	  ir_node *ons[2];                                                     \
304 	  ons[0] = id;                                                         \
305 	  ons[1] = n;                                                          \
306 	  hook_merge_nodes(&n, 1, ons, ARRAY_SIZE(ons), HOOK_OPT_ID);          \
307 	  __dbg_info_merge_sets(&n, 1, ons, ARRAY_SIZE(ons), dbg_opt_auxnode); \
308 	} while(0)
309 
310 /**
311  * Merge the debug info due to common-subexpression elimination.
312  *
313  * @param oldn  the old node
314  * @param n     the node that replaces oldn
315  */
316 #define DBG_OPT_CSE(oldn, n)                                           \
317 	do {                                                               \
318 	  ir_node *ons[2];                                                 \
319 	  ons[0] = oldn;                                                   \
320 	  ons[1] = n;                                                      \
321 	  hook_merge_nodes(&n, 1, ons, ARRAY_SIZE(ons), HOOK_OPT_CSE);     \
322 	  __dbg_info_merge_sets(&n, 1, ons, ARRAY_SIZE(ons), dbg_opt_cse); \
323 	} while(0)
324 
325 /**
326  * Merge the debug info due to polymorphic call optimization.
327  * A Sel node was replaced by a constant.
328  *
329  * @param sel   the Sel node that will be replaced.
330  * @param c     the constant node that replaces sel
331  */
332 #define DBG_OPT_POLY(sel, c)                                                 \
333 	do {                                                                     \
334 	  ir_node *ons[3];                                                       \
335 	  ons[0] = sel;                                                          \
336 	  ons[1] = skip_Proj(get_Sel_ptr(sel));                                  \
337 	  ons[2] = c;                                                            \
338 	  hook_merge_nodes(&c, 1, ons, ARRAY_SIZE(ons), HOOK_OPT_POLY_CALL);     \
339 	  __dbg_info_merge_sets(&c, 1, ons, ARRAY_SIZE(ons), dbg_rem_poly_call); \
340 	} while(0)
341 
342 /**
343  * A node was replaced by another node due to a Confirmation.
344  *
345  * @param oldn  the old node
346  * @param n     the new node
347  */
348 #define DBG_OPT_CONFIRM(oldn, n)                                  \
349 	do {                                                          \
350 	  hook_merge_nodes(&n, 1, &oldn, 1, HOOK_OPT_CONFIRM);        \
351 	  __dbg_info_merge_pair(n, oldn, dbg_opt_confirm);            \
352 	} while(0)
353 
354 /**
355  * A node was replaced by a constant due to a Confimation.
356  *
357  * @param oldn  the old node
358  * @param c     the new constant node
359  */
360 #define DBG_OPT_CONFIRM_C(oldn, c)                                \
361 	do {                                                          \
362 	  hook_merge_nodes(&c, 1, &oldn, 1, HOOK_OPT_CONFIRM_C);      \
363 	  __dbg_info_merge_pair(c, oldn, dbg_opt_confirm);            \
364 	} while(0)
365 
366 /**
367  * A exception exdge was removed due to a Confirmation prove.
368  *
369  * @param oldn  the old node
370  */
371 #define DBG_OPT_EXC_REM(oldn)                                     \
372 	do {                                                          \
373 	  hook_merge_nodes(NULL, 0, &oldn, 1, HOOK_OPT_EXC_REM);      \
374 	} while(0)
375 
376 /**
377  * A node could be evaluated to a value due to a Confirm.
378  * This will lead to a constant evaluation.
379  *
380  * @param n  the node that could be evaluated
381  */
382 #define DBG_EVAL_CONFIRM(n)                                    \
383 	do {                                                       \
384 	  hook_merge_nodes(NULL, 0, (ir_node**)&n, 1, HOOK_OPT_CONFIRM_E);    \
385 	} while(0)
386 
387 /**
388  * Merge the debug info due to a GVN-PRE result.
389  *
390  * @param oldn  the old node
391  * @param n     the new node replacing oldn
392  * @param flag  firm statistics option
393  */
394 #define DBG_OPT_GVN_PRE(oldn, n, flag)                        \
395 	do {                                                      \
396 	  hook_merge_nodes(&n, 1, &oldn, 1, (hook_opt_kind)flag); \
397 	  __dbg_info_merge_pair(n, oldn, dbg_gvn_pre);            \
398 	} while(0)
399 
400 /**
401  * Merge the debug info due to a combo result.
402  *
403  * @param oldn  the old node
404  * @param n     the new node replacing oldn
405  * @param flag  firm statistics option
406  */
407 #define DBG_OPT_COMBO(oldn, n, flag)                          \
408 	do {                                                      \
409 	  hook_merge_nodes(&n, 1, &oldn, 1, (hook_opt_kind)flag); \
410 	  __dbg_info_merge_pair(n, oldn, dbg_combo);              \
411 	} while(0)
412 
413 /**
414  * Merge the debug info due to a jump threading result.
415  *
416  * @param oldn  the old control flow node
417  * @param n     the new control flow node replacing oldn
418  */
419 #define DBG_OPT_JUMPTHREADING(oldn, n)                         \
420 	do {                                                   \
421 	  hook_merge_nodes(&n, 1, &oldn, 1, (hook_opt_kind)FS_OPT_JUMPTHREADING); \
422 	  __dbg_info_merge_pair(n, oldn, dbg_jumpthreading);       \
423 	} while(0)
424 
425 #endif
426