summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader
diff options
context:
space:
mode:
authorBrian <[email protected]>2007-03-26 18:46:07 -0600
committerBrian <[email protected]>2007-03-26 18:46:07 -0600
commit9878e8ff516486900228429f26b37cb01cd7313f (patch)
treef5c516c3ca9f8659e8790444299ea9293f52e807 /src/mesa/shader
parent6583429f89df1b6838c5405bd32e5ef30bdf163f (diff)
Checkpoint: implementing true CAL/RET instructions for subroutine calls.
Also, found/fixed a code generation regression: the emit_swizzle() function was always returning NULL. This caused emit_move() to miss its chance at peephole optimization.
Diffstat (limited to 'src/mesa/shader')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c29
-rw-r--r--src/mesa/shader/slang/slang_compile_operation.h1
-rw-r--r--src/mesa/shader/slang/slang_emit.c73
-rw-r--r--src/mesa/shader/slang/slang_ir.h2
4 files changed, 92 insertions, 13 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 0ca5054eadc..93b6d9f8544 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -468,6 +468,21 @@ new_float_literal(const float v[4], GLuint size)
return n;
}
+
+/**
+ * Inlined subroutine.
+ */
+static slang_ir_node *
+new_inlined_function_call(slang_ir_node *code, slang_label *name)
+{
+ slang_ir_node *n = new_node1(IR_FUNC, code);
+ assert(name);
+ if (n)
+ n->Label = name;
+ return n;
+}
+
+
/**
* Unconditional jump.
*/
@@ -1092,8 +1107,18 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
else {
/* non-assembly function */
inlined = slang_inline_function_call(A, fun, oper, dest);
+ if (inlined) {
+ assert(inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
+ inlined->type == SLANG_OPER_SEQUENCE);
+ inlined->type = SLANG_OPER_INLINED_CALL;
+ inlined->fun = fun;
+ inlined->label = _slang_label_new((char*) fun->header.a_name);
+ }
}
+ if (!inlined)
+ return NULL;
+
/* Replace the function call with the inlined block */
slang_operation_destruct(oper);
*oper = *inlined;
@@ -2581,6 +2606,7 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
return n;
}
+ case SLANG_OPER_INLINED_CALL:
case SLANG_OPER_SEQUENCE:
{
slang_ir_node *tree = NULL;
@@ -2589,6 +2615,9 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
slang_ir_node *n = _slang_gen_operation(A, &oper->children[i]);
tree = tree ? new_seq(tree, n) : n;
}
+ if (oper->type == SLANG_OPER_INLINED_CALL) {
+ tree = new_inlined_function_call(tree, oper->label);
+ }
return tree;
}
diff --git a/src/mesa/shader/slang/slang_compile_operation.h b/src/mesa/shader/slang/slang_compile_operation.h
index b63db04e7eb..d497b6f66f7 100644
--- a/src/mesa/shader/slang/slang_compile_operation.h
+++ b/src/mesa/shader/slang/slang_compile_operation.h
@@ -93,6 +93,7 @@ typedef enum slang_operation_type_
SLANG_OPER_NOT, /* "!" [expr] */
SLANG_OPER_SUBSCRIPT, /* [expr] "[" [expr] "]" */
SLANG_OPER_CALL, /* [func name] [param] [param] [...] */
+ SLANG_OPER_INLINED_CALL, /* inlined function call */
SLANG_OPER_FIELD, /* i.e.: ".next" or ".xzy" or ".xxx" etc */
SLANG_OPER_POSTINCREMENT, /* [var] "++" */
SLANG_OPER_POSTDECREMENT /* [var] "--" */
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index e747a6ef327..21b73c2f971 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -62,6 +62,7 @@ typedef struct
/* code-gen options */
GLboolean EmitHighLevelInstructions;
GLboolean EmitCondCodes;
+ GLboolean EmitBeginEndSub;
GLboolean EmitComments;
} slang_emit_info;
@@ -203,6 +204,13 @@ new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode)
{
struct gl_program *prog = emitInfo->prog;
struct prog_instruction *inst;
+
+#if 0
+ /* print prev inst */
+ if (prog->NumInstructions > 0) {
+ _mesa_print_instruction(prog->Instructions + prog->NumInstructions - 1);
+ }
+#endif
prog->Instructions = _mesa_realloc_instructions(prog->Instructions,
prog->NumInstructions,
prog->NumInstructions + 1);
@@ -710,6 +718,28 @@ emit_label(slang_emit_info *emitInfo, const slang_ir_node *n)
}
+/**
+ * Emit code for an inlined function call.
+ */
+static struct prog_instruction *
+emit_func(slang_emit_info *emitInfo, slang_ir_node *n)
+{
+ struct prog_instruction *inst;
+ assert(n->Label);
+ if (emitInfo->EmitBeginEndSub) {
+ inst = new_instruction(emitInfo, OPCODE_BGNSUB);
+ inst->Comment = _mesa_strdup(n->Label->Name);
+ }
+ inst = emit(emitInfo, n->Children[0]);
+ if (emitInfo->EmitBeginEndSub) {
+ inst = new_instruction(emitInfo, OPCODE_ENDSUB);
+ inst->Comment = _mesa_strdup(n->Label->Name);
+ }
+ n->Store = n->Children[0]->Store;
+ return inst;
+}
+
+
static struct prog_instruction *
emit_return(slang_emit_info *emitInfo, slang_ir_node *n)
{
@@ -803,14 +833,20 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)
n->Store = n->Children[0]->Store;
#if PEEPHOLE_OPTIMIZATIONS
- if (inst && _slang_is_temp(emitInfo->vt, n->Children[1]->Store)) {
+ if (inst &&
+ _slang_is_temp(emitInfo->vt, n->Children[1]->Store) &&
+ (inst->DstReg.File == n->Children[1]->Store->File) &&
+ (inst->DstReg.Index == n->Children[1]->Store->Index)) {
/* Peephole optimization:
- * Just modify the RHS to put its result into the dest of this
- * MOVE operation. Then, this MOVE is a no-op.
+ * The Right-Hand-Side has its results in a temporary place.
+ * Modify the RHS (and the prev instruction) to store its results
+ * in the destination specified by n->Children[0].
+ * Then, this MOVE is a no-op.
*/
- _slang_free_temp(emitInfo->vt, n->Children[1]->Store);
+ if (n->Children[1]->Opcode != IR_SWIZZLE)
+ _slang_free_temp(emitInfo->vt, n->Children[1]->Store);
*n->Children[1]->Store = *n->Children[0]->Store;
- /* fixup the prev (RHS) instruction */
+ /* fixup the previous instruction (which stored the RHS result) */
assert(n->Children[0]->Store->Index >= 0);
storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
return inst;
@@ -870,11 +906,17 @@ emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
* Need to update condition code register.
* Next instruction is typically an IR_IF.
*/
- if (inst) {
- /* set inst's CondUpdate flag */
+ if (inst &&
+ n->Children[0]->Store &&
+ inst->DstReg.File == n->Children[0]->Store->File &&
+ inst->DstReg.Index == n->Children[0]->Store->Index) {
+ /* The previous instruction wrote to the register who's value
+ * we're testing. Just update that instruction so that the
+ * condition codes are updated.
+ */
inst->CondUpdate = GL_TRUE;
n->Store = n->Children[0]->Store;
- return inst; /* XXX or null? */
+ return inst;
}
else {
/* This'll happen for things like "if (i) ..." where no code
@@ -1227,8 +1269,9 @@ static struct prog_instruction *
emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
{
GLuint swizzle;
+ struct prog_instruction *inst;
- (void) emit(emitInfo, n->Children[0]);
+ inst = emit(emitInfo, n->Children[0]);
#ifdef DEBUG
{
@@ -1246,10 +1289,10 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
n->Store->Index = n->Children[0]->Store->Index;
n->Store->Size = swizzle_size(n->Store->Swizzle);
#if 0
- printf("Emit Swizzle reg %d chSize %d size %d swz %s\n",
+ printf("Emit Swizzle %s reg %d chSize %d mySize %d\n",
+ _mesa_swizzle_string(n->Store->Swizzle, 0, 0),
n->Store->Index, n->Children[0]->Store->Size,
- n->Store->Size,
- _mesa_swizzle_string(n->Store->Swizzle, 0, 0));
+ n->Store->Size);
#endif
/* apply this swizzle to child's swizzle to get composed swizzle */
@@ -1257,7 +1300,7 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
n->Store->Swizzle = swizzle_swizzle(n->Children[0]->Store->Swizzle,
swizzle);
- return NULL;
+ return inst;
}
@@ -1505,6 +1548,9 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
case IR_KILL:
return emit_kill(emitInfo);
+ case IR_FUNC:
+ return emit_func(emitInfo, n);
+
case IR_IF:
return emit_if(emitInfo, n);
@@ -1553,6 +1599,7 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,
emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes;
+ emitInfo.EmitBeginEndSub = 0; /* XXX temporary */
emitInfo.EmitComments = 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 a617a7e1737..a9a530aaf8f 100644
--- a/src/mesa/shader/slang/slang_ir.h
+++ b/src/mesa/shader/slang/slang_ir.h
@@ -62,6 +62,8 @@ typedef enum
IR_RETURN, /* return from subroutine */
IR_CALL, /* call subroutine */
+ IR_FUNC, /* inlined function code */
+
IR_LOOP, /* high-level loop-begin / loop-end */
/* Children[0] = loop body */
/* Children[1] = loop tail code, or NULL */