irconsconfirm.c 16.8 KB
Newer Older
Michael Beck's avatar
Michael Beck committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Matthias Braun's avatar
Matthias Braun committed
3
4
 *
 * This file is part of libFirm.
Michael Beck's avatar
Michael Beck committed
5
 *
Matthias Braun's avatar
Matthias Braun committed
6
7
8
9
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
Michael Beck's avatar
Michael Beck committed
10
 *
Matthias Braun's avatar
Matthias Braun committed
11
12
13
14
15
16
17
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
Michael Beck's avatar
Michael Beck committed
18
 */
19

Matthias Braun's avatar
Matthias Braun committed
20
21
22
23
24
25
26
/**
 * @file
 * @brief    Construction of Confirm nodes
 * @author   Michael Beck
 * @date     6.2005
 * @version  $Id$
 */
Matthias Braun's avatar
Matthias Braun committed
27
#include "config.h"
28

29
30
#include "irconsconfirm.h"

Michael Beck's avatar
Michael Beck committed
31
32
33
34
35
36
#include "irgraph_t.h"
#include "irnode_t.h"
#include "ircons_t.h"
#include "irgmod.h"
#include "iropt_dbg.h"
#include "iredges_t.h"
Michael Beck's avatar
Michael Beck committed
37
#include "irgwalk.h"
Michael Beck's avatar
Michael Beck committed
38
#include "irprintf.h"
39
#include "irgopt.h"
40
#include "irpass.h"
Matthias Braun's avatar
Matthias Braun committed
41
#include "irtools.h"
42
#include "array_t.h"
43
#include "debug.h"
Matthias Braun's avatar
Matthias Braun committed
44
#include "error.h"
45
#include "irflag.h"
Michael Beck's avatar
Michael Beck committed
46
47
48
49

/**
 * Walker environment.
 */
50
typedef struct env_t {
51
52
53
54
	unsigned num_confirms;  /**< Number of inserted Confirm nodes. */
	unsigned num_consts;    /**< Number of constants placed. */
	unsigned num_eq;        /**< Number of equalities placed. */
	unsigned num_non_null;  /**< Number of non-null Confirms. */
Michael Beck's avatar
Michael Beck committed
55
56
} env_t;

57
58
59
/** The debug handle. */
DEBUG_ONLY(static firm_dbg_module_t *dbg;)

60
/**
61
 * Return the effective use block of a node and its predecessor on
62
63
64
65
66
67
68
 * position pos.
 *
 * @param node  the node
 * @param pos   the position of the used input
 *
 * This handles correctly Phi nodes.
 */
69
70
static ir_node *get_effective_use_block(ir_node *node, int pos)
{
71
	if (is_Phi(node)) {
72
73
74
		/* the effective use of a Phi argument is in its predecessor block */
		node = get_nodes_block(node);
		return get_Block_cfgpred_block(node, pos);
75
76
	}
	return get_nodes_block(node);
77
78
}

Matthias Braun's avatar
Matthias Braun committed
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
static ir_node *get_case_value(ir_node *switchn, long pn)
{
	ir_graph              *irg       = get_irn_irg(switchn);
	const ir_switch_table *table     = get_Switch_table(switchn);
	size_t                 n_entries = ir_switch_table_get_n_entries(table);
	ir_tarval             *val       = NULL;
	size_t                 e;
	for (e = 0; e < n_entries; ++e) {
		const ir_switch_table_entry *entry
			= ir_switch_table_get_entry_const(table, e);
		if (entry->pn != pn)
			continue;
		/* multiple matching entries gets too complicated for a single
		 * Confirm */
		if (val != NULL)
			return NULL;
		/* case ranges are too complicated too */
		if (entry->min != entry->max)
			return NULL;
		val = entry->min;
	}
	assert(val != NULL);
	return new_r_Const(irg, val);
}

Michael Beck's avatar
Michael Beck committed
104
105
106
107
108
109
/**
 * Handle a CASE-branch.
 *
 * Branch labels are a simple case. We can replace the value
 * by a Const with the branch label.
 */
Matthias Braun's avatar
Matthias Braun committed
110
static void handle_case(ir_node *block, ir_node *switchn, long pn, env_t *env)
111
{
Matthias Braun's avatar
Matthias Braun committed
112
113
114
115
	ir_node         *c = NULL;
	ir_node         *selector = get_Switch_selector(switchn);
	const ir_edge_t *edge;
	const ir_edge_t *next;
Michael Beck's avatar
Michael Beck committed
116

Matthias Braun's avatar
Matthias Braun committed
117
118
	/* we can't do usefull things with the default label */
	if (pn == pn_Switch_default)
Michael Beck's avatar
Michael Beck committed
119
120
		return;

Matthias Braun's avatar
Matthias Braun committed
121
	foreach_out_edge_safe(selector, edge, next) {
Michael Beck's avatar
Michael Beck committed
122
123
124
125
126
127
128
129
130
131
132
		ir_node *succ = get_edge_src_irn(edge);
		int     pos   = get_edge_src_pos(edge);
		ir_node *blk  = get_effective_use_block(succ, pos);

		if (block_dominates(block, blk)) {
			/*
			 * Ok, we found a user of irn that is placed
			 * in a block dominated by the branch block.
			 * We can replace the input with the Constant
			 * branch label.
			 */
Matthias Braun's avatar
Matthias Braun committed
133
134
			if (c == NULL)
				c = get_case_value(switchn, pn);
Michael Beck's avatar
Michael Beck committed
135
136

			set_irn_n(succ, pos, c);
Matthias Braun's avatar
Matthias Braun committed
137
			DBG_OPT_CONFIRM_C(selector, c);
138
			DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, succ, c));
Michael Beck's avatar
Michael Beck committed
139
140
141
142

			env->num_consts += 1;
		}
	}
143
}
Michael Beck's avatar
Michael Beck committed
144

145
146
147
148
149
150
151
152
/**
 * Handle a mode_b input of Cond nodes.
 *
 * @param block     the block which is entered by the branch
 * @param selector  the mode_b node expressing the branch condition
 * @param pnc       the true/false condition branch
 * @param env       statistical environment
 */
153
154
static void handle_modeb(ir_node *block, ir_node *selector, pn_Cond pnc, env_t *env)
{
155
	ir_node *cond, *old, *other_blk = NULL, *con = NULL;
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
	ir_node *c_b = NULL, *c_o = NULL;
	const ir_edge_t *edge, *next;

	for (edge = get_irn_out_edge_first(selector); edge; edge = next) {
		ir_node *user     = get_edge_src_irn(edge);
		int     pos       = get_edge_src_pos(edge);
		ir_node *user_blk = get_effective_use_block(user, pos);

		next = get_irn_out_edge_next(selector, edge);
		if (block_dominates(block, user_blk)) {
			/*
			 * Ok, we found a usage of selector in a block
			 * dominated by the branch block.
			 * We can replace the input with true/false.
			 */
			if (con == NULL) {
172
173
				ir_graph *irg = get_irn_irg(block);
				con = new_r_Const(irg, pnc == pn_Cond_true ? tarval_b_true : tarval_b_false);
174
175
176
177
178
			}
			old = get_irn_n(user, pos);
			set_irn_n(user, pos, con);
			DBG_OPT_CONFIRM_C(old, con);

179
			DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, user, con));
180
181
182
183
184
185
186
187
188
189
190

			env->num_consts += 1;
		} else {
			int i, n;

			/* get the other block */
			if (other_blk == NULL) {
				/* we have already tested, that block has only ONE Cond predecessor */
				cond = get_Proj_pred(get_Block_cfgpred(block, 0));
				foreach_out_edge(cond, edge) {
					ir_node *proj = get_edge_src_irn(edge);
191
					if (get_Proj_proj(proj) == (long)pnc)
192
193
194
195
196
197
						continue;
					edge = get_irn_out_edge_first(proj);
					other_blk = get_edge_src_irn(edge);
					break;
				}
				assert(other_blk);
198

199
				/*
200
201
202
203
				 * Note the special case here: if block is a then, there might be no else
				 * block. In that case the other_block is the user_blk itself and pred_block
				 * is the cond_block ...
				 *
204
				 * Best would be to introduce a block here, removing this critical edge.
205
206
207
208
				 * For some reasons I cannot repair dominance here, so I have to remove
				 * ALL critical edges...
				 * FIXME: This should not be needed if we could repair dominance ...
				 */
209
210
211
212
213
214
215
216
217
218
219
220
			}

			n = get_Block_n_cfgpreds(user_blk);

			/*
			 * We have found a user in a non-dominated block:
			 * check, if all its block predecessors are dominated.
			 * If yes, place a Phi.
			 */
			for (i = n - 1; i >= 0; --i) {
				ir_node *pred_blk = get_Block_cfgpred_block(user_blk, i);

221
222
				if (!block_dominates(block, pred_blk) &&
				    !block_dominates(other_blk, pred_blk)) {
223
224
225
226
227
228
229
230
231
232
					/* can't do anything */
					break;
				}
			}
			if (i < 0) {
				ir_node *phi, **in;

				NEW_ARR_A(ir_node *, in, n);
				/* ok, ALL predecessors are either dominated by block OR other block */
				if (c_b == NULL) {
233
234
235
					ir_graph *irg    = get_irn_irg(block);
					ir_node *c_true  = new_r_Const(irg, tarval_b_true);
					ir_node *c_false = new_r_Const(irg, tarval_b_false);
236
					env->num_consts += 2;
237
238
239
240
241
242
243
					if (pnc == pn_Cond_true) {
						c_b = c_true;
						c_o = c_false;
					} else {
						c_b = c_false;
						c_o = c_true;
					}
244
245
246
247
248
249
250
251
252
				}
				for (i = n - 1; i >= 0; --i) {
					ir_node *pred_blk = get_Block_cfgpred_block(user_blk, i);

					if (block_dominates(block, pred_blk))
						in[i] = c_b;
					else
						in[i] = c_o;
				}
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
			}
		}
	}
}

Michael Beck's avatar
Michael Beck committed
261
262
263
264
265
/**
 * Handle an IF-branch.
 *
 * @param block   the block which is entered by the branch
 * @param cmp     the Cmp node expressing the branch condition
266
 * @param rel     the Compare relation for taking this branch
Michael Beck's avatar
Michael Beck committed
267
268
 * @param env     statistical environment
 */
269
static void handle_if(ir_node *block, ir_node *cmp, ir_relation rel, env_t *env)
270
{
Michael Beck's avatar
Michael Beck committed
271
272
	ir_node *left  = get_Cmp_left(cmp);
	ir_node *right = get_Cmp_right(cmp);
273
	ir_node *cond_block;
Michael Beck's avatar
Michael Beck committed
274
275
276
277
	ir_op *op;
	const ir_edge_t *edge, *next;

	/* Beware of Bads */
278
	if (is_Bad(left) || is_Bad(right))
Michael Beck's avatar
Michael Beck committed
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
		return;

	op = get_irn_op(left);

	/* Do not create Confirm nodes for Cmp(Const, Const) constructs.
	   These are removed anyway */
	if (op == op_Const && is_Const(right))
		return;

	/* try to place the constant on the right side for a Confirm */
	if (op == op_Const || op == op_SymConst) {
		ir_node *t = left;

		left  = right;
		right = t;

295
		rel = get_inversed_relation(rel);
Michael Beck's avatar
Michael Beck committed
296
297
298
299
300
301
	}

	/*
	 * First case: both values are identical.
	 * replace the left one by the right (potentially const) one.
	 */
302
	if (rel == ir_relation_equal) {
303
		cond_block = get_Block_cfgpred_block(block, 0);
Michael Beck's avatar
Michael Beck committed
304
		for (edge = get_irn_out_edge_first(left); edge; edge = next) {
305
			ir_node *user = get_edge_src_irn(edge);
Michael Beck's avatar
Michael Beck committed
306
			int     pos   = get_edge_src_pos(edge);
307
			ir_node *blk  = get_effective_use_block(user, pos);
Michael Beck's avatar
Michael Beck committed
308
309
310
311
312
313
314
315

			next = get_irn_out_edge_next(left, edge);
			if (block_dominates(block, blk)) {
				/*
				 * Ok, we found a usage of left in a block
				 * dominated by the branch block.
				 * We can replace the input with right.
				 */
316
				set_irn_n(user, pos, right);
Michael Beck's avatar
Michael Beck committed
317
318
				DBG_OPT_CONFIRM(left, right);

319
				DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, user, right));
Michael Beck's avatar
Michael Beck committed
320
321

				env->num_eq += 1;
322
323
324
325
326
327
328
			} else if (block_dominates(blk, cond_block)
					&& is_Const(right)
					&& get_irn_pinned(user) == op_pin_state_floats) {
				/*
				 * left == Const and we found a movable user of left in a
				 * dominator of the Cond block
				 */
329
330
331
332
333
334
335
336
				const ir_edge_t *user_edge;
				const ir_edge_t *user_next;
				foreach_out_edge_safe(user, user_edge, user_next) {
					ir_node *usr_of_usr = get_edge_src_irn(user_edge);
					int      npos       = get_edge_src_pos(user_edge);
					ir_node *user_blk   = get_effective_use_block(usr_of_usr, npos);

					if (block_dominates(block, user_blk)) {
337
338
339
						/*
						 * The user of the user is dominated by our true/false
						 * block. So, create a copy of user WITH the constant
340
						 * replacing its pos'th input.
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
						 *
						 * This is always good for unop's and might be good
						 * for binops.
						 *
						 * If user has other user in the false/true block, code
						 * placement will move it down.
						 * If there are users in cond block or upper, we create
						 * "redundant ops", because one will have a const op,
						 * the other no const ...
						 */
						ir_node *new_op = exact_copy(user);
						set_nodes_block(new_op, block);
						set_irn_n(new_op, pos, right);
						set_irn_n(usr_of_usr, npos, new_op);
						env->num_eq += 1;
356
357
					}
				}
Michael Beck's avatar
Michael Beck committed
358
359
			}
		}
360
	} else { /* not ir_relation_equal cases */
Michael Beck's avatar
Michael Beck committed
361
362
		ir_node *c = NULL;

363
		foreach_out_edge_safe(left, edge, next) {
Michael Beck's avatar
Michael Beck committed
364
365
366
367
368
369
370
371
372
373
374
			ir_node *succ = get_edge_src_irn(edge);
			int     pos   = get_edge_src_pos(edge);
			ir_node *blk  = get_effective_use_block(succ, pos);

			if (block_dominates(block, blk)) {
				/*
				 * Ok, we found a usage of left in a block
				 * dominated by the branch block.
				 * We can replace the input with a Confirm(left, pnc, right).
				 */
				if (! c)
375
					c = new_r_Confirm(block, left, right, rel);
Michael Beck's avatar
Michael Beck committed
376
377
378

				pos = get_edge_src_pos(edge);
				set_irn_n(succ, pos, c);
379
				DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, succ, c));
Michael Beck's avatar
Michael Beck committed
380
381
382
383

				env->num_confirms += 1;
			}
		}
384
385
386

		if (! is_Const(right)) {
			/* also construct inverse Confirms */
387
388
			ir_node *rc = NULL;

389
			rel = get_inversed_relation(rel);
390
			foreach_out_edge_safe(right, edge, next) {
391
				ir_node *succ = get_edge_src_irn(edge);
392
393
394
395
396
397
398
399
				int     pos;
				ir_node *blk;

				if (succ == c)
					continue;

				pos  = get_edge_src_pos(edge);
				blk  = get_effective_use_block(succ, pos);
400
401
402
403
404

				if (block_dominates(block, blk)) {
					/*
					 * Ok, we found a usage of right in a block
					 * 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
412
					set_irn_n(succ, pos, rc);
					DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, succ, rc));
413
414
415
416
417

					env->num_confirms += 1;
				}
			}
		}
Michael Beck's avatar
Michael Beck committed
418
	}
419
}
Michael Beck's avatar
Michael Beck committed
420
421

/**
422
 * Pre-block-walker: Called for every block to insert Confirm nodes
Michael Beck's avatar
Michael Beck committed
423
 */
424
static void insert_Confirm_in_block(ir_node *block, void *data)
425
{
426
	env_t   *env = (env_t*) data;
Matthias Braun's avatar
Matthias Braun committed
427
428
	ir_node *cond;
	ir_node *proj;
Michael Beck's avatar
Michael Beck committed
429
430
431
432
433
434
435
436
437

	/*
	 * we can only handle blocks with only ONE control flow
	 * predecessor yet.
	 */
	if (get_Block_n_cfgpreds(block) != 1)
		return;

	proj = get_Block_cfgpred(block, 0);
438
	if (! is_Proj(proj))
Michael Beck's avatar
Michael Beck committed
439
440
441
		return;

	cond = get_Proj_pred(proj);
Matthias Braun's avatar
Matthias Braun committed
442
443
444
445
446
	if (is_Switch(cond)) {
		long proj_nr = get_Proj_proj(proj);
		handle_case(block, cond, proj_nr, env);
	} else if (is_Const(cond)) {
		ir_node *selector = get_Cond_selector(cond);
447
		ir_relation rel;
Michael Beck's avatar
Michael Beck committed
448

449
		handle_modeb(block, selector, (pn_Cond) get_Proj_proj(proj), env);
450

451
		if (! is_Cmp(selector))
Michael Beck's avatar
Michael Beck committed
452
453
			return;

454
		rel = get_Cmp_relation(selector);
Michael Beck's avatar
Michael Beck committed
455
456
457

		if (get_Proj_proj(proj) != pn_Cond_true) {
			/* it's the false branch */
458
			rel = get_negated_relation(rel);
Michael Beck's avatar
Michael Beck committed
459
		}
460
		DB((dbg, LEVEL_2, "At %+F using %+F Confirm %=\n", block, selector, rel));
Michael Beck's avatar
Michael Beck committed
461

462
		handle_if(block, selector, rel, env);
Michael Beck's avatar
Michael Beck committed
463
	}
464
}
465

466
467
468
/**
 * Checks if a node is a non-null Confirm.
 */
469
470
static int is_non_null_Confirm(const ir_node *ptr)
{
471
472
	for (;;) {
		if (! is_Confirm(ptr))
473
			break;
474
		if (get_Confirm_relation(ptr) == ir_relation_less_greater) {
475
476
477
478
479
480
481
			ir_node *bound = get_Confirm_bound(ptr);

			if (is_Const(bound) && is_Const_null(bound))
				return 1;
		}
		ptr = get_Confirm_value(ptr);
	}
482
483
484
485
486
487
488
489
	/*
	 * While a SymConst is not a Confirm, it is non-null
	 * anyway. This helps to reduce the number of
	 * constructed Confirms.
	 */
	if (is_SymConst_addr_ent(ptr))
		return 1;
	return 0;
490
}
491

492
/**
493
 * The given pointer will be dereferenced, add non-null Confirms.
494
495
496
497
498
 *
 * @param ptr    a node representing an address
 * @param block  the block of the dereferencing instruction
 * @param env    environment
 */
499
500
static void insert_non_null(ir_node *ptr, ir_node *block, env_t *env)
{
501
502
503
504
505
506
507
508
509
	const ir_edge_t *edge, *next;
	ir_node         *c = NULL;

	foreach_out_edge_safe(ptr, edge, next) {
		ir_node *succ = get_edge_src_irn(edge);
		int     pos;
		ir_node *blk;


510
511
		/* for now, we place a Confirm only in front of a Cmp */
		if (! is_Cmp(succ))
512
			continue;
513
514
515
516

		pos = get_edge_src_pos(edge);
		blk = get_effective_use_block(succ, pos);

517
		if (block_dominates(block, blk)) {
518
519
520
521
522
523
			/*
			 * Ok, we found a usage of ptr in a block
			 * dominated by the Load/Store block.
			 * We can replace the input with a Confirm(ptr, !=, NULL).
			 */
			if (c == NULL) {
524
525
526
				ir_mode  *mode = get_irn_mode(ptr);
				ir_graph *irg  = get_irn_irg(block);
				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
535
536
			env->num_confirms += 1;
		}
	}
537
}
538
539
540
541

/**
 * Pre-walker: Called for every node to insert Confirm nodes
 */
542
static void insert_Confirm(ir_node *node, void *data)
543
{
544
	ir_node *ptr;
545
	env_t   *env = (env_t*) data;
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563

	switch (get_irn_opcode(node)) {
	case iro_Block:
		insert_Confirm_in_block(node, env);
		break;
	case iro_Load:
		ptr = get_Load_ptr(node);
		if (! is_non_null_Confirm(ptr))
			insert_non_null(ptr, get_nodes_block(node), env);
		break;
	case iro_Store:
		ptr = get_Store_ptr(node);
		if (! is_non_null_Confirm(ptr))
			insert_non_null(ptr, get_nodes_block(node), env);
		break;
	default:
		break;
	}
564
}
Michael Beck's avatar
Michael Beck committed
565
566
567
568

/*
 * Construct Confirm nodes
 */
569
570
void construct_confirms(ir_graph *irg)
{
Michael Beck's avatar
Michael Beck committed
571
572
	env_t env;
	int edges_active = edges_activated(irg);
Michael Beck's avatar
Michael Beck committed
573

574
575
	FIRM_DBG_REGISTER(dbg, "firm.ana.confirm");

576
577
	remove_critical_cf_edges(irg);

Michael Beck's avatar
Michael Beck committed
578
579
	/* we need dominance info */
	assure_doms(irg);
Michael Beck's avatar
Michael Beck committed
580

Michael Beck's avatar
Michael Beck committed
581
582
	assert(get_irg_pinned(irg) == op_pin_state_pinned &&
	       "Nodes must be placed to insert Confirms");
Michael Beck's avatar
Michael Beck committed
583

Michael Beck's avatar
Michael Beck committed
584
585
586
587
	if (! edges_active) {
		/* We need edges */
		edges_activate(irg);
	}
Michael Beck's avatar
Michael Beck committed
588

Michael Beck's avatar
Michael Beck committed
589
590
591
	env.num_confirms = 0;
	env.num_consts   = 0;
	env.num_eq       = 0;
592
	env.num_non_null = 0;
Michael Beck's avatar
Michael Beck committed
593

594
	if (get_opt_global_null_ptr_elimination()) {
595
596
597
598
599
600
		/* do global NULL test elimination */
		irg_walk_graph(irg, insert_Confirm, NULL, &env);
	} else {
		/* now, visit all blocks and add Confirms where possible */
		irg_block_walk_graph(irg, insert_Confirm_in_block, NULL, &env);
	}
Michael Beck's avatar
Michael Beck committed
601

602
603
604
	DB((dbg, LEVEL_1, "# Confirms inserted : %u\n", env.num_confirms));
	DB((dbg, LEVEL_1, "# Const replacements: %u\n", env.num_consts));
	DB((dbg, LEVEL_1, "# node equalities   : %u\n", env.num_eq));
605
	DB((dbg, LEVEL_1, "# non-null Confirms : %u\n", env.num_non_null));
Michael Beck's avatar
Michael Beck committed
606

Michael Beck's avatar
Michael Beck committed
607
608
609
	/* deactivate edges if they where off */
	if (! edges_active)
		edges_deactivate(irg);
610
}
Michael Beck's avatar
Michael Beck committed
611

612
/* Construct a pass. */
613
614
ir_graph_pass_t *construct_confirms_pass(const char *name)
{
615
	return def_graph_pass(name ? name : "confirm", construct_confirms);
616
}
617

618
static void remove_confirm(ir_node *n, void *env)
619
{
620
621
	ir_node *value;

Michael Beck's avatar
Michael Beck committed
622
	(void) env;
623
624
625
626
627
628
	if (!is_Confirm(n))
		return;

	value = get_Confirm_value(n);
	exchange(n, value);
}
Michael Beck's avatar
Michael Beck committed
629
630
631
632

/*
 * Remove all Confirm nodes from a graph.
 */
633
634
void remove_confirms(ir_graph *irg)
{
635
	irg_walk_graph(irg, NULL, remove_confirm, NULL);
636
}
637
638

/* Construct a pass. */
639
640
ir_graph_pass_t *remove_confirms_pass(const char *name)
{
641
	return def_graph_pass(name ? name : "rem_confirm", remove_confirms);
642
}