return 0;
}
\f
-/* Split single instruction. Helper function for split_all_insns.
- Return last insn in the sequence if successful, or NULL if unsuccessful. */
+/* Split single instruction. Helper function for split_all_insns and
+ split_all_insns_noflow. Return last insn in the sequence if successful,
+ or NULL if unsuccessful. */
+
static rtx
split_insn (rtx insn)
{
- rtx set;
- if (!INSN_P (insn))
- ;
- /* Don't split no-op move insns. These should silently
- disappear later in final. Splitting such insns would
- break the code that handles REG_NO_CONFLICT blocks. */
+ /* Split insns here to get max fine-grain parallelism. */
+ rtx first = PREV_INSN (insn);
+ rtx last = try_split (PATTERN (insn), insn, 1);
- else if ((set = single_set (insn)) != NULL && set_noop_p (set))
- {
- /* Nops get in the way while scheduling, so delete them
- now if register allocation has already been done. It
- is too risky to try to do this before register
- allocation, and there are unlikely to be very many
- nops then anyways. */
- if (reload_completed)
- delete_insn_and_edges (insn);
- }
- else
- {
- /* Split insns here to get max fine-grain parallelism. */
- rtx first = PREV_INSN (insn);
- rtx last = try_split (PATTERN (insn), insn, 1);
+ if (last == insn)
+ return NULL_RTX;
+
+ /* try_split returns the NOTE that INSN became. */
+ PUT_CODE (insn, NOTE);
+ NOTE_SOURCE_FILE (insn) = 0;
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- if (last != insn)
+ /* ??? Coddle to md files that generate subregs in post-reload
+ splitters instead of computing the proper hard register. */
+ if (reload_completed && first != last)
+ {
+ first = NEXT_INSN (first);
+ for (;;)
{
- /* try_split returns the NOTE that INSN became. */
- PUT_CODE (insn, NOTE);
- NOTE_SOURCE_FILE (insn) = 0;
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-
- /* ??? Coddle to md files that generate subregs in post-
- reload splitters instead of computing the proper
- hard register. */
- if (reload_completed && first != last)
- {
- first = NEXT_INSN (first);
- while (1)
- {
- if (INSN_P (first))
- cleanup_subreg_operands (first);
- if (first == last)
- break;
- first = NEXT_INSN (first);
- }
- }
- return last;
+ if (INSN_P (first))
+ cleanup_subreg_operands (first);
+ if (first == last)
+ break;
+ first = NEXT_INSN (first);
}
}
- return NULL_RTX;
+ return last;
}
+
/* Split all insns in the function. If UPD_LIFE, update life info after. */
void
for (insn = bb->head; !finish ; insn = next)
{
- rtx last;
-
/* Can't use `next_real_insn' because that might go across
CODE_LABELS and short-out basic blocks. */
next = NEXT_INSN (insn);
finish = (insn == bb->end);
- last = split_insn (insn);
- if (last)
+ if (INSN_P (insn))
{
- /* The split sequence may include barrier, but the
- BB boundary we are interested in will be set to previous
- one. */
-
- while (GET_CODE (last) == BARRIER)
- last = PREV_INSN (last);
- SET_BIT (blocks, bb->index);
- changed = true;
- insn = last;
+ rtx set = single_set (insn);
+
+ /* Don't split no-op move insns. These should silently
+ disappear later in final. Splitting such insns would
+ break the code that handles REG_NO_CONFLICT blocks. */
+ if (set && set_noop_p (set))
+ {
+ /* Nops get in the way while scheduling, so delete them
+ now if register allocation has already been done. It
+ is too risky to try to do this before register
+ allocation, and there are unlikely to be very many
+ nops then anyways. */
+ if (reload_completed)
+ {
+ /* If the no-op set has a REG_UNUSED note, we need
+ to update liveness information. */
+ if (find_reg_note (insn, REG_UNUSED, NULL_RTX))
+ {
+ SET_BIT (blocks, bb->index);
+ changed = true;
+ }
+ /* ??? Is life info affected by deleting edges? */
+ delete_insn_and_edges (insn);
+ }
+ }
+ else
+ {
+ rtx last = split_insn (insn);
+ if (last)
+ {
+ /* The split sequence may include barrier, but the
+ BB boundary we are interested in will be set to
+ previous one. */
+
+ while (GET_CODE (last) == BARRIER)
+ last = PREV_INSN (last);
+ SET_BIT (blocks, bb->index);
+ changed = true;
+ }
+ }
}
}
}
for (insn = get_insns (); insn; insn = next)
{
next = NEXT_INSN (insn);
- split_insn (insn);
+ if (INSN_P (insn))
+ {
+ /* Don't split no-op move insns. These should silently
+ disappear later in final. Splitting such insns would
+ break the code that handles REG_NO_CONFLICT blocks. */
+ rtx set = single_set (insn);
+ if (set && set_noop_p (set))
+ {
+ /* Nops get in the way while scheduling, so delete them
+ now if register allocation has already been done. It
+ is too risky to try to do this before register
+ allocation, and there are unlikely to be very many
+ nops then anyways.
+
+ ??? Should we use delete_insn when the CFG isn't valid? */
+ if (reload_completed)
+ delete_insn_and_edges (insn);
+ }
+ else
+ split_insn (insn);
+ }
}
- return;
}
\f
#ifdef HAVE_peephole2
--- /dev/null
+/* PR optimization/11634 */
+
+/* The following code used to ICE in verify_local_live_at_start on
+ PA when compiled with -O2. The cause was that split_all_insns was
+ not updating liveness information when deleting no-op moves that
+ had REG_UNUSED notes. */
+
+/* { dg-do compile { target hppa*-*-* } } */
+/* { dg-options "-O2" } */
+
+void *f(void *s);
+void H5T_conv_vlen (unsigned long long nelmts, unsigned char *bg_ptr)
+{
+ long long seq_len;
+ unsigned long long bg_seq_len = 0;
+ unsigned src_base_size, dst_base_size;
+ void *tmp_buf = 0;
+ unsigned tmp_buf_size = 0;
+ unsigned long long elmtno;
+ for (elmtno = 0; elmtno < nelmts; elmtno++)
+ {
+ unsigned char *tmp = bg_ptr;
+ bg_seq_len = *tmp;
+ if (bg_seq_len > 0
+ && tmp_buf_size <
+ (unsigned) (bg_seq_len *
+ (src_base_size > dst_base_size
+ ? src_base_size
+ : dst_base_size)))
+ {
+ tmp_buf_size =
+ (unsigned) (bg_seq_len *
+ (src_base_size > dst_base_size
+ ? src_base_size
+ : dst_base_size));
+ }
+ if (bg_seq_len < seq_len)
+ f ((unsigned char *) tmp_buf + dst_base_size * bg_seq_len);
+ }
+}
+