1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2011 The Chromium OS authors.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL GOOGLE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "i915_context.h"
29bf215546Sopenharmony_ci#include "i915_fpc.h"
30bf215546Sopenharmony_ci#include "i915_reg.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "pipe/p_shader_tokens.h"
33bf215546Sopenharmony_ci#include "tgsi/tgsi_dump.h"
34bf215546Sopenharmony_ci#include "tgsi/tgsi_exec.h"
35bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h"
36bf215546Sopenharmony_ci#include "util/u_math.h"
37bf215546Sopenharmony_ci#include "util/u_memory.h"
38bf215546Sopenharmony_ci#include "util/u_string.h"
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_cistruct i915_optimize_context {
41bf215546Sopenharmony_ci   int first_write[TGSI_EXEC_NUM_TEMPS];
42bf215546Sopenharmony_ci   int last_read[TGSI_EXEC_NUM_TEMPS];
43bf215546Sopenharmony_ci};
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_cistatic bool
46bf215546Sopenharmony_cisame_src_dst_reg(struct i915_full_src_register *s1,
47bf215546Sopenharmony_ci                 struct i915_full_dst_register *d1)
48bf215546Sopenharmony_ci{
49bf215546Sopenharmony_ci   return (s1->Register.File == d1->Register.File &&
50bf215546Sopenharmony_ci           s1->Register.Indirect == d1->Register.Indirect &&
51bf215546Sopenharmony_ci           s1->Register.Dimension == d1->Register.Dimension &&
52bf215546Sopenharmony_ci           s1->Register.Index == d1->Register.Index);
53bf215546Sopenharmony_ci}
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_cistatic bool
56bf215546Sopenharmony_cisame_dst_reg(struct i915_full_dst_register *d1,
57bf215546Sopenharmony_ci             struct i915_full_dst_register *d2)
58bf215546Sopenharmony_ci{
59bf215546Sopenharmony_ci   return (d1->Register.File == d2->Register.File &&
60bf215546Sopenharmony_ci           d1->Register.Indirect == d2->Register.Indirect &&
61bf215546Sopenharmony_ci           d1->Register.Dimension == d2->Register.Dimension &&
62bf215546Sopenharmony_ci           d1->Register.Index == d2->Register.Index);
63bf215546Sopenharmony_ci}
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_cistatic bool
66bf215546Sopenharmony_cisame_src_reg(struct i915_full_src_register *d1,
67bf215546Sopenharmony_ci             struct i915_full_src_register *d2)
68bf215546Sopenharmony_ci{
69bf215546Sopenharmony_ci   return (d1->Register.File == d2->Register.File &&
70bf215546Sopenharmony_ci           d1->Register.Indirect == d2->Register.Indirect &&
71bf215546Sopenharmony_ci           d1->Register.Dimension == d2->Register.Dimension &&
72bf215546Sopenharmony_ci           d1->Register.Index == d2->Register.Index &&
73bf215546Sopenharmony_ci           d1->Register.Absolute == d2->Register.Absolute &&
74bf215546Sopenharmony_ci           d1->Register.Negate == d2->Register.Negate);
75bf215546Sopenharmony_ci}
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_cistatic const struct {
78bf215546Sopenharmony_ci   bool is_texture;
79bf215546Sopenharmony_ci   bool commutes;
80bf215546Sopenharmony_ci   unsigned neutral_element;
81bf215546Sopenharmony_ci   unsigned num_dst;
82bf215546Sopenharmony_ci   unsigned num_src;
83bf215546Sopenharmony_ci} op_table[TGSI_OPCODE_LAST] = {
84bf215546Sopenharmony_ci   [TGSI_OPCODE_ADD] = {false, true, TGSI_SWIZZLE_ZERO, 1, 2},
85bf215546Sopenharmony_ci   [TGSI_OPCODE_CEIL] = {false, false, 0, 1, 1},
86bf215546Sopenharmony_ci   [TGSI_OPCODE_CMP] = {false, false, 0, 1, 2},
87bf215546Sopenharmony_ci   [TGSI_OPCODE_COS] = {false, false, 0, 1, 1},
88bf215546Sopenharmony_ci   [TGSI_OPCODE_DDX] = {false, false, 0, 1, 0},
89bf215546Sopenharmony_ci   [TGSI_OPCODE_DDY] = {false, false, 0, 1, 0},
90bf215546Sopenharmony_ci   [TGSI_OPCODE_DP2] = {false, true, TGSI_SWIZZLE_ONE, 1, 2},
91bf215546Sopenharmony_ci   [TGSI_OPCODE_DP3] = {false, true, TGSI_SWIZZLE_ONE, 1, 2},
92bf215546Sopenharmony_ci   [TGSI_OPCODE_DP4] = {false, true, TGSI_SWIZZLE_ONE, 1, 2},
93bf215546Sopenharmony_ci   [TGSI_OPCODE_DST] = {false, false, 0, 1, 2},
94bf215546Sopenharmony_ci   [TGSI_OPCODE_END] = {false, false, 0, 0, 0},
95bf215546Sopenharmony_ci   [TGSI_OPCODE_EX2] = {false, false, 0, 1, 1},
96bf215546Sopenharmony_ci   [TGSI_OPCODE_FLR] = {false, false, 0, 1, 1},
97bf215546Sopenharmony_ci   [TGSI_OPCODE_FRC] = {false, false, 0, 1, 1},
98bf215546Sopenharmony_ci   [TGSI_OPCODE_KILL_IF] = {false, false, 0, 0, 1},
99bf215546Sopenharmony_ci   [TGSI_OPCODE_KILL] = {false, false, 0, 0, 0},
100bf215546Sopenharmony_ci   [TGSI_OPCODE_LG2] = {false, false, 0, 1, 1},
101bf215546Sopenharmony_ci   [TGSI_OPCODE_LIT] = {false, false, 0, 1, 1},
102bf215546Sopenharmony_ci   [TGSI_OPCODE_LRP] = {false, false, 0, 1, 3},
103bf215546Sopenharmony_ci   [TGSI_OPCODE_MAX] = {false, false, 0, 1, 2},
104bf215546Sopenharmony_ci   [TGSI_OPCODE_MAD] = {false, false, 0, 1, 3},
105bf215546Sopenharmony_ci   [TGSI_OPCODE_MIN] = {false, false, 0, 1, 2},
106bf215546Sopenharmony_ci   [TGSI_OPCODE_MOV] = {false, false, 0, 1, 1},
107bf215546Sopenharmony_ci   [TGSI_OPCODE_MUL] = {false, true, TGSI_SWIZZLE_ONE, 1, 2},
108bf215546Sopenharmony_ci   [TGSI_OPCODE_NOP] = {false, false, 0, 0, 0},
109bf215546Sopenharmony_ci   [TGSI_OPCODE_POW] = {false, false, 0, 1, 2},
110bf215546Sopenharmony_ci   [TGSI_OPCODE_RCP] = {false, false, 0, 1, 1},
111bf215546Sopenharmony_ci   [TGSI_OPCODE_RET] = {false, false, 0, 0, 0},
112bf215546Sopenharmony_ci   [TGSI_OPCODE_RSQ] = {false, false, 0, 1, 1},
113bf215546Sopenharmony_ci   [TGSI_OPCODE_SEQ] = {false, false, 0, 1, 2},
114bf215546Sopenharmony_ci   [TGSI_OPCODE_SGE] = {false, false, 0, 1, 2},
115bf215546Sopenharmony_ci   [TGSI_OPCODE_SGT] = {false, false, 0, 1, 2},
116bf215546Sopenharmony_ci   [TGSI_OPCODE_SIN] = {false, false, 0, 1, 1},
117bf215546Sopenharmony_ci   [TGSI_OPCODE_SLE] = {false, false, 0, 1, 2},
118bf215546Sopenharmony_ci   [TGSI_OPCODE_SLT] = {false, false, 0, 1, 2},
119bf215546Sopenharmony_ci   [TGSI_OPCODE_SNE] = {false, false, 0, 1, 2},
120bf215546Sopenharmony_ci   [TGSI_OPCODE_SSG] = {false, false, 0, 1, 1},
121bf215546Sopenharmony_ci   [TGSI_OPCODE_TEX] = {true, false, 0, 1, 2},
122bf215546Sopenharmony_ci   [TGSI_OPCODE_TRUNC] = {false, false, 0, 1, 1},
123bf215546Sopenharmony_ci   [TGSI_OPCODE_TXB] = {true, false, 0, 1, 2},
124bf215546Sopenharmony_ci   [TGSI_OPCODE_TXP] = {true, false, 0, 1, 2},
125bf215546Sopenharmony_ci};
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_cistatic bool
128bf215546Sopenharmony_ciop_has_dst(unsigned opcode)
129bf215546Sopenharmony_ci{
130bf215546Sopenharmony_ci   return (op_table[opcode].num_dst > 0);
131bf215546Sopenharmony_ci}
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_cistatic int
134bf215546Sopenharmony_ciop_num_dst(unsigned opcode)
135bf215546Sopenharmony_ci{
136bf215546Sopenharmony_ci   return op_table[opcode].num_dst;
137bf215546Sopenharmony_ci}
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_cistatic int
140bf215546Sopenharmony_ciop_num_src(unsigned opcode)
141bf215546Sopenharmony_ci{
142bf215546Sopenharmony_ci   return op_table[opcode].num_src;
143bf215546Sopenharmony_ci}
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_cistatic bool
146bf215546Sopenharmony_ciop_commutes(unsigned opcode)
147bf215546Sopenharmony_ci{
148bf215546Sopenharmony_ci   return op_table[opcode].commutes;
149bf215546Sopenharmony_ci}
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_cistatic bool
152bf215546Sopenharmony_ciis_unswizzled(struct i915_full_src_register *r, unsigned write_mask)
153bf215546Sopenharmony_ci{
154bf215546Sopenharmony_ci   if (write_mask & TGSI_WRITEMASK_X && r->Register.SwizzleX != TGSI_SWIZZLE_X)
155bf215546Sopenharmony_ci      return false;
156bf215546Sopenharmony_ci   if (write_mask & TGSI_WRITEMASK_Y && r->Register.SwizzleY != TGSI_SWIZZLE_Y)
157bf215546Sopenharmony_ci      return false;
158bf215546Sopenharmony_ci   if (write_mask & TGSI_WRITEMASK_Z && r->Register.SwizzleZ != TGSI_SWIZZLE_Z)
159bf215546Sopenharmony_ci      return false;
160bf215546Sopenharmony_ci   if (write_mask & TGSI_WRITEMASK_W && r->Register.SwizzleW != TGSI_SWIZZLE_W)
161bf215546Sopenharmony_ci      return false;
162bf215546Sopenharmony_ci   return true;
163bf215546Sopenharmony_ci}
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_cistatic bool
166bf215546Sopenharmony_ciop_is_texture(unsigned opcode)
167bf215546Sopenharmony_ci{
168bf215546Sopenharmony_ci   return op_table[opcode].is_texture;
169bf215546Sopenharmony_ci}
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_cistatic unsigned
172bf215546Sopenharmony_ciop_neutral_element(unsigned opcode)
173bf215546Sopenharmony_ci{
174bf215546Sopenharmony_ci   unsigned ne = op_table[opcode].neutral_element;
175bf215546Sopenharmony_ci   if (!ne) {
176bf215546Sopenharmony_ci      debug_printf("No neutral element for opcode %d\n", opcode);
177bf215546Sopenharmony_ci      ne = TGSI_SWIZZLE_ZERO;
178bf215546Sopenharmony_ci   }
179bf215546Sopenharmony_ci   return ne;
180bf215546Sopenharmony_ci}
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci/*
183bf215546Sopenharmony_ci * Sets the swizzle to the neutral element for the operation for the bits
184bf215546Sopenharmony_ci * of writemask which are set, swizzle to identity otherwise.
185bf215546Sopenharmony_ci */
186bf215546Sopenharmony_cistatic void
187bf215546Sopenharmony_ciset_neutral_element_swizzle(struct i915_full_src_register *r,
188bf215546Sopenharmony_ci                            unsigned write_mask, unsigned neutral)
189bf215546Sopenharmony_ci{
190bf215546Sopenharmony_ci   if (write_mask & TGSI_WRITEMASK_X)
191bf215546Sopenharmony_ci      r->Register.SwizzleX = neutral;
192bf215546Sopenharmony_ci   else
193bf215546Sopenharmony_ci      r->Register.SwizzleX = TGSI_SWIZZLE_X;
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci   if (write_mask & TGSI_WRITEMASK_Y)
196bf215546Sopenharmony_ci      r->Register.SwizzleY = neutral;
197bf215546Sopenharmony_ci   else
198bf215546Sopenharmony_ci      r->Register.SwizzleY = TGSI_SWIZZLE_Y;
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   if (write_mask & TGSI_WRITEMASK_Z)
201bf215546Sopenharmony_ci      r->Register.SwizzleZ = neutral;
202bf215546Sopenharmony_ci   else
203bf215546Sopenharmony_ci      r->Register.SwizzleZ = TGSI_SWIZZLE_Z;
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci   if (write_mask & TGSI_WRITEMASK_W)
206bf215546Sopenharmony_ci      r->Register.SwizzleW = neutral;
207bf215546Sopenharmony_ci   else
208bf215546Sopenharmony_ci      r->Register.SwizzleW = TGSI_SWIZZLE_W;
209bf215546Sopenharmony_ci}
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_cistatic void
212bf215546Sopenharmony_cicopy_src_reg(struct i915_src_register *o, const struct tgsi_src_register *i)
213bf215546Sopenharmony_ci{
214bf215546Sopenharmony_ci   o->File = i->File;
215bf215546Sopenharmony_ci   o->Indirect = i->Indirect;
216bf215546Sopenharmony_ci   o->Dimension = i->Dimension;
217bf215546Sopenharmony_ci   o->Index = i->Index;
218bf215546Sopenharmony_ci   o->SwizzleX = i->SwizzleX;
219bf215546Sopenharmony_ci   o->SwizzleY = i->SwizzleY;
220bf215546Sopenharmony_ci   o->SwizzleZ = i->SwizzleZ;
221bf215546Sopenharmony_ci   o->SwizzleW = i->SwizzleW;
222bf215546Sopenharmony_ci   o->Absolute = i->Absolute;
223bf215546Sopenharmony_ci   o->Negate = i->Negate;
224bf215546Sopenharmony_ci}
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_cistatic void
227bf215546Sopenharmony_cicopy_dst_reg(struct i915_dst_register *o, const struct tgsi_dst_register *i)
228bf215546Sopenharmony_ci{
229bf215546Sopenharmony_ci   o->File = i->File;
230bf215546Sopenharmony_ci   o->WriteMask = i->WriteMask;
231bf215546Sopenharmony_ci   o->Indirect = i->Indirect;
232bf215546Sopenharmony_ci   o->Dimension = i->Dimension;
233bf215546Sopenharmony_ci   o->Index = i->Index;
234bf215546Sopenharmony_ci}
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_cistatic void
237bf215546Sopenharmony_cicopy_instruction(struct i915_full_instruction *o,
238bf215546Sopenharmony_ci                 const struct tgsi_full_instruction *i)
239bf215546Sopenharmony_ci{
240bf215546Sopenharmony_ci   memcpy(&o->Instruction, &i->Instruction, sizeof(o->Instruction));
241bf215546Sopenharmony_ci   memcpy(&o->Texture, &i->Texture, sizeof(o->Texture));
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   copy_dst_reg(&o->Dst[0].Register, &i->Dst[0].Register);
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   copy_src_reg(&o->Src[0].Register, &i->Src[0].Register);
246bf215546Sopenharmony_ci   copy_src_reg(&o->Src[1].Register, &i->Src[1].Register);
247bf215546Sopenharmony_ci   copy_src_reg(&o->Src[2].Register, &i->Src[2].Register);
248bf215546Sopenharmony_ci}
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_cistatic void
251bf215546Sopenharmony_cicopy_token(union i915_full_token *o, union tgsi_full_token *i)
252bf215546Sopenharmony_ci{
253bf215546Sopenharmony_ci   if (i->Token.Type != TGSI_TOKEN_TYPE_INSTRUCTION)
254bf215546Sopenharmony_ci      memcpy(o, i, sizeof(*o));
255bf215546Sopenharmony_ci   else
256bf215546Sopenharmony_ci      copy_instruction(&o->FullInstruction, &i->FullInstruction);
257bf215546Sopenharmony_ci}
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_cistatic void
260bf215546Sopenharmony_ciliveness_mark_written(struct i915_optimize_context *ctx,
261bf215546Sopenharmony_ci                      struct i915_full_dst_register *dst_reg, int pos)
262bf215546Sopenharmony_ci{
263bf215546Sopenharmony_ci   int dst_reg_index;
264bf215546Sopenharmony_ci   if (dst_reg->Register.File == TGSI_FILE_TEMPORARY) {
265bf215546Sopenharmony_ci      dst_reg_index = dst_reg->Register.Index;
266bf215546Sopenharmony_ci      assert(dst_reg_index < TGSI_EXEC_NUM_TEMPS);
267bf215546Sopenharmony_ci      /* dead -> live transition */
268bf215546Sopenharmony_ci      if (ctx->first_write[dst_reg_index] != -1)
269bf215546Sopenharmony_ci         ctx->first_write[dst_reg_index] = pos;
270bf215546Sopenharmony_ci   }
271bf215546Sopenharmony_ci}
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_cistatic void
274bf215546Sopenharmony_ciliveness_mark_read(struct i915_optimize_context *ctx,
275bf215546Sopenharmony_ci                   struct i915_full_src_register *src_reg, int pos)
276bf215546Sopenharmony_ci{
277bf215546Sopenharmony_ci   int src_reg_index;
278bf215546Sopenharmony_ci   if (src_reg->Register.File == TGSI_FILE_TEMPORARY) {
279bf215546Sopenharmony_ci      src_reg_index = src_reg->Register.Index;
280bf215546Sopenharmony_ci      assert(src_reg_index < TGSI_EXEC_NUM_TEMPS);
281bf215546Sopenharmony_ci      /* live -> dead transition */
282bf215546Sopenharmony_ci      if (ctx->last_read[src_reg_index] != -1)
283bf215546Sopenharmony_ci         ctx->last_read[src_reg_index] = pos;
284bf215546Sopenharmony_ci   }
285bf215546Sopenharmony_ci}
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_cistatic void
288bf215546Sopenharmony_ciliveness_analysis(struct i915_optimize_context *ctx,
289bf215546Sopenharmony_ci                  struct i915_token_list *tokens)
290bf215546Sopenharmony_ci{
291bf215546Sopenharmony_ci   struct i915_full_dst_register *dst_reg;
292bf215546Sopenharmony_ci   struct i915_full_src_register *src_reg;
293bf215546Sopenharmony_ci   union i915_full_token *current;
294bf215546Sopenharmony_ci   unsigned opcode;
295bf215546Sopenharmony_ci   int num_dst, num_src;
296bf215546Sopenharmony_ci   int i = 0;
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   for (i = 0; i < TGSI_EXEC_NUM_TEMPS; i++) {
299bf215546Sopenharmony_ci      ctx->first_write[i] = -1;
300bf215546Sopenharmony_ci      ctx->last_read[i] = -1;
301bf215546Sopenharmony_ci   }
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci   for (i = 0; i < tokens->NumTokens; i++) {
304bf215546Sopenharmony_ci      current = &tokens->Tokens[i];
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci      if (current->Token.Type != TGSI_TOKEN_TYPE_INSTRUCTION)
307bf215546Sopenharmony_ci         continue;
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci      opcode = current->FullInstruction.Instruction.Opcode;
310bf215546Sopenharmony_ci      num_dst = op_num_dst(opcode);
311bf215546Sopenharmony_ci
312bf215546Sopenharmony_ci      switch (num_dst) {
313bf215546Sopenharmony_ci      case 1:
314bf215546Sopenharmony_ci         dst_reg = &current->FullInstruction.Dst[0];
315bf215546Sopenharmony_ci         liveness_mark_written(ctx, dst_reg, i);
316bf215546Sopenharmony_ci         FALLTHROUGH;
317bf215546Sopenharmony_ci      case 0:
318bf215546Sopenharmony_ci         break;
319bf215546Sopenharmony_ci      default:
320bf215546Sopenharmony_ci         debug_printf("Op %d has %d dst regs\n", opcode, num_dst);
321bf215546Sopenharmony_ci         break;
322bf215546Sopenharmony_ci      }
323bf215546Sopenharmony_ci   }
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci   for (i = tokens->NumTokens - 1; i >= 0; i--) {
326bf215546Sopenharmony_ci      current = &tokens->Tokens[i];
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci      if (current->Token.Type != TGSI_TOKEN_TYPE_INSTRUCTION)
329bf215546Sopenharmony_ci         continue;
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci      opcode = current->FullInstruction.Instruction.Opcode;
332bf215546Sopenharmony_ci      num_src = op_num_src(opcode);
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci      switch (num_src) {
335bf215546Sopenharmony_ci      case 3:
336bf215546Sopenharmony_ci         src_reg = &current->FullInstruction.Src[2];
337bf215546Sopenharmony_ci         liveness_mark_read(ctx, src_reg, i);
338bf215546Sopenharmony_ci         FALLTHROUGH;
339bf215546Sopenharmony_ci      case 2:
340bf215546Sopenharmony_ci         src_reg = &current->FullInstruction.Src[1];
341bf215546Sopenharmony_ci         liveness_mark_read(ctx, src_reg, i);
342bf215546Sopenharmony_ci         FALLTHROUGH;
343bf215546Sopenharmony_ci      case 1:
344bf215546Sopenharmony_ci         src_reg = &current->FullInstruction.Src[0];
345bf215546Sopenharmony_ci         liveness_mark_read(ctx, src_reg, i);
346bf215546Sopenharmony_ci         FALLTHROUGH;
347bf215546Sopenharmony_ci      case 0:
348bf215546Sopenharmony_ci         break;
349bf215546Sopenharmony_ci      default:
350bf215546Sopenharmony_ci         debug_printf("Op %d has %d src regs\n", opcode, num_src);
351bf215546Sopenharmony_ci         break;
352bf215546Sopenharmony_ci      }
353bf215546Sopenharmony_ci   }
354bf215546Sopenharmony_ci}
355bf215546Sopenharmony_ci
356bf215546Sopenharmony_cistatic int
357bf215546Sopenharmony_ciunused_from(struct i915_optimize_context *ctx,
358bf215546Sopenharmony_ci            struct i915_full_dst_register *dst_reg, int from)
359bf215546Sopenharmony_ci{
360bf215546Sopenharmony_ci   int dst_reg_index = dst_reg->Register.Index;
361bf215546Sopenharmony_ci   assert(dst_reg_index < TGSI_EXEC_NUM_TEMPS);
362bf215546Sopenharmony_ci   return (from >= ctx->last_read[dst_reg_index]);
363bf215546Sopenharmony_ci}
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci/* Returns a mask with the components used for a texture access instruction */
366bf215546Sopenharmony_cistatic unsigned
367bf215546Sopenharmony_cii915_tex_mask(union i915_full_token *instr)
368bf215546Sopenharmony_ci{
369bf215546Sopenharmony_ci   return i915_coord_mask(instr->FullInstruction.Instruction.Opcode,
370bf215546Sopenharmony_ci                          instr->FullInstruction.Texture.Texture);
371bf215546Sopenharmony_ci}
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_cistatic bool
374bf215546Sopenharmony_citarget_is_texture2d(uint32_t tex)
375bf215546Sopenharmony_ci{
376bf215546Sopenharmony_ci   switch (tex) {
377bf215546Sopenharmony_ci   case TGSI_TEXTURE_2D:
378bf215546Sopenharmony_ci   case TGSI_TEXTURE_RECT:
379bf215546Sopenharmony_ci      return true;
380bf215546Sopenharmony_ci   default:
381bf215546Sopenharmony_ci      return false;
382bf215546Sopenharmony_ci   }
383bf215546Sopenharmony_ci}
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci/*
386bf215546Sopenharmony_ci * Optimize away useless indirect texture reads:
387bf215546Sopenharmony_ci *    MOV TEMP[0].xy, IN[0].xyyy
388bf215546Sopenharmony_ci *    TEX TEMP[1], TEMP[0], SAMP[0], 2D
389bf215546Sopenharmony_ci * into:
390bf215546Sopenharmony_ci *    TEX TEMP[1], IN[0], SAMP[0], 2D
391bf215546Sopenharmony_ci *
392bf215546Sopenharmony_ci * note: this only seems to work on 2D/RECT textures, but not SHAADOW2D/1D/..
393bf215546Sopenharmony_ci */
394bf215546Sopenharmony_cistatic void
395bf215546Sopenharmony_cii915_fpc_optimize_mov_before_tex(struct i915_optimize_context *ctx,
396bf215546Sopenharmony_ci                                 struct i915_token_list *tokens, int index)
397bf215546Sopenharmony_ci{
398bf215546Sopenharmony_ci   union i915_full_token *current = &tokens->Tokens[index - 1];
399bf215546Sopenharmony_ci   union i915_full_token *next = &tokens->Tokens[index];
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci   if (current->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION &&
402bf215546Sopenharmony_ci       next->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION &&
403bf215546Sopenharmony_ci       current->FullInstruction.Instruction.Opcode == TGSI_OPCODE_MOV &&
404bf215546Sopenharmony_ci       op_is_texture(next->FullInstruction.Instruction.Opcode) &&
405bf215546Sopenharmony_ci       target_is_texture2d(next->FullInstruction.Texture.Texture) &&
406bf215546Sopenharmony_ci       same_src_dst_reg(&next->FullInstruction.Src[0],
407bf215546Sopenharmony_ci                        &current->FullInstruction.Dst[0]) &&
408bf215546Sopenharmony_ci       is_unswizzled(&current->FullInstruction.Src[0], i915_tex_mask(next)) &&
409bf215546Sopenharmony_ci       unused_from(ctx, &current->FullInstruction.Dst[0], index)) {
410bf215546Sopenharmony_ci      memcpy(&next->FullInstruction.Src[0], &current->FullInstruction.Src[0],
411bf215546Sopenharmony_ci             sizeof(struct i915_src_register));
412bf215546Sopenharmony_ci      current->FullInstruction.Instruction.Opcode = TGSI_OPCODE_NOP;
413bf215546Sopenharmony_ci   }
414bf215546Sopenharmony_ci}
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ci/*
417bf215546Sopenharmony_ci * Optimize away things like:
418bf215546Sopenharmony_ci *    MOV TEMP[0].xy, TEMP[1].xyyy (first write for TEMP[0])
419bf215546Sopenharmony_ci *    MOV TEMP[0].w, TEMP[1].wwww (last write for TEMP[0])
420bf215546Sopenharmony_ci * into:
421bf215546Sopenharmony_ci *    NOP
422bf215546Sopenharmony_ci *    MOV OUT[0].xyw, TEMP[1].xyww
423bf215546Sopenharmony_ci */
424bf215546Sopenharmony_cistatic void
425bf215546Sopenharmony_cii915_fpc_optimize_mov_after_mov(union i915_full_token *current,
426bf215546Sopenharmony_ci                                union i915_full_token *next)
427bf215546Sopenharmony_ci{
428bf215546Sopenharmony_ci   struct i915_full_src_register *src_reg1, *src_reg2;
429bf215546Sopenharmony_ci   struct i915_full_dst_register *dst_reg1, *dst_reg2;
430bf215546Sopenharmony_ci   unsigned swizzle_x, swizzle_y, swizzle_z, swizzle_w;
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci   if (current->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION &&
433bf215546Sopenharmony_ci       next->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION &&
434bf215546Sopenharmony_ci       current->FullInstruction.Instruction.Opcode == TGSI_OPCODE_MOV &&
435bf215546Sopenharmony_ci       next->FullInstruction.Instruction.Opcode == TGSI_OPCODE_MOV &&
436bf215546Sopenharmony_ci       current->FullInstruction.Instruction.Saturate ==
437bf215546Sopenharmony_ci          next->FullInstruction.Instruction.Saturate &&
438bf215546Sopenharmony_ci       same_dst_reg(&next->FullInstruction.Dst[0],
439bf215546Sopenharmony_ci                    &current->FullInstruction.Dst[0]) &&
440bf215546Sopenharmony_ci       same_src_reg(&next->FullInstruction.Src[0],
441bf215546Sopenharmony_ci                    &current->FullInstruction.Src[0]) &&
442bf215546Sopenharmony_ci       !same_src_dst_reg(&current->FullInstruction.Src[0],
443bf215546Sopenharmony_ci                         &current->FullInstruction.Dst[0])) {
444bf215546Sopenharmony_ci      src_reg1 = &current->FullInstruction.Src[0];
445bf215546Sopenharmony_ci      dst_reg1 = &current->FullInstruction.Dst[0];
446bf215546Sopenharmony_ci      src_reg2 = &next->FullInstruction.Src[0];
447bf215546Sopenharmony_ci      dst_reg2 = &next->FullInstruction.Dst[0];
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci      /* Start with swizzles from the first mov */
450bf215546Sopenharmony_ci      swizzle_x = src_reg1->Register.SwizzleX;
451bf215546Sopenharmony_ci      swizzle_y = src_reg1->Register.SwizzleY;
452bf215546Sopenharmony_ci      swizzle_z = src_reg1->Register.SwizzleZ;
453bf215546Sopenharmony_ci      swizzle_w = src_reg1->Register.SwizzleW;
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci      /* Pile the second mov on top */
456bf215546Sopenharmony_ci      if (dst_reg2->Register.WriteMask & TGSI_WRITEMASK_X)
457bf215546Sopenharmony_ci         swizzle_x = src_reg2->Register.SwizzleX;
458bf215546Sopenharmony_ci      if (dst_reg2->Register.WriteMask & TGSI_WRITEMASK_Y)
459bf215546Sopenharmony_ci         swizzle_y = src_reg2->Register.SwizzleY;
460bf215546Sopenharmony_ci      if (dst_reg2->Register.WriteMask & TGSI_WRITEMASK_Z)
461bf215546Sopenharmony_ci         swizzle_z = src_reg2->Register.SwizzleZ;
462bf215546Sopenharmony_ci      if (dst_reg2->Register.WriteMask & TGSI_WRITEMASK_W)
463bf215546Sopenharmony_ci         swizzle_w = src_reg2->Register.SwizzleW;
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci      dst_reg2->Register.WriteMask |= dst_reg1->Register.WriteMask;
466bf215546Sopenharmony_ci      src_reg2->Register.SwizzleX = swizzle_x;
467bf215546Sopenharmony_ci      src_reg2->Register.SwizzleY = swizzle_y;
468bf215546Sopenharmony_ci      src_reg2->Register.SwizzleZ = swizzle_z;
469bf215546Sopenharmony_ci      src_reg2->Register.SwizzleW = swizzle_w;
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci      current->FullInstruction.Instruction.Opcode = TGSI_OPCODE_NOP;
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci      return;
474bf215546Sopenharmony_ci   }
475bf215546Sopenharmony_ci}
476bf215546Sopenharmony_ci
477bf215546Sopenharmony_ci/*
478bf215546Sopenharmony_ci * Optimize away things like:
479bf215546Sopenharmony_ci *    MUL OUT[0].xyz, TEMP[1], TEMP[2]
480bf215546Sopenharmony_ci *    MOV OUT[0].w, TEMP[2]
481bf215546Sopenharmony_ci * into:
482bf215546Sopenharmony_ci *    MUL OUT[0].xyzw, TEMP[1].xyz1, TEMP[2]
483bf215546Sopenharmony_ci * This is useful for optimizing texenv.
484bf215546Sopenharmony_ci */
485bf215546Sopenharmony_cistatic void
486bf215546Sopenharmony_cii915_fpc_optimize_mov_after_alu(union i915_full_token *current,
487bf215546Sopenharmony_ci                                union i915_full_token *next)
488bf215546Sopenharmony_ci{
489bf215546Sopenharmony_ci   if (current->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION &&
490bf215546Sopenharmony_ci       next->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION &&
491bf215546Sopenharmony_ci       op_commutes(current->FullInstruction.Instruction.Opcode) &&
492bf215546Sopenharmony_ci       current->FullInstruction.Instruction.Saturate ==
493bf215546Sopenharmony_ci          next->FullInstruction.Instruction.Saturate &&
494bf215546Sopenharmony_ci       next->FullInstruction.Instruction.Opcode == TGSI_OPCODE_MOV &&
495bf215546Sopenharmony_ci       same_dst_reg(&next->FullInstruction.Dst[0],
496bf215546Sopenharmony_ci                    &current->FullInstruction.Dst[0]) &&
497bf215546Sopenharmony_ci       same_src_reg(&next->FullInstruction.Src[0],
498bf215546Sopenharmony_ci                    &current->FullInstruction.Src[1]) &&
499bf215546Sopenharmony_ci       !same_src_dst_reg(&next->FullInstruction.Src[0],
500bf215546Sopenharmony_ci                         &current->FullInstruction.Dst[0]) &&
501bf215546Sopenharmony_ci       is_unswizzled(&current->FullInstruction.Src[0],
502bf215546Sopenharmony_ci                     current->FullInstruction.Dst[0].Register.WriteMask) &&
503bf215546Sopenharmony_ci       is_unswizzled(&current->FullInstruction.Src[1],
504bf215546Sopenharmony_ci                     current->FullInstruction.Dst[0].Register.WriteMask) &&
505bf215546Sopenharmony_ci       is_unswizzled(&next->FullInstruction.Src[0],
506bf215546Sopenharmony_ci                     next->FullInstruction.Dst[0].Register.WriteMask)) {
507bf215546Sopenharmony_ci      next->FullInstruction.Instruction.Opcode = TGSI_OPCODE_NOP;
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci      set_neutral_element_swizzle(&current->FullInstruction.Src[1], 0, 0);
510bf215546Sopenharmony_ci      set_neutral_element_swizzle(
511bf215546Sopenharmony_ci         &current->FullInstruction.Src[0],
512bf215546Sopenharmony_ci         next->FullInstruction.Dst[0].Register.WriteMask,
513bf215546Sopenharmony_ci         op_neutral_element(current->FullInstruction.Instruction.Opcode));
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci      current->FullInstruction.Dst[0].Register.WriteMask =
516bf215546Sopenharmony_ci         current->FullInstruction.Dst[0].Register.WriteMask |
517bf215546Sopenharmony_ci         next->FullInstruction.Dst[0].Register.WriteMask;
518bf215546Sopenharmony_ci      return;
519bf215546Sopenharmony_ci   }
520bf215546Sopenharmony_ci
521bf215546Sopenharmony_ci   if (current->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION &&
522bf215546Sopenharmony_ci       next->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION &&
523bf215546Sopenharmony_ci       op_commutes(current->FullInstruction.Instruction.Opcode) &&
524bf215546Sopenharmony_ci       current->FullInstruction.Instruction.Saturate ==
525bf215546Sopenharmony_ci          next->FullInstruction.Instruction.Saturate &&
526bf215546Sopenharmony_ci       next->FullInstruction.Instruction.Opcode == TGSI_OPCODE_MOV &&
527bf215546Sopenharmony_ci       same_dst_reg(&next->FullInstruction.Dst[0],
528bf215546Sopenharmony_ci                    &current->FullInstruction.Dst[0]) &&
529bf215546Sopenharmony_ci       same_src_reg(&next->FullInstruction.Src[0],
530bf215546Sopenharmony_ci                    &current->FullInstruction.Src[0]) &&
531bf215546Sopenharmony_ci       !same_src_dst_reg(&next->FullInstruction.Src[0],
532bf215546Sopenharmony_ci                         &current->FullInstruction.Dst[0]) &&
533bf215546Sopenharmony_ci       is_unswizzled(&current->FullInstruction.Src[0],
534bf215546Sopenharmony_ci                     current->FullInstruction.Dst[0].Register.WriteMask) &&
535bf215546Sopenharmony_ci       is_unswizzled(&current->FullInstruction.Src[1],
536bf215546Sopenharmony_ci                     current->FullInstruction.Dst[0].Register.WriteMask) &&
537bf215546Sopenharmony_ci       is_unswizzled(&next->FullInstruction.Src[0],
538bf215546Sopenharmony_ci                     next->FullInstruction.Dst[0].Register.WriteMask)) {
539bf215546Sopenharmony_ci      next->FullInstruction.Instruction.Opcode = TGSI_OPCODE_NOP;
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci      set_neutral_element_swizzle(&current->FullInstruction.Src[0], 0, 0);
542bf215546Sopenharmony_ci      set_neutral_element_swizzle(
543bf215546Sopenharmony_ci         &current->FullInstruction.Src[1],
544bf215546Sopenharmony_ci         next->FullInstruction.Dst[0].Register.WriteMask,
545bf215546Sopenharmony_ci         op_neutral_element(current->FullInstruction.Instruction.Opcode));
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_ci      current->FullInstruction.Dst[0].Register.WriteMask =
548bf215546Sopenharmony_ci         current->FullInstruction.Dst[0].Register.WriteMask |
549bf215546Sopenharmony_ci         next->FullInstruction.Dst[0].Register.WriteMask;
550bf215546Sopenharmony_ci      return;
551bf215546Sopenharmony_ci   }
552bf215546Sopenharmony_ci}
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci/*
555bf215546Sopenharmony_ci * Optimize away things like:
556bf215546Sopenharmony_ci *    MOV TEMP[0].xyz TEMP[0].xyzx
557bf215546Sopenharmony_ci * into:
558bf215546Sopenharmony_ci *    NOP
559bf215546Sopenharmony_ci */
560bf215546Sopenharmony_cistatic bool
561bf215546Sopenharmony_cii915_fpc_useless_mov(union tgsi_full_token *tgsi_current)
562bf215546Sopenharmony_ci{
563bf215546Sopenharmony_ci   union i915_full_token current;
564bf215546Sopenharmony_ci   copy_token(&current, tgsi_current);
565bf215546Sopenharmony_ci   if (current.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION &&
566bf215546Sopenharmony_ci       current.FullInstruction.Instruction.Opcode == TGSI_OPCODE_MOV &&
567bf215546Sopenharmony_ci       op_has_dst(current.FullInstruction.Instruction.Opcode) &&
568bf215546Sopenharmony_ci       !current.FullInstruction.Instruction.Saturate &&
569bf215546Sopenharmony_ci       current.FullInstruction.Src[0].Register.Absolute == 0 &&
570bf215546Sopenharmony_ci       current.FullInstruction.Src[0].Register.Negate == 0 &&
571bf215546Sopenharmony_ci       is_unswizzled(&current.FullInstruction.Src[0],
572bf215546Sopenharmony_ci                     current.FullInstruction.Dst[0].Register.WriteMask) &&
573bf215546Sopenharmony_ci       same_src_dst_reg(&current.FullInstruction.Src[0],
574bf215546Sopenharmony_ci                        &current.FullInstruction.Dst[0])) {
575bf215546Sopenharmony_ci      return true;
576bf215546Sopenharmony_ci   }
577bf215546Sopenharmony_ci   return false;
578bf215546Sopenharmony_ci}
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_ci/*
581bf215546Sopenharmony_ci * Optimize away things like:
582bf215546Sopenharmony_ci *    *** TEMP[0], TEMP[1], TEMP[2]
583bf215546Sopenharmony_ci *    MOV OUT[0] TEMP[0]
584bf215546Sopenharmony_ci * into:
585bf215546Sopenharmony_ci *    *** OUT[0], TEMP[1], TEMP[2]
586bf215546Sopenharmony_ci */
587bf215546Sopenharmony_cistatic void
588bf215546Sopenharmony_cii915_fpc_optimize_useless_mov_after_inst(struct i915_optimize_context *ctx,
589bf215546Sopenharmony_ci                                         struct i915_token_list *tokens,
590bf215546Sopenharmony_ci                                         int index)
591bf215546Sopenharmony_ci{
592bf215546Sopenharmony_ci   union i915_full_token *current = &tokens->Tokens[index - 1];
593bf215546Sopenharmony_ci   union i915_full_token *next = &tokens->Tokens[index];
594bf215546Sopenharmony_ci
595bf215546Sopenharmony_ci   // &out_tokens->Tokens[i-1], &out_tokens->Tokens[i]);
596bf215546Sopenharmony_ci   if (current->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION &&
597bf215546Sopenharmony_ci       next->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION &&
598bf215546Sopenharmony_ci       next->FullInstruction.Instruction.Opcode == TGSI_OPCODE_MOV &&
599bf215546Sopenharmony_ci       op_has_dst(current->FullInstruction.Instruction.Opcode) &&
600bf215546Sopenharmony_ci       !next->FullInstruction.Instruction.Saturate &&
601bf215546Sopenharmony_ci       next->FullInstruction.Src[0].Register.Absolute == 0 &&
602bf215546Sopenharmony_ci       next->FullInstruction.Src[0].Register.Negate == 0 &&
603bf215546Sopenharmony_ci       unused_from(ctx, &current->FullInstruction.Dst[0], index) &&
604bf215546Sopenharmony_ci       current->FullInstruction.Dst[0].Register.WriteMask ==
605bf215546Sopenharmony_ci          TGSI_WRITEMASK_XYZW &&
606bf215546Sopenharmony_ci       is_unswizzled(&next->FullInstruction.Src[0],
607bf215546Sopenharmony_ci                     next->FullInstruction.Dst[0].Register.WriteMask) &&
608bf215546Sopenharmony_ci       current->FullInstruction.Dst[0].Register.WriteMask ==
609bf215546Sopenharmony_ci          next->FullInstruction.Dst[0].Register.WriteMask &&
610bf215546Sopenharmony_ci       same_src_dst_reg(&next->FullInstruction.Src[0],
611bf215546Sopenharmony_ci                        &current->FullInstruction.Dst[0])) {
612bf215546Sopenharmony_ci      next->FullInstruction.Instruction.Opcode = TGSI_OPCODE_NOP;
613bf215546Sopenharmony_ci
614bf215546Sopenharmony_ci      current->FullInstruction.Dst[0] = next->FullInstruction.Dst[0];
615bf215546Sopenharmony_ci      return;
616bf215546Sopenharmony_ci   }
617bf215546Sopenharmony_ci}
618bf215546Sopenharmony_ci
619bf215546Sopenharmony_cistruct i915_token_list *
620bf215546Sopenharmony_cii915_optimize(const struct tgsi_token *tokens)
621bf215546Sopenharmony_ci{
622bf215546Sopenharmony_ci   struct i915_token_list *out_tokens = MALLOC(sizeof(struct i915_token_list));
623bf215546Sopenharmony_ci   struct tgsi_parse_context parse;
624bf215546Sopenharmony_ci   struct i915_optimize_context *ctx;
625bf215546Sopenharmony_ci   int i = 0;
626bf215546Sopenharmony_ci
627bf215546Sopenharmony_ci   ctx = malloc(sizeof(*ctx));
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_ci   out_tokens->NumTokens = 0;
630bf215546Sopenharmony_ci
631bf215546Sopenharmony_ci   /* Count the tokens */
632bf215546Sopenharmony_ci   tgsi_parse_init(&parse, tokens);
633bf215546Sopenharmony_ci   while (!tgsi_parse_end_of_tokens(&parse)) {
634bf215546Sopenharmony_ci      tgsi_parse_token(&parse);
635bf215546Sopenharmony_ci      out_tokens->NumTokens++;
636bf215546Sopenharmony_ci   }
637bf215546Sopenharmony_ci   tgsi_parse_free(&parse);
638bf215546Sopenharmony_ci
639bf215546Sopenharmony_ci   /* Allocate our tokens */
640bf215546Sopenharmony_ci   out_tokens->Tokens =
641bf215546Sopenharmony_ci      MALLOC(sizeof(union i915_full_token) * out_tokens->NumTokens);
642bf215546Sopenharmony_ci
643bf215546Sopenharmony_ci   tgsi_parse_init(&parse, tokens);
644bf215546Sopenharmony_ci   while (!tgsi_parse_end_of_tokens(&parse)) {
645bf215546Sopenharmony_ci      tgsi_parse_token(&parse);
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_ci      if (i915_fpc_useless_mov(&parse.FullToken)) {
648bf215546Sopenharmony_ci         out_tokens->NumTokens--;
649bf215546Sopenharmony_ci         continue;
650bf215546Sopenharmony_ci      }
651bf215546Sopenharmony_ci
652bf215546Sopenharmony_ci      copy_token(&out_tokens->Tokens[i], &parse.FullToken);
653bf215546Sopenharmony_ci
654bf215546Sopenharmony_ci      i++;
655bf215546Sopenharmony_ci   }
656bf215546Sopenharmony_ci   tgsi_parse_free(&parse);
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_ci   liveness_analysis(ctx, out_tokens);
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_ci   i = 1;
661bf215546Sopenharmony_ci   while (i < out_tokens->NumTokens) {
662bf215546Sopenharmony_ci      i915_fpc_optimize_useless_mov_after_inst(ctx, out_tokens, i);
663bf215546Sopenharmony_ci      i915_fpc_optimize_mov_after_alu(&out_tokens->Tokens[i - 1],
664bf215546Sopenharmony_ci                                      &out_tokens->Tokens[i]);
665bf215546Sopenharmony_ci      i915_fpc_optimize_mov_after_mov(&out_tokens->Tokens[i - 1],
666bf215546Sopenharmony_ci                                      &out_tokens->Tokens[i]);
667bf215546Sopenharmony_ci      i915_fpc_optimize_mov_before_tex(ctx, out_tokens, i);
668bf215546Sopenharmony_ci      i++;
669bf215546Sopenharmony_ci   }
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_ci   free(ctx);
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci   return out_tokens;
674bf215546Sopenharmony_ci}
675bf215546Sopenharmony_ci
676bf215546Sopenharmony_civoid
677bf215546Sopenharmony_cii915_optimize_free(struct i915_token_list *tokens)
678bf215546Sopenharmony_ci{
679bf215546Sopenharmony_ci   free(tokens->Tokens);
680bf215546Sopenharmony_ci   free(tokens);
681bf215546Sopenharmony_ci}
682