remove unnecessary comments before functions
[libfirm] / ir / ana / irconsconfirm.c
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    Construction of Confirm nodes
23  * @author   Michael Beck
24  * @date     6.2005
25  */
26 #include "config.h"
27
28 #include "irconsconfirm.h"
29
30 #include "irgraph_t.h"
31 #include "irnode_t.h"
32 #include "ircons_t.h"
33 #include "irgmod.h"
34 #include "iropt_dbg.h"
35 #include "iredges_t.h"
36 #include "irgwalk.h"
37 #include "irprintf.h"
38 #include "irgopt.h"
39 #include "irpass.h"
40 #include "irtools.h"
41 #include "array_t.h"
42 #include "debug.h"
43 #include "error.h"
44 #include "irflag.h"
45 #include "opt_manage.h"
46
47 /**
48  * Walker environment.
49  */
50 typedef struct env_t {
51         unsigned num_confirms;  /**< Number of inserted Confirm nodes. */
52         unsigned num_consts;    /**< Number of constants placed. */
53         unsigned num_eq;        /**< Number of equalities placed. */
54         unsigned num_non_null;  /**< Number of non-null Confirms. */
55 } env_t;
56
57 /** The debug handle. */
58 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
59
60 /**
61  * Return the effective use block of a node and its predecessor on
62  * position pos.
63  *
64  * @param node  the node
65  * @param pos   the position of the used input
66  *
67  * This handles correctly Phi nodes.
68  */
69 static ir_node *get_effective_use_block(ir_node *node, int pos)
70 {
71         if (is_Phi(node)) {
72                 /* the effective use of a Phi argument is in its predecessor block */
73                 node = get_nodes_block(node);
74                 return get_Block_cfgpred_block(node, pos);
75         }
76         return get_nodes_block(node);
77 }
78
79 static ir_node *get_case_value(ir_node *switchn, long pn)
80 {
81         ir_graph              *irg       = get_irn_irg(switchn);
82         const ir_switch_table *table     = get_Switch_table(switchn);
83         size_t                 n_entries = ir_switch_table_get_n_entries(table);
84         ir_tarval             *val       = NULL;
85         size_t                 e;
86         for (e = 0; e < n_entries; ++e) {
87                 const ir_switch_table_entry *entry
88                         = ir_switch_table_get_entry_const(table, e);
89                 if (entry->pn != pn)
90                         continue;
91                 /* multiple matching entries gets too complicated for a single
92                  * Confirm */
93                 if (val != NULL)
94                         return NULL;
95                 /* case ranges are too complicated too */
96                 if (entry->min != entry->max)
97                         return NULL;
98                 val = entry->min;
99         }
100         assert(val != NULL);
101         return new_r_Const(irg, val);
102 }
103
104 /**
105  * Handle a CASE-branch.
106  *
107  * Branch labels are a simple case. We can replace the value
108  * by a Const with the branch label.
109  */
110 static void handle_case(ir_node *block, ir_node *switchn, long pn, env_t *env)
111 {
112         ir_node         *c = NULL;
113         ir_node         *selector = get_Switch_selector(switchn);
114         const ir_edge_t *edge;
115         const ir_edge_t *next;
116
117         /* we can't do usefull things with the default label */
118         if (pn == pn_Switch_default)
119                 return;
120
121         foreach_out_edge_safe(selector, edge, next) {
122                 ir_node *succ = get_edge_src_irn(edge);
123                 int     pos   = get_edge_src_pos(edge);
124                 ir_node *blk  = get_effective_use_block(succ, pos);
125
126                 if (block_dominates(block, blk)) {
127                         /*
128                          * Ok, we found a user of irn that is placed
129                          * in a block dominated by the branch block.
130                          * We can replace the input with the Constant
131                          * branch label.
132                          */
133                         if (c == NULL)
134                                 c = get_case_value(switchn, pn);
135
136                         set_irn_n(succ, pos, c);
137                         DBG_OPT_CONFIRM_C(selector, c);
138                         DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, succ, c));
139
140                         env->num_consts += 1;
141                 }
142         }
143 }
144
145 /**
146  * Handle a mode_b input of Cond nodes.
147  *
148  * @param block     the block which is entered by the branch
149  * @param selector  the mode_b node expressing the branch condition
150  * @param pnc       the true/false condition branch
151  * @param env       statistical environment
152  */
153 static void handle_modeb(ir_node *block, ir_node *selector, pn_Cond pnc, env_t *env)
154 {
155         ir_node *cond, *old, *other_blk = NULL, *con = NULL;
156         ir_node *c_b = NULL, *c_o = NULL;
157         const ir_edge_t *edge, *next;
158
159         for (edge = get_irn_out_edge_first(selector); edge; edge = next) {
160                 ir_node *user     = get_edge_src_irn(edge);
161                 int     pos       = get_edge_src_pos(edge);
162                 ir_node *user_blk = get_effective_use_block(user, pos);
163
164                 next = get_irn_out_edge_next(selector, edge);
165                 if (block_dominates(block, user_blk)) {
166                         /*
167                          * Ok, we found a usage of selector in a block
168                          * dominated by the branch block.
169                          * We can replace the input with true/false.
170                          */
171                         if (con == NULL) {
172                                 ir_graph *irg = get_irn_irg(block);
173                                 con = new_r_Const(irg, pnc == pn_Cond_true ? tarval_b_true : tarval_b_false);
174                         }
175                         old = get_irn_n(user, pos);
176                         set_irn_n(user, pos, con);
177                         DBG_OPT_CONFIRM_C(old, con);
178
179                         DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, user, con));
180
181                         env->num_consts += 1;
182                 } else {
183                         int i, n;
184
185                         /* get the other block */
186                         if (other_blk == NULL) {
187                                 /* we have already tested, that block has only ONE Cond predecessor */
188                                 cond = get_Proj_pred(get_Block_cfgpred(block, 0));
189                                 foreach_out_edge(cond, edge) {
190                                         ir_node *proj = get_edge_src_irn(edge);
191                                         if (get_Proj_proj(proj) == (long)pnc)
192                                                 continue;
193                                         edge = get_irn_out_edge_first(proj);
194                                         other_blk = get_edge_src_irn(edge);
195                                         break;
196                                 }
197                                 assert(other_blk);
198
199                                 /*
200                                  * Note the special case here: if block is a then, there might be no else
201                                  * block. In that case the other_block is the user_blk itself and pred_block
202                                  * is the cond_block ...
203                                  *
204                                  * Best would be to introduce a block here, removing this critical edge.
205                                  * For some reasons I cannot repair dominance here, so I have to remove
206                                  * ALL critical edges...
207                                  * FIXME: This should not be needed if we could repair dominance ...
208                                  */
209                         }
210
211                         n = get_Block_n_cfgpreds(user_blk);
212
213                         /*
214                          * We have found a user in a non-dominated block:
215                          * check, if all its block predecessors are dominated.
216                          * If yes, place a Phi.
217                          */
218                         for (i = n - 1; i >= 0; --i) {
219                                 ir_node *pred_blk = get_Block_cfgpred_block(user_blk, i);
220
221                                 if (!block_dominates(block, pred_blk) &&
222                                     !block_dominates(other_blk, pred_blk)) {
223                                         /* can't do anything */
224                                         break;
225                                 }
226                         }
227                         if (i < 0) {
228                                 ir_node *phi, **in;
229
230                                 NEW_ARR_A(ir_node *, in, n);
231                                 /* ok, ALL predecessors are either dominated by block OR other block */
232                                 if (c_b == NULL) {
233                                         ir_graph *irg    = get_irn_irg(block);
234                                         ir_node *c_true  = new_r_Const(irg, tarval_b_true);
235                                         ir_node *c_false = new_r_Const(irg, tarval_b_false);
236                                         env->num_consts += 2;
237                                         if (pnc == pn_Cond_true) {
238                                                 c_b = c_true;
239                                                 c_o = c_false;
240                                         } else {
241                                                 c_b = c_false;
242                                                 c_o = c_true;
243                                         }
244                                 }
245                                 for (i = n - 1; i >= 0; --i) {
246                                         ir_node *pred_blk = get_Block_cfgpred_block(user_blk, i);
247
248                                         if (block_dominates(block, pred_blk))
249                                                 in[i] = c_b;
250                                         else
251                                                 in[i] = c_o;
252                                 }
253                                 phi = new_r_Phi(user_blk, n, in, mode_b);
254                                 set_irn_n(user, pos, phi);
255                                 env->num_eq += 1;
256                         }
257                 }
258         }
259 }
260
261 /**
262  * Handle an IF-branch.
263  *
264  * @param block   the block which is entered by the branch
265  * @param cmp     the Cmp node expressing the branch condition
266  * @param rel     the Compare relation for taking this branch
267  * @param env     statistical environment
268  */
269 static void handle_if(ir_node *block, ir_node *cmp, ir_relation rel, env_t *env)
270 {
271         ir_node *left  = get_Cmp_left(cmp);
272         ir_node *right = get_Cmp_right(cmp);
273         ir_node *cond_block;
274         ir_op *op;
275         const ir_edge_t *edge, *next;
276
277         /* Beware of Bads */
278         if (is_Bad(left) || is_Bad(right))
279                 return;
280
281         op = get_irn_op(left);
282
283         /* Do not create Confirm nodes for Cmp(Const, Const) constructs.
284            These are removed anyway */
285         if (op == op_Const && is_Const(right))
286                 return;
287
288         /* try to place the constant on the right side for a Confirm */
289         if (op == op_Const || op == op_SymConst) {
290                 ir_node *t = left;
291
292                 left  = right;
293                 right = t;
294
295                 rel = get_inversed_relation(rel);
296         }
297
298         /*
299          * First case: both values are identical.
300          * replace the left one by the right (potentially const) one.
301          */
302         if (rel == ir_relation_equal) {
303                 cond_block = get_Block_cfgpred_block(block, 0);
304                 for (edge = get_irn_out_edge_first(left); edge; edge = next) {
305                         ir_node *user = get_edge_src_irn(edge);
306                         int     pos   = get_edge_src_pos(edge);
307                         ir_node *blk  = get_effective_use_block(user, pos);
308
309                         next = get_irn_out_edge_next(left, edge);
310                         if (block_dominates(block, blk)) {
311                                 /*
312                                  * Ok, we found a usage of left in a block
313                                  * dominated by the branch block.
314                                  * We can replace the input with right.
315                                  */
316                                 set_irn_n(user, pos, right);
317                                 DBG_OPT_CONFIRM(left, right);
318
319                                 DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, user, right));
320
321                                 env->num_eq += 1;
322                         } else if (block_dominates(blk, cond_block)
323                                         && is_Const(right)
324                                         && get_irn_pinned(user) == op_pin_state_floats) {
325                                 /*
326                                  * left == Const and we found a movable user of left in a
327                                  * dominator of the Cond block
328                                  */
329                                 const ir_edge_t *user_edge;
330                                 const ir_edge_t *user_next;
331                                 foreach_out_edge_safe(user, user_edge, user_next) {
332                                         ir_node *usr_of_usr = get_edge_src_irn(user_edge);
333                                         int      npos       = get_edge_src_pos(user_edge);
334                                         ir_node *user_blk   = get_effective_use_block(usr_of_usr, npos);
335
336                                         if (block_dominates(block, user_blk)) {
337                                                 /*
338                                                  * The user of the user is dominated by our true/false
339                                                  * block. So, create a copy of user WITH the constant
340                                                  * replacing its pos'th input.
341                                                  *
342                                                  * This is always good for unop's and might be good
343                                                  * for binops.
344                                                  *
345                                                  * If user has other user in the false/true block, code
346                                                  * placement will move it down.
347                                                  * If there are users in cond block or upper, we create
348                                                  * "redundant ops", because one will have a const op,
349                                                  * the other no const ...
350                                                  */
351                                                 ir_node *new_op = exact_copy(user);
352                                                 set_nodes_block(new_op, block);
353                                                 set_irn_n(new_op, pos, right);
354                                                 set_irn_n(usr_of_usr, npos, new_op);
355                                                 env->num_eq += 1;
356                                         }
357                                 }
358                         }
359                 }
360         } else { /* not ir_relation_equal cases */
361                 ir_node *c = NULL;
362
363                 foreach_out_edge_safe(left, edge, next) {
364                         ir_node *succ = get_edge_src_irn(edge);
365                         int     pos   = get_edge_src_pos(edge);
366                         ir_node *blk  = get_effective_use_block(succ, pos);
367
368                         if (block_dominates(block, blk)) {
369                                 /*
370                                  * Ok, we found a usage of left in a block
371                                  * dominated by the branch block.
372                                  * We can replace the input with a Confirm(left, pnc, right).
373                                  */
374                                 if (! c)
375                                         c = new_r_Confirm(block, left, right, rel);
376
377                                 pos = get_edge_src_pos(edge);
378                                 set_irn_n(succ, pos, c);
379                                 DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, succ, c));
380
381                                 env->num_confirms += 1;
382                         }
383                 }
384
385                 if (! is_Const(right)) {
386                         /* also construct inverse Confirms */
387                         ir_node *rc = NULL;
388
389                         rel = get_inversed_relation(rel);
390                         foreach_out_edge_safe(right, edge, next) {
391                                 ir_node *succ = get_edge_src_irn(edge);
392                                 int     pos;
393                                 ir_node *blk;
394
395                                 if (succ == c)
396                                         continue;
397
398                                 pos  = get_edge_src_pos(edge);
399                                 blk  = get_effective_use_block(succ, pos);
400
401                                 if (block_dominates(block, blk)) {
402                                         /*
403                                          * Ok, we found a usage of right in a block
404                                          * dominated by the branch block.
405                                          * We can replace the input with a Confirm(right, rel^-1, left).
406                                          */
407                                         if (! rc)
408                                                 rc = new_r_Confirm(block, right, left, rel);
409
410                                         pos = get_edge_src_pos(edge);
411                                         set_irn_n(succ, pos, rc);
412                                         DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, succ, rc));
413
414                                         env->num_confirms += 1;
415                                 }
416                         }
417                 }
418         }
419 }
420
421 /**
422  * Pre-block-walker: Called for every block to insert Confirm nodes
423  */
424 static void insert_Confirm_in_block(ir_node *block, void *data)
425 {
426         env_t   *env = (env_t*) data;
427         ir_node *cond;
428         ir_node *proj;
429
430         /*
431          * we can only handle blocks with only ONE control flow
432          * predecessor yet.
433          */
434         if (get_Block_n_cfgpreds(block) != 1)
435                 return;
436
437         proj = get_Block_cfgpred(block, 0);
438         if (! is_Proj(proj))
439                 return;
440
441         cond = get_Proj_pred(proj);
442         if (is_Switch(cond)) {
443                 long proj_nr = get_Proj_proj(proj);
444                 handle_case(block, cond, proj_nr, env);
445         } else if (is_Cond(cond)) {
446                 ir_node *selector = get_Cond_selector(cond);
447                 ir_relation rel;
448
449                 handle_modeb(block, selector, (pn_Cond) get_Proj_proj(proj), env);
450
451                 if (! is_Cmp(selector))
452                         return;
453
454                 rel = get_Cmp_relation(selector);
455
456                 if (get_Proj_proj(proj) != pn_Cond_true) {
457                         /* it's the false branch */
458                         rel = get_negated_relation(rel);
459                 }
460                 DB((dbg, LEVEL_2, "At %+F using %+F Confirm %=\n", block, selector, rel));
461
462                 handle_if(block, selector, rel, env);
463         }
464 }
465
466 /**
467  * Checks if a node is a non-null Confirm.
468  */
469 static int is_non_null_Confirm(const ir_node *ptr)
470 {
471         for (;;) {
472                 if (! is_Confirm(ptr))
473                         break;
474                 if (get_Confirm_relation(ptr) == ir_relation_less_greater) {
475                         ir_node *bound = get_Confirm_bound(ptr);
476
477                         if (is_Const(bound) && is_Const_null(bound))
478                                 return 1;
479                 }
480                 ptr = get_Confirm_value(ptr);
481         }
482         /*
483          * While a SymConst is not a Confirm, it is non-null
484          * anyway. This helps to reduce the number of
485          * constructed Confirms.
486          */
487         if (is_SymConst_addr_ent(ptr))
488                 return 1;
489         return 0;
490 }
491
492 /**
493  * The given pointer will be dereferenced, add non-null Confirms.
494  *
495  * @param ptr    a node representing an address
496  * @param block  the block of the dereferencing instruction
497  * @param env    environment
498  */
499 static void insert_non_null(ir_node *ptr, ir_node *block, env_t *env)
500 {
501         const ir_edge_t *edge, *next;
502         ir_node         *c = NULL;
503
504         foreach_out_edge_safe(ptr, edge, next) {
505                 ir_node *succ = get_edge_src_irn(edge);
506                 int     pos;
507                 ir_node *blk;
508
509
510                 /* for now, we place a Confirm only in front of a Cmp */
511                 if (! is_Cmp(succ))
512                         continue;
513
514                 pos = get_edge_src_pos(edge);
515                 blk = get_effective_use_block(succ, pos);
516
517                 if (block_dominates(block, blk)) {
518                         /*
519                          * Ok, we found a usage of ptr in a block
520                          * dominated by the Load/Store block.
521                          * We can replace the input with a Confirm(ptr, !=, NULL).
522                          */
523                         if (c == NULL) {
524                                 ir_mode  *mode = get_irn_mode(ptr);
525                                 ir_graph *irg  = get_irn_irg(block);
526                                 c = new_r_Const(irg, get_mode_null(mode));
527                                 c = new_r_Confirm(block, ptr, c, ir_relation_less_greater);
528                         }
529
530                         set_irn_n(succ, pos, c);
531                         DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, succ, c));
532
533                         env->num_non_null += 1;
534                         env->num_confirms += 1;
535                 }
536         }
537 }
538
539 /**
540  * Pre-walker: Called for every node to insert Confirm nodes
541  */
542 static void insert_Confirm(ir_node *node, void *data)
543 {
544         ir_node *ptr;
545         env_t   *env = (env_t*) data;
546
547         switch (get_irn_opcode(node)) {
548         case iro_Block:
549                 insert_Confirm_in_block(node, env);
550                 break;
551         case iro_Load:
552                 ptr = get_Load_ptr(node);
553                 if (! is_non_null_Confirm(ptr))
554                         insert_non_null(ptr, get_nodes_block(node), env);
555                 break;
556         case iro_Store:
557                 ptr = get_Store_ptr(node);
558                 if (! is_non_null_Confirm(ptr))
559                         insert_non_null(ptr, get_nodes_block(node), env);
560                 break;
561         default:
562                 break;
563         }
564 }
565
566 /*
567  * Construct Confirm nodes
568  */
569 static ir_graph_state_t do_construct_confirms(ir_graph *irg)
570 {
571         env_t env;
572         FIRM_DBG_REGISTER(dbg, "firm.ana.confirm");
573
574         assert(get_irg_pinned(irg) == op_pin_state_pinned &&
575                "Nodes must be placed to insert Confirms");
576
577         env.num_confirms = 0;
578         env.num_consts   = 0;
579         env.num_eq       = 0;
580         env.num_non_null = 0;
581
582         if (get_opt_global_null_ptr_elimination()) {
583                 /* do global NULL test elimination */
584                 irg_walk_graph(irg, insert_Confirm, NULL, &env);
585         } else {
586                 /* now, visit all blocks and add Confirms where possible */
587                 irg_block_walk_graph(irg, insert_Confirm_in_block, NULL, &env);
588         }
589
590         DB((dbg, LEVEL_1, "# Confirms inserted : %u\n", env.num_confirms));
591         DB((dbg, LEVEL_1, "# Const replacements: %u\n", env.num_consts));
592         DB((dbg, LEVEL_1, "# node equalities   : %u\n", env.num_eq));
593         DB((dbg, LEVEL_1, "# non-null Confirms : %u\n", env.num_non_null));
594         return 0;
595 }
596
597 static optdesc_t opt_confirms = {
598         "confirms",
599         IR_GRAPH_STATE_CONSISTENT_OUT_EDGES
600         | IR_GRAPH_STATE_CONSISTENT_DOMINANCE
601         | IR_GRAPH_STATE_NO_CRITICAL_EDGES,
602         do_construct_confirms
603 };
604
605 void construct_confirms(ir_graph *irg)
606 {
607         perform_irg_optimization(irg, &opt_confirms);
608 }
609
610 ir_graph_pass_t *construct_confirms_pass(const char *name)
611 {
612         return def_graph_pass(name ? name : "confirm", construct_confirms);
613 }
614
615 static void remove_confirm(ir_node *n, void *env)
616 {
617         ir_node *value;
618
619         (void) env;
620         if (!is_Confirm(n))
621                 return;
622
623         value = get_Confirm_value(n);
624         exchange(n, value);
625 }
626
627 void remove_confirms(ir_graph *irg)
628 {
629         irg_walk_graph(irg, NULL, remove_confirm, NULL);
630 }
631
632 ir_graph_pass_t *remove_confirms_pass(const char *name)
633 {
634         return def_graph_pass(name ? name : "rem_confirm", remove_confirms);
635 }