11c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/*
21c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Copyright 2011 Tom Stellard <tstellar@gmail.com>
31c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
41c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * All Rights Reserved.
51c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
61c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Permission is hereby granted, free of charge, to any person obtaining
71c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * a copy of this software and associated documentation files (the
81c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * "Software"), to deal in the Software without restriction, including
91c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * without limitation the rights to use, copy, modify, merge, publish,
101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * distribute, sublicense, and/or sell copies of the Software, and to
111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * permit persons to whom the Software is furnished to do so, subject to
121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * the following conditions:
131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * The above copyright notice and this permission notice (including the
151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * next paragraph) shall be included in all copies or substantial
161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * portions of the Software.
171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák *
261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_variable.h"
291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "memory_pool.h"
311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_compiler_util.h"
321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_dataflow.h"
331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_list.h"
341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_opcodes.h"
351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák#include "radeon_program.h"
361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Rewrite the index and writemask for the destination register of var
391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * and its friends to new_index and new_writemask.  This function also takes
401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * care of rewriting the swizzles for the sources of var.
411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_variable_change_dst(
431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_variable * var,
441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int new_index,
451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int new_writemask)
461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_variable * var_ptr;
481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_list * readers;
491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int old_mask = rc_variable_writemask_sum(var);
501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int conversion_swizzle =
511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			rc_make_conversion_swizzle(old_mask, new_writemask);
521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for (var_ptr = var; var_ptr; var_ptr = var_ptr->Friend) {
541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (var_ptr->Inst->Type == RC_INSTRUCTION_NORMAL) {
551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			rc_normal_rewrite_writemask(var_ptr->Inst,
561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							conversion_swizzle);
571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			var_ptr->Inst->U.I.DstReg.Index = new_index;
581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		} else {
591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			struct rc_pair_sub_instruction * sub;
601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (var_ptr->Dst.WriteMask == RC_MASK_W) {
611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				assert(new_writemask & RC_MASK_W);
621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				sub = &var_ptr->Inst->U.P.Alpha;
631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			} else {
641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				sub = &var_ptr->Inst->U.P.RGB;
651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				rc_pair_rewrite_writemask(sub,
661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							conversion_swizzle);
671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			sub->DestIndex = new_index;
691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	readers = rc_variable_readers_union(var);
731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for ( ; readers; readers = readers->Next) {
751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		struct rc_reader * reader = readers->Item;
761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (reader->Inst->Type == RC_INSTRUCTION_NORMAL) {
771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			reader->U.I.Src->Index = new_index;
781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			reader->U.I.Src->Swizzle = rc_rewrite_swizzle(
791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				reader->U.I.Src->Swizzle, conversion_swizzle);
801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		} else {
811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			struct rc_pair_instruction * pair_inst =
821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							&reader->Inst->U.P;
831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int src_type = rc_source_type_swz(
841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							reader->U.P.Arg->Swizzle);
851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			int src_index = reader->U.P.Arg->Source;
871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (src_index == RC_PAIR_PRESUB_SRC) {
881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				src_index = rc_pair_get_src_index(
891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						pair_inst, reader->U.P.Src);
901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			/* Try to delete the old src, it is OK if this fails,
921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * because rc_pair_alloc_source might be able to
931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * find a source the ca be reused.
941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 */
951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (rc_pair_remove_src(reader->Inst, src_type,
961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							src_index, old_mask)) {
971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				/* Reuse the source index of the source that
981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 * was just deleted and set its register
991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 * index.  We can't use rc_pair_alloc_source
1001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 * for this becuase it might return a source
1011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				 * index that is already being used. */
1021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				if (src_type & RC_SOURCE_RGB) {
1031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					pair_inst->RGB.Src[src_index]
1041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						.Used =	1;
1051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					pair_inst->RGB.Src[src_index]
1061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						.Index = new_index;
1071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					pair_inst->RGB.Src[src_index]
1081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						.File = RC_FILE_TEMPORARY;
1091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				}
1101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				if (src_type & RC_SOURCE_ALPHA) {
1111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					pair_inst->Alpha.Src[src_index]
1121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						.Used = 1;
1131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					pair_inst->Alpha.Src[src_index]
1141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						.Index = new_index;
1151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					pair_inst->Alpha.Src[src_index]
1161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						.File = RC_FILE_TEMPORARY;
1171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				}
1181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			} else {
1191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				src_index = rc_pair_alloc_source(
1201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						&reader->Inst->U.P,
1211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						src_type & RC_SOURCE_RGB,
1221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						src_type & RC_SOURCE_ALPHA,
1231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						RC_FILE_TEMPORARY,
1241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						new_index);
1251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				if (src_index < 0) {
1261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					rc_error(var->C, "Rewrite of inst %u failed "
1271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						"Can't allocate source for "
1281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						"Inst %u src_type=%x "
1291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						"new_index=%u new_mask=%u\n",
1301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						var->Inst->IP, reader->Inst->IP, src_type, new_index, new_writemask);
1311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						continue;
1321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				}
1331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
1341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			reader->U.P.Arg->Swizzle = rc_rewrite_swizzle(
1351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				reader->U.P.Arg->Swizzle, conversion_swizzle);
1361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (reader->U.P.Arg->Source != RC_PAIR_PRESUB_SRC) {
1371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				reader->U.P.Arg->Source = src_index;
1381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
1391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
1401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
1411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
1421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
1441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Compute the live intervals for var and its friends.
1451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
1461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_variable_compute_live_intervals(struct rc_variable * var)
1471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
1481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	while(var) {
1491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		unsigned int i;
1501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		unsigned int start = var->Inst->IP;
1511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		for (i = 0; i < var->ReaderCount; i++) {
1531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int chan;
1541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int chan_start = start;
1551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int chan_end = var->Readers[i].Inst->IP;
1561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int mask = var->Readers[i].WriteMask;
1571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			struct rc_instruction * inst;
1581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			/* Extend the live interval of T0 to the start of the
1601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * loop for sequences like:
1611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * BGNLOOP
1621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * read T0
1631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * ...
1641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * write T0
1651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * ENDLOOP
1661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 */
1671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (var->Readers[i].Inst->IP < start) {
1681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				struct rc_instruction * bgnloop =
1691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					rc_match_endloop(var->Readers[i].Inst);
1701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				chan_start = bgnloop->IP;
1711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
1721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
1731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			/* Extend the live interval of T0 to the start of the
1741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * loop in case there is a BRK instruction in the loop
1751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * (we don't actually check for a BRK instruction we
1761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * assume there is one somewhere in the loop, which
1771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * there usually is) for sequences like:
1781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * BGNLOOP
1791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * ...
1801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * conditional BRK
1811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * ...
1821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * write T0
1831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * ENDLOOP
1841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * read T0
1851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 ***************************************************
1861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * Extend the live interval of T0 to the end of the
1871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * loop for sequences like:
1881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * write T0
1891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * BGNLOOP
1901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * ...
1911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * read T0
1921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * ENDLOOP
1931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 */
1941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			for (inst = var->Inst; inst != var->Readers[i].Inst;
1951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							inst = inst->Next) {
1961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				rc_opcode op = rc_get_flow_control_inst(inst);
1971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				if (op == RC_OPCODE_ENDLOOP) {
1981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					struct rc_instruction * bgnloop =
1991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						rc_match_endloop(inst);
2001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					if (bgnloop->IP < chan_start) {
2011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						chan_start = bgnloop->IP;
2021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					}
2031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				} else if (op == RC_OPCODE_BGNLOOP) {
2041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					struct rc_instruction * endloop =
2051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						rc_match_bgnloop(inst);
2061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					if (endloop->IP > chan_end) {
2071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						chan_end = endloop->IP;
2081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					}
2091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				}
2101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
2111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			for (chan = 0; chan < 4; chan++) {
2131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				if ((mask >> chan) & 0x1) {
2141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					if (!var->Live[chan].Used
2151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					|| chan_start < var->Live[chan].Start) {
2161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						var->Live[chan].Start =
2171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák								chan_start;
2181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					}
2191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					if (!var->Live[chan].Used
2201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					|| chan_end > var->Live[chan].End) {
2211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						var->Live[chan].End = chan_end;
2221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					}
2231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					var->Live[chan].Used = 1;
2241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				}
2251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
2261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
2271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		var = var->Friend;
2281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
2291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
2321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * @return 1 if a and b share a reader
2331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * @return 0 if they do not
2341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
2351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic unsigned int readers_intersect(
2361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_variable * a,
2371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_variable * b)
2381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int a_index, b_index;
2401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for (a_index = 0; a_index < a->ReaderCount; a_index++) {
2411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		struct rc_reader reader_a = a->Readers[a_index];
2421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		for (b_index = 0; b_index < b->ReaderCount; b_index++) {
2431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			struct rc_reader reader_b = b->Readers[b_index];
2441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (reader_a.Inst->Type == RC_INSTRUCTION_NORMAL
2451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				&& reader_b.Inst->Type == RC_INSTRUCTION_NORMAL
2461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				&& reader_a.U.I.Src == reader_b.U.I.Src) {
2471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				return 1;
2491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
2501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (reader_a.Inst->Type == RC_INSTRUCTION_PAIR
2511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				&& reader_b.Inst->Type == RC_INSTRUCTION_PAIR
2521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				&& reader_a.U.P.Src == reader_b.U.P.Src) {
2531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				return 1;
2551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
2561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
2571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
2581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return 0;
2591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_variable_add_friend(
2621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_variable * var,
2631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_variable * friend)
2641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	assert(var->Dst.Index == friend->Dst.Index);
2661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	while(var->Friend) {
2671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		var = var->Friend;
2681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
2691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	var->Friend = friend;
2701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstruct rc_variable * rc_variable(
2731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler * c,
2741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int DstFile,
2751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int DstIndex,
2761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int DstWriteMask,
2771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader_data * reader_data)
2781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_variable * new =
2801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			memory_pool_malloc(&c->Pool, sizeof(struct rc_variable));
2811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	memset(new, 0, sizeof(struct rc_variable));
2821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	new->C = c;
2831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	new->Dst.File = DstFile;
2841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	new->Dst.Index = DstIndex;
2851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	new->Dst.WriteMask = DstWriteMask;
2861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (reader_data) {
2871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		new->Inst = reader_data->Writer;
2881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		new->ReaderCount = reader_data->ReaderCount;
2891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		new->Readers = reader_data->Readers;
2901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
2911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return new;
2921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
2931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
2941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void get_variable_helper(
2951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_list ** variable_list,
2961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_variable * variable)
2971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
2981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_list * list_ptr;
2991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for (list_ptr = *variable_list; list_ptr; list_ptr = list_ptr->Next) {
3002d1004d9aa719bb93a4f057b0eefe88f23b44e44Tom Stellard		struct rc_variable * var;
3012d1004d9aa719bb93a4f057b0eefe88f23b44e44Tom Stellard		for (var = list_ptr->Item; var; var = var->Friend) {
3022d1004d9aa719bb93a4f057b0eefe88f23b44e44Tom Stellard			if (readers_intersect(var, variable)) {
3032d1004d9aa719bb93a4f057b0eefe88f23b44e44Tom Stellard				rc_variable_add_friend(var, variable);
3042d1004d9aa719bb93a4f057b0eefe88f23b44e44Tom Stellard				return;
3052d1004d9aa719bb93a4f057b0eefe88f23b44e44Tom Stellard			}
3061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
3071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
3081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_list_add(variable_list, rc_list(&variable->C->Pool, variable));
3091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
3101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic void get_variable_pair_helper(
3121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_list ** variable_list,
3131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct radeon_compiler * c,
3141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * inst,
3151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_pair_sub_instruction * sub_inst)
3161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
3171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader_data reader_data;
3181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_variable * new_var;
3191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_register_file file;
3201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int writemask;
3211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (sub_inst->Opcode == RC_OPCODE_NOP) {
3231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return;
3241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
3251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	memset(&reader_data, 0, sizeof(struct rc_reader_data));
3261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	rc_get_readers_sub(c, inst, sub_inst, &reader_data, NULL, NULL, NULL);
3271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (reader_data.ReaderCount == 0) {
3291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return;
3301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
3311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (sub_inst->WriteMask) {
3331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		file = RC_FILE_TEMPORARY;
3341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		writemask = sub_inst->WriteMask;
3351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	} else if (sub_inst->OutputWriteMask) {
3361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		file = RC_FILE_OUTPUT;
3371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		writemask = sub_inst->OutputWriteMask;
3381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	} else {
3391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		writemask = 0;
3401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		file = RC_FILE_NONE;
3411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
3421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	new_var = rc_variable(c, file, sub_inst->DestIndex, writemask,
3431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák								&reader_data);
3441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	get_variable_helper(variable_list, new_var);
3451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
3461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
3481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * Generate a list of variables used by the shader program.  Each instruction
3491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * that writes to a register is considered a variable.  The struct rc_variable
3501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * data structure includes a list of readers and is essentially a
3511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * definition-use chain.  Any two variables that share a reader are considered
3521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * "friends" and they are linked together via the Friend attribute.
3531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
3541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstruct rc_list * rc_get_variables(struct radeon_compiler * c)
3551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
3561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_instruction * inst;
3571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_list * variable_list = NULL;
3581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for (inst = c->Program.Instructions.Next;
3601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					inst != &c->Program.Instructions;
3611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					inst = inst->Next) {
3621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		struct rc_reader_data reader_data;
3631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		struct rc_variable * new_var;
3641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		memset(&reader_data, 0, sizeof(reader_data));
3651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (inst->Type == RC_INSTRUCTION_NORMAL) {
3671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			rc_get_readers(c, inst, &reader_data, NULL, NULL, NULL);
3681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (reader_data.ReaderCount == 0) {
3691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				continue;
3701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
3711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			new_var = rc_variable(c, inst->U.I.DstReg.File,
3721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				inst->U.I.DstReg.Index,
3731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				inst->U.I.DstReg.WriteMask, &reader_data);
3741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			get_variable_helper(&variable_list, new_var);
3751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		} else {
3761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			get_variable_pair_helper(&variable_list, c, inst,
3771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							&inst->U.P.RGB);
3781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			get_variable_pair_helper(&variable_list, c, inst,
3791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák							&inst->U.P.Alpha);
3801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
3811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
3821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return variable_list;
3841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
3851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
3861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/**
3871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * @return The bitwise or of the writemasks of a variable and all of its
3881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * friends.
3891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
3901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákunsigned int rc_variable_writemask_sum(struct rc_variable * var)
3911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
3921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int writemask = 0;
3931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	while(var) {
3941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		writemask |= var->Dst.WriteMask;
3951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		var = var->Friend;
3961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
3971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return writemask;
3981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
3991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák/*
4011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * @return A list of readers for a variable and its friends.  Readers
4021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * that read from two different variable friends are only included once in
4031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák * this list.
4041c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák */
4051c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstruct rc_list * rc_variable_readers_union(struct rc_variable * var)
4061c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
4071c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_list * list = NULL;
4081c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	while (var) {
4091c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		unsigned int i;
4101c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		for (i = 0; i < var->ReaderCount; i++) {
4111c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			struct rc_list * temp;
4121c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			struct rc_reader * a = &var->Readers[i];
4131c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			unsigned int match = 0;
4141c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			for (temp = list; temp; temp = temp->Next) {
4151c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				struct rc_reader * b = temp->Item;
4161c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				if (a->Inst->Type != b->Inst->Type) {
4171c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					continue;
4181c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				}
4191c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				if (a->Inst->Type == RC_INSTRUCTION_NORMAL) {
4201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					if (a->U.I.Src == b->U.I.Src) {
4211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						match = 1;
4221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						break;
4231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					}
4241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				}
4251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				if (a->Inst->Type == RC_INSTRUCTION_PAIR) {
4261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					if (a->U.P.Arg == b->U.P.Arg
4271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					    && a->U.P.Src == b->U.P.Src) {
4281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						match = 1;
4291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						break;
4301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					}
4311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				}
4321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
4331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			if (match) {
4341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				continue;
4351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
4361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			rc_list_add(&list, rc_list(&var->C->Pool, a));
4371c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
4381c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		var = var->Friend;
4391c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
4401c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return list;
4411c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
4421c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4431c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic unsigned int reader_equals_src(
4441c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_reader reader,
4451c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int src_type,
4461c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * src)
4471c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
4481c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (reader.Inst->Type != src_type) {
4491c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return 0;
4501c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
4511c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	if (src_type == RC_INSTRUCTION_NORMAL) {
4521c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return reader.U.I.Src == src;
4531c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	} else {
4541c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		return reader.U.P.Src == src;
4551c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
4561c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
4571c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4581c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstatic unsigned int variable_writes_src(
4591c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_variable * var,
4601c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int src_type,
4611c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * src)
4621c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
4631c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int i;
4641c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for (i = 0; i < var->ReaderCount; i++) {
4651c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (reader_equals_src(var->Readers[i], src_type, src)) {
4661c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			return 1;
4671c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
4681c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
4691c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return 0;
4701c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
4711c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4721c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
4731c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákstruct rc_list * rc_variable_list_get_writers(
4741c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_list * var_list,
4751c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int src_type,
4761c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	void * src)
4771c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
4781c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_list * list_ptr;
4791c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	struct rc_list * writer_list = NULL;
4801c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	for (list_ptr = var_list; list_ptr; list_ptr = list_ptr->Next) {
4811c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		struct rc_variable * var = list_ptr->Item;
4821c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (variable_writes_src(var, src_type, src)) {
4831c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			struct rc_variable * friend;
4841c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			rc_list_add(&writer_list, rc_list(&var->C->Pool, var));
4851c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			for (friend = var->Friend; friend;
4861c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						friend = friend->Friend) {
4871c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				if (variable_writes_src(friend, src_type, src)) {
4881c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					rc_list_add(&writer_list,
4891c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák						rc_list(&var->C->Pool, friend));
4901c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák				}
4911c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			}
4921c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			/* Once we have indentifed the variable and its
4931c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * friends that write this source, we can stop
4941c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * stop searching, because we know know of the
4951c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * other variables in the list will write this source.
4961c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 * If they did they would be friends of var.
4971c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			 */
4981c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			break;
4991c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
5001c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
5011c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	return writer_list;
5021c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
5031c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák
504e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellardstruct rc_list * rc_variable_list_get_writers_one_reader(
505e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard	struct rc_list * var_list,
506e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard	unsigned int src_type,
507e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard	void * src)
508e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard{
509e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard	struct rc_list * writer_list =
510e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard		rc_variable_list_get_writers(var_list, src_type, src);
511e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard	struct rc_list * reader_list =
512e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard		rc_variable_readers_union(writer_list->Item);
513e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard	if (rc_list_count(reader_list) > 1) {
514e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard		return NULL;
515e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard	} else {
516e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard		return writer_list;
517e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard	}
518e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard}
519e945fb04d04c33da5e77d22d739c5740a522a61eTom Stellard
5201c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšákvoid rc_variable_print(struct rc_variable * var)
5211c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák{
5221c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	unsigned int i;
5231c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	while (var) {
5241c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		fprintf(stderr, "%u: TEMP[%u].%u: ",
5251c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			var->Inst->IP, var->Dst.Index, var->Dst.WriteMask);
5261c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		for (i = 0; i < 4; i++) {
5271c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			fprintf(stderr, "chan %u: start=%u end=%u ", i,
5281c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák					var->Live[i].Start, var->Live[i].End);
5291c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
5301c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		fprintf(stderr, "%u readers\n", var->ReaderCount);
5311c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		if (var->Friend) {
5321c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák			fprintf(stderr, "Friend: \n\t");
5331c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		}
5341c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák		var = var->Friend;
5351c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák	}
5361c2c4ddbd1e97bfd13430521e5c09cb5ce8e36e6Marek Olšák}
537