From ba71bbb0383aca2cb077dc0ab88c782baf7e9cf6 Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Mon, 21 Dec 2020 14:54:11 +0530 Subject: [PATCH] Add processing if and loops in nir_to_llvm translation --- src/libre-soc/vulkan/libresoc_llvm.c | 21 +++ src/libre-soc/vulkan/libresoc_llvm_build.c | 158 +++++++++++++++++++-- src/libre-soc/vulkan/libresoc_llvm_build.h | 12 +- 3 files changed, 177 insertions(+), 14 deletions(-) diff --git a/src/libre-soc/vulkan/libresoc_llvm.c b/src/libre-soc/vulkan/libresoc_llvm.c index bc17e979b16..234091292c0 100644 --- a/src/libre-soc/vulkan/libresoc_llvm.c +++ b/src/libre-soc/vulkan/libresoc_llvm.c @@ -2368,12 +2368,33 @@ static void visit_block(struct libresoc_nir_tran_ctx *ctx, nir_block *block) static void visit_if(struct libresoc_nir_tran_ctx *ctx, nir_if *if_stmt) { + LLVMValueRef value = get_src(ctx, if_stmt->condition); + nir_block *then_block = (nir_block *)exec_list_get_head(&if_stmt->then_list); + + build_uif(&ctx->lc, value, then_block->index); + + visit_cf_list(ctx, &if_stmt->then_list); + + if (!exec_list_is_empty(&if_stmt->else_list)) { + nir_block *else_block = (nir_block *)exec_list_get_head(&if_stmt->else_list); + + build_else(&ctx->lc, else_block->index); + visit_cf_list(ctx, &if_stmt->else_list); + } + + build_endif(&ctx->lc, then_block->index); } static void visit_loop(struct libresoc_nir_tran_ctx *ctx, nir_loop *loop) { + nir_block *first_loop_block = (nir_block *)exec_list_get_head(&loop->body); + + build_bgnloop(&ctx->lc, first_loop_block->index); + + visit_cf_list(ctx, &loop->body); + build_endloop(&ctx->lc, first_loop_block->index); } static void visit_cf_list(struct libresoc_nir_tran_ctx *ctx, struct exec_list *list) diff --git a/src/libre-soc/vulkan/libresoc_llvm_build.c b/src/libre-soc/vulkan/libresoc_llvm_build.c index a7896fd8bf1..213b048340b 100644 --- a/src/libre-soc/vulkan/libresoc_llvm_build.c +++ b/src/libre-soc/vulkan/libresoc_llvm_build.c @@ -5,8 +5,10 @@ #include #include #include +#include +#define LLVM_INITIAL_CF_DEPTH 4 /* Data for if/else/endif and bgnloop/endloop control flow structures. */ struct llvm_flow { @@ -109,18 +111,6 @@ static LLVMValueRef eliminate_negative_zero(struct libresoc_llvm_context *ctx, L return val; } -void build_break(struct libresoc_llvm_context *lc) -{ - struct llvm_flow *flow = get_innermost_loop(lc); - LLVMBuildBr(lc->builder, flow->next_block); -} - -void build_continue(struct libresoc_llvm_context *lc) -{ - struct llvm_flow *flow = get_innermost_loop(lc); - LLVMBuildBr(lc->builder, flow->loop_entry_block); -} - int get_llvm_num_components(LLVMValueRef value) { LLVMTypeRef type = LLVMTypeOf(value); @@ -925,3 +915,147 @@ void build_kill_if_false(struct libresoc_llvm_context *ctx, LLVMValueRef i1) { build_intrinsic(ctx, "llvm.amdgcn.kill", ctx->voidt, &i1, 1, 0); } + +static struct llvm_flow *push_flow(struct libresoc_llvm_context *ctx) +{ + struct llvm_flow *flow; + + if (ctx->flow->depth >= ctx->flow->depth_max) { + unsigned new_max = MAX2(ctx->flow->depth << 1,LLVM_INITIAL_CF_DEPTH); + + ctx->flow->stack = realloc(ctx->flow->stack, new_max * sizeof(*ctx->flow->stack)); + ctx->flow->depth_max = new_max; + } + + flow = &ctx->flow->stack[ctx->flow->depth]; + ctx->flow->depth++; + + flow->next_block = NULL; + flow->loop_entry_block = NULL; + return flow; +} + +static void set_basicblock_name(LLVMBasicBlockRef bb, const char *base, int label_id) +{ + char buf[32]; + snprintf(buf, sizeof(buf), "%s%d", base, label_id); + LLVMSetValueName(LLVMBasicBlockAsValue(bb), buf); +} + +/* Append a basic block at the level of the parent flow. + */ +static LLVMBasicBlockRef append_basic_block(struct libresoc_llvm_context *ctx, const char *name) +{ + assert(ctx->flow->depth >= 1); + + if (ctx->flow->depth >= 2) { + struct llvm_flow *flow = &ctx->flow->stack[ctx->flow->depth - 2]; + + return LLVMInsertBasicBlockInContext(ctx->context, flow->next_block, name); + } + + LLVMValueRef main_fn = LLVMGetBasicBlockParent(LLVMGetInsertBlock(ctx->builder)); + return LLVMAppendBasicBlockInContext(ctx->context, main_fn, name); +} + +static void emit_default_branch(LLVMBuilderRef builder, LLVMBasicBlockRef target) +{ + if (!LLVMGetBasicBlockTerminator(LLVMGetInsertBlock(builder))) + LLVMBuildBr(builder, target); +} + +static struct llvm_flow *get_current_flow(struct libresoc_llvm_context *ctx) +{ + if (ctx->flow->depth > 0) + return &ctx->flow->stack[ctx->flow->depth - 1]; + return NULL; +} + +void build_bgnloop(struct libresoc_llvm_context *ctx, int label_id) +{ + struct llvm_flow *flow = push_flow(ctx); + flow->loop_entry_block = append_basic_block(ctx, "LOOP"); + flow->next_block = append_basic_block(ctx, "ENDLOOP"); + set_basicblock_name(flow->loop_entry_block, "loop", label_id); + LLVMBuildBr(ctx->builder, flow->loop_entry_block); + LLVMPositionBuilderAtEnd(ctx->builder, flow->loop_entry_block); +} + +void build_break(struct libresoc_llvm_context *ctx) +{ + struct llvm_flow *flow = get_innermost_loop(ctx); + LLVMBuildBr(ctx->builder, flow->next_block); +} + +void build_continue(struct libresoc_llvm_context *ctx) +{ + struct llvm_flow *flow = get_innermost_loop(ctx); + LLVMBuildBr(ctx->builder, flow->loop_entry_block); +} + +void build_else(struct libresoc_llvm_context *ctx, int label_id) +{ + struct llvm_flow *current_branch = get_current_flow(ctx); + LLVMBasicBlockRef endif_block; + + assert(!current_branch->loop_entry_block); + + endif_block = append_basic_block(ctx, "ENDIF"); + emit_default_branch(ctx->builder, endif_block); + + LLVMPositionBuilderAtEnd(ctx->builder, current_branch->next_block); + set_basicblock_name(current_branch->next_block, "else", label_id); + + current_branch->next_block = endif_block; +} + +void build_endif(struct libresoc_llvm_context *ctx, int label_id) +{ + struct llvm_flow *current_branch = get_current_flow(ctx); + + assert(!current_branch->loop_entry_block); + + emit_default_branch(ctx->builder, current_branch->next_block); + LLVMPositionBuilderAtEnd(ctx->builder, current_branch->next_block); + set_basicblock_name(current_branch->next_block, "endif", label_id); + + ctx->flow->depth--; +} + +void build_endloop(struct libresoc_llvm_context *ctx, int label_id) +{ + struct llvm_flow *current_loop = get_current_flow(ctx); + + assert(current_loop->loop_entry_block); + + emit_default_branch(ctx->builder, current_loop->loop_entry_block); + + LLVMPositionBuilderAtEnd(ctx->builder, current_loop->next_block); + set_basicblock_name(current_loop->next_block, "endloop", label_id); + ctx->flow->depth--; +} + +void build_ifcc(struct libresoc_llvm_context *ctx, LLVMValueRef cond, int label_id) +{ + struct llvm_flow *flow = push_flow(ctx); + LLVMBasicBlockRef if_block; + + if_block = append_basic_block(ctx, "IF"); + flow->next_block = append_basic_block(ctx, "ELSE"); + set_basicblock_name(if_block, "if", label_id); + LLVMBuildCondBr(ctx->builder, cond, if_block, flow->next_block); + LLVMPositionBuilderAtEnd(ctx->builder, if_block); +} + +void build_if(struct libresoc_llvm_context *ctx, LLVMValueRef value, int label_id) +{ + LLVMValueRef cond = LLVMBuildFCmp(ctx->builder, LLVMRealUNE, value, ctx->f32_0, ""); + build_ifcc(ctx, cond, label_id); +} + +void build_uif(struct libresoc_llvm_context *ctx, LLVMValueRef value, int label_id) +{ + LLVMValueRef cond = + LLVMBuildICmp(ctx->builder, LLVMIntNE, to_integer(ctx, value), ctx->i32_0, ""); + build_ifcc(ctx, cond, label_id); +} diff --git a/src/libre-soc/vulkan/libresoc_llvm_build.h b/src/libre-soc/vulkan/libresoc_llvm_build.h index 32f27cbaff2..d43967ccf28 100644 --- a/src/libre-soc/vulkan/libresoc_llvm_build.h +++ b/src/libre-soc/vulkan/libresoc_llvm_build.h @@ -10,8 +10,6 @@ void disable_signed_zeros(struct libresoc_llvm_context *ctx); void add_function_attr(LLVMContextRef ctx, LLVMValueRef function, int attr_idx, enum func_attr attr); void add_func_attributes(LLVMContextRef ctx, LLVMValueRef function, unsigned attrib_mask); -void build_break(struct libresoc_llvm_context *lc); -void build_continue(struct libresoc_llvm_context *lc); LLVMValueRef build_alloca_undef(struct libresoc_llvm_context *lc, LLVMTypeRef type, const char *name); LLVMValueRef build_gep_ptr(struct libresoc_llvm_context *lc, LLVMValueRef base_ptr, @@ -90,4 +88,14 @@ LLVMValueRef build_cvt_pk_u16(struct libresoc_llvm_context *ctx, LLVMValueRef ar bool hi); LLVMValueRef build_wqm_vote(struct libresoc_llvm_context *ctx, LLVMValueRef i1); void build_kill_if_false(struct libresoc_llvm_context *ctx, LLVMValueRef i1); + +void build_bgnloop(struct libresoc_llvm_context *ctx, int label_id); +void build_break(struct libresoc_llvm_context *ctx); +void build_continue(struct libresoc_llvm_context *ctx); +void build_else(struct libresoc_llvm_context *ctx, int label_id); +void build_endif(struct libresoc_llvm_context *ctx, int label_id); +void build_endloop(struct libresoc_llvm_context *ctx, int label_id); +void build_ifcc(struct libresoc_llvm_context *ctx, LLVMValueRef cond, int label_id); +void build_if(struct libresoc_llvm_context *ctx, LLVMValueRef value, int label_id); +void build_uif(struct libresoc_llvm_context *ctx, LLVMValueRef value, int label_id); #endif -- 2.30.2