/* Return true if INSN requires the stack frame to be set up. PROLOGUE_USED contains the hard registers used in the function prologue. SET_UP_BY_PROLOGUE is the set of registers we expect the prologue to set up for the function. */ bool requires_stack_frame_p (rtx_insn *insn, HARD_REG_SET prologue_used, HARD_REG_SET set_up_by_prologue) { df_ref def, use; HARD_REG_SET hardregs; unsigned regno; if (CALL_P (insn)) return !SIBLING_CALL_P (insn); /* We need a frame to get the unique CFA expected by the unwinder. */ if (cfun->can_throw_non_call_exceptions && can_throw_internal (insn)) return true; CLEAR_HARD_REG_SET (hardregs); FOR_EACH_INSN_DEF (def, insn) { rtx dreg = DF_REF_REG (def); if (!REG_P (dreg)) continue; add_to_hard_reg_set (&hardregs, GET_MODE (dreg), REGNO (dreg)); }
static void mark_insn (rtx_insn *insn, bool fast) { if (!marked_insn_p (insn)) { if (!fast) worklist.safe_push (insn); bitmap_set_bit (marked, INSN_UID (insn)); if (dump_file) fprintf (dump_file, " Adding insn %d to worklist\n", INSN_UID (insn)); if (CALL_P (insn) && !df_in_progress && !SIBLING_CALL_P (insn) && (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))) find_call_stack_args (as_a <rtx_call_insn *> (insn), true, fast, NULL); } }
static bool deletable_insn_p (rtx_insn *insn, bool fast, bitmap arg_stores) { rtx body, x; int i; df_ref def; if (CALL_P (insn) /* We cannot delete calls inside of the recursive dce because this may cause basic blocks to be deleted and this messes up the rest of the stack of optimization passes. */ && (!df_in_progress) /* We cannot delete pure or const sibling calls because it is hard to see the result. */ && (!SIBLING_CALL_P (insn)) /* We can delete dead const or pure calls as long as they do not infinite loop. */ && (RTL_CONST_OR_PURE_CALL_P (insn) && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))) return find_call_stack_args (as_a <rtx_call_insn *> (insn), false, fast, arg_stores); /* Don't delete jumps, notes and the like. */ if (!NONJUMP_INSN_P (insn)) return false; /* Don't delete insns that may throw if we cannot do so. */ if (!(cfun->can_delete_dead_exceptions && can_alter_cfg) && !insn_nothrow_p (insn)) return false; /* If INSN sets a global_reg, leave it untouched. */ FOR_EACH_INSN_DEF (def, insn) if (HARD_REGISTER_NUM_P (DF_REF_REGNO (def)) && global_regs[DF_REF_REGNO (def)]) return false; /* Initialization of pseudo PIC register should never be removed. */ else if (DF_REF_REG (def) == pic_offset_table_rtx && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER) return false; body = PATTERN (insn); switch (GET_CODE (body)) { case USE: case VAR_LOCATION: return false; case CLOBBER: if (fast) { /* A CLOBBER of a dead pseudo register serves no purpose. That is not necessarily true for hard registers until after reload. */ x = XEXP (body, 0); return REG_P (x) && (!HARD_REGISTER_P (x) || reload_completed); } else /* Because of the way that use-def chains are built, it is not possible to tell if the clobber is dead because it can never be the target of a use-def chain. */ return false; case PARALLEL: for (i = XVECLEN (body, 0) - 1; i >= 0; i--) if (!deletable_insn_p_1 (XVECEXP (body, 0, i))) return false; return true; default: return deletable_insn_p_1 (body); } }
static basic_block expand_gimple_tailcall (basic_block bb, tree stmt, bool *can_fallthru) { rtx last2, last; edge e; edge_iterator ei; int probability; gcov_type count; last2 = last = get_last_insn (); expand_expr_stmt (stmt); for (last = NEXT_INSN (last); last; last = NEXT_INSN (last)) if (CALL_P (last) && SIBLING_CALL_P (last)) goto found; maybe_dump_rtl_for_tree_stmt (stmt, last2); *can_fallthru = true; return NULL; found: /* ??? Wouldn't it be better to just reset any pending stack adjust? Any instructions emitted here are about to be deleted. */ do_pending_stack_adjust (); /* Remove any non-eh, non-abnormal edges that don't go to exit. */ /* ??? I.e. the fallthrough edge. HOWEVER! If there were to be EH or abnormal edges, we shouldn't have created a tail call in the first place. So it seems to me we should just be removing all edges here, or redirecting the existing fallthru edge to the exit block. */ probability = 0; count = 0; for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ) { if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH))) { if (e->dest != EXIT_BLOCK_PTR) { e->dest->count -= e->count; e->dest->frequency -= EDGE_FREQUENCY (e); if (e->dest->count < 0) e->dest->count = 0; if (e->dest->frequency < 0) e->dest->frequency = 0; } count += e->count; probability += e->probability; remove_edge (e); } else ei_next (&ei); } /* This is somewhat ugly: the call_expr expander often emits instructions after the sibcall (to perform the function return). These confuse the find_sub_basic_blocks code, so we need to get rid of these. */ last = NEXT_INSN (last); gcc_assert (BARRIER_P (last)); *can_fallthru = false; while (NEXT_INSN (last)) { /* For instance an sqrt builtin expander expands if with sibcall in the then and label for `else`. */ if (LABEL_P (NEXT_INSN (last))) { *can_fallthru = true; break; } delete_insn (NEXT_INSN (last)); } e = make_edge (bb, EXIT_BLOCK_PTR, EDGE_ABNORMAL | EDGE_SIBCALL); e->probability += probability; e->count += count; BB_END (bb) = last; update_bb_for_insn (bb); if (NEXT_INSN (last)) { bb = create_basic_block (NEXT_INSN (last), get_last_insn (), bb); last = BB_END (bb); if (BARRIER_P (last)) BB_END (bb) = PREV_INSN (last); } maybe_dump_rtl_for_tree_stmt (stmt, last2); return bb; }