d3dcompiler: Track def-use chains for anonymous nodes.
This is useful for replacing one instruction with another of a different type, which is useful for some optimizations such as constant folding. Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Matteo Bruni <mbruni@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
eadcba7925
commit
8bd5fe3001
|
@ -662,6 +662,8 @@ struct hlsl_ir_node
|
|||
enum hlsl_ir_node_type type;
|
||||
struct hlsl_type *data_type;
|
||||
|
||||
struct list uses;
|
||||
|
||||
struct source_location loc;
|
||||
|
||||
/* Liveness ranges. "index" is the index of this instruction. Since this is
|
||||
|
@ -671,6 +673,12 @@ struct hlsl_ir_node
|
|||
unsigned int index, last_read;
|
||||
};
|
||||
|
||||
struct hlsl_src
|
||||
{
|
||||
struct hlsl_ir_node *node;
|
||||
struct list entry;
|
||||
};
|
||||
|
||||
#define HLSL_STORAGE_EXTERN 0x00000001
|
||||
#define HLSL_STORAGE_NOINTERPOLATION 0x00000002
|
||||
#define HLSL_MODIFIER_PRECISE 0x00000004
|
||||
|
@ -733,7 +741,7 @@ struct hlsl_ir_function_decl
|
|||
struct hlsl_ir_if
|
||||
{
|
||||
struct hlsl_ir_node node;
|
||||
struct hlsl_ir_node *condition;
|
||||
struct hlsl_src condition;
|
||||
struct list *then_instrs;
|
||||
struct list *else_instrs;
|
||||
};
|
||||
|
@ -817,7 +825,7 @@ struct hlsl_ir_expr
|
|||
{
|
||||
struct hlsl_ir_node node;
|
||||
enum hlsl_ir_expr_op op;
|
||||
struct hlsl_ir_node *operands[3];
|
||||
struct hlsl_src operands[3];
|
||||
};
|
||||
|
||||
enum hlsl_ir_jump_type
|
||||
|
@ -837,14 +845,14 @@ struct hlsl_ir_jump
|
|||
struct hlsl_ir_swizzle
|
||||
{
|
||||
struct hlsl_ir_node node;
|
||||
struct hlsl_ir_node *val;
|
||||
struct hlsl_src val;
|
||||
DWORD swizzle;
|
||||
};
|
||||
|
||||
struct hlsl_deref
|
||||
{
|
||||
struct hlsl_ir_var *var;
|
||||
struct hlsl_ir_node *offset;
|
||||
struct hlsl_src offset;
|
||||
};
|
||||
|
||||
struct hlsl_ir_load
|
||||
|
@ -857,7 +865,7 @@ struct hlsl_ir_assignment
|
|||
{
|
||||
struct hlsl_ir_node node;
|
||||
struct hlsl_deref lhs;
|
||||
struct hlsl_ir_node *rhs;
|
||||
struct hlsl_src rhs;
|
||||
unsigned char writemask;
|
||||
};
|
||||
|
||||
|
@ -1055,6 +1063,21 @@ static inline void init_node(struct hlsl_ir_node *node, enum hlsl_ir_node_type t
|
|||
node->type = type;
|
||||
node->data_type = data_type;
|
||||
node->loc = loc;
|
||||
list_init(&node->uses);
|
||||
}
|
||||
|
||||
static inline void hlsl_src_from_node(struct hlsl_src *src, struct hlsl_ir_node *node)
|
||||
{
|
||||
src->node = node;
|
||||
if (node)
|
||||
list_add_tail(&node->uses, &src->entry);
|
||||
}
|
||||
|
||||
static inline void hlsl_src_remove(struct hlsl_src *src)
|
||||
{
|
||||
if (src->node)
|
||||
list_remove(&src->entry);
|
||||
src->node = NULL;
|
||||
}
|
||||
|
||||
struct hlsl_ir_node *add_assignment(struct list *instrs, struct hlsl_ir_node *lhs,
|
||||
|
|
|
@ -308,7 +308,7 @@ static BOOL append_conditional_break(struct list *cond_list)
|
|||
return FALSE;
|
||||
}
|
||||
init_node(&iff->node, HLSL_IR_IF, NULL, condition->loc);
|
||||
iff->condition = not;
|
||||
hlsl_src_from_node(&iff->condition, not);
|
||||
list_add_tail(cond_list, &iff->node.entry);
|
||||
|
||||
if (!(iff->then_instrs = d3dcompiler_alloc(sizeof(*iff->then_instrs))))
|
||||
|
@ -421,7 +421,7 @@ static struct hlsl_ir_swizzle *new_swizzle(DWORD s, unsigned int components,
|
|||
return NULL;
|
||||
init_node(&swizzle->node, HLSL_IR_SWIZZLE,
|
||||
new_hlsl_type(NULL, HLSL_CLASS_VECTOR, val->data_type->base_type, components, 1), *loc);
|
||||
swizzle->val = val;
|
||||
hlsl_src_from_node(&swizzle->val, val);
|
||||
swizzle->swizzle = s;
|
||||
return swizzle;
|
||||
}
|
||||
|
@ -551,8 +551,8 @@ static struct hlsl_ir_assignment *new_assignment(struct hlsl_ir_var *var, struct
|
|||
|
||||
init_node(&assign->node, HLSL_IR_ASSIGNMENT, NULL, loc);
|
||||
assign->lhs.var = var;
|
||||
assign->lhs.offset = offset;
|
||||
assign->rhs = rhs;
|
||||
hlsl_src_from_node(&assign->lhs.offset, offset);
|
||||
hlsl_src_from_node(&assign->rhs, rhs);
|
||||
assign->writemask = writemask;
|
||||
return assign;
|
||||
}
|
||||
|
@ -616,7 +616,7 @@ struct hlsl_ir_node *new_unary_expr(enum hlsl_ir_expr_op op, struct hlsl_ir_node
|
|||
return NULL;
|
||||
init_node(&expr->node, HLSL_IR_EXPR, arg->data_type, loc);
|
||||
expr->op = op;
|
||||
expr->operands[0] = arg;
|
||||
hlsl_src_from_node(&expr->operands[0], arg);
|
||||
return &expr->node;
|
||||
}
|
||||
|
||||
|
@ -631,8 +631,8 @@ struct hlsl_ir_node *new_binary_expr(enum hlsl_ir_expr_op op,
|
|||
return NULL;
|
||||
init_node(&expr->node, HLSL_IR_EXPR, arg1->data_type, arg1->loc);
|
||||
expr->op = op;
|
||||
expr->operands[0] = arg1;
|
||||
expr->operands[1] = arg2;
|
||||
hlsl_src_from_node(&expr->operands[0], arg1);
|
||||
hlsl_src_from_node(&expr->operands[1], arg2);
|
||||
return &expr->node;
|
||||
}
|
||||
|
||||
|
@ -662,9 +662,9 @@ static struct hlsl_ir_load *add_load(struct list *instrs, struct hlsl_ir_node *v
|
|||
const struct hlsl_deref *src = &load_from_node(var_node)->src;
|
||||
|
||||
var = src->var;
|
||||
if (src->offset)
|
||||
if (src->offset.node)
|
||||
{
|
||||
if (!(add = new_binary_expr(HLSL_IR_BINOP_ADD, src->offset, offset)))
|
||||
if (!(add = new_binary_expr(HLSL_IR_BINOP_ADD, src->offset.node, offset)))
|
||||
return NULL;
|
||||
list_add_tail(instrs, &add->entry);
|
||||
offset = add;
|
||||
|
@ -691,7 +691,7 @@ static struct hlsl_ir_load *add_load(struct list *instrs, struct hlsl_ir_node *v
|
|||
return NULL;
|
||||
init_node(&load->node, HLSL_IR_LOAD, data_type, loc);
|
||||
load->src.var = var;
|
||||
load->src.offset = offset;
|
||||
hlsl_src_from_node(&load->src.offset, offset);
|
||||
list_add_tail(instrs, &load->node.entry);
|
||||
return load;
|
||||
}
|
||||
|
@ -2212,16 +2212,18 @@ jump_statement:
|
|||
selection_statement: KW_IF '(' expr ')' if_body
|
||||
{
|
||||
struct hlsl_ir_if *instr = d3dcompiler_alloc(sizeof(*instr));
|
||||
struct hlsl_ir_node *condition = node_from_list($3);
|
||||
|
||||
if (!instr)
|
||||
{
|
||||
ERR("Out of memory\n");
|
||||
YYABORT;
|
||||
}
|
||||
init_node(&instr->node, HLSL_IR_IF, NULL, get_location(&@1));
|
||||
instr->condition = node_from_list($3);
|
||||
hlsl_src_from_node(&instr->condition, condition);
|
||||
instr->then_instrs = $5.then_instrs;
|
||||
instr->else_instrs = $5.else_instrs;
|
||||
if (instr->condition->data_type->dimx > 1 || instr->condition->data_type->dimy > 1)
|
||||
if (condition->data_type->dimx > 1 || condition->data_type->dimy > 1)
|
||||
{
|
||||
hlsl_report_message(instr->node.loc, HLSL_LEVEL_ERROR,
|
||||
"if condition requires a scalar");
|
||||
|
@ -2883,19 +2885,18 @@ static void compute_liveness_recurse(struct list *instrs, unsigned int loop_firs
|
|||
var = assignment->lhs.var;
|
||||
if (!var->first_write)
|
||||
var->first_write = loop_first ? min(instr->index, loop_first) : instr->index;
|
||||
assignment->rhs->last_read = instr->index;
|
||||
if (assignment->lhs.offset)
|
||||
assignment->lhs.offset->last_read = instr->index;
|
||||
assignment->rhs.node->last_read = instr->index;
|
||||
if (assignment->lhs.offset.node)
|
||||
assignment->lhs.offset.node->last_read = instr->index;
|
||||
break;
|
||||
}
|
||||
case HLSL_IR_EXPR:
|
||||
{
|
||||
struct hlsl_ir_expr *expr = expr_from_node(instr);
|
||||
expr->operands[0]->last_read = instr->index;
|
||||
if (expr->operands[1])
|
||||
expr->operands[1]->last_read = instr->index;
|
||||
if (expr->operands[2])
|
||||
expr->operands[2]->last_read = instr->index;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(expr->operands) && expr->operands[i].node; ++i)
|
||||
expr->operands[i].node->last_read = instr->index;
|
||||
break;
|
||||
}
|
||||
case HLSL_IR_IF:
|
||||
|
@ -2904,7 +2905,7 @@ static void compute_liveness_recurse(struct list *instrs, unsigned int loop_firs
|
|||
compute_liveness_recurse(iff->then_instrs, loop_first, loop_last);
|
||||
if (iff->else_instrs)
|
||||
compute_liveness_recurse(iff->else_instrs, loop_first, loop_last);
|
||||
iff->condition->last_read = instr->index;
|
||||
iff->condition.node->last_read = instr->index;
|
||||
break;
|
||||
}
|
||||
case HLSL_IR_LOAD:
|
||||
|
@ -2912,8 +2913,8 @@ static void compute_liveness_recurse(struct list *instrs, unsigned int loop_firs
|
|||
struct hlsl_ir_load *load = load_from_node(instr);
|
||||
var = load->src.var;
|
||||
var->last_read = loop_last ? max(instr->index, loop_last) : instr->index;
|
||||
if (load->src.offset)
|
||||
load->src.offset->last_read = instr->index;
|
||||
if (load->src.offset.node)
|
||||
load->src.offset.node->last_read = instr->index;
|
||||
break;
|
||||
}
|
||||
case HLSL_IR_LOOP:
|
||||
|
@ -2926,7 +2927,7 @@ static void compute_liveness_recurse(struct list *instrs, unsigned int loop_firs
|
|||
case HLSL_IR_SWIZZLE:
|
||||
{
|
||||
struct hlsl_ir_swizzle *swizzle = swizzle_from_node(instr);
|
||||
swizzle->val->last_read = instr->index;
|
||||
swizzle->val.node->last_read = instr->index;
|
||||
break;
|
||||
}
|
||||
case HLSL_IR_CONSTANT:
|
||||
|
|
|
@ -1369,9 +1369,8 @@ struct hlsl_ir_expr *add_expr(struct list *instrs, enum hlsl_ir_expr_op op, stru
|
|||
return NULL;
|
||||
init_node(&expr->node, HLSL_IR_EXPR, type, *loc);
|
||||
expr->op = op;
|
||||
expr->operands[0] = operands[0];
|
||||
expr->operands[1] = operands[1];
|
||||
expr->operands[2] = operands[2];
|
||||
for (i = 0; i <= 2; ++i)
|
||||
hlsl_src_from_node(&expr->operands[i], operands[i]);
|
||||
list_add_tail(instrs, &expr->node.entry);
|
||||
|
||||
return expr;
|
||||
|
@ -1485,11 +1484,12 @@ struct hlsl_ir_node *add_assignment(struct list *instrs, struct hlsl_ir_node *lh
|
|||
if (lhs->data_type->type == HLSL_CLASS_MATRIX)
|
||||
FIXME("Assignments with writemasks and matrices on lhs are not supported yet.\n");
|
||||
|
||||
lhs_inner = swizzle->val;
|
||||
lhs_inner = swizzle->val.node;
|
||||
hlsl_src_remove(&swizzle->val);
|
||||
list_remove(&lhs->entry);
|
||||
|
||||
list_add_after(&rhs->entry, &lhs->entry);
|
||||
swizzle->val = rhs;
|
||||
hlsl_src_from_node(&swizzle->val, rhs);
|
||||
if (!invert_swizzle(&swizzle->swizzle, &writemask, &width))
|
||||
{
|
||||
hlsl_report_message(lhs->loc, HLSL_LEVEL_ERROR, "invalid writemask");
|
||||
|
@ -1513,7 +1513,8 @@ struct hlsl_ir_node *add_assignment(struct list *instrs, struct hlsl_ir_node *lh
|
|||
|
||||
init_node(&assign->node, HLSL_IR_ASSIGNMENT, lhs_type, lhs->loc);
|
||||
assign->writemask = writemask;
|
||||
assign->lhs = load_from_node(lhs)->src;
|
||||
assign->lhs.var = load_from_node(lhs)->src.var;
|
||||
hlsl_src_from_node(&assign->lhs.offset, load_from_node(lhs)->src.offset.node);
|
||||
if (assign_op != ASSIGN_OP_ASSIGN)
|
||||
{
|
||||
enum hlsl_ir_expr_op op = op_from_assignment(assign_op);
|
||||
|
@ -1524,7 +1525,7 @@ struct hlsl_ir_node *add_assignment(struct list *instrs, struct hlsl_ir_node *lh
|
|||
list_add_after(&rhs->entry, &expr->entry);
|
||||
rhs = expr;
|
||||
}
|
||||
assign->rhs = rhs;
|
||||
hlsl_src_from_node(&assign->rhs, rhs);
|
||||
list_add_tail(instrs, &assign->node.entry);
|
||||
|
||||
return &assign->node;
|
||||
|
@ -1787,12 +1788,12 @@ static void debug_dump_instr_list(const struct list *list)
|
|||
}
|
||||
}
|
||||
|
||||
static void debug_dump_src(const struct hlsl_ir_node *node)
|
||||
static void debug_dump_src(const struct hlsl_src *src)
|
||||
{
|
||||
if (node->index)
|
||||
wine_dbg_printf("@%u", node->index);
|
||||
if (src->node->index)
|
||||
wine_dbg_printf("@%u", src->node->index);
|
||||
else
|
||||
wine_dbg_printf("%p", node);
|
||||
wine_dbg_printf("%p", src->node);
|
||||
}
|
||||
|
||||
static void debug_dump_ir_var(const struct hlsl_ir_var *var)
|
||||
|
@ -1806,15 +1807,15 @@ static void debug_dump_ir_var(const struct hlsl_ir_var *var)
|
|||
|
||||
static void debug_dump_deref(const struct hlsl_deref *deref)
|
||||
{
|
||||
if (deref->offset)
|
||||
if (deref->offset.node)
|
||||
/* Print the variable's type for convenience. */
|
||||
wine_dbg_printf("(%s %s)", debug_hlsl_type(deref->var->data_type), deref->var->name);
|
||||
else
|
||||
wine_dbg_printf("%s", deref->var->name);
|
||||
if (deref->offset)
|
||||
if (deref->offset.node)
|
||||
{
|
||||
wine_dbg_printf("[");
|
||||
debug_dump_src(deref->offset);
|
||||
debug_dump_src(&deref->offset);
|
||||
wine_dbg_printf("]");
|
||||
}
|
||||
}
|
||||
|
@ -1942,9 +1943,9 @@ static void debug_dump_ir_expr(const struct hlsl_ir_expr *expr)
|
|||
unsigned int i;
|
||||
|
||||
wine_dbg_printf("%s (", debug_expr_op(expr));
|
||||
for (i = 0; i < 3 && expr->operands[i]; ++i)
|
||||
for (i = 0; i < 3 && expr->operands[i].node; ++i)
|
||||
{
|
||||
debug_dump_src(expr->operands[i]);
|
||||
debug_dump_src(&expr->operands[i]);
|
||||
wine_dbg_printf(" ");
|
||||
}
|
||||
wine_dbg_printf(")");
|
||||
|
@ -1976,7 +1977,7 @@ static void debug_dump_ir_assignment(const struct hlsl_ir_assignment *assign)
|
|||
if (assign->writemask != BWRITERSP_WRITEMASK_ALL)
|
||||
wine_dbg_printf("%s", debug_writemask(assign->writemask));
|
||||
wine_dbg_printf(" ");
|
||||
debug_dump_src(assign->rhs);
|
||||
debug_dump_src(&assign->rhs);
|
||||
wine_dbg_printf(")");
|
||||
}
|
||||
|
||||
|
@ -1984,9 +1985,9 @@ static void debug_dump_ir_swizzle(const struct hlsl_ir_swizzle *swizzle)
|
|||
{
|
||||
unsigned int i;
|
||||
|
||||
debug_dump_src(swizzle->val);
|
||||
debug_dump_src(&swizzle->val);
|
||||
wine_dbg_printf(".");
|
||||
if (swizzle->val->data_type->dimy > 1)
|
||||
if (swizzle->val.node->data_type->dimy > 1)
|
||||
{
|
||||
for (i = 0; i < swizzle->node.data_type->dimx; ++i)
|
||||
wine_dbg_printf("_m%u%u", (swizzle->swizzle >> i * 8) & 0xf, (swizzle->swizzle >> (i * 8 + 4)) & 0xf);
|
||||
|
@ -2022,7 +2023,7 @@ static void debug_dump_ir_jump(const struct hlsl_ir_jump *jump)
|
|||
static void debug_dump_ir_if(const struct hlsl_ir_if *if_node)
|
||||
{
|
||||
wine_dbg_printf("if (");
|
||||
debug_dump_src(if_node->condition);
|
||||
debug_dump_src(&if_node->condition);
|
||||
wine_dbg_printf(")\n{\n");
|
||||
debug_dump_instr_list(if_node->then_instrs);
|
||||
wine_dbg_printf("}\n");
|
||||
|
@ -2135,21 +2136,29 @@ static void free_ir_constant(struct hlsl_ir_constant *constant)
|
|||
|
||||
static void free_ir_load(struct hlsl_ir_load *load)
|
||||
{
|
||||
hlsl_src_remove(&load->src.offset);
|
||||
d3dcompiler_free(load);
|
||||
}
|
||||
|
||||
static void free_ir_swizzle(struct hlsl_ir_swizzle *swizzle)
|
||||
{
|
||||
hlsl_src_remove(&swizzle->val);
|
||||
d3dcompiler_free(swizzle);
|
||||
}
|
||||
|
||||
static void free_ir_expr(struct hlsl_ir_expr *expr)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(expr->operands); ++i)
|
||||
hlsl_src_remove(&expr->operands[i]);
|
||||
d3dcompiler_free(expr);
|
||||
}
|
||||
|
||||
static void free_ir_assignment(struct hlsl_ir_assignment *assignment)
|
||||
{
|
||||
hlsl_src_remove(&assignment->rhs);
|
||||
hlsl_src_remove(&assignment->lhs.offset);
|
||||
d3dcompiler_free(assignment);
|
||||
}
|
||||
|
||||
|
@ -2157,6 +2166,7 @@ static void free_ir_if(struct hlsl_ir_if *if_node)
|
|||
{
|
||||
free_instr_list(if_node->then_instrs);
|
||||
free_instr_list(if_node->else_instrs);
|
||||
hlsl_src_remove(&if_node->condition);
|
||||
d3dcompiler_free(if_node);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue