mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-30 03:10:06 +00:00
Add custom basic dead instruction elimination pass
This commit is contained in:
+15
-13
@@ -3318,9 +3318,11 @@ void lb_end_procedure_body(lbProcedure *p) {
|
|||||||
LLVMBuildBr(p->builder, p->entry_block->block);
|
LLVMBuildBr(p->builder, p->entry_block->block);
|
||||||
LLVMPositionBuilderAtEnd(p->builder, p->curr_block->block);
|
LLVMPositionBuilderAtEnd(p->builder, p->curr_block->block);
|
||||||
|
|
||||||
|
LLVMValueRef instr = nullptr;
|
||||||
|
|
||||||
// Make sure there is a "ret void" at the end of a procedure with no return type
|
// Make sure there is a "ret void" at the end of a procedure with no return type
|
||||||
if (p->type->Proc.result_count == 0) {
|
if (p->type->Proc.result_count == 0) {
|
||||||
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
|
instr = LLVMGetLastInstruction(p->curr_block->block);
|
||||||
if (!lb_is_instr_terminating(instr)) {
|
if (!lb_is_instr_terminating(instr)) {
|
||||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
||||||
LLVMBuildRetVoid(p->builder);
|
LLVMBuildRetVoid(p->builder);
|
||||||
@@ -3332,7 +3334,7 @@ void lb_end_procedure_body(lbProcedure *p) {
|
|||||||
|
|
||||||
// Make sure every block terminates, and if not, make it unreachable
|
// Make sure every block terminates, and if not, make it unreachable
|
||||||
for (block = first_block; block != nullptr; block = LLVMGetNextBasicBlock(block)) {
|
for (block = first_block; block != nullptr; block = LLVMGetNextBasicBlock(block)) {
|
||||||
LLVMValueRef instr = LLVMGetLastInstruction(block);
|
instr = LLVMGetLastInstruction(block);
|
||||||
if (instr == nullptr || !lb_is_instr_terminating(instr)) {
|
if (instr == nullptr || !lb_is_instr_terminating(instr)) {
|
||||||
LLVMPositionBuilderAtEnd(p->builder, block);
|
LLVMPositionBuilderAtEnd(p->builder, block);
|
||||||
LLVMBuildUnreachable(p->builder);
|
LLVMBuildUnreachable(p->builder);
|
||||||
@@ -14045,7 +14047,7 @@ lbProcedure *lb_create_startup_type_info(lbModule *m) {
|
|||||||
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
lb_run_function_pass_manager(default_function_pass_manager, p);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -14134,7 +14136,7 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start
|
|||||||
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
lb_run_function_pass_manager(default_function_pass_manager, p);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -14251,7 +14253,7 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
|
|||||||
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
lb_run_function_pass_manager(default_function_pass_manager, p);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14376,26 +14378,26 @@ WORKER_TASK_PROC(lb_llvm_function_pass_worker_proc) {
|
|||||||
lbProcedure *p = m->procedures_to_generate[i];
|
lbProcedure *p = m->procedures_to_generate[i];
|
||||||
if (p->body != nullptr) { // Build Procedure
|
if (p->body != nullptr) { // Build Procedure
|
||||||
if (p->flags & lbProcedureFlag_WithoutMemcpyPass) {
|
if (p->flags & lbProcedureFlag_WithoutMemcpyPass) {
|
||||||
LLVMRunFunctionPassManager(default_function_pass_manager_without_memcpy, p->value);
|
lb_run_function_pass_manager(default_function_pass_manager_without_memcpy, p);
|
||||||
} else {
|
} else {
|
||||||
if (p->entity && p->entity->kind == Entity_Procedure) {
|
if (p->entity && p->entity->kind == Entity_Procedure) {
|
||||||
switch (p->entity->Procedure.optimization_mode) {
|
switch (p->entity->Procedure.optimization_mode) {
|
||||||
case ProcedureOptimizationMode_None:
|
case ProcedureOptimizationMode_None:
|
||||||
case ProcedureOptimizationMode_Minimal:
|
case ProcedureOptimizationMode_Minimal:
|
||||||
LLVMRunFunctionPassManager(function_pass_manager_minimal, p->value);
|
lb_run_function_pass_manager(function_pass_manager_minimal, p);
|
||||||
break;
|
break;
|
||||||
case ProcedureOptimizationMode_Size:
|
case ProcedureOptimizationMode_Size:
|
||||||
LLVMRunFunctionPassManager(function_pass_manager_size, p->value);
|
lb_run_function_pass_manager(function_pass_manager_size, p);
|
||||||
break;
|
break;
|
||||||
case ProcedureOptimizationMode_Speed:
|
case ProcedureOptimizationMode_Speed:
|
||||||
LLVMRunFunctionPassManager(function_pass_manager_speed, p->value);
|
lb_run_function_pass_manager(function_pass_manager_speed, p);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
lb_run_function_pass_manager(default_function_pass_manager, p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
lb_run_function_pass_manager(default_function_pass_manager, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14403,11 +14405,11 @@ WORKER_TASK_PROC(lb_llvm_function_pass_worker_proc) {
|
|||||||
|
|
||||||
for_array(i, m->equal_procs.entries) {
|
for_array(i, m->equal_procs.entries) {
|
||||||
lbProcedure *p = m->equal_procs.entries[i].value;
|
lbProcedure *p = m->equal_procs.entries[i].value;
|
||||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
lb_run_function_pass_manager(default_function_pass_manager, p);
|
||||||
}
|
}
|
||||||
for_array(i, m->hasher_procs.entries) {
|
for_array(i, m->hasher_procs.entries) {
|
||||||
lbProcedure *p = m->hasher_procs.entries[i].value;
|
lbProcedure *p = m->hasher_procs.entries[i].value;
|
||||||
LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
|
lb_run_function_pass_manager(default_function_pass_manager, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -248,3 +248,96 @@ void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPa
|
|||||||
|
|
||||||
LLVMAddCFGSimplificationPass(mpm);
|
LLVMAddCFGSimplificationPass(mpm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lb_run_remove_dead_instruction_pass(lbProcedure *p) {
|
||||||
|
isize removal_count = 0;
|
||||||
|
isize pass_count = 0;
|
||||||
|
isize const max_pass_count = 10;
|
||||||
|
// Custom remove dead instruction pass
|
||||||
|
for (; pass_count < max_pass_count; pass_count++) {
|
||||||
|
bool was_dead_instructions = false;
|
||||||
|
|
||||||
|
// NOTE(bill): Iterate backwards
|
||||||
|
// reduces the number of passes as things later on will depend on things previously
|
||||||
|
for (LLVMBasicBlockRef block = LLVMGetLastBasicBlock(p->value);
|
||||||
|
block != nullptr;
|
||||||
|
block = LLVMGetPreviousBasicBlock(block)) {
|
||||||
|
// NOTE(bill): Iterate backwards
|
||||||
|
// reduces the number of passes as things later on will depend on things previously
|
||||||
|
for (LLVMValueRef instr = LLVMGetLastInstruction(block);
|
||||||
|
instr != nullptr;
|
||||||
|
/**/) {
|
||||||
|
LLVMValueRef curr_instr = instr;
|
||||||
|
instr = LLVMGetPreviousInstruction(instr);
|
||||||
|
|
||||||
|
LLVMUseRef first_use = LLVMGetFirstUse(curr_instr);
|
||||||
|
if (first_use != nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (LLVMTypeOf(curr_instr) == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(bill): Explicit instructions are set here because some instructions could have side effects
|
||||||
|
switch (LLVMGetInstructionOpcode(curr_instr)) {
|
||||||
|
case LLVMAdd:
|
||||||
|
case LLVMFAdd:
|
||||||
|
case LLVMSub:
|
||||||
|
case LLVMFSub:
|
||||||
|
case LLVMMul:
|
||||||
|
case LLVMFMul:
|
||||||
|
case LLVMUDiv:
|
||||||
|
case LLVMSDiv:
|
||||||
|
case LLVMFDiv:
|
||||||
|
case LLVMURem:
|
||||||
|
case LLVMSRem:
|
||||||
|
case LLVMFRem:
|
||||||
|
case LLVMShl:
|
||||||
|
case LLVMLShr:
|
||||||
|
case LLVMAShr:
|
||||||
|
case LLVMAnd:
|
||||||
|
case LLVMOr:
|
||||||
|
case LLVMXor:
|
||||||
|
case LLVMAlloca:
|
||||||
|
case LLVMLoad:
|
||||||
|
case LLVMGetElementPtr:
|
||||||
|
case LLVMTrunc:
|
||||||
|
case LLVMZExt:
|
||||||
|
case LLVMSExt:
|
||||||
|
case LLVMFPToUI:
|
||||||
|
case LLVMFPToSI:
|
||||||
|
case LLVMUIToFP:
|
||||||
|
case LLVMSIToFP:
|
||||||
|
case LLVMFPTrunc:
|
||||||
|
case LLVMFPExt:
|
||||||
|
case LLVMPtrToInt:
|
||||||
|
case LLVMIntToPtr:
|
||||||
|
case LLVMBitCast:
|
||||||
|
case LLVMAddrSpaceCast:
|
||||||
|
case LLVMICmp:
|
||||||
|
case LLVMFCmp:
|
||||||
|
case LLVMSelect:
|
||||||
|
case LLVMExtractElement:
|
||||||
|
removal_count += 1;
|
||||||
|
LLVMInstructionEraseFromParent(curr_instr);
|
||||||
|
was_dead_instructions = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!was_dead_instructions) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p) {
|
||||||
|
LLVMRunFunctionPassManager(fpm, p->value);
|
||||||
|
// NOTE(bill): LLVMAddDCEPass doesn't seem to be exported in the official DLL's for LLVM
|
||||||
|
// which means we cannot rely upon it
|
||||||
|
// This is also useful for read the .ll for debug purposes because a lot of instructions
|
||||||
|
// are not removed
|
||||||
|
lb_run_remove_dead_instruction_pass(p);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user