Skip to content

Commit

Permalink
Optimize output in dead branches.
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Mar 1, 2024
1 parent 3f022ab commit 099dfd7
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 239 deletions.
1 change: 0 additions & 1 deletion src/compiler/llvm_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,6 @@ void llvm_add_global_decl(GenContext *c, Decl *decl)
bool same_module = decl_module(decl) == c->code_module;
const char *name = same_module ? "temp_global" : decl_get_extname(decl);
decl->backend_ref = llvm_add_global(c, name, decl->type, decl->alignment);
llvm_set_alignment(decl->backend_ref, decl->alignment);
if (!same_module)
{
LLVMSetLinkage(decl->backend_ref, LLVMExternalLinkage);
Expand Down
13 changes: 10 additions & 3 deletions src/compiler/llvm_codegen_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -6165,8 +6165,12 @@ static inline void llvm_emit_return_block(GenContext *c, BEValue *be_value, Type

} while (0);

// Emit the last statement
llvm_emit_stmt(c, value);
bool has_current_block = llvm_get_current_block_if_in_use(c) != NULL;
if (has_current_block)
{
// Emit the last statement
llvm_emit_stmt(c, value);
}

// In the case of a void with no return, then this may be true.
if (llvm_basic_block_is_unused(expr_block))
Expand All @@ -6176,7 +6180,10 @@ static inline void llvm_emit_return_block(GenContext *c, BEValue *be_value, Type
goto DONE;
}

llvm_emit_br(c, expr_block);
if (has_current_block)
{
llvm_emit_br(c, expr_block);
}

// Emit the exit block.
llvm_emit_block(c, expr_block);
Expand Down
78 changes: 45 additions & 33 deletions src/compiler/llvm_codegen_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,12 @@ void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value)
llvm_value_set_decl(c, value, decl);
return;
}

// Push the builder
void *builder = c->builder;
c->builder = c->global_builder;

// Emit the global.
decl->backend_ref = llvm_add_global(c, "temp", var_type, decl->alignment);
if (IS_OPTIONAL(decl))
{
Expand All @@ -51,13 +55,18 @@ void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value)
decl->var.optional_ref = llvm_add_global(c, scratch_buffer_to_string(), type_anyfault, 0);
}
llvm_emit_global_variable_init(c, decl);

// Pop the builder
c->builder = builder;
llvm_value_set_decl(c, value, decl);
return;
}

// Create a local alloca
assert(!decl->backend_ref);
llvm_emit_local_var_alloca(c, decl);
Expr *init = decl->var.init_expr;

// Create optional storage
bool is_optional = IS_OPTIONAL(decl);
if (is_optional)
{
Expand All @@ -68,44 +77,41 @@ void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value)
// Only clear out the result if the assignment isn't an optional.
}

// Grab the init expression
Expr *init = decl->var.init_expr;
if (init)
{
llvm_value_set_decl_address(c, value, decl);
value->kind = BE_ADDRESS;
BEValue res = llvm_emit_assign_expr(c, value, decl->var.init_expr, decl->var.optional_ref);
if (!is_optional) *value = res;
return;
}
else if (decl->var.no_init)

// If the variable has a no-init, then set the value to undef.
if (decl->var.no_init)
{
llvm_value_set(value, LLVMGetUndef(alloc_type), decl->type);
if (decl->var.optional_ref)
if (is_optional)
{
llvm_store_to_ptr_raw(c, decl->var.optional_ref, llvm_get_undef(c, type_anyfault), type_anyfault);
}
return;
}
else


// Normal case, zero init.
llvm_value_set_decl_address(c, value, decl);
if (is_optional)
{
if (decl->var.optional_ref)
{
llvm_store_to_ptr_zero(c, decl->var.optional_ref, type_anyfault);
}
llvm_store_to_ptr_zero(c, decl->var.optional_ref, type_anyfault);

Type *type = type_lowering(decl->type);
// Normal case, zero init.
if (type_is_builtin(type->type_kind) || type->type_kind == TYPE_POINTER)
{
LLVMValueRef zero = llvm_get_zero(c, var_type);
llvm_value_set(value, zero, type);
llvm_store_decl(c, decl, value);
}
else
{
llvm_value_set_decl_address(c, value, decl);
value->kind = BE_ADDRESS;
llvm_store_zero(c, value);
llvm_value_set(value, llvm_get_zero(c, type), type);
}
// Prevent accidental optional folding in "llvm_store_zero"!
value->kind = BE_ADDRESS;
}

llvm_store_zero(c, value);
llvm_value_set(value, llvm_get_zero(c, var_type), var_type);
}

/**
Expand Down Expand Up @@ -152,7 +158,7 @@ static void llvm_emit_cond(GenContext *c, BEValue *be_value, Expr *expr, bool bo
void llvm_emit_jmp(GenContext *context, LLVMBasicBlockRef block)
{
llvm_emit_br(context, block);
LLVMBasicBlockRef post_jump_block = llvm_basic_block_new(context, "jmp");
LLVMBasicBlockRef post_jump_block = llvm_basic_block_new(context, "unreachable");
llvm_emit_block(context, post_jump_block);
}

Expand Down Expand Up @@ -202,14 +208,17 @@ static inline void llvm_emit_return(GenContext *c, Ast *ast)
llvm_emit_statement_chain(c, ast->return_stmt.cleanup);
}

// Are we in an expression block?
if (!has_return_value)
{
llvm_emit_return_implicit(c);
}
else
if (llvm_get_current_block_if_in_use(c))
{
llvm_emit_return_abi(c, &return_value, NULL);
// Are we in an expression block?
if (!has_return_value)
{
llvm_emit_return_implicit(c);
}
else
{
llvm_emit_return_abi(c, &return_value, NULL);
}
}
c->current_block = NULL;
if (error_return_block && LLVMGetFirstUse(LLVMBasicBlockAsValue(error_return_block)))
Expand Down Expand Up @@ -587,8 +596,11 @@ void llvm_emit_for_stmt(GenContext *c, Ast *ast)
// The inc block might also be the end of the body block.
llvm_emit_block(c, inc_block);
}
BEValue dummy;
llvm_emit_expr(c, &dummy, incr ? exprptr(incr) : NULL);
if (llvm_get_current_block_if_in_use(c))
{
BEValue dummy;
llvm_emit_expr(c, &dummy, incr ? exprptr(incr) : NULL);
}
}

// Loop back.
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/llvm_codegen_storeload.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ LLVMValueRef llvm_store_zero(GenContext *c, BEValue *ref)
{
llvm_value_addr(c, ref);
Type *type = ref->type;
if (!type_is_abi_aggregate(type))
if (!type_is_abi_aggregate(type) || type_is_builtin(type->type_kind))
{
return llvm_store_raw(c, ref, llvm_get_zero(c, type));
}
Expand Down
8 changes: 2 additions & 6 deletions src/compiler/sema_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,8 @@ static inline bool sema_expr_analyse_enum_constant(SemaContext *context, Expr *e
static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr);
static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr);

static inline bool
sema_expr_analyse_type_access(SemaContext *context, Expr *expr, Type *parent_type, bool was_group, Expr *identifier,
bool *missing_ref);
static inline bool
sema_expr_analyse_member_access(SemaContext *context, Expr *expr, Expr *parent, bool was_group, Expr *identifier,
bool *missing_ref);
static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *expr, Type *parent_type, bool was_group, Expr *identifier, bool *missing_ref);
static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *expr, Expr *parent, bool was_group, Expr *identifier, bool *missing_ref);
static inline bool sema_expr_fold_to_member(Expr *expr, Expr *parent, Decl *member);
static inline void sema_expr_flatten_const(SemaContext *context, Expr *expr);

Expand Down
6 changes: 3 additions & 3 deletions test/test_suite/defer/defer_and_expr_block.c3t
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ if.then: ; preds = %entry
call void (ptr, ...) @printf(ptr @.str.1)
br label %expr_block.exit
expr_block.exit: ; preds = %if.then
call void (ptr, ...) @printf(ptr @.str.5)
call void (ptr, ...) @printf(ptr @.str.6)
call void (ptr, ...) @printf(ptr @.str.7)
call void (ptr, ...) @printf(ptr @.str.2)
call void (ptr, ...) @printf(ptr @.str.3)
call void (ptr, ...) @printf(ptr @.str.4)
ret void
}

Loading

0 comments on commit 099dfd7

Please sign in to comment.