From 4aa487e7968d015af4fe729f697105448fcb843f Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 7 Feb 2007 15:12:13 -0700 Subject: [PATCH] Use IR_LOOP to represent do-while and for-loops. Also, start moving high vs. low-level instruction selection into slang_emit.c --- src/mesa/shader/slang/slang_codegen.c | 110 +++++++++++++++----------- src/mesa/shader/slang/slang_emit.c | 82 +++++++++++-------- src/mesa/shader/slang/slang_ir.h | 7 +- src/mesa/shader/slang/slang_link.c | 2 +- src/mesa/swrast/s_fragprog.c | 12 ++- 5 files changed, 128 insertions(+), 85 deletions(-) diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 42c1f0897eb..14870f57ae8 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -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); - endLab = new_label(endAtom); - tree = new_seq(tree, endLab); + loop->Children[0] = new_seq(ifThen, + new_seq(body,incr)); - /* Pop this loop */ - A->CurLoopBreak = prevLoopBreak; - A->CurLoopCont = prevLoopCont; + A->CurLoop = prevLoop; /* pop loop, restore prev */ - 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); diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 2d5a7cf6f9d..29588379a2f 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -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_CONT: - { - 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: + /* fall-through */ + case IR_CONT: { + gl_inst_opcode opcode; 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; } diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index a7c858c69f7..0c827d9cd8c 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -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, diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index 017cf6078cb..b1d355ff802 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -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; diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c index 403a03aa32a..ace10a9222c 100644 --- a/src/mesa/swrast/s_fragprog.c +++ b/src/mesa/swrast/s_fragprog.c @@ -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; -- 2.30.2