xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r300/compiler/radeon_program_pair.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2008-2009 Nicolai Haehnle.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "radeon_program_pair.h"
7 
8 #include "radeon_compiler_util.h"
9 
10 #include <stdlib.h>
11 
12 /**
13  * Return the source slot where we installed the given register access,
14  * or -1 if no slot was free anymore.
15  */
rc_pair_alloc_source(struct rc_pair_instruction * pair,unsigned int rgb,unsigned int alpha,rc_register_file file,unsigned int index)16 int rc_pair_alloc_source(struct rc_pair_instruction *pair,
17 	unsigned int rgb, unsigned int alpha,
18 	rc_register_file file, unsigned int index)
19 {
20 	int candidate = -1;
21 	int candidate_quality = -1;
22 	unsigned int alpha_used = 0;
23 	unsigned int rgb_used = 0;
24 	int i;
25 
26 	if ((!rgb && !alpha) || file == RC_FILE_NONE)
27 		return 0;
28 
29 	/* Make sure only one presubtract operation is used per instruction. */
30 	if (file == RC_FILE_PRESUB) {
31 		if (rgb && pair->RGB.Src[RC_PAIR_PRESUB_SRC].Used
32 			&& index != pair->RGB.Src[RC_PAIR_PRESUB_SRC].Index) {
33 				return -1;
34 		}
35 
36 		if (alpha && pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Used
37 			&& index != pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Index) {
38 				return -1;
39 		}
40 	}
41 
42 	for(i = 0; i < 3; ++i) {
43 		int q = 0;
44 		if (rgb) {
45 			if (pair->RGB.Src[i].Used) {
46 				if (pair->RGB.Src[i].File != file ||
47 				    pair->RGB.Src[i].Index != index) {
48 					rgb_used++;
49 					continue;
50 				}
51 				q++;
52 			}
53 		}
54 		if (alpha) {
55 			if (pair->Alpha.Src[i].Used) {
56 				if (pair->Alpha.Src[i].File != file ||
57 				    pair->Alpha.Src[i].Index != index) {
58 					alpha_used++;
59 					continue;
60 				}
61 				q++;
62 			}
63 		}
64 		if (q > candidate_quality) {
65 			candidate_quality = q;
66 			candidate = i;
67 		}
68 	}
69 
70 	if (file == RC_FILE_PRESUB) {
71 		candidate = RC_PAIR_PRESUB_SRC;
72 	} else if (candidate < 0 || (rgb && rgb_used > 2)
73 			|| (alpha && alpha_used > 2)) {
74 		return -1;
75 	}
76 
77 	/* candidate >= 0 */
78 
79 	if (rgb) {
80 		pair->RGB.Src[candidate].Used = 1;
81 		pair->RGB.Src[candidate].File = file;
82 		pair->RGB.Src[candidate].Index = index;
83 		if (candidate == RC_PAIR_PRESUB_SRC) {
84 			/* For registers with the RC_FILE_PRESUB file,
85 			 * the index stores the presubtract op. */
86 			int src_regs = rc_presubtract_src_reg_count(index);
87 			for(i = 0; i < src_regs; i++) {
88 				pair->RGB.Src[i].Used = 1;
89 			}
90 		}
91 	}
92 	if (alpha) {
93 		pair->Alpha.Src[candidate].Used = 1;
94 		pair->Alpha.Src[candidate].File = file;
95 		pair->Alpha.Src[candidate].Index = index;
96 		if (candidate == RC_PAIR_PRESUB_SRC) {
97 			/* For registers with the RC_FILE_PRESUB file,
98 			 * the index stores the presubtract op. */
99 			int src_regs = rc_presubtract_src_reg_count(index);
100 			for(i=0; i < src_regs; i++) {
101 				pair->Alpha.Src[i].Used = 1;
102 			}
103 		}
104 	}
105 
106 	return candidate;
107 }
108 
pair_foreach_source_callback(struct rc_pair_instruction * pair,void * data,rc_pair_foreach_src_fn cb,unsigned int swz,unsigned int src)109 static void pair_foreach_source_callback(
110 	struct rc_pair_instruction * pair,
111 	void * data,
112 	rc_pair_foreach_src_fn cb,
113 	unsigned int swz,
114 	unsigned int src)
115 {
116 	/* swz > 3 means that the swizzle is either not used, or a constant
117 	 * swizzle (e.g. 0, 1, 0.5). */
118 	if(swz > 3)
119 		return;
120 
121 	if(swz == RC_SWIZZLE_W) {
122 		if (src == RC_PAIR_PRESUB_SRC) {
123 			unsigned int i;
124 			unsigned int src_count = rc_presubtract_src_reg_count(
125 				pair->Alpha.Src[RC_PAIR_PRESUB_SRC].Index);
126 			for(i = 0; i < src_count; i++) {
127 				cb(data, &pair->Alpha.Src[i]);
128 			}
129 		} else {
130 			cb(data, &pair->Alpha.Src[src]);
131 		}
132 	} else {
133 		if (src == RC_PAIR_PRESUB_SRC) {
134 			unsigned int i;
135 			unsigned int src_count = rc_presubtract_src_reg_count(
136 				pair->RGB.Src[RC_PAIR_PRESUB_SRC].Index);
137 			for(i = 0; i < src_count; i++) {
138 				cb(data, &pair->RGB.Src[i]);
139 			}
140 		}
141 		else {
142 			cb(data, &pair->RGB.Src[src]);
143 		}
144 	}
145 }
146 
rc_pair_foreach_source_that_alpha_reads(struct rc_pair_instruction * pair,void * data,rc_pair_foreach_src_fn cb)147 void rc_pair_foreach_source_that_alpha_reads(
148 	struct rc_pair_instruction * pair,
149 	void * data,
150 	rc_pair_foreach_src_fn cb)
151 {
152 	unsigned int i;
153 	const struct rc_opcode_info * info =
154 				rc_get_opcode_info(pair->Alpha.Opcode);
155 	for(i = 0; i < info->NumSrcRegs; i++) {
156 		pair_foreach_source_callback(pair, data, cb,
157 					GET_SWZ(pair->Alpha.Arg[i].Swizzle, 0),
158 					pair->Alpha.Arg[i].Source);
159 	}
160 }
161 
rc_pair_foreach_source_that_rgb_reads(struct rc_pair_instruction * pair,void * data,rc_pair_foreach_src_fn cb)162 void rc_pair_foreach_source_that_rgb_reads(
163 	struct rc_pair_instruction * pair,
164 	void * data,
165 	rc_pair_foreach_src_fn cb)
166 {
167 	unsigned int i;
168 	const struct rc_opcode_info * info =
169 				rc_get_opcode_info(pair->RGB.Opcode);
170 	for(i = 0; i < info->NumSrcRegs; i++) {
171 		unsigned int chan;
172 		unsigned int swz = RC_SWIZZLE_UNUSED;
173 		/* Find a swizzle that is either X,Y,Z,or W.  We assume here
174 		 * that if one channel swizzles X,Y, or Z, then none of the
175 		 * other channels swizzle W, and vice-versa. */
176 		for(chan = 0; chan < 4; chan++) {
177 			swz = GET_SWZ(pair->RGB.Arg[i].Swizzle, chan);
178 			if(swz == RC_SWIZZLE_X || swz == RC_SWIZZLE_Y
179 			|| swz == RC_SWIZZLE_Z || swz == RC_SWIZZLE_W)
180 				continue;
181 		}
182 		pair_foreach_source_callback(pair, data, cb,
183 					swz,
184 					pair->RGB.Arg[i].Source);
185 	}
186 }
187 
rc_pair_get_src(struct rc_pair_instruction * pair_inst,struct rc_pair_instruction_arg * arg)188 struct rc_pair_instruction_source * rc_pair_get_src(
189 	struct rc_pair_instruction * pair_inst,
190 	struct rc_pair_instruction_arg * arg)
191 {
192 	unsigned int type;
193 
194 	type = rc_source_type_swz(arg->Swizzle);
195 
196 	if (type & RC_SOURCE_RGB) {
197 		return &pair_inst->RGB.Src[arg->Source];
198 	} else if (type & RC_SOURCE_ALPHA) {
199 		return &pair_inst->Alpha.Src[arg->Source];
200 	} else {
201 		return NULL;
202 	}
203 }
204 
rc_pair_get_src_index(struct rc_pair_instruction * pair_inst,struct rc_pair_instruction_source * src)205 int rc_pair_get_src_index(
206 	struct rc_pair_instruction * pair_inst,
207 	struct rc_pair_instruction_source * src)
208 {
209 	int i;
210 	for (i = 0; i < 3; i++) {
211 		if (&pair_inst->RGB.Src[i] == src
212 			|| &pair_inst->Alpha.Src[i] == src) {
213 			return i;
214 		}
215 	}
216 	return -1;
217 }
218