1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (C) 2009 Nicolai Haehnle.
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * All Rights Reserved.
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * a copy of this software and associated documentation files (the
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * "Software"), to deal in the Software without restriction, including
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * without limitation the rights to use, copy, modify, merge, publish,
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * distribute, sublicense, and/or sell copies of the Software, and to
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * permit persons to whom the Software is furnished to do so, subject to
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the following conditions:
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * next paragraph) shall be included in all copies or substantial
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * portions of the Software.
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_dataflow.h"
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "radeon_compiler.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct updatemask_state {
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned char Output[RC_REGISTER_MAX_INDEX];
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned char Temporary[RC_REGISTER_MAX_INDEX];
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned char Address;
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned char Special[RC_NUM_SPECIAL_REGISTERS];
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct instruction_state {
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned char WriteMask:4;
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned char WriteALUResult:1;
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned char SrcReg[3];
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct loopinfo {
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct updatemask_state * Breaks;
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int BreakCount;
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int BreaksReserved;
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct branchinfo {
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int HaveElse:1;
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct updatemask_state StoreEndif;
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct updatemask_state StoreElse;
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct deadcode_state {
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct radeon_compiler * C;
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct instruction_state * Instructions;
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct updatemask_state R;
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct branchinfo * BranchStack;
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int BranchStackSize;
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int BranchStackReserved;
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct loopinfo * LoopStack;
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int LoopStackSize;
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int LoopStackReserved;
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void or_updatemasks(
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct updatemask_state * dst,
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct updatemask_state * a,
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct updatemask_state * b)
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(unsigned int i = 0; i < RC_REGISTER_MAX_INDEX; ++i) {
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		dst->Output[i] = a->Output[i] | b->Output[i];
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		dst->Temporary[i] = a->Temporary[i] | b->Temporary[i];
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(unsigned int i = 0; i < RC_NUM_SPECIAL_REGISTERS; ++i)
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		dst->Special[i] = a->Special[i] | b->Special[i];
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	dst->Address = a->Address | b->Address;
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void push_break(struct deadcode_state *s)
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct loopinfo * loop = &s->LoopStack[s->LoopStackSize - 1];
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memory_pool_array_reserve(&s->C->Pool, struct updatemask_state,
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		loop->Breaks, loop->BreakCount, loop->BreaksReserved, 1);
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memcpy(&loop->Breaks[loop->BreakCount++], &s->R, sizeof(s->R));
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void push_loop(struct deadcode_state * s)
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memory_pool_array_reserve(&s->C->Pool, struct loopinfo, s->LoopStack,
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			s->LoopStackSize, s->LoopStackReserved, 1);
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memset(&s->LoopStack[s->LoopStackSize++], 0, sizeof(struct loopinfo));
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void push_branch(struct deadcode_state * s)
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct branchinfo * branch;
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memory_pool_array_reserve(&s->C->Pool, struct branchinfo, s->BranchStack,
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			s->BranchStackSize, s->BranchStackReserved, 1);
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	branch = &s->BranchStack[s->BranchStackSize++];
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	branch->HaveElse = 0;
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memcpy(&branch->StoreEndif, &s->R, sizeof(s->R));
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic unsigned char * get_used_ptr(struct deadcode_state *s, rc_register_file file, unsigned int index)
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (file == RC_FILE_OUTPUT || file == RC_FILE_TEMPORARY) {
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (index >= RC_REGISTER_MAX_INDEX) {
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			rc_error(s->C, "%s: index %i is out of bounds for file %i\n", __FUNCTION__, index, file);
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return 0;
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (file == RC_FILE_OUTPUT)
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return &s->R.Output[index];
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return &s->R.Temporary[index];
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else if (file == RC_FILE_ADDRESS) {
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return &s->R.Address;
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} else if (file == RC_FILE_SPECIAL) {
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (index >= RC_NUM_SPECIAL_REGISTERS) {
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			rc_error(s->C, "%s: special file index %i out of bounds\n", __FUNCTION__, index);
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			return 0;
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return &s->R.Special[index];
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return 0;
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void mark_used(struct deadcode_state * s, rc_register_file file, unsigned int index, unsigned int mask)
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned char * pused = get_used_ptr(s, file, index);
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (pused)
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		*pused |= mask;
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void update_instruction(struct deadcode_state * s, struct rc_instruction * inst)
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct instruction_state * insts = &s->Instructions[inst->IP];
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int usedmask = 0;
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int srcmasks[3];
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (opcode->HasDstReg) {
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned char * pused = get_used_ptr(s, inst->U.I.DstReg.File, inst->U.I.DstReg.Index);
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (pused) {
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			usedmask = *pused & inst->U.I.DstReg.WriteMask;
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			*pused &= ~usedmask;
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	insts->WriteMask |= usedmask;
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (inst->U.I.WriteALUResult) {
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned char * pused = get_used_ptr(s, RC_FILE_SPECIAL, RC_SPECIAL_ALU_RESULT);
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (pused && *pused) {
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (inst->U.I.WriteALUResult == RC_ALURESULT_X)
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				usedmask |= RC_MASK_X;
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else if (inst->U.I.WriteALUResult == RC_ALURESULT_W)
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				usedmask |= RC_MASK_W;
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			*pused = 0;
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			insts->WriteALUResult = 1;
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_compute_sources_for_writemask(inst, usedmask, srcmasks);
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) {
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int refmask = 0;
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int newsrcmask = srcmasks[src] & ~insts->SrcReg[src];
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		insts->SrcReg[src] |= newsrcmask;
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for(unsigned int chan = 0; chan < 4; ++chan) {
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (GET_BIT(newsrcmask, chan))
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				refmask |= 1 << GET_SWZ(inst->U.I.SrcReg[src].Swizzle, chan);
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/* get rid of spurious bits from ZERO, ONE, etc. swizzles */
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		refmask &= RC_MASK_XYZW;
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (!refmask)
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			continue;
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		mark_used(s, inst->U.I.SrcReg[src].File, inst->U.I.SrcReg[src].Index, refmask);
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (inst->U.I.SrcReg[src].RelAddr)
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			mark_used(s, RC_FILE_ADDRESS, 0, RC_MASK_X);
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void mark_output_use(void * data, unsigned int index, unsigned int mask)
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct deadcode_state * s = data;
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	mark_used(s, RC_FILE_OUTPUT, index, mask);
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid rc_dataflow_deadcode(struct radeon_compiler * c, void *user)
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct deadcode_state s;
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int nr_instructions;
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_dataflow_mark_outputs_fn dce = (rc_dataflow_mark_outputs_fn)user;
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned int ip;
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memset(&s, 0, sizeof(s));
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	s.C = c;
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	nr_instructions = rc_recompute_ips(c);
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	s.Instructions = memory_pool_malloc(&c->Pool, sizeof(struct instruction_state)*nr_instructions);
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	memset(s.Instructions, 0, sizeof(struct instruction_state)*nr_instructions);
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	dce(c, &s, &mark_output_use);
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(struct rc_instruction * inst = c->Program.Instructions.Prev;
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    inst != &c->Program.Instructions;
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    inst = inst->Prev) {
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		switch(opcode->Opcode){
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/* Mark all sources in the loop body as used before doing
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * normal deadcode analysis.  This is probably not optimal.
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 */
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case RC_OPCODE_ENDLOOP:
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		{
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			int endloops = 1;
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			struct rc_instruction *ptr;
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			for(ptr = inst->Prev; endloops > 0; ptr = ptr->Prev){
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				opcode = rc_get_opcode_info(ptr->U.I.Opcode);
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if(ptr->U.I.Opcode == RC_OPCODE_BGNLOOP){
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					endloops--;
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					continue;
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if(ptr->U.I.Opcode == RC_OPCODE_ENDLOOP){
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					endloops++;
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					continue;
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if(opcode->HasDstReg){
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					int src = 0;
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					unsigned int srcmasks[3];
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					rc_compute_sources_for_writemask(ptr,
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						ptr->U.I.DstReg.WriteMask, srcmasks);
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					for(src=0; src < opcode->NumSrcRegs; src++){
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						mark_used(&s,
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org							ptr->U.I.SrcReg[src].File,
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org							ptr->U.I.SrcReg[src].Index,
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org							srcmasks[src]);
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					}
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			push_loop(&s);
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case RC_OPCODE_BRK:
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			push_break(&s);
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case RC_OPCODE_BGNLOOP:
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		{
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned int i;
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			struct loopinfo * loop = &s.LoopStack[s.LoopStackSize-1];
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			for(i = 0; i < loop->BreakCount; i++) {
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				or_updatemasks(&s.R, &s.R, &loop->Breaks[i]);
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case RC_OPCODE_CONT:
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case RC_OPCODE_ENDIF:
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			push_branch(&s);
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		default:
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (opcode->IsFlowControl && s.BranchStackSize) {
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				struct branchinfo * branch = &s.BranchStack[s.BranchStackSize-1];
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (opcode->Opcode == RC_OPCODE_IF) {
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					or_updatemasks(&s.R,
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org							&s.R,
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org							branch->HaveElse ? &branch->StoreElse : &branch->StoreEndif);
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					s.BranchStackSize--;
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				} else if (opcode->Opcode == RC_OPCODE_ELSE) {
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					if (branch->HaveElse) {
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						rc_error(c, "%s: Multiple ELSE for one IF/ENDIF\n", __FUNCTION__);
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					} else {
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						memcpy(&branch->StoreElse, &s.R, sizeof(s.R));
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						memcpy(&s.R, &branch->StoreEndif, sizeof(s.R));
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						branch->HaveElse = 1;
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					}
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				} else {
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					rc_error(c, "%s: Unhandled control flow instruction %s\n", __FUNCTION__, opcode->Name);
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		update_instruction(&s, inst);
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	ip = 0;
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for(struct rc_instruction * inst = c->Program.Instructions.Next;
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    inst != &c->Program.Instructions;
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    inst = inst->Next, ++ip) {
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		int dead = 1;
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int srcmasks[3];
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		unsigned int usemask;
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (!opcode->HasDstReg) {
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			dead = 0;
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		} else {
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			inst->U.I.DstReg.WriteMask = s.Instructions[ip].WriteMask;
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (s.Instructions[ip].WriteMask)
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				dead = 0;
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (s.Instructions[ip].WriteALUResult)
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				dead = 0;
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				inst->U.I.WriteALUResult = RC_ALURESULT_NONE;
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (dead) {
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			struct rc_instruction * todelete = inst;
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			inst = inst->Prev;
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			rc_remove_instruction(todelete);
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			continue;
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		usemask = s.Instructions[ip].WriteMask;
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (inst->U.I.WriteALUResult == RC_ALURESULT_X)
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			usemask |= RC_MASK_X;
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else if (inst->U.I.WriteALUResult == RC_ALURESULT_W)
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			usemask |= RC_MASK_W;
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		rc_compute_sources_for_writemask(inst, usemask, srcmasks);
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for(unsigned int src = 0; src < 3; ++src) {
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			for(unsigned int chan = 0; chan < 4; ++chan) {
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (!GET_BIT(srcmasks[src], chan))
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					SET_SWZ(inst->U.I.SrcReg[src].Swizzle, chan, RC_SWIZZLE_UNUSED);
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	rc_calculate_inputs_outputs(c);
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
360