code clean-up, re-org. Added IR_F_TO_I support.
This commit is contained in:
@@ -69,6 +69,7 @@ static slang_ir_info IrInfo[] = {
|
||||
{ IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
|
||||
/* unary ops */
|
||||
{ IR_I_TO_F, "IR_I_TO_F", OPCODE_NOP, 1, 1 },
|
||||
{ IR_F_TO_I, "IR_F_TO_I", OPCODE_INT, 4, 1 }, /* 4 floats to 4 ints */
|
||||
{ IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 },
|
||||
{ IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 },
|
||||
{ IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 },
|
||||
@@ -588,6 +589,104 @@ emit_tex(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
|
||||
}
|
||||
|
||||
|
||||
static struct prog_instruction *
|
||||
emit_move(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
|
||||
{
|
||||
struct prog_instruction *inst;
|
||||
|
||||
/* rhs */
|
||||
assert(n->Children[1]);
|
||||
inst = emit(vt, n->Children[1], prog);
|
||||
|
||||
/* lhs */
|
||||
emit(vt, n->Children[0], prog);
|
||||
|
||||
#if 1
|
||||
if (inst && _slang_is_temp(vt, 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.
|
||||
*/
|
||||
_slang_free_temp(vt, n->Children[1]->Store->Index,
|
||||
n->Children[1]->Store->Size);
|
||||
*n->Children[1]->Store = *n->Children[0]->Store;
|
||||
/* fixup the prev (RHS) instruction */
|
||||
storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
|
||||
return inst;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (n->Children[0]->Store->Size > 4) {
|
||||
/* move matrix/struct etc */
|
||||
slang_ir_storage dstStore = *n->Children[0]->Store;
|
||||
slang_ir_storage srcStore = *n->Children[1]->Store;
|
||||
GLint size = srcStore.Size;
|
||||
ASSERT(n->Children[0]->Writemask == WRITEMASK_XYZW);
|
||||
ASSERT(n->Children[1]->Swizzle == SWIZZLE_NOOP);
|
||||
dstStore.Size = 4;
|
||||
srcStore.Size = 4;
|
||||
while (size >= 4) {
|
||||
inst = new_instruction(prog, OPCODE_MOV);
|
||||
inst->Comment = _mesa_strdup("IR_MOVE block");
|
||||
storage_to_dst_reg(&inst->DstReg, &dstStore, n->Writemask);
|
||||
storage_to_src_reg(&inst->SrcReg[0], &srcStore,
|
||||
n->Children[1]->Swizzle);
|
||||
srcStore.Index++;
|
||||
dstStore.Index++;
|
||||
size -= 4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
inst = new_instruction(prog, OPCODE_MOV);
|
||||
storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
|
||||
storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store,
|
||||
n->Children[1]->Swizzle);
|
||||
}
|
||||
/* XXX is this test correct? */
|
||||
if (_slang_is_temp(vt, n->Children[1]->Store->Index)) {
|
||||
_slang_free_temp(vt, n->Children[1]->Store->Index,
|
||||
n->Children[1]->Store->Size);
|
||||
}
|
||||
/*inst->Comment = _mesa_strdup("IR_MOVE");*/
|
||||
assert(!n->Store);
|
||||
n->Store = n->Children[0]->Store; /*XXX new */
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct prog_instruction *
|
||||
emit_cond(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
|
||||
{
|
||||
/* Conditional expression (in if/while/for stmts).
|
||||
* Need to update condition code register.
|
||||
* Next instruction is typically an IR_CJUMP.
|
||||
*/
|
||||
/* last child expr instruction: */
|
||||
struct prog_instruction *inst = emit(vt, n->Children[0], prog);
|
||||
if (inst) {
|
||||
/* set inst's CondUpdate flag */
|
||||
inst->CondUpdate = GL_TRUE;
|
||||
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.
|
||||
*/
|
||||
alloc_temp_storage(vt, n, 1);
|
||||
inst = new_instruction(prog, 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,
|
||||
n->Children[0]->Swizzle);
|
||||
_slang_free_temp(vt, n->Store->Index, n->Store->Size);
|
||||
return inst; /* XXX or null? */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct prog_instruction *
|
||||
emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
|
||||
{
|
||||
@@ -597,6 +696,7 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
|
||||
|
||||
switch (n->Opcode) {
|
||||
case IR_SEQ:
|
||||
/* sequence of two sub-trees */
|
||||
assert(n->Children[0]);
|
||||
assert(n->Children[1]);
|
||||
emit(vt, n->Children[0], prog);
|
||||
@@ -662,66 +762,7 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
|
||||
}
|
||||
return NULL; /* no instruction */
|
||||
|
||||
case IR_MOVE:
|
||||
/* rhs */
|
||||
assert(n->Children[1]);
|
||||
inst = emit(vt, n->Children[1], prog);
|
||||
/* lhs */
|
||||
emit(vt, n->Children[0], prog);
|
||||
|
||||
#if 1
|
||||
if (inst && _slang_is_temp(vt, 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.
|
||||
*/
|
||||
_slang_free_temp(vt, n->Children[1]->Store->Index,
|
||||
n->Children[1]->Store->Size);
|
||||
*n->Children[1]->Store = *n->Children[0]->Store;
|
||||
/* fixup the prev (RHS) instruction */
|
||||
storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
|
||||
return inst;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (n->Children[0]->Store->Size > 4) {
|
||||
/* move matrix/struct etc */
|
||||
slang_ir_storage dstStore = *n->Children[0]->Store;
|
||||
slang_ir_storage srcStore = *n->Children[1]->Store;
|
||||
GLint size = srcStore.Size;
|
||||
ASSERT(n->Children[0]->Writemask == WRITEMASK_XYZW);
|
||||
ASSERT(n->Children[1]->Swizzle == SWIZZLE_NOOP);
|
||||
dstStore.Size = 4;
|
||||
srcStore.Size = 4;
|
||||
while (size >= 4) {
|
||||
inst = new_instruction(prog, OPCODE_MOV);
|
||||
inst->Comment = _mesa_strdup("IR_MOVE block");
|
||||
storage_to_dst_reg(&inst->DstReg, &dstStore, n->Writemask);
|
||||
storage_to_src_reg(&inst->SrcReg[0], &srcStore,
|
||||
n->Children[1]->Swizzle);
|
||||
srcStore.Index++;
|
||||
dstStore.Index++;
|
||||
size -= 4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
inst = new_instruction(prog, OPCODE_MOV);
|
||||
storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
|
||||
storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store,
|
||||
n->Children[1]->Swizzle);
|
||||
}
|
||||
/* XXX is this test correct? */
|
||||
if (_slang_is_temp(vt, n->Children[1]->Store->Index)) {
|
||||
_slang_free_temp(vt, n->Children[1]->Store->Index,
|
||||
n->Children[1]->Store->Size);
|
||||
}
|
||||
/*inst->Comment = _mesa_strdup("IR_MOVE");*/
|
||||
assert(!n->Store);
|
||||
n->Store = n->Children[0]->Store; /*XXX new */
|
||||
return inst;
|
||||
}
|
||||
break;
|
||||
/* Simple binary operators */
|
||||
case IR_ADD:
|
||||
case IR_SUB:
|
||||
case IR_MUL:
|
||||
@@ -738,10 +779,12 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
|
||||
case IR_EXP:
|
||||
case IR_EXP2:
|
||||
return emit_binop(vt, n, prog);
|
||||
/* Simple unary operators */
|
||||
case IR_RSQ:
|
||||
case IR_RCP:
|
||||
case IR_FLOOR:
|
||||
case IR_FRAC:
|
||||
case IR_F_TO_I:
|
||||
case IR_ABS:
|
||||
case IR_SIN:
|
||||
case IR_COS:
|
||||
@@ -754,44 +797,23 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
|
||||
return emit_tex(vt, n, prog);
|
||||
case IR_NEG:
|
||||
return emit_negation(vt, n, prog);
|
||||
case IR_LABEL:
|
||||
return emit_label(n->Target, prog);
|
||||
case IR_FLOAT:
|
||||
n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */
|
||||
break;
|
||||
|
||||
case IR_MOVE:
|
||||
return emit_move(vt, n, prog);
|
||||
|
||||
case IR_COND:
|
||||
{
|
||||
/* Conditional expression (in if/while/for stmts).
|
||||
* Need to update condition code register.
|
||||
* Next instruction is typically an IR_CJUMP.
|
||||
*/
|
||||
/* last child expr instruction: */
|
||||
struct prog_instruction *inst = emit(vt, n->Children[0], prog);
|
||||
if (inst) {
|
||||
/* set inst's CondUpdate flag */
|
||||
inst->CondUpdate = GL_TRUE;
|
||||
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.
|
||||
*/
|
||||
alloc_temp_storage(vt, n, 1);
|
||||
inst = new_instruction(prog, 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,
|
||||
n->Children[0]->Swizzle);
|
||||
_slang_free_temp(vt, n->Store->Index, n->Store->Size);
|
||||
return inst; /* XXX or null? */
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return emit_cond(vt, n, prog);
|
||||
|
||||
case IR_LABEL:
|
||||
return emit_label(n->Target, prog);
|
||||
case IR_JUMP:
|
||||
return emit_jump(n->Target, prog);
|
||||
case IR_CJUMP:
|
||||
return emit_cjump(n->Target, prog);
|
||||
|
||||
default:
|
||||
_mesa_problem(NULL, "Unexpected IR opcode in emit()\n");
|
||||
abort();
|
||||
|
||||
Reference in New Issue
Block a user