From b768c485474baefdde63098776e9d32c17b859ab Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 8 Feb 2007 13:23:17 -0700 Subject: Use conditional break in for/do/while loops. --- src/mesa/shader/slang/slang_codegen.c | 106 +++++++++++++++------------------- src/mesa/shader/slang/slang_emit.c | 44 +++++++++++++- 2 files changed, 88 insertions(+), 62 deletions(-) diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index bd7b30cd13..6671f31c47 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -616,6 +616,21 @@ new_break(slang_ir_node *loopNode) } +static slang_ir_node * +new_break_if_false(slang_ir_node *loopNode, slang_ir_node *cond) +{ + slang_ir_node *n = new_node1(IR_BREAK_IF_FALSE, cond); + assert(loopNode); + assert(loopNode->Opcode == IR_LOOP); + if (n) { + /* insert this node at head of linked list */ + n->BranchNode = loopNode->BranchNode; + loopNode->BranchNode = n; + } + return n; +} + + static slang_ir_node * new_cont(slang_ir_node *loopNode) { @@ -631,6 +646,14 @@ new_cont(slang_ir_node *loopNode) } +static slang_ir_node * +new_cond(slang_ir_node *n) +{ + slang_ir_node *c = new_node1(IR_COND, n); + return c; +} + + static slang_ir_node * new_if(slang_ir_node *cond, slang_ir_node *ifPart, slang_ir_node *elsePart) { @@ -1290,14 +1313,6 @@ _slang_is_noop(const slang_operation *oper) } -static slang_ir_node * -_slang_gen_cond(slang_ir_node *n) -{ - slang_ir_node *c = new_node1(IR_COND, n); - return c; -} - - static void print_funcs(struct slang_function_scope_ *scope, const char *name) { @@ -1381,12 +1396,10 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper) slang_ir_node *prevLoop; /* * LOOP: - * eval expr (child[0]), updating condcodes - * IF !expr: - * BRK + * BREAK if !expr (child[0]) * body code (child[1]) */ - slang_ir_node *ifThen, *cond, *body, *loop; + slang_ir_node *loop, *cond, *breakIf, *body; loop = new_loop(NULL); @@ -1395,19 +1408,12 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper) A->CurLoop = loop; cond = _slang_gen_operation(A, &oper->children[0]); - cond = new_node1(IR_NOT, cond); - cond = _slang_gen_cond(cond); - - ifThen = new_if(cond, - new_break(A->CurLoop), - NULL); - + breakIf = new_break_if_false(A->CurLoop, cond); body = _slang_gen_operation(A, &oper->children[1]); + loop->Children[0] = new_seq(breakIf, body); - loop->Children[0] = new_seq(ifThen, body); - - - A->CurLoop = prevLoop; /* pop loop, restore prev */ + /* pop loop, restore prev */ + A->CurLoop = prevLoop; return loop; } @@ -1423,11 +1429,9 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper) /* * LOOP: * body code (child[0]) - * eval expr (child[1]), updating condcodes - * IF !expr: - * BRK + * BREAK if !expr (child[1]) */ - slang_ir_node *ifThen, *cond, *body, *loop; + slang_ir_node *loop, *cond, *breakIf, *body; loop = new_loop(NULL); @@ -1436,18 +1440,12 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper) 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); + breakIf = new_break_if_false(A->CurLoop, cond); + loop->Children[0] = new_seq(body, breakIf); - ifThen = new_if(cond, - new_break(A->CurLoop), - NULL); - - loop->Children[0] = new_seq(body, ifThen); - - A->CurLoop = prevLoop; /* pop loop, restore prev */ + /* pop loop, restore prev */ + A->CurLoop = prevLoop; return loop; } @@ -1463,13 +1461,11 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper) /* * init (child[0]) * LOOP: - * eval expr (child[1]), updating condcodes - * IF !expr: - * BRK + * BREAK if !expr (child[1]) * body code (child[3]) * incr code (child[2]) // XXX continue here */ - slang_ir_node *init, *ifThen, *cond, *body, *loop, *incr; + slang_ir_node *loop, *cond, *breakIf, *body, *init, *incr; init = _slang_gen_operation(A, &oper->children[0]); loop = new_loop(NULL); @@ -1479,21 +1475,14 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper) A->CurLoop = loop; 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); - + breakIf = new_break_if_false(A->CurLoop, cond); body = _slang_gen_operation(A, &oper->children[3]); - incr = _slang_gen_operation(A, &oper->children[2]); + loop->Children[0] = new_seq(breakIf, + new_seq(body, incr)); - loop->Children[0] = new_seq(ifThen, - new_seq(body,incr)); - - A->CurLoop = prevLoop; /* pop loop, restore prev */ + /* pop loop, restore prev */ + A->CurLoop = prevLoop; return new_seq(init, loop); } @@ -1521,7 +1510,7 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper) slang_atom endifAtom = slang_atom_pool_gen(A->atoms, "__endif"); cond = _slang_gen_operation(A, &oper->children[0]); - cond = _slang_gen_cond(cond); + cond = new_cond(cond); /*assert(cond->Store);*/ bra = new_cjump(haveElseClause ? elseAtom : endifAtom, 0); tree = new_seq(cond, bra); @@ -1572,7 +1561,7 @@ _slang_gen_hl_if(slang_assemble_ctx * A, const slang_operation *oper) slang_ir_node *ifNode, *cond, *ifBody, *elseBody; cond = _slang_gen_operation(A, &oper->children[0]); - cond = _slang_gen_cond(cond); + cond = new_cond(cond); ifBody = _slang_gen_operation(A, &oper->children[1]); if (haveElseClause) elseBody = _slang_gen_operation(A, &oper->children[2]); @@ -1662,7 +1651,7 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper) /* eval condition */ cond = _slang_gen_operation(A, &oper->children[0]); - cond = _slang_gen_cond(cond); + cond = new_cond(cond); tree = new_seq(tmpDecl, cond); /* jump if false to "alt" label */ @@ -2245,9 +2234,6 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) case slang_oper_block_no_new_scope: /* list of operations */ - /* - assert(oper->num_children > 0); - */ if (oper->num_children > 0) { slang_ir_node *n, *tree = NULL; @@ -2287,7 +2273,7 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) break; case slang_oper_expression: return _slang_gen_operation(A, &oper->children[0]); - break; + case slang_oper_for: return _slang_gen_for(A, oper); case slang_oper_do: diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 6e2394f265..d83880a26f 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -332,6 +332,9 @@ slang_print_ir(const slang_ir_node *n, int indent) case IR_BREAK: printf("BREAK\n"); break; + case IR_BREAK_IF_FALSE: + printf("BREAK_IF_FALSE\n"); + break; case IR_VAR: printf("VAR %s%s at %s store %p\n", @@ -1153,13 +1156,17 @@ emit_loop(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) */ for (ir = n->BranchNode; ir; ir = ir->BranchNode) { struct prog_instruction *inst = prog->Instructions + ir->InstLocation; - if (ir->Opcode == IR_BREAK) { + if (ir->Opcode == IR_BREAK || + ir->Opcode == IR_BREAK_IF_FALSE || + ir->Opcode == IR_BREAK_IF_TRUE) { assert(inst->Opcode == OPCODE_BRK || inst->Opcode == OPCODE_BRA); inst->BranchTarget = endInstLoc + 1; } else { - assert(ir->Opcode == IR_CONT); + assert(ir->Opcode == IR_CONT || + ir->Opcode == IR_CONT_IF_FALSE || + ir->Opcode == IR_CONT_IF_TRUE); assert(inst->Opcode == OPCODE_CONT || inst->Opcode == OPCODE_BRA); /* XXX goto top of loop instead! */ @@ -1191,6 +1198,35 @@ emit_cont_break(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) } +/** + * Conditional loop continue/break. + */ +static struct prog_instruction * +emit_cont_break_if(slang_var_table *vt, slang_ir_node *n, + struct gl_program *prog, GLboolean breakTrue) +{ + gl_inst_opcode opcode; + struct prog_instruction *inst; + + /* evaluate condition expr, setting cond codes */ + inst = emit(vt, n->Children[0], prog); + assert(inst); + inst->CondUpdate = GL_TRUE; + + n->InstLocation = prog->NumInstructions; + if (EmitHighLevelInstructions) { + opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK; + } + else { + opcode = OPCODE_BRA; + } + inst = new_instruction(prog, opcode); + inst->DstReg.CondMask = breakTrue ? COND_NE : COND_EQ; + return inst; +} + + + /** * Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term). * Ex: fix_swizzle("zyNN") -> "zyyy" @@ -1407,6 +1443,10 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) case IR_LOOP: return emit_loop(vt, n, prog); + case IR_BREAK_IF_FALSE: + return emit_cont_break_if(vt, n, prog, GL_FALSE); + case IR_BREAK_IF_TRUE: + return emit_cont_break_if(vt, n, prog, GL_TRUE); case IR_BREAK: /* fall-through */ case IR_CONT: -- cgit v1.2.3