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