Kaynağa Gözat

r300/compiler: Handle more complex conditionals in loops.

tags/mesa-7.9-rc1
Tom Stellard 15 yıl önce
ebeveyn
işleme
3eca311b72

+ 84
- 71
src/mesa/drivers/dri/r300/compiler/radeon_emulate_loops.c Dosyayı Görüntüle

@@ -47,6 +47,10 @@ struct emulate_loop_state {

struct loop_info {
struct rc_instruction * BeginLoop;
struct rc_instruction * Cond;
struct rc_instruction * If;
struct rc_instruction * Brk;
struct rc_instruction * EndIf;
struct rc_instruction * EndLoop;
};

@@ -293,37 +297,12 @@ static int transform_const_loop(struct emulate_loop_state * s,
count_inst.Amount);

DBG("Loop will have %d iterations.\n", iterations);
/* Prepare loop for unrolling */
/* Remove the first 4 instructions inside the loop, which are part
* of the conditional and no longer needed.
*/
/* SLT/SGE/SGT/SLE */
if(loop->BeginLoop->Next->U.I.Opcode != RC_OPCODE_SLT &&
loop->BeginLoop->Next->U.I.Opcode != RC_OPCODE_SGE &&
loop->BeginLoop->Next->U.I.Opcode != RC_OPCODE_SGT &&
loop->BeginLoop->Next->U.I.Opcode != RC_OPCODE_SLE){
rc_error(s->C,"Unexpected instruction, expected LT,GT,LE,GE\n");
return 0;
}
/* IF */
rc_remove_instruction(loop->BeginLoop->Next);
if(loop->BeginLoop->Next->U.I.Opcode != RC_OPCODE_IF){
rc_error(s->C,"Unexpected instruction, expected IF\n");
return 0;
}
rc_remove_instruction(loop->BeginLoop->Next);
/* BRK */
if(loop->BeginLoop->Next->U.I.Opcode != RC_OPCODE_BRK){
rc_error(s->C,"Unexpected instruction, expected BRK\n");
return 0;
}
rc_remove_instruction(loop->BeginLoop->Next);
/* ENDIF */
if(loop->BeginLoop->Next->U.I.Opcode != RC_OPCODE_ENDIF){
rc_error(s->C,"Unexpected instruction, expected ENDIF\n");
return 0;
}
rc_remove_instruction(loop->BeginLoop->Next);
rc_remove_instruction(loop->Cond);
rc_remove_instruction(loop->If);
rc_remove_instruction(loop->Brk);
rc_remove_instruction(loop->EndIf);
loop_unroll(s, loop, iterations);
loop->EndLoop = NULL;
@@ -334,6 +313,7 @@ static int transform_const_loop(struct emulate_loop_state * s,
* This function prepares a loop to be unrolled by converting it into an if
* statement. Here is an outline of the conversion process:
* BGNLOOP; -> BGNLOOP;
* <Additional conditional code> -> <Additional conditional code>
* SGE/SLT temp[0], temp[1], temp[2]; -> SLT/SGE temp[0], temp[1], temp[2];
* IF temp[0]; -> IF temp[0];
* BRK; ->
@@ -342,7 +322,10 @@ static int transform_const_loop(struct emulate_loop_state * s,
* ENDLOOP; -> ENDLOOP
*
* @param inst A pointer to a BGNLOOP instruction.
* @return A pointer to the ENDLOOP instruction.
* @return If the loop can be unrolled, a pointer to the first instruction of
* the unrolled loop.
* Otherwise, A pointer to the ENDLOOP instruction.
* Null if there is an error.
*/
static struct rc_instruction * transform_loop(struct emulate_loop_state * s,
struct rc_instruction * inst)
@@ -355,27 +338,79 @@ static struct rc_instruction * transform_loop(struct emulate_loop_state * s,

loop = &s->Loops[s->LoopCount++];
memset(loop, 0, sizeof(struct loop_info));
if(inst->U.I.Opcode != RC_OPCODE_BGNLOOP){
rc_error(s->C, "expected BGNLOOP\n", __FUNCTION__);
return NULL;
}
loop->BeginLoop = inst;

for(ptr = loop->BeginLoop->Next; !loop->EndLoop; ptr = ptr->Next){
switch(ptr->U.I.Opcode){
case RC_OPCODE_BGNLOOP:
/* Nested loop */
ptr = transform_loop(s, ptr);
if(!ptr){
return NULL;
}
break;
case RC_OPCODE_BRK:
loop->Brk = ptr;
if(ptr->Next->U.I.Opcode != RC_OPCODE_ENDIF){
rc_error(s->C,
"%s: expected ENDIF\n",__FUNCTION__);
return NULL;
}
loop->EndIf = ptr->Next;
if(ptr->Prev->U.I.Opcode != RC_OPCODE_IF){
rc_error(s->C,
"%s: expected IF\n", __FUNCTION__);
return NULL;
}
loop->If = ptr->Prev;
switch(loop->If->Prev->U.I.Opcode){
case RC_OPCODE_SLT:
case RC_OPCODE_SGE:
case RC_OPCODE_SGT:
case RC_OPCODE_SLE:
case RC_OPCODE_SEQ:
case RC_OPCODE_SNE:
break;
default:
rc_error(s->C, "%s expected conditional\n",
__FUNCTION__);
return NULL;
}
loop->Cond = loop->If->Prev;
ptr = loop->EndIf;
break;
case RC_OPCODE_ENDLOOP:
loop->EndLoop = ptr;
break;
}
}
/* Reverse the conditional instruction */
ptr = inst->Next;
switch(ptr->U.I.Opcode){
switch(loop->Cond->U.I.Opcode){
case RC_OPCODE_SGE:
ptr->U.I.Opcode = RC_OPCODE_SLT;
loop->Cond->U.I.Opcode = RC_OPCODE_SLT;
break;
case RC_OPCODE_SLT:
ptr->U.I.Opcode = RC_OPCODE_SGE;
loop->Cond->U.I.Opcode = RC_OPCODE_SGE;
break;
case RC_OPCODE_SLE:
ptr->U.I.Opcode = RC_OPCODE_SGT;
loop->Cond->U.I.Opcode = RC_OPCODE_SGT;
break;
case RC_OPCODE_SGT:
ptr->U.I.Opcode = RC_OPCODE_SLE;
loop->Cond->U.I.Opcode = RC_OPCODE_SLE;
break;
default:
rc_error(s->C,
"Loop does not start with a conditional instruction.");
case RC_OPCODE_SEQ:
loop->Cond->U.I.Opcode = RC_OPCODE_SNE;
break;
case RC_OPCODE_SNE:
loop->Cond->U.I.Opcode = RC_OPCODE_SEQ;
break;
default:
rc_error(s->C, "loop->Cond is not a conditional.\n");
return NULL;
}
/* Check if the number of loops is known at compile time. */
@@ -383,36 +418,11 @@ static struct rc_instruction * transform_loop(struct emulate_loop_state * s,
return loop->BeginLoop->Next;
}

while(!loop->EndLoop){
struct rc_instruction * endif;
if(ptr->Type == RC_INSTRUCTION_NORMAL){
}
switch(ptr->U.I.Opcode){
case RC_OPCODE_BGNLOOP:
/* Nested loop */
ptr = transform_loop(s, ptr);
break;
case RC_OPCODE_BRK:
/* The BRK instruction should always be followed by
* an ENDIF. This ENDIF will eventually replace the
* ENDLOOP insruction. */
if(ptr->Next->U.I.Opcode != RC_OPCODE_ENDIF){
rc_error(s->C,
"transform_loop: expected ENDIF\n");
}
endif = ptr->Next;
rc_remove_instruction(ptr);
rc_remove_instruction(endif);
break;
case RC_OPCODE_ENDLOOP:
/* Insert the ENDIF before ENDLOOP. */
rc_insert_instruction(ptr->Prev, endif);
loop->EndLoop = ptr;
break;
}
ptr = ptr->Next;
}
return ptr;
/* Prepare the loop to be unrolled */
rc_remove_instruction(loop->Brk);
rc_remove_instruction(loop->EndIf);
rc_insert_instruction(loop->EndLoop->Prev, loop->EndIf);
return loop->EndLoop;
}

static void rc_transform_loops(struct emulate_loop_state * s)
@@ -422,6 +432,9 @@ static void rc_transform_loops(struct emulate_loop_state * s)
if(ptr->Type == RC_INSTRUCTION_NORMAL &&
ptr->U.I.Opcode == RC_OPCODE_BGNLOOP){
ptr = transform_loop(s, ptr);
if(!ptr){
return;
}
}
ptr = ptr->Next;
}

Loading…
İptal
Kaydet