void single_def_use_dom_walker::before_dom_children (basic_block bb) { int bb_index = bb->index; struct df_md_bb_info *md_bb_info = df_md_get_bb_info (bb_index); struct df_lr_bb_info *lr_bb_info = df_lr_get_bb_info (bb_index); rtx_insn *insn; bitmap_copy (local_md, &md_bb_info->in); bitmap_copy (local_lr, &lr_bb_info->in); /* Push a marker for the leave_block callback. */ reg_defs_stack.safe_push (NULL); process_uses (df_get_artificial_uses (bb_index), DF_REF_AT_TOP); process_defs (df_get_artificial_defs (bb_index), DF_REF_AT_TOP); /* We don't call df_simulate_initialize_forwards, as it may overestimate the live registers if there are unused artificial defs. We prefer liveness to be underestimated. */ FOR_BB_INSNS (bb, insn) if (INSN_P (insn)) { unsigned int uid = INSN_UID (insn); process_uses (DF_INSN_UID_USES (uid), 0); process_uses (DF_INSN_UID_EQ_USES (uid), 0); process_defs (DF_INSN_UID_DEFS (uid), 0); df_simulate_one_insn_forwards (bb, insn, local_lr); } process_uses (df_get_artificial_uses (bb_index), 0); process_defs (df_get_artificial_defs (bb_index), 0); }
static void merge_in_block (int max_reg, basic_block bb) { rtx insn; rtx curr; int success_in_block = 0; if (dump_file) fprintf (dump_file, "\n\nstarting bb %d\n", bb->index); FOR_BB_INSNS_REVERSE_SAFE (bb, insn, curr) { unsigned int uid = INSN_UID (insn); bool insn_is_add_or_inc = true; if (!NONDEBUG_INSN_P (insn)) continue; /* This continue is deliberate. We do not want the uses of the jump put into reg_next_use because it is not considered safe to combine a preincrement with a jump. */ if (JUMP_P (insn)) continue; if (dump_file) dump_insn_slim (dump_file, insn); /* Does this instruction increment or decrement a register? */ if (parse_add_or_inc (insn, true)) { int regno = REGNO (inc_insn.reg_res); /* Cannot handle case where there are three separate regs before a mem ref. Too many moves would be needed to be profitable. */ if ((inc_insn.form == FORM_PRE_INC) || inc_insn.reg1_is_const) { mem_insn.insn = get_next_ref (regno, bb, reg_next_use); if (mem_insn.insn) { bool ok = true; if (!inc_insn.reg1_is_const) { /* We are only here if we are going to try a HAVE_*_MODIFY_REG type transformation. c is a reg and we must sure that the path from the inc_insn to the mem_insn.insn is both def and use clear of c because the inc insn is going to move into the mem_insn.insn. */ int luid = DF_INSN_LUID (mem_insn.insn); rtx other_insn = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_use); if (other_insn && luid > DF_INSN_LUID (other_insn)) ok = false; other_insn = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def); if (other_insn && luid > DF_INSN_LUID (other_insn)) ok = false; } if (dump_file) dump_inc_insn (dump_file); if (ok && find_address (&PATTERN (mem_insn.insn)) == -1) { if (dump_file) dump_mem_insn (dump_file); if (try_merge ()) { success_in_block++; insn_is_add_or_inc = false; } } } } } else { insn_is_add_or_inc = false; mem_insn.insn = insn; if (find_mem (&PATTERN (insn))) success_in_block++; } /* If the inc insn was merged with a mem, the inc insn is gone and there is noting to update. */ if (DF_INSN_UID_GET (uid)) { df_ref *def_rec; df_ref *use_rec; /* Need to update next use. */ for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) { df_ref def = *def_rec; reg_next_use[DF_REF_REGNO (def)] = NULL; reg_next_inc_use[DF_REF_REGNO (def)] = NULL; reg_next_def[DF_REF_REGNO (def)] = insn; } for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) { df_ref use = *use_rec; reg_next_use[DF_REF_REGNO (use)] = insn; if (insn_is_add_or_inc) reg_next_inc_use[DF_REF_REGNO (use)] = insn; else reg_next_inc_use[DF_REF_REGNO (use)] = NULL; } } else if (dump_file) fprintf (dump_file, "skipping update of deleted insn %d\n", uid); }
static void initialize_uninitialized_regs (void) { basic_block bb; bitmap already_genned = BITMAP_ALLOC (NULL); if (optimize == 1) { df_live_add_problem (); df_live_set_all_dirty (); } df_analyze (); FOR_EACH_BB (bb) { rtx insn; bitmap lr = DF_LR_IN (bb); bitmap ur = DF_LIVE_IN (bb); bitmap_clear (already_genned); FOR_BB_INSNS (bb, insn) { unsigned int uid = INSN_UID (insn); df_ref *use_rec; if (!INSN_P (insn)) continue; for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) { df_ref use = *use_rec; unsigned int regno = DF_REF_REGNO (use); /* Only do this for the pseudos. */ if (regno < FIRST_PSEUDO_REGISTER) continue; /* Do not generate multiple moves for the same regno. This is common for sequences of subreg operations. They would be deleted during combine but there is no reason to churn the system. */ if (bitmap_bit_p (already_genned, regno)) continue; /* A use is MUST uninitialized if it reaches the top of the block from the inside of the block (the lr test) and no def for it reaches the top of the block from outside of the block (the ur test). */ if (bitmap_bit_p (lr, regno) && (!bitmap_bit_p (ur, regno))) { rtx move_insn; rtx reg = DF_REF_REAL_REG (use); bitmap_set_bit (already_genned, regno); start_sequence (); emit_move_insn (reg, CONST0_RTX (GET_MODE (reg))); move_insn = get_insns (); end_sequence (); emit_insn_before (move_insn, insn); if (dump_file) fprintf (dump_file, "adding initialization in %s of reg %d at in block %d for insn %d.\n", current_function_name (), regno, bb->index, uid); } } } }