irconsconfirm.c 16.6 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
/**
 * @file
 * @brief    Construction of Confirm nodes
 * @author   Michael Beck
 * @date     6.2005
 */
Matthias Braun's avatar
Matthias Braun committed
26
#include "config.h"
27

28
29
#include "irconsconfirm.h"

Michael Beck's avatar
Michael Beck committed
30
31
32
33
34
35
#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
36
#include "irgwalk.h"
Michael Beck's avatar
Michael Beck committed
37
#include "irprintf.h"
38
#include "irgopt.h"
39
#include "irpass.h"
Matthias Braun's avatar
Matthias Braun committed
40
#include "irtools.h"
41
#include "array_t.h"
42
#include "debug.h"
Matthias Braun's avatar
Matthias Braun committed
43
#include "error.h"
44
#include "irflag.h"
Michael Beck's avatar
Michael Beck committed
45
46
47
48

/**
 * Walker environment.
 */
49
typedef struct env_t {
50
51
52
53
	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
54
55
} env_t;

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

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

Matthias Braun's avatar
Matthias Braun committed
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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
103
104
105
106
107
108
/**
 * 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
109
static void handle_case(ir_node *block, ir_node *switchn, long pn, env_t *env)
110
{
Matthias Braun's avatar
Matthias Braun committed
111
112
113
114
	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
115

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

Matthias Braun's avatar
Matthias Braun committed
120
	foreach_out_edge_safe(selector, edge, next) {
Michael Beck's avatar
Michael Beck committed
121
122
123
124
125
126
127
128
129
130
131
		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
132
133
			if (c == NULL)
				c = get_case_value(switchn, pn);
Michael Beck's avatar
Michael Beck committed
134
135

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

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

144
145
146
147
148
149
150
151
/**
 * 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
 */
152
153
static void handle_modeb(ir_node *block, ir_node *selector, pn_Cond pnc, env_t *env)
{
154
	ir_node *cond, *old, *other_blk = NULL, *con = NULL;
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
	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) {
171
172
				ir_graph *irg = get_irn_irg(block);
				con = new_r_Const(irg, pnc == pn_Cond_true ? tarval_b_true : tarval_b_false);
173
174
175
176
177
			}
			old = get_irn_n(user, pos);
			set_irn_n(user, pos, con);
			DBG_OPT_CONFIRM_C(old, con);

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

			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);
190
					if (get_Proj_proj(proj) == (long)pnc)
191
192
193
194
195
196
						continue;
					edge = get_irn_out_edge_first(proj);
					other_blk = get_edge_src_irn(edge);
					break;
				}
				assert(other_blk);
197

198
				/*
199
200
201
202
				 * 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 ...
				 *
203
				 * Best would be to introduce a block here, removing this critical edge.
204
205
206
207
				 * 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 ...
				 */
208
209
210
211
212
213
214
215
216
217
218
219
			}

			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);

220
221
				if (!block_dominates(block, pred_blk) &&
				    !block_dominates(other_blk, pred_blk)) {
222
223
224
225
226
227
228
229
230
231
					/* 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) {
232
233
234
					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);
235
					env->num_consts += 2;
236
237
238
239
240
241
242
					if (pnc == pn_Cond_true) {
						c_b = c_true;
						c_o = c_false;
					} else {
						c_b = c_false;
						c_o = c_true;
					}
243
244
245
246
247
248
249
250
251
				}
				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;
				}
252
				phi = new_r_Phi(user_blk, n, in, mode_b);
253
				set_irn_n(user, pos, phi);
254
				env->num_eq += 1;
255
256
257
258
259
			}
		}
	}
}

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

	/* Beware of Bads */
277
	if (is_Bad(left) || is_Bad(right))
Michael Beck's avatar
Michael Beck committed
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
		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;

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

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

			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.
				 */
315
				set_irn_n(user, pos, right);
Michael Beck's avatar
Michael Beck committed
316
317
				DBG_OPT_CONFIRM(left, right);

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

				env->num_eq += 1;
321
322
323
324
325
326
327
			} 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
				 */
328
329
330
331
332
333
334
335
				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)) {
336
337
338
						/*
						 * The user of the user is dominated by our true/false
						 * block. So, create a copy of user WITH the constant
339
						 * replacing its pos'th input.
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
						 *
						 * 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;
355
356
					}
				}
Michael Beck's avatar
Michael Beck committed
357
358
			}
		}
359
	} else { /* not ir_relation_equal cases */
Michael Beck's avatar
Michael Beck committed
360
361
		ir_node *c = NULL;

362
		foreach_out_edge_safe(left, edge, next) {
Michael Beck's avatar
Michael Beck committed
363
364
365
366
367
368
369
370
371
372
373
			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)
374
					c = new_r_Confirm(block, left, right, rel);
Michael Beck's avatar
Michael Beck committed
375
376
377

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

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

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

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

				if (succ == c)
					continue;

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

				if (block_dominates(block, blk)) {
					/*
					 * Ok, we found a usage of right in a block
					 * dominated by the branch block.
404
					 * We can replace the input with a Confirm(right, rel^-1, left).
405
					 */
406
					if (! rc)
407
						rc = new_r_Confirm(block, right, left, rel);
408
409

					pos = get_edge_src_pos(edge);
410
411
					set_irn_n(succ, pos, rc);
					DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, succ, rc));
412
413
414
415
416

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

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

	/*
	 * 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);
437
	if (! is_Proj(proj))
Michael Beck's avatar
Michael Beck committed
438
439
440
		return;

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

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

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

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

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

461
		handle_if(block, selector, rel, env);
Michael Beck's avatar
Michael Beck committed
462
	}
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 (;;) {
		if (! is_Confirm(ptr))
472
			break;
473
		if (get_Confirm_relation(ptr) == ir_relation_less_greater) {
474
475
476
477
478
479
480
			ir_node *bound = get_Confirm_bound(ptr);

			if (is_Const(bound) && is_Const_null(bound))
				return 1;
		}
		ptr = get_Confirm_value(ptr);
	}
481
482
483
484
485
486
487
488
	/*
	 * 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;
489
}
490

491
/**
492
 * The given pointer will be dereferenced, add non-null Confirms.
493
494
495
496
497
 *
 * @param ptr    a node representing an address
 * @param block  the block of the dereferencing instruction
 * @param env    environment
 */
498
499
static void insert_non_null(ir_node *ptr, ir_node *block, env_t *env)
{
500
501
502
503
504
505
506
507
508
	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;


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

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

516
		if (block_dominates(block, blk)) {
517
518
519
520
521
522
			/*
			 * 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) {
523
524
525
				ir_mode  *mode = get_irn_mode(ptr);
				ir_graph *irg  = get_irn_irg(block);
				c = new_r_Const(irg, get_mode_null(mode));
526
				c = new_r_Confirm(block, ptr, c, ir_relation_less_greater);
527
528
529
			}

			set_irn_n(succ, pos, c);
530
			DB((dbg, LEVEL_2, "Replacing input %d of node %+F with %+F\n", pos, succ, c));
531

532
			env->num_non_null += 1;
533
534
535
			env->num_confirms += 1;
		}
	}
536
}
537
538
539
540

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

	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;
	}
563
}
Michael Beck's avatar
Michael Beck committed
564

565
void construct_confirms(ir_graph *irg)
566
{
Michael Beck's avatar
Michael Beck committed
567
	env_t env;
568
569
	FIRM_DBG_REGISTER(dbg, "firm.ana.confirm");

570
571
572
573
574
	assure_irg_properties(irg,
	      IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES
		| IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE
		| IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES);

Michael Beck's avatar
Michael Beck committed
575
576
	assert(get_irg_pinned(irg) == op_pin_state_pinned &&
	       "Nodes must be placed to insert Confirms");
Michael Beck's avatar
Michael Beck committed
577

Michael Beck's avatar
Michael Beck committed
578
579
580
	env.num_confirms = 0;
	env.num_consts   = 0;
	env.num_eq       = 0;
581
	env.num_non_null = 0;
Michael Beck's avatar
Michael Beck committed
582

583
	if (get_opt_global_null_ptr_elimination()) {
584
585
586
587
588
589
		/* 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
590

591
592
593
	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));
594
	DB((dbg, LEVEL_1, "# non-null Confirms : %u\n", env.num_non_null));
Michael Beck's avatar
Michael Beck committed
595

596
	confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_CONTROL_FLOW);
597
}
Michael Beck's avatar
Michael Beck committed
598

599
600
ir_graph_pass_t *construct_confirms_pass(const char *name)
{
601
	return def_graph_pass(name ? name : "confirm", construct_confirms);
602
}
603

604
static void remove_confirm(ir_node *n, void *env)
605
{
606
607
	ir_node *value;

Michael Beck's avatar
Michael Beck committed
608
	(void) env;
609
610
611
612
613
614
	if (!is_Confirm(n))
		return;

	value = get_Confirm_value(n);
	exchange(n, value);
}
Michael Beck's avatar
Michael Beck committed
615

616
617
void remove_confirms(ir_graph *irg)
{
618
	irg_walk_graph(irg, NULL, remove_confirm, NULL);
619
	confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_CONTROL_FLOW);
620
}
621

622
623
ir_graph_pass_t *remove_confirms_pass(const char *name)
{
624
	return def_graph_pass(name ? name : "rem_confirm", remove_confirms);
625
}