void union_defs (df_ref use, struct web_entry *def_entry, unsigned int *used, struct web_entry *use_entry, bool (*fun) (struct web_entry *, struct web_entry *)) { struct df_insn_info *insn_info = DF_REF_INSN_INFO (use); struct df_link *link = DF_REF_CHAIN (use); rtx set; if (insn_info) { df_ref eq_use; set = single_set (insn_info->insn); FOR_EACH_INSN_INFO_EQ_USE (eq_use, insn_info) if (use != eq_use && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (eq_use)) (*fun) (use_entry + DF_REF_ID (use), use_entry + DF_REF_ID (eq_use)); } else
static void replace_ref (struct ref *ref, rtx reg) { rtx oldreg = DF_REF_REAL_REG (ref); rtx *loc = DF_REF_REAL_LOC (ref); if (oldreg == reg) return; if (dump_file) fprintf (dump_file, "Updating insn %i (%i->%i)\n", INSN_UID (DF_REF_INSN (ref)), REGNO (oldreg), REGNO (reg)); *loc = reg; }
static rtx entry_register (struct web_entry *entry, struct ref *ref, char *used) { struct web_entry *root; rtx reg, newreg; /* Find the corresponding web and see if it has been visited. */ root = unionfind_root (entry); if (root->reg) return root->reg; /* We are seeing this web for the first time, do the assignment. */ reg = DF_REF_REAL_REG (ref); /* In case the original register is already assigned, generate new one. */ if (!used[REGNO (reg)]) newreg = reg, used[REGNO (reg)] = 1; else if (REG_USERVAR_P (reg) && 0/*&& !flag_messy_debugging*/) { newreg = reg; if (dump_file) fprintf (dump_file, "New web forced to keep reg=%i (user variable)\n", REGNO (reg)); } else { newreg = gen_reg_rtx (GET_MODE (reg)); REG_USERVAR_P (newreg) = REG_USERVAR_P (reg); REG_POINTER (newreg) = REG_POINTER (reg); REG_LOOP_TEST_P (newreg) = REG_LOOP_TEST_P (reg); REG_ATTRS (newreg) = REG_ATTRS (reg); if (dump_file) fprintf (dump_file, "Web oldreg=%i newreg=%i\n", REGNO (reg), REGNO (newreg)); } root->reg = newreg; return newreg; }
static void union_defs (struct df *df, struct ref *use, struct web_entry *def_entry, struct web_entry *use_entry) { rtx insn = DF_REF_INSN (use); struct df_link *link = DF_REF_CHAIN (use); struct df_link *use_link = DF_INSN_USES (df, insn); struct df_link *def_link = DF_INSN_DEFS (df, insn); rtx set = single_set (insn); /* Some instructions may use match_dup for their operands. In case the operands are dead, we will assign them different pseudos, creating invalid instructions, so union all uses of the same operand for each insn. */ while (use_link) { if (use != use_link->ref && DF_REF_REAL_REG (use) == DF_REF_REAL_REG (use_link->ref)) unionfind_union (use_entry + DF_REF_ID (use), use_entry + DF_REF_ID (use_link->ref)); use_link = use_link->next; } /* Recognize trivial noop moves and attempt to keep them as noop. While most of noop moves should be removed, we still keep some of them at libcall boundaries and such. */ if (set && SET_SRC (set) == DF_REF_REG (use) && SET_SRC (set) == SET_DEST (set)) { while (def_link) { if (DF_REF_REAL_REG (use) == DF_REF_REAL_REG (def_link->ref)) unionfind_union (use_entry + DF_REF_ID (use), def_entry + DF_REF_ID (def_link->ref)); def_link = def_link->next; } } while (link) { unionfind_union (use_entry + DF_REF_ID (use), def_entry + DF_REF_ID (link->ref)); link = link->next; } /* A READ_WRITE use requires the corresponding def to be in the same register. Find it and union. */ if (use->flags & DF_REF_READ_WRITE) { struct df_link *link = DF_INSN_DEFS (df, DF_REF_INSN (use)); while (link) { if (DF_REF_REAL_REG (link->ref) == DF_REF_REAL_REG (use)) unionfind_union (use_entry + DF_REF_ID (use), def_entry + DF_REF_ID (link->ref)); link = link->next; } } }
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_FN (bb, cfun) { rtx_insn *insn; bitmap lr = DF_LR_IN (bb); bitmap ur = DF_LIVE_IN (bb); bitmap_clear (already_genned); FOR_BB_INSNS (bb, insn) { df_ref use; if (!NONDEBUG_INSN_P (insn)) continue; FOR_EACH_INSN_USE (use, insn) { 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_insn *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, INSN_UID (insn)); } }