llvm_backend_opt.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. /**************************************************************************
  2. IMPORTANT NOTE(bill, 2021-11-06): Regarding Optimization Passes
  3. A lot of the passes taken here have been modified with what was
  4. partially done in LLVM 11.
  5. Passes that CANNOT be used by Odin due to C-like optimizations which
  6. are not compatible with Odin:
  7. LLVMAddCorrelatedValuePropagationPass
  8. LLVMAddAggressiveInstCombinerPass
  9. LLVMAddInstructionCombiningPass
  10. LLVMAddIndVarSimplifyPass
  11. LLVMAddLoopUnrollPass
  12. LLVMAddEarlyCSEMemSSAPass
  13. LLVMAddGVNPass
  14. LLVMAddDeadStoreEliminationPass - Causes too many false positive
  15. Odin does not allow poison-value based optimizations.
  16. For example, *-flowing integers in C is "undefined behaviour" and thus
  17. many optimizers, including LLVM, take advantage of this for a certain
  18. class of optimizations. Odin on the other hand defines *-flowing
  19. behaviour to obey the rules of 2's complement, meaning wrapping is a
  20. expected. This means any outputted IR containing the following flags
  21. may cause incorrect behaviour:
  22. nsw (no signed wrap)
  23. nuw (no unsigned wrap)
  24. poison (poison value)
  25. **************************************************************************/
  26. gb_internal void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level);
  27. gb_internal void lb_add_function_simplifcation_passes(LLVMPassManagerRef mpm, i32 optimization_level);
  28. gb_internal void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPassManagerRef mpm, i32 optimization_level);
  29. gb_internal void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level);
  30. // gb_internal LLVMBool lb_must_preserve_predicate_callback(LLVMValueRef value, void *user_data) {
  31. // lbModule *m = cast(lbModule *)user_data;
  32. // if (m == nullptr) {
  33. // return false;
  34. // }
  35. // if (value == nullptr) {
  36. // return false;
  37. // }
  38. // return LLVMIsAAllocaInst(value) != nullptr;
  39. // }
  40. #if LLVM_VERSION_MAJOR < 12
  41. #define LLVM_ADD_CONSTANT_VALUE_PASS(fpm) LLVMAddConstantPropagationPass(fpm)
  42. #else
  43. #define LLVM_ADD_CONSTANT_VALUE_PASS(fpm)
  44. #endif
  45. gb_internal bool lb_opt_ignore(i32 optimization_level) {
  46. optimization_level = gb_clamp(optimization_level, -1, 2);
  47. return optimization_level == -1;
  48. }
  49. gb_internal void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm, i32 optimization_level) {
  50. if (lb_opt_ignore(optimization_level)) {
  51. return;
  52. }
  53. if (false && optimization_level <= 0 && build_context.ODIN_DEBUG) {
  54. LLVMAddMergedLoadStoreMotionPass(fpm);
  55. } else {
  56. LLVMAddPromoteMemoryToRegisterPass(fpm);
  57. LLVMAddMergedLoadStoreMotionPass(fpm);
  58. LLVM_ADD_CONSTANT_VALUE_PASS(fpm);
  59. if (!build_context.ODIN_DEBUG) {
  60. LLVMAddEarlyCSEPass(fpm);
  61. }
  62. }
  63. }
  64. gb_internal void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level) {
  65. if (lb_opt_ignore(optimization_level)) {
  66. return;
  67. }
  68. if (ignore_memcpy_pass) {
  69. lb_basic_populate_function_pass_manager(fpm, optimization_level);
  70. return;
  71. } else if (optimization_level <= 0) {
  72. LLVMAddMemCpyOptPass(fpm);
  73. lb_basic_populate_function_pass_manager(fpm, optimization_level);
  74. return;
  75. }
  76. #if 0
  77. LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
  78. LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
  79. LLVMPassManagerBuilderSetSizeLevel(pmb, optimization_level);
  80. LLVMPassManagerBuilderPopulateFunctionPassManager(pmb, fpm);
  81. #else
  82. LLVMAddMemCpyOptPass(fpm);
  83. lb_basic_populate_function_pass_manager(fpm, optimization_level);
  84. LLVMAddSCCPPass(fpm);
  85. LLVMAddPromoteMemoryToRegisterPass(fpm);
  86. LLVMAddUnifyFunctionExitNodesPass(fpm);
  87. LLVMAddCFGSimplificationPass(fpm);
  88. LLVMAddEarlyCSEPass(fpm);
  89. LLVMAddLowerExpectIntrinsicPass(fpm);
  90. #endif
  91. }
  92. gb_internal void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level) {
  93. if (lb_opt_ignore(optimization_level)) {
  94. return;
  95. }
  96. if (optimization_level <= 0) {
  97. LLVMAddMemCpyOptPass(fpm);
  98. lb_basic_populate_function_pass_manager(fpm, optimization_level);
  99. return;
  100. }
  101. #if 1
  102. LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
  103. LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
  104. LLVMPassManagerBuilderSetSizeLevel(pmb, optimization_level);
  105. LLVMPassManagerBuilderPopulateFunctionPassManager(pmb, fpm);
  106. #else
  107. LLVMAddMemCpyOptPass(fpm);
  108. LLVMAddPromoteMemoryToRegisterPass(fpm);
  109. LLVMAddMergedLoadStoreMotionPass(fpm);
  110. LLVM_ADD_CONSTANT_VALUE_PASS(fpm);
  111. LLVMAddEarlyCSEPass(fpm);
  112. LLVM_ADD_CONSTANT_VALUE_PASS(fpm);
  113. LLVMAddMergedLoadStoreMotionPass(fpm);
  114. LLVMAddPromoteMemoryToRegisterPass(fpm);
  115. LLVMAddCFGSimplificationPass(fpm);
  116. LLVMAddSCCPPass(fpm);
  117. LLVMAddPromoteMemoryToRegisterPass(fpm);
  118. LLVMAddUnifyFunctionExitNodesPass(fpm);
  119. LLVMAddCFGSimplificationPass(fpm);
  120. LLVMAddEarlyCSEPass(fpm);
  121. LLVMAddLowerExpectIntrinsicPass(fpm);
  122. #endif
  123. }
  124. gb_internal void lb_add_function_simplifcation_passes(LLVMPassManagerRef mpm, i32 optimization_level) {
  125. LLVMAddCFGSimplificationPass(mpm);
  126. LLVMAddJumpThreadingPass(mpm);
  127. LLVMAddSimplifyLibCallsPass(mpm);
  128. LLVMAddTailCallEliminationPass(mpm);
  129. LLVMAddCFGSimplificationPass(mpm);
  130. LLVMAddReassociatePass(mpm);
  131. LLVMAddLoopRotatePass(mpm);
  132. LLVMAddLICMPass(mpm);
  133. LLVMAddLoopUnswitchPass(mpm);
  134. LLVMAddCFGSimplificationPass(mpm);
  135. LLVMAddLoopIdiomPass(mpm);
  136. LLVMAddLoopDeletionPass(mpm);
  137. LLVMAddMergedLoadStoreMotionPass(mpm);
  138. LLVMAddMemCpyOptPass(mpm);
  139. LLVMAddSCCPPass(mpm);
  140. LLVMAddBitTrackingDCEPass(mpm);
  141. LLVMAddJumpThreadingPass(mpm);
  142. LLVM_ADD_CONSTANT_VALUE_PASS(mpm);
  143. LLVMAddLICMPass(mpm);
  144. LLVMAddLoopRerollPass(mpm);
  145. LLVMAddAggressiveDCEPass(mpm);
  146. LLVMAddCFGSimplificationPass(mpm);
  147. }
  148. gb_internal void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPassManagerRef mpm, i32 optimization_level) {
  149. // NOTE(bill): Treat -opt:3 as if it was -opt:2
  150. // TODO(bill): Determine which opt definitions should exist in the first place
  151. if (optimization_level <= 0 && build_context.ODIN_DEBUG) {
  152. return;
  153. }
  154. LLVMAddAlwaysInlinerPass(mpm);
  155. LLVMAddStripDeadPrototypesPass(mpm);
  156. LLVMAddAnalysisPasses(target_machine, mpm);
  157. LLVMAddPruneEHPass(mpm);
  158. if (optimization_level <= 0) {
  159. return;
  160. }
  161. LLVMAddGlobalDCEPass(mpm);
  162. if (optimization_level >= 2) {
  163. // NOTE(bill, 2021-03-29: use this causes invalid code generation)
  164. // LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
  165. // LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
  166. // LLVMPassManagerBuilderPopulateModulePassManager(pmb, mpm);
  167. // LLVMPassManagerBuilderPopulateLTOPassManager(pmb, mpm, false, true);
  168. // return;
  169. }
  170. LLVMAddIPSCCPPass(mpm);
  171. LLVMAddCalledValuePropagationPass(mpm);
  172. LLVMAddGlobalOptimizerPass(mpm);
  173. LLVMAddDeadArgEliminationPass(mpm);
  174. LLVMAddCFGSimplificationPass(mpm);
  175. LLVMAddPruneEHPass(mpm);
  176. if (optimization_level < 2) {
  177. return;
  178. }
  179. LLVMAddFunctionInliningPass(mpm);
  180. lb_add_function_simplifcation_passes(mpm, optimization_level);
  181. LLVMAddGlobalDCEPass(mpm);
  182. LLVMAddGlobalOptimizerPass(mpm);
  183. LLVMAddLoopRotatePass(mpm);
  184. LLVMAddLoopVectorizePass(mpm);
  185. if (optimization_level >= 2) {
  186. LLVMAddEarlyCSEPass(mpm);
  187. LLVM_ADD_CONSTANT_VALUE_PASS(mpm);
  188. LLVMAddLICMPass(mpm);
  189. LLVMAddLoopUnswitchPass(mpm);
  190. LLVMAddCFGSimplificationPass(mpm);
  191. }
  192. LLVMAddCFGSimplificationPass(mpm);
  193. LLVMAddSLPVectorizePass(mpm);
  194. LLVMAddLICMPass(mpm);
  195. LLVMAddAlignmentFromAssumptionsPass(mpm);
  196. LLVMAddStripDeadPrototypesPass(mpm);
  197. if (optimization_level >= 2) {
  198. LLVMAddGlobalDCEPass(mpm);
  199. LLVMAddConstantMergePass(mpm);
  200. }
  201. LLVMAddCFGSimplificationPass(mpm);
  202. }
  203. /**************************************************************************
  204. IMPORTANT NOTE(bill, 2021-11-06): Custom Passes
  205. The procedures below are custom written passes to aid in the
  206. optimization of Odin programs
  207. **************************************************************************/
  208. gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) {
  209. unsigned debug_declare_id = LLVMLookupIntrinsicID("llvm.dbg.declare", 16);
  210. GB_ASSERT(debug_declare_id != 0);
  211. isize removal_count = 0;
  212. isize pass_count = 0;
  213. isize const max_pass_count = 10;
  214. isize original_instruction_count = 0;
  215. // Custom remove dead instruction pass
  216. for (; pass_count < max_pass_count; pass_count++) {
  217. bool was_dead_instructions = false;
  218. // NOTE(bill): Iterate backwards
  219. // reduces the number of passes as things later on will depend on things previously
  220. for (LLVMBasicBlockRef block = LLVMGetLastBasicBlock(p->value);
  221. block != nullptr;
  222. block = LLVMGetPreviousBasicBlock(block)) {
  223. // NOTE(bill): Iterate backwards
  224. // reduces the number of passes as things later on will depend on things previously
  225. for (LLVMValueRef instr = LLVMGetLastInstruction(block);
  226. instr != nullptr;
  227. /**/) {
  228. if (pass_count == 0) {
  229. original_instruction_count += 1;
  230. }
  231. LLVMValueRef curr_instr = instr;
  232. instr = LLVMGetPreviousInstruction(instr);
  233. LLVMUseRef first_use = LLVMGetFirstUse(curr_instr);
  234. if (first_use != nullptr) {
  235. continue;
  236. }
  237. if (LLVMTypeOf(curr_instr) == nullptr) {
  238. continue;
  239. }
  240. // NOTE(bill): Explicit instructions are set here because some instructions could have side effects
  241. switch (LLVMGetInstructionOpcode(curr_instr)) {
  242. // case LLVMAlloca:
  243. case LLVMFNeg:
  244. case LLVMAdd:
  245. case LLVMFAdd:
  246. case LLVMSub:
  247. case LLVMFSub:
  248. case LLVMMul:
  249. case LLVMFMul:
  250. case LLVMUDiv:
  251. case LLVMSDiv:
  252. case LLVMFDiv:
  253. case LLVMURem:
  254. case LLVMSRem:
  255. case LLVMFRem:
  256. case LLVMShl:
  257. case LLVMLShr:
  258. case LLVMAShr:
  259. case LLVMAnd:
  260. case LLVMOr:
  261. case LLVMXor:
  262. case LLVMLoad:
  263. case LLVMGetElementPtr:
  264. case LLVMTrunc:
  265. case LLVMZExt:
  266. case LLVMSExt:
  267. case LLVMFPToUI:
  268. case LLVMFPToSI:
  269. case LLVMUIToFP:
  270. case LLVMSIToFP:
  271. case LLVMFPTrunc:
  272. case LLVMFPExt:
  273. case LLVMPtrToInt:
  274. case LLVMIntToPtr:
  275. case LLVMBitCast:
  276. case LLVMAddrSpaceCast:
  277. case LLVMICmp:
  278. case LLVMFCmp:
  279. case LLVMSelect:
  280. case LLVMExtractElement:
  281. case LLVMShuffleVector:
  282. case LLVMExtractValue:
  283. removal_count += 1;
  284. LLVMInstructionEraseFromParent(curr_instr);
  285. was_dead_instructions = true;
  286. break;
  287. }
  288. }
  289. }
  290. if (!was_dead_instructions) {
  291. break;
  292. }
  293. }
  294. }
  295. gb_internal void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p, lbFunctionPassManagerKind pass_manager_kind) {
  296. if (p == nullptr) {
  297. return;
  298. }
  299. LLVMRunFunctionPassManager(fpm, p->value);
  300. switch (pass_manager_kind) {
  301. case lbFunctionPassManager_none:
  302. return;
  303. case lbFunctionPassManager_default:
  304. case lbFunctionPassManager_default_without_memcpy:
  305. if (build_context.optimization_level < 0) {
  306. return;
  307. }
  308. break;
  309. }
  310. // NOTE(bill): LLVMAddDCEPass doesn't seem to be exported in the official DLL's for LLVM
  311. // which means we cannot rely upon it
  312. // This is also useful for read the .ll for debug purposes because a lot of instructions
  313. // are not removed
  314. lb_run_remove_dead_instruction_pass(p);
  315. }
  316. gb_internal void llvm_delete_function(LLVMValueRef func) {
  317. // for (LLVMBasicBlockRef block = LLVMGetFirstBasicBlock(func); block != nullptr; /**/) {
  318. // LLVMBasicBlockRef curr_block = block;
  319. // block = LLVMGetNextBasicBlock(block);
  320. // for (LLVMValueRef instr = LLVMGetFirstInstruction(curr_block); instr != nullptr; /**/) {
  321. // LLVMValueRef curr_instr = instr;
  322. // instr = LLVMGetNextInstruction(instr);
  323. // LLVMInstructionEraseFromParent(curr_instr);
  324. // }
  325. // LLVMRemoveBasicBlockFromParent(curr_block);
  326. // }
  327. LLVMDeleteFunction(func);
  328. }
  329. gb_internal void lb_append_to_compiler_used(lbModule *m, LLVMValueRef func) {
  330. LLVMValueRef global = LLVMGetNamedGlobal(m->mod, "llvm.compiler.used");
  331. LLVMValueRef *constants;
  332. int operands = 1;
  333. if (global != NULL) {
  334. GB_ASSERT(LLVMIsAGlobalVariable(global));
  335. LLVMValueRef initializer = LLVMGetInitializer(global);
  336. GB_ASSERT(LLVMIsAConstantArray(initializer));
  337. operands = LLVMGetNumOperands(initializer) + 1;
  338. constants = gb_alloc_array(temporary_allocator(), LLVMValueRef, operands);
  339. for (int i = 0; i < operands - 1; i++) {
  340. LLVMValueRef operand = LLVMGetOperand(initializer, i);
  341. GB_ASSERT(LLVMIsAConstant(operand));
  342. constants[i] = operand;
  343. }
  344. LLVMDeleteGlobal(global);
  345. } else {
  346. constants = gb_alloc_array(temporary_allocator(), LLVMValueRef, 1);
  347. }
  348. LLVMTypeRef Int8PtrTy = LLVMPointerType(LLVMInt8TypeInContext(m->ctx), 0);
  349. LLVMTypeRef ATy = LLVMArrayType(Int8PtrTy, operands);
  350. constants[operands - 1] = LLVMConstBitCast(func, Int8PtrTy);
  351. LLVMValueRef initializer = LLVMConstArray(Int8PtrTy, constants, operands);
  352. global = LLVMAddGlobal(m->mod, ATy, "llvm.compiler.used");
  353. LLVMSetLinkage(global, LLVMAppendingLinkage);
  354. LLVMSetSection(global, "llvm.metadata");
  355. LLVMSetInitializer(global, initializer);
  356. }
  357. gb_internal void lb_run_remove_unused_function_pass(lbModule *m) {
  358. isize removal_count = 0;
  359. isize pass_count = 0;
  360. isize const max_pass_count = 10;
  361. // Custom remove dead function pass
  362. for (; pass_count < max_pass_count; pass_count++) {
  363. bool was_dead = false;
  364. for (LLVMValueRef func = LLVMGetFirstFunction(m->mod);
  365. func != nullptr;
  366. /**/
  367. ) {
  368. LLVMValueRef curr_func = func;
  369. func = LLVMGetNextFunction(func);
  370. LLVMUseRef first_use = LLVMGetFirstUse(curr_func);
  371. if (first_use != nullptr) {
  372. continue;
  373. }
  374. String name = {};
  375. name.text = cast(u8 *)LLVMGetValueName2(curr_func, cast(size_t *)&name.len);
  376. if (LLVMIsDeclaration(curr_func)) {
  377. // Ignore for the time being
  378. continue;
  379. }
  380. LLVMLinkage linkage = LLVMGetLinkage(curr_func);
  381. if (linkage != LLVMInternalLinkage) {
  382. continue;
  383. }
  384. Entity **found = map_get(&m->procedure_values, curr_func);
  385. if (found && *found) {
  386. Entity *e = *found;
  387. bool is_required = (e->flags & EntityFlag_Require) == EntityFlag_Require;
  388. if (is_required) {
  389. lb_append_to_compiler_used(m, curr_func);
  390. continue;
  391. }
  392. }
  393. llvm_delete_function(curr_func);
  394. was_dead = true;
  395. removal_count += 1;
  396. }
  397. if (!was_dead) {
  398. break;
  399. }
  400. }
  401. }
  402. gb_internal void lb_run_remove_unused_globals_pass(lbModule *m) {
  403. isize removal_count = 0;
  404. isize pass_count = 0;
  405. isize const max_pass_count = 10;
  406. // Custom remove dead function pass
  407. for (; pass_count < max_pass_count; pass_count++) {
  408. bool was_dead = false;
  409. for (LLVMValueRef global = LLVMGetFirstGlobal(m->mod);
  410. global != nullptr;
  411. /**/
  412. ) {
  413. LLVMValueRef curr_global = global;
  414. global = LLVMGetNextGlobal(global);
  415. LLVMUseRef first_use = LLVMGetFirstUse(curr_global);
  416. if (first_use != nullptr) {
  417. continue;
  418. }
  419. String name = {};
  420. name.text = cast(u8 *)LLVMGetValueName2(curr_global, cast(size_t *)&name.len);
  421. LLVMLinkage linkage = LLVMGetLinkage(curr_global);
  422. if (linkage != LLVMInternalLinkage) {
  423. continue;
  424. }
  425. Entity **found = map_get(&m->procedure_values, curr_global);
  426. if (found && *found) {
  427. Entity *e = *found;
  428. bool is_required = (e->flags & EntityFlag_Require) == EntityFlag_Require;
  429. if (is_required) {
  430. continue;
  431. }
  432. }
  433. LLVMDeleteGlobal(curr_global);
  434. was_dead = true;
  435. removal_count += 1;
  436. }
  437. if (!was_dead) {
  438. break;
  439. }
  440. }
  441. }