Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
 
3
/*
4
 * Copyright (C) 2014 Rob Clark 
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice (including the next
14
 * paragraph) shall be included in all copies or substantial portions of the
15
 * Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 * SOFTWARE.
24
 *
25
 * Authors:
26
 *    Rob Clark 
27
 */
28
 
29
#include 
30
 
31
#include "ir3.h"
32
 
33
/*
34
 * Flatten: flatten out legs of if/else, etc
35
 *
36
 * TODO probably should use some heuristic to decide to not flatten
37
 * if one side of the other is too large / deeply nested / whatever?
38
 */
39
 
40
struct ir3_flatten_ctx {
41
	struct ir3_block *block;
42
	unsigned cnt;
43
};
44
 
45
static struct ir3_register *unwrap(struct ir3_register *reg)
46
{
47
 
48
	if (reg->flags & IR3_REG_SSA) {
49
		struct ir3_instruction *instr = reg->instr;
50
		if (is_meta(instr)) {
51
			switch (instr->opc) {
52
			case OPC_META_OUTPUT:
53
			case OPC_META_FLOW:
54
				if (instr->regs_count > 1)
55
					return instr->regs[1];
56
				return NULL;
57
			default:
58
				break;
59
			}
60
		}
61
	}
62
	return reg;
63
}
64
 
65
static void ir3_instr_flatten(struct ir3_flatten_ctx *ctx,
66
		struct ir3_instruction *instr)
67
{
68
	struct ir3_instruction *src;
69
 
70
	/* if we've already visited this instruction, bail now: */
71
	if (ir3_instr_check_mark(instr))
72
		return;
73
 
74
	instr->block = ctx->block;
75
 
76
	/* TODO: maybe some threshold to decide whether to
77
	 * flatten or not??
78
	 */
79
	if (is_meta(instr)) {
80
		if (instr->opc == OPC_META_PHI) {
81
			struct ir3_register *cond, *t, *f;
82
 
83
			cond = unwrap(instr->regs[1]);
84
			t    = unwrap(instr->regs[2]);  /* true val */
85
			f    = unwrap(instr->regs[3]);  /* false val */
86
 
87
			/* must have cond, but t or f may be null if only written
88
			 * one one side of the if/else (in which case we can just
89
			 * convert the PHI to a simple move).
90
			 */
91
			assert(cond);
92
			assert(t || f);
93
 
94
			if (t && f) {
95
				/* convert the PHI instruction to sel.{b16,b32} */
96
				instr->category = 3;
97
 
98
				/* instruction type based on dst size: */
99
				if (instr->regs[0]->flags & IR3_REG_HALF)
100
					instr->opc = OPC_SEL_B16;
101
				else
102
					instr->opc = OPC_SEL_B32;
103
 
104
				instr->regs[1] = t;
105
				instr->regs[2] = cond;
106
				instr->regs[3] = f;
107
			} else {
108
				/* convert to simple mov: */
109
				instr->category = 1;
110
				instr->cat1.dst_type = TYPE_F32;
111
				instr->cat1.src_type = TYPE_F32;
112
				instr->regs_count = 2;
113
				instr->regs[1] = t ? t : f;
114
			}
115
 
116
			ctx->cnt++;
117
		} else if ((instr->opc == OPC_META_INPUT) &&
118
				(instr->regs_count == 2)) {
119
			type_t ftype;
120
 
121
			if (instr->regs[0]->flags & IR3_REG_HALF)
122
				ftype = TYPE_F16;
123
			else
124
				ftype = TYPE_F32;
125
 
126
			/* convert meta:input to mov: */
127
			instr->category = 1;
128
			instr->cat1.src_type = ftype;
129
			instr->cat1.dst_type = ftype;
130
		}
131
	}
132
 
133
	/* recursively visit children: */
134
	foreach_ssa_src(src, instr)
135
		ir3_instr_flatten(ctx, src);
136
}
137
 
138
/* return >= 0 is # of phi's flattened, < 0 is error */
139
int ir3_block_flatten(struct ir3_block *block)
140
{
141
	struct ir3_flatten_ctx ctx = {
142
			.block = block,
143
	};
144
	unsigned i;
145
 
146
	ir3_clear_mark(block->shader);
147
	for(i = 0; i < block->noutputs; i++)
148
		if (block->outputs[i])
149
			ir3_instr_flatten(&ctx, block->outputs[i]);
150
 
151
	return ctx.cnt;
152
}