aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/llvm_backend.cpp28
-rw-r--r--src/llvm_backend_opt.cpp93
2 files changed, 108 insertions, 13 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 240e33c80..7bdc8b04a 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -3318,9 +3318,11 @@ void lb_end_procedure_body(lbProcedure *p) {
LLVMBuildBr(p->builder, p->entry_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
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)) {
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
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
for (block = first_block; block != nullptr; block = LLVMGetNextBasicBlock(block)) {
- LLVMValueRef instr = LLVMGetLastInstruction(block);
+ instr = LLVMGetLastInstruction(block);
if (instr == nullptr || !lb_is_instr_terminating(instr)) {
LLVMPositionBuilderAtEnd(p->builder, block);
LLVMBuildUnreachable(p->builder);
@@ -14045,7 +14047,7 @@ lbProcedure *lb_create_startup_type_info(lbModule *m) {
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
}
- LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
+ lb_run_function_pass_manager(default_function_pass_manager, p);
return p;
}
@@ -14134,7 +14136,7 @@ lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *start
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
}
- LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
+ lb_run_function_pass_manager(default_function_pass_manager, p);
return p;
}
@@ -14251,7 +14253,7 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
}
- LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
+ lb_run_function_pass_manager(default_function_pass_manager, p);
return p;
}
@@ -14376,26 +14378,26 @@ WORKER_TASK_PROC(lb_llvm_function_pass_worker_proc) {
lbProcedure *p = m->procedures_to_generate[i];
if (p->body != nullptr) { // Build Procedure
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 {
if (p->entity && p->entity->kind == Entity_Procedure) {
switch (p->entity->Procedure.optimization_mode) {
case ProcedureOptimizationMode_None:
case ProcedureOptimizationMode_Minimal:
- LLVMRunFunctionPassManager(function_pass_manager_minimal, p->value);
+ lb_run_function_pass_manager(function_pass_manager_minimal, p);
break;
case ProcedureOptimizationMode_Size:
- LLVMRunFunctionPassManager(function_pass_manager_size, p->value);
+ lb_run_function_pass_manager(function_pass_manager_size, p);
break;
case ProcedureOptimizationMode_Speed:
- LLVMRunFunctionPassManager(function_pass_manager_speed, p->value);
+ lb_run_function_pass_manager(function_pass_manager_speed, p);
break;
default:
- LLVMRunFunctionPassManager(default_function_pass_manager, p->value);
+ lb_run_function_pass_manager(default_function_pass_manager, p);
break;
}
} 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) {
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) {
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;
diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp
index 6b7ca507a..fa9d3b456 100644
--- a/src/llvm_backend_opt.cpp
+++ b/src/llvm_backend_opt.cpp
@@ -248,3 +248,96 @@ void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPa
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);
+}