static struct df_link * get_defs (rtx_insn *insn, rtx reg, vec<rtx_insn *> *dest) { df_ref use; struct df_link *ref_chain, *ref_link; FOR_EACH_INSN_USE (use, insn) { if (GET_CODE (DF_REF_REG (use)) == SUBREG) return NULL; if (REGNO (DF_REF_REG (use)) == REGNO (reg)) break; } gcc_assert (use != NULL); ref_chain = DF_REF_CHAIN (use); for (ref_link = ref_chain; ref_link; ref_link = ref_link->next) { /* Problem getting some definition for this instruction. */ if (ref_link->ref == NULL) return NULL; if (DF_REF_INSN_INFO (ref_link->ref) == NULL) return NULL; } if (dest) for (ref_link = ref_chain; ref_link; ref_link = ref_link->next) dest->safe_push (DF_REF_INSN (ref_link->ref)); return ref_chain; }
static struct df_link * get_uses (rtx_insn *insn, rtx reg) { df_ref def; struct df_link *ref_chain, *ref_link; FOR_EACH_INSN_DEF (def, insn) if (REGNO (DF_REF_REG (def)) == REGNO (reg)) break; gcc_assert (def != NULL); ref_chain = DF_REF_CHAIN (def); for (ref_link = ref_chain; ref_link; ref_link = ref_link->next) { /* Problem getting some use for this instruction. */ if (ref_link->ref == NULL) return NULL; if (DF_REF_CLASS (ref_link->ref) != DF_REF_REGULAR) return NULL; } return ref_chain; }
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 struct df_link * get_defs (rtx_insn *insn, rtx reg, vec<rtx_insn *> *dest) { df_ref use; struct df_link *ref_chain, *ref_link; FOR_EACH_INSN_USE (use, insn) { if (GET_CODE (DF_REF_REG (use)) == SUBREG) return NULL; if (REGNO (DF_REF_REG (use)) == REGNO (reg)) break; } gcc_assert (use != NULL); ref_chain = DF_REF_CHAIN (use); for (ref_link = ref_chain; ref_link; ref_link = ref_link->next) { /* Problem getting some definition for this instruction. */ if (ref_link->ref == NULL) return NULL; if (DF_REF_INSN_INFO (ref_link->ref) == NULL) return NULL; /* As global regs are assumed to be defined at each function call dataflow can report a call_insn as being a definition of REG. But we can't do anything with that in this pass so proceed only if the instruction really sets REG in a way that can be deduced from the RTL structure. */ if (global_regs[REGNO (reg)] && !set_of (reg, DF_REF_INSN (ref_link->ref))) return NULL; } if (dest) for (ref_link = ref_chain; ref_link; ref_link = ref_link->next) dest->safe_push (DF_REF_INSN (ref_link->ref)); return ref_chain; }
static struct df_link * get_defs (rtx insn, rtx reg, vec<rtx> *dest) { df_ref reg_info, *uses; struct df_link *ref_chain, *ref_link; reg_info = NULL; for (uses = DF_INSN_USES (insn); *uses; uses++) { reg_info = *uses; if (GET_CODE (DF_REF_REG (reg_info)) == SUBREG) return NULL; if (REGNO (DF_REF_REG (reg_info)) == REGNO (reg)) break; } gcc_assert (reg_info != NULL && uses != NULL); ref_chain = DF_REF_CHAIN (reg_info); for (ref_link = ref_chain; ref_link; ref_link = ref_link->next) { /* Problem getting some definition for this instruction. */ if (ref_link->ref == NULL) return NULL; if (DF_REF_INSN_INFO (ref_link->ref) == NULL) return NULL; } if (dest) for (ref_link = ref_chain; ref_link; ref_link = ref_link->next) dest->safe_push (DF_REF_INSN (ref_link->ref)); return ref_chain; }
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 bool find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, bitmap arg_stores) { rtx p; rtx_insn *insn, *prev_insn; bool ret; HOST_WIDE_INT min_sp_off, max_sp_off; bitmap sp_bytes; gcc_assert (CALL_P (call_insn)); if (!ACCUMULATE_OUTGOING_ARGS) return true; if (!do_mark) { gcc_assert (arg_stores); bitmap_clear (arg_stores); } min_sp_off = INTTYPE_MAXIMUM (HOST_WIDE_INT); max_sp_off = 0; /* First determine the minimum and maximum offset from sp for stored arguments. */ for (p = CALL_INSN_FUNCTION_USAGE (call_insn); p; p = XEXP (p, 1)) if (GET_CODE (XEXP (p, 0)) == USE && MEM_P (XEXP (XEXP (p, 0), 0))) { rtx mem = XEXP (XEXP (p, 0), 0), addr; HOST_WIDE_INT off = 0, size; if (!MEM_SIZE_KNOWN_P (mem)) return false; size = MEM_SIZE (mem); addr = XEXP (mem, 0); if (GET_CODE (addr) == PLUS && REG_P (XEXP (addr, 0)) && CONST_INT_P (XEXP (addr, 1))) { off = INTVAL (XEXP (addr, 1)); addr = XEXP (addr, 0); } if (addr != stack_pointer_rtx) { if (!REG_P (addr)) return false; /* If not fast, use chains to see if addr wasn't set to sp + offset. */ if (!fast) { df_ref use; struct df_link *defs; rtx set; FOR_EACH_INSN_USE (use, call_insn) if (rtx_equal_p (addr, DF_REF_REG (use))) break; if (use == NULL) return false; for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) if (! DF_REF_IS_ARTIFICIAL (defs->ref)) break; if (defs == NULL) return false; set = single_set (DF_REF_INSN (defs->ref)); if (!set) return false; if (GET_CODE (SET_SRC (set)) != PLUS || XEXP (SET_SRC (set), 0) != stack_pointer_rtx || !CONST_INT_P (XEXP (SET_SRC (set), 1))) return false; off += INTVAL (XEXP (SET_SRC (set), 1)); } else return false;