condeval.c 2.71 KB
Newer Older
1
2
3
4
5
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef HAVE_ALLOCA_H
6
#include <alloca.h>
7
8
9
10
11
12
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif

#include <assert.h>
13
14
15
16
17
18
19
20
21
#include "array.h"
#include "debug.h"
#include "ircons.h"
#include "irgwalk.h"
#include "irnode.h"
#include "tv.h"

DEBUG_ONLY(static firm_dbg_module_t *dbg);

22
23
24
/**
 * Block-walker:
 */
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
static void cond_eval(ir_node* block, void* env)
{
	int n_block = get_Block_n_cfgpreds(block);
	int i;

	for (i = 0; i < n_block; i++) {
		ir_node* pred;
		ir_node* projx;
		ir_node* cond;
		ir_node* cmp;
		ir_node* left;
		ir_node* right;
		ir_node* cond_block;
		ir_node* phi;
		ir_node* cnst;
		pn_Cmp pnc;
		int n_phi;
		int j;

		pred = get_Block_cfgpred(block, i);
		if (!is_Proj(pred)) continue;
		projx = pred;

		pred = get_Proj_pred(projx);
		if (!is_Cond(pred)) continue;
		cond = pred;

		pred = get_Cond_selector(cond);
		assert(is_Proj(pred));
		// TODO handle switches
		if (get_irn_mode(pred) != mode_b) continue;
		pnc = get_Proj_proj(pred);

		cmp = get_Proj_pred(pred);
		assert(is_Cmp(cmp));

		left  = get_Cmp_left(cmp);
		right = get_Cmp_right(cmp);

		// TODO handle Const-Const and Phi-Phi
		if (is_Phi(left)) {
			if (!is_Const(right)) continue;
			phi  = left;
			cnst = right;
		} else if (is_Phi(right)) {
			if (!is_Const(left)) continue;
			phi  = right;
			cnst = left;
			pnc = get_inversed_pnc(pnc);
		} else {
			continue;
		}

		cond_block = get_nodes_block(cond);
		if (get_nodes_block(phi) != cond_block) continue;

		if (get_Proj_proj(projx) == 0) pnc = get_negated_pnc(pnc, get_irn_mode(cnst));

		n_phi = get_Phi_n_preds(phi);
		for (j = 0; j < n_phi; j++) {
			tarval* tv_phi;
			tarval* tv_cnst;
			ir_node** ins;
			int k;
89
			pn_Cmp cmp_val;
90
91
92
93
94
95
96
97

			pred = get_Phi_pred(phi, j);
			// TODO handle Phi cascades
			if (!is_Const(pred)) continue;

			tv_phi  = get_Const_tarval(pred);
			tv_cnst = get_Const_tarval(cnst);

98
99
100
101
102
			cmp_val = tarval_cmp(tv_phi, tv_cnst);
			if (cmp_val == pn_Cmp_False)
				continue;
			if ((cmp_val & pnc) != cmp_val)
				continue;
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

			DB((
				dbg, LEVEL_1,
				"> Found condition evaluation candidate %+F->%+F predecessor %d\n",
				block, cond_block, j
			));

#if 0 // TODO repair data flow and dominance
			NEW_ARR_A(ir_node*, ins, n_block + 1);
			for (k = 0; k < n_block; k++) ins[k] = get_Block_cfgpred(block, k);
			ins[k] = get_Block_cfgpred(cond_block, j);
			set_irn_in(block, n_block + 1, ins);

			set_Block_cfgpred(cond_block, j, new_Bad());
			set_Phi_pred(phi, j, new_Bad());
#endif
		}
	}
}


void opt_cond_eval(ir_graph* irg)
{
	FIRM_DBG_REGISTER(dbg, "firm.opt.condeval");
127
    firm_dbg_set_mask(dbg, SET_LEVEL_5);
128
129
130
131
132

	DB((dbg, LEVEL_1, "===> Performing condition evaluation on %+F\n", irg));

	irg_block_walk_graph(irg, NULL, cond_eval, NULL);
}