diff options
| author | Brian <brian@yutani.localnet.net> | 2007-03-26 18:46:07 -0600 | 
|---|---|---|
| committer | Brian <brian@yutani.localnet.net> | 2007-03-26 18:46:07 -0600 | 
| commit | 9878e8ff516486900228429f26b37cb01cd7313f (patch) | |
| tree | f5c516c3ca9f8659e8790444299ea9293f52e807 /src | |
| parent | 6583429f89df1b6838c5405bd32e5ef30bdf163f (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')
| -rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 29 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_compile_operation.h | 1 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 73 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_ir.h | 2 | 
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 0ca5054ead..93b6d9f854 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 b63db04e7e..d497b6f66f 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 e747a6ef32..21b73c2f97 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 a617a7e173..a9a530aaf8 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 */ | 
