benode.c 13.4 KB
Newer Older
Sebastian Hack's avatar
Sebastian Hack committed
1
2
3
4
5
6
7
8
9
10
/**
 * @file   benode.c
 * @date   17.05.2005
 * @author Sebastian Hack
 *
 * Backend node support.
 *
 * Copyright (C) 2005 Universitaet Karlsruhe
 * Released under the GPL
 */
11

Michael Beck's avatar
Michael Beck committed
12
13
14
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
Sebastian Hack's avatar
Sebastian Hack committed
15
16
17
18
19
20

#include <stdlib.h>

#include "obst.h"
#include "set.h"
#include "pmap.h"
21
#include "util.h"
Sebastian Hack's avatar
Sebastian Hack committed
22
#include "debug.h"
Sebastian Hack's avatar
Sebastian Hack committed
23
24
25
26

#include "irop_t.h"
#include "irmode_t.h"
#include "irnode_t.h"
27
#include "ircons_t.h"
28
#include "irprintf.h"
Sebastian Hack's avatar
Sebastian Hack committed
29

30
31
32
#include "be_t.h"
#include "belive_t.h"
#include "besched_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
33
34
#include "benode_t.h"

35
36
#include "beirgmod.h"

Daniel Grund's avatar
Daniel Grund committed
37
38
#define DBG_LEVEL 0

Sebastian Hack's avatar
Sebastian Hack committed
39
typedef enum _node_kind_t {
Christian Würdig's avatar
Christian Würdig committed
40
41
42
43
44
	node_kind_spill,
	node_kind_reload,
	node_kind_perm,
	node_kind_copy,
	node_kind_last
Sebastian Hack's avatar
Sebastian Hack committed
45
46
47
} node_kind_t;

typedef struct {
Christian Würdig's avatar
Christian Würdig committed
48
49
50
51
52
	node_kind_t kind;
	const arch_register_class_t *cls;
	ir_op *op;
	int n_pos;
	int *pos;
Sebastian Hack's avatar
Sebastian Hack committed
53
54
} be_op_t;

55
56
57
58
59
60
61
62
63
64
65
typedef struct {
	const be_node_factory_t *factory;
	int n_regs;
	const arch_register_t *reg[1];
} be_node_attr_t;

typedef struct {
	be_node_attr_t attr;
	ir_node *spill_ctx;
} be_spill_attr_t;

Sebastian Hack's avatar
Sebastian Hack committed
66
static int templ_pos_Spill[] = {
Sebastian Hack's avatar
Sebastian Hack committed
67
	0
Sebastian Hack's avatar
Sebastian Hack committed
68
69
70
};

static int templ_pos_Reload[] = {
Sebastian Hack's avatar
Sebastian Hack committed
71
	-1
Sebastian Hack's avatar
Sebastian Hack committed
72
73
74
};

static int templ_pos_Copy[] = {
Sebastian Hack's avatar
Sebastian Hack committed
75
	0, -1
Sebastian Hack's avatar
Sebastian Hack committed
76
77
};

78
79
80
81
82
83
84
85
86
87
88
89
static int dump_node(ir_node *irn, FILE *f, dump_reason_t reason);

static const ir_op_ops be_node_ops = {
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
90
91
	NULL,
	NULL,
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
	dump_node,
	NULL
};

static be_node_attr_t *init_node_attr(ir_node *irn,
		const be_node_factory_t *fact, int n_regs)
{
	be_node_attr_t *attr = (be_node_attr_t *) &irn->attr;
	int i;

	attr->n_regs  = n_regs;
	attr->factory = fact;

	for(i = 0; i < n_regs; ++i)
		attr->reg[i] = NULL;

	return attr;
}

Sebastian Hack's avatar
Sebastian Hack committed
111
112
113
114
#define ARRSIZE(x) (sizeof(x) / sizeof(x[0]))

static int cmp_op_map(const void *a, const void *b, size_t size)
{
Christian Würdig's avatar
Christian Würdig committed
115
116
	const be_op_t *x = a;
	const be_op_t *y = b;
Sebastian Hack's avatar
Sebastian Hack committed
117

Christian Würdig's avatar
Christian Würdig committed
118
	return !(x->kind == y->kind && x->cls == y->cls);
Sebastian Hack's avatar
Sebastian Hack committed
119
120
121
}

static be_op_t *get_op(const be_node_factory_t *fact,
Christian Würdig's avatar
Christian Würdig committed
122
		const arch_register_class_t *cls, node_kind_t kind)
Sebastian Hack's avatar
Sebastian Hack committed
123
{
Christian Würdig's avatar
Christian Würdig committed
124
	be_op_t templ;
Sebastian Hack's avatar
Sebastian Hack committed
125

Christian Würdig's avatar
Christian Würdig committed
126
127
	templ.kind = kind;
	templ.cls = cls;
Sebastian Hack's avatar
Sebastian Hack committed
128

Christian Würdig's avatar
Christian Würdig committed
129
130
	return set_insert(fact->ops, &templ, sizeof(templ),
		HASH_PTR(cls) + 7 * kind);
Sebastian Hack's avatar
Sebastian Hack committed
131
132
133
}

ir_node *new_Spill(const be_node_factory_t *factory,
Christian Würdig's avatar
Christian Würdig committed
134
135
		const arch_register_class_t *cls,
		ir_graph *irg, ir_node *bl, ir_node *node_to_spill, ir_node *ctx)
Sebastian Hack's avatar
Sebastian Hack committed
136
{
137
138
	be_spill_attr_t *attr;
	ir_node *irn;
Christian Würdig's avatar
Christian Würdig committed
139
140
	ir_node *in[1];
	ir_op *op = get_op(factory, cls, node_kind_spill)->op;
Sebastian Hack's avatar
Sebastian Hack committed
141

Christian Würdig's avatar
Christian Würdig committed
142
143
	assert(op && "Spill opcode must be present for this register class");
	in[0] = node_to_spill;
144
145
146
	irn  = new_ir_node(NULL, irg, bl, op, mode_M, 1, in);
	attr = (be_spill_attr_t *) init_node_attr(irn, factory, 0);
	attr->spill_ctx = ctx;
Sebastian Hack's avatar
Sebastian Hack committed
147

Christian Würdig's avatar
Christian Würdig committed
148
	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
149
150
151
}

ir_node *new_Reload(const be_node_factory_t *factory,
Christian Würdig's avatar
Christian Würdig committed
152
153
		const arch_register_class_t *cls, ir_graph *irg,
		ir_node *bl, ir_mode *mode, ir_node *spill_node)
Sebastian Hack's avatar
Sebastian Hack committed
154
{
Christian Würdig's avatar
Christian Würdig committed
155
156
	ir_node *irn, *in[1];
	ir_op *op = get_op(factory, cls, node_kind_reload)->op;
Sebastian Hack's avatar
Sebastian Hack committed
157

Christian Würdig's avatar
Christian Würdig committed
158
159
160
	assert(op && "Reload opcode must be present for this register class");
	// assert(is_Spill(factory, spill_node) && "Operand of Reload must be a Spill");
	in[0] = spill_node;
Sebastian Hack's avatar
Sebastian Hack committed
161

Christian Würdig's avatar
Christian Würdig committed
162
	irn  = new_ir_node(NULL, irg, bl, op, mode, 1, in);
163
164
165
	init_node_attr(irn, factory, 1);

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
166
167
168
}

ir_node *new_Perm(const be_node_factory_t *factory,
Christian Würdig's avatar
Christian Würdig committed
169
170
		const arch_register_class_t *cls,
		ir_graph *irg, ir_node *bl, int arity, ir_node **in)
Sebastian Hack's avatar
Sebastian Hack committed
171
{
172
	ir_node *irn;
Christian Würdig's avatar
Christian Würdig committed
173
	ir_op *op = get_op(factory, cls, node_kind_perm)->op;
Sebastian Hack's avatar
Sebastian Hack committed
174

Christian Würdig's avatar
Christian Würdig committed
175
	irn  = new_ir_node(NULL, irg, bl, op, mode_T, arity, in);
176
177
178
	init_node_attr(irn, factory, arity);

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
179
180
181
}

ir_node *new_Copy(const be_node_factory_t *factory,
Christian Würdig's avatar
Christian Würdig committed
182
183
		const arch_register_class_t *cls,
		ir_graph *irg, ir_node *bl, ir_node *in)
Sebastian Hack's avatar
Sebastian Hack committed
184
{
Christian Würdig's avatar
Christian Würdig committed
185
186
	ir_node *irn, *ins[1];
	ir_op *op = get_op(factory, cls, node_kind_copy)->op;
Sebastian Hack's avatar
Sebastian Hack committed
187

Christian Würdig's avatar
Christian Würdig committed
188
	ins[0] = in;
Sebastian Hack's avatar
Sebastian Hack committed
189

Christian Würdig's avatar
Christian Würdig committed
190
	irn  = new_ir_node(NULL, irg, bl, op, get_irn_mode(in), 1, ins);
191
192
193
	init_node_attr(irn, factory, 1);

	return irn;
Sebastian Hack's avatar
Sebastian Hack committed
194
195
}

Sebastian Hack's avatar
Sebastian Hack committed
196
197
198
ir_node *be_spill(
		const be_node_factory_t *factory,
		const arch_env_t *arch_env,
199
		ir_node *irn, ir_node *ctx)
Sebastian Hack's avatar
Sebastian Hack committed
200
{
Christian Würdig's avatar
Christian Würdig committed
201
	const arch_register_class_t *cls = arch_get_irn_reg_class(arch_env, irn, -1);
202

Christian Würdig's avatar
Christian Würdig committed
203
204
205
	ir_node *bl    = get_nodes_block(irn);
	ir_graph *irg  = get_irn_irg(bl);
	ir_node *spill = new_Spill(factory, cls, irg, bl, irn, ctx);
Sebastian Hack's avatar
Sebastian Hack committed
206
207
208
209
210
211
212
213
214
215
216
217
	ir_node *insert;

	/*
	 * search the right insertion point. a spill of a phi cannot be put
	 * directly after the phi, if there are some phis behind the one which
	 * is spilled.
	 */
	insert = sched_next(irn);
	while(is_Phi(insert) && !sched_is_end(insert))
		insert = sched_next(insert);

	sched_add_before(insert, spill);
Christian Würdig's avatar
Christian Würdig committed
218
	return spill;
Sebastian Hack's avatar
Sebastian Hack committed
219
220
}

Sebastian Hack's avatar
Sebastian Hack committed
221
ir_node *be_reload(const be_node_factory_t *factory,
Christian Würdig's avatar
Christian Würdig committed
222
223
224
					 const arch_env_t *arch_env,
					 const arch_register_class_t *cls,
					 ir_node *irn, int pos, ir_mode *mode, ir_node *spill)
Sebastian Hack's avatar
Sebastian Hack committed
225
226
227
{
	ir_node *reload;

Christian Würdig's avatar
Christian Würdig committed
228
229
	ir_node *bl   = get_nodes_block(irn);
	ir_graph *irg = get_irn_irg(bl);
Sebastian Hack's avatar
Sebastian Hack committed
230
231
232

	assert(is_Spill(factory, spill)
			|| (is_Phi(spill) && get_irn_mode(spill) == mode_M));
Sebastian Hack's avatar
Sebastian Hack committed
233

Christian Würdig's avatar
Christian Würdig committed
234
	reload = new_Reload(factory, cls, irg, bl, mode, spill);
Sebastian Hack's avatar
Sebastian Hack committed
235

Sebastian Hack's avatar
Sebastian Hack committed
236
	set_irn_n(irn, pos, reload);
Christian Würdig's avatar
Christian Würdig committed
237
238
	sched_add_before(irn, reload);
	return reload;
Sebastian Hack's avatar
Sebastian Hack committed
239
}
Sebastian Hack's avatar
Sebastian Hack committed
240

Sebastian Hack's avatar
Sebastian Hack committed
241
242
243
244
245
246
247
248
249
250
251
/**
 * If the node is a proj, reset the node to the proj's target and return
 * the proj number.
 * @param node The address of a node pointer.
 * @param def  A default value.
 * @return     If *node is a Proj, *node is set to the Proj's target and
 *             the Proj number is returned. Else *node remains the same and @p def
 *             is returned.
 */
static int redir_proj(const ir_node **node, int def)
{
Christian Würdig's avatar
Christian Würdig committed
252
	const ir_node *n = *node;
Sebastian Hack's avatar
Sebastian Hack committed
253

Christian Würdig's avatar
Christian Würdig committed
254
255
256
257
	if(is_Proj(n)) {
		*node = get_Proj_pred(n);
		def = -(get_Proj_proj(n) + 1);
	}
Sebastian Hack's avatar
Sebastian Hack committed
258

Christian Würdig's avatar
Christian Würdig committed
259
	return def;
Sebastian Hack's avatar
Sebastian Hack committed
260
261
262
263
}

static const arch_register_req_t *
be_node_get_irn_reg_req(const arch_irn_ops_t *_self,
Sebastian Hack's avatar
Sebastian Hack committed
264
		arch_register_req_t *req, const ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
265
{
Sebastian Hack's avatar
Sebastian Hack committed
266
267
268
	be_op_t *bo;
	const be_node_factory_t *factory =
		container_of(_self, const be_node_factory_t, irn_ops);
Sebastian Hack's avatar
Sebastian Hack committed
269

Daniel Grund's avatar
Daniel Grund committed
270
271
272
	if(get_irn_mode(irn) == mode_T && pos < 0)
		return NULL;

Sebastian Hack's avatar
Sebastian Hack committed
273
274
275
276
277
278
	/*
	 * were interested in an output operand, so
	 * let's resolve projs.
	 */
	if(pos < 0)
		pos = redir_proj((const ir_node **) &irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
279

Sebastian Hack's avatar
Sebastian Hack committed
280
	bo = pmap_get(factory->irn_op_map, get_irn_op(irn));
Sebastian Hack's avatar
Sebastian Hack committed
281

Sebastian Hack's avatar
Sebastian Hack committed
282
283
	if(bo) {
		int i;
Sebastian Hack's avatar
Sebastian Hack committed
284

Sebastian Hack's avatar
Sebastian Hack committed
285
286
		req->type = arch_register_req_type_normal;
		req->cls  = bo->cls;
Sebastian Hack's avatar
Sebastian Hack committed
287

Sebastian Hack's avatar
Sebastian Hack committed
288
289
290
291
		for(i = 0; i < bo->n_pos; ++i)
			if(pos == bo->pos[i])
				return req;
	}
Sebastian Hack's avatar
Sebastian Hack committed
292

Sebastian Hack's avatar
Sebastian Hack committed
293
	return NULL;
Sebastian Hack's avatar
Sebastian Hack committed
294
295
296
297
}

void
be_node_set_irn_reg(const arch_irn_ops_t *_self, ir_node *irn,
Christian Würdig's avatar
Christian Würdig committed
298
		const arch_register_t *reg)
Sebastian Hack's avatar
Sebastian Hack committed
299
{
Sebastian Hack's avatar
Sebastian Hack committed
300
301
	int pos;
	be_op_t *bo;
302
	be_node_attr_t *attr;
Sebastian Hack's avatar
Sebastian Hack committed
303
304
	const be_node_factory_t *factory =
		container_of(_self, const be_node_factory_t, irn_ops);
Sebastian Hack's avatar
Sebastian Hack committed
305

Daniel Grund's avatar
Daniel Grund committed
306
	if(get_irn_mode(irn) == mode_T && pos < 0)
Sebastian Hack's avatar
Sebastian Hack committed
307
		return;
Daniel Grund's avatar
Daniel Grund committed
308

Sebastian Hack's avatar
Sebastian Hack committed
309
310
	pos = redir_proj((const ir_node **) &irn, -1);
	bo = pmap_get(factory->irn_op_map, get_irn_op(irn));
Daniel Grund's avatar
Daniel Grund committed
311
312
313
314

	if(!bo)
		return;

315
316
	attr = (be_node_attr_t *) &irn->attr;
	attr->reg[-pos - 1] = reg;
Sebastian Hack's avatar
Sebastian Hack committed
317
318
319
}

const arch_register_t *
Sebastian Hack's avatar
Sebastian Hack committed
320
be_node_get_irn_reg(const arch_irn_ops_t *_self, const ir_node *irn)
Sebastian Hack's avatar
Sebastian Hack committed
321
{
Sebastian Hack's avatar
Sebastian Hack committed
322
323
324
325
	int i, pos;
	be_op_t *bo;
	const be_node_factory_t *factory =
		container_of(_self, const be_node_factory_t, irn_ops);
Sebastian Hack's avatar
Sebastian Hack committed
326

Daniel Grund's avatar
Daniel Grund committed
327
328
329
	if(get_irn_mode(irn) == mode_T && pos < 0)
		return NULL;

Sebastian Hack's avatar
Sebastian Hack committed
330
331
	pos = redir_proj((const ir_node **) &irn, -1);
	bo = pmap_get(factory->irn_op_map, get_irn_op(irn));
Daniel Grund's avatar
Daniel Grund committed
332

Sebastian Hack's avatar
Sebastian Hack committed
333
334
	if(!bo)
		return NULL;
Daniel Grund's avatar
Daniel Grund committed
335

Sebastian Hack's avatar
Sebastian Hack committed
336
337
	for(i = 0; i < bo->n_pos; ++i) {
		if(bo->pos[i] == pos) {
338
339
			be_node_attr_t *attr = (be_node_attr_t *) &irn->attr;
			return attr->reg[-pos - 1];
Sebastian Hack's avatar
Sebastian Hack committed
340
341
		}
	}
Daniel Grund's avatar
Daniel Grund committed
342

Sebastian Hack's avatar
Sebastian Hack committed
343
	return NULL;
Sebastian Hack's avatar
Sebastian Hack committed
344
345
346
347
}

arch_irn_class_t be_node_classify(const arch_irn_ops_t *_self, const ir_node *irn)
{
Christian Würdig's avatar
Christian Würdig committed
348
	const be_node_factory_t *factory = container_of(_self, const be_node_factory_t, irn_ops);
Sebastian Hack's avatar
Sebastian Hack committed
349

Christian Würdig's avatar
Christian Würdig committed
350
351
	be_op_t *bo;
	int idx;
Sebastian Hack's avatar
Sebastian Hack committed
352

Christian Würdig's avatar
Christian Würdig committed
353
354
	idx = redir_proj(&irn, 0);
	bo = pmap_get(factory->irn_op_map, get_irn_op(irn));
Sebastian Hack's avatar
Sebastian Hack committed
355

Sebastian Hack's avatar
Sebastian Hack committed
356
357
358
359
360
361
362
	switch(bo->kind) {
#define XXX(a) case node_kind_ ## a: return arch_irn_class_ ## a;
		XXX(spill)
		XXX(reload)
		XXX(perm)
		XXX(copy)
#undef XXX
Sebastian Hack's avatar
Sebastian Hack committed
363
364
		default:
		return 0;
Sebastian Hack's avatar
Sebastian Hack committed
365
366
	}

Christian Würdig's avatar
Christian Würdig committed
367
	return 0;
Sebastian Hack's avatar
Sebastian Hack committed
368
369
}

Sebastian Hack's avatar
Sebastian Hack committed
370
371
372
373
374
arch_irn_class_t be_node_get_flags(const arch_irn_ops_t *_self, const ir_node *irn)
{
	return 0;
}

Sebastian Hack's avatar
Sebastian Hack committed
375
376
377
static const arch_irn_ops_t *
be_node_get_irn_ops(const arch_irn_handler_t *_self, const ir_node *irn)
{
Christian Würdig's avatar
Christian Würdig committed
378
379
380
	be_op_t *bo;
	const be_node_factory_t *factory =
		container_of(_self, const be_node_factory_t, handler);
Sebastian Hack's avatar
Sebastian Hack committed
381

Christian Würdig's avatar
Christian Würdig committed
382
383
	redir_proj(&irn, 0);
	bo = pmap_get(factory->irn_op_map, get_irn_op(irn));
Sebastian Hack's avatar
Sebastian Hack committed
384

Christian Würdig's avatar
Christian Würdig committed
385
	return bo ? &factory->irn_ops : NULL;
Sebastian Hack's avatar
Sebastian Hack committed
386
387
388
389
}

const arch_irn_handler_t *be_node_get_irn_handler(const be_node_factory_t *f)
{
Christian Würdig's avatar
Christian Würdig committed
390
	return &f->handler;
Sebastian Hack's avatar
Sebastian Hack committed
391
392
393
394
}

int is_Spill(const be_node_factory_t *f, const ir_node *irn)
{
Christian Würdig's avatar
Christian Würdig committed
395
396
397
	be_op_t *bo;
	bo = pmap_get(f->irn_op_map, get_irn_op(irn));
	return bo != NULL && bo->kind == node_kind_spill;
Sebastian Hack's avatar
Sebastian Hack committed
398
399
}

Sebastian Hack's avatar
Sebastian Hack committed
400
be_node_factory_t *be_node_factory_init(be_node_factory_t *factory, const arch_isa_t *isa)
Sebastian Hack's avatar
Sebastian Hack committed
401
{
Christian Würdig's avatar
Christian Würdig committed
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
	int i, j, n;

	factory->ops = new_set(cmp_op_map, 64);
	factory->irn_op_map = pmap_create();
	obstack_init(&factory->obst);

	factory->handler.get_irn_ops = be_node_get_irn_ops;

	factory->irn_ops.get_irn_reg_req = be_node_get_irn_reg_req;
	factory->irn_ops.set_irn_reg     = be_node_set_irn_reg;
	factory->irn_ops.get_irn_reg     = be_node_get_irn_reg;
	factory->irn_ops.classify        = be_node_classify;
	factory->irn_ops.get_flags       = be_node_get_flags;

	for(i = 0, n = arch_isa_get_n_reg_class(isa); i < n; ++i) {
		const arch_register_class_t *cls = arch_isa_get_reg_class(isa, i);
		be_op_t *ent;

		ent = get_op(factory, cls, node_kind_spill);
		ent->op = new_ir_op(get_next_ir_opcode(), "Spill", op_pin_state_pinned,
				0, oparity_unary, 0, sizeof(be_spill_attr_t), &be_node_ops);
		ent->n_pos = ARRSIZE(templ_pos_Spill);
		ent->pos = templ_pos_Spill;
		pmap_insert(factory->irn_op_map, ent->op, ent);

		ent = get_op(factory, cls, node_kind_reload);
		ent->op = new_ir_op(get_next_ir_opcode(), "Reload", op_pin_state_pinned, 0,
				oparity_unary, 0, sizeof(be_node_attr_t), &be_node_ops);
		ent->n_pos = ARRSIZE(templ_pos_Reload);
		ent->pos = templ_pos_Reload;
		pmap_insert(factory->irn_op_map, ent->op, ent);

		ent = get_op(factory, cls, node_kind_copy);
		ent->op = new_ir_op(get_next_ir_opcode(), "Copy", op_pin_state_pinned, 0,
				oparity_unary, 0, sizeof(be_node_attr_t), &be_node_ops);
		ent->n_pos = ARRSIZE(templ_pos_Copy);
		ent->pos = templ_pos_Copy;
		pmap_insert(factory->irn_op_map, ent->op, ent);

		ent = get_op(factory, cls, node_kind_perm);
		ent->op = new_ir_op(get_next_ir_opcode(), "Perm", op_pin_state_pinned, 0,
				oparity_variable, 0,
444
				sizeof(be_node_attr_t) + sizeof(arch_register_t) * cls->n_regs, &be_node_ops);
Christian Würdig's avatar
Christian Würdig committed
445
446
447
448
449
450
451
452
453
454
455
456
		ent->n_pos = 2 * cls->n_regs;
		ent->pos = obstack_alloc(&factory->obst, sizeof(ent->pos[0]) * ent->n_pos);
		for(j = 0; j < ent->n_pos; j += 2) {
			int k = j / 2;
			ent->pos[j] = k;
			ent->pos[j + 1] = -(k + 1);
		}
		pmap_insert(factory->irn_op_map, ent->op, ent);

	}

	return factory;
Sebastian Hack's avatar
Sebastian Hack committed
457
458
}

459
460
461
static int dump_node(ir_node *irn, FILE *f, dump_reason_t reason)
{
	be_node_attr_t *attr = (be_node_attr_t *) &irn->attr;
Christian Würdig's avatar
Christian Würdig committed
462
	be_op_t *bo          = pmap_get(attr->factory->irn_op_map, get_irn_op(irn));
463
464
465
466
467
468
469
470
471
472
473

	int i;

	switch(reason) {
		case dump_node_opcode_txt:
			fprintf(f, get_op_name(bo->op));
			break;
		case dump_node_mode_txt:
			fprintf(f, get_mode_name(get_irn_mode(irn)));
			break;
		case dump_node_nodeattr_txt:
Daniel Grund's avatar
Daniel Grund committed
474
			fprintf(f, "%s ", bo->cls->name);
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
			break;
		case dump_node_info_txt:
			for(i = 0; i < attr->n_regs; ++i) {
				const arch_register_t *reg = attr->reg[i];
				fprintf(f, "reg #%d: %s\n", i, reg ? reg->name : "n/a");
			}

			if(bo->kind == node_kind_spill) {
				be_spill_attr_t *a = (be_spill_attr_t *) attr;
				ir_fprintf(f, "spill context: %+F\n", a->spill_ctx);
			}
			break;
	}

	return 1;
}

Sebastian Hack's avatar
Sebastian Hack committed
492
ir_node *insert_Perm_after(const be_main_env_t *env,
Christian Würdig's avatar
Christian Würdig committed
493
494
495
							 const arch_register_class_t *cls,
							 dom_front_info_t *dom_front,
							 ir_node *pos)
Sebastian Hack's avatar
Sebastian Hack committed
496
{
Christian Würdig's avatar
Christian Würdig committed
497
498
499
500
501
	const arch_env_t *arch_env  = env->arch_env;
	ir_node *bl                 = is_Block(pos) ? pos : get_nodes_block(pos);
	ir_graph *irg               = get_irn_irg(bl);
	pset *live                  = pset_new_ptr_default();
	firm_dbg_module_t *dbg      = firm_dbg_register("firm.be.node");
Sebastian Hack's avatar
Sebastian Hack committed
502

Christian Würdig's avatar
Christian Würdig committed
503
504
505
	irn_live_t *li;
	ir_node *curr, *irn, *perm, **nodes;
	int i, n;
506

Christian Würdig's avatar
Christian Würdig committed
507
508
	firm_dbg_set_mask(dbg, DBG_LEVEL);
	DBG((dbg, LEVEL_1, "Insert Perm after: %+F\n", pos));
509

Daniel Grund's avatar
Daniel Grund committed
510
511
512
513
514
515
516

	live_foreach(bl, li) {
		ir_node *irn = (ir_node *) li->irn;
		if(live_is_end(li) && arch_irn_has_reg_class(arch_env, irn, -1, cls))
			pset_insert_ptr(live, irn);
	}

Christian Würdig's avatar
Christian Würdig committed
517
518
	sched_foreach_reverse(bl, irn) {
		ir_node *x;
Sebastian Hack's avatar
Sebastian Hack committed
519

520
521
522
523
	/*
	 * If we encounter the node we want to insert the Perm after,
	 * exit immediately, so that this node is still live
	 */
Christian Würdig's avatar
Christian Würdig committed
524
525
		if(irn == pos)
			break;
526

Christian Würdig's avatar
Christian Würdig committed
527
528
529
		DBG((dbg, LEVEL_1, "%+F\n", irn));
		for(x = pset_first(live); x; x = pset_next(live))
			DBG((dbg, LEVEL_1, "\tlive: %+F\n", x));
530

Christian Würdig's avatar
Christian Würdig committed
531
532
		if(arch_irn_has_reg_class(arch_env, irn, -1, cls))
			pset_remove_ptr(live, irn);
533

Christian Würdig's avatar
Christian Würdig committed
534
535
		for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
			ir_node *op = get_irn_n(irn, i);
536

Christian Würdig's avatar
Christian Würdig committed
537
538
539
540
			if(arch_irn_has_reg_class(arch_env, op, -1, cls))
				pset_insert_ptr(live, op);
		}
	}
Sebastian Hack's avatar
Sebastian Hack committed
541

Christian Würdig's avatar
Christian Würdig committed
542
543
	n = pset_count(live);
	nodes = malloc(n * sizeof(nodes[0]));
Sebastian Hack's avatar
Sebastian Hack committed
544

Christian Würdig's avatar
Christian Würdig committed
545
546
547
548
549
	DBG((dbg, LEVEL_1, "live:\n"));
	for(irn = pset_first(live), i = 0; irn; irn = pset_next(live), i++) {
		DBG((dbg, LEVEL_1, "\t%+F\n", irn));
		nodes[i] = irn;
	}
550

Christian Würdig's avatar
Christian Würdig committed
551
552
553
	perm = new_Perm(env->node_factory, cls, irg, bl, n, nodes);
	sched_add_after(pos, perm);
	free(nodes);
554

Christian Würdig's avatar
Christian Würdig committed
555
556
557
558
	curr = perm;
	for(i = 0; i < n; ++i) {
		ir_node *copies[1];
		ir_node *perm_op = get_irn_n(perm, i);
Sebastian Hack's avatar
Sebastian Hack committed
559
	const arch_register_t *reg = arch_get_irn_register(arch_env, perm_op);
560

Christian Würdig's avatar
Christian Würdig committed
561
562
563
		ir_mode *mode = get_irn_mode(perm_op);
		ir_node *proj = new_r_Proj(irg, bl, perm, mode, i);
		arch_set_irn_register(arch_env, proj, reg);
564

Christian Würdig's avatar
Christian Würdig committed
565
566
		sched_add_after(curr, proj);
		curr = proj;
567

Christian Würdig's avatar
Christian Würdig committed
568
569
570
571
		copies[0] = proj;
		be_introduce_copies(dom_front, perm_op, array_size(copies), copies);
	}
	return perm;
Sebastian Hack's avatar
Sebastian Hack committed
572
}