* [reviewed] qsort comparator consistency checking
@ 2017-09-29 13:29 Alexander Monakov
2017-09-29 17:46 ` Christophe Lyon
0 siblings, 1 reply; 7+ messages in thread
From: Alexander Monakov @ 2017-09-29 13:29 UTC (permalink / raw)
To: gcc-patches
Hello,
I'm going to install the following patch on trunk in the next few hours.
This revision doesn't offer per-callsite opt-out anymore as suggested by
Richi on the Cauldron (made possible by fixing all known issues on trunk).
Thus this patch has a few minor differences compared to the previous
revision that was ack'ed by Jeff.
Tested on x86_64-linux, i686-linux and ppc64le-linux.
Alexander
* genmodes.c (calc_wider_mode): Suppress qsort macro.
* system.h [CHECKING_P] (qsort): Redirect to qsort_chk.
(qsort_chk): Declare.
* vec.c [CHECKING_P] (qsort_chk_error): New static function.
(qsort_chk): New function.
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index 97ed949c255..4eb8ee56d88 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -880,7 +880,7 @@ calc_wider_mode (void)
for (i = 0, m = modes[c]; m; i++, m = m->next)
sortbuf[i] = m;
- qsort (sortbuf, i, sizeof (struct mode_data *), cmp_modes);
+ (qsort) (sortbuf, i, sizeof (struct mode_data *), cmp_modes);
sortbuf[i] = 0;
for (j = 0; j < i; j++)
diff --git a/gcc/system.h b/gcc/system.h
index 59449f1942b..f0664e93fc8 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -1181,4 +1181,14 @@ helper_const_non_const_cast (const char *p)
/* Get definitions of HOST_WIDE_INT. */
#include "hwint.h"
+/* qsort comparator consistency checking: except in release-checking compilers,
+ redirect 4-argument qsort calls to qsort_chk; keep 1-argument invocations
+ corresponding to vec::qsort (cmp): they use C qsort internally anyway. */
+#if CHECKING_P
+#define PP_5th(a1, a2, a3, a4, a5, ...) a5
+#undef qsort
+#define qsort(...) PP_5th (__VA_ARGS__, qsort_chk, 3, 2, qsort, 0) (__VA_ARGS__)
+void qsort_chk (void *, size_t, size_t, int (*)(const void *, const void *));
+#endif
+
#endif /* ! GCC_SYSTEM_H */
diff --git a/gcc/vec.c b/gcc/vec.c
index d612703184b..9a80f3421db 100644
--- a/gcc/vec.c
+++ b/gcc/vec.c
@@ -31,6 +31,12 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "hash-table.h"
#include "selftest.h"
+#ifdef GENERATOR_FILE
+#include "errors.h"
+#else
+#include "input.h"
+#include "diagnostic-core.h"
+#endif
/* vNULL is an empty type with a template cast operation that returns
a zero-initialized vec<T, A, L> instance. Use this when you want
@@ -190,6 +196,93 @@ dump_vec_loc_statistics (void)
vec_mem_desc.dump (VEC_ORIGIN);
}
+#if CHECKING_P
+/* Report qsort comparator CMP consistency check failure with P1, P2, P3 as
+ witness elements. */
+ATTRIBUTE_NORETURN ATTRIBUTE_COLD
+static void
+qsort_chk_error (const void *p1, const void *p2, const void *p3,
+ int (*cmp) (const void *, const void *))
+{
+ if (!p3)
+ {
+ int r1 = cmp (p1, p2), r2 = cmp (p2, p1);
+ error ("qsort comparator not anti-commutative: %d, %d", r1, r2);
+ }
+ else if (p1 == p2)
+ {
+ int r = cmp (p1, p3);
+ error ("qsort comparator non-negative on sorted output: %d", r);
+ }
+ else
+ {
+ int r1 = cmp (p1, p2), r2 = cmp (p2, p3), r3 = cmp (p1, p3);
+ error ("qsort comparator not transitive: %d, %d, %d", r1, r2, r3);
+ }
+ internal_error ("qsort checking failed");
+}
+
+/* Wrapper around qsort with checking that CMP is consistent on given input.
+
+ Strictly speaking, passing invalid (non-transitive, non-anti-commutative)
+ comparators to libc qsort can result in undefined behavior. Therefore we
+ should ideally perform consistency checks prior to invoking qsort, but in
+ order to do that optimally we'd need to sort the array ourselves beforehand
+ with a sorting routine known to be "safe". Instead, we expect that most
+ implementations in practice will still produce some permutation of input
+ array even for invalid comparators, which enables us to perform checks on
+ the output array. */
+void
+qsort_chk (void *base, size_t n, size_t size,
+ int (*cmp)(const void *, const void *))
+{
+ (qsort) (base, n, size, cmp);
+#if 0
+#define LIM(n) (n)
+#else
+ /* Limit overall time complexity to O(n log n). */
+#define LIM(n) ((n) <= 16 ? (n) : 12 + floor_log2 (n))
+#endif
+#define ELT(i) ((const char *) base + (i) * size)
+#define CMP(i, j) cmp (ELT (i), ELT (j))
+#define ERR2(i, j) qsort_chk_error (ELT (i), ELT (j), NULL, cmp)
+#define ERR3(i, j, k) qsort_chk_error (ELT (i), ELT (j), ELT (k), cmp)
+ size_t i1, i2, i, j;
+ /* This outer loop iterates over maximum spans [i1, i2) such that
+ elements within each span compare equal to each other. */
+ for (i1 = 0; i1 < n; i1 = i2)
+ {
+ /* Position i2 one past last element that compares equal to i1'th. */
+ for (i2 = i1 + 1; i2 < n; i2++)
+ if (CMP (i1, i2))
+ break;
+ else if (CMP (i2, i1))
+ return ERR2 (i1, i2);
+ size_t lim1 = LIM (i2 - i1), lim2 = LIM (n - i2);
+ /* Verify that other pairs within current span compare equal. */
+ for (i = i1 + 1; i + 1 < i2; i++)
+ for (j = i + 1; j < i1 + lim1; j++)
+ if (CMP (i, j))
+ return ERR3 (i, i1, j);
+ else if (CMP (j, i))
+ return ERR2 (i, j);
+ /* Verify that elements within this span compare less than
+ elements beyond the span. */
+ for (i = i1; i < i2; i++)
+ for (j = i2; j < i2 + lim2; j++)
+ if (CMP (i, j) >= 0)
+ return ERR3 (i, i1, j);
+ else if (CMP (j, i) <= 0)
+ return ERR2 (i, j);
+ }
+#undef ERR3
+#undef ERR2
+#undef CMP
+#undef ELT
+#undef LIM
+}
+#endif /* #if CHECKING_P */
+
#ifndef GENERATOR_FILE
#if CHECKING_P
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [reviewed] qsort comparator consistency checking 2017-09-29 13:29 [reviewed] qsort comparator consistency checking Alexander Monakov @ 2017-09-29 17:46 ` Christophe Lyon 2017-09-29 17:58 ` Andrew Pinski 0 siblings, 1 reply; 7+ messages in thread From: Christophe Lyon @ 2017-09-29 17:46 UTC (permalink / raw) To: Alexander Monakov; +Cc: gcc-patches Hi, On 29 September 2017 at 15:29, Alexander Monakov <amonakov@ispras.ru> wrote: > Hello, > > I'm going to install the following patch on trunk in the next few hours. > This revision doesn't offer per-callsite opt-out anymore as suggested by > Richi on the Cauldron (made possible by fixing all known issues on trunk). > Thus this patch has a few minor differences compared to the previous > revision that was ack'ed by Jeff. > > Tested on x86_64-linux, i686-linux and ppc64le-linux. > > Alexander > > * genmodes.c (calc_wider_mode): Suppress qsort macro. > * system.h [CHECKING_P] (qsort): Redirect to qsort_chk. > (qsort_chk): Declare. > * vec.c [CHECKING_P] (qsort_chk_error): New static function. > (qsort_chk): New function. > This patch (r253295) breaks the gcc build for aarch64-linux-gnu: libtool: compile: /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/./gcc/xgcc -shared-libgcc -B/tmp/3041688_6.t mpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/./gcc -nostdinc++ -L/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj -aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/src -L/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-g nu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/src/.libs -L/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64 -none-linux-gnu/libstdc++-v3/libsupc++/.libs -B/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/tools/aarch64-none-linux-gnu/bin/ -B/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/tools/aarch64-none-linux-gnu/lib/ -isystem /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/tools/aarch64-none-linux-gnu/include -isystem /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/tools/aarch64-none-linux-gnu/sys-include -I/tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/../libgcc -I/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/aarch64-none-linux-gnu -I/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include -I/tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++ -D_GLIBCXX_SHARED -std=gnu++14 -Wall -Wextra -Wwrite-strings -Wcast-qual -Wabi -fdiagnostics-show-location=once -ffunction-sections -fdata-sections -frandom-seed=ops.lo -g -O2 -D_GNU_SOURCE -c /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/src/filesystem/ops.cc -fPIC -DPIC -D_GLIBCXX_SHARED -o ops.o In file included from /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/deque:66:0, from /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/stack:60, from /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/src/filesystem/ops.cc:32: /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/bits/deque.tcc: In member function 'void std::deque<_Tp, _Alloc>::_M_range_insert_aux(std::deque<_Tp, _Alloc>::iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = std::experimental::filesystem::v1::__cxx11::path::iterator; _Tp = std::experimental::filesystem::v1::__cxx11::path; _Alloc = std::allocator<std::experimental::filesystem::v1::__cxx11::path>]': /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/bits/deque.tcc:626:7: error: qsort comparator non-negative on sorted output: 8 } ^ during RTL pass: sched2 /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/bits/deque.tcc:626:7: internal compiler error: qsort checking failed 0x55f7a1 qsort_chk_error /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/vec.c:222 0x15337d8 qsort_chk(void*, unsigned long, unsigned long, int (*)(void const*, void const*)) /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/vec.c:274 0x14360e0 ready_sort_real /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/haifa-sched.c:3087 0x143de85 schedule_block(basic_block_def**, void*) /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/haifa-sched.c:6749 0xd42132 schedule_region /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/sched-rgn.c:3174 0xd42132 schedule_insns() /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/sched-rgn.c:3513 0xd424ee rest_of_handle_sched2 /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/sched-rgn.c:3737 0xd424ee execute /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/sched-rgn.c:3873 Christophe > diff --git a/gcc/genmodes.c b/gcc/genmodes.c > index 97ed949c255..4eb8ee56d88 100644 > --- a/gcc/genmodes.c > +++ b/gcc/genmodes.c > @@ -880,7 +880,7 @@ calc_wider_mode (void) > for (i = 0, m = modes[c]; m; i++, m = m->next) > sortbuf[i] = m; > > - qsort (sortbuf, i, sizeof (struct mode_data *), cmp_modes); > + (qsort) (sortbuf, i, sizeof (struct mode_data *), cmp_modes); > > sortbuf[i] = 0; > for (j = 0; j < i; j++) > diff --git a/gcc/system.h b/gcc/system.h > index 59449f1942b..f0664e93fc8 100644 > --- a/gcc/system.h > +++ b/gcc/system.h > @@ -1181,4 +1181,14 @@ helper_const_non_const_cast (const char *p) > /* Get definitions of HOST_WIDE_INT. */ > #include "hwint.h" > > +/* qsort comparator consistency checking: except in release-checking compilers, > + redirect 4-argument qsort calls to qsort_chk; keep 1-argument invocations > + corresponding to vec::qsort (cmp): they use C qsort internally anyway. */ > +#if CHECKING_P > +#define PP_5th(a1, a2, a3, a4, a5, ...) a5 > +#undef qsort > +#define qsort(...) PP_5th (__VA_ARGS__, qsort_chk, 3, 2, qsort, 0) (__VA_ARGS__) > +void qsort_chk (void *, size_t, size_t, int (*)(const void *, const void *)); > +#endif > + > #endif /* ! GCC_SYSTEM_H */ > diff --git a/gcc/vec.c b/gcc/vec.c > index d612703184b..9a80f3421db 100644 > --- a/gcc/vec.c > +++ b/gcc/vec.c > @@ -31,6 +31,12 @@ along with GCC; see the file COPYING3. If not see > #include "coretypes.h" > #include "hash-table.h" > #include "selftest.h" > +#ifdef GENERATOR_FILE > +#include "errors.h" > +#else > +#include "input.h" > +#include "diagnostic-core.h" > +#endif > > /* vNULL is an empty type with a template cast operation that returns > a zero-initialized vec<T, A, L> instance. Use this when you want > @@ -190,6 +196,93 @@ dump_vec_loc_statistics (void) > vec_mem_desc.dump (VEC_ORIGIN); > } > > +#if CHECKING_P > +/* Report qsort comparator CMP consistency check failure with P1, P2, P3 as > + witness elements. */ > +ATTRIBUTE_NORETURN ATTRIBUTE_COLD > +static void > +qsort_chk_error (const void *p1, const void *p2, const void *p3, > + int (*cmp) (const void *, const void *)) > +{ > + if (!p3) > + { > + int r1 = cmp (p1, p2), r2 = cmp (p2, p1); > + error ("qsort comparator not anti-commutative: %d, %d", r1, r2); > + } > + else if (p1 == p2) > + { > + int r = cmp (p1, p3); > + error ("qsort comparator non-negative on sorted output: %d", r); > + } > + else > + { > + int r1 = cmp (p1, p2), r2 = cmp (p2, p3), r3 = cmp (p1, p3); > + error ("qsort comparator not transitive: %d, %d, %d", r1, r2, r3); > + } > + internal_error ("qsort checking failed"); > +} > + > +/* Wrapper around qsort with checking that CMP is consistent on given input. > + > + Strictly speaking, passing invalid (non-transitive, non-anti-commutative) > + comparators to libc qsort can result in undefined behavior. Therefore we > + should ideally perform consistency checks prior to invoking qsort, but in > + order to do that optimally we'd need to sort the array ourselves beforehand > + with a sorting routine known to be "safe". Instead, we expect that most > + implementations in practice will still produce some permutation of input > + array even for invalid comparators, which enables us to perform checks on > + the output array. */ > +void > +qsort_chk (void *base, size_t n, size_t size, > + int (*cmp)(const void *, const void *)) > +{ > + (qsort) (base, n, size, cmp); > +#if 0 > +#define LIM(n) (n) > +#else > + /* Limit overall time complexity to O(n log n). */ > +#define LIM(n) ((n) <= 16 ? (n) : 12 + floor_log2 (n)) > +#endif > +#define ELT(i) ((const char *) base + (i) * size) > +#define CMP(i, j) cmp (ELT (i), ELT (j)) > +#define ERR2(i, j) qsort_chk_error (ELT (i), ELT (j), NULL, cmp) > +#define ERR3(i, j, k) qsort_chk_error (ELT (i), ELT (j), ELT (k), cmp) > + size_t i1, i2, i, j; > + /* This outer loop iterates over maximum spans [i1, i2) such that > + elements within each span compare equal to each other. */ > + for (i1 = 0; i1 < n; i1 = i2) > + { > + /* Position i2 one past last element that compares equal to i1'th. */ > + for (i2 = i1 + 1; i2 < n; i2++) > + if (CMP (i1, i2)) > + break; > + else if (CMP (i2, i1)) > + return ERR2 (i1, i2); > + size_t lim1 = LIM (i2 - i1), lim2 = LIM (n - i2); > + /* Verify that other pairs within current span compare equal. */ > + for (i = i1 + 1; i + 1 < i2; i++) > + for (j = i + 1; j < i1 + lim1; j++) > + if (CMP (i, j)) > + return ERR3 (i, i1, j); > + else if (CMP (j, i)) > + return ERR2 (i, j); > + /* Verify that elements within this span compare less than > + elements beyond the span. */ > + for (i = i1; i < i2; i++) > + for (j = i2; j < i2 + lim2; j++) > + if (CMP (i, j) >= 0) > + return ERR3 (i, i1, j); > + else if (CMP (j, i) <= 0) > + return ERR2 (i, j); > + } > +#undef ERR3 > +#undef ERR2 > +#undef CMP > +#undef ELT > +#undef LIM > +} > +#endif /* #if CHECKING_P */ > + > #ifndef GENERATOR_FILE > #if CHECKING_P > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [reviewed] qsort comparator consistency checking 2017-09-29 17:46 ` Christophe Lyon @ 2017-09-29 17:58 ` Andrew Pinski 2017-09-29 18:14 ` Alexander Monakov 0 siblings, 1 reply; 7+ messages in thread From: Andrew Pinski @ 2017-09-29 17:58 UTC (permalink / raw) To: Christophe Lyon; +Cc: Alexander Monakov, gcc-patches On Fri, Sep 29, 2017 at 10:46 AM, Christophe Lyon <christophe.lyon@linaro.org> wrote: > Hi, > > > On 29 September 2017 at 15:29, Alexander Monakov <amonakov@ispras.ru> wrote: >> Hello, >> >> I'm going to install the following patch on trunk in the next few hours. >> This revision doesn't offer per-callsite opt-out anymore as suggested by >> Richi on the Cauldron (made possible by fixing all known issues on trunk). >> Thus this patch has a few minor differences compared to the previous >> revision that was ack'ed by Jeff. >> >> Tested on x86_64-linux, i686-linux and ppc64le-linux. >> >> Alexander >> >> * genmodes.c (calc_wider_mode): Suppress qsort macro. >> * system.h [CHECKING_P] (qsort): Redirect to qsort_chk. >> (qsort_chk): Declare. >> * vec.c [CHECKING_P] (qsort_chk_error): New static function. >> (qsort_chk): New function. >> > > This patch (r253295) breaks the gcc build for aarch64-linux-gnu: I was just about to report the same thing. Thanks, Andrew > libtool: compile: > /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/./gcc/xgcc > -shared-libgcc -B/tmp/3041688_6.t > mpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/./gcc > -nostdinc++ -L/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj > -aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/src > -L/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-g > nu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/src/.libs > -L/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64 > -none-linux-gnu/libstdc++-v3/libsupc++/.libs > -B/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/tools/aarch64-none-linux-gnu/bin/ > -B/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/tools/aarch64-none-linux-gnu/lib/ > -isystem /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/tools/aarch64-none-linux-gnu/include > -isystem /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/tools/aarch64-none-linux-gnu/sys-include > -I/tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/../libgcc > -I/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/aarch64-none-linux-gnu > -I/tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include > -I/tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++ > -D_GLIBCXX_SHARED -std=gnu++14 -Wall -Wextra -Wwrite-strings > -Wcast-qual -Wabi -fdiagnostics-show-location=once -ffunction-sections > -fdata-sections -frandom-seed=ops.lo -g -O2 -D_GNU_SOURCE -c > /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/src/filesystem/ops.cc > -fPIC -DPIC -D_GLIBCXX_SHARED -o ops.o > In file included from > /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/deque:66:0, > from > /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/stack:60, > from > /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/src/filesystem/ops.cc:32: > /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/bits/deque.tcc: > In member function 'void std::deque<_Tp, > _Alloc>::_M_range_insert_aux(std::deque<_Tp, _Alloc>::iterator, > _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with > _ForwardIterator = > std::experimental::filesystem::v1::__cxx11::path::iterator; _Tp = > std::experimental::filesystem::v1::__cxx11::path; _Alloc = > std::allocator<std::experimental::filesystem::v1::__cxx11::path>]': > /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/bits/deque.tcc:626:7: > error: qsort comparator non-negative on sorted output: 8 > } > ^ > during RTL pass: sched2 > /tmp/3041688_6.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-aarch64-none-linux-gnu/gcc3/aarch64-none-linux-gnu/libstdc++-v3/include/bits/deque.tcc:626:7: > internal compiler error: qsort checking failed > 0x55f7a1 qsort_chk_error > /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/vec.c:222 > 0x15337d8 qsort_chk(void*, unsigned long, unsigned long, int (*)(void > const*, void const*)) > /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/vec.c:274 > 0x14360e0 ready_sort_real > /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/haifa-sched.c:3087 > 0x143de85 schedule_block(basic_block_def**, void*) > /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/haifa-sched.c:6749 > 0xd42132 schedule_region > /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/sched-rgn.c:3174 > 0xd42132 schedule_insns() > /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/sched-rgn.c:3513 > 0xd424ee rest_of_handle_sched2 > /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/sched-rgn.c:3737 > 0xd424ee execute > /tmp/3041688_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/sched-rgn.c:3873 > > Christophe > >> diff --git a/gcc/genmodes.c b/gcc/genmodes.c >> index 97ed949c255..4eb8ee56d88 100644 >> --- a/gcc/genmodes.c >> +++ b/gcc/genmodes.c >> @@ -880,7 +880,7 @@ calc_wider_mode (void) >> for (i = 0, m = modes[c]; m; i++, m = m->next) >> sortbuf[i] = m; >> >> - qsort (sortbuf, i, sizeof (struct mode_data *), cmp_modes); >> + (qsort) (sortbuf, i, sizeof (struct mode_data *), cmp_modes); >> >> sortbuf[i] = 0; >> for (j = 0; j < i; j++) >> diff --git a/gcc/system.h b/gcc/system.h >> index 59449f1942b..f0664e93fc8 100644 >> --- a/gcc/system.h >> +++ b/gcc/system.h >> @@ -1181,4 +1181,14 @@ helper_const_non_const_cast (const char *p) >> /* Get definitions of HOST_WIDE_INT. */ >> #include "hwint.h" >> >> +/* qsort comparator consistency checking: except in release-checking compilers, >> + redirect 4-argument qsort calls to qsort_chk; keep 1-argument invocations >> + corresponding to vec::qsort (cmp): they use C qsort internally anyway. */ >> +#if CHECKING_P >> +#define PP_5th(a1, a2, a3, a4, a5, ...) a5 >> +#undef qsort >> +#define qsort(...) PP_5th (__VA_ARGS__, qsort_chk, 3, 2, qsort, 0) (__VA_ARGS__) >> +void qsort_chk (void *, size_t, size_t, int (*)(const void *, const void *)); >> +#endif >> + >> #endif /* ! GCC_SYSTEM_H */ >> diff --git a/gcc/vec.c b/gcc/vec.c >> index d612703184b..9a80f3421db 100644 >> --- a/gcc/vec.c >> +++ b/gcc/vec.c >> @@ -31,6 +31,12 @@ along with GCC; see the file COPYING3. If not see >> #include "coretypes.h" >> #include "hash-table.h" >> #include "selftest.h" >> +#ifdef GENERATOR_FILE >> +#include "errors.h" >> +#else >> +#include "input.h" >> +#include "diagnostic-core.h" >> +#endif >> >> /* vNULL is an empty type with a template cast operation that returns >> a zero-initialized vec<T, A, L> instance. Use this when you want >> @@ -190,6 +196,93 @@ dump_vec_loc_statistics (void) >> vec_mem_desc.dump (VEC_ORIGIN); >> } >> >> +#if CHECKING_P >> +/* Report qsort comparator CMP consistency check failure with P1, P2, P3 as >> + witness elements. */ >> +ATTRIBUTE_NORETURN ATTRIBUTE_COLD >> +static void >> +qsort_chk_error (const void *p1, const void *p2, const void *p3, >> + int (*cmp) (const void *, const void *)) >> +{ >> + if (!p3) >> + { >> + int r1 = cmp (p1, p2), r2 = cmp (p2, p1); >> + error ("qsort comparator not anti-commutative: %d, %d", r1, r2); >> + } >> + else if (p1 == p2) >> + { >> + int r = cmp (p1, p3); >> + error ("qsort comparator non-negative on sorted output: %d", r); >> + } >> + else >> + { >> + int r1 = cmp (p1, p2), r2 = cmp (p2, p3), r3 = cmp (p1, p3); >> + error ("qsort comparator not transitive: %d, %d, %d", r1, r2, r3); >> + } >> + internal_error ("qsort checking failed"); >> +} >> + >> +/* Wrapper around qsort with checking that CMP is consistent on given input. >> + >> + Strictly speaking, passing invalid (non-transitive, non-anti-commutative) >> + comparators to libc qsort can result in undefined behavior. Therefore we >> + should ideally perform consistency checks prior to invoking qsort, but in >> + order to do that optimally we'd need to sort the array ourselves beforehand >> + with a sorting routine known to be "safe". Instead, we expect that most >> + implementations in practice will still produce some permutation of input >> + array even for invalid comparators, which enables us to perform checks on >> + the output array. */ >> +void >> +qsort_chk (void *base, size_t n, size_t size, >> + int (*cmp)(const void *, const void *)) >> +{ >> + (qsort) (base, n, size, cmp); >> +#if 0 >> +#define LIM(n) (n) >> +#else >> + /* Limit overall time complexity to O(n log n). */ >> +#define LIM(n) ((n) <= 16 ? (n) : 12 + floor_log2 (n)) >> +#endif >> +#define ELT(i) ((const char *) base + (i) * size) >> +#define CMP(i, j) cmp (ELT (i), ELT (j)) >> +#define ERR2(i, j) qsort_chk_error (ELT (i), ELT (j), NULL, cmp) >> +#define ERR3(i, j, k) qsort_chk_error (ELT (i), ELT (j), ELT (k), cmp) >> + size_t i1, i2, i, j; >> + /* This outer loop iterates over maximum spans [i1, i2) such that >> + elements within each span compare equal to each other. */ >> + for (i1 = 0; i1 < n; i1 = i2) >> + { >> + /* Position i2 one past last element that compares equal to i1'th. */ >> + for (i2 = i1 + 1; i2 < n; i2++) >> + if (CMP (i1, i2)) >> + break; >> + else if (CMP (i2, i1)) >> + return ERR2 (i1, i2); >> + size_t lim1 = LIM (i2 - i1), lim2 = LIM (n - i2); >> + /* Verify that other pairs within current span compare equal. */ >> + for (i = i1 + 1; i + 1 < i2; i++) >> + for (j = i + 1; j < i1 + lim1; j++) >> + if (CMP (i, j)) >> + return ERR3 (i, i1, j); >> + else if (CMP (j, i)) >> + return ERR2 (i, j); >> + /* Verify that elements within this span compare less than >> + elements beyond the span. */ >> + for (i = i1; i < i2; i++) >> + for (j = i2; j < i2 + lim2; j++) >> + if (CMP (i, j) >= 0) >> + return ERR3 (i, i1, j); >> + else if (CMP (j, i) <= 0) >> + return ERR2 (i, j); >> + } >> +#undef ERR3 >> +#undef ERR2 >> +#undef CMP >> +#undef ELT >> +#undef LIM >> +} >> +#endif /* #if CHECKING_P */ >> + >> #ifndef GENERATOR_FILE >> #if CHECKING_P >> ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [reviewed] qsort comparator consistency checking 2017-09-29 17:58 ` Andrew Pinski @ 2017-09-29 18:14 ` Alexander Monakov 2017-09-29 19:39 ` Steve Ellcey 0 siblings, 1 reply; 7+ messages in thread From: Alexander Monakov @ 2017-09-29 18:14 UTC (permalink / raw) To: Andrew Pinski; +Cc: Christophe Lyon, gcc-patches On Fri, 29 Sep 2017, Andrew Pinski wrote: > > This patch (r253295) breaks the gcc build for aarch64-linux-gnu: > > I was just about to report the same thing. I think autoprefetch ranking heuristic is still wrong if multi_mem_insn_p may be true; please try this patch. * haifa-sched.c (autopref_rank_data): Remove. (autopref_rank_for_schedule): Only use min_offset difference. diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 549e8961411..cea1242e1f1 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -5647,62 +5647,6 @@ autopref_multipass_init (const rtx_insn *insn, int write) } -/* Helper for autopref_rank_for_schedule. Given the data of two - insns relevant to the auto-prefetcher modelling code DATA1 and DATA2 - return their comparison result. Return 0 if there is no sensible - ranking order for the two insns. */ - -static int -autopref_rank_data (autopref_multipass_data_t data1, - autopref_multipass_data_t data2) -{ - /* Simple case when both insns are simple single memory ops. */ - if (!data1->multi_mem_insn_p && !data2->multi_mem_insn_p) - return data1->min_offset - data2->min_offset; - - /* Two load/store multiple insns. Return 0 if the offset ranges - overlap and the difference between the minimum offsets otherwise. */ - else if (data1->multi_mem_insn_p && data2->multi_mem_insn_p) - { - int min1 = data1->min_offset; - int max1 = data1->max_offset; - int min2 = data2->min_offset; - int max2 = data2->max_offset; - - if (max1 < min2 || min1 > max2) - return min1 - min2; - else - return 0; - } - - /* The other two cases is a pair of a load/store multiple and - a simple memory op. Return 0 if the single op's offset is within the - range of the multi-op insn and the difference between the single offset - and the minimum offset of the multi-set insn otherwise. */ - else if (data1->multi_mem_insn_p && !data2->multi_mem_insn_p) - { - int max1 = data1->max_offset; - int min1 = data1->min_offset; - - if (data2->min_offset >= min1 - && data2->min_offset <= max1) - return 0; - else - return min1 - data2->min_offset; - } - else - { - int max2 = data2->max_offset; - int min2 = data2->min_offset; - - if (data1->min_offset >= min2 - && data1->min_offset <= max2) - return 0; - else - return data1->min_offset - min2; - } -} - /* Helper function for rank_for_schedule sorting. */ static int autopref_rank_for_schedule (const rtx_insn *insn1, const rtx_insn *insn2) @@ -5725,7 +5669,7 @@ autopref_rank_for_schedule (const rtx_insn *insn1, const rtx_insn *insn2) int irrel2 = data2->status == AUTOPREF_MULTIPASS_DATA_IRRELEVANT; if (!irrel1 && !irrel2) - r = autopref_rank_data (data1, data2); + r = data1->min_offset - data2->min_offset; else r = irrel2 - irrel1; } ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [reviewed] qsort comparator consistency checking 2017-09-29 18:14 ` Alexander Monakov @ 2017-09-29 19:39 ` Steve Ellcey 2017-09-29 19:43 ` Christophe Lyon 0 siblings, 1 reply; 7+ messages in thread From: Steve Ellcey @ 2017-09-29 19:39 UTC (permalink / raw) To: Alexander Monakov, Andrew Pinski; +Cc: Christophe Lyon, gcc-patches On Fri, 2017-09-29 at 21:14 +0300, Alexander Monakov wrote: > On Fri, 29 Sep 2017, Andrew Pinski wrote: > > > > > > > > This patch (r253295) breaks the gcc build for aarch64-linux-gnu: > > I was just about to report the same thing. > I think autoprefetch ranking heuristic is still wrong if > multi_mem_insn_p > may be true; please try this patch. > > * haifa-sched.c (autopref_rank_data): Remove. > (autopref_rank_for_schedule): Only use min_offset difference. This fixed the build for me on aarch64. Â I am still running the testsuite. Steve Ellcey sellcey@cavium.com ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [reviewed] qsort comparator consistency checking 2017-09-29 19:39 ` Steve Ellcey @ 2017-09-29 19:43 ` Christophe Lyon 2017-09-29 19:46 ` Steve Ellcey 0 siblings, 1 reply; 7+ messages in thread From: Christophe Lyon @ 2017-09-29 19:43 UTC (permalink / raw) To: sellcey; +Cc: Alexander Monakov, Andrew Pinski, gcc-patches On 29 September 2017 at 21:39, Steve Ellcey <sellcey@cavium.com> wrote: > On Fri, 2017-09-29 at 21:14 +0300, Alexander Monakov wrote: >> On Fri, 29 Sep 2017, Andrew Pinski wrote: >> > >> > > >> > > This patch (r253295) breaks the gcc build for aarch64-linux-gnu: >> > I was just about to report the same thing. >> I think autoprefetch ranking heuristic is still wrong if >> multi_mem_insn_p >> may be true; please try this patch. >> >> * haifa-sched.c (autopref_rank_data): Remove. >> (autopref_rank_for_schedule): Only use min_offset difference. > > This fixed the build for me on aarch64. I am still running the > testsuite. > It doesn't for me. I'm getting another build error: /home/christophe.lyon/src/GCC/sources/gcc-fsf/aarch64-build/gcc/haifa-sched.c: In function ‘int autopref_multipass_dfa_lookahead_guard_1(const rtx_insn*, const rtx_insn*, int)’: /home/christophe.lyon/src/GCC/sources/gcc-fsf/aarch64-build/gcc/haifa-sched.c:5700:42: error: ‘autopref_rank_data’ was not declared in this scope The removed autopref_rank_data function is still called by autopref_multipass_dfa_lookahead_guard_1. Christophe > Steve Ellcey > sellcey@cavium.com ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [reviewed] qsort comparator consistency checking 2017-09-29 19:43 ` Christophe Lyon @ 2017-09-29 19:46 ` Steve Ellcey 0 siblings, 0 replies; 7+ messages in thread From: Steve Ellcey @ 2017-09-29 19:46 UTC (permalink / raw) To: Christophe Lyon; +Cc: Alexander Monakov, Andrew Pinski, gcc-patches On Fri, 2017-09-29 at 21:43 +0200, Christophe Lyon wrote: > On 29 September 2017 at 21:39, Steve Ellcey <sellcey@cavium.com> > wrote: > > > > On Fri, 2017-09-29 at 21:14 +0300, Alexander Monakov wrote: > > > > > > On Fri, 29 Sep 2017, Andrew Pinski wrote: > > > > > > > > > > > > > > > > > > > > > > > This patch (r253295) breaks the gcc build for aarch64-linux- > > > > > gnu: > > > > I was just about to report the same thing. > > > I think autoprefetch ranking heuristic is still wrong if > > > multi_mem_insn_p > > > may be true; please try this patch. > > > > > >       * haifa-sched.c (autopref_rank_data): Remove. > > >       (autopref_rank_for_schedule): Only use min_offset > > > difference. > > This fixed the build for me on aarch64.  I am still running the > > testsuite. > > > It doesn't for me. I'm getting another build error: > /home/christophe.lyon/src/GCC/sources/gcc-fsf/aarch64- > build/gcc/haifa-sched.c: > In function âint autopref_multipass_dfa_lookahead_guard_1(const > rtx_insn*, const rtx_insn*, int)â: > /home/christophe.lyon/src/GCC/sources/gcc-fsf/aarch64- > build/gcc/haifa-sched.c:5700:42: > error: âautopref_rank_dataâ was not declared in this scope > > The removed autopref_rank_data function is still called by > autopref_multipass_dfa_lookahead_guard_1. OK, I actually cheated and removed the call but not the function itself because 'it couldn't possible matter, could it'?  :-) Steve Ellcey ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-09-29 19:46 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-09-29 13:29 [reviewed] qsort comparator consistency checking Alexander Monakov 2017-09-29 17:46 ` Christophe Lyon 2017-09-29 17:58 ` Andrew Pinski 2017-09-29 18:14 ` Alexander Monakov 2017-09-29 19:39 ` Steve Ellcey 2017-09-29 19:43 ` Christophe Lyon 2017-09-29 19:46 ` Steve Ellcey
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).