gcc-8.0.0-alpha20171217 snapshot (r255766) ICEs when compiling the following snippet w/ -O1 (-O2, -Os) -fschedule-insns -fselective-scheduling -fno-guess-branch-probability: void oh (long int qc, short int de) { { long int uf = 0; int *xu, *gx = &uf; p6: *gx = (qc == 0) ? -1 : (qc - uf); if (de == *gx) { ++*xu; de = *xu; } else de = qc; } goto p6; } % gcc-8.0.0-alpha20171217 -O1 -fschedule-insns -fselective-scheduling -fno-guess-branch-probability -c -w vugfco5g.c vugfco5g.c: In function 'oh': vugfco5g.c:20:1: error: qsort comparator non-negative on sorted output: 3 } ^ during RTL pass: sched1 vugfco5g.c:20:1: internal compiler error: qsort checking failed 0x829340 qsort_chk_error /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/vec.c:222 0x8293c7 qsort_chk(void*, unsigned long, unsigned long, int (*)(void const*, void const*)) /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/vec.c:274 0xd069c4 vec<_expr*, va_heap, vl_embed>::qsort(int (*)(void const*, void const*)) /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/vec.h:1050 0xd069c4 vec<_expr*, va_heap, vl_ptr>::qsort(int (*)(void const*, void const*)) /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/vec.h:1812 0xd069c4 fill_vec_av_set /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/sel-sched.c:3725 0xd089ea fill_ready_list /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/sel-sched.c:4022 0xd089ea find_best_expr /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/sel-sched.c:4382 0xd089ea fill_insns /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/sel-sched.c:5539 0xd0ae50 schedule_on_fences /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/sel-sched.c:7356 0xd0ae50 sel_sched_region_2 /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/sel-sched.c:7494 0xd0c588 sel_sched_region_1 /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/sel-sched.c:7536 0xd0c588 sel_sched_region(int) /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/sel-sched.c:7637 0xd0d5e1 run_selective_scheduling() /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/sel-sched.c:7713 0xcedadd rest_of_handle_sched /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/sched-rgn.c:3715 0xcedadd execute /var/tmp/portage/sys-devel/gcc-8.0.0_alpha20171217/work/gcc-8-20171217/gcc/sched-rgn.c:3825
Confirmed, started with r255607.
Thanks. So the fix for PR 82398 was incomplete. Here we have insns: i1: uid: 43 prio: 0 usefulness: 100% i2: uid: 20 prio: 3 usefulness: 0% i3: uid: 46 prio: 5 usefulness: 0% and sel_rank_for_schedule says i2 < i3 by priority difference, but i1 < i2 && i3 < i1 by uid difference (btw it appears that either the comment or the sense of the last tiebreaker is inverted). Now priority comparison code doesn't account for the possibility of priority being 0. I think we should either - simplify priority comparison to always compare by (prio + prio_adj) * use (in which case comparison i2<?>i3 will fall down to uid comparison), or - slightly expand it to always sort zero-usefulness exprs after non-zero ones (even when they have priority 0 like i1 in the example). Andrey, do you have a preference?
> (btw it appears that either the comment or the sense of the last tiebreaker is inverted) I have to take that back, I was confused by the unusual tmp vs. tmp2 order: sel_rank_for_schedule (const void *x, const void *y) { expr_t tmp = *(const expr_t *) y; expr_t tmp2 = *(const expr_t *) x; ... and the ordering sel_rank_for_schedule seeks to produce is "worse insns first, better last". The rest of the previous comment still stands.
(In reply to Alexander Monakov from comment #2) > Thanks. So the fix for PR 82398 was incomplete. Here we have insns: > > i1: uid: 43 prio: 0 usefulness: 100% > i2: uid: 20 prio: 3 usefulness: 0% > i3: uid: 46 prio: 5 usefulness: 0% > > and sel_rank_for_schedule says i2 < i3 by priority difference, but i1 < i2 > && i3 < i1 by uid difference (btw it appears that either the comment or the > sense of the last tiebreaker is inverted). Now priority comparison code > doesn't account for the possibility of priority being 0. > > I think we should either > - simplify priority comparison to always compare by (prio + prio_adj) * use > (in which case comparison i2<?>i3 will fall down to uid comparison), or > - slightly expand it to always sort zero-usefulness exprs after non-zero > ones (even when they have priority 0 like i1 in the example). > > Andrey, do you have a preference? I think the second choice is better as then we do not fall down to uids for different priorities. I was hoping we would not get a zero usefulness in real life with REG_BR_PROB_BASE equal to 10000... sigh.
Author: amonakov Date: Tue Dec 26 14:34:33 2017 New Revision: 256001 URL: https://gcc.gnu.org/viewcvs?rev=256001&root=gcc&view=rev Log: sel-sched: fix zero-usefulness case in sel_rank_for_schedule (PR 83513) PR rtl-optimization/83513 * sel-sched.c (sel_rank_for_schedule): Order by non-zero usefulness before priority comparison. Modified: trunk/gcc/ChangeLog trunk/gcc/sel-sched.c
Fixed.