llvm_backend_opt.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level);
  2. void lb_add_function_simplifcation_passes(LLVMPassManagerRef mpm, i32 optimization_level);
  3. void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPassManagerRef mpm, i32 optimization_level);
  4. void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level);
  5. LLVMBool lb_must_preserve_predicate_callback(LLVMValueRef value, void *user_data) {
  6. lbModule *m = cast(lbModule *)user_data;
  7. if (m == nullptr) {
  8. return false;
  9. }
  10. if (value == nullptr) {
  11. return false;
  12. }
  13. return LLVMIsAAllocaInst(value) != nullptr;
  14. }
  15. void lb_add_must_preserve_predicate_pass(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level) {
  16. if (false && optimization_level == 0 && m->debug_builder) {
  17. // LLVMAddInternalizePassWithMustPreservePredicate(fpm, m, lb_must_preserve_predicate_callback);
  18. }
  19. }
  20. void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm) {
  21. LLVMAddPromoteMemoryToRegisterPass(fpm);
  22. LLVMAddMergedLoadStoreMotionPass(fpm);
  23. LLVMAddConstantPropagationPass(fpm);
  24. LLVMAddEarlyCSEPass(fpm);
  25. LLVMAddConstantPropagationPass(fpm);
  26. LLVMAddMergedLoadStoreMotionPass(fpm);
  27. LLVMAddPromoteMemoryToRegisterPass(fpm);
  28. LLVMAddCFGSimplificationPass(fpm);
  29. }
  30. void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level) {
  31. // NOTE(bill): Treat -opt:3 as if it was -opt:2
  32. // TODO(bill): Determine which opt definitions should exist in the first place
  33. optimization_level = gb_clamp(optimization_level, 0, 2);
  34. lb_add_must_preserve_predicate_pass(m, fpm, optimization_level);
  35. if (ignore_memcpy_pass) {
  36. lb_basic_populate_function_pass_manager(fpm);
  37. return;
  38. } else if (optimization_level == 0) {
  39. LLVMAddMemCpyOptPass(fpm);
  40. lb_basic_populate_function_pass_manager(fpm);
  41. return;
  42. }
  43. #if 0
  44. LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
  45. LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
  46. LLVMPassManagerBuilderSetSizeLevel(pmb, optimization_level);
  47. LLVMPassManagerBuilderPopulateFunctionPassManager(pmb, fpm);
  48. #else
  49. LLVMAddMemCpyOptPass(fpm);
  50. LLVMAddPromoteMemoryToRegisterPass(fpm);
  51. LLVMAddMergedLoadStoreMotionPass(fpm);
  52. LLVMAddConstantPropagationPass(fpm);
  53. LLVMAddEarlyCSEPass(fpm);
  54. LLVMAddConstantPropagationPass(fpm);
  55. LLVMAddMergedLoadStoreMotionPass(fpm);
  56. LLVMAddPromoteMemoryToRegisterPass(fpm);
  57. LLVMAddCFGSimplificationPass(fpm);
  58. LLVMAddSCCPPass(fpm);
  59. LLVMAddPromoteMemoryToRegisterPass(fpm);
  60. LLVMAddUnifyFunctionExitNodesPass(fpm);
  61. LLVMAddCFGSimplificationPass(fpm);
  62. LLVMAddEarlyCSEPass(fpm);
  63. LLVMAddLowerExpectIntrinsicPass(fpm);
  64. #endif
  65. }
  66. void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level) {
  67. // NOTE(bill): Treat -opt:3 as if it was -opt:2
  68. // TODO(bill): Determine which opt definitions should exist in the first place
  69. optimization_level = gb_clamp(optimization_level, 0, 2);
  70. lb_add_must_preserve_predicate_pass(m, fpm, optimization_level);
  71. if (optimization_level == 0) {
  72. LLVMAddMemCpyOptPass(fpm);
  73. lb_basic_populate_function_pass_manager(fpm);
  74. return;
  75. }
  76. #if 1
  77. LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
  78. LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
  79. LLVMPassManagerBuilderSetSizeLevel(pmb, optimization_level);
  80. LLVMPassManagerBuilderPopulateFunctionPassManager(pmb, fpm);
  81. #else
  82. LLVMAddMemCpyOptPass(fpm);
  83. LLVMAddPromoteMemoryToRegisterPass(fpm);
  84. LLVMAddMergedLoadStoreMotionPass(fpm);
  85. LLVMAddConstantPropagationPass(fpm);
  86. LLVMAddEarlyCSEPass(fpm);
  87. LLVMAddConstantPropagationPass(fpm);
  88. LLVMAddMergedLoadStoreMotionPass(fpm);
  89. LLVMAddPromoteMemoryToRegisterPass(fpm);
  90. LLVMAddCFGSimplificationPass(fpm);
  91. LLVMAddSCCPPass(fpm);
  92. LLVMAddPromoteMemoryToRegisterPass(fpm);
  93. LLVMAddUnifyFunctionExitNodesPass(fpm);
  94. LLVMAddCFGSimplificationPass(fpm);
  95. LLVMAddEarlyCSEPass(fpm);
  96. LLVMAddLowerExpectIntrinsicPass(fpm);
  97. #endif
  98. }
  99. void lb_add_function_simplifcation_passes(LLVMPassManagerRef mpm, i32 optimization_level) {
  100. LLVMAddEarlyCSEMemSSAPass(mpm);
  101. LLVMAddGVNPass(mpm);
  102. LLVMAddCFGSimplificationPass(mpm);
  103. LLVMAddJumpThreadingPass(mpm);
  104. // if (optimization_level > 2) {
  105. // LLVMAddAggressiveInstCombinerPass(mpm);
  106. // }
  107. LLVMAddInstructionCombiningPass(mpm);
  108. LLVMAddSimplifyLibCallsPass(mpm);
  109. LLVMAddTailCallEliminationPass(mpm);
  110. LLVMAddCFGSimplificationPass(mpm);
  111. LLVMAddReassociatePass(mpm);
  112. LLVMAddLoopRotatePass(mpm);
  113. LLVMAddLICMPass(mpm);
  114. LLVMAddLoopUnswitchPass(mpm);
  115. LLVMAddCFGSimplificationPass(mpm);
  116. LLVMAddInstructionCombiningPass(mpm);
  117. LLVMAddIndVarSimplifyPass(mpm);
  118. LLVMAddLoopIdiomPass(mpm);
  119. LLVMAddLoopDeletionPass(mpm);
  120. LLVMAddLoopUnrollPass(mpm);
  121. LLVMAddMergedLoadStoreMotionPass(mpm);
  122. LLVMAddGVNPass(mpm);
  123. LLVMAddMemCpyOptPass(mpm);
  124. LLVMAddSCCPPass(mpm);
  125. LLVMAddBitTrackingDCEPass(mpm);
  126. LLVMAddInstructionCombiningPass(mpm);
  127. LLVMAddJumpThreadingPass(mpm);
  128. LLVMAddCorrelatedValuePropagationPass(mpm);
  129. LLVMAddDeadStoreEliminationPass(mpm);
  130. LLVMAddLICMPass(mpm);
  131. LLVMAddLoopRerollPass(mpm);
  132. LLVMAddAggressiveDCEPass(mpm);
  133. LLVMAddCFGSimplificationPass(mpm);
  134. LLVMAddInstructionCombiningPass(mpm);
  135. }
  136. void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPassManagerRef mpm, i32 optimization_level) {
  137. // NOTE(bill): Treat -opt:3 as if it was -opt:2
  138. // TODO(bill): Determine which opt definitions should exist in the first place
  139. optimization_level = gb_clamp(optimization_level, 0, 2);
  140. LLVMAddAlwaysInlinerPass(mpm);
  141. LLVMAddStripDeadPrototypesPass(mpm);
  142. LLVMAddAnalysisPasses(target_machine, mpm);
  143. LLVMAddPruneEHPass(mpm);
  144. if (optimization_level == 0) {
  145. return;
  146. }
  147. LLVMAddGlobalDCEPass(mpm);
  148. if (optimization_level >= 2) {
  149. // NOTE(bill, 2021-03-29: use this causes invalid code generation)
  150. // LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
  151. // LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
  152. // LLVMPassManagerBuilderPopulateModulePassManager(pmb, mpm);
  153. // LLVMPassManagerBuilderPopulateLTOPassManager(pmb, mpm, false, true);
  154. // return;
  155. }
  156. LLVMAddIPSCCPPass(mpm);
  157. LLVMAddCalledValuePropagationPass(mpm);
  158. LLVMAddGlobalOptimizerPass(mpm);
  159. LLVMAddDeadArgEliminationPass(mpm);
  160. // LLVMAddConstantMergePass(mpm); // ???
  161. LLVMAddInstructionCombiningPass(mpm);
  162. LLVMAddCFGSimplificationPass(mpm);
  163. LLVMAddPruneEHPass(mpm);
  164. if (optimization_level < 2) {
  165. return;
  166. }
  167. LLVMAddFunctionInliningPass(mpm);
  168. lb_add_function_simplifcation_passes(mpm, optimization_level);
  169. LLVMAddGlobalDCEPass(mpm);
  170. LLVMAddGlobalOptimizerPass(mpm);
  171. // LLVMAddLowerConstantIntrinsicsPass(mpm);
  172. LLVMAddLoopRotatePass(mpm);
  173. LLVMAddLoopVectorizePass(mpm);
  174. LLVMAddInstructionCombiningPass(mpm);
  175. if (optimization_level >= 2) {
  176. LLVMAddEarlyCSEPass(mpm);
  177. LLVMAddCorrelatedValuePropagationPass(mpm);
  178. LLVMAddLICMPass(mpm);
  179. LLVMAddLoopUnswitchPass(mpm);
  180. LLVMAddCFGSimplificationPass(mpm);
  181. LLVMAddInstructionCombiningPass(mpm);
  182. }
  183. LLVMAddCFGSimplificationPass(mpm);
  184. LLVMAddSLPVectorizePass(mpm);
  185. LLVMAddLICMPass(mpm);
  186. LLVMAddAlignmentFromAssumptionsPass(mpm);
  187. LLVMAddStripDeadPrototypesPass(mpm);
  188. if (optimization_level >= 2) {
  189. LLVMAddGlobalDCEPass(mpm);
  190. LLVMAddConstantMergePass(mpm);
  191. }
  192. LLVMAddCFGSimplificationPass(mpm);
  193. }
  194. void lb_run_remove_dead_instruction_pass(lbProcedure *p) {
  195. isize removal_count = 0;
  196. isize pass_count = 0;
  197. isize const max_pass_count = 10;
  198. // Custom remove dead instruction pass
  199. for (; pass_count < max_pass_count; pass_count++) {
  200. bool was_dead_instructions = false;
  201. // NOTE(bill): Iterate backwards
  202. // reduces the number of passes as things later on will depend on things previously
  203. for (LLVMBasicBlockRef block = LLVMGetLastBasicBlock(p->value);
  204. block != nullptr;
  205. block = LLVMGetPreviousBasicBlock(block)) {
  206. // NOTE(bill): Iterate backwards
  207. // reduces the number of passes as things later on will depend on things previously
  208. for (LLVMValueRef instr = LLVMGetLastInstruction(block);
  209. instr != nullptr;
  210. /**/) {
  211. LLVMValueRef curr_instr = instr;
  212. instr = LLVMGetPreviousInstruction(instr);
  213. LLVMUseRef first_use = LLVMGetFirstUse(curr_instr);
  214. if (first_use != nullptr) {
  215. continue;
  216. }
  217. if (LLVMTypeOf(curr_instr) == nullptr) {
  218. continue;
  219. }
  220. // NOTE(bill): Explicit instructions are set here because some instructions could have side effects
  221. switch (LLVMGetInstructionOpcode(curr_instr)) {
  222. case LLVMAdd:
  223. case LLVMFAdd:
  224. case LLVMSub:
  225. case LLVMFSub:
  226. case LLVMMul:
  227. case LLVMFMul:
  228. case LLVMUDiv:
  229. case LLVMSDiv:
  230. case LLVMFDiv:
  231. case LLVMURem:
  232. case LLVMSRem:
  233. case LLVMFRem:
  234. case LLVMShl:
  235. case LLVMLShr:
  236. case LLVMAShr:
  237. case LLVMAnd:
  238. case LLVMOr:
  239. case LLVMXor:
  240. case LLVMAlloca:
  241. case LLVMLoad:
  242. case LLVMGetElementPtr:
  243. case LLVMTrunc:
  244. case LLVMZExt:
  245. case LLVMSExt:
  246. case LLVMFPToUI:
  247. case LLVMFPToSI:
  248. case LLVMUIToFP:
  249. case LLVMSIToFP:
  250. case LLVMFPTrunc:
  251. case LLVMFPExt:
  252. case LLVMPtrToInt:
  253. case LLVMIntToPtr:
  254. case LLVMBitCast:
  255. case LLVMAddrSpaceCast:
  256. case LLVMICmp:
  257. case LLVMFCmp:
  258. case LLVMSelect:
  259. case LLVMExtractElement:
  260. removal_count += 1;
  261. LLVMInstructionEraseFromParent(curr_instr);
  262. was_dead_instructions = true;
  263. break;
  264. }
  265. }
  266. }
  267. if (!was_dead_instructions) {
  268. break;
  269. }
  270. }
  271. }
  272. void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p) {
  273. LLVMRunFunctionPassManager(fpm, p->value);
  274. // NOTE(bill): LLVMAddDCEPass doesn't seem to be exported in the official DLL's for LLVM
  275. // which means we cannot rely upon it
  276. // This is also useful for read the .ll for debug purposes because a lot of instructions
  277. // are not removed
  278. lb_run_remove_dead_instruction_pass(p);
  279. }