amd64_finish.c 3.14 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
 * Copyright (C) 1995-2012 University of Karlsruhe.  All right reserved.
 *
 * This file is part of libFirm.
 *
 * 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.
 *
 * 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.
 */

/**
 * @file
 * @brief   This file implements functions to finalize the irg for emit.
 */
#include "amd64_finish.h"
#include "bearch.h"
#include "benode.h"
#include "besched.h"
#include "debug.h"
#include "error.h"
30
#include "amd64_nodes_attr.h"
31
32
33
34
35
36
37
38
#include "gen_amd64_new_nodes.h"
#include "irgwalk.h"

DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

/**
 * Returns the index of the first "same" register.
 */
Matthias Braun's avatar
Matthias Braun committed
39
static unsigned get_first_same(arch_register_req_t const *const req)
40
41
{
	unsigned const other = req->other_same;
Matthias Braun's avatar
Matthias Braun committed
42
	for (unsigned i = 0; i != 32; ++i) {
43
44
45
46
47
48
49
50
51
52
53
54
		if (other & (1U << i))
			return i;
	}
	panic("same position not found");
}

/**
 * Insert copies for all amd64 nodes where the should_be_same requirement is
 * not fulfilled.
 */
static void assure_should_be_same_requirements(ir_node *const node)
{
Matthias Braun's avatar
Matthias Braun committed
55
	unsigned const n_res = arch_get_irn_n_outs(node);
56
57

	/* Check all OUT requirements, if there is a should_be_same. */
Matthias Braun's avatar
Matthias Braun committed
58
59
60
61
62
63
64
65
66
67
68
69
	for (unsigned i = 0; i < n_res; ++i) {
		arch_register_req_t const *const req
			= arch_get_irn_register_req_out(node, i);
		if (!arch_register_req_is(req, should_be_same))
			continue;
		unsigned               const same_pos = get_first_same(req);
		ir_node               *const in_node  = get_irn_n(node, same_pos);
		arch_register_t const *const in_reg   = arch_get_irn_register(in_node);
		arch_register_t const *const out_reg
			= arch_get_irn_register_out(node, i);
		if (in_reg == out_reg)
			continue;
70

Matthias Braun's avatar
Matthias Braun committed
71
72
		ir_node *const block = get_nodes_block(node);
		ir_node *const copy  = be_new_Copy(block, in_node);
73

Matthias Braun's avatar
Matthias Braun committed
74
75
76
77
78
79
80
81
		/* Destination is the out register. */
		arch_set_irn_register(copy, out_reg);
		/* Insert copy before the node into the schedule. */
		sched_add_before(node, copy);
		/* Set copy as in. */
		set_irn_n(node, same_pos, copy);

		DBG((dbg, LEVEL_1, "created copy %+F for should be same argument at input %d of %+F\n", copy, same_pos, node));
82
83
84
85
86
87
88
89
90
91
92
	}
}

/**
 * Block walker: finishes a block.
 */
static void amd64_finish_irg_walker(ir_node *const block, void *const env)
{
	(void) env;

	/* Insert should_be_same copies. */
Matthias Braun's avatar
Matthias Braun committed
93
94
	for (ir_node *irn = sched_first(block), *next; !sched_is_end(irn);
	     irn = next) {
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
		next = sched_next(irn);
		if (is_amd64_irn(irn)) {
			assure_should_be_same_requirements(irn);
		}
	}
}

/**
 * Add Copy nodes for not fulfilled should_be_same constraints.
 */
void amd64_finish_irg(ir_graph *const irg)
{
	irg_block_walk_graph(irg, 0, amd64_finish_irg_walker, 0);
}

void amd64_init_finish(void)
{
	FIRM_DBG_REGISTER(dbg, "firm.be.amd64.finish");
}