+/* Return true if the entire libcall sequence starting at INSN is dead.
+ NOTE is the REG_LIBCALL note attached to INSN.
+
+ A libcall sequence is a block of insns with no side-effects, i.e.
+ that is only used for its return value. The terminology derives
+ from that of a call, but a libcall sequence need not contain one.
+ It is only defined by a pair of REG_LIBCALL/REG_RETVAL notes.
+
+ From a dataflow viewpoint, a libcall sequence has the property that
+ no UD chain can enter it from the outside. As a consequence, if a
+ libcall sequence has a dead return value, it is effectively dead.
+ This is both enforced by CSE (cse_extended_basic_block) and relied
+ upon by delete_trivially_dead_insns.
+
+ However, in practice, the return value business is a tricky one and
+ only checking the liveness of the last insn is not sufficient to
+ decide whether the whole sequence is dead (e.g. PR middle-end/19551)
+ so we check the liveness of every insn starting from the call. */
+
+static bool
+libcall_dead_p (rtx insn, rtx note)
+{
+ rtx last = XEXP (note, 0);
+
+ /* Find the call insn. */
+ while (insn != last && !CALL_P (insn))
+ insn = NEXT_INSN (insn);
+
+ /* If there is none, do nothing special, since ordinary death handling
+ can understand these insns. */
+ if (!CALL_P (insn))
+ return false;
+
+ /* If this is a call that returns a value via an invisible pointer, the
+ dataflow engine cannot see it so it has been marked unconditionally.
+ Skip it unless it has been made the last insn in the libcall, for
+ example by the combiner, in which case we're left with no easy way
+ of asserting its liveness. */
+ if (!single_set (insn))
+ {
+ if (insn == last)
+ return false;
+ insn = NEXT_INSN (insn);
+ }
+
+ while (insn != NEXT_INSN (last))
+ {
+ if (INSN_P (insn) && marked_insn_p (insn))
+ return false;
+ insn = NEXT_INSN (insn);
+ }
+
+ return true;
+}
+
+