12bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin/**************************************************************************
22bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin *
32bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * Copyright 2011 The Chromium OS authors.
42bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * All Rights Reserved.
52bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin *
62bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * Permission is hereby granted, free of charge, to any person obtaining a
72bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * copy of this software and associated documentation files (the
82bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * "Software"), to deal in the Software without restriction, including
92bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * without limitation the rights to use, copy, modify, merge, publish,
102bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * distribute, sub license, and/or sell copies of the Software, and to
112bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * permit persons to whom the Software is furnished to do so, subject to
122bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * the following conditions:
132bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin *
142bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * The above copyright notice and this permission notice (including the
152bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * next paragraph) shall be included in all copies or substantial portions
162bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * of the Software.
172bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin *
182bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
192bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
202bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
212bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * IN NO EVENT SHALL GOOGLE AND/OR ITS SUPPLIERS BE LIABLE FOR
222bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
232bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
242bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
252bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin *
262bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin **************************************************************************/
272bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
282bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin#include "i915_reg.h"
292bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin#include "i915_context.h"
302bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin#include "i915_fpc.h"
312bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
322bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin#include "pipe/p_shader_tokens.h"
332bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin#include "util/u_math.h"
342bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin#include "util/u_memory.h"
352bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin#include "util/u_string.h"
362bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin#include "tgsi/tgsi_parse.h"
372bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin#include "tgsi/tgsi_dump.h"
382bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
3951f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesinstatic boolean same_src_dst_reg(struct i915_full_src_register* s1, struct i915_full_dst_register* d1)
4051f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin{
4151f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin   return (s1->Register.File == d1->Register.File &&
4251f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin           s1->Register.Indirect == d1->Register.Indirect &&
4351f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin           s1->Register.Dimension == d1->Register.Dimension &&
4451f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin           s1->Register.Index == d1->Register.Index);
4551f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin}
4651f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin
472bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesinstatic boolean same_dst_reg(struct i915_full_dst_register* d1, struct i915_full_dst_register* d2)
482bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin{
492bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   return (d1->Register.File == d2->Register.File &&
502bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin           d1->Register.Indirect == d2->Register.Indirect &&
512bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin           d1->Register.Dimension == d2->Register.Dimension &&
522bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin           d1->Register.Index == d2->Register.Index);
532bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin}
542bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
552bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesinstatic boolean same_src_reg(struct i915_full_src_register* d1, struct i915_full_src_register* d2)
562bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin{
572bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   return (d1->Register.File == d2->Register.File &&
582bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin           d1->Register.Indirect == d2->Register.Indirect &&
592bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin           d1->Register.Dimension == d2->Register.Dimension &&
602bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin           d1->Register.Index == d2->Register.Index &&
612bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin           d1->Register.Absolute == d2->Register.Absolute &&
622bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin           d1->Register.Negate == d2->Register.Negate);
632bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin}
642bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
65687e62a5d76e2e4cbbc6268e5b0e3f148b681185Stéphane Marchesinstatic boolean has_destination(unsigned opcode)
66687e62a5d76e2e4cbbc6268e5b0e3f148b681185Stéphane Marchesin{
67687e62a5d76e2e4cbbc6268e5b0e3f148b681185Stéphane Marchesin   return (opcode != TGSI_OPCODE_NOP &&
68687e62a5d76e2e4cbbc6268e5b0e3f148b681185Stéphane Marchesin           opcode != TGSI_OPCODE_KIL &&
693235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin           opcode != TGSI_OPCODE_KILP &&
703235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin           opcode != TGSI_OPCODE_END &&
71687e62a5d76e2e4cbbc6268e5b0e3f148b681185Stéphane Marchesin           opcode != TGSI_OPCODE_RET);
72687e62a5d76e2e4cbbc6268e5b0e3f148b681185Stéphane Marchesin}
73687e62a5d76e2e4cbbc6268e5b0e3f148b681185Stéphane Marchesin
74053af6ac8cda226a62844fc014ed9f133557c111Stéphane Marchesinstatic boolean is_unswizzled(struct i915_full_src_register* r,
759baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin                             unsigned write_mask)
76053af6ac8cda226a62844fc014ed9f133557c111Stéphane Marchesin{
779baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   if ( write_mask & TGSI_WRITEMASK_X && r->Register.SwizzleX != TGSI_SWIZZLE_X)
78053af6ac8cda226a62844fc014ed9f133557c111Stéphane Marchesin      return FALSE;
799baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   if ( write_mask & TGSI_WRITEMASK_Y && r->Register.SwizzleY != TGSI_SWIZZLE_Y)
80053af6ac8cda226a62844fc014ed9f133557c111Stéphane Marchesin      return FALSE;
819baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   if ( write_mask & TGSI_WRITEMASK_Z && r->Register.SwizzleZ != TGSI_SWIZZLE_Z)
82053af6ac8cda226a62844fc014ed9f133557c111Stéphane Marchesin      return FALSE;
839baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   if ( write_mask & TGSI_WRITEMASK_W && r->Register.SwizzleW != TGSI_SWIZZLE_W)
84053af6ac8cda226a62844fc014ed9f133557c111Stéphane Marchesin      return FALSE;
8531484b068d4d2842593498c75ec831dfa75af14eStéphane Marchesin   return TRUE;
86053af6ac8cda226a62844fc014ed9f133557c111Stéphane Marchesin}
872bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
88f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesinstatic boolean op_commutes(unsigned opcode)
89f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin{
90841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin   switch(opcode)
91841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin   {
92841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin      case TGSI_OPCODE_ADD:
93841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin      case TGSI_OPCODE_MUL:
94841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin      case TGSI_OPCODE_DP2:
95841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin      case TGSI_OPCODE_DP3:
96841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin      case TGSI_OPCODE_DP4:
97841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin         return TRUE;
98841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin   }
99f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin   return FALSE;
100f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin}
101f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin
102f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesinstatic unsigned op_neutral_element(unsigned opcode)
103f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin{
104841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin   switch(opcode)
105841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin   {
106841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin      case TGSI_OPCODE_ADD:
107841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin         return TGSI_SWIZZLE_ZERO;
108841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin      case TGSI_OPCODE_MUL:
109841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin      case TGSI_OPCODE_DP2:
110841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin      case TGSI_OPCODE_DP3:
111841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin      case TGSI_OPCODE_DP4:
112841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin         return TGSI_SWIZZLE_ONE;
113841eee5d44b222a5819804726187683033eb71dbStéphane Marchesin   }
114f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin
115f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin   debug_printf("Unknown opcode %d\n",opcode);
116f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin   return TGSI_SWIZZLE_ZERO;
117f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin}
118f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin
1192bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin/*
1209baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin * Sets the swizzle to the neutral element for the operation for the bits
1219baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin * of writemask which are set, swizzle to identity otherwise.
1229baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin */
1239baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesinstatic void set_neutral_element_swizzle(struct i915_full_src_register* r,
1249baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin                                        unsigned write_mask,
1259baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin                                        unsigned neutral)
1269baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin{
1279baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   if ( write_mask & TGSI_WRITEMASK_X )
1289baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      r->Register.SwizzleX = neutral;
1299baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   else
1309baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      r->Register.SwizzleX = TGSI_SWIZZLE_X;
1319baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin
1329baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   if ( write_mask & TGSI_WRITEMASK_Y )
1339baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      r->Register.SwizzleY = neutral;
1349baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   else
1359baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      r->Register.SwizzleY = TGSI_SWIZZLE_Y;
1369baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin
1379baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   if ( write_mask & TGSI_WRITEMASK_Z )
1389baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      r->Register.SwizzleZ = neutral;
1399baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   else
1409baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      r->Register.SwizzleZ = TGSI_SWIZZLE_Z;
1419baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin
1429baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   if ( write_mask & TGSI_WRITEMASK_W )
1439baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      r->Register.SwizzleW = neutral;
1449baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin   else
1459baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      r->Register.SwizzleW = TGSI_SWIZZLE_W;
1469baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin}
1479baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin
1483235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesinstatic void copy_src_reg(struct i915_src_register* o, const struct tgsi_src_register* i)
1493235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin{
1503235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->File      = i->File;
1513235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->Indirect  = i->Indirect;
1523235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->Dimension = i->Dimension;
1533235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->Index     = i->Index;
1543235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->SwizzleX  = i->SwizzleX;
1553235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->SwizzleY  = i->SwizzleY;
1563235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->SwizzleZ  = i->SwizzleZ;
1573235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->SwizzleW  = i->SwizzleW;
1583235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->Absolute  = i->Absolute;
1593235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->Negate    = i->Negate;
1603235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin}
1613235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin
1623235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesinstatic void copy_dst_reg(struct i915_dst_register* o, const struct tgsi_dst_register* i)
1633235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin{
1643235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->File      = i->File;
1653235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->WriteMask = i->WriteMask;
1663235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->Indirect  = i->Indirect;
1673235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->Dimension = i->Dimension;
1683235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   o->Index     = i->Index;
1693235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin}
1703235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin
1713235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesinstatic void copy_instruction(struct i915_full_instruction* o, const struct tgsi_full_instruction* i)
1723235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin{
1733235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   memcpy(&o->Instruction, &i->Instruction, sizeof(o->Instruction));
1743235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   memcpy(&o->Texture, &i->Texture, sizeof(o->Texture));
1753235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin
1763235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   copy_dst_reg(&o->Dst[0].Register, &i->Dst[0].Register);
1773235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin
1783235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   copy_src_reg(&o->Src[0].Register, &i->Src[0].Register);
1793235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   copy_src_reg(&o->Src[1].Register, &i->Src[1].Register);
1803235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   copy_src_reg(&o->Src[2].Register, &i->Src[2].Register);
1813235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin}
1823235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin
1833235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesinstatic void copy_token(union i915_full_token* o, union tgsi_full_token* i)
1843235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin{
1853235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   if (i->Token.Type != TGSI_TOKEN_TYPE_INSTRUCTION)
1863235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin      memcpy(o, i, sizeof(*o));
1873235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   else
1883235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin      copy_instruction(&o->FullInstruction, &i->FullInstruction);
1893235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin
1903235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin}
1913235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin
1929baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin/*
1932bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * Optimize away things like:
1942bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin *    MUL OUT[0].xyz, TEMP[1], TEMP[2]
1952bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin *    MOV OUT[0].w, TEMP[2]
19651f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin * into:
1972bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin *    MUL OUT[0].xyzw, TEMP[1].xyz1, TEMP[2]
1982bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin * This is useful for optimizing texenv.
1992bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin */
200f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesinstatic void i915_fpc_optimize_mov_after_alu(union i915_full_token* current, union i915_full_token* next)
2012bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin{
2022bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   if ( current->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION  &&
2032bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin        next->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION  &&
204f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin        op_commutes(current->FullInstruction.Instruction.Opcode) &&
2059baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin        current->FullInstruction.Instruction.Saturate == next->FullInstruction.Instruction.Saturate &&
2062bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin        next->FullInstruction.Instruction.Opcode == TGSI_OPCODE_MOV &&
2079a15b1eb95da138231994b6d05cf09c60ba1d842Stéphane Marchesin        same_dst_reg(&next->FullInstruction.Dst[0], &current->FullInstruction.Dst[0]) &&
208053af6ac8cda226a62844fc014ed9f133557c111Stéphane Marchesin        same_src_reg(&next->FullInstruction.Src[0], &current->FullInstruction.Src[1]) &&
2093235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin        !same_src_dst_reg(&next->FullInstruction.Src[0], &current->FullInstruction.Dst[0]) &&
2109baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin        is_unswizzled(&current->FullInstruction.Src[0], current->FullInstruction.Dst[0].Register.WriteMask) &&
2119baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin        is_unswizzled(&current->FullInstruction.Src[1], current->FullInstruction.Dst[0].Register.WriteMask) &&
2129baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin        is_unswizzled(&next->FullInstruction.Src[0], next->FullInstruction.Dst[0].Register.WriteMask) )
2132bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   {
2142bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin      next->FullInstruction.Instruction.Opcode = TGSI_OPCODE_NOP;
2159baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin
2169baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      set_neutral_element_swizzle(&current->FullInstruction.Src[1], 0, 0);
2179baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      set_neutral_element_swizzle(&current->FullInstruction.Src[0],
2189baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin                                  next->FullInstruction.Dst[0].Register.WriteMask,
2199baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin                                  op_neutral_element(current->FullInstruction.Instruction.Opcode));
2209baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin
2219baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      current->FullInstruction.Dst[0].Register.WriteMask = current->FullInstruction.Dst[0].Register.WriteMask |
2229baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin                                                           next->FullInstruction.Dst[0].Register.WriteMask;
2232bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin      return;
2242bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   }
2252bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
2262bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   if ( current->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION  &&
2272bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin        next->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION  &&
228f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin        op_commutes(current->FullInstruction.Instruction.Opcode) &&
2299baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin        current->FullInstruction.Instruction.Saturate == next->FullInstruction.Instruction.Saturate &&
2302bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin        next->FullInstruction.Instruction.Opcode == TGSI_OPCODE_MOV &&
2319a15b1eb95da138231994b6d05cf09c60ba1d842Stéphane Marchesin        same_dst_reg(&next->FullInstruction.Dst[0], &current->FullInstruction.Dst[0]) &&
232053af6ac8cda226a62844fc014ed9f133557c111Stéphane Marchesin        same_src_reg(&next->FullInstruction.Src[0], &current->FullInstruction.Src[0]) &&
2333235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin        !same_src_dst_reg(&next->FullInstruction.Src[0], &current->FullInstruction.Dst[0]) &&
2349baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin        is_unswizzled(&current->FullInstruction.Src[0], current->FullInstruction.Dst[0].Register.WriteMask) &&
2359baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin        is_unswizzled(&current->FullInstruction.Src[1], current->FullInstruction.Dst[0].Register.WriteMask) &&
2369baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin        is_unswizzled(&next->FullInstruction.Src[0], next->FullInstruction.Dst[0].Register.WriteMask) )
2372bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   {
2382bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin      next->FullInstruction.Instruction.Opcode = TGSI_OPCODE_NOP;
2399baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin
2409baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      set_neutral_element_swizzle(&current->FullInstruction.Src[0], 0, 0);
2419baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      set_neutral_element_swizzle(&current->FullInstruction.Src[1],
2429baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin                                  next->FullInstruction.Dst[0].Register.WriteMask,
2439baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin                                  op_neutral_element(current->FullInstruction.Instruction.Opcode));
2449baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin
2459baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin      current->FullInstruction.Dst[0].Register.WriteMask = current->FullInstruction.Dst[0].Register.WriteMask |
2469baad926602547e14d4fdc6a66ec629dfa6acbb2Stéphane Marchesin                                                           next->FullInstruction.Dst[0].Register.WriteMask;
2472bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin      return;
2482bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   }
2492bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin}
2502bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
25151f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin/*
25251f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin * Optimize away things like:
2533235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin *    MOV TEMP[0].xyz TEMP[0].xyzx
2543235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin * into:
2553235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin *    NOP
2563235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin */
2573235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesinstatic boolean i915_fpc_useless_mov(union tgsi_full_token* tgsi_current)
2583235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin{
2593235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   union i915_full_token current;
2603235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   copy_token(&current , tgsi_current);
2613235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   if ( current.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION  &&
2623235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin        current.FullInstruction.Instruction.Opcode == TGSI_OPCODE_MOV &&
2633235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin        has_destination(current.FullInstruction.Instruction.Opcode) &&
2643235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin        current.FullInstruction.Instruction.Saturate == TGSI_SAT_NONE &&
2653235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin        current.FullInstruction.Src[0].Register.Absolute == 0 &&
2663235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin        current.FullInstruction.Src[0].Register.Negate == 0 &&
2673235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin        is_unswizzled(&current.FullInstruction.Src[0], current.FullInstruction.Dst[0].Register.WriteMask) &&
2683235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin        same_src_dst_reg(&current.FullInstruction.Src[0], &current.FullInstruction.Dst[0]) )
2693235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   {
2703235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin      return TRUE;
2713235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   }
2723235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin   return FALSE;
2733235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin}
2743235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin
2753235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin/*
2763235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin * Optimize away things like:
27751f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin *    *** TEMP[0], TEMP[1], TEMP[2]
27851f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin *    MOV OUT[0] TEMP[0]
27951f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin * into:
28051f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin *    *** OUT[0], TEMP[1], TEMP[2]
28151f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin */
2823235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesinstatic void i915_fpc_optimize_useless_mov_after_inst(union i915_full_token* current, union i915_full_token* next)
28351f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin{
28451f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin   if ( current->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION  &&
28551f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin        next->Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION  &&
28651f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin        next->FullInstruction.Instruction.Opcode == TGSI_OPCODE_MOV &&
287687e62a5d76e2e4cbbc6268e5b0e3f148b681185Stéphane Marchesin        has_destination(current->FullInstruction.Instruction.Opcode) &&
28851f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin        next->FullInstruction.Instruction.Saturate == TGSI_SAT_NONE &&
28951f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin        next->FullInstruction.Src[0].Register.Absolute == 0 &&
29051f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin        next->FullInstruction.Src[0].Register.Negate == 0 &&
291b50d250e02457f367c195ee1808b061e0dfe2d00Stéphane Marchesin        next->FullInstruction.Dst[0].Register.File == TGSI_FILE_OUTPUT &&
29251f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin        is_unswizzled(&next->FullInstruction.Src[0], next->FullInstruction.Dst[0].Register.WriteMask) &&
29351f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin        current->FullInstruction.Dst[0].Register.WriteMask == next->FullInstruction.Dst[0].Register.WriteMask &&
29451f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin        same_src_dst_reg(&next->FullInstruction.Src[0], &current->FullInstruction.Dst[0]) )
29551f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin   {
29651f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin      next->FullInstruction.Instruction.Opcode = TGSI_OPCODE_NOP;
29751f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin
29851f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin      current->FullInstruction.Dst[0] = next->FullInstruction.Dst[0];
29951f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin      return;
30051f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin   }
30151f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin}
30251f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin
3032bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesinstruct i915_token_list* i915_optimize(const struct tgsi_token *tokens)
3042bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin{
3052bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   struct i915_token_list *out_tokens = MALLOC(sizeof(struct i915_token_list));
3062bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   struct tgsi_parse_context parse;
3072bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   int i = 0;
3082bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
3097a10976adb65010bec7952a80d1b43d62b3f8bb3Brian Paul   out_tokens->NumTokens = 0;
3107a10976adb65010bec7952a80d1b43d62b3f8bb3Brian Paul
3112bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   /* Count the tokens */
3122bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   tgsi_parse_init( &parse, tokens );
3132bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   while( !tgsi_parse_end_of_tokens( &parse ) ) {
3142bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin      tgsi_parse_token( &parse );
3152bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin      out_tokens->NumTokens++;
3162bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   }
3172bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   tgsi_parse_free (&parse);
3182bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
3192bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   /* Allocate our tokens */
3202bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   out_tokens->Tokens = MALLOC(sizeof(union i915_full_token) * out_tokens->NumTokens);
3212bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
3222bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   tgsi_parse_init( &parse, tokens );
3232bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   while( !tgsi_parse_end_of_tokens( &parse ) ) {
3242bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin      tgsi_parse_token( &parse );
3253235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin
3263235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin      if (i915_fpc_useless_mov(&parse.FullToken)) {
3273235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin         out_tokens->NumTokens--;
3283235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin         continue;
3293235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin      }
3303235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin
3312bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin      copy_token(&out_tokens->Tokens[i] , &parse.FullToken);
3322bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
33351f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin      if (i > 0) {
3343235435e801122fb6d28c0bcc232ddaeb6b9c568Stéphane Marchesin         i915_fpc_optimize_useless_mov_after_inst(&out_tokens->Tokens[i-1], &out_tokens->Tokens[i]);
335f934c80faf0d1fb559cee0a903daba321098320dStéphane Marchesin         i915_fpc_optimize_mov_after_alu(&out_tokens->Tokens[i-1], &out_tokens->Tokens[i]);
33651f641291d19d05acf04f08dd51215c2702a1695Stéphane Marchesin      }
3372bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin      i++;
3382bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   }
3392bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   tgsi_parse_free (&parse);
3402bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
3412bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   return out_tokens;
3422bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin}
3432bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
3442bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesinvoid i915_optimize_free(struct i915_token_list* tokens)
3452bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin{
3462bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   free(tokens->Tokens);
3472bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin   free(tokens);
3482bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin}
3492bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
3502bc5e0e97ba7b6c32f6ff90cb90448173d74b89bStéphane Marchesin
351