1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: MIT 2f08c3bdfSopenharmony_ci// 3f08c3bdfSopenharmony_ci// SSA conversion 4f08c3bdfSopenharmony_ci// Copyright (C) 2005 Luc Van Oostenryck 5f08c3bdfSopenharmony_ci// 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci#include <assert.h> 8f08c3bdfSopenharmony_ci#include "ssa.h" 9f08c3bdfSopenharmony_ci#include "lib.h" 10f08c3bdfSopenharmony_ci#include "dominate.h" 11f08c3bdfSopenharmony_ci#include "flowgraph.h" 12f08c3bdfSopenharmony_ci#include "linearize.h" 13f08c3bdfSopenharmony_ci#include "simplify.h" 14f08c3bdfSopenharmony_ci#include "flow.h" 15f08c3bdfSopenharmony_ci 16f08c3bdfSopenharmony_ci 17f08c3bdfSopenharmony_ci// Is it possible and desirable for this to be promoted to a pseudo? 18f08c3bdfSopenharmony_cistatic inline bool is_promotable(struct symbol *type) 19f08c3bdfSopenharmony_ci{ 20f08c3bdfSopenharmony_ci struct symbol *member; 21f08c3bdfSopenharmony_ci int bf_seen; 22f08c3bdfSopenharmony_ci int nbr; 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_ci if (type->type == SYM_NODE) 25f08c3bdfSopenharmony_ci type = type->ctype.base_type; 26f08c3bdfSopenharmony_ci switch (type->type) { 27f08c3bdfSopenharmony_ci case SYM_ENUM: 28f08c3bdfSopenharmony_ci case SYM_BITFIELD: 29f08c3bdfSopenharmony_ci case SYM_PTR: 30f08c3bdfSopenharmony_ci case SYM_RESTRICT: // OK, always integer types 31f08c3bdfSopenharmony_ci return 1; 32f08c3bdfSopenharmony_ci case SYM_STRUCT: 33f08c3bdfSopenharmony_ci // we allow a single scalar field 34f08c3bdfSopenharmony_ci // but a run of bitfields count for 1 35f08c3bdfSopenharmony_ci // (and packed bifields are excluded). 36f08c3bdfSopenharmony_ci if (type->packed) 37f08c3bdfSopenharmony_ci return 0; 38f08c3bdfSopenharmony_ci nbr = 0; 39f08c3bdfSopenharmony_ci bf_seen = 0; 40f08c3bdfSopenharmony_ci FOR_EACH_PTR(type->symbol_list, member) { 41f08c3bdfSopenharmony_ci if (is_bitfield_type(member)) { 42f08c3bdfSopenharmony_ci if (bf_seen) 43f08c3bdfSopenharmony_ci continue; 44f08c3bdfSopenharmony_ci bf_seen = 1; 45f08c3bdfSopenharmony_ci } else { 46f08c3bdfSopenharmony_ci bf_seen = 0; 47f08c3bdfSopenharmony_ci } 48f08c3bdfSopenharmony_ci if (!is_scalar_type(member)) 49f08c3bdfSopenharmony_ci return 0; 50f08c3bdfSopenharmony_ci if (nbr++) 51f08c3bdfSopenharmony_ci return 0; 52f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(member); 53f08c3bdfSopenharmony_ci if (bf_seen && (type->bit_size > long_ctype.bit_size)) 54f08c3bdfSopenharmony_ci return 0; 55f08c3bdfSopenharmony_ci return 1; 56f08c3bdfSopenharmony_ci case SYM_UNION: 57f08c3bdfSopenharmony_ci // FIXME: should be like struct but has problem 58f08c3bdfSopenharmony_ci // when used with/for type cohercion 59f08c3bdfSopenharmony_ci // -----> OK if only same sized integral types 60f08c3bdfSopenharmony_ci FOR_EACH_PTR(type->symbol_list, member) { 61f08c3bdfSopenharmony_ci if (member->bit_size != type->bit_size) 62f08c3bdfSopenharmony_ci return 0; 63f08c3bdfSopenharmony_ci if (!is_integral_type(member)) 64f08c3bdfSopenharmony_ci return 0; 65f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(member); 66f08c3bdfSopenharmony_ci return 1; 67f08c3bdfSopenharmony_ci default: 68f08c3bdfSopenharmony_ci break; 69f08c3bdfSopenharmony_ci } 70f08c3bdfSopenharmony_ci if (type->ctype.base_type == &int_type) 71f08c3bdfSopenharmony_ci return 1; 72f08c3bdfSopenharmony_ci if (type->ctype.base_type == &fp_type) 73f08c3bdfSopenharmony_ci return 1; 74f08c3bdfSopenharmony_ci return 0; 75f08c3bdfSopenharmony_ci} 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_cistatic void kill_store(struct instruction *insn) 78f08c3bdfSopenharmony_ci{ 79f08c3bdfSopenharmony_ci remove_use(&insn->src); 80f08c3bdfSopenharmony_ci remove_use(&insn->target); 81f08c3bdfSopenharmony_ci insn->bb = NULL; 82f08c3bdfSopenharmony_ci} 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_cistatic bool same_memop(struct instruction *a, struct instruction *b) 85f08c3bdfSopenharmony_ci{ 86f08c3bdfSopenharmony_ci if (a->size != b->size || a->offset != b->offset) 87f08c3bdfSopenharmony_ci return false; 88f08c3bdfSopenharmony_ci if (is_integral_type(a->type) && is_float_type(b->type)) 89f08c3bdfSopenharmony_ci return false; 90f08c3bdfSopenharmony_ci if (is_float_type(a->type) && is_integral_type(b->type)) 91f08c3bdfSopenharmony_ci return false; 92f08c3bdfSopenharmony_ci return true; 93f08c3bdfSopenharmony_ci} 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_cistatic void rewrite_local_var(struct basic_block *bb, pseudo_t addr, int nbr_stores, int nbr_uses) 96f08c3bdfSopenharmony_ci{ 97f08c3bdfSopenharmony_ci struct instruction *store = NULL; 98f08c3bdfSopenharmony_ci struct instruction *insn; 99f08c3bdfSopenharmony_ci bool remove = false; 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci if (!bb) 102f08c3bdfSopenharmony_ci return; 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci FOR_EACH_PTR(bb->insns, insn) { 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci if (!insn->bb || insn->src != addr) 107f08c3bdfSopenharmony_ci continue; 108f08c3bdfSopenharmony_ci switch (insn->opcode) { 109f08c3bdfSopenharmony_ci case OP_LOAD: 110f08c3bdfSopenharmony_ci if (!store) 111f08c3bdfSopenharmony_ci replace_with_pseudo(insn, undef_pseudo()); 112f08c3bdfSopenharmony_ci else if (same_memop(store, insn)) 113f08c3bdfSopenharmony_ci replace_with_pseudo(insn, store->target); 114f08c3bdfSopenharmony_ci else 115f08c3bdfSopenharmony_ci remove = false; 116f08c3bdfSopenharmony_ci break; 117f08c3bdfSopenharmony_ci case OP_STORE: 118f08c3bdfSopenharmony_ci store = insn; 119f08c3bdfSopenharmony_ci remove = true; 120f08c3bdfSopenharmony_ci break; 121f08c3bdfSopenharmony_ci } 122f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(insn); 123f08c3bdfSopenharmony_ci if (remove) 124f08c3bdfSopenharmony_ci kill_store(store); 125f08c3bdfSopenharmony_ci} 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_ci// we would like to know: 128f08c3bdfSopenharmony_ci// is there one or more stores? 129f08c3bdfSopenharmony_ci// are all loads & stores local/done in a single block? 130f08c3bdfSopenharmony_cistatic void ssa_convert_one_var(struct entrypoint *ep, struct symbol *var) 131f08c3bdfSopenharmony_ci{ 132f08c3bdfSopenharmony_ci unsigned long generation = ++bb_generation; 133f08c3bdfSopenharmony_ci struct basic_block_list *alpha = NULL; 134f08c3bdfSopenharmony_ci struct basic_block_list *idf = NULL; 135f08c3bdfSopenharmony_ci struct basic_block *samebb = NULL; 136f08c3bdfSopenharmony_ci struct basic_block *bb; 137f08c3bdfSopenharmony_ci struct pseudo_user *pu; 138f08c3bdfSopenharmony_ci unsigned long mod = var->ctype.modifiers; 139f08c3bdfSopenharmony_ci bool local = true; 140f08c3bdfSopenharmony_ci int nbr_stores = 0; 141f08c3bdfSopenharmony_ci int nbr_uses = 0; 142f08c3bdfSopenharmony_ci pseudo_t addr; 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_ci /* Never used as a symbol? */ 145f08c3bdfSopenharmony_ci addr = var->pseudo; 146f08c3bdfSopenharmony_ci if (!addr) 147f08c3bdfSopenharmony_ci return; 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_ci /* We don't do coverage analysis of volatiles.. */ 150f08c3bdfSopenharmony_ci if (mod & MOD_VOLATILE) 151f08c3bdfSopenharmony_ci return; 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci /* ..and symbols with external visibility need more care */ 154f08c3bdfSopenharmony_ci mod &= (MOD_NONLOCAL | MOD_STATIC | MOD_ADDRESSABLE); 155f08c3bdfSopenharmony_ci if (mod) 156f08c3bdfSopenharmony_ci goto external_visibility; 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_ci if (!is_promotable(var)) 159f08c3bdfSopenharmony_ci return; 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci // 1) insert in the worklist all BBs that may modify var 162f08c3bdfSopenharmony_ci FOR_EACH_PTR(addr->users, pu) { 163f08c3bdfSopenharmony_ci struct instruction *insn = pu->insn; 164f08c3bdfSopenharmony_ci struct basic_block *bb = insn->bb; 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_ci switch (insn->opcode) { 167f08c3bdfSopenharmony_ci case OP_STORE: 168f08c3bdfSopenharmony_ci nbr_stores++; 169f08c3bdfSopenharmony_ci if (bb->generation != generation) { 170f08c3bdfSopenharmony_ci bb->generation = generation; 171f08c3bdfSopenharmony_ci add_bb(&alpha, bb); 172f08c3bdfSopenharmony_ci } 173f08c3bdfSopenharmony_ci /* fall through */ 174f08c3bdfSopenharmony_ci case OP_LOAD: 175f08c3bdfSopenharmony_ci if (local) { 176f08c3bdfSopenharmony_ci if (!samebb) 177f08c3bdfSopenharmony_ci samebb = bb; 178f08c3bdfSopenharmony_ci else if (samebb != bb) 179f08c3bdfSopenharmony_ci local = false; 180f08c3bdfSopenharmony_ci } 181f08c3bdfSopenharmony_ci nbr_uses++; 182f08c3bdfSopenharmony_ci break; 183f08c3bdfSopenharmony_ci case OP_SYMADDR: 184f08c3bdfSopenharmony_ci mod |= MOD_ADDRESSABLE; 185f08c3bdfSopenharmony_ci goto external_visibility; 186f08c3bdfSopenharmony_ci default: 187f08c3bdfSopenharmony_ci warning(var->pos, "symbol '%s' pseudo used in unexpected way", 188f08c3bdfSopenharmony_ci show_ident(var->ident)); 189f08c3bdfSopenharmony_ci } 190f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(pu); 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_ci // if all uses are local to a single block 193f08c3bdfSopenharmony_ci // they can easily be rewritten and doesn't need phi-nodes 194f08c3bdfSopenharmony_ci // FIXME: could be done for extended BB too 195f08c3bdfSopenharmony_ci if (local) { 196f08c3bdfSopenharmony_ci rewrite_local_var(samebb, addr, nbr_stores, nbr_uses); 197f08c3bdfSopenharmony_ci return; 198f08c3bdfSopenharmony_ci } 199f08c3bdfSopenharmony_ci 200f08c3bdfSopenharmony_ci idf_compute(ep, &idf, alpha); 201f08c3bdfSopenharmony_ci FOR_EACH_PTR(idf, bb) { 202f08c3bdfSopenharmony_ci struct instruction *node = insert_phi_node(bb, var); 203f08c3bdfSopenharmony_ci node->phi_var = var->pseudo; 204f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(bb); 205f08c3bdfSopenharmony_ci var->torename = 1; 206f08c3bdfSopenharmony_ci 207f08c3bdfSopenharmony_ciexternal_visibility: 208f08c3bdfSopenharmony_ci if (mod & (MOD_NONLOCAL | MOD_STATIC)) 209f08c3bdfSopenharmony_ci return; 210f08c3bdfSopenharmony_ci kill_dead_stores(ep, addr, !mod); 211f08c3bdfSopenharmony_ci} 212f08c3bdfSopenharmony_ci 213f08c3bdfSopenharmony_cistatic struct instruction *lookup_var(struct basic_block *bb, struct symbol *var) 214f08c3bdfSopenharmony_ci{ 215f08c3bdfSopenharmony_ci do { 216f08c3bdfSopenharmony_ci struct instruction *insn = phi_map_lookup(bb->phi_map, var); 217f08c3bdfSopenharmony_ci if (insn) 218f08c3bdfSopenharmony_ci return insn; 219f08c3bdfSopenharmony_ci } while ((bb = bb->idom)); 220f08c3bdfSopenharmony_ci return NULL; 221f08c3bdfSopenharmony_ci} 222f08c3bdfSopenharmony_ci 223f08c3bdfSopenharmony_cistatic struct instruction_list *phis_all; 224f08c3bdfSopenharmony_cistatic struct instruction_list *phis_used; 225f08c3bdfSopenharmony_cistatic struct instruction_list *stores; 226f08c3bdfSopenharmony_ci 227f08c3bdfSopenharmony_cistatic bool matching_load(struct instruction *def, struct instruction *insn) 228f08c3bdfSopenharmony_ci{ 229f08c3bdfSopenharmony_ci if (insn->size != def->size) 230f08c3bdfSopenharmony_ci return false; 231f08c3bdfSopenharmony_ci switch (def->opcode) { 232f08c3bdfSopenharmony_ci case OP_STORE: 233f08c3bdfSopenharmony_ci case OP_LOAD: 234f08c3bdfSopenharmony_ci if (insn->offset != def->offset) 235f08c3bdfSopenharmony_ci return false; 236f08c3bdfSopenharmony_ci case OP_PHI: 237f08c3bdfSopenharmony_ci break; 238f08c3bdfSopenharmony_ci default: 239f08c3bdfSopenharmony_ci return false; 240f08c3bdfSopenharmony_ci } 241f08c3bdfSopenharmony_ci return true; 242f08c3bdfSopenharmony_ci} 243f08c3bdfSopenharmony_ci 244f08c3bdfSopenharmony_cistatic void ssa_rename_insn(struct basic_block *bb, struct instruction *insn) 245f08c3bdfSopenharmony_ci{ 246f08c3bdfSopenharmony_ci struct instruction *def; 247f08c3bdfSopenharmony_ci struct symbol *var; 248f08c3bdfSopenharmony_ci pseudo_t addr; 249f08c3bdfSopenharmony_ci pseudo_t val; 250f08c3bdfSopenharmony_ci 251f08c3bdfSopenharmony_ci switch (insn->opcode) { 252f08c3bdfSopenharmony_ci case OP_STORE: 253f08c3bdfSopenharmony_ci addr = insn->src; 254f08c3bdfSopenharmony_ci if (addr->type != PSEUDO_SYM) 255f08c3bdfSopenharmony_ci break; 256f08c3bdfSopenharmony_ci var = addr->sym; 257f08c3bdfSopenharmony_ci if (!var || !var->torename) 258f08c3bdfSopenharmony_ci break; 259f08c3bdfSopenharmony_ci phi_map_update(&bb->phi_map, var, insn); 260f08c3bdfSopenharmony_ci add_instruction(&stores, insn); 261f08c3bdfSopenharmony_ci break; 262f08c3bdfSopenharmony_ci case OP_LOAD: 263f08c3bdfSopenharmony_ci addr = insn->src; 264f08c3bdfSopenharmony_ci if (addr->type != PSEUDO_SYM) 265f08c3bdfSopenharmony_ci break; 266f08c3bdfSopenharmony_ci var = addr->sym; 267f08c3bdfSopenharmony_ci if (!var || !var->torename) 268f08c3bdfSopenharmony_ci break; 269f08c3bdfSopenharmony_ci def = lookup_var(bb, var); 270f08c3bdfSopenharmony_ci if (!def) { 271f08c3bdfSopenharmony_ci val = undef_pseudo(); 272f08c3bdfSopenharmony_ci } else if (!matching_load(def, insn)) { 273f08c3bdfSopenharmony_ci var->torename = false; 274f08c3bdfSopenharmony_ci break; 275f08c3bdfSopenharmony_ci } else { 276f08c3bdfSopenharmony_ci val = def->target; 277f08c3bdfSopenharmony_ci } 278f08c3bdfSopenharmony_ci replace_with_pseudo(insn, val); 279f08c3bdfSopenharmony_ci break; 280f08c3bdfSopenharmony_ci case OP_PHI: 281f08c3bdfSopenharmony_ci var = insn->type; 282f08c3bdfSopenharmony_ci if (!var || !var->torename) 283f08c3bdfSopenharmony_ci break; 284f08c3bdfSopenharmony_ci phi_map_update(&bb->phi_map, var, insn); 285f08c3bdfSopenharmony_ci add_instruction(&phis_all, insn); 286f08c3bdfSopenharmony_ci break; 287f08c3bdfSopenharmony_ci } 288f08c3bdfSopenharmony_ci} 289f08c3bdfSopenharmony_ci 290f08c3bdfSopenharmony_cistatic void ssa_rename_insns(struct entrypoint *ep) 291f08c3bdfSopenharmony_ci{ 292f08c3bdfSopenharmony_ci struct basic_block *bb; 293f08c3bdfSopenharmony_ci 294f08c3bdfSopenharmony_ci FOR_EACH_PTR(ep->bbs, bb) { 295f08c3bdfSopenharmony_ci struct instruction *insn; 296f08c3bdfSopenharmony_ci FOR_EACH_PTR(bb->insns, insn) { 297f08c3bdfSopenharmony_ci if (!insn->bb) 298f08c3bdfSopenharmony_ci continue; 299f08c3bdfSopenharmony_ci ssa_rename_insn(bb, insn); 300f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(insn); 301f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(bb); 302f08c3bdfSopenharmony_ci} 303f08c3bdfSopenharmony_ci 304f08c3bdfSopenharmony_cistatic void mark_phi_used(pseudo_t val) 305f08c3bdfSopenharmony_ci{ 306f08c3bdfSopenharmony_ci struct instruction *node; 307f08c3bdfSopenharmony_ci 308f08c3bdfSopenharmony_ci if (val->type != PSEUDO_REG) 309f08c3bdfSopenharmony_ci return; 310f08c3bdfSopenharmony_ci node = val->def; 311f08c3bdfSopenharmony_ci if (node->opcode != OP_PHI) 312f08c3bdfSopenharmony_ci return; 313f08c3bdfSopenharmony_ci if (node->used) 314f08c3bdfSopenharmony_ci return; 315f08c3bdfSopenharmony_ci node->used = 1; 316f08c3bdfSopenharmony_ci add_instruction(&phis_used, node); 317f08c3bdfSopenharmony_ci} 318f08c3bdfSopenharmony_ci 319f08c3bdfSopenharmony_cistatic void ssa_rename_phi(struct instruction *insn) 320f08c3bdfSopenharmony_ci{ 321f08c3bdfSopenharmony_ci struct basic_block *par; 322f08c3bdfSopenharmony_ci struct symbol *var; 323f08c3bdfSopenharmony_ci 324f08c3bdfSopenharmony_ci if (!insn->phi_var) 325f08c3bdfSopenharmony_ci return; 326f08c3bdfSopenharmony_ci var = insn->phi_var->sym; 327f08c3bdfSopenharmony_ci if (!var->torename) 328f08c3bdfSopenharmony_ci return; 329f08c3bdfSopenharmony_ci FOR_EACH_PTR(insn->bb->parents, par) { 330f08c3bdfSopenharmony_ci struct instruction *def = lookup_var(par, var); 331f08c3bdfSopenharmony_ci pseudo_t val = def ? def->target : undef_pseudo(); 332f08c3bdfSopenharmony_ci struct instruction *phisrc = alloc_phisrc(val, var); 333f08c3bdfSopenharmony_ci pseudo_t phi = phisrc->target; 334f08c3bdfSopenharmony_ci phi->ident = var->ident; 335f08c3bdfSopenharmony_ci insert_last_instruction(par, phisrc); 336f08c3bdfSopenharmony_ci link_phi(insn, phi); 337f08c3bdfSopenharmony_ci mark_phi_used(val); 338f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(par); 339f08c3bdfSopenharmony_ci} 340f08c3bdfSopenharmony_ci 341f08c3bdfSopenharmony_cistatic void ssa_rename_phis(struct entrypoint *ep) 342f08c3bdfSopenharmony_ci{ 343f08c3bdfSopenharmony_ci struct instruction *phi; 344f08c3bdfSopenharmony_ci 345f08c3bdfSopenharmony_ci phis_used = NULL; 346f08c3bdfSopenharmony_ci FOR_EACH_PTR(phis_all, phi) { 347f08c3bdfSopenharmony_ci if (has_users(phi->target)) { 348f08c3bdfSopenharmony_ci phi->used = 1; 349f08c3bdfSopenharmony_ci add_instruction(&phis_used, phi); 350f08c3bdfSopenharmony_ci } 351f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(phi); 352f08c3bdfSopenharmony_ci 353f08c3bdfSopenharmony_ci FOR_EACH_PTR(phis_used, phi) { 354f08c3bdfSopenharmony_ci if (!phi->bb) 355f08c3bdfSopenharmony_ci continue; 356f08c3bdfSopenharmony_ci ssa_rename_phi(phi); 357f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(phi); 358f08c3bdfSopenharmony_ci} 359f08c3bdfSopenharmony_ci 360f08c3bdfSopenharmony_cistatic void remove_dead_stores(struct instruction_list *stores) 361f08c3bdfSopenharmony_ci{ 362f08c3bdfSopenharmony_ci struct instruction *store; 363f08c3bdfSopenharmony_ci 364f08c3bdfSopenharmony_ci FOR_EACH_PTR(stores, store) { 365f08c3bdfSopenharmony_ci struct symbol *var = store->addr->sym; 366f08c3bdfSopenharmony_ci 367f08c3bdfSopenharmony_ci if (var->torename) 368f08c3bdfSopenharmony_ci kill_store(store); 369f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(store); 370f08c3bdfSopenharmony_ci} 371f08c3bdfSopenharmony_ci 372f08c3bdfSopenharmony_civoid ssa_convert(struct entrypoint *ep) 373f08c3bdfSopenharmony_ci{ 374f08c3bdfSopenharmony_ci struct basic_block *bb; 375f08c3bdfSopenharmony_ci pseudo_t pseudo; 376f08c3bdfSopenharmony_ci int first, last; 377f08c3bdfSopenharmony_ci 378f08c3bdfSopenharmony_ci // calculate the number of BBs 379f08c3bdfSopenharmony_ci first = ep->entry->bb->nr; 380f08c3bdfSopenharmony_ci last = first; 381f08c3bdfSopenharmony_ci FOR_EACH_PTR(ep->bbs, bb) { 382f08c3bdfSopenharmony_ci int nr = bb->nr; 383f08c3bdfSopenharmony_ci if (nr > last) 384f08c3bdfSopenharmony_ci last = nr; 385f08c3bdfSopenharmony_ci bb->phi_map = NULL; 386f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(bb); 387f08c3bdfSopenharmony_ci 388f08c3bdfSopenharmony_ci // try to promote memory accesses to pseudos 389f08c3bdfSopenharmony_ci stores = NULL; 390f08c3bdfSopenharmony_ci FOR_EACH_PTR(ep->accesses, pseudo) { 391f08c3bdfSopenharmony_ci ssa_convert_one_var(ep, pseudo->sym); 392f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(pseudo); 393f08c3bdfSopenharmony_ci 394f08c3bdfSopenharmony_ci // rename the converted accesses 395f08c3bdfSopenharmony_ci phis_all = phis_used = NULL; 396f08c3bdfSopenharmony_ci ssa_rename_insns(ep); 397f08c3bdfSopenharmony_ci ssa_rename_phis(ep); 398f08c3bdfSopenharmony_ci 399f08c3bdfSopenharmony_ci // remove now dead stores 400f08c3bdfSopenharmony_ci remove_dead_stores(stores); 401f08c3bdfSopenharmony_ci} 402