ircons.c 18.9 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Matthias Braun's avatar
Matthias Braun committed
6
7
8
9
10
/**
 * @file
 * @brief   Various irnode constructors. Automatic construction of SSA
 *          representation.
 * @author  Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Boris Boesler
11
 *          Michael Beck, Matthias Braun
Götz Lindenmaier's avatar
Götz Lindenmaier committed
12
 */
Christoph Mallon's avatar
Christoph Mallon committed
13
14

#include "../adt/util.h"
15
#include "array.h"
Matthias Braun's avatar
Matthias Braun committed
16
#include "panic.h"
17
#include "irbackedge_t.h"
Christoph Mallon's avatar
Christoph Mallon committed
18
#include "ircons_t.h"
19
20
#include "iredges_t.h"
#include "irflag_t.h"
Christoph Mallon's avatar
Christoph Mallon committed
21
22
#include "irflag_t.h"
#include "irgmod.h"
23
#include "irgopt.h"
Christoph Mallon's avatar
Christoph Mallon committed
24
25
26
27
28
29
30
31
#include "irgraph_t.h"
#include "irhooks.h"
#include "irmode_t.h"
#include "irnode_t.h"
#include "irop_t.h"
#include "iropt_t.h"
#include "irprog_t.h"
#include "irverify.h"
32

Michael Beck's avatar
Michael Beck committed
33
34
/**
 * Language dependent variable initialization callback.
35
 */
36
static uninitialized_local_variable_func_t *default_initialize_local_variable = NULL;
37

38
39
ir_node *new_rd_Const_long(dbg_info *db, ir_graph *irg, ir_mode *mode,
                           long value)
40
{
41
	return new_rd_Const(db, irg, new_tarval_from_long(value, mode));
42
}
43

44
45
46
ir_node *new_rd_ASM(dbg_info *db, ir_node *block, ir_node *mem,
                    int arity, ir_node *in[], ir_asm_constraint *inputs,
                    size_t n_outs, ir_asm_constraint *outputs, size_t n_clobber,
47
	                ident *clobber[], ident *text)
48
{
Christoph Mallon's avatar
Christoph Mallon committed
49
	ir_graph *const irg = get_irn_irg(block);
50

Christoph Mallon's avatar
Christoph Mallon committed
51
52
	int       const r_arity = arity + 1;
	ir_node **const r_in    = ALLOCAN(ir_node*, r_arity);
53
	r_in[0] = mem;
Christoph Mallon's avatar
Christoph Mallon committed
54
	memcpy(&r_in[1], in, arity * sizeof(r_in[1]));
55
56

	ir_node *res = new_ir_node(db, irg, block, op_ASM, mode_T, r_arity, r_in);
57

58
	struct obstack *const obst = get_irg_obstack(irg);
Christoph Mallon's avatar
Christoph Mallon committed
59
60
61
62
63
64
	asm_attr       *const a    = &res->attr.assem;
	a->pin_state          = op_pin_state_pinned;
	a->input_constraints  = NEW_ARR_D(ir_asm_constraint, obst, arity);
	a->output_constraints = NEW_ARR_D(ir_asm_constraint, obst, n_outs);
	a->clobbers           = NEW_ARR_D(ident*,            obst, n_clobber);
	a->text               = text;
65

Christoph Mallon's avatar
Christoph Mallon committed
66
67
68
	memcpy(a->input_constraints,  inputs,  sizeof(inputs[0])  * arity);
	memcpy(a->output_constraints, outputs, sizeof(outputs[0]) * n_outs);
	memcpy(a->clobbers,           clobber, sizeof(clobber[0]) * n_clobber);
69

Matthias Braun's avatar
Matthias Braun committed
70
	verify_new_node(irg, res);
71
	res = optimize_node(res);
72
	return res;
73
}
74

75
76
ir_node *new_r_Const_long(ir_graph *irg, ir_mode *mode, long value)
{
77
	return new_rd_Const_long(NULL, irg, mode, value);
78
}
79

80
ir_node *new_r_ASM(ir_node *block, ir_node *mem,
Michael Beck's avatar
Michael Beck committed
81
                   int arity, ir_node *in[], ir_asm_constraint *inputs,
82
83
                   size_t n_outs, ir_asm_constraint *outputs,
                   size_t n_clobber, ident *clobber[], ident *text)
84
{
85
	return new_rd_ASM(NULL, block, mem, arity, in, inputs, n_outs, outputs, n_clobber, clobber, text);
Michael Beck's avatar
Michael Beck committed
86
}
Michael Beck's avatar
Michael Beck committed
87

Michael Beck's avatar
Michael Beck committed
88
/** Creates a Phi node with 0 predecessors. */
89
90
static inline ir_node *new_rd_Phi0(dbg_info *dbgi, ir_node *block,
                                   ir_mode *mode, int pos)
91
{
92
	ir_graph *irg = get_irn_irg(block);
93
94
	ir_node  *res = new_ir_node(dbgi, irg, block, op_Phi, mode, 0, NULL);
	res->attr.phi.u.pos = pos;
Matthias Braun's avatar
Matthias Braun committed
95
	verify_new_node(irg, res);
96
	return res;
97
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
98

99
static ir_node *get_r_value_internal(ir_node *block, int pos, ir_mode *mode);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
100

101
102
103
104
static void try_remove_unnecessary_phi(ir_node *phi)
{
	ir_node *phi_value = NULL;

Christoph Mallon's avatar
Christoph Mallon committed
105
106
	/* See if all inputs are either pointing to a single value or
	 * are self references. */
107
	bool have_self_loop = false;
108
	foreach_irn_in(phi, i, in) {
109
110
		if (in == phi) {
			have_self_loop = true;
111
			continue;
112
		}
113
114
115
116
117
118
119
120
121
122
123
		if (in == phi_value)
			continue;
		/** found a different value from the one we already found, can't remove
		 * the phi (yet) */
		if (phi_value != NULL)
			return;
		phi_value = in;
	}
	if (phi_value == NULL)
		return;

124
125
126
127
128
	/* Do not remove PhiM with self-loops as potentially endless loops are
	 * observable, see comment in equivalent_node_Phi() to learn more. */
	if (have_self_loop && get_irn_mode(phi) == mode_M)
		return;

129
	/* if we're here then all phi inputs have been either phi_value
Christoph Mallon's avatar
Christoph Mallon committed
130
	 * or self-references, we can replace the phi by phi_value. */
131
132
133
	exchange(phi, phi_value);

	/* recursively check phi_value, because it could be that we were the last
Christoph Mallon's avatar
Christoph Mallon committed
134
	 * phi-node in a loop-body. Then our argument is an unnecessary phi in
135
136
137
138
139
140
	 * the loop header which can be eliminated now */
	if (is_Phi(phi_value)) {
		try_remove_unnecessary_phi(phi_value);
	}
}

Sebastian Felis's avatar
Sebastian Felis committed
141
/**
Michael Beck's avatar
Michael Beck committed
142
143
144
145
146
 * Computes the predecessors for the real phi node, and then
 * allocates and returns this node.  The routine called to allocate the
 * node might optimize it away and return a real value.
 * This function must be called with an in-array of proper size.
 */
147
static ir_node *set_phi_arguments(ir_node *phi, int pos)
148
{
149
150
151
152
153
	ir_node  *block        = get_nodes_block(phi);
	ir_graph *irg          = get_irn_irg(block);
	int       arity        = get_irn_arity(block);
	ir_node **in           = ALLOCAN(ir_node*, arity);
	ir_mode  *mode         = get_irn_mode(phi);
154
155

	/* This loop goes to all predecessor blocks of the block the Phi node
Christoph Mallon's avatar
Christoph Mallon committed
156
157
158
	 * is in and there finds the operands of the Phi node by calling
	 * get_r_value_internal.  */
	for (int i = 0; i < arity; ++i) {
159
160
		ir_node *cfgpred = get_Block_cfgpred_block(block, i);
		ir_node *value;
161
		if (cfgpred == NULL) {
Matthias Braun's avatar
Matthias Braun committed
162
			value = new_r_Bad(irg, mode);
163
		} else {
164
165
166
			value = get_r_value_internal(cfgpred, pos, mode);
		}
		in[i] = value;
167
168
	}

169
	phi->attr.phi.u.backedge = new_backedge_arr(get_irg_obstack(irg), arity);
170
	set_irn_in(phi, arity, in);
171

Matthias Braun's avatar
Matthias Braun committed
172
	verify_new_node(irg, phi);
173

174
	try_remove_unnecessary_phi(phi);
175
176
177
178
179
180

	/* To solve the problem of (potentially) endless loops being observable
	 * behaviour we add a keep-alive edge too all PhiM nodes. */
	if (mode == mode_M && !is_Id(phi))
		keep_alive(phi);

181
	return phi;
182
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
183

Michael Beck's avatar
Michael Beck committed
184
/**
185
186
 * This function returns the last definition of a value.  In case
 * this value was last defined in a previous block, Phi nodes are
Michael Beck's avatar
Michael Beck committed
187
188
 * inserted.  If the part of the firm graph containing the definition
 * is not yet constructed, a dummy Phi node is returned.
189
190
191
192
 *
 * @param block   the current block
 * @param pos     the value number of the value searched
 * @param mode    the mode of this value (needed for Phi construction)
Michael Beck's avatar
Michael Beck committed
193
 */
194
static ir_node *get_r_value_internal(ir_node *block, int pos, ir_mode *mode)
195
{
Christoph Mallon's avatar
Christoph Mallon committed
196
	ir_node *res = block->attr.block.graph_arr[pos];
Michael Beck's avatar
Michael Beck committed
197
198
	if (res != NULL)
		return res;
199

200
	/* in a matured block we can immediately determine the phi arguments */
201
	if (get_Block_matured(block)) {
Christoph Mallon's avatar
Christoph Mallon committed
202
203
		ir_graph *const irg   = get_irn_irg(block);
		int       const arity = get_irn_arity(block);
204
		/* no predecessors: use unknown value */
205
206
207
208
209
210
211
212
213
214
		if (arity == 0) {
			if (block == get_irg_start_block(irg)) {
				if (default_initialize_local_variable != NULL) {
					ir_node *rem = get_r_cur_block(irg);
					set_r_cur_block(irg, block);
					res = default_initialize_local_variable(irg, mode, pos - 1);
					set_r_cur_block(irg, rem);
				} else {
					res = new_r_Unknown(irg, mode);
				}
215
			} else {
Christoph Mallon's avatar
Christoph Mallon committed
216
				goto bad; /* unreachable block, use Bad */
217
218
219
			}
		/* one predecessor just use its value */
		} else if (arity == 1) {
Matthias Braun's avatar
Matthias Braun committed
220
			ir_node *cfgpred = get_Block_cfgpred(block, 0);
221
			if (is_Bad(cfgpred)) {
Christoph Mallon's avatar
Christoph Mallon committed
222
bad:
Matthias Braun's avatar
Matthias Braun committed
223
				res = new_r_Bad(irg, mode);
224
			} else {
Matthias Braun's avatar
Matthias Braun committed
225
226
				ir_node *cfgpred_block = get_nodes_block(cfgpred);
				res = get_r_value_internal(cfgpred_block, pos, mode);
227
228
			}
		} else {
Christoph Mallon's avatar
Christoph Mallon committed
229
			/* multiple predecessors construct Phi */
230
231
232
233
234
235
236
237
238
239
			res = new_rd_Phi0(NULL, block, mode, pos);
			/* enter phi0 into our variable value table to break cycles
			 * arising from set_phi_arguments */
			block->attr.block.graph_arr[pos] = res;
			res = set_phi_arguments(res, pos);
		}
	} else {
		/* in case of immature block we have to keep a Phi0 */
		res = new_rd_Phi0(NULL, block, mode, pos);
		/* enqueue phi so we can set arguments once the block matures */
240
241
		res->attr.phi.next     = block->attr.block.phis;
		block->attr.block.phis = res;
242
243
244
	}
	block->attr.block.graph_arr[pos] = res;
	return res;
245
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
246

247
void mature_immBlock(ir_node *block)
248
{
249
250
251
	if (get_Block_matured(block))
		return;

Christoph Mallon's avatar
Christoph Mallon committed
252
253
254
255
256
257
258
259
260
261
262
263
264
	ir_graph       *const irg     = get_irn_irg(block);
	struct obstack *const obst    = get_irg_obstack(irg);
	size_t          const n_preds = ARR_LEN(block->in) - 1;
	/* Fix block parameters. */
	block->attr.block.backedge = new_backedge_arr(obst, n_preds);

	/* Traverse a chain of Phi nodes attached to this block and mature these,
	 * too. */
	for (ir_node *phi = block->attr.block.phis; phi != NULL;) {
		ir_node *const next      = phi->attr.phi.next;
		int      const pos       = phi->attr.phi.u.pos;
		ir_node *const new_value = set_phi_arguments(phi, pos);
		if (block->attr.block.graph_arr[pos] == phi)
265
			block->attr.block.graph_arr[pos] = new_value;
Christoph Mallon's avatar
Christoph Mallon committed
266
		phi = next;
267
	}
268

269
	set_Block_matured(block, 1);
270

Christoph Mallon's avatar
Christoph Mallon committed
271
	/* Create final in-array for the block. */
272
	if (block->attr.block.dynamic_ins) {
Christoph Mallon's avatar
Christoph Mallon committed
273
		ir_node **const new_in = DUP_ARR_D(ir_node*, obst, block->in);
274
275
276
277
278
		DEL_ARR_F(block->in);
		block->in = new_in;
		block->attr.block.dynamic_ins = false;
	}

279
	/* Now, as the block is a finished Firm node, we can optimize it.
Christoph Mallon's avatar
Christoph Mallon committed
280
281
282
283
284
285
	 * Since other nodes have been allocated since the block was created we can
	 * not free the node on the obstack.  Therefore we have to call
	 * optimize_in_place().
	 * Unfortunately the optimization does not change a lot, as all allocated
	 * nodes refer to the unoptimized node.
	 * We can call optimize_in_place_2(), as global cse has no effect on blocks.
286
	 */
Matthias Braun's avatar
Matthias Braun committed
287
	verify_new_node(irg, block);
288
	optimize_in_place_2(block);
289
}
Christian Schäfer's avatar
Christian Schäfer committed
290

291
ir_node *new_d_Const_long(dbg_info *db, ir_mode *mode, long value)
292
{
293
	assert(irg_is_constrained(current_ir_graph, IR_GRAPH_CONSTRAINT_CONSTRUCTION));
294
295
	return new_rd_Const_long(db, current_ir_graph, mode, value);
}
296

297
ir_node *new_d_ASM(dbg_info *db, ir_node *mem, int arity, ir_node *in[],
298
                   ir_asm_constraint *inputs,
299
300
                   size_t n_outs, ir_asm_constraint *outputs,
                   size_t n_clobber, ident *clobber[], ident *text)
301
{
302
	assert(irg_is_constrained(current_ir_graph, IR_GRAPH_CONSTRAINT_CONSTRUCTION));
303
304
	return new_rd_ASM(db, current_ir_graph->current_block, mem, arity, in,
	                  inputs, n_outs, outputs, n_clobber, clobber, text);
305
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
306

307
308
ir_node *new_rd_DivRL(dbg_info *dbgi, ir_node *block, ir_node * irn_mem, ir_node * irn_left, ir_node * irn_right, ir_mode* resmode, op_pin_state pin_state)
{
Christoph Mallon's avatar
Christoph Mallon committed
309
310
311
312
313
	ir_graph *const irg = get_Block_irg(block);
	ir_node  *const in[] = { irn_mem, irn_left, irn_right };
	ir_node        *res  = new_ir_node(dbgi, irg, block, op_Div, mode_T, 3, in);
	res->attr.div.resmode       = resmode;
	res->attr.div.no_remainder  = 1;
314
	res->attr.div.exc.pin_state = pin_state;
Matthias Braun's avatar
Matthias Braun committed
315
	verify_new_node(irg, res);
316
	res = optimize_node(res);
317
318
319
320
321
322
323
324
325
326
	return res;
}

ir_node *new_r_DivRL(ir_node *block, ir_node * irn_mem, ir_node * irn_left, ir_node * irn_right, ir_mode* resmode, op_pin_state pin_state)
{
	return new_rd_DivRL(NULL, block, irn_mem, irn_left, irn_right, resmode, pin_state);
}

ir_node *new_d_DivRL(dbg_info *dbgi, ir_node * irn_mem, ir_node * irn_left, ir_node * irn_right, ir_mode* resmode, op_pin_state pin_state)
{
327
	assert(irg_is_constrained(current_ir_graph, IR_GRAPH_CONSTRAINT_CONSTRUCTION));
Christoph Mallon's avatar
Christoph Mallon committed
328
	return new_rd_DivRL(dbgi, current_ir_graph->current_block, irn_mem, irn_left, irn_right, resmode, pin_state);
329
330
331
332
333
334
335
}

ir_node *new_DivRL(ir_node * irn_mem, ir_node * irn_left, ir_node * irn_right, ir_mode* resmode, op_pin_state pin_state)
{
	return new_d_DivRL(NULL, irn_mem, irn_left, irn_right, resmode, pin_state);
}

336
ir_node *new_rd_immBlock(dbg_info *dbgi, ir_graph *irg)
337
{
338
	assert(irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_CONSTRUCTION));
339
	/* creates a new dynamic in-array as length of in is -1 */
Christoph Mallon's avatar
Christoph Mallon committed
340
	ir_node *const res = new_ir_node(dbgi, irg, NULL, op_Block, mode_BB, -1, NULL);
Michael Beck's avatar
Michael Beck committed
341

342
	set_Block_matured(res, 0);
Christoph Mallon's avatar
Christoph Mallon committed
343
344
345
346
347
	block_attr *const b = &res->attr.block;
	b->dynamic_ins = true;
	b->irg.irg     = irg;
	b->backedge    = NULL;
	b->entity      = NULL;
Michael Beck's avatar
Michael Beck committed
348

349
350
351
	set_Block_block_visited(res, 0);

	/* Create and initialize array for Phi-node construction. */
352
	res->attr.block.graph_arr = NEW_ARR_DZ(ir_node*, get_irg_obstack(irg), irg->n_loc);
353
354

	/* Immature block may not be optimized! */
Matthias Braun's avatar
Matthias Braun committed
355
	verify_new_node(irg, res);
356
357

	return res;
358
359
360
361
362
363
364
365
366
367
368
}

ir_node *new_r_immBlock(ir_graph *irg)
{
	return new_rd_immBlock(NULL, irg);
}

ir_node *new_d_immBlock(dbg_info *dbgi)
{
	return new_rd_immBlock(dbgi, current_ir_graph);
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
369

370
ir_node *new_immBlock(void)
371
{
372
	return new_d_immBlock(NULL);
373
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
374

375
void add_immBlock_pred(ir_node *block, ir_node *jmp)
376
{
Andreas Zwinkau's avatar
Andreas Zwinkau committed
377
	assert(is_Block(block) && "Error: Must be a Block");
378
	assert(!get_Block_matured(block) && "Error: Block already matured!\n");
379
	assert(is_ir_node(jmp));
Michael Beck's avatar
Michael Beck committed
380

Christoph Mallon's avatar
Christoph Mallon committed
381
	int const n = ARR_LEN(block->in) - 1;
Michael Beck's avatar
Michael Beck committed
382
383
384
	ARR_APP1(ir_node *, block->in, jmp);
	/* Call the hook */
	hook_set_irn_n(block, n, jmp, NULL);
385
}
Christian Schäfer's avatar
Christian Schäfer committed
386

387
void set_cur_block(ir_node *target)
388
{
389
	set_r_cur_block(current_ir_graph, target);
390
391
392
393
}

void set_r_cur_block(ir_graph *irg, ir_node *target)
{
394
	assert(irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_CONSTRUCTION));
395
396
	assert(target == NULL || is_Block(target));
	assert(target == NULL || get_irn_irg(target) == irg);
397
398
	irg->current_block = target;
}
Christian Schäfer's avatar
Christian Schäfer committed
399

400
401
ir_node *get_r_cur_block(ir_graph *irg)
{
402
	assert(irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_CONSTRUCTION));
403
404
	return irg->current_block;
}
Christian Schäfer's avatar
Christian Schäfer committed
405

406
ir_node *(get_cur_block)(void)
407
408
409
410
411
{
	return get_r_cur_block(current_ir_graph);
}

ir_node *get_r_value(ir_graph *irg, int pos, ir_mode *mode)
412
{
413
	assert(irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_CONSTRUCTION));
414
415
	assert(pos >= 0);

416
	return get_r_value_internal(irg->current_block, pos + 1, mode);
417
}
Michael Beck's avatar
Michael Beck committed
418

419
ir_node *get_value(int pos, ir_mode *mode)
420
{
421
422
	return get_r_value(current_ir_graph, pos, mode);
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
423

424
425
426
427
428
429
/**
 * helper function for guess_mode: recursively look for a definition for
 * local variable @p pos, returns its mode if found.
 */
static ir_mode *guess_recursively(ir_node *block, int pos)
{
430
	if (irn_visited_else_mark(block))
431
432
433
		return NULL;

	/* already have a defintion -> we can simply look at its mode */
Christoph Mallon's avatar
Christoph Mallon committed
434
	ir_node *const value = block->attr.block.graph_arr[pos];
435
436
437
438
	if (value != NULL)
		return get_irn_mode(value);

	/* now we try to guess, by looking at the predecessor blocks */
Christoph Mallon's avatar
Christoph Mallon committed
439
440
	for (int i = 0, n_preds = get_irn_arity(block); i < n_preds; ++i) {
		ir_node *const pred_block = get_Block_cfgpred_block(block, i);
441
442
		if (pred_block == NULL)
			continue;
Christoph Mallon's avatar
Christoph Mallon committed
443
		ir_mode *const mode = guess_recursively(pred_block, pos);
444
445
446
447
448
449
450
451
		if (mode != NULL)
			return mode;
	}

	/* no way to guess */
	return NULL;
}

452
ir_mode *ir_r_guess_mode(ir_graph *irg, int pos)
453
454
{
	/* already have a defintion -> we can simply look at its mode */
Christoph Mallon's avatar
Christoph Mallon committed
455
456
	ir_node *const block = irg->current_block;
	ir_node *const value = block->attr.block.graph_arr[pos+1];
457
458
459
	if (value != NULL)
		return get_irn_mode(value);

460
461
	ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
	inc_irg_visited(irg);
Christoph Mallon's avatar
Christoph Mallon committed
462
	ir_mode *const mode = guess_recursively(block, pos + 1);
463
	ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
464
465
466
467

	return mode;
}

468
469
470
471
472
ir_mode *ir_guess_mode(int pos)
{
	return ir_r_guess_mode(current_ir_graph, pos);
}

473
void set_r_value(ir_graph *irg, int pos, ir_node *value)
474
{
475
	assert(irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_CONSTRUCTION));
476
	assert(pos >= 0);
Christoph Mallon's avatar
Christoph Mallon committed
477
	assert(pos + 1 < irg->n_loc);
478
	assert(is_ir_node(value));
479
	irg->current_block->attr.block.graph_arr[pos + 1] = value;
480
481
482
483
484
485
}

void set_value(int pos, ir_node *value)
{
	set_r_value(current_ir_graph, pos, value);
}
Christian Schäfer's avatar
Christian Schäfer committed
486

487
ir_node *get_r_store(ir_graph *irg)
488
{
489
	assert(irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_CONSTRUCTION));
490
	return get_r_value_internal(irg->current_block, 0, mode_M);
491
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
492

493
494
495
496
497
ir_node *get_store(void)
{
	return get_r_store(current_ir_graph);
}

Christoph Mallon's avatar
Christoph Mallon committed
498
void set_r_store(ir_graph *const irg, ir_node *store)
499
{
500
	assert(irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_CONSTRUCTION));
501
502
503
504
505
506
	/* Beware: due to dead code elimination, a store might become a Bad node even in
	   the construction phase. */
	assert((get_irn_mode(store) == mode_M || is_Bad(store)) && "storing non-memory node");

	if (get_opt_auto_create_sync()) {
		/* handle non-volatile Load nodes by automatically creating Sync's */
Christoph Mallon's avatar
Christoph Mallon committed
507
		ir_node *const load = skip_Proj(store);
508
		if (is_Load(load) && get_Load_volatility(load) == volatility_non_volatile) {
Christoph Mallon's avatar
Christoph Mallon committed
509
			ir_node *const pred = get_Load_mem(load);
510
511
512
513
514
515
516
517
			if (is_Sync(pred)) {
				/* a Load after a Sync: move it up */
				ir_node *mem = skip_Proj(get_Sync_pred(pred, 0));

				set_Load_mem(load, get_memop_mem(mem));
				add_Sync_pred(pred, store);
				store = pred;
			} else {
Christoph Mallon's avatar
Christoph Mallon committed
518
				ir_node *const pload = skip_Proj(pred);
519
520
521
522
				if (is_Load(pload) && get_Load_volatility(pload) == volatility_non_volatile) {
					/* a Load after a Load: create a new Sync */
					set_Load_mem(load, get_Load_mem(pload));

Christoph Mallon's avatar
Christoph Mallon committed
523
524
					ir_node *in[] = { pred, store };
					store = new_r_Sync(irg->current_block, ARRAY_SIZE(in), in);
525
526
527
528
				}
			}
		}
	}
529
530
	irg->current_block->attr.block.graph_arr[0] = store;
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
531

532
void set_store(ir_node *store)
533
{
534
535
	set_r_store(current_ir_graph, store);
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
536

537
void keep_alive(ir_node *ka)
538
{
539
540
	ir_graph *irg = get_irn_irg(ka);
	add_End_keepalive(get_irg_end(irg), ka);
541
}
Christian Schäfer's avatar
Christian Schäfer committed
542

543
544
void ir_set_uninitialized_local_variable_func(
		uninitialized_local_variable_func_t *func)
545
{
546
	default_initialize_local_variable = func;
547
}
548

549
550
void irg_finalize_cons(ir_graph *irg)
{
551
552
553
	ir_node *end_block = get_irg_end_block(irg);
	mature_immBlock(end_block);

554
	clear_irg_constraints(irg, IR_GRAPH_CONSTRAINT_CONSTRUCTION);
555
556
}

557
void irp_finalize_cons(void)
558
{
559
560
	foreach_irp_irg(i, irg) {
		irg_finalize_cons(irg);
561
	}
562
}
563

564
565
ir_node *new_Const_long(ir_mode *mode, long value)
{
566
	return new_d_Const_long(NULL, mode, value);
567
568
}

569
570
571
572
ir_node *new_ASM(ir_node *mem, int arity, ir_node *in[],
                 ir_asm_constraint *inputs, size_t n_outs,
                 ir_asm_constraint *outputs, size_t n_clobber,
                 ident *clobber[], ident *text)
573
{
574
	return new_d_ASM(NULL, mem, arity, in, inputs, n_outs, outputs, n_clobber, clobber, text);
Michael Beck's avatar
Michael Beck committed
575
}
576

577
ir_node *new_r_Anchor(ir_graph *irg)
578
{
Christoph Mallon's avatar
Christoph Mallon committed
579
	ir_node *const res = new_ir_node(NULL, irg, NULL, op_Anchor, mode_ANY, 0, NULL);
580
	res->attr.anchor.irg.irg = irg;
581

Matthias Braun's avatar
Matthias Braun committed
582
	/* hack to get get_irn_irg in set_irn_in() working */
583
584
	res->in[0] = res;

Christoph Mallon's avatar
Christoph Mallon committed
585
	/* we can't have NULL inputs so reference ourselves for now */
Christoph Mallon's avatar
Christoph Mallon committed
586
587
588
	int const arity = anchor_last + 1;
	ir_node  *in[arity];
	for (size_t i = 0; i < (size_t)arity; ++i) {
Matthias Braun's avatar
Matthias Braun committed
589
		in[i] = res;
590
	}
Christoph Mallon's avatar
Christoph Mallon committed
591
	set_irn_in(res, arity, in);
592

593
	return res;
594
}
595
596
597
598
599

ir_node *new_r_Block_noopt(ir_graph *irg, int arity, ir_node *in[])
{
	ir_node *res = new_ir_node(NULL, irg, NULL, op_Block, mode_BB, arity, in);
	res->attr.block.irg.irg = irg;
600
	res->attr.block.backedge = new_backedge_arr(get_irg_obstack(irg), arity);
601
602
	set_Block_matured(res, 1);
	/* Create and initialize array for Phi-node construction. */
603
	if (irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_CONSTRUCTION)) {
604
		res->attr.block.graph_arr = NEW_ARR_DZ(ir_node*, get_irg_obstack(irg), irg->n_loc);
605
	}
Matthias Braun's avatar
Matthias Braun committed
606
	verify_new_node(irg, res);
607
608
	return res;
}
609
610
611
612
613

void (verify_new_node)(ir_graph *irg, ir_node *node)
{
	verify_new_node_(irg, node);
}
614
615
616
617
618
619
620
621
622
623

ir_node *new_rd_Const_null(dbg_info *const dbgi, ir_graph *const irg, ir_mode *const mode)
{
	return new_rd_Const(dbgi, irg, get_mode_null(mode));
}

ir_node *new_r_Const_null(ir_graph *const irg, ir_mode *const mode)
{
	return new_r_Const(irg, get_mode_null(mode));
}
624
625
626
627
628
629
630
631
632
633

ir_node *new_rd_Const_one(dbg_info *const dbgi, ir_graph *const irg, ir_mode *const mode)
{
	return new_rd_Const(dbgi, irg, get_mode_one(mode));
}

ir_node *new_r_Const_one(ir_graph *const irg, ir_mode *const mode)
{
	return new_r_Const(irg, get_mode_one(mode));
}