modulo-sched: skip loops with strange register defs [PR100225]

PR84878 fix adds an assertion which can fail, e.g. when stack pointer
is adjusted inside the loop.  We have to prevent it and search earlier
for any 'strange' instruction.  The solution is to skip the whole loop
if using 'note_stores' we found that one of hard registers is in
'df->regular_block_artificial_uses' set.

Also patch properly prohibit not single-set instruction in loop body.

gcc/ChangeLog:

	PR rtl-optimization/100225
	PR rtl-optimization/84878
	* modulo-sched.c (sms_schedule): Use note_stores to skip loops
	where we have an instruction which touches (writes) any hard
	register from df->regular_block_artificial_uses set.
	Allow not-single-set instruction only right before basic block
	tail.

gcc/testsuite/ChangeLog:

	PR rtl-optimization/100225
	PR rtl-optimization/84878
	* gcc.dg/pr100225.c: New test.

libgomp/ChangeLog:

	* testsuite/libgomp.oacc-c-c++-common/atomic_capture-3.c: New test.
This commit is contained in:
Roman Zhuykov 2021-04-30 11:08:03 +03:00
parent 17f2908fcf
commit 4cf3b10f27
3 changed files with 1676 additions and 20 deletions

View File

@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "dbgcnt.h"
#include "loop-unroll.h"
#include "hard-reg-set.h"
#ifdef INSN_SCHEDULING
@ -1356,6 +1357,7 @@ sms_schedule (void)
basic_block condition_bb = NULL;
edge latch_edge;
HOST_WIDE_INT trip_count, max_trip_count;
HARD_REG_SET prohibited_regs;
loop_optimizer_init (LOOPS_HAVE_PREHEADERS
| LOOPS_HAVE_RECORDED_EXITS);
@ -1385,6 +1387,8 @@ sms_schedule (void)
We use loop->num as index into this array. */
g_arr = XCNEWVEC (ddg_ptr, number_of_loops (cfun));
REG_SET_TO_HARD_REG_SET (prohibited_regs, &df->regular_block_artificial_uses);
if (dump_file)
{
fprintf (dump_file, "\n\nSMS analysis phase\n");
@ -1469,23 +1473,31 @@ sms_schedule (void)
}
/* Don't handle BBs with calls or barriers
or !single_set with the exception of instructions that include
count_reg---these instructions are part of the control part
that do-loop recognizes.
or !single_set with the exception of do-loop control part insns.
??? Should handle insns defining subregs. */
for (insn = head; insn != NEXT_INSN (tail); insn = NEXT_INSN (insn))
{
rtx set;
for (insn = head; insn != NEXT_INSN (tail); insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
{
HARD_REG_SET regs;
CLEAR_HARD_REG_SET (regs);
note_stores (insn, record_hard_reg_sets, &regs);
if (hard_reg_set_intersect_p (regs, prohibited_regs))
break;
}
if (CALL_P (insn)
|| BARRIER_P (insn)
|| (NONDEBUG_INSN_P (insn) && !JUMP_P (insn)
&& !single_set (insn) && GET_CODE (PATTERN (insn)) != USE
&& !reg_mentioned_p (count_reg, insn))
|| (INSN_P (insn) && (set = single_set (insn))
&& GET_CODE (SET_DEST (set)) == SUBREG))
break;
}
if (CALL_P (insn)
|| BARRIER_P (insn)
|| (INSN_P (insn) && single_set (insn)
&& GET_CODE (SET_DEST (single_set (insn))) == SUBREG)
/* Not a single set. */
|| (NONDEBUG_INSN_P (insn) && !JUMP_P (insn)
&& !single_set (insn) && GET_CODE (PATTERN (insn)) != USE
/* But non-single-set allowed in one special case. */
&& (insn != prev_nondebug_insn (tail)
|| !reg_mentioned_p (count_reg, insn))))
break;
}
if (insn != NEXT_INSN (tail))
{
@ -1495,11 +1507,13 @@ sms_schedule (void)
fprintf (dump_file, "SMS loop-with-call\n");
else if (BARRIER_P (insn))
fprintf (dump_file, "SMS loop-with-barrier\n");
else if ((NONDEBUG_INSN_P (insn) && !JUMP_P (insn)
&& !single_set (insn) && GET_CODE (PATTERN (insn)) != USE))
fprintf (dump_file, "SMS loop-with-not-single-set\n");
else
fprintf (dump_file, "SMS loop with subreg in lhs\n");
else if (INSN_P (insn) && single_set (insn)
&& GET_CODE (SET_DEST (single_set (insn))) == SUBREG)
fprintf (dump_file, "SMS loop with subreg in lhs\n");
else
fprintf (dump_file,
"SMS loop-with-not-single-set-or-prohibited-reg\n");
print_rtl_single (dump_file, insn);
}

View File

@ -0,0 +1,15 @@
/* PR rtl-optimization/100225 */
/* { dg-do compile } */
/* { dg-options "-O1 -fmodulo-sched" } */
void
vorbis_synthesis_lapout (void);
void
ov_info (int **lappcm, int ov_info_i)
{
while (ov_info_i < 1)
lappcm[ov_info_i++] = __builtin_alloca (1);
vorbis_synthesis_lapout ();
}

File diff suppressed because it is too large Load Diff