Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 6 ++++++ libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d-shader/hlsl.y | 8 +++----- 3 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 19c0e2e4..988f64dc 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -382,6 +382,12 @@ struct hlsl_ir_expr *hlsl_new_cast(struct hlsl_ir_node *node, struct hlsl_type * return hlsl_ir_expr(cast); }
+struct hlsl_ir_expr *hlsl_new_copy(struct hlsl_ir_node *node) +{ + /* Use a cast to the same type as a makeshift identity expression. */ + return hlsl_new_cast(node, node->data_type, &node->loc); +} + struct hlsl_ir_var *hlsl_new_var(const char *name, struct hlsl_type *type, const struct vkd3d_shader_location loc, const char *semantic, unsigned int modifiers, const struct hlsl_reg_reservation *reg_reservation) { diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 5a2f6af1..92ac5270 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -525,6 +525,7 @@ struct hlsl_ir_node *hlsl_new_binary_expr(enum hlsl_ir_expr_op op, struct hlsl_i struct hlsl_ir_node *arg2) DECLSPEC_HIDDEN; struct hlsl_ir_expr *hlsl_new_cast(struct hlsl_ir_node *node, struct hlsl_type *type, struct vkd3d_shader_location *loc) DECLSPEC_HIDDEN; +struct hlsl_ir_expr *hlsl_new_copy(struct hlsl_ir_node *node) DECLSPEC_HIDDEN; struct hlsl_ir_function_decl *hlsl_new_func_decl(struct hlsl_ctx *ctx, struct hlsl_type *return_type, struct list *parameters, const char *semantic, struct vkd3d_shader_location loc) DECLSPEC_HIDDEN; struct hlsl_ir_if *hlsl_new_if(struct hlsl_ir_node *condition, struct vkd3d_shader_location loc) DECLSPEC_HIDDEN; diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 6fceafb6..afac0ab3 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1336,9 +1336,8 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in
/* Don't use the instruction itself as a source, as this makes structure * splitting easier. Instead copy it here. Since we retrieve sources from - * the last instruction in the list, we do need to copy. Use a cast - * instruction to the same type as a makeshift identity expression. */ - if (!(copy = hlsl_new_cast(rhs, rhs->data_type, &lhs->loc))) + * the last instruction in the list, we do need to copy. */ + if (!(copy = hlsl_new_copy(rhs))) return NULL; list_add_tail(instrs, ©->node.entry); return ©->node; @@ -1365,8 +1364,7 @@ static bool add_increment(struct hlsl_ctx *ctx, struct list *instrs, bool decrem { struct hlsl_ir_expr *copy;
- /* Use a cast to the same type as a makeshift identity expression. */ - if (!(copy = hlsl_new_cast(lhs, lhs->data_type, &lhs->loc))) + if (!(copy = hlsl_new_copy(lhs))) return false; list_add_tail(instrs, ©->node.entry);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 102 +++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 39984702..c8d8d17f 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -20,6 +20,106 @@
#include "hlsl.h"
+static bool transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), + struct list *instrs, void *context) +{ + struct hlsl_ir_node *instr, *next; + bool progress = 0; + + LIST_FOR_EACH_ENTRY_SAFE(instr, next, instrs, struct hlsl_ir_node, entry) + { + if (instr->type == HLSL_IR_IF) + { + struct hlsl_ir_if *iff = hlsl_ir_if(instr); + + progress |= transform_ir(ctx, func, &iff->then_instrs, context); + progress |= transform_ir(ctx, func, &iff->else_instrs, context); + } + else if (instr->type == HLSL_IR_LOOP) + progress |= transform_ir(ctx, func, &hlsl_ir_loop(instr)->body, context); + + progress |= func(ctx, instr, context); + } + + return progress; +} + +static void replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new) +{ + struct hlsl_src *src, *next; + + LIST_FOR_EACH_ENTRY_SAFE(src, next, &old->uses, struct hlsl_src, entry) + { + hlsl_src_remove(src); + hlsl_src_from_node(src, new); + } + list_add_before(&old->entry, &new->entry); + list_remove(&old->entry); + hlsl_free_instr(old); +} + +static bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +{ + struct hlsl_ir_constant *arg1, *arg2 = NULL, *res; + struct hlsl_ir_expr *expr; + unsigned int i; + + if (instr->type != HLSL_IR_EXPR) + return false; + expr = hlsl_ir_expr(instr); + + for (i = 0; i < ARRAY_SIZE(expr->operands); ++i) + { + if (expr->operands[i].node && expr->operands[i].node->type != HLSL_IR_CONSTANT) + return false; + } + arg1 = hlsl_ir_constant(expr->operands[0].node); + if (expr->operands[1].node) + arg2 = hlsl_ir_constant(expr->operands[1].node); + + if (!(res = vkd3d_calloc(1, sizeof(*res)))) + { + ctx->failed = true; + return false; + } + init_node(&res->node, HLSL_IR_CONSTANT, instr->data_type, instr->loc); + + switch (instr->data_type->base_type) + { + case HLSL_TYPE_UINT: + { + unsigned int i; + + switch (expr->op) + { + case HLSL_IR_BINOP_ADD: + for (i = 0; i < instr->data_type->dimx; ++i) + res->value.u[i] = arg1->value.u[i] + arg2->value.u[i]; + break; + + case HLSL_IR_BINOP_MUL: + for (i = 0; i < instr->data_type->dimx; ++i) + res->value.u[i] = arg1->value.u[i] * arg2->value.u[i]; + break; + + default: + FIXME("Fold uint op %#x.\n", expr->op); + vkd3d_free(res); + return false; + } + break; + } + + default: + FIXME("Fold type %#x op %#x.\n", instr->data_type->base_type, expr->op); + vkd3d_free(res); + return false; + } + + replace_node(&expr->node, &res->node); + return true; +} + /* Allocate a unique, ordered index to each instruction, which will be used for * computing liveness ranges. */ static unsigned int index_instructions(struct list *instrs, unsigned int index) @@ -163,6 +263,8 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun { list_move_head(entry_func->body, &ctx->static_initializers);
+ while (transform_ir(ctx, fold_constants, entry_func->body, NULL)); + /* Index 0 means unused; index 1 means function entry, so start at 2. */ index_instructions(entry_func->body, 2);
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
On Tue, Mar 16, 2021 at 10:33 PM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
libs/vkd3d-shader/hlsl_codegen.c | 102 +++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+)
I have a tiny nitpick:
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 39984702..c8d8d17f 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -20,6 +20,106 @@
#include "hlsl.h"
+static bool transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *),
struct list *instrs, void *context)
+{
The "func" callback parameters in the declaration should probably either be all named or all unnamed.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index c8d8d17f..22ad3ed0 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -120,6 +120,32 @@ static bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, voi return true; }
+static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +{ + switch (instr->type) + { + case HLSL_IR_CONSTANT: + case HLSL_IR_EXPR: + case HLSL_IR_LOAD: + case HLSL_IR_SWIZZLE: + if (list_empty(&instr->uses)) + { + list_remove(&instr->entry); + hlsl_free_instr(instr); + return true; + } + break; + + case HLSL_IR_ASSIGNMENT: + case HLSL_IR_IF: + case HLSL_IR_JUMP: + case HLSL_IR_LOOP: + break; + } + + return false; +} + /* Allocate a unique, ordered index to each instruction, which will be used for * computing liveness ranges. */ static unsigned int index_instructions(struct list *instrs, unsigned int index) @@ -264,6 +290,7 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun list_move_head(entry_func->body, &ctx->static_initializers);
while (transform_ir(ctx, fold_constants, entry_func->body, NULL)); + while (transform_ir(ctx, dce, entry_func->body, NULL));
/* Index 0 means unused; index 1 means function entry, so start at 2. */ index_instructions(entry_func->body, 2);
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 22ad3ed0..2df88f57 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -53,11 +53,26 @@ static void replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new) hlsl_src_remove(src); hlsl_src_from_node(src, new); } - list_add_before(&old->entry, &new->entry); list_remove(&old->entry); hlsl_free_instr(old); }
+static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +{ + if (instr->type == HLSL_IR_EXPR) + { + struct hlsl_ir_expr *expr = hlsl_ir_expr(instr); + + if (expr->op == HLSL_IR_UNOP_CAST && hlsl_type_compare(expr->node.data_type, expr->operands[0].node->data_type)) + { + replace_node(&expr->node, expr->operands[0].node); + return true; + } + } + + return false; +} + static bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) { struct hlsl_ir_constant *arg1, *arg2 = NULL, *res; @@ -116,6 +131,7 @@ static bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, voi return false; }
+ list_add_before(&expr->node.entry, &res->node.entry); replace_node(&expr->node, &res->node); return true; } @@ -289,6 +305,7 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun { list_move_head(entry_func->body, &ctx->static_initializers);
+ while (transform_ir(ctx, fold_redundant_casts, entry_func->body, NULL)); while (transform_ir(ctx, fold_constants, entry_func->body, NULL)); while (transform_ir(ctx, dce, entry_func->body, NULL));
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 2df88f57..283a67e6 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -57,13 +57,24 @@ static void replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new) hlsl_free_instr(old); }
+static bool is_vec1(const struct hlsl_type *type) +{ + return (type->type == HLSL_CLASS_SCALAR) || (type->type == HLSL_CLASS_VECTOR && type->dimx == 1); +} + static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) { if (instr->type == HLSL_IR_EXPR) { struct hlsl_ir_expr *expr = hlsl_ir_expr(instr); + const struct hlsl_type *src_type = expr->operands[0].node->data_type; + const struct hlsl_type *dst_type = expr->node.data_type; + + if (expr->op != HLSL_IR_UNOP_CAST) + return false;
- if (expr->op == HLSL_IR_UNOP_CAST && hlsl_type_compare(expr->node.data_type, expr->operands[0].node->data_type)) + if (hlsl_type_compare(src_type, dst_type) + || (src_type->base_type == dst_type->base_type && is_vec1(src_type) && is_vec1(dst_type))) { replace_node(&expr->node, expr->operands[0].node); return true;
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com