1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: MIT 2f08c3bdfSopenharmony_ci// 3f08c3bdfSopenharmony_ci// Copyright (C) 2004 Linus Torvalds 4f08c3bdfSopenharmony_ci// Copyright (C) 2004 Christopher Li 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/// 7f08c3bdfSopenharmony_ci// Optimization main loop 8f08c3bdfSopenharmony_ci// ---------------------- 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_ci#include <assert.h> 11f08c3bdfSopenharmony_ci#include "optimize.h" 12f08c3bdfSopenharmony_ci#include "flowgraph.h" 13f08c3bdfSopenharmony_ci#include "linearize.h" 14f08c3bdfSopenharmony_ci#include "liveness.h" 15f08c3bdfSopenharmony_ci#include "simplify.h" 16f08c3bdfSopenharmony_ci#include "flow.h" 17f08c3bdfSopenharmony_ci#include "cse.h" 18f08c3bdfSopenharmony_ci#include "ir.h" 19f08c3bdfSopenharmony_ci#include "ssa.h" 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ciint repeat_phase; 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_cistatic void clear_symbol_pseudos(struct entrypoint *ep) 24f08c3bdfSopenharmony_ci{ 25f08c3bdfSopenharmony_ci pseudo_t pseudo; 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci FOR_EACH_PTR(ep->accesses, pseudo) { 28f08c3bdfSopenharmony_ci pseudo->sym->pseudo = NULL; 29f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(pseudo); 30f08c3bdfSopenharmony_ci} 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_cistatic void clean_up_insns(struct entrypoint *ep) 34f08c3bdfSopenharmony_ci{ 35f08c3bdfSopenharmony_ci struct basic_block *bb; 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_ci FOR_EACH_PTR(ep->bbs, bb) { 38f08c3bdfSopenharmony_ci struct instruction *insn; 39f08c3bdfSopenharmony_ci FOR_EACH_PTR(bb->insns, insn) { 40f08c3bdfSopenharmony_ci if (!insn->bb) 41f08c3bdfSopenharmony_ci continue; 42f08c3bdfSopenharmony_ci repeat_phase |= simplify_instruction(insn); 43f08c3bdfSopenharmony_ci if (!insn->bb) 44f08c3bdfSopenharmony_ci continue; 45f08c3bdfSopenharmony_ci assert(insn->bb == bb); 46f08c3bdfSopenharmony_ci cse_collect(insn); 47f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(insn); 48f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(bb); 49f08c3bdfSopenharmony_ci} 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_cistatic void cleanup_cfg(struct entrypoint *ep) 52f08c3bdfSopenharmony_ci{ 53f08c3bdfSopenharmony_ci kill_unreachable_bbs(ep); 54f08c3bdfSopenharmony_ci domtree_build(ep); 55f08c3bdfSopenharmony_ci} 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci/// 58f08c3bdfSopenharmony_ci// optimization main loop 59f08c3bdfSopenharmony_civoid optimize(struct entrypoint *ep) 60f08c3bdfSopenharmony_ci{ 61f08c3bdfSopenharmony_ci if (fdump_ir & PASS_LINEARIZE) 62f08c3bdfSopenharmony_ci show_entry(ep); 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci /* 65f08c3bdfSopenharmony_ci * Do trivial flow simplification - branches to 66f08c3bdfSopenharmony_ci * branches, kill dead basicblocks etc 67f08c3bdfSopenharmony_ci */ 68f08c3bdfSopenharmony_ci kill_unreachable_bbs(ep); 69f08c3bdfSopenharmony_ci ir_validate(ep); 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci cfg_postorder(ep); 72f08c3bdfSopenharmony_ci if (simplify_cfg_early(ep)) 73f08c3bdfSopenharmony_ci kill_unreachable_bbs(ep); 74f08c3bdfSopenharmony_ci ir_validate(ep); 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci domtree_build(ep); 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci /* 79f08c3bdfSopenharmony_ci * Turn symbols into pseudos 80f08c3bdfSopenharmony_ci */ 81f08c3bdfSopenharmony_ci if (fpasses & PASS_MEM2REG) 82f08c3bdfSopenharmony_ci ssa_convert(ep); 83f08c3bdfSopenharmony_ci ir_validate(ep); 84f08c3bdfSopenharmony_ci if (fdump_ir & PASS_MEM2REG) 85f08c3bdfSopenharmony_ci show_entry(ep); 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci if (!(fpasses & PASS_OPTIM)) 88f08c3bdfSopenharmony_ci return; 89f08c3bdfSopenharmony_cirepeat: 90f08c3bdfSopenharmony_ci /* 91f08c3bdfSopenharmony_ci * Remove trivial instructions, and try to CSE 92f08c3bdfSopenharmony_ci * the rest. 93f08c3bdfSopenharmony_ci */ 94f08c3bdfSopenharmony_ci do { 95f08c3bdfSopenharmony_ci simplify_memops(ep); 96f08c3bdfSopenharmony_ci do { 97f08c3bdfSopenharmony_ci repeat_phase = 0; 98f08c3bdfSopenharmony_ci clean_up_insns(ep); 99f08c3bdfSopenharmony_ci if (repeat_phase & REPEAT_CFG_CLEANUP) 100f08c3bdfSopenharmony_ci kill_unreachable_bbs(ep); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci cse_eliminate(ep); 103f08c3bdfSopenharmony_ci simplify_memops(ep); 104f08c3bdfSopenharmony_ci } while (repeat_phase); 105f08c3bdfSopenharmony_ci pack_basic_blocks(ep); 106f08c3bdfSopenharmony_ci if (repeat_phase & REPEAT_CFG_CLEANUP) 107f08c3bdfSopenharmony_ci cleanup_cfg(ep); 108f08c3bdfSopenharmony_ci } while (repeat_phase); 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci vrfy_flow(ep); 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci /* Cleanup */ 113f08c3bdfSopenharmony_ci clear_symbol_pseudos(ep); 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci /* And track pseudo register usage */ 116f08c3bdfSopenharmony_ci track_pseudo_liveness(ep); 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci /* 119f08c3bdfSopenharmony_ci * Some flow optimizations can only effectively 120f08c3bdfSopenharmony_ci * be done when we've done liveness analysis. But 121f08c3bdfSopenharmony_ci * if they trigger, we need to start all over 122f08c3bdfSopenharmony_ci * again 123f08c3bdfSopenharmony_ci */ 124f08c3bdfSopenharmony_ci if (simplify_flow(ep)) { 125f08c3bdfSopenharmony_ci clear_liveness(ep); 126f08c3bdfSopenharmony_ci if (repeat_phase & REPEAT_CFG_CLEANUP) 127f08c3bdfSopenharmony_ci cleanup_cfg(ep); 128f08c3bdfSopenharmony_ci goto repeat; 129f08c3bdfSopenharmony_ci } 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_ci /* Finally, add deathnotes to pseudos now that we have them */ 132f08c3bdfSopenharmony_ci if (dbg_dead) 133f08c3bdfSopenharmony_ci track_pseudo_death(ep); 134f08c3bdfSopenharmony_ci} 135