Use IR_LOOP to represent do-while and for-loops.

Also, start moving high vs. low-level instruction selection into slang_emit.c
This commit is contained in:
Brian
2007-02-07 15:12:13 -07:00
parent 1f99a7514e
commit 4aa487e796
5 changed files with 128 additions and 85 deletions

View File

@@ -1423,7 +1423,7 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
/**
* Generate IR tree for a while-loop using high-level LOOP, IF instructions.
* Generate loop code using high-level IR_LOOP instruction
*/
static slang_ir_node *
_slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
@@ -1509,6 +1509,46 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
}
/**
* Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
*/
static slang_ir_node *
_slang_gen_hl_do(slang_assemble_ctx * A, const slang_operation *oper)
{
slang_ir_node *prevLoop;
/*
* LOOP:
* body code (child[0])
* eval expr (child[1]), updating condcodes
* IF !expr:
* BRK
*/
slang_ir_node *ifThen, *cond, *body, *loop;
loop = new_loop(NULL);
/* save old, push new loop */
prevLoop = A->CurLoop;
A->CurLoop = loop;
body = _slang_gen_operation(A, &oper->children[0]);
cond = _slang_gen_operation(A, &oper->children[1]);
cond = new_node1(IR_NOT, cond);
cond = _slang_gen_cond(cond);
ifThen = new_if(cond,
new_break(A->CurLoop),
NULL);
loop->Children[0] = new_seq(body, ifThen);
A->CurLoop = prevLoop; /* pop loop, restore prev */
return loop;
}
/**
* Generate IR tree for a for-loop.
*/
@@ -1573,69 +1613,48 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
/**
* Generate IR tree for a for-loop, using high-level BGNLOOP/ENDLOOP and
* IF/ENDIF instructions.
*
* XXX note done yet!
* Generate for-loop using high-level IR_LOOP instruction.
*/
static slang_ir_node *
_slang_gen_hl_for(slang_assemble_ctx * A, const slang_operation *oper)
{
slang_ir_node *prevLoop;
/*
* init code (child[0])
* BGNLOOP
* init (child[0])
* LOOP:
* eval expr (child[1]), updating condcodes
* IF !expr THEN
* IF !expr:
* BRK
* ENDIF
* code body (child[3])
* label "__continueFor" // jump here for "continue"
* incr code (child[2])
* ENDLOOP
* body code (child[3])
* incr code (child[2]) // XXX continue here
*/
slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startFor");
slang_atom contAtom = slang_atom_pool_gen(A->atoms, "__continueFor");
slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endFor");
slang_ir_node *init, *startLab, *cond, *bra, *body, *contLab;
slang_ir_node *incr, *jump, *endLab, *tree;
slang_atom prevLoopBreak = A->CurLoopBreak;
slang_atom prevLoopCont = A->CurLoopCont;
/* Push this loop */
A->CurLoopBreak = endAtom;
A->CurLoopCont = contAtom;
slang_ir_node *init, *ifThen, *cond, *body, *loop, *incr;
init = _slang_gen_operation(A, &oper->children[0]);
startLab = new_label(startAtom);
tree = new_seq(init, startLab);
loop = new_loop(NULL);
/* save old, push new loop */
prevLoop = A->CurLoop;
A->CurLoop = loop;
cond = _slang_gen_operation(A, &oper->children[1]);
cond = new_node1(IR_NOT, cond);
cond = _slang_gen_cond(cond);
tree = new_seq(tree, cond);
bra = new_cjump(endAtom, 0);
tree = new_seq(tree, bra);
ifThen = new_if(cond,
new_break(A->CurLoop),
NULL);
body = _slang_gen_operation(A, &oper->children[3]);
tree = new_seq(tree, body);
contLab = new_label(contAtom);
tree = new_seq(tree, contLab);
incr = _slang_gen_operation(A, &oper->children[2]);
tree = new_seq(tree, incr);
jump = new_jump(startAtom);
tree = new_seq(tree, jump);
loop->Children[0] = new_seq(ifThen,
new_seq(body,incr));
endLab = new_label(endAtom);
tree = new_seq(tree, endLab);
A->CurLoop = prevLoop; /* pop loop, restore prev */
/* Pop this loop */
A->CurLoopBreak = prevLoopBreak;
A->CurLoopCont = prevLoopCont;
return tree;
return new_seq(init, loop);
}
@@ -2434,7 +2453,10 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
else
return _slang_gen_while(A, oper);
case slang_oper_do:
return _slang_gen_do(A, oper);
if (UseHighLevelInstructions)
return _slang_gen_hl_do(A, oper);
else
return _slang_gen_do(A, oper);
case slang_oper_for:
if (UseHighLevelInstructions)
return _slang_gen_hl_for(A, oper);

View File

@@ -43,6 +43,9 @@
#define ANNOTATE 1
static GLboolean EmitHighLevelInstructions = GL_FALSE;
/**
* Assembly and IR info
*/
@@ -1304,57 +1307,72 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
case IR_LOOP:
{
struct prog_instruction *beginInst, *endInst;
GLuint endInstLoc;
slang_ir_node *p;
GLuint beginInstLoc, endInstLoc;
slang_ir_node *ir;
/* save location of this instruction, used by OPCODE_ENDLOOP */
n->InstLocation = prog->NumInstructions;
(void) new_instruction(prog, OPCODE_BGNLOOP);
/* emit OPCODE_BGNLOOP */
beginInstLoc = prog->NumInstructions;
if (EmitHighLevelInstructions) {
(void) new_instruction(prog, OPCODE_BGNLOOP);
}
/* body */
emit(vt, n->Children[0], prog);
endInstLoc = prog->NumInstructions;
endInst = new_instruction(prog, OPCODE_ENDLOOP);
/* The ENDLOOP's BranchTarget points to top of loop */
endInst->BranchTarget = n->InstLocation;
/* Update BGNLOOP's BranchTarget to point to this instruction */
beginInst = prog->Instructions + n->InstLocation;
beginInst->BranchTarget = prog->NumInstructions - 1;
if (EmitHighLevelInstructions) {
/* emit OPCODE_ENDLOOP */
endInst = new_instruction(prog, OPCODE_ENDLOOP);
}
else {
/* emit unconditional BRA-nch */
endInst = new_instruction(prog, OPCODE_BRA);
endInst->DstReg.CondMask = COND_TR; /* always true */
}
/* end instruction's BranchTarget points to top of loop */
endInst->BranchTarget = beginInstLoc;
if (EmitHighLevelInstructions) {
/* BGNLOOP's BranchTarget points to the ENDLOOP inst */
beginInst = prog->Instructions + beginInstLoc;
beginInst->BranchTarget = prog->NumInstructions - 1;
}
/* Done emitting loop code. Now walk over the loop's linked list
* of BREAK and CONT nodes, filling in their BranchTarget fields.
* of BREAK and CONT nodes, filling in their BranchTarget fields
* (which will point to the ENDLOOP or ENDLOOP+1 instructions).
*/
for (p = n->BranchNode; p; p = p->BranchNode) {
if (p->Opcode == IR_BREAK) {
struct prog_instruction *brkInst
= prog->Instructions + p->InstLocation;
assert(brkInst->Opcode == OPCODE_BRK);
brkInst->BranchTarget = endInstLoc + 1;
for (ir = n->BranchNode; ir; ir = ir->BranchNode) {
struct prog_instruction *inst
= prog->Instructions + ir->InstLocation;
if (ir->Opcode == IR_BREAK) {
assert(inst->Opcode == OPCODE_BRK ||
inst->Opcode == OPCODE_BRA);
inst->BranchTarget = endInstLoc + 1;
}
else {
assert(p->Opcode == IR_CONT);
struct prog_instruction *contInst
= prog->Instructions + p->InstLocation;
assert(contInst->Opcode == OPCODE_CONT);
contInst->BranchTarget = endInstLoc;
assert(ir->Opcode == IR_CONT);
assert(inst->Opcode == OPCODE_CONT ||
inst->Opcode == OPCODE_BRA);
inst->BranchTarget = endInstLoc;
}
}
return NULL;
}
case IR_BREAK:
/* fall-through */
case IR_CONT:
{
gl_inst_opcode opcode;
struct prog_instruction *inst;
n->InstLocation = prog->NumInstructions;
inst = new_instruction(prog, OPCODE_CONT);
inst->DstReg.CondMask = COND_TR; /* always true */
return inst;
}
case IR_BREAK:
{
struct prog_instruction *inst;
n->InstLocation = prog->NumInstructions;
inst = new_instruction(prog, OPCODE_BRK);
if (EmitHighLevelInstructions) {
opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
}
else {
opcode = OPCODE_BRA;
}
inst = new_instruction(prog, opcode);
inst->DstReg.CondMask = COND_TR; /* always true */
return inst;
}

View File

@@ -39,7 +39,7 @@
/**
* Intermediate Representation opcode
* Intermediate Representation opcodes
*/
typedef enum
{
@@ -64,6 +64,11 @@ typedef enum
IR_CONT, /* continue loop */
IR_BREAK, /* break loop */
IR_BREAK_IF_TRUE,
IR_BREAK_IF_FALSE,
IR_CONT_IF_TRUE,
IR_CONT_IF_FALSE,
IR_MOVE,
IR_ADD,
IR_SUB,

View File

@@ -298,7 +298,7 @@ _slang_resolve_branches(struct gl_program *prog)
for (i = 0; i < prog->NumInstructions; i++) {
struct prog_instruction *inst = prog->Instructions + i;
if (inst->Opcode == OPCODE_BRA) {
if (inst->Opcode == OPCODE_BRA && inst->BranchTarget < 0) {
for (j = 0; j < numTargets; j++) {
if (!strcmp(inst->Comment, targets[j].Name)) {
inst->BranchTarget = targets[j].Pos;

View File

@@ -675,9 +675,10 @@ execute_program( GLcontext *ctx,
}
}
break;
case OPCODE_BGNLOOP: /* begin loop */
case OPCODE_BGNLOOP:
/* no-op */
break;
case OPCODE_ENDLOOP: /* end loop */
case OPCODE_ENDLOOP:
/* subtract 1 here since pc is incremented by for(pc) loop */
pc = inst->BranchTarget - 1; /* go to matching BNGLOOP */
break;
@@ -695,10 +696,7 @@ execute_program( GLcontext *ctx,
test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
/* take branch */
pc = inst->BranchTarget;
/*
printf("Take branch to %u\n", pc);
*/
pc = inst->BranchTarget - 1;
}
}
break;
@@ -721,7 +719,7 @@ execute_program( GLcontext *ctx,
return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
}
machine->CallStack[machine->StackDepth++] = pc + 1;
pc = inst->BranchTarget;
pc = inst->BranchTarget; /* XXX - 1 ??? */
}
}
break;