diff options
author | Nicolai Hähnle <[email protected]> | 2009-10-03 21:28:59 +0200 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2009-10-03 23:37:16 +0200 |
commit | b7cf887ca74561469c144f1d12227e1bcf277e7e (patch) | |
tree | c956777f799712573febf464310a1ec0f75f1991 /src/mesa/drivers | |
parent | 6d25b9125ec1e66e0e255b0ee20fe18dfe1076fa (diff) |
r300/compiler: Introduce control flow instructions and refactor dataflow
Note that control flow instruction support isn't actually fully functional yet.
Signed-off-by: Nicolai Hähnle <[email protected]>
Diffstat (limited to 'src/mesa/drivers')
14 files changed, 431 insertions, 776 deletions
diff --git a/src/mesa/drivers/dri/r300/compiler/Makefile b/src/mesa/drivers/dri/r300/compiler/Makefile index 53fb7caa95d..0d8dcb9f870 100644 --- a/src/mesa/drivers/dri/r300/compiler/Makefile +++ b/src/mesa/drivers/dri/r300/compiler/Makefile @@ -14,8 +14,7 @@ C_SOURCES = \ radeon_program_alu.c \ radeon_program_pair.c \ radeon_dataflow.c \ - radeon_dataflow_annotate.c \ - radeon_dataflow_dealias.c \ + radeon_dataflow_deadcode.c \ radeon_dataflow_swizzles.c \ r3xx_fragprog.c \ r300_fragprog.c \ diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c index bf9bea685ab..590201a9bab 100644 --- a/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r3xx_fragprog.c @@ -24,6 +24,7 @@ #include <stdio.h> +#include "radeon_dataflow.h" #include "radeon_program_alu.h" #include "r300_fragprog.h" #include "r300_fragprog_swizzle.h" @@ -107,17 +108,23 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c) if (c->Base.Debug) { fprintf(stderr, "Fragment Program: After native rewrite:\n"); - rc_print_program(&c->Base.Program, 0); + rc_print_program(&c->Base.Program); + fflush(stderr); + } + + rc_dataflow_deadcode(&c->Base, &dataflow_outputs_mark_use, c); + + if (c->Base.Debug) { + fprintf(stderr, "Fragment Program: After deadcode:\n"); + rc_print_program(&c->Base.Program); fflush(stderr); } - rc_dataflow_annotate(&c->Base, &dataflow_outputs_mark_use, c); - rc_dataflow_dealias(&c->Base); rc_dataflow_swizzles(&c->Base); if (c->Base.Debug) { fprintf(stderr, "Compiler: after dataflow passes:\n"); - rc_print_program(&c->Base.Program, 0); + rc_print_program(&c->Base.Program); fflush(stderr); } diff --git a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c index ac72f8cbb61..e1e735568de 100644 --- a/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c +++ b/src/mesa/drivers/dri/r300/compiler/r3xx_vertprog.c @@ -588,7 +588,7 @@ void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler) if (compiler->Base.Debug) { fprintf(stderr, "Vertex program after native rewrite:\n"); - rc_print_program(&compiler->Base.Program, 0); + rc_print_program(&compiler->Base.Program); fflush(stderr); } @@ -605,21 +605,25 @@ void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler) if (compiler->Base.Debug) { fprintf(stderr, "Vertex program after source conflict resolve:\n"); - rc_print_program(&compiler->Base.Program, 0); + rc_print_program(&compiler->Base.Program); + fflush(stderr); + } + + rc_dataflow_deadcode(&compiler->Base, &dataflow_outputs_mark_used, compiler); + + if (compiler->Base.Debug) { + fprintf(stderr, "Vertex program after deadcode:\n"); + rc_print_program(&compiler->Base.Program); fflush(stderr); } - rc_dataflow_annotate(&compiler->Base, &dataflow_outputs_mark_used, compiler); - rc_dataflow_dealias(&compiler->Base); rc_dataflow_swizzles(&compiler->Base); - /* This invalidates dataflow annotations and should be replaced - * by a future generic register allocation pass. */ allocate_temporary_registers(compiler); if (compiler->Base.Debug) { fprintf(stderr, "Vertex program after dataflow:\n"); - rc_print_program(&compiler->Base.Program, 0); + rc_print_program(&compiler->Base.Program); fflush(stderr); } diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c index af6777a7bd3..a171d8ab54b 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.c @@ -30,77 +30,3 @@ #include "radeon_compiler.h" -static void add_ref_to_vector(struct rc_dataflow_ref * ref, struct rc_dataflow_vector * vector) -{ - ref->Vector = vector; - ref->Prev = &vector->Refs; - ref->Next = vector->Refs.Next; - ref->Prev->Next = ref; - ref->Next->Prev = ref; -} - -struct rc_dataflow_ref * rc_dataflow_create_ref(struct radeon_compiler * c, - struct rc_dataflow_vector * vector, struct rc_instruction * inst) -{ - struct rc_dataflow_ref * ref = memory_pool_malloc(&c->Pool, sizeof(struct rc_dataflow_ref)); - ref->ReadInstruction = inst; - ref->UseMask = 0; - - add_ref_to_vector(ref, vector); - - return ref; -} - -struct rc_dataflow_vector * rc_dataflow_create_vector(struct radeon_compiler * c, - rc_register_file file, unsigned int index, struct rc_instruction * inst) -{ - struct rc_dataflow_vector * vec = memory_pool_malloc(&c->Pool, sizeof(struct rc_dataflow_vector)); - - memset(vec, 0, sizeof(struct rc_dataflow_vector)); - vec->File = file; - vec->Index = index; - vec->WriteInstruction = inst; - - vec->Refs.Next = vec->Refs.Prev = &vec->Refs; - - return vec; -} - -void rc_dataflow_remove_ref(struct rc_dataflow_ref * ref) -{ - ref->Prev->Next = ref->Next; - ref->Next->Prev = ref->Prev; -} - -void rc_dataflow_remove_instruction(struct rc_instruction * inst) -{ - for(unsigned int i = 0; i < 3; ++i) { - if (inst->Dataflow.SrcReg[i]) { - rc_dataflow_remove_ref(inst->Dataflow.SrcReg[i]); - inst->Dataflow.SrcReg[i] = 0; - } - if (inst->Dataflow.SrcRegAddress[i]) { - rc_dataflow_remove_ref(inst->Dataflow.SrcRegAddress[i]); - inst->Dataflow.SrcRegAddress[i] = 0; - } - } - - if (inst->Dataflow.DstReg) { - while(inst->Dataflow.DstReg->Refs.Next != &inst->Dataflow.DstReg->Refs) { - struct rc_dataflow_ref * ref = inst->Dataflow.DstReg->Refs.Next; - rc_dataflow_remove_ref(ref); - if (inst->Dataflow.DstRegPrev) - add_ref_to_vector(ref, inst->Dataflow.DstRegPrev->Vector); - } - - inst->Dataflow.DstReg->WriteInstruction = 0; - inst->Dataflow.DstReg = 0; - } - - if (inst->Dataflow.DstRegPrev) { - rc_dataflow_remove_ref(inst->Dataflow.DstRegPrev); - inst->Dataflow.DstRegPrev = 0; - } - - inst->Dataflow.DstRegAliased = 0; -} diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.h b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.h index c9856affe88..76c323d0576 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow.h @@ -34,79 +34,14 @@ struct radeon_compiler; struct rc_instruction; struct rc_swizzle_caps; -struct rc_dataflow_vector; - -struct rc_dataflow_ref { - struct rc_dataflow_vector * Vector; - - /** - * Linked list of references to the above-mentioned vector. - * The linked list is \em not sorted. - */ - /*@{*/ - struct rc_dataflow_ref * Prev; - struct rc_dataflow_ref * Next; - /*@}*/ - - unsigned int UseMask:4; - struct rc_instruction * ReadInstruction; -}; - -struct rc_dataflow_vector { - rc_register_file File:3; - unsigned int Index:RC_REGISTER_INDEX_BITS; - - /** For private use in compiler passes. MUST BE RESET TO 0 by the end of each pass. - * The annotate pass uses this bit to track whether a vector is in the - * update stack. - */ - unsigned int PassBit:1; - /** Which of the components have been written with useful values */ - unsigned int ValidMask:4; - /** Which of the components are used downstream */ - unsigned int UseMask:4; - /** The instruction that produced this vector */ - struct rc_instruction * WriteInstruction; - - /** Linked list of references to this vector */ - struct rc_dataflow_ref Refs; -}; - -struct rc_instruction_dataflow { - struct rc_dataflow_ref * SrcReg[3]; - struct rc_dataflow_ref * SrcRegAddress[3]; - - /** Reference the components of the destination register - * that are carried over without being overwritten */ - struct rc_dataflow_ref * DstRegPrev; - /** Indicates whether the destination register was in use - * before this instruction */ - unsigned int DstRegAliased:1; - struct rc_dataflow_vector * DstReg; -}; - -/** - * General functions for manipulating the dataflow structures. - */ -/*@{*/ -struct rc_dataflow_ref * rc_dataflow_create_ref(struct radeon_compiler * c, - struct rc_dataflow_vector * vector, struct rc_instruction * inst); -struct rc_dataflow_vector * rc_dataflow_create_vector(struct radeon_compiler * c, - rc_register_file file, unsigned int index, struct rc_instruction * inst); -void rc_dataflow_remove_ref(struct rc_dataflow_ref * ref); - -void rc_dataflow_remove_instruction(struct rc_instruction * inst); -/*@}*/ - /** - * Compiler passes based on dataflow structures. + * Compiler passes based on dataflow analysis. */ /*@{*/ typedef void (*rc_dataflow_mark_outputs_fn)(void * userdata, void * data, void (*mark_fn)(void * data, unsigned int index, unsigned int mask)); -void rc_dataflow_annotate(struct radeon_compiler * c, rc_dataflow_mark_outputs_fn dce, void * userdata); -void rc_dataflow_dealias(struct radeon_compiler * c); +void rc_dataflow_deadcode(struct radeon_compiler * c, rc_dataflow_mark_outputs_fn dce, void * userdata); void rc_dataflow_swizzles(struct radeon_compiler * c); /*@}*/ diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_annotate.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_annotate.c deleted file mode 100644 index 41d175a22f2..00000000000 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_annotate.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (C) 2009 Nicolai Haehnle. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "radeon_dataflow.h" - -#include "radeon_compiler.h" - - -struct dataflow_state { - struct radeon_compiler * C; - unsigned int DCE:1; - unsigned int UpdateRunning:1; - - struct rc_dataflow_vector * Input[RC_REGISTER_MAX_INDEX]; - struct rc_dataflow_vector * Output[RC_REGISTER_MAX_INDEX]; - struct rc_dataflow_vector * Temporary[RC_REGISTER_MAX_INDEX]; - struct rc_dataflow_vector * Address; - - struct rc_dataflow_vector ** UpdateStack; - unsigned int UpdateStackSize; - unsigned int UpdateStackReserved; -}; - -static void mark_vector_use(struct dataflow_state * s, struct rc_dataflow_vector * vector, unsigned int mask); - -static struct rc_dataflow_vector * get_register_contents(struct dataflow_state * s, - rc_register_file file, unsigned int index) -{ - if (file == RC_FILE_INPUT || file == RC_FILE_OUTPUT || file == RC_FILE_TEMPORARY) { - if (index >= RC_REGISTER_MAX_INDEX) - return 0; /* cannot happen, but be defensive */ - - if (file == RC_FILE_TEMPORARY) - return s->Temporary[index]; - if (file == RC_FILE_INPUT) - return s->Input[index]; - if (file == RC_FILE_OUTPUT) - return s->Output[index]; - } - - if (file == RC_FILE_ADDRESS) - return s->Address; - - return 0; /* can happen, constant register file */ -} - -static void mark_ref_use(struct dataflow_state * s, struct rc_dataflow_ref * ref, unsigned int mask) -{ - if (!(mask & ~ref->UseMask)) - return; - - ref->UseMask |= mask; - mark_vector_use(s, ref->Vector, ref->UseMask); -} - -static void mark_source_use(struct dataflow_state * s, struct rc_instruction * inst, - unsigned int src, unsigned int srcmask) -{ - unsigned int refmask = 0; - - for(unsigned int i = 0; i < 4; ++i) { - if (GET_BIT(srcmask, i)) - refmask |= 1 << GET_SWZ(inst->I.SrcReg[src].Swizzle, i); - } - - /* get rid of spurious bits from ZERO, ONE, etc. swizzles */ - refmask &= RC_MASK_XYZW; - - if (!refmask) - return; /* can happen if the swizzle contains constant components */ - - if (inst->Dataflow.SrcReg[src]) - mark_ref_use(s, inst->Dataflow.SrcReg[src], refmask); - - if (inst->Dataflow.SrcRegAddress[src]) - mark_ref_use(s, inst->Dataflow.SrcRegAddress[src], RC_MASK_X); -} - -static void compute_sources_for_writemask( - struct rc_instruction * inst, - unsigned int writemask, - unsigned int *srcmasks) -{ - const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode); - - srcmasks[0] = 0; - srcmasks[1] = 0; - srcmasks[2] = 0; - - if (inst->I.Opcode == RC_OPCODE_KIL) - srcmasks[0] |= RC_MASK_XYZW; - - if (!writemask) - return; - - if (opcode->IsComponentwise) { - for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) - srcmasks[src] |= writemask; - } else if (opcode->IsStandardScalar) { - for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) - srcmasks[src] |= RC_MASK_X; - } else { - switch(inst->I.Opcode) { - case RC_OPCODE_ARL: - srcmasks[0] |= RC_MASK_X; - break; - case RC_OPCODE_DP3: - srcmasks[0] |= RC_MASK_XYZ; - srcmasks[1] |= RC_MASK_XYZ; - break; - case RC_OPCODE_DP4: - srcmasks[0] |= RC_MASK_XYZW; - srcmasks[1] |= RC_MASK_XYZW; - break; - case RC_OPCODE_TEX: - case RC_OPCODE_TXB: - case RC_OPCODE_TXP: - srcmasks[0] |= RC_MASK_XYZW; - break; - case RC_OPCODE_DST: - srcmasks[0] |= 0x6; - srcmasks[1] |= 0xa; - break; - case RC_OPCODE_EXP: - case RC_OPCODE_LOG: - srcmasks[0] |= RC_MASK_XY; - break; - case RC_OPCODE_LIT: - srcmasks[0] |= 0xb; - break; - default: - break; - } - } -} - -static void mark_instruction_source_use(struct dataflow_state * s, - struct rc_instruction * inst, unsigned int writemask) -{ - unsigned int srcmasks[3]; - - compute_sources_for_writemask(inst, writemask, srcmasks); - - for(unsigned int src = 0; src < 3; ++src) - mark_source_use(s, inst, src, srcmasks[src]); -} - -static void run_update(struct dataflow_state * s) -{ - s->UpdateRunning = 1; - - while(s->UpdateStackSize) { - struct rc_dataflow_vector * vector = s->UpdateStack[--s->UpdateStackSize]; - vector->PassBit = 0; - - if (vector->WriteInstruction) { - struct rc_instruction * inst = vector->WriteInstruction; - - if (inst->Dataflow.DstRegPrev) { - unsigned int carryover = vector->UseMask & ~inst->I.DstReg.WriteMask; - - if (carryover) - mark_ref_use(s, inst->Dataflow.DstRegPrev, carryover); - } - - mark_instruction_source_use( - s, vector->WriteInstruction, - vector->UseMask & inst->I.DstReg.WriteMask); - } - } - - s->UpdateRunning = 0; -} - -static void mark_vector_use(struct dataflow_state * s, struct rc_dataflow_vector * vector, unsigned int mask) -{ - if (!(mask & ~vector->UseMask)) - return; /* no new used bits */ - - vector->UseMask |= mask; - if (vector->PassBit) - return; - - if (s->UpdateStackSize >= s->UpdateStackReserved) { - unsigned int new_reserve = 2 * s->UpdateStackReserved; - struct rc_dataflow_vector ** new_stack; - - if (!new_reserve) - new_reserve = 16; - - new_stack = memory_pool_malloc(&s->C->Pool, new_reserve * sizeof(struct rc_dataflow_vector *)); - memcpy(new_stack, s->UpdateStack, s->UpdateStackSize * sizeof(struct rc_dataflow_vector *)); - - s->UpdateStack = new_stack; - s->UpdateStackReserved = new_reserve; - } - - s->UpdateStack[s->UpdateStackSize++] = vector; - vector->PassBit = 1; - - if (!s->UpdateRunning) - run_update(s); -} - -static void annotate_instruction(struct dataflow_state * s, struct rc_instruction * inst) -{ - const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode); - unsigned int src; - - for(src = 0; src < opcode->NumSrcRegs; ++src) { - struct rc_dataflow_vector * vector = get_register_contents(s, inst->I.SrcReg[src].File, inst->I.SrcReg[src].Index); - if (vector) { - inst->Dataflow.SrcReg[src] = rc_dataflow_create_ref(s->C, vector, inst); - } - if (inst->I.SrcReg[src].RelAddr) { - struct rc_dataflow_vector * addr = get_register_contents(s, RC_FILE_ADDRESS, 0); - if (addr) - inst->Dataflow.SrcRegAddress[src] = rc_dataflow_create_ref(s->C, addr, inst); - } - } - - mark_instruction_source_use(s, inst, 0); /* for KIL */ - - if (opcode->HasDstReg) { - struct rc_dataflow_vector * oldvec = get_register_contents(s, inst->I.DstReg.File, inst->I.DstReg.Index); - struct rc_dataflow_vector * newvec = rc_dataflow_create_vector(s->C, inst->I.DstReg.File, inst->I.DstReg.Index, inst); - - newvec->ValidMask = inst->I.DstReg.WriteMask; - - if (oldvec) { - unsigned int carryover = oldvec->ValidMask & ~inst->I.DstReg.WriteMask; - - if (oldvec->ValidMask) - inst->Dataflow.DstRegAliased = 1; - - if (carryover) { - inst->Dataflow.DstRegPrev = rc_dataflow_create_ref(s->C, oldvec, inst); - newvec->ValidMask |= carryover; - - if (!s->DCE) - mark_ref_use(s, inst->Dataflow.DstRegPrev, carryover); - } - } - - inst->Dataflow.DstReg = newvec; - - if (newvec->File == RC_FILE_TEMPORARY) - s->Temporary[newvec->Index] = newvec; - else if (newvec->File == RC_FILE_OUTPUT) - s->Output[newvec->Index] = newvec; - else - s->Address = newvec; - - if (!s->DCE) - mark_vector_use(s, newvec, inst->I.DstReg.WriteMask); - } -} - -static void init_inputs(struct dataflow_state * s) -{ - unsigned int index; - - for(index = 0; index < 32; ++index) { - if (s->C->Program.InputsRead & (1 << index)) { - s->Input[index] = rc_dataflow_create_vector(s->C, RC_FILE_INPUT, index, 0); - s->Input[index]->ValidMask = RC_MASK_XYZW; - } - } -} - -static void mark_output_use(void * data, unsigned int index, unsigned int mask) -{ - struct dataflow_state * s = data; - struct rc_dataflow_vector * vec = s->Output[index]; - - if (vec) - mark_vector_use(s, vec, mask); -} - -void rc_dataflow_annotate(struct radeon_compiler * c, rc_dataflow_mark_outputs_fn dce, void * userdata) -{ - struct dataflow_state s; - struct rc_instruction * inst; - - memset(&s, 0, sizeof(s)); - s.C = c; - s.DCE = dce ? 1 : 0; - - init_inputs(&s); - - for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) { - annotate_instruction(&s, inst); - } - - if (s.DCE) { - dce(userdata, &s, &mark_output_use); - - for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) { - const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode); - - if (opcode->HasDstReg) { - unsigned int redundant_writes = inst->I.DstReg.WriteMask & ~inst->Dataflow.DstReg->UseMask; - - inst->I.DstReg.WriteMask &= ~redundant_writes; - - if (!inst->I.DstReg.WriteMask) { - struct rc_instruction * todelete = inst; - inst = inst->Prev; - rc_remove_instruction(todelete); - continue; - } - } - - unsigned int srcmasks[3]; - compute_sources_for_writemask(inst, inst->I.DstReg.WriteMask, srcmasks); - - for(unsigned int src = 0; src < 3; ++src) { - for(unsigned int chan = 0; chan < 4; ++chan) { - if (!GET_BIT(srcmasks[src], chan)) - SET_SWZ(inst->I.SrcReg[src].Swizzle, chan, RC_SWIZZLE_UNUSED); - } - - if (inst->Dataflow.SrcReg[src]) { - if (!inst->Dataflow.SrcReg[src]->UseMask) { - rc_dataflow_remove_ref(inst->Dataflow.SrcReg[src]); - inst->Dataflow.SrcReg[src] = 0; - } - } - - if (inst->Dataflow.SrcRegAddress[src]) { - if (!inst->Dataflow.SrcRegAddress[src]->UseMask) { - rc_dataflow_remove_ref(inst->Dataflow.SrcRegAddress[src]); - inst->Dataflow.SrcRegAddress[src] = 0; - } - } - } - } - - rc_calculate_inputs_outputs(c); - } -} diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c new file mode 100644 index 00000000000..95af6fd411f --- /dev/null +++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2009 Nicolai Haehnle. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "radeon_dataflow.h" + +#include "radeon_compiler.h" + + +struct updatemask_state { + unsigned char Output[RC_REGISTER_MAX_INDEX]; + unsigned char Temporary[RC_REGISTER_MAX_INDEX]; + unsigned char Address; +}; + +struct instruction_state { + unsigned char WriteMask; + unsigned char SrcReg[3]; +}; + +struct branchinfo { + unsigned int HaveElse:1; + + struct updatemask_state StoreEndif; + struct updatemask_state StoreElse; +}; + +struct deadcode_state { + struct radeon_compiler * C; + struct instruction_state * Instructions; + + struct updatemask_state R; + + struct branchinfo * BranchStack; + unsigned int BranchStackSize; + unsigned int BranchStackReserved; +}; + + +static void or_updatemasks( + struct updatemask_state * dst, + struct updatemask_state * a, + struct updatemask_state * b) +{ + for(unsigned int i = 0; i < RC_REGISTER_MAX_INDEX; ++i) { + dst->Output[i] = a->Output[i] | b->Output[i]; + dst->Temporary[i] = a->Temporary[i] | b->Temporary[i]; + } + + dst->Address = a->Address | b->Address; +} + +static void push_branch(struct deadcode_state * s) +{ + if (s->BranchStackSize >= s->BranchStackReserved) { + unsigned int new_reserve = 2 * s->BranchStackReserved; + struct branchinfo * new_stack; + + if (!new_reserve) + new_reserve = 4; + + new_stack = memory_pool_malloc(&s->C->Pool, new_reserve * sizeof(struct branchinfo)); + memcpy(new_stack, s->BranchStack, s->BranchStackSize * sizeof(struct branchinfo)); + + s->BranchStack = new_stack; + s->BranchStackReserved = new_reserve; + } + + struct branchinfo * branch = &s->BranchStack[s->BranchStackSize++]; + branch->HaveElse = 0; + memcpy(&branch->StoreEndif, &s->R, sizeof(s->R)); +} + +static unsigned char * get_used_ptr(struct deadcode_state *s, rc_register_file file, unsigned int index) +{ + if (file == RC_FILE_OUTPUT || file == RC_FILE_TEMPORARY) { + if (index >= RC_REGISTER_MAX_INDEX) { + rc_error(s->C, "%s: index %i is out of bounds for file %i\n", __FUNCTION__, index, file); + return 0; + } + + if (file == RC_FILE_OUTPUT) + return &s->R.Output[index]; + else + return &s->R.Temporary[index]; + } else if (file == RC_FILE_ADDRESS) { + return &s->R.Address; + } + + return 0; +} + +static void mark_used(struct deadcode_state * s, rc_register_file file, unsigned int index, unsigned int mask) +{ + unsigned char * pused = get_used_ptr(s, file, index); + if (pused) + *pused |= mask; +} + +static void update_instruction(struct deadcode_state * s, struct rc_instruction * inst) +{ + const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode); + struct instruction_state * insts = &s->Instructions[inst->IP]; + unsigned int usedmask = 0; + + if (opcode->HasDstReg) { + unsigned char * pused = get_used_ptr(s, inst->I.DstReg.File, inst->I.DstReg.Index); + if (pused) { + usedmask = *pused & inst->I.DstReg.WriteMask; + *pused &= ~usedmask; + } + } + + insts->WriteMask |= usedmask; + + unsigned int srcmasks[3]; + rc_compute_sources_for_writemask(opcode, usedmask, srcmasks); + + for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) { + unsigned int refmask = 0; + unsigned int newsrcmask = srcmasks[src] & ~insts->SrcReg[src]; + insts->SrcReg[src] |= newsrcmask; + + for(unsigned int chan = 0; chan < 4; ++chan) { + if (GET_BIT(newsrcmask, chan)) + refmask |= 1 << GET_SWZ(inst->I.SrcReg[src].Swizzle, chan); + } + + /* get rid of spurious bits from ZERO, ONE, etc. swizzles */ + refmask &= RC_MASK_XYZW; + + if (!refmask) + continue; + + mark_used(s, inst->I.SrcReg[src].File, inst->I.SrcReg[src].Index, refmask); + + if (inst->I.SrcReg[src].RelAddr) + mark_used(s, RC_FILE_ADDRESS, 0, RC_MASK_X); + } +} + +static void mark_output_use(void * data, unsigned int index, unsigned int mask) +{ + struct deadcode_state * s = data; + + mark_used(s, RC_FILE_OUTPUT, index, mask); +} + +void rc_dataflow_deadcode(struct radeon_compiler * c, rc_dataflow_mark_outputs_fn dce, void * userdata) +{ + struct deadcode_state s; + unsigned int nr_instructions; + + memset(&s, 0, sizeof(s)); + s.C = c; + + nr_instructions = rc_recompute_ips(c); + s.Instructions = memory_pool_malloc(&c->Pool, sizeof(struct instruction_state)*nr_instructions); + memset(s.Instructions, 0, sizeof(struct instruction_state)*nr_instructions); + + dce(userdata, &s, &mark_output_use); + + for(struct rc_instruction * inst = c->Program.Instructions.Prev; + inst != &c->Program.Instructions; + inst = inst->Prev) { + const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode); + + if (opcode->IsControlFlow) { + if (opcode->Opcode == RC_OPCODE_ENDIF) { + push_branch(&s); + } else { + if (s.BranchStackSize) { + struct branchinfo * branch = &s.BranchStack[s.BranchStackSize-1]; + + if (opcode->Opcode == RC_OPCODE_IF) { + or_updatemasks(&s.R, + &s.R, + branch->HaveElse ? &branch->StoreElse : &branch->StoreEndif); + + s.BranchStackSize--; + } else if (opcode->Opcode == RC_OPCODE_ELSE) { + if (branch->HaveElse) { + rc_error(c, "%s: Multiple ELSE for one IF/ENDIF\n", __FUNCTION__); + } else { + memcpy(&branch->StoreElse, &s.R, sizeof(s.R)); + memcpy(&s.R, &branch->StoreEndif, sizeof(s.R)); + branch->HaveElse = 1; + } + } else { + rc_error(c, "%s: Unhandled control flow instruction %s\n", __FUNCTION__, opcode->Name); + } + } else { + rc_error(c, "%s: Unexpected control flow instruction\n", __FUNCTION__); + } + } + } + + update_instruction(&s, inst); + } + + unsigned int ip = 0; + for(struct rc_instruction * inst = c->Program.Instructions.Next; + inst != &c->Program.Instructions; + inst = inst->Next, ++ip) { + const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode); + + if (opcode->HasDstReg) { + if (s.Instructions[ip].WriteMask) { + inst->I.DstReg.WriteMask = s.Instructions[ip].WriteMask; + } else { + struct rc_instruction * todelete = inst; + inst = inst->Prev; + rc_remove_instruction(todelete); + continue; + } + } + + unsigned int srcmasks[3]; + rc_compute_sources_for_writemask(opcode, s.Instructions[ip].WriteMask, srcmasks); + + for(unsigned int src = 0; src < 3; ++src) { + for(unsigned int chan = 0; chan < 4; ++chan) { + if (!GET_BIT(srcmasks[src], chan)) + SET_SWZ(inst->I.SrcReg[src].Swizzle, chan, RC_SWIZZLE_UNUSED); + } + } + } + + rc_calculate_inputs_outputs(c); +} diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_dealias.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_dealias.c deleted file mode 100644 index 4596636970a..00000000000 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_dealias.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2009 Nicolai Haehnle. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "radeon_dataflow.h" - -#include "radeon_compiler.h" - - -#define DEALIAS_LIST_SIZE 128 - -struct dealias_state { - struct radeon_compiler * C; - - unsigned int OldIndex:RC_REGISTER_INDEX_BITS; - unsigned int NewIndex:RC_REGISTER_INDEX_BITS; - unsigned int DealiasFail:1; - - struct rc_dataflow_vector * List[DEALIAS_LIST_SIZE]; - unsigned int Length; -}; - -static void push_dealias_vector(struct dealias_state * s, struct rc_dataflow_vector * vec) -{ - if (s->Length >= DEALIAS_LIST_SIZE) { - rc_debug(s->C, "%s: list size exceeded\n", __FUNCTION__); - s->DealiasFail = 1; - return; - } - - if (rc_assert(s->C, vec->File == RC_FILE_TEMPORARY && vec->Index == s->OldIndex)) - return; - - s->List[s->Length++] = vec; -} - -static void run_dealias(struct dealias_state * s) -{ - unsigned int i; - - for(i = 0; i < s->Length && !s->DealiasFail; ++i) { - struct rc_dataflow_vector * vec = s->List[i]; - struct rc_dataflow_ref * ref; - - for(ref = vec->Refs.Next; ref != &vec->Refs; ref = ref->Next) { - if (ref->ReadInstruction->Dataflow.DstRegPrev == ref) - push_dealias_vector(s, ref->ReadInstruction->Dataflow.DstReg); - } - } - - if (s->DealiasFail) - return; - - for(i = 0; i < s->Length; ++i) { - struct rc_dataflow_vector * vec = s->List[i]; - struct rc_dataflow_ref * ref; - - vec->Index = s->NewIndex; - vec->WriteInstruction->I.DstReg.Index = s->NewIndex; - - for(ref = vec->Refs.Next; ref != &vec->Refs; ref = ref->Next) { - struct rc_instruction * inst = ref->ReadInstruction; - unsigned int i; - - for(i = 0; i < 3; ++i) { - if (inst->Dataflow.SrcReg[i] == ref) { - if (rc_assert(s->C, inst->I.SrcReg[i].File == RC_FILE_TEMPORARY && - inst->I.SrcReg[i].Index == s->OldIndex)) - return; - - inst->I.SrcReg[i].Index = s->NewIndex; - } - } - } - } -} - -/** - * Breaks register aliasing to reduce multiple assignments to a single register. - * - * This affects sequences like: - * MUL r0, ...; - * MAD r0, r1, r2, r0; - * In this example, a new register will be used for the destination of the - * second MAD. - * - * The purpose of this dealiasing is to make the resulting code more SSA-like - * and therefore make it easier to move instructions around. - * This is of crucial importance for R300 fragment programs, where de-aliasing - * can help to reduce texture indirections, but other targets can benefit from - * it as well. - * - * \note When compiling GLSL, there may be some benefit gained from breaking - * up vectors whose components are unrelated. This is not done yet and should - * be investigated at some point (of course, a matching pass to re-merge - * components would be required). - */ -void rc_dataflow_dealias(struct radeon_compiler * c) -{ - struct dealias_state s; - - memset(&s, 0, sizeof(s)); - s.C = c; - - struct rc_instruction * inst; - for(inst = c->Program.Instructions.Prev; inst != &c->Program.Instructions; inst = inst->Prev) { - if (!inst->Dataflow.DstRegAliased || inst->Dataflow.DstReg->File != RC_FILE_TEMPORARY) - continue; - - if (inst->Dataflow.DstReg->UseMask & ~inst->I.DstReg.WriteMask) - continue; - - s.OldIndex = inst->I.DstReg.Index; - s.NewIndex = rc_find_free_temporary(c); - s.DealiasFail = 0; - s.Length = 0; - - inst->Dataflow.DstRegAliased = 0; - if (inst->Dataflow.DstRegPrev) { - rc_dataflow_remove_ref(inst->Dataflow.DstRegPrev); - inst->Dataflow.DstRegPrev = 0; - } - - push_dealias_vector(&s, inst->Dataflow.DstReg); - run_dealias(&s); - } -} diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c index 1aa91eff7c1..fcef218b594 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c @@ -37,8 +37,6 @@ static void rewrite_source(struct radeon_compiler * c, struct rc_swizzle_split split; unsigned int tempreg = rc_find_free_temporary(c); unsigned int usemask; - struct rc_dataflow_ref * oldref = inst->Dataflow.SrcReg[src]; - struct rc_dataflow_vector * vector = 0; usemask = 0; for(unsigned int chan = 0; chan < 4; ++chan) { @@ -75,30 +73,8 @@ static void rewrite_source(struct radeon_compiler * c, else if (masked_negate == split.Phase[phase]) mov->I.SrcReg[0].Negate = RC_MASK_XYZW; - if (oldref) { - mov->Dataflow.SrcReg[0] = rc_dataflow_create_ref(c, oldref->Vector, mov); - mov->Dataflow.SrcReg[0]->UseMask = phase_refmask; - } - - mov->Dataflow.DstReg = rc_dataflow_create_vector(c, RC_FILE_TEMPORARY, tempreg, mov); - mov->Dataflow.DstReg->ValidMask = split.Phase[phase]; - - if (vector) { - mov->Dataflow.DstRegPrev = rc_dataflow_create_ref(c, vector, mov); - mov->Dataflow.DstRegPrev->UseMask = vector->ValidMask; - mov->Dataflow.DstReg->ValidMask |= vector->ValidMask; - mov->Dataflow.DstRegAliased = 1; - } - - mov->Dataflow.DstReg->UseMask = mov->Dataflow.DstReg->ValidMask; - vector = mov->Dataflow.DstReg; } - if (oldref) - rc_dataflow_remove_ref(oldref); - inst->Dataflow.SrcReg[src] = rc_dataflow_create_ref(c, vector, inst); - inst->Dataflow.SrcReg[src]->UseMask = usemask; - inst->I.SrcReg[src].File = RC_FILE_TEMPORARY; inst->I.SrcReg[src].Index = tempreg; inst->I.SrcReg[src].Swizzle = 0; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c index b7200990c22..e097a62b550 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.c @@ -27,6 +27,8 @@ #include "radeon_opcodes.h" +#include "radeon_program_constants.h" + struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE] = { { .Opcode = RC_OPCODE_NOP, @@ -340,8 +342,84 @@ struct rc_opcode_info rc_opcodes[MAX_RC_OPCODE] = { .HasDstReg = 1 }, { + .Opcode = RC_OPCODE_IF, + .Name = "IF", + .IsControlFlow = 1, + .NumSrcRegs = 1 + }, + { + .Opcode = RC_OPCODE_ELSE, + .Name = "ELSE", + .IsControlFlow = 1, + .NumSrcRegs = 0 + }, + { + .Opcode = RC_OPCODE_ENDIF, + .Name = "ENDIF", + .IsControlFlow = 1, + .NumSrcRegs = 0 + }, + { .Opcode = RC_OPCODE_REPL_ALPHA, .Name = "REPL_ALPHA", .HasDstReg = 1 } }; + +void rc_compute_sources_for_writemask( + const struct rc_opcode_info * opcode, + unsigned int writemask, + unsigned int *srcmasks) +{ + srcmasks[0] = 0; + srcmasks[1] = 0; + srcmasks[2] = 0; + + if (opcode->Opcode == RC_OPCODE_KIL) + srcmasks[0] |= RC_MASK_XYZW; + else if (opcode->Opcode == RC_OPCODE_IF) + srcmasks[0] |= RC_MASK_X; + + if (!writemask) + return; + + if (opcode->IsComponentwise) { + for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) + srcmasks[src] |= writemask; + } else if (opcode->IsStandardScalar) { + for(unsigned int src = 0; src < opcode->NumSrcRegs; ++src) + srcmasks[src] |= RC_MASK_X; + } else { + switch(opcode->Opcode) { + case RC_OPCODE_ARL: + srcmasks[0] |= RC_MASK_X; + break; + case RC_OPCODE_DP3: + srcmasks[0] |= RC_MASK_XYZ; + srcmasks[1] |= RC_MASK_XYZ; + break; + case RC_OPCODE_DP4: + srcmasks[0] |= RC_MASK_XYZW; + srcmasks[1] |= RC_MASK_XYZW; + break; + case RC_OPCODE_TEX: + case RC_OPCODE_TXB: + case RC_OPCODE_TXP: + srcmasks[0] |= RC_MASK_XYZW; + break; + case RC_OPCODE_DST: + srcmasks[0] |= 0x6; + srcmasks[1] |= 0xa; + break; + case RC_OPCODE_EXP: + case RC_OPCODE_LOG: + srcmasks[0] |= RC_MASK_XY; + break; + case RC_OPCODE_LIT: + srcmasks[0] |= 0xb; + break; + default: + break; + } + } +} diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h index 8e30bef1e3e..f8ba5255ca7 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_opcodes.h @@ -166,6 +166,18 @@ typedef enum { RC_OPCODE_TXL, RC_OPCODE_TXP, + /** branch instruction: + * If src0.x != 0.0, continue with the next instruction; + * otherwise, jump to matching RC_OPCODE_ELSE or RC_OPCODE_ENDIF. + */ + RC_OPCODE_IF, + + /** branch instruction: jump to matching RC_OPCODE_ENDIF */ + RC_OPCODE_ELSE, + + /** branch instruction: has no effect */ + RC_OPCODE_ENDIF, + /** special instruction, used in R300-R500 fragment program pair instructions * indicates that the result of the alpha operation shall be replicated * across all other channels */ @@ -188,6 +200,9 @@ struct rc_opcode_info { unsigned int NumSrcRegs:2; unsigned int HasDstReg:1; + /** true if this instruction affects control flow */ + unsigned int IsControlFlow:1; + /** true if this is a vector instruction that operates on components in parallel * without any cross-component interaction */ unsigned int IsComponentwise:1; @@ -207,4 +222,9 @@ static inline const struct rc_opcode_info * rc_get_opcode_info(rc_opcode opcode) return &rc_opcodes[opcode]; } +void rc_compute_sources_for_writemask( + const struct rc_opcode_info * opcode, + unsigned int writemask, + unsigned int *srcmasks); + #endif /* RADEON_OPCODES_H */ diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.c b/src/mesa/drivers/dri/r300/compiler/radeon_program.c index b97c48084b4..a1ee7c0cab7 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.c @@ -154,7 +154,24 @@ struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, str void rc_remove_instruction(struct rc_instruction * inst) { - rc_dataflow_remove_instruction(inst); inst->Prev->Next = inst->Next; inst->Next->Prev = inst->Prev; } + +/** + * Return the number of instructions in the program. + */ +unsigned int rc_recompute_ips(struct radeon_compiler * c) +{ + unsigned int ip = 0; + + for(struct rc_instruction * inst = c->Program.Instructions.Next; + inst != &c->Program.Instructions; + inst = inst->Next) { + inst->IP = ip++; + } + + c->Program.Instructions.IP = 0xcafedead; + + return ip; +} diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.h b/src/mesa/drivers/dri/r300/compiler/radeon_program.h index d38c9a420c6..efa2b0dfe3e 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.h @@ -34,7 +34,6 @@ #include "radeon_opcodes.h" #include "radeon_code.h" #include "radeon_program_constants.h" -#include "radeon_dataflow.h" struct radeon_compiler; @@ -73,33 +72,33 @@ struct rc_dst_register { * instruction types may be valid. */ struct rc_sub_instruction { - struct rc_src_register SrcReg[3]; - struct rc_dst_register DstReg; - - /** - * Opcode of this instruction, according to \ref rc_opcode enums. - */ - rc_opcode Opcode:8; - - /** - * Saturate each value of the result to the range [0,1] or [-1,1], - * according to \ref rc_saturate_mode enums. - */ - rc_saturate_mode SaturateMode:2; - - /** - * \name Extra fields for TEX, TXB, TXD, TXL, TXP instructions. - */ - /*@{*/ - /** Source texture unit. */ - unsigned int TexSrcUnit:5; - - /** Source texture target, one of the \ref rc_texture_target enums */ - rc_texture_target TexSrcTarget:3; - - /** True if tex instruction should do shadow comparison */ - unsigned int TexShadow:1; - /*@}*/ + struct rc_src_register SrcReg[3]; + struct rc_dst_register DstReg; + + /** + * Opcode of this instruction, according to \ref rc_opcode enums. + */ + rc_opcode Opcode:8; + + /** + * Saturate each value of the result to the range [0,1] or [-1,1], + * according to \ref rc_saturate_mode enums. + */ + rc_saturate_mode SaturateMode:2; + + /** + * \name Extra fields for TEX, TXB, TXD, TXL, TXP instructions. + */ + /*@{*/ + /** Source texture unit. */ + unsigned int TexSrcUnit:5; + + /** Source texture target, one of the \ref rc_texture_target enums */ + rc_texture_target TexSrcTarget:3; + + /** True if tex instruction should do shadow comparison */ + unsigned int TexShadow:1; + /*@}*/ }; struct rc_instruction { @@ -109,13 +108,11 @@ struct rc_instruction { struct rc_sub_instruction I; /** - * Dataflow annotations. - * - * These are not supplied by the caller of the compiler, - * but filled in during compilation stages that make use of - * dataflow analysis. + * Warning: IPs are not stable. If you want to use them, + * you need to recompute them at the beginning of each pass + * using \ref rc_recompute_ips */ - struct rc_instruction_dataflow Dataflow; + unsigned int IP; }; struct rc_program { @@ -210,10 +207,8 @@ struct rc_instruction *rc_alloc_instruction(struct radeon_compiler * c); struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, struct rc_instruction * after); void rc_remove_instruction(struct rc_instruction * inst); -enum { - RC_PRINT_DATAFLOW = 0x1 -}; +unsigned int rc_recompute_ips(struct radeon_compiler * c); -void rc_print_program(const struct rc_program *prog, unsigned int flags); +void rc_print_program(const struct rc_program *prog); #endif diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c index 38060ea3adf..04852864516 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_print.c @@ -24,11 +24,6 @@ #include <stdio.h> -static void print_comment(FILE * f) -{ - fprintf(f, " # "); -} - static const char * textarget_to_string(rc_texture_target target) { switch(target) { @@ -121,19 +116,7 @@ static void rc_print_src_register(FILE * f, struct rc_src_register src) fprintf(f, "|"); } -static void rc_print_ref(FILE * f, struct rc_dataflow_ref * ref) -{ - fprintf(f, "ref(%p", ref->Vector); - - if (ref->UseMask != RC_MASK_XYZW) { - fprintf(f, "."); - rc_print_mask(f, ref->UseMask); - } - - fprintf(f, ")"); -} - -static void rc_print_instruction(FILE * f, unsigned int flags, struct rc_instruction * inst) +static void rc_print_instruction(FILE * f, struct rc_instruction * inst) { const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode); unsigned int reg; @@ -169,45 +152,22 @@ static void rc_print_instruction(FILE * f, unsigned int flags, struct rc_instruc } fprintf(f, ";\n"); - - if (flags & RC_PRINT_DATAFLOW) { - print_comment(f); - - fprintf(f, "Dst = %p", inst->Dataflow.DstReg); - if (inst->Dataflow.DstRegAliased) - fprintf(f, " aliased"); - if (inst->Dataflow.DstRegPrev) { - fprintf(f, " from "); - rc_print_ref(f, inst->Dataflow.DstRegPrev); - } - - for(reg = 0; reg < opcode->NumSrcRegs; ++reg) { - fprintf(f, ", "); - if (inst->Dataflow.SrcReg[reg]) - rc_print_ref(f, inst->Dataflow.SrcReg[reg]); - else - fprintf(f, "<no ref>"); - } - - fprintf(f, "\n"); - } } /** * Print program to stderr, default options. */ -void rc_print_program(const struct rc_program *prog, unsigned int flags) +void rc_print_program(const struct rc_program *prog) { unsigned int linenum = 0; struct rc_instruction *inst; - fprintf(stderr, "# Radeon Compiler Program%s\n", - flags & RC_PRINT_DATAFLOW ? " (with dataflow annotations)" : ""); + fprintf(stderr, "# Radeon Compiler Program\n"); for(inst = prog->Instructions.Next; inst != &prog->Instructions; inst = inst->Next) { fprintf(stderr, "%3d: ", linenum); - rc_print_instruction(stderr, flags, inst); + rc_print_instruction(stderr, inst); linenum++; } |