mesa: Branch 'glsl-compiler-1' - 5 commits
Brian Paul
brianp at kemper.freedesktop.org
Fri Mar 23 23:49:30 UTC 2007
docs/shading.html | 46 +++++++
src/mesa/main/mtypes.h | 6 -
src/mesa/shader/prog_execute.c | 53 +++++++--
src/mesa/shader/prog_instruction.c | 6 -
src/mesa/shader/prog_instruction.h | 4
src/mesa/shader/prog_print.c | 37 ++++--
src/mesa/shader/shader_api.c | 1
src/mesa/shader/slang/slang_codegen.c | 90 ++++++++-------
src/mesa/shader/slang/slang_emit.c | 198 +++++++++++++++++++++++++---------
src/mesa/shader/slang/slang_ir.h | 11 +
src/mesa/tnl/t_vb_arbprogram.c | 4
11 files changed, 347 insertions(+), 109 deletions(-)
New commits:
diff-tree 8f9db0f81c13c3244f07333f33a15bfe098e0f31 (from d1934c2065751e2c594316c5abd2c49c47bfc1b8)
Author: Brian <brian at yutani.localnet.net>
Date: Fri Mar 23 17:49:19 2007 -0600
document internal compiler options
diff --git a/docs/shading.html b/docs/shading.html
index cb2c1c3..40a6d7a 100644
--- a/docs/shading.html
+++ b/docs/shading.html
@@ -67,7 +67,7 @@ All other major features of the shading
<li>The quality of generated code is pretty good, register usage is fair.
<li>Shader error detection and reporting of errors (InfoLog) is not
very good yet.
-<li>There are massive memory leaks in the compiler.
+<li>There are known memory leaks in the compiler.
</ul>
<p>
@@ -236,6 +236,50 @@ The final vertex and fragment programs m
(see drivers/dri/i915/i915_fragprog.c for example).
</p>
+<h3>Code Generation Options</h3>
+
+<p>
+Internally, there are several options that control the compiler's code
+generation and instruction selection.
+These options are seen in the gl_shader_state struct and may be set
+by the device driver to indicate its preferences:
+
+<pre>
+struct gl_shader_state
+{
+ ...
+ /** Driver-selectable options: */
+ GLboolean EmitHighLevelInstructions;
+ GLboolean EmitCondCodes;
+ GLboolean EmitComments;
+};
+</pre>
+
+<ul>
+<li>EmitHighLevelInstructions
+<br>
+This option controls instruction selection for loops and conditionals.
+If the option is set high-level IF/ELSE/ENDIF, LOOP/ENDLOOP, CONT/BRK
+instructions will be emitted.
+Otherwise, those constructs will be implemented with BRA instructions.
+</li>
+
+<li>EmitCondCodes
+<br>
+If set, condition codes (ala GL_NV_fragment_program) will be used for
+branching and looping.
+Otherwise, ordinary registers will be used (the IF instruction will
+examine the first operand's X component and do the if-part if non-zero).
+This option is only relevant if EmitHighLevelInstructions is set.
+</li>
+
+<li>EmitComments
+<br>
+If set, instructions will be annoted with comments to help with debugging.
+Extra NOP instructions will also be inserted.
+</br>
+
+</ul>
</BODY>
diff-tree d1934c2065751e2c594316c5abd2c49c47bfc1b8 (from 81767eead9e1b1b5d5dfd274c0875fa1332a5983)
Author: Brian <brian at yutani.localnet.net>
Date: Fri Mar 23 17:48:42 2007 -0600
Fix issues related to the 'continue' statement.
IR_LOOP now has two children: the body code, and the tail code.
Tail code is the "i++" part of a for-loop, or the expression at the end
of a "do {} while(expr);" loop.
"continue" translates into: "execute tail code; CONT;"
Also, the test for infinite do/while loops was incorrect.
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 4e41aa8..2eb509b 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -414,7 +414,7 @@ _slang_free_ir_tree(slang_ir_node *n)
return;
for (i = 0; i < 3; i++)
_slang_free_ir_tree(n->Children[i]);
- /* Do not free n->BranchNode since it's a child elsewhere */
+ /* Do not free n->List since it's a child elsewhere */
free(n);
#endif
}
@@ -515,8 +515,8 @@ new_break(slang_ir_node *loopNode)
assert(loopNode->Opcode == IR_LOOP);
if (n) {
/* insert this node at head of linked list */
- n->BranchNode = loopNode->BranchNode;
- loopNode->BranchNode = n;
+ n->List = loopNode->List;
+ loopNode->List = n;
}
return n;
}
@@ -534,8 +534,8 @@ new_break_if(slang_ir_node *loopNode, sl
n = new_node1(breakTrue ? IR_BREAK_IF_TRUE : IR_BREAK_IF_FALSE, cond);
if (n) {
/* insert this node at head of linked list */
- n->BranchNode = loopNode->BranchNode;
- loopNode->BranchNode = n;
+ n->List = loopNode->List;
+ loopNode->List = n;
}
return n;
}
@@ -553,23 +553,8 @@ new_cont_if(slang_ir_node *loopNode, sla
n = new_node1(contTrue ? IR_CONT_IF_TRUE : IR_CONT_IF_FALSE, cond);
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)
-{
- slang_ir_node *n = new_node0(IR_CONT);
- assert(loopNode);
- assert(loopNode->Opcode == IR_LOOP);
- if (n) {
- /* insert this node at head of linked list */
- n->BranchNode = loopNode->BranchNode;
- loopNode->BranchNode = n;
+ n->List = loopNode->List;
+ loopNode->List = n;
}
return n;
}
@@ -1369,7 +1354,8 @@ _slang_gen_while(slang_assemble_ctx * A,
loop->Children[0] = new_seq(breakIf, body);
/* Do infinite loop detection */
- if (!loop->BranchNode && isConst && constTrue) {
+ /* loop->List is head of linked list of break/continue nodes */
+ if (!loop->List && isConst && constTrue) {
/* infinite loop detected */
A->CurLoop = prevLoop; /* clean-up */
slang_info_log_error(A->log, "Infinite loop detected!");
@@ -1392,30 +1378,33 @@ _slang_gen_do(slang_assemble_ctx * A, co
/*
* LOOP:
* body code (child[0])
- * BREAK if !expr (child[1])
+ * tail code:
+ * BREAK if !expr (child[1])
*/
- slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body;
+ slang_ir_node *prevLoop, *loop, *cond;
GLboolean isConst, constTrue;
- /* Check if loop condition is a constant */
- isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
-
loop = new_loop(NULL);
/* save old, push new loop */
prevLoop = A->CurLoop;
A->CurLoop = loop;
- body = _slang_gen_operation(A, &oper->children[0]);
- cond = new_cond(_slang_gen_operation(A, &oper->children[1]));
+ /* loop body: */
+ loop->Children[0] = _slang_gen_operation(A, &oper->children[0]);
+
+ /* Check if loop condition is a constant */
+ isConst = _slang_is_constant_cond(&oper->children[1], &constTrue);
if (isConst && constTrue) {
- /* while(nonzero constant), no conditional break */
- breakIf = NULL;
+ /* do { } while(1) ==> no conditional break */
+ loop->Children[1] = NULL; /* no tail code */
}
else {
- breakIf = new_break_if(A->CurLoop, cond, GL_FALSE);
+ cond = new_cond(_slang_gen_operation(A, &oper->children[1]));
+ loop->Children[1] = new_break_if(A->CurLoop, cond, GL_FALSE);
}
- loop->Children[0] = new_seq(body, breakIf);
+
+ /* XXX we should do infinite loop detection, as above */
/* pop loop, restore prev */
A->CurLoop = prevLoop;
@@ -1431,11 +1420,12 @@ static slang_ir_node *
_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
{
/*
- * init (child[0])
+ * init code (child[0])
* LOOP:
* BREAK if !expr (child[1])
* body code (child[3])
- * incr code (child[2]) // XXX continue here
+ * tail code:
+ * incr code (child[2]) // XXX continue here
*/
slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr;
@@ -1450,8 +1440,9 @@ _slang_gen_for(slang_assemble_ctx * A, c
breakIf = new_break_if(A->CurLoop, cond, GL_FALSE);
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(breakIf, body);
+ loop->Children[1] = incr; /* tail code */
/* pop loop, restore prev */
A->CurLoop = prevLoop;
@@ -1460,6 +1451,25 @@ _slang_gen_for(slang_assemble_ctx * A, c
}
+static slang_ir_node *
+_slang_gen_continue(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ slang_ir_node *n, *loopNode;
+ assert(oper->type == SLANG_OPER_CONTINUE);
+ loopNode = A->CurLoop;
+ assert(loopNode);
+ assert(loopNode->Opcode == IR_LOOP);
+ n = new_node0(IR_CONT);
+ if (n) {
+ n->Parent = loopNode;
+ /* insert this node at head of linked list */
+ n->List = loopNode->List;
+ loopNode->List = n;
+ }
+ return n;
+}
+
+
/**
* Determine if the given operation is of a specific type.
*/
@@ -2364,7 +2374,7 @@ _slang_gen_operation(slang_assemble_ctx
if (!A->CurLoop) {
slang_info_log_error(A->log, "'continue' not in loop");
}
- return new_cont(A->CurLoop);
+ return _slang_gen_continue(A, oper);
case SLANG_OPER_DISCARD:
return new_node0(IR_KILL);
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 9e476b8..6ec20da 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -316,6 +316,7 @@ slang_print_ir(const slang_ir_node *n, i
printf("ELSE\n");
slang_print_ir(n->Children[2], indent+3);
}
+ spaces(indent);
printf("ENDIF\n");
break;
@@ -335,6 +336,11 @@ slang_print_ir(const slang_ir_node *n, i
case IR_LOOP:
printf("LOOP\n");
slang_print_ir(n->Children[0], indent+3);
+ if (n->Children[1]) {
+ spaces(indent);
+ printf("TAIL:\n");
+ slang_print_ir(n->Children[1], indent+3);
+ }
spaces(indent);
printf("ENDLOOP\n");
break;
@@ -685,6 +691,19 @@ instruction_annotation(gl_inst_opcode op
}
+/**
+ * Emit an instruction that's just a comment.
+ */
+static struct prog_instruction *
+emit_comment(slang_emit_info *emitInfo, const char *s)
+{
+ struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_NOP);
+ if (inst) {
+ inst->Comment = _mesa_strdup(s);
+ }
+ return inst;
+}
+
/**
* Generate code for a simple arithmetic instruction.
@@ -1005,9 +1024,16 @@ static struct prog_instruction *
emit_label(slang_emit_info *emitInfo, const slang_ir_node *n)
{
assert(n->Label);
+#if 0
+ /* XXX this fails in loop tail code - investigate someday */
assert(_slang_label_get_location(n->Label) < 0);
_slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
emitInfo->prog);
+#else
+ if (_slang_label_get_location(n->Label) < 0)
+ _slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
+ emitInfo->prog);
+#endif
return NULL;
}
@@ -1097,7 +1123,9 @@ emit_move(slang_emit_info *emitInfo, sla
assert(n->Children[1]->Store->Index >= 0);
+#if 0
assert(!n->Store);
+#endif
n->Store = n->Children[0]->Store;
#if PEEPHOLE_OPTIMIZATIONS
@@ -1316,9 +1344,11 @@ emit_loop(slang_emit_info *emitInfo, sla
{
struct gl_program *prog = emitInfo->prog;
struct prog_instruction *beginInst, *endInst;
- GLuint beginInstLoc, endInstLoc;
+ GLuint beginInstLoc, tailInstLoc, endInstLoc;
slang_ir_node *ir;
+ slang_print_ir(n, 10);
+
/* emit OPCODE_BGNLOOP */
beginInstLoc = prog->NumInstructions;
if (emitInfo->EmitHighLevelInstructions) {
@@ -1328,6 +1358,14 @@ emit_loop(slang_emit_info *emitInfo, sla
/* body */
emit(emitInfo, n->Children[0]);
+ /* tail */
+ tailInstLoc = prog->NumInstructions;
+ if (n->Children[1]) {
+ if (emitInfo->EmitComments)
+ emit_comment(emitInfo, "Loop tail code:");
+ emit(emitInfo, n->Children[1]);
+ }
+
endInstLoc = prog->NumInstructions;
if (emitInfo->EmitHighLevelInstructions) {
/* emit OPCODE_ENDLOOP */
@@ -1338,7 +1376,7 @@ emit_loop(slang_emit_info *emitInfo, sla
endInst = new_instruction(emitInfo, OPCODE_BRA);
endInst->DstReg.CondMask = COND_TR; /* always true */
}
- /* end instruction's BranchTarget points to top of loop */
+ /* ENDLOOP's BranchTarget points to the BGNLOOP inst */
endInst->BranchTarget = beginInstLoc;
if (emitInfo->EmitHighLevelInstructions) {
@@ -1351,7 +1389,7 @@ emit_loop(slang_emit_info *emitInfo, sla
* BREAK and CONT nodes, filling in their BranchTarget fields (which
* will point to the ENDLOOP+1 or BGNLOOP instructions, respectively).
*/
- for (ir = n->BranchNode; ir; ir = ir->BranchNode) {
+ for (ir = n->List; ir; ir = ir->List) {
struct prog_instruction *inst = prog->Instructions + ir->InstLocation;
assert(inst->BranchTarget < 0);
if (ir->Opcode == IR_BREAK ||
@@ -1372,8 +1410,8 @@ emit_loop(slang_emit_info *emitInfo, sla
inst->Opcode == OPCODE_CONT0 ||
inst->Opcode == OPCODE_CONT1 ||
inst->Opcode == OPCODE_BRA);
- /* to go instruction at top of loop */
- inst->BranchTarget = beginInstLoc;
+ /* go to instruction at tail of loop */
+ inst->BranchTarget = endInstLoc;
}
}
return NULL;
@@ -1389,13 +1427,28 @@ emit_cont_break(slang_emit_info *emitInf
{
gl_inst_opcode opcode;
struct prog_instruction *inst;
- n->InstLocation = emitInfo->prog->NumInstructions;
+
+ if (n->Opcode == IR_CONT) {
+ /* we need to execute the loop's tail code before doing CONT */
+ assert(n->Parent);
+ assert(n->Parent->Opcode == IR_LOOP);
+ if (n->Parent->Children[1]) {
+ /* emit tail code */
+ if (emitInfo->EmitComments) {
+ emit_comment(emitInfo, "continue - tail code:");
+ }
+ emit(emitInfo, n->Parent->Children[1]);
+ }
+ }
+
+ /* opcode selection */
if (emitInfo->EmitHighLevelInstructions) {
opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
}
else {
opcode = OPCODE_BRA;
}
+ n->InstLocation = emitInfo->prog->NumInstructions;
inst = new_instruction(emitInfo, opcode);
inst->DstReg.CondMask = COND_TR; /* always true */
return inst;
@@ -1456,7 +1509,7 @@ emit_cont_break_if(slang_emit_info *emit
inst->DstReg.CondMask = breakTrue ? COND_NE : COND_EQ;
}
else {
- /* BRK0, BRK1, CONT0, CONT1 */
+ /* BRK0, BRK1, CONT0, CONT1 uses SrcReg[0] as the condition */
storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
}
return inst;
@@ -1607,7 +1660,9 @@ emit(slang_emit_info *emitInfo, slang_ir
assert(n->Children[1]);
emit(emitInfo, n->Children[0]);
inst = emit(emitInfo, n->Children[1]);
+#if 0
assert(!n->Store);
+#endif
n->Store = n->Children[1]->Store;
return inst;
@@ -1623,10 +1678,11 @@ emit(slang_emit_info *emitInfo, slang_ir
assert(n->Store);
assert(n->Store->File != PROGRAM_UNDEFINED);
assert(n->Store->Size > 0);
- assert(n->Store->Index < 0);
+ /*assert(n->Store->Index < 0);*/
if (!n->Var || n->Var->isTemp) {
/* a nameless/temporary variable, will be freed after first use */
- if (!_slang_alloc_temp(emitInfo->vt, n->Store)) {
+ /*NEW*/
+ if (n->Store->Index < 0 && !_slang_alloc_temp(emitInfo->vt, n->Store)) {
slang_info_log_error(emitInfo->log,
"Ran out of registers, too many temporaries");
return NULL;
@@ -1654,8 +1710,7 @@ emit(slang_emit_info *emitInfo, slang_ir
_mesa_swizzle_string(n->Store->Swizzle, 0, GL_FALSE),
(n->Var ? (char *) n->Var->a_name : "anonymous"),
n->Store->Size);
- inst = new_instruction(emitInfo, OPCODE_NOP);
- inst->Comment = _mesa_strdup(s);
+ inst = emit_comment(emitInfo, s);
return inst;
}
return NULL;
@@ -1828,7 +1883,7 @@ _slang_emit_code(slang_ir_node *n, slang
emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
emitInfo.EmitCondCodes = 0; /* XXX temporary! */
- emitInfo.EmitComments = ctx->Shader.EmitComments;
+ emitInfo.EmitComments = 1 + ctx->Shader.EmitComments;
(void) emit(&emitInfo, n);
diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h
index cc9df69..37dd38e 100644
--- a/src/mesa/shader/slang/slang_ir.h
+++ b/src/mesa/shader/slang/slang_ir.h
@@ -53,6 +53,9 @@ typedef enum
IR_COND, /* conditional expression/predicate */
IR_IF, /* high-level IF/then/else */
+ /* Children[0] = conditional expression */
+ /* Children[1] = if-true part */
+ /* Children[2] = if-else part, or NULL */
IR_BEGIN_SUB, /* begin subroutine */
IR_END_SUB, /* end subroutine */
@@ -60,13 +63,18 @@ typedef enum
IR_CALL, /* call subroutine */
IR_LOOP, /* high-level loop-begin / loop-end */
+ /* Children[0] = loop body */
+ /* Children[1] = loop tail code, or NULL */
+
IR_CONT, /* continue loop */
+ /* n->Parent = ptr to parent IR_LOOP Node */
IR_BREAK, /* break loop */
IR_BREAK_IF_TRUE,
IR_BREAK_IF_FALSE,
IR_CONT_IF_TRUE,
IR_CONT_IF_FALSE,
+ /* Children[0] = the condition expression */
IR_MOVE,
@@ -161,7 +169,8 @@ typedef struct slang_ir_node_
GLuint Writemask; /**< If Opcode == IR_MOVE */
GLfloat Value[4]; /**< If Opcode == IR_FLOAT */
slang_variable *Var; /**< If Opcode == IR_VAR or IR_VAR_DECL */
- struct slang_ir_node_ *BranchNode; /**< Used for branching instructions */
+ struct slang_ir_node_ *List; /**< For various linked lists */
+ struct slang_ir_node_ *Parent; /**< Pointer to logical parent (ie. loop) */
slang_label *Label; /**< Used for branches */
} slang_ir_node;
diff-tree 81767eead9e1b1b5d5dfd274c0875fa1332a5983 (from 63556fa9949f543a8134b6b5ff3d216acb71dd9f)
Author: Brian <brian at yutani.localnet.net>
Date: Fri Mar 23 17:45:53 2007 -0600
consolidate some code
diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c
index 39d2a07..3f7ad47 100644
--- a/src/mesa/shader/prog_print.c
+++ b/src/mesa/shader/prog_print.c
@@ -601,14 +601,9 @@ _mesa_print_instruction_opt(const struct
_mesa_printf("ENDLOOP; # (goto %d)\n", inst->BranchTarget);
break;
case OPCODE_BRK:
- _mesa_printf("BRK (%s%s); #(goto %d)",
- condcode_string(inst->DstReg.CondMask),
- _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
- inst->BranchTarget);
- print_comment(inst);
- break;
case OPCODE_CONT:
- _mesa_printf("CONT (%s%s); #(goto %d)",
+ _mesa_printf("%s (%s%s); # (goto %d)",
+ _mesa_opcode_string(inst->Opcode),
condcode_string(inst->DstReg.CondMask),
_mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
inst->BranchTarget);
diff-tree 63556fa9949f543a8134b6b5ff3d216acb71dd9f (from bf020d8d7f719dfea7ea3c65bd2833df6439b59e)
Author: Brian <brian at yutani.localnet.net>
Date: Fri Mar 23 14:47:46 2007 -0600
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.
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 0c9bf20..828b0f2 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2127,8 +2127,10 @@ struct gl_shader_program
struct gl_shader_state
{
struct gl_shader_program *CurrentProgram; /**< The user-bound program */
- GLboolean EmitHighLevelInstructions; /**< Driver-selectable */
- GLboolean EmitComments; /**< Driver-selectable */
+ /** Driver-selectable options: */
+ GLboolean EmitHighLevelInstructions; /**< IF/ELSE/ENDIF vs. BRA, etc. */
+ GLboolean EmitCondCodes; /**< Use condition codes? */
+ GLboolean EmitComments; /**< Annotated instructions */
};
diff --git a/src/mesa/shader/prog_execute.c b/src/mesa/shader/prog_execute.c
index 092c07f..f881d47 100644
--- a/src/mesa/shader/prog_execute.c
+++ b/src/mesa/shader/prog_execute.c
@@ -720,6 +720,32 @@ _mesa_execute_program(GLcontext * ctx,
pc = inst->BranchTarget - 1;
}
break;
+ case OPCODE_BRK0: /* Break if zero */
+ /* fall-through */
+ case OPCODE_CONT0: /* Continue if zero */
+ {
+ GLfloat a[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ if (a[0] == 0.0) {
+ /* take branch */
+ /* Subtract 1 here since we'll do pc++ at end of for-loop */
+ pc = inst->BranchTarget - 1;
+ }
+ }
+ break;
+ case OPCODE_BRK1: /* Break if non-zero */
+ /* fall-through */
+ case OPCODE_CONT1: /* Continue if non-zero */
+ {
+ GLfloat a[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ if (a[0] != 0.0) {
+ /* take branch */
+ /* Subtract 1 here since we'll do pc++ at end of for-loop */
+ pc = inst->BranchTarget - 1;
+ }
+ }
+ break;
case OPCODE_CAL: /* Call subroutine (conditional) */
if (eval_condition(machine, inst)) {
/* call the subroutine */
@@ -914,13 +940,26 @@ _mesa_execute_program(GLcontext * ctx,
}
break;
case OPCODE_IF:
- if (eval_condition(machine, inst)) {
- /* do if-clause (just continue execution) */
- }
- else {
- /* go to the instruction after ELSE or ENDIF */
- assert(inst->BranchTarget >= 0);
- pc = inst->BranchTarget - 1;
+ {
+ GLboolean cond;
+ /* eval condition */
+ if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+ GLfloat a[4];
+ fetch_vector1(&inst->SrcReg[0], machine, a);
+ cond = (a[0] != 0.0);
+ }
+ else {
+ cond = eval_condition(machine, inst);
+ }
+ /* do if/else */
+ if (cond) {
+ /* do if-clause (just continue execution) */
+ }
+ else {
+ /* go to the instruction after ELSE or ENDIF */
+ assert(inst->BranchTarget >= 0);
+ pc = inst->BranchTarget - 1;
+ }
}
break;
case OPCODE_ELSE:
diff --git a/src/mesa/shader/prog_instruction.c b/src/mesa/shader/prog_instruction.c
index ed479a7..272caf6 100644
--- a/src/mesa/shader/prog_instruction.c
+++ b/src/mesa/shader/prog_instruction.c
@@ -138,9 +138,13 @@ static const struct instruction_info Ins
{ OPCODE_BGNSUB, "BGNSUB", 0 },
{ OPCODE_BRA, "BRA", 0 },
{ OPCODE_BRK, "BRK", 0 },
+ { OPCODE_BRK0, "BRK0", 1 },
+ { OPCODE_BRK1, "BRK1", 1 },
{ OPCODE_CAL, "CAL", 0 },
{ OPCODE_CMP, "CMP", 3 },
- { OPCODE_CONT, "CONT", 1 },
+ { OPCODE_CONT, "CONT", 0 },
+ { OPCODE_CONT0, "CONT0", 1 },
+ { OPCODE_CONT1, "CONT1", 1 },
{ OPCODE_COS, "COS", 1 },
{ OPCODE_DDX, "DDX", 1 },
{ OPCODE_DDY, "DDY", 1 },
diff --git a/src/mesa/shader/prog_instruction.h b/src/mesa/shader/prog_instruction.h
index c800757..dc2d2dc 100644
--- a/src/mesa/shader/prog_instruction.h
+++ b/src/mesa/shader/prog_instruction.h
@@ -153,9 +153,13 @@ typedef enum prog_opcode {
OPCODE_BGNSUB, /* opt */
OPCODE_BRA, /* 2 X */
OPCODE_BRK, /* 2 opt */
+ OPCODE_BRK0, /* opt */
+ OPCODE_BRK1, /* opt */
OPCODE_CAL, /* 2 2 */
OPCODE_CMP, /* X */
OPCODE_CONT, /* opt */
+ OPCODE_CONT0, /* opt */
+ OPCODE_CONT1, /* opt */
OPCODE_COS, /* X 2 X X */
OPCODE_DDX, /* X X */
OPCODE_DDY, /* X X */
diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c
index d290ce0..39d2a07 100644
--- a/src/mesa/shader/prog_print.c
+++ b/src/mesa/shader/prog_print.c
@@ -572,10 +572,20 @@ _mesa_print_instruction_opt(const struct
print_comment(inst);
break;
case OPCODE_IF:
- _mesa_printf("IF (%s%s); # (if false, goto %d)",
- condcode_string(inst->DstReg.CondMask),
- _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
- inst->BranchTarget);
+ if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+ /* Use ordinary register */
+ _mesa_printf("IF ");
+ print_src_reg(&inst->SrcReg[0], mode, prog);
+ _mesa_printf("; ");
+ }
+ else {
+ /* Use cond codes */
+ _mesa_printf("IF (%s%s);",
+ condcode_string(inst->DstReg.CondMask),
+ _mesa_swizzle_string(inst->DstReg.CondSwizzle,
+ 0, GL_FALSE));
+ }
+ _mesa_printf(" # (if false, goto %d)", inst->BranchTarget);
print_comment(inst);
return indent + 3;
case OPCODE_ELSE:
@@ -604,6 +614,18 @@ _mesa_print_instruction_opt(const struct
inst->BranchTarget);
print_comment(inst);
break;
+
+ case OPCODE_BRK0:
+ case OPCODE_BRK1:
+ case OPCODE_CONT0:
+ case OPCODE_CONT1:
+ _mesa_printf("%s ", _mesa_opcode_string(inst->Opcode));
+ print_src_reg(&inst->SrcReg[0], mode, prog);
+ _mesa_printf("; ");
+ _mesa_printf(" # (goto %d)", inst->BranchTarget);
+ print_comment(inst);
+ break;
+
case OPCODE_BGNSUB:
_mesa_printf("SUB");
print_comment(inst);
diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c
index aab522e..88aa8c5 100644
--- a/src/mesa/shader/shader_api.c
+++ b/src/mesa/shader/shader_api.c
@@ -206,6 +206,7 @@ _mesa_init_shader_state(GLcontext * ctx)
* are generated by the GLSL compiler.
*/
ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
+ ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
ctx->Shader.EmitComments = GL_FALSE;
}
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 16a054b..9e476b8 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, sla
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, sla
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
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
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, sla
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, sla
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, sla
/**
- * "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 *emit
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
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);
diff --git a/src/mesa/tnl/t_vb_arbprogram.c b/src/mesa/tnl/t_vb_arbprogram.c
index b322d48..425a866 100644
--- a/src/mesa/tnl/t_vb_arbprogram.c
+++ b/src/mesa/tnl/t_vb_arbprogram.c
@@ -741,9 +741,13 @@ static gpu_function opcode_func[MAX_OPCO
do_NOP,/*BGNSUB*/
do_NOP,/*BRA*/
do_NOP,/*BRK*/
+ do_NOP,/*BRK0*/
+ do_NOP,/*BRK1*/
do_NOP,/*CAL*/
do_NOP,/*CMP*/
do_NOP,/*CONT*/
+ do_NOP,/*CONT0*/
+ do_NOP,/*CONT1*/
do_NOP,/*COS*/
do_NOP,/*DDX*/
do_NOP,/*DDY*/
diff-tree bf020d8d7f719dfea7ea3c65bd2833df6439b59e (from 2bdac09d16904334424a53d4c7436408a5cc3ca5)
Author: Brian <brian at yutani.localnet.net>
Date: Fri Mar 23 14:44:34 2007 -0600
minor tweaks
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index f1be713..4e41aa8 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -1369,7 +1369,7 @@ _slang_gen_while(slang_assemble_ctx * A,
loop->Children[0] = new_seq(breakIf, body);
/* Do infinite loop detection */
- if (loop->BranchNode == 0 && isConst && constTrue) {
+ if (!loop->BranchNode && isConst && constTrue) {
/* infinite loop detected */
A->CurLoop = prevLoop; /* clean-up */
slang_info_log_error(A->log, "Infinite loop detected!");
@@ -1485,7 +1485,7 @@ static slang_ir_node *
_slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
{
/*
- * eval expr (child[0]), updating condcodes
+ * eval expr (child[0])
* IF expr THEN
* if-body code
* ELSE
More information about the mesa-commit
mailing list