aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_opt.cpp
diff options
context:
space:
mode:
authorDaniel Gavin <danielgavin5@hotmail.com>2021-05-20 12:15:14 +0200
committerDaniel Gavin <danielgavin5@hotmail.com>2021-05-20 12:15:14 +0200
commit44ee0f2cdc773fc3ba3261de076b8a8a7fb64f03 (patch)
treec408237d1bd2e6bfcb0c5526d9c0d8cdb97bbf69 /src/llvm_backend_opt.cpp
parent50035f257eb33769211ca49a30c51f9a20440a0e (diff)
parent92abddddc5ca4be622e93856c7246159b594e9e9 (diff)
Merge branch 'master' into prototype-fmt
Diffstat (limited to 'src/llvm_backend_opt.cpp')
-rw-r--r--src/llvm_backend_opt.cpp131
1 files changed, 127 insertions, 4 deletions
diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp
index 3b268dffa..213005f8f 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);
@@ -226,3 +248,104 @@ 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;
+ isize original_instruction_count = 0;
+ // 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;
+ /**/) {
+ if (pass_count == 0) {
+ original_instruction_count += 1;
+ }
+
+ 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 LLVMFNeg:
+ 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:
+ case LLVMShuffleVector:
+ case LLVMExtractValue:
+ 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);
+}