llvm_backend_opt.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  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. return optimization_level < 0;
  47. }
  48. gb_internal void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm, i32 optimization_level) {
  49. if (lb_opt_ignore(optimization_level)) {
  50. return;
  51. }
  52. #if !LB_USE_NEW_PASS_SYSTEM
  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. #endif
  64. }
  65. gb_internal void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level) {
  66. if (lb_opt_ignore(optimization_level)) {
  67. return;
  68. }
  69. #if !LB_USE_NEW_PASS_SYSTEM
  70. if (ignore_memcpy_pass) {
  71. lb_basic_populate_function_pass_manager(fpm, optimization_level);
  72. return;
  73. } else if (optimization_level <= 0) {
  74. LLVMAddMemCpyOptPass(fpm);
  75. lb_basic_populate_function_pass_manager(fpm, optimization_level);
  76. return;
  77. }
  78. #if 0
  79. LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
  80. LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
  81. LLVMPassManagerBuilderSetSizeLevel(pmb, optimization_level);
  82. LLVMPassManagerBuilderPopulateFunctionPassManager(pmb, fpm);
  83. #else
  84. LLVMAddMemCpyOptPass(fpm);
  85. lb_basic_populate_function_pass_manager(fpm, optimization_level);
  86. LLVMAddSCCPPass(fpm);
  87. LLVMAddPromoteMemoryToRegisterPass(fpm);
  88. LLVMAddUnifyFunctionExitNodesPass(fpm);
  89. LLVMAddCFGSimplificationPass(fpm);
  90. LLVMAddEarlyCSEPass(fpm);
  91. LLVMAddLowerExpectIntrinsicPass(fpm);
  92. #endif
  93. #endif
  94. }
  95. gb_internal void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level) {
  96. if (lb_opt_ignore(optimization_level)) {
  97. return;
  98. }
  99. #if !LB_USE_NEW_PASS_SYSTEM
  100. if (optimization_level <= 0) {
  101. LLVMAddMemCpyOptPass(fpm);
  102. lb_basic_populate_function_pass_manager(fpm, optimization_level);
  103. return;
  104. }
  105. #if 1
  106. LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
  107. LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
  108. LLVMPassManagerBuilderSetSizeLevel(pmb, optimization_level);
  109. LLVMPassManagerBuilderPopulateFunctionPassManager(pmb, fpm);
  110. #else
  111. LLVMAddMemCpyOptPass(fpm);
  112. LLVMAddPromoteMemoryToRegisterPass(fpm);
  113. LLVMAddMergedLoadStoreMotionPass(fpm);
  114. LLVM_ADD_CONSTANT_VALUE_PASS(fpm);
  115. LLVMAddEarlyCSEPass(fpm);
  116. LLVM_ADD_CONSTANT_VALUE_PASS(fpm);
  117. LLVMAddMergedLoadStoreMotionPass(fpm);
  118. LLVMAddPromoteMemoryToRegisterPass(fpm);
  119. LLVMAddCFGSimplificationPass(fpm);
  120. LLVMAddSCCPPass(fpm);
  121. LLVMAddPromoteMemoryToRegisterPass(fpm);
  122. LLVMAddUnifyFunctionExitNodesPass(fpm);
  123. LLVMAddCFGSimplificationPass(fpm);
  124. LLVMAddEarlyCSEPass(fpm);
  125. LLVMAddLowerExpectIntrinsicPass(fpm);
  126. #endif
  127. #endif
  128. }
  129. gb_internal void lb_add_function_simplifcation_passes(LLVMPassManagerRef mpm, i32 optimization_level) {
  130. #if !LB_USE_NEW_PASS_SYSTEM
  131. LLVMAddCFGSimplificationPass(mpm);
  132. LLVMAddJumpThreadingPass(mpm);
  133. LLVMAddSimplifyLibCallsPass(mpm);
  134. LLVMAddTailCallEliminationPass(mpm);
  135. LLVMAddCFGSimplificationPass(mpm);
  136. LLVMAddReassociatePass(mpm);
  137. LLVMAddLoopRotatePass(mpm);
  138. LLVMAddLICMPass(mpm);
  139. LLVMAddLoopUnswitchPass(mpm);
  140. LLVMAddCFGSimplificationPass(mpm);
  141. LLVMAddLoopIdiomPass(mpm);
  142. LLVMAddLoopDeletionPass(mpm);
  143. LLVMAddMergedLoadStoreMotionPass(mpm);
  144. LLVMAddMemCpyOptPass(mpm);
  145. LLVMAddSCCPPass(mpm);
  146. LLVMAddBitTrackingDCEPass(mpm);
  147. LLVMAddJumpThreadingPass(mpm);
  148. LLVM_ADD_CONSTANT_VALUE_PASS(mpm);
  149. LLVMAddLICMPass(mpm);
  150. LLVMAddLoopRerollPass(mpm);
  151. LLVMAddAggressiveDCEPass(mpm);
  152. LLVMAddCFGSimplificationPass(mpm);
  153. #endif
  154. }
  155. gb_internal void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPassManagerRef mpm, i32 optimization_level) {
  156. // NOTE(bill): Treat -opt:3 as if it was -opt:2
  157. // TODO(bill): Determine which opt definitions should exist in the first place
  158. if (optimization_level <= 0 && build_context.ODIN_DEBUG) {
  159. return;
  160. }
  161. #if !LB_USE_NEW_PASS_SYSTEM
  162. LLVMAddAlwaysInlinerPass(mpm);
  163. LLVMAddStripDeadPrototypesPass(mpm);
  164. LLVMAddAnalysisPasses(target_machine, mpm);
  165. LLVMAddPruneEHPass(mpm);
  166. if (optimization_level <= 0) {
  167. return;
  168. }
  169. LLVMAddGlobalDCEPass(mpm);
  170. if (optimization_level >= 2) {
  171. // NOTE(bill, 2021-03-29: use this causes invalid code generation)
  172. // LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
  173. // LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
  174. // LLVMPassManagerBuilderPopulateModulePassManager(pmb, mpm);
  175. // LLVMPassManagerBuilderPopulateLTOPassManager(pmb, mpm, false, true);
  176. // return;
  177. }
  178. LLVMAddIPSCCPPass(mpm);
  179. LLVMAddCalledValuePropagationPass(mpm);
  180. LLVMAddGlobalOptimizerPass(mpm);
  181. LLVMAddDeadArgEliminationPass(mpm);
  182. LLVMAddCFGSimplificationPass(mpm);
  183. LLVMAddPruneEHPass(mpm);
  184. if (optimization_level < 2) {
  185. return;
  186. }
  187. LLVMAddFunctionInliningPass(mpm);
  188. lb_add_function_simplifcation_passes(mpm, optimization_level);
  189. LLVMAddGlobalDCEPass(mpm);
  190. LLVMAddGlobalOptimizerPass(mpm);
  191. LLVMAddLoopRotatePass(mpm);
  192. LLVMAddLoopVectorizePass(mpm);
  193. if (optimization_level >= 2) {
  194. LLVMAddEarlyCSEPass(mpm);
  195. LLVM_ADD_CONSTANT_VALUE_PASS(mpm);
  196. LLVMAddLICMPass(mpm);
  197. LLVMAddLoopUnswitchPass(mpm);
  198. LLVMAddCFGSimplificationPass(mpm);
  199. }
  200. LLVMAddCFGSimplificationPass(mpm);
  201. LLVMAddSLPVectorizePass(mpm);
  202. LLVMAddLICMPass(mpm);
  203. LLVMAddAlignmentFromAssumptionsPass(mpm);
  204. LLVMAddStripDeadPrototypesPass(mpm);
  205. if (optimization_level >= 2) {
  206. LLVMAddGlobalDCEPass(mpm);
  207. LLVMAddConstantMergePass(mpm);
  208. }
  209. LLVMAddCFGSimplificationPass(mpm);
  210. #endif
  211. }
  212. /**************************************************************************
  213. IMPORTANT NOTE(bill, 2021-11-06): Custom Passes
  214. The procedures below are custom written passes to aid in the
  215. optimization of Odin programs
  216. **************************************************************************/
  217. gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) {
  218. unsigned debug_declare_id = LLVMLookupIntrinsicID("llvm.dbg.declare", 16);
  219. GB_ASSERT(debug_declare_id != 0);
  220. isize removal_count = 0;
  221. isize pass_count = 0;
  222. isize const max_pass_count = 10;
  223. isize original_instruction_count = 0;
  224. // Custom remove dead instruction pass
  225. for (; pass_count < max_pass_count; pass_count++) {
  226. bool was_dead_instructions = false;
  227. // NOTE(bill): Iterate backwards
  228. // reduces the number of passes as things later on will depend on things previously
  229. for (LLVMBasicBlockRef block = LLVMGetLastBasicBlock(p->value);
  230. block != nullptr;
  231. block = LLVMGetPreviousBasicBlock(block)) {
  232. // NOTE(bill): Iterate backwards
  233. // reduces the number of passes as things later on will depend on things previously
  234. for (LLVMValueRef instr = LLVMGetLastInstruction(block);
  235. instr != nullptr;
  236. /**/) {
  237. if (pass_count == 0) {
  238. original_instruction_count += 1;
  239. }
  240. LLVMValueRef curr_instr = instr;
  241. instr = LLVMGetPreviousInstruction(instr);
  242. LLVMUseRef first_use = LLVMGetFirstUse(curr_instr);
  243. if (first_use != nullptr) {
  244. continue;
  245. }
  246. if (LLVMTypeOf(curr_instr) == nullptr) {
  247. continue;
  248. }
  249. // NOTE(bill): Explicit instructions are set here because some instructions could have side effects
  250. switch (LLVMGetInstructionOpcode(curr_instr)) {
  251. // case LLVMAlloca:
  252. case LLVMLoad:
  253. if (LLVMGetVolatile(curr_instr)) {
  254. break;
  255. }
  256. /*fallthrough*/
  257. case LLVMFNeg:
  258. case LLVMAdd:
  259. case LLVMFAdd:
  260. case LLVMSub:
  261. case LLVMFSub:
  262. case LLVMMul:
  263. case LLVMFMul:
  264. case LLVMUDiv:
  265. case LLVMSDiv:
  266. case LLVMFDiv:
  267. case LLVMURem:
  268. case LLVMSRem:
  269. case LLVMFRem:
  270. case LLVMShl:
  271. case LLVMLShr:
  272. case LLVMAShr:
  273. case LLVMAnd:
  274. case LLVMOr:
  275. case LLVMXor:
  276. case LLVMGetElementPtr:
  277. case LLVMTrunc:
  278. case LLVMZExt:
  279. case LLVMSExt:
  280. case LLVMFPToUI:
  281. case LLVMFPToSI:
  282. case LLVMUIToFP:
  283. case LLVMSIToFP:
  284. case LLVMFPTrunc:
  285. case LLVMFPExt:
  286. case LLVMPtrToInt:
  287. case LLVMIntToPtr:
  288. case LLVMBitCast:
  289. case LLVMAddrSpaceCast:
  290. case LLVMICmp:
  291. case LLVMFCmp:
  292. case LLVMSelect:
  293. case LLVMExtractElement:
  294. case LLVMShuffleVector:
  295. case LLVMExtractValue:
  296. removal_count += 1;
  297. LLVMInstructionEraseFromParent(curr_instr);
  298. was_dead_instructions = true;
  299. break;
  300. }
  301. }
  302. }
  303. if (!was_dead_instructions) {
  304. break;
  305. }
  306. }
  307. }
  308. gb_internal LLVMValueRef lb_run_instrumentation_pass_insert_call(lbProcedure *p, Entity *entity, LLVMBuilderRef dummy_builder, bool is_enter) {
  309. lbModule *m = p->module;
  310. if (p->debug_info != nullptr) {
  311. TokenPos pos = {};
  312. if (is_enter) {
  313. pos = ast_token(p->body).pos;
  314. } else {
  315. pos = ast_end_token(p->body).pos;
  316. }
  317. LLVMSetCurrentDebugLocation2(dummy_builder, lb_debug_location_from_token_pos(p, pos));
  318. }
  319. lbValue cc = lb_find_procedure_value_from_entity(m, entity);
  320. LLVMValueRef args[3] = {};
  321. args[0] = LLVMConstPointerCast(p->value, lb_type(m, t_rawptr));
  322. if (is_arch_wasm()) {
  323. args[1] = LLVMConstPointerNull(lb_type(m, t_rawptr));
  324. } else {
  325. LLVMValueRef returnaddress_args[1] = {};
  326. returnaddress_args[0] = LLVMConstInt(LLVMInt32TypeInContext(m->ctx), 0, false);
  327. char const *instrinsic_name = "llvm.returnaddress";
  328. unsigned id = LLVMLookupIntrinsicID(instrinsic_name, gb_strlen(instrinsic_name));
  329. GB_ASSERT_MSG(id != 0, "Unable to find %s", instrinsic_name);
  330. LLVMValueRef ip = LLVMGetIntrinsicDeclaration(m->mod, id, nullptr, 0);
  331. LLVMTypeRef call_type = LLVMIntrinsicGetType(m->ctx, id, nullptr, 0);
  332. args[1] = LLVMBuildCall2(dummy_builder, call_type, ip, returnaddress_args, gb_count_of(returnaddress_args), "");
  333. }
  334. Token name = {};
  335. if (p->entity) {
  336. name = p->entity->token;
  337. }
  338. args[2] = lb_emit_source_code_location_as_global_ptr(p, name.string, name.pos).value;
  339. LLVMTypeRef fnp = lb_type_internal_for_procedures_raw(p->module, entity->type);
  340. return LLVMBuildCall2(dummy_builder, fnp, cc.value, args, gb_count_of(args), "");
  341. }
  342. gb_internal void lb_run_instrumentation_pass(lbProcedure *p) {
  343. lbModule *m = p->module;
  344. Entity *enter = m->info->instrumentation_enter_entity;
  345. Entity *exit = m->info->instrumentation_exit_entity;
  346. if (enter == nullptr || exit == nullptr) {
  347. return;
  348. }
  349. if (!(p->entity &&
  350. p->entity->kind == Entity_Procedure &&
  351. p->entity->Procedure.has_instrumentation)) {
  352. return;
  353. }
  354. #define LLVM_V_NAME(x) x, cast(unsigned)(gb_count_of(x)-1)
  355. LLVMBuilderRef dummy_builder = LLVMCreateBuilderInContext(m->ctx);
  356. defer (LLVMDisposeBuilder(dummy_builder));
  357. LLVMBasicBlockRef entry_bb = p->entry_block->block;
  358. LLVMPositionBuilder(dummy_builder, entry_bb, LLVMGetFirstInstruction(entry_bb));
  359. lb_run_instrumentation_pass_insert_call(p, enter, dummy_builder, true);
  360. LLVMRemoveStringAttributeAtIndex(p->value, LLVMAttributeIndex_FunctionIndex, LLVM_V_NAME("instrument-function-entry"));
  361. unsigned bb_count = LLVMCountBasicBlocks(p->value);
  362. LLVMBasicBlockRef *bbs = gb_alloc_array(temporary_allocator(), LLVMBasicBlockRef, bb_count);
  363. LLVMGetBasicBlocks(p->value, bbs);
  364. for (unsigned i = 0; i < bb_count; i++) {
  365. LLVMBasicBlockRef bb = bbs[i];
  366. LLVMValueRef terminator = LLVMGetBasicBlockTerminator(bb);
  367. if (terminator == nullptr ||
  368. !LLVMIsAReturnInst(terminator)) {
  369. continue;
  370. }
  371. // TODO(bill): getTerminatingMustTailCall()
  372. // If T is preceded by a musttail call, that's the real terminator.
  373. // if (CallInst *CI = BB.getTerminatingMustTailCall())
  374. // T = CI;
  375. LLVMPositionBuilderBefore(dummy_builder, terminator);
  376. lb_run_instrumentation_pass_insert_call(p, exit, dummy_builder, false);
  377. }
  378. LLVMRemoveStringAttributeAtIndex(p->value, LLVMAttributeIndex_FunctionIndex, LLVM_V_NAME("instrument-function-exit"));
  379. #undef LLVM_V_NAME
  380. }
  381. gb_internal void lb_run_function_pass_manager(LLVMPassManagerRef fpm, lbProcedure *p, lbFunctionPassManagerKind pass_manager_kind) {
  382. if (p == nullptr) {
  383. return;
  384. }
  385. // NOTE(bill): LLVMAddDCEPass doesn't seem to be exported in the official DLL's for LLVM
  386. // which means we cannot rely upon it
  387. // This is also useful for read the .ll for debug purposes because a lot of instructions
  388. // are not removed
  389. lb_run_remove_dead_instruction_pass(p);
  390. lb_run_instrumentation_pass(p);
  391. switch (pass_manager_kind) {
  392. case lbFunctionPassManager_none:
  393. return;
  394. case lbFunctionPassManager_default:
  395. case lbFunctionPassManager_default_without_memcpy:
  396. if (build_context.optimization_level < 0) {
  397. return;
  398. }
  399. break;
  400. }
  401. LLVMRunFunctionPassManager(fpm, p->value);
  402. }
  403. gb_internal void llvm_delete_function(LLVMValueRef func) {
  404. // for (LLVMBasicBlockRef block = LLVMGetFirstBasicBlock(func); block != nullptr; /**/) {
  405. // LLVMBasicBlockRef curr_block = block;
  406. // block = LLVMGetNextBasicBlock(block);
  407. // for (LLVMValueRef instr = LLVMGetFirstInstruction(curr_block); instr != nullptr; /**/) {
  408. // LLVMValueRef curr_instr = instr;
  409. // instr = LLVMGetNextInstruction(instr);
  410. // LLVMInstructionEraseFromParent(curr_instr);
  411. // }
  412. // LLVMRemoveBasicBlockFromParent(curr_block);
  413. // }
  414. LLVMDeleteFunction(func);
  415. }
  416. gb_internal void lb_append_to_compiler_used(lbModule *m, LLVMValueRef func) {
  417. LLVMValueRef global = LLVMGetNamedGlobal(m->mod, "llvm.compiler.used");
  418. LLVMValueRef *constants;
  419. int operands = 1;
  420. if (global != NULL) {
  421. GB_ASSERT(LLVMIsAGlobalVariable(global));
  422. LLVMValueRef initializer = LLVMGetInitializer(global);
  423. GB_ASSERT(LLVMIsAConstantArray(initializer));
  424. operands = LLVMGetNumOperands(initializer) + 1;
  425. constants = gb_alloc_array(temporary_allocator(), LLVMValueRef, operands);
  426. for (int i = 0; i < operands - 1; i++) {
  427. LLVMValueRef operand = LLVMGetOperand(initializer, i);
  428. GB_ASSERT(LLVMIsAConstant(operand));
  429. constants[i] = operand;
  430. }
  431. LLVMDeleteGlobal(global);
  432. } else {
  433. constants = gb_alloc_array(temporary_allocator(), LLVMValueRef, 1);
  434. }
  435. LLVMTypeRef Int8PtrTy = LLVMPointerType(LLVMInt8TypeInContext(m->ctx), 0);
  436. LLVMTypeRef ATy = llvm_array_type(Int8PtrTy, operands);
  437. constants[operands - 1] = LLVMConstBitCast(func, Int8PtrTy);
  438. LLVMValueRef initializer = LLVMConstArray(Int8PtrTy, constants, operands);
  439. global = LLVMAddGlobal(m->mod, ATy, "llvm.compiler.used");
  440. LLVMSetLinkage(global, LLVMAppendingLinkage);
  441. LLVMSetSection(global, "llvm.metadata");
  442. LLVMSetInitializer(global, initializer);
  443. }
  444. gb_internal void lb_run_remove_unused_function_pass(lbModule *m) {
  445. isize removal_count = 0;
  446. isize pass_count = 0;
  447. isize const max_pass_count = 10;
  448. // Custom remove dead function pass
  449. for (; pass_count < max_pass_count; pass_count++) {
  450. bool was_dead = false;
  451. for (LLVMValueRef func = LLVMGetFirstFunction(m->mod);
  452. func != nullptr;
  453. /**/
  454. ) {
  455. LLVMValueRef curr_func = func;
  456. func = LLVMGetNextFunction(func);
  457. LLVMUseRef first_use = LLVMGetFirstUse(curr_func);
  458. if (first_use != nullptr) {
  459. continue;
  460. }
  461. String name = {};
  462. name.text = cast(u8 *)LLVMGetValueName2(curr_func, cast(size_t *)&name.len);
  463. if (LLVMIsDeclaration(curr_func)) {
  464. // Ignore for the time being
  465. continue;
  466. }
  467. LLVMLinkage linkage = LLVMGetLinkage(curr_func);
  468. if (linkage != LLVMInternalLinkage) {
  469. continue;
  470. }
  471. Entity **found = map_get(&m->procedure_values, curr_func);
  472. if (found && *found) {
  473. Entity *e = *found;
  474. bool is_required = (e->flags & EntityFlag_Require) == EntityFlag_Require;
  475. if (is_required) {
  476. lb_append_to_compiler_used(m, curr_func);
  477. continue;
  478. }
  479. }
  480. llvm_delete_function(curr_func);
  481. was_dead = true;
  482. removal_count += 1;
  483. }
  484. if (!was_dead) {
  485. break;
  486. }
  487. }
  488. }
  489. gb_internal void lb_run_remove_unused_globals_pass(lbModule *m) {
  490. isize removal_count = 0;
  491. isize pass_count = 0;
  492. isize const max_pass_count = 10;
  493. // Custom remove dead function pass
  494. for (; pass_count < max_pass_count; pass_count++) {
  495. bool was_dead = false;
  496. for (LLVMValueRef global = LLVMGetFirstGlobal(m->mod);
  497. global != nullptr;
  498. /**/
  499. ) {
  500. LLVMValueRef curr_global = global;
  501. global = LLVMGetNextGlobal(global);
  502. LLVMUseRef first_use = LLVMGetFirstUse(curr_global);
  503. if (first_use != nullptr) {
  504. continue;
  505. }
  506. String name = {};
  507. name.text = cast(u8 *)LLVMGetValueName2(curr_global, cast(size_t *)&name.len);
  508. LLVMLinkage linkage = LLVMGetLinkage(curr_global);
  509. if (linkage != LLVMInternalLinkage) {
  510. continue;
  511. }
  512. Entity **found = map_get(&m->procedure_values, curr_global);
  513. if (found && *found) {
  514. Entity *e = *found;
  515. bool is_required = (e->flags & EntityFlag_Require) == EntityFlag_Require;
  516. if (is_required) {
  517. continue;
  518. }
  519. }
  520. LLVMDeleteGlobal(curr_global);
  521. was_dead = true;
  522. removal_count += 1;
  523. }
  524. if (!was_dead) {
  525. break;
  526. }
  527. }
  528. }