1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"),
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * on the rights to use, copy, modify, merge, publish, distribute, sub
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * license, and/or sell copies of the Software, and to permit persons to whom
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the Software is furnished to do so, subject to the following conditions:
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the next
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * paragraph) shall be included in all copies or substantial portions of the
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software.
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_compiler.h"
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdarg.h>
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdio.h>
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdlib.h>
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_dataflow.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_program.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_program_pair.h"
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_compiler_util.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_init(struct radeon_compiler * c)
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memset(c, 0, sizeof(*c));
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memory_pool_init(&c->Pool);
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->Program.Instructions.Prev = &c->Program.Instructions;
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->Program.Instructions.Next = &c->Program.Instructions;
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->Program.Instructions.U.I.Opcode = RC_OPCODE_ILLEGAL_OPCODE;
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_destroy(struct radeon_compiler * c)
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_constants_destroy(&c->Program.Constants);
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memory_pool_destroy(&c->Pool);
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	free(c->ErrorMsg);
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_debug(struct radeon_compiler * c, const char * fmt, ...)
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	va_list ap;
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (!(c->Debug & RC_DBG_LOG))
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	va_start(ap, fmt);
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	vfprintf(stderr, fmt, ap);
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	va_end(ap);
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_error(struct radeon_compiler * c, const char * fmt, ...)
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	va_list ap;
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->Error = 1;
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (!c->ErrorMsg) {
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/* Only remember the first error */
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		char buf[1024];
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		int written;
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		va_start(ap, fmt);
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		written = vsnprintf(buf, sizeof(buf), fmt, ap);
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		va_end(ap);
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (written < sizeof(buf)) {
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			c->ErrorMsg = strdup(buf);
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		} else {
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			c->ErrorMsg = malloc(written + 1);
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			va_start(ap, fmt);
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			vsnprintf(c->ErrorMsg, written + 1, fmt, ap);
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			va_end(ap);
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (c->Debug & RC_DBG_LOG) {
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fprintf(stderr, "r300compiler error: ");
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		va_start(ap, fmt);
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		vfprintf(stderr, fmt, ap);
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		va_end(ap);
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint rc_if_fail_helper(struct radeon_compiler * c, const char * file, int line, const char * assertion)
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_error(c, "ICE at %s:%i: assertion failed: %s\n", file, line, assertion);
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return 1;
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Recompute c->Program.InputsRead and c->Program.OutputsWritten
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * based on which inputs and outputs are actually referenced
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * in program instructions.
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_calculate_inputs_outputs(struct radeon_compiler * c)
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction *inst;
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->Program.InputsRead = 0;
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->Program.OutputsWritten = 0;
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next)
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	{
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		int i;
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for (i = 0; i < opcode->NumSrcRegs; ++i) {
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT)
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				c->Program.InputsRead |= 1 << inst->U.I.SrcReg[i].Index;
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (opcode->HasDstReg) {
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (inst->U.I.DstReg.File == RC_FILE_OUTPUT)
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				c->Program.OutputsWritten |= 1 << inst->U.I.DstReg.Index;
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Rewrite the program such that everything that source the given input
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * register will source new_input instead.
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_move_input(struct radeon_compiler * c, unsigned input, struct rc_src_register new_input)
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst;
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->Program.InputsRead &= ~(1 << input);
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned i;
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for(i = 0; i < opcode->NumSrcRegs; ++i) {
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT && inst->U.I.SrcReg[i].Index == input) {
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.SrcReg[i].File = new_input.File;
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.SrcReg[i].Index = new_input.Index;
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.SrcReg[i].Swizzle = combine_swizzles(new_input.Swizzle, inst->U.I.SrcReg[i].Swizzle);
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (!inst->U.I.SrcReg[i].Abs) {
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					inst->U.I.SrcReg[i].Negate ^= new_input.Negate;
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					inst->U.I.SrcReg[i].Abs = new_input.Abs;
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				c->Program.InputsRead |= 1 << new_input.Index;
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Rewrite the program such that everything that writes into the given
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * output register will instead write to new_output. The new_output
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * writemask is honoured.
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_move_output(struct radeon_compiler * c, unsigned output, unsigned new_output, unsigned writemask)
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst;
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->Program.OutputsWritten &= ~(1 << output);
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (opcode->HasDstReg) {
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (inst->U.I.DstReg.File == RC_FILE_OUTPUT && inst->U.I.DstReg.Index == output) {
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.DstReg.Index = new_output;
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.DstReg.WriteMask &= writemask;
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				c->Program.OutputsWritten |= 1 << new_output;
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Rewrite the program such that a given output is duplicated.
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_copy_output(struct radeon_compiler * c, unsigned output, unsigned dup_output)
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned tempreg = rc_find_free_temporary(c);
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst;
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (opcode->HasDstReg) {
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (inst->U.I.DstReg.File == RC_FILE_OUTPUT && inst->U.I.DstReg.Index == output) {
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.DstReg.Index = tempreg;
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst = rc_insert_new_instruction(c, c->Program.Instructions.Prev);
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.Opcode = RC_OPCODE_MOV;
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.DstReg.File = RC_FILE_OUTPUT;
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.DstReg.Index = output;
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.SrcReg[0].Index = tempreg;
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst = rc_insert_new_instruction(c, c->Program.Instructions.Prev);
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.Opcode = RC_OPCODE_MOV;
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.DstReg.File = RC_FILE_OUTPUT;
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.DstReg.Index = dup_output;
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.SrcReg[0].Index = tempreg;
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->Program.OutputsWritten |= 1 << dup_output;
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Introduce standard code fragment to deal with fragment.position.
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_transform_fragment_wpos(struct radeon_compiler * c, unsigned wpos, unsigned new_input,
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                int full_vtransform)
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned tempregi = rc_find_free_temporary(c);
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst_rcp;
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst_mul;
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst_mad;
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * inst;
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->Program.InputsRead &= ~(1 << wpos);
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->Program.InputsRead |= 1 << new_input;
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* perspective divide */
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_rcp = rc_insert_new_instruction(c, &c->Program.Instructions);
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_rcp->U.I.Opcode = RC_OPCODE_RCP;
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_rcp->U.I.DstReg.File = RC_FILE_TEMPORARY;
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_rcp->U.I.DstReg.Index = tempregi;
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_rcp->U.I.DstReg.WriteMask = RC_MASK_W;
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_rcp->U.I.SrcReg[0].File = RC_FILE_INPUT;
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_rcp->U.I.SrcReg[0].Index = new_input;
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_rcp->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_WWWW;
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mul = rc_insert_new_instruction(c, inst_rcp);
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mul->U.I.Opcode = RC_OPCODE_MUL;
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY;
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mul->U.I.DstReg.Index = tempregi;
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mul->U.I.DstReg.WriteMask = RC_MASK_XYZ;
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mul->U.I.SrcReg[0].File = RC_FILE_INPUT;
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mul->U.I.SrcReg[0].Index = new_input;
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mul->U.I.SrcReg[1].File = RC_FILE_TEMPORARY;
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mul->U.I.SrcReg[1].Index = tempregi;
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mul->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_WWWW;
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* viewport transformation */
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad = rc_insert_new_instruction(c, inst_mul);
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad->U.I.Opcode = RC_OPCODE_MAD;
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad->U.I.DstReg.File = RC_FILE_TEMPORARY;
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad->U.I.DstReg.Index = tempregi;
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad->U.I.DstReg.WriteMask = RC_MASK_XYZ;
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad->U.I.SrcReg[0].Index = tempregi;
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZ0;
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad->U.I.SrcReg[1].File = RC_FILE_CONSTANT;
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XYZ0;
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad->U.I.SrcReg[2].File = RC_FILE_CONSTANT;
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_mad->U.I.SrcReg[2].Swizzle = RC_SWIZZLE_XYZ0;
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (full_vtransform) {
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst_mad->U.I.SrcReg[1].Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_R300_VIEWPORT_SCALE, 0);
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst_mad->U.I.SrcReg[2].Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_R300_VIEWPORT_OFFSET, 0);
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else {
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst_mad->U.I.SrcReg[1].Index =
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		inst_mad->U.I.SrcReg[2].Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_R300_WINDOW_DIMENSION, 0);
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for (inst = inst_mad->Next; inst != &c->Program.Instructions; inst = inst->Next) {
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned i;
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for(i = 0; i < opcode->NumSrcRegs; i++) {
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT &&
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    inst->U.I.SrcReg[i].Index == wpos) {
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.SrcReg[i].File = RC_FILE_TEMPORARY;
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.SrcReg[i].Index = tempregi;
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The FACE input in hardware contains 1 if it's a back face, 0 otherwise.
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Gallium and OpenGL define it the other way around.
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * So let's just negate FACE at the beginning of the shader and rewrite the rest
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of the shader to read from the newly allocated temporary.
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_transform_fragment_face(struct radeon_compiler *c, unsigned face)
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned tempregi = rc_find_free_temporary(c);
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction *inst_add;
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction *inst;
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* perspective divide */
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_add = rc_insert_new_instruction(c, &c->Program.Instructions);
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_add->U.I.Opcode = RC_OPCODE_ADD;
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_add->U.I.DstReg.File = RC_FILE_TEMPORARY;
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_add->U.I.DstReg.Index = tempregi;
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_add->U.I.DstReg.WriteMask = RC_MASK_X;
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_add->U.I.SrcReg[0].File = RC_FILE_NONE;
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_add->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_1111;
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_add->U.I.SrcReg[1].File = RC_FILE_INPUT;
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_add->U.I.SrcReg[1].Index = face;
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_add->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XXXX;
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	inst_add->U.I.SrcReg[1].Negate = RC_MASK_XYZW;
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for (inst = inst_add->Next; inst != &c->Program.Instructions; inst = inst->Next) {
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned i;
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for(i = 0; i < opcode->NumSrcRegs; i++) {
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT &&
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    inst->U.I.SrcReg[i].Index == face) {
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.SrcReg[i].File = RC_FILE_TEMPORARY;
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.SrcReg[i].Index = tempregi;
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void reg_count_callback(void * userdata, struct rc_instruction * inst,
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_register_file file, unsigned int index, unsigned int mask)
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_program_stats *s = userdata;
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (file == RC_FILE_TEMPORARY)
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		(int)index > s->num_temp_regs ? s->num_temp_regs = index : 0;
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (file == RC_FILE_INLINE)
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		s->num_inline_literals++;
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_get_stats(struct radeon_compiler *c, struct rc_program_stats *s)
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_instruction * tmp;
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memset(s, 0, sizeof(*s));
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(tmp = c->Program.Instructions.Next; tmp != &c->Program.Instructions;
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org							tmp = tmp->Next){
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		const struct rc_opcode_info * info;
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_for_all_reads_mask(tmp, reg_count_callback, s);
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (tmp->Type == RC_INSTRUCTION_NORMAL) {
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			info = rc_get_opcode_info(tmp->U.I.Opcode);
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (info->Opcode == RC_OPCODE_BEGIN_TEX)
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				continue;
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (tmp->U.I.PreSub.Opcode != RC_PRESUB_NONE)
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				s->num_presub_ops++;
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		} else {
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (tmp->U.P.RGB.Src[RC_PAIR_PRESUB_SRC].Used)
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				s->num_presub_ops++;
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (tmp->U.P.Alpha.Src[RC_PAIR_PRESUB_SRC].Used)
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				s->num_presub_ops++;
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/* Assuming alpha will never be a flow control or
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * a tex instruction. */
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (tmp->U.P.Alpha.Opcode != RC_OPCODE_NOP)
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				s->num_alpha_insts++;
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (tmp->U.P.RGB.Opcode != RC_OPCODE_NOP)
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				s->num_rgb_insts++;
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (tmp->U.P.RGB.Omod != RC_OMOD_MUL_1 &&
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				tmp->U.P.RGB.Omod != RC_OMOD_DISABLE) {
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				s->num_omod_ops++;
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (tmp->U.P.Alpha.Omod != RC_OMOD_MUL_1 &&
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				tmp->U.P.Alpha.Omod != RC_OMOD_DISABLE) {
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				s->num_omod_ops++;
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			info = rc_get_opcode_info(tmp->U.P.RGB.Opcode);
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (info->IsFlowControl)
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			s->num_fc_insts++;
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (info->HasTexture)
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			s->num_tex_insts++;
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		s->num_insts++;
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Increment here because the reg_count_callback store the max
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * temporary reg index in s->nun_temp_regs. */
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	s->num_temp_regs++;
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void print_stats(struct radeon_compiler * c)
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_program_stats s;
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (c->initial_num_insts <= 5)
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_get_stats(c, &s);
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	switch (c->type) {
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	case RC_VERTEX_PROGRAM:
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fprintf(stderr,"~~~~~~~~~ VERTEX PROGRAM ~~~~~~~~\n"
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u Instructions\n"
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u Flow Control Instructions\n"
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u Temporary Registers\n"
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~~~~~~~~~~~~~~ END ~~~~~~~~~~~~~~\n",
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       s.num_insts, s.num_fc_insts, s.num_temp_regs);
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		break;
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	case RC_FRAGMENT_PROGRAM:
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fprintf(stderr,"~~~~~~~~ FRAGMENT PROGRAM ~~~~~~~\n"
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u Instructions\n"
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u Vector Instructions (RGB)\n"
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u Scalar Instructions (Alpha)\n"
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u Flow Control Instructions\n"
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u Texture Instructions\n"
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u Presub Operations\n"
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u OMOD Operations\n"
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u Temporary Registers\n"
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~%4u Inline Literals\n"
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "~~~~~~~~~~~~~~ END ~~~~~~~~~~~~~~\n",
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       s.num_insts, s.num_rgb_insts, s.num_alpha_insts,
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       s.num_fc_insts, s.num_tex_insts, s.num_presub_ops,
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       s.num_omod_ops, s.num_temp_regs, s.num_inline_literals);
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		break;
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	default:
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		assert(0);
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char *shader_name[RC_NUM_PROGRAM_TYPES] = {
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	"Vertex Program",
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	"Fragment Program"
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_run_compiler_passes(struct radeon_compiler *c, struct radeon_compiler_pass *list)
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for (unsigned i = 0; list[i].name; i++) {
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (list[i].predicate) {
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			list[i].run(c, list[i].user);
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (c->Error)
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				return;
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if ((c->Debug & RC_DBG_LOG) && list[i].dump) {
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fprintf(stderr, "%s: after '%s'\n", shader_name[c->type], list[i].name);
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				rc_print_program(&c->Program);
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Executes a list of compiler passes given in the parameter 'list'. */
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_run_compiler(struct radeon_compiler *c, struct radeon_compiler_pass *list)
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct rc_program_stats s;
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_get_stats(c, &s);
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	c->initial_num_insts = s.num_insts;
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (c->Debug & RC_DBG_LOG) {
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fprintf(stderr, "%s: before compilation\n", shader_name[c->type]);
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_print_program(&c->Program);
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_run_compiler_passes(c, list);
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (c->Debug & RC_DBG_STATS)
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		print_stats(c);
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_validate_final_shader(struct radeon_compiler *c, void *user)
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Check the number of constants. */
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (c->Program.Constants.Count > c->max_constants) {
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_error(c, "Too many constants. Max: %i, Got: %i\n",
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 c->max_constants, c->Program.Constants.Count);
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
503