static bool interesting_second_load (rtx set, struct load ***load, rtx insn) { rtx mem, reg; if (!set) return false; mem = SET_SRC (set); reg = SET_DEST (set); if (!MEM_P (mem) || MEM_VOLATILE_P (mem) || !REG_P (reg)) return false; *load = (struct load **) htab_find_slot_with_hash (htab_load, mem, load_rtx_hash (mem), NO_INSERT); if (!*load) return false; /* Don't work on cases that never happen: if there is no kill, we would have inherited the reload; if the store and load regs are the same we would need to find an available register. If the kill insn was already replaced by a move this information is stale, disregard it. */ if (rtx_equal_p (reg, (**load)->reg) || !(**load)->reg_kill || INSN_DELETED_P ((**load)->reg_kill) || reg_used_between_p (reg, PREV_INSN ((**load)->reg_kill), NEXT_INSN (insn)) || reg_set_between_p (reg, PREV_INSN ((**load)->reg_kill), insn)) { if (dump_file) { fputs ("\nCan't insert the move before the kill for this load:\n ", dump_file); print_inline_rtx (dump_file, insn, 2); fputs ("\n\n", dump_file); } return false; } return true; }
static int identify_call_return_value (rtx cp, rtx *p_hard_return, rtx *p_soft_return) { rtx insn, set, hard, soft; insn = XEXP (cp, 0); /* Search backward through the "normal" call sequence to the CALL insn. */ while (NEXT_INSN (insn)) insn = NEXT_INSN (insn); while (GET_CODE (insn) != CALL_INSN) insn = PREV_INSN (insn); /* Assume the pattern is (set (dest) (call ...)), or that the first member of a parallel is. This is the hard return register used by the function. */ if (GET_CODE (PATTERN (insn)) == SET && GET_CODE (SET_SRC (PATTERN (insn))) == CALL) hard = SET_DEST (PATTERN (insn)); else if (GET_CODE (PATTERN (insn)) == PARALLEL && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET && GET_CODE (SET_SRC (XVECEXP (PATTERN (insn), 0, 0))) == CALL) hard = SET_DEST (XVECEXP (PATTERN (insn), 0, 0)); else return 0; /* If we didn't get a single hard register (e.g. a parallel), give up. */ if (GET_CODE (hard) != REG) return 0; /* Stack adjustment done after call may appear here. */ insn = skip_stack_adjustment (insn); if (! insn) return 0; /* Restore of GP register may appear here. */ insn = skip_pic_restore (insn); if (! insn) return 0; /* If there's nothing after, there's no soft return value. */ insn = NEXT_INSN (insn); if (! insn) return 0; /* We're looking for a source of the hard return register. */ set = single_set (insn); if (! set || SET_SRC (set) != hard) return 0; soft = SET_DEST (set); insn = NEXT_INSN (insn); /* Allow this first destination to be copied to a second register, as might happen if the first register wasn't the particular pseudo we'd been expecting. */ if (insn && (set = single_set (insn)) != NULL_RTX && SET_SRC (set) == soft) { soft = SET_DEST (set); insn = NEXT_INSN (insn); } /* Don't fool with anything but pseudo registers. */ if (GET_CODE (soft) != REG || REGNO (soft) < FIRST_PSEUDO_REGISTER) return 0; /* This value must not be modified before the end of the sequence. */ if (reg_set_between_p (soft, insn, NULL_RTX)) return 0; *p_hard_return = hard; *p_soft_return = soft; return 1; }