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 = ¤t->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 = ¤t->FullInstruction.Src[2]; 337bf215546Sopenharmony_ci liveness_mark_read(ctx, src_reg, i); 338bf215546Sopenharmony_ci FALLTHROUGH; 339bf215546Sopenharmony_ci case 2: 340bf215546Sopenharmony_ci src_reg = ¤t->FullInstruction.Src[1]; 341bf215546Sopenharmony_ci liveness_mark_read(ctx, src_reg, i); 342bf215546Sopenharmony_ci FALLTHROUGH; 343bf215546Sopenharmony_ci case 1: 344bf215546Sopenharmony_ci src_reg = ¤t->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 ¤t->FullInstruction.Dst[0]) && 408bf215546Sopenharmony_ci is_unswizzled(¤t->FullInstruction.Src[0], i915_tex_mask(next)) && 409bf215546Sopenharmony_ci unused_from(ctx, ¤t->FullInstruction.Dst[0], index)) { 410bf215546Sopenharmony_ci memcpy(&next->FullInstruction.Src[0], ¤t->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 ¤t->FullInstruction.Dst[0]) && 440bf215546Sopenharmony_ci same_src_reg(&next->FullInstruction.Src[0], 441bf215546Sopenharmony_ci ¤t->FullInstruction.Src[0]) && 442bf215546Sopenharmony_ci !same_src_dst_reg(¤t->FullInstruction.Src[0], 443bf215546Sopenharmony_ci ¤t->FullInstruction.Dst[0])) { 444bf215546Sopenharmony_ci src_reg1 = ¤t->FullInstruction.Src[0]; 445bf215546Sopenharmony_ci dst_reg1 = ¤t->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 ¤t->FullInstruction.Dst[0]) && 497bf215546Sopenharmony_ci same_src_reg(&next->FullInstruction.Src[0], 498bf215546Sopenharmony_ci ¤t->FullInstruction.Src[1]) && 499bf215546Sopenharmony_ci !same_src_dst_reg(&next->FullInstruction.Src[0], 500bf215546Sopenharmony_ci ¤t->FullInstruction.Dst[0]) && 501bf215546Sopenharmony_ci is_unswizzled(¤t->FullInstruction.Src[0], 502bf215546Sopenharmony_ci current->FullInstruction.Dst[0].Register.WriteMask) && 503bf215546Sopenharmony_ci is_unswizzled(¤t->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(¤t->FullInstruction.Src[1], 0, 0); 510bf215546Sopenharmony_ci set_neutral_element_swizzle( 511bf215546Sopenharmony_ci ¤t->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 ¤t->FullInstruction.Dst[0]) && 529bf215546Sopenharmony_ci same_src_reg(&next->FullInstruction.Src[0], 530bf215546Sopenharmony_ci ¤t->FullInstruction.Src[0]) && 531bf215546Sopenharmony_ci !same_src_dst_reg(&next->FullInstruction.Src[0], 532bf215546Sopenharmony_ci ¤t->FullInstruction.Dst[0]) && 533bf215546Sopenharmony_ci is_unswizzled(¤t->FullInstruction.Src[0], 534bf215546Sopenharmony_ci current->FullInstruction.Dst[0].Register.WriteMask) && 535bf215546Sopenharmony_ci is_unswizzled(¤t->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(¤t->FullInstruction.Src[0], 0, 0); 542bf215546Sopenharmony_ci set_neutral_element_swizzle( 543bf215546Sopenharmony_ci ¤t->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(¤t, 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(¤t.FullInstruction.Src[0], 572bf215546Sopenharmony_ci current.FullInstruction.Dst[0].Register.WriteMask) && 573bf215546Sopenharmony_ci same_src_dst_reg(¤t.FullInstruction.Src[0], 574bf215546Sopenharmony_ci ¤t.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, ¤t->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 ¤t->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