From 8ff80dec5824a710eac384ed83608f5a88a57cb7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 11 May 2021 12:00:55 +0100 Subject: Minor change (in preparation for something else) to opt passes --- src/llvm_backend_opt.cpp | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'src/llvm_backend_opt.cpp') diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index 3b268dffa..fa1c87bf5 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -1,7 +1,25 @@ -void lb_populate_function_pass_manager(LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level); +void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level); void lb_add_function_simplifcation_passes(LLVMPassManagerRef mpm, i32 optimization_level); void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPassManagerRef mpm, i32 optimization_level); -void lb_populate_function_pass_manager_specific(LLVMPassManagerRef fpm, i32 optimization_level); +void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level); + +LLVMBool lb_must_preserve_predicate_callback(LLVMValueRef value, void *user_data) { + lbModule *m = cast(lbModule *)user_data; + if (m == nullptr) { + return false; + } + if (value == nullptr) { + return false; + } + return LLVMIsAAllocaInst(value) != nullptr; +} + +void lb_add_must_preserve_predicate_pass(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level) { + if (false && optimization_level == 0 && m->debug_builder) { + LLVMAddInternalizePassWithMustPreservePredicate(fpm, m, lb_must_preserve_predicate_callback); + } +} + void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm) { LLVMAddPromoteMemoryToRegisterPass(fpm); @@ -15,11 +33,13 @@ void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm) { LLVMAddCFGSimplificationPass(fpm); } -void lb_populate_function_pass_manager(LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level) { +void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level) { // NOTE(bill): Treat -opt:3 as if it was -opt:2 // TODO(bill): Determine which opt definitions should exist in the first place optimization_level = gb_clamp(optimization_level, 0, 2); + lb_add_must_preserve_predicate_pass(m, fpm, optimization_level); + if (ignore_memcpy_pass) { lb_basic_populate_function_pass_manager(fpm); return; @@ -57,11 +77,13 @@ void lb_populate_function_pass_manager(LLVMPassManagerRef fpm, bool ignore_memcp #endif } -void lb_populate_function_pass_manager_specific(LLVMPassManagerRef fpm, i32 optimization_level) { +void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level) { // NOTE(bill): Treat -opt:3 as if it was -opt:2 // TODO(bill): Determine which opt definitions should exist in the first place optimization_level = gb_clamp(optimization_level, 0, 2); + lb_add_must_preserve_predicate_pass(m, fpm, optimization_level); + if (optimization_level == 0) { LLVMAddMemCpyOptPass(fpm); lb_basic_populate_function_pass_manager(fpm); @@ -194,7 +216,7 @@ void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPa LLVMAddGlobalDCEPass(mpm); LLVMAddGlobalOptimizerPass(mpm); - // LLVMAddLowerConstantIntrinsicsPass(mpm); + LLVMAddLowerConstantIntrinsicsPass(mpm); LLVMAddLoopRotatePass(mpm); -- cgit v1.2.3 From 8bb6651dda3e239be9ae85eeadf2d189bd478f73 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 11 May 2021 12:08:09 +0100 Subject: Remove test call for LLVM --- src/llvm_backend_opt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/llvm_backend_opt.cpp') diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index fa1c87bf5..b40998c5f 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -16,7 +16,7 @@ LLVMBool lb_must_preserve_predicate_callback(LLVMValueRef value, void *user_data void lb_add_must_preserve_predicate_pass(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level) { if (false && optimization_level == 0 && m->debug_builder) { - LLVMAddInternalizePassWithMustPreservePredicate(fpm, m, lb_must_preserve_predicate_callback); + // LLVMAddInternalizePassWithMustPreservePredicate(fpm, m, lb_must_preserve_predicate_callback); } } -- cgit v1.2.3 From eac61fb5361a595363684df4737c3d918e9e7b88 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 11 May 2021 12:17:48 +0100 Subject: Remove `LLVMAddLowerConstantIntrinsicsPass` --- src/llvm_backend_opt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/llvm_backend_opt.cpp') diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index b40998c5f..6b7ca507a 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -216,7 +216,7 @@ void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPa LLVMAddGlobalDCEPass(mpm); LLVMAddGlobalOptimizerPass(mpm); - LLVMAddLowerConstantIntrinsicsPass(mpm); + // LLVMAddLowerConstantIntrinsicsPass(mpm); LLVMAddLoopRotatePass(mpm); -- cgit v1.2.3 From 1cf6b6679dd7dfd4e00cb55891970ce68f59c67d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 15 May 2021 21:10:06 +0100 Subject: Add custom basic dead instruction elimination pass --- src/llvm_backend.cpp | 28 ++++++++------- src/llvm_backend_opt.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 13 deletions(-) (limited to 'src/llvm_backend_opt.cpp') 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); +} -- cgit v1.2.3 From fffb83282b4e725152476ceb54a19d770e93a83e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 15 May 2021 21:24:17 +0100 Subject: Add missing instructions to pass --- src/llvm_backend_opt.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/llvm_backend_opt.cpp') diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index fa9d3b456..c4eecdb5d 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -318,6 +318,8 @@ void lb_run_remove_dead_instruction_pass(lbProcedure *p) { case LLVMFCmp: case LLVMSelect: case LLVMExtractElement: + case LLVMShuffleVector: + case LLVMExtractValue: removal_count += 1; LLVMInstructionEraseFromParent(curr_instr); was_dead_instructions = true; -- cgit v1.2.3 From b1cfeb6c95066e0f50d43bcd44f846e1f28f61ce Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 15 May 2021 22:14:20 +0100 Subject: Add missing instruction to pass --- src/llvm_backend_opt.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/llvm_backend_opt.cpp') diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index c4eecdb5d..213005f8f 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -253,6 +253,7 @@ void lb_run_remove_dead_instruction_pass(lbProcedure *p) { isize removal_count = 0; isize pass_count = 0; isize const max_pass_count = 10; + isize original_instruction_count = 0; // Custom remove dead instruction pass for (; pass_count < max_pass_count; pass_count++) { bool was_dead_instructions = false; @@ -267,6 +268,10 @@ void lb_run_remove_dead_instruction_pass(lbProcedure *p) { for (LLVMValueRef instr = LLVMGetLastInstruction(block); instr != nullptr; /**/) { + if (pass_count == 0) { + original_instruction_count += 1; + } + LLVMValueRef curr_instr = instr; instr = LLVMGetPreviousInstruction(instr); @@ -280,6 +285,7 @@ void lb_run_remove_dead_instruction_pass(lbProcedure *p) { // NOTE(bill): Explicit instructions are set here because some instructions could have side effects switch (LLVMGetInstructionOpcode(curr_instr)) { + case LLVMFNeg: case LLVMAdd: case LLVMFAdd: case LLVMSub: -- cgit v1.2.3