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 --- dlls/d3dcompiler_43/d3dcompiler_private.h | 33 ++++++++++++--- dlls/d3dcompiler_43/hlsl.y | 49 +++++++++++----------- dlls/d3dcompiler_43/utils.c | 50 ++++++++++++++--------- 3 files changed, 83 insertions(+), 49 deletions(-)
diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h index 50457b2e64e..23eff210940 100644 --- a/dlls/d3dcompiler_43/d3dcompiler_private.h +++ b/dlls/d3dcompiler_43/d3dcompiler_private.h @@ -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, diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y index 21828337939..475fd414fd7 100644 --- a/dlls/d3dcompiler_43/hlsl.y +++ b/dlls/d3dcompiler_43/hlsl.y @@ -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: diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c index 30aa9de1dd4..4bc3b9b0a64 100644 --- a/dlls/d3dcompiler_43/utils.c +++ b/dlls/d3dcompiler_43/utils.c @@ -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); }