From 63556fa9949f543a8134b6b5ff3d216acb71dd9f Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 23 Mar 2007 14:47:46 -0600 Subject: Add the ability to generate programs that doesn't use condition codes. ctx->Shader.EmitCondCodes determines if we use condition codes. If not, IF statement uses first operand's X component as the condition. Added OPCODE_BRK0, OPCODE_BRK1, OPCODE_CONT0, OPCODE_CONT1 to handle the common cases of conditional break/continue. --- src/mesa/shader/slang/slang_emit.c | 123 ++++++++++++++++++++++++++----------- 1 file changed, 86 insertions(+), 37 deletions(-) (limited to 'src/mesa/shader/slang/slang_emit.c') diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 16a054b35e..9e476b8a0f 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -61,6 +61,7 @@ typedef struct struct gl_program *prog; /* code-gen options */ GLboolean EmitHighLevelInstructions; + GLboolean EmitCondCodes; GLboolean EmitComments; } slang_emit_info; @@ -1155,10 +1156,6 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n) static struct prog_instruction * emit_cond(slang_emit_info *emitInfo, slang_ir_node *n) { - /* Conditional expression (in if/while/for stmts). - * Need to update condition code register. - * Next instruction is typically an IR_IF. - */ struct prog_instruction *inst; if (!n->Children[0]) @@ -1166,28 +1163,39 @@ emit_cond(slang_emit_info *emitInfo, slang_ir_node *n) inst = emit(emitInfo, n->Children[0]); - if (inst) { - /* set inst's CondUpdate flag */ - inst->CondUpdate = GL_TRUE; - n->Store = n->Children[0]->Store; - return inst; /* XXX or null? */ + if (emitInfo->EmitCondCodes) { + /* Conditional expression (in if/while/for stmts). + * Need to update condition code register. + * Next instruction is typically an IR_IF. + */ + if (inst) { + /* set inst's CondUpdate flag */ + inst->CondUpdate = GL_TRUE; + n->Store = n->Children[0]->Store; + return inst; /* XXX or null? */ + } + else { + /* This'll happen for things like "if (i) ..." where no code + * is normally generated for the expression "i". + * Generate a move instruction just to set condition codes. + * Note: must use full 4-component vector since all four + * condition codes must be set identically. + */ + if (!alloc_temp_storage(emitInfo, n, 4)) + return NULL; + inst = new_instruction(emitInfo, OPCODE_MOV); + inst->CondUpdate = GL_TRUE; + storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); + _slang_free_temp(emitInfo->vt, n->Store); + inst->Comment = _mesa_strdup("COND expr"); + return inst; /* XXX or null? */ + } } else { - /* This'll happen for things like "if (i) ..." where no code - * is normally generated for the expression "i". - * Generate a move instruction just to set condition codes. - * Note: must use full 4-component vector since all four - * condition codes must be set identically. - */ - if (!alloc_temp_storage(emitInfo, n, 4)) - return NULL; - inst = new_instruction(emitInfo, OPCODE_MOV); - inst->CondUpdate = GL_TRUE; - storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); - storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); - _slang_free_temp(emitInfo->vt, n->Store); - inst->Comment = _mesa_strdup("COND expr"); - return inst; /* XXX or null? */ + /* No-op */ + n->Store = n->Children[0]->Store; + return NULL; } } @@ -1244,7 +1252,13 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n) ifInstLoc = prog->NumInstructions; if (emitInfo->EmitHighLevelInstructions) { ifInst = new_instruction(emitInfo, OPCODE_IF); - ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */ + if (emitInfo->EmitCondCodes) { + ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */ + } + else { + /* test reg.x */ + storage_to_src_reg(&ifInst->SrcReg[0], n->Children[0]->Store); + } } else { /* conditional jump to else, or endif */ @@ -1252,8 +1266,10 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n) ifInst->DstReg.CondMask = COND_EQ; /* BRA if cond is zero */ ifInst->Comment = _mesa_strdup("if zero"); } - /* which condition code to use: */ - ifInst->DstReg.CondSwizzle = n->Children[0]->Store->Swizzle; + if (emitInfo->EmitCondCodes) { + /* which condition code to use: */ + ifInst->DstReg.CondSwizzle = n->Children[0]->Store->Swizzle; + } /* if body */ emit(emitInfo, n->Children[1]); @@ -1342,6 +1358,8 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n) ir->Opcode == IR_BREAK_IF_FALSE || ir->Opcode == IR_BREAK_IF_TRUE) { assert(inst->Opcode == OPCODE_BRK || + inst->Opcode == OPCODE_BRK0 || + inst->Opcode == OPCODE_BRK1 || inst->Opcode == OPCODE_BRA); /* go to instruction after end of loop */ inst->BranchTarget = endInstLoc + 1; @@ -1351,6 +1369,8 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n) ir->Opcode == IR_CONT_IF_FALSE || ir->Opcode == IR_CONT_IF_TRUE); assert(inst->Opcode == OPCODE_CONT || + inst->Opcode == OPCODE_CONT0 || + inst->Opcode == OPCODE_CONT1 || inst->Opcode == OPCODE_BRA); /* to go instruction at top of loop */ inst->BranchTarget = beginInstLoc; @@ -1361,7 +1381,7 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n) /** - * "Continue" or "break" statement. + * Unconditional "continue" or "break" statement. * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted. */ static struct prog_instruction * @@ -1393,24 +1413,52 @@ emit_cont_break_if(slang_emit_info *emitInfo, slang_ir_node *n, gl_inst_opcode opcode; struct prog_instruction *inst; + assert(n->Opcode == IR_CONT_IF_TRUE || + n->Opcode == IR_CONT_IF_FALSE || + n->Opcode == IR_BREAK_IF_TRUE || + n->Opcode == IR_BREAK_IF_FALSE); + /* evaluate condition expr, setting cond codes */ inst = emit(emitInfo, n->Children[0]); - assert(inst); - inst->CondUpdate = GL_TRUE; + if (emitInfo->EmitCondCodes) { + assert(inst); + inst->CondUpdate = GL_TRUE; + } n->InstLocation = emitInfo->prog->NumInstructions; + + /* opcode selection */ if (emitInfo->EmitHighLevelInstructions) { - if (n->Opcode == IR_CONT_IF_TRUE || - n->Opcode == IR_CONT_IF_FALSE) - opcode = OPCODE_CONT; - else - opcode = OPCODE_BRK; + if (emitInfo->EmitCondCodes) { + if (n->Opcode == IR_CONT_IF_TRUE || + n->Opcode == IR_CONT_IF_FALSE) + opcode = OPCODE_CONT; + else + opcode = OPCODE_BRK; + } + else { + if (n->Opcode == IR_CONT_IF_TRUE) + opcode = OPCODE_CONT1; + else if (n->Opcode == IR_CONT_IF_FALSE) + opcode = OPCODE_CONT0; + else if (n->Opcode == IR_BREAK_IF_TRUE) + opcode = OPCODE_BRK1; + else if (n->Opcode == IR_BREAK_IF_FALSE) + opcode = OPCODE_BRK0; + } } else { opcode = OPCODE_BRA; } + inst = new_instruction(emitInfo, opcode); - inst->DstReg.CondMask = breakTrue ? COND_NE : COND_EQ; + if (emitInfo->EmitCondCodes) { + inst->DstReg.CondMask = breakTrue ? COND_NE : COND_EQ; + } + else { + /* BRK0, BRK1, CONT0, CONT1 */ + storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); + } return inst; } @@ -1779,7 +1827,8 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt, emitInfo.prog = prog; emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions; - emitInfo.EmitComments = 1+ctx->Shader.EmitComments; + emitInfo.EmitCondCodes = 0; /* XXX temporary! */ + emitInfo.EmitComments = ctx->Shader.EmitComments; (void) emit(&emitInfo, n); -- cgit v1.2.3