r300/compiler: handle indexable temporaries correctly in deadcode elimination
authorMarek Olšák <maraeo@gmail.com>
Sun, 22 Aug 2010 01:29:54 +0000 (03:29 +0200)
committerMarek Olšák <maraeo@gmail.com>
Wed, 25 Aug 2010 00:44:28 +0000 (02:44 +0200)
src/mesa/drivers/dri/r300/compiler/radeon_dataflow_deadcode.c

index faf531b412e29d9abd61fbe16f3f3ea36b1aeb9f..acdb371de936192570610f9cbe9260fdc548a63c 100644 (file)
@@ -157,8 +157,12 @@ static void update_instruction(struct deadcode_state * s, struct rc_instruction
                unsigned char * pused = get_used_ptr(s, inst->U.I.DstReg.File, inst->U.I.DstReg.Index);
                if (pused) {
                        usedmask = *pused & inst->U.I.DstReg.WriteMask;
-                       *pused &= ~usedmask;
+                       if (!inst->U.I.DstReg.RelAddr)
+                               *pused &= ~usedmask;
                }
+
+               if (inst->U.I.DstReg.RelAddr)
+                       mark_used(s, RC_FILE_ADDRESS, 0, RC_MASK_X);
        }
 
        insts->WriteMask |= usedmask;
@@ -213,6 +217,7 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, rc_dataflow_mark_outputs_f
 {
        struct deadcode_state s;
        unsigned int nr_instructions;
+       unsigned has_temp_reladdr_src = 0;
 
        memset(&s, 0, sizeof(s));
        s.C = c;
@@ -300,6 +305,30 @@ void rc_dataflow_deadcode(struct radeon_compiler * c, rc_dataflow_mark_outputs_f
                                        rc_error(c, "%s: Unhandled control flow instruction %s\n", __FUNCTION__, opcode->Name);
                                }
                        }
+
+                       if (!has_temp_reladdr_src) {
+                               for (unsigned i = 0; i < opcode->NumSrcRegs; i++) {
+                                       if (inst->U.I.SrcReg[i].File == RC_FILE_TEMPORARY &&
+                                           inst->U.I.SrcReg[i].RelAddr) {
+                                               /* If there is a register read from a temporary file with relative addressing,
+                                                * mark all preceding written registers as used. */
+                                               for (struct rc_instruction *ptr = inst->Prev;
+                                                    ptr != &c->Program.Instructions;
+                                                    ptr = ptr->Prev) {
+                                                       if (opcode->HasDstReg &&
+                                                           ptr->U.I.DstReg.File == RC_FILE_TEMPORARY &&
+                                                           ptr->U.I.DstReg.WriteMask) {
+                                                               mark_used(&s,
+                                                                         ptr->U.I.DstReg.File,
+                                                                         ptr->U.I.DstReg.Index,
+                                                                         ptr->U.I.DstReg.WriteMask);
+                                                       }
+                                               }
+
+                                               has_temp_reladdr_src = 1;
+                                       }
+                               }
+                       }
                }
 
                update_instruction(&s, inst);