You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
1
(21) |
|
2
(19) |
3
(33) |
4
(24) |
5
(18) |
6
(13) |
7
(22) |
8
(21) |
|
9
(38) |
10
(25) |
11
(20) |
12
(27) |
13
(43) |
14
(9) |
15
(19) |
|
16
(37) |
17
(19) |
18
(13) |
19
(11) |
20
(8) |
21
(11) |
22
(25) |
|
23
(21) |
24
(30) |
25
(18) |
26
(11) |
27
(10) |
28
(14) |
29
(40) |
|
30
(24) |
31
(14) |
|
|
|
|
|
|
From: <sv...@va...> - 2008-03-25 20:18:36
|
Author: bart
Date: 2008-03-25 20:18:40 +0000 (Tue, 25 Mar 2008)
New Revision: 7791
Log:
Updated test plan.
Modified:
trunk/exp-drd/Testing.txt
Modified: trunk/exp-drd/Testing.txt
===================================================================
--- trunk/exp-drd/Testing.txt 2008-03-25 19:16:20 UTC (rev 7790)
+++ trunk/exp-drd/Testing.txt 2008-03-25 20:18:40 UTC (rev 7791)
@@ -17,8 +17,9 @@
./vg-in-place --tool=exp-drd kate
./vg-in-place --trace-children=yes --tool=exp-drd knode
4. Test DRD with Firefox. First of all, build and install Firefox 3. Next,
- run the following command:
- LD_LIBRARY_PATH=$HOME/software/mozilla-build/dist/lib: ./vg-in-place --tool=exp-drd $HOME/software/mozilla-build/dist/bin/firefox-bin
+ run one of the following commands:
+ LD_LIBRARY_PATH=$HOME/firefox3/lib/firefox-3.0b4: ./vg-in-place --trace-children=yes --tool=exp-drd $HOME/firefox3/lib/firefox-3.0b4/firefox-bin
+ LD_LIBRARY_PATH=$HOME/software/mozilla-build/dist/lib: ./vg-in-place --trace-children=yes --tool=exp-drd $HOME/software/mozilla-build/dist/bin/firefox-bin
@@ -62,4 +63,5 @@
${SRC}/configure
make -s || exit $?
+make -s install || exit $?
------------------------------------------------------------
|
|
From: <sv...@va...> - 2008-03-25 19:16:16
|
Author: bart
Date: 2008-03-25 19:16:20 +0000 (Tue, 25 Mar 2008)
New Revision: 7790
Log:
Another small optimization.
Modified:
trunk/exp-drd/drd_bitmap.h
Modified: trunk/exp-drd/drd_bitmap.h
===================================================================
--- trunk/exp-drd/drd_bitmap.h 2008-03-25 18:51:06 UTC (rev 7789)
+++ trunk/exp-drd/drd_bitmap.h 2008-03-25 19:16:20 UTC (rev 7790)
@@ -434,8 +434,15 @@
struct bitmap2* bm2;
tl_assert(bm);
- if (! bm_cache_lookup(bm, a1, &bm2) || bm2 == 0)
+ if (bm_cache_lookup(bm, a1, &bm2))
{
+ if (bm2 == 0)
+ {
+ bm2 = bm2_insert(bm, a1);
+ }
+ }
+ else
+ {
bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
if (bm2ref)
{
|
|
From: <sv...@va...> - 2008-03-25 18:51:02
|
Author: bart
Date: 2008-03-25 18:51:06 +0000 (Tue, 25 Mar 2008)
New Revision: 7789
Log:
Cache misses too.
Modified:
trunk/exp-drd/drd_bitmap.c
trunk/exp-drd/drd_bitmap.h
Modified: trunk/exp-drd/drd_bitmap.c
===================================================================
--- trunk/exp-drd/drd_bitmap.c 2008-03-25 17:19:20 UTC (rev 7788)
+++ trunk/exp-drd/drd_bitmap.c 2008-03-25 18:51:06 UTC (rev 7789)
@@ -59,15 +59,18 @@
unsigned i;
struct bitmap* bm;
- // If this assert fails, fix the definition of BITS_PER_BITS_PER_UWORD
- // in drd_bitmap.h.
+ /* If this assert fails, fix the definition of BITS_PER_BITS_PER_UWORD */
+ /* in drd_bitmap.h. */
tl_assert((1 << BITS_PER_BITS_PER_UWORD) == BITS_PER_UWORD);
bm = VG_(malloc)(sizeof(*bm));
tl_assert(bm);
+ /* Cache initialization. a1 is initialized with a value that never can */
+ /* match any valid address: the upper ADDR0_BITS bits of a1 are always */
+ /* zero for a valid cache entry. */
for (i = 0; i < N_CACHE_ELEM; i++)
{
- bm->cache[i].a1 = 0;
+ bm->cache[i].a1 = ~(UWord)1;
bm->cache[i].bm2 = 0;
}
bm->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free));
Modified: trunk/exp-drd/drd_bitmap.h
===================================================================
--- trunk/exp-drd/drd_bitmap.h 2008-03-25 17:19:20 UTC (rev 7788)
+++ trunk/exp-drd/drd_bitmap.h 2008-03-25 18:51:06 UTC (rev 7789)
@@ -201,69 +201,74 @@
struct bitmap2ref* const bm2ref);
-#if 0
-/** Bitmap invariant check.
- *
- * @return 1 if the invariant is satisfied, 0 if not.
- */
static __inline__
-int bm_check(const struct bitmap* const bm)
+Bool bm_cache_lookup(const struct bitmap* const bm, const UWord a1,
+ struct bitmap2** bm2)
{
- struct bitmap2_ref* bm2ref;
-
tl_assert(bm);
+ tl_assert(bm2);
- return (bm->cache[0].a1 == 0
- && bm->cache[1].a1 == 0
- || ((bm2ref = VG_(OSetGen_Lookup)(bm->oset, &bm->last_lookup_a1))
- && bm2ref->bm2
- && bm->last_lookup_a1 == bm2ref->bm2->addr
- && bm2ref->bm2->refcnt >= 1)
- );
-}
-#endif
-
-static __inline__
-struct bitmap2* bm_cache_lookup(const struct bitmap* const bm, const UWord a1)
-{
- tl_assert(bm);
-
#if N_CACHE_ELEM > 8
#error Please update the code below.
#endif
#if N_CACHE_ELEM >= 1
if (a1 == bm->cache[0].a1)
- return bm->cache[0].bm2;
+ {
+ *bm2 = bm->cache[0].bm2;
+ return True;
+ }
#endif
#if N_CACHE_ELEM >= 2
if (a1 == bm->cache[1].a1)
- return bm->cache[1].bm2;
+ {
+ *bm2 = bm->cache[1].bm2;
+ return True;
+ }
#endif
#if N_CACHE_ELEM >= 3
if (a1 == bm->cache[2].a1)
- return bm->cache[2].bm2;
+ {
+ *bm2 = bm->cache[2].bm2;
+ return True;
+ }
#endif
#if N_CACHE_ELEM >= 4
if (a1 == bm->cache[3].a1)
- return bm->cache[3].bm2;
+ {
+ *bm2 = bm->cache[3].bm2;
+ return True;
+ }
#endif
#if N_CACHE_ELEM >= 5
if (a1 == bm->cache[4].a1)
- return bm->cache[4].bm2;
+ {
+ *bm2 = bm->cache[4].bm2;
+ return True;
+ }
#endif
#if N_CACHE_ELEM >= 6
if (a1 == bm->cache[5].a1)
- return bm->cache[5].bm2;
+ {
+ *bm2 = bm->cache[5].bm2;
+ return True;
+ }
#endif
#if N_CACHE_ELEM >= 7
if (a1 == bm->cache[6].a1)
- return bm->cache[6].bm2;
+ {
+ *bm2 = bm->cache[6].bm2;
+ return True;
+ }
#endif
#if N_CACHE_ELEM >= 8
if (a1 == bm->cache[7].a1)
- return bm->cache[7].bm2;
+ {
+ *bm2 = bm->cache[7].bm2;
+ return True;
+ }
#endif
- return 0;
+ *bm2 = 0;
+ return False;
}
static __inline__
@@ -311,25 +316,20 @@
static __inline__
const struct bitmap2* bm2_lookup(const struct bitmap* const bm, const UWord a1)
{
+ struct bitmap2* bm2;
struct bitmap2ref* bm2ref;
tl_assert(bm);
- if (a1 == bm->cache[0].a1)
+ if (! bm_cache_lookup(bm, a1, &bm2))
{
- return bm->cache[0].bm2;
- }
- if (a1 == bm->cache[1].a1)
- {
- return bm->cache[1].bm2;
- }
- bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
- if (bm2ref)
- {
- struct bitmap2* const bm2 = bm2ref->bm2;
+ bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
+ if (bm2ref)
+ {
+ bm2 = bm2ref->bm2;
+ }
bm_update_cache(*(struct bitmap**)&bm, a1, bm2);
- return bm2;
}
- return 0;
+ return bm2;
}
/** Look up the address a1 in bitmap bm and return a pointer to a second
@@ -346,9 +346,10 @@
struct bitmap2* bm2;
bm2ref = 0;
- bm2 = bm_cache_lookup(bm, a1);
- if (bm2)
+ if (bm_cache_lookup(bm, a1, &bm2))
{
+ if (bm2 == 0)
+ return 0;
if (bm2->refcnt > 1)
{
bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
@@ -357,14 +358,9 @@
else
{
bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
- if (bm2ref)
- {
- bm2 = bm2ref->bm2;
- }
- else
- {
+ if (bm2ref == 0)
return 0;
- }
+ bm2 = bm2ref->bm2;
}
tl_assert(bm2);
@@ -438,8 +434,7 @@
struct bitmap2* bm2;
tl_assert(bm);
- bm2 = bm_cache_lookup(bm, a1);
- if (bm2 == 0)
+ if (! bm_cache_lookup(bm, a1, &bm2) || bm2 == 0)
{
bm2ref = VG_(OSetGen_Lookup)(bm->oset, &a1);
if (bm2ref)
|
|
From: <sv...@va...> - 2008-03-25 17:19:16
|
Author: bart
Date: 2008-03-25 17:19:20 +0000 (Tue, 25 Mar 2008)
New Revision: 7788
Log:
Minor optimization of bm_clear().
Modified:
trunk/exp-drd/drd_bitmap.c
trunk/exp-drd/drd_bitmap.h
Modified: trunk/exp-drd/drd_bitmap.c
===================================================================
--- trunk/exp-drd/drd_bitmap.c 2008-03-25 17:03:01 UTC (rev 7787)
+++ trunk/exp-drd/drd_bitmap.c 2008-03-25 17:19:20 UTC (rev 7788)
@@ -379,28 +379,6 @@
return 0;
}
-static __inline__
-void bm1_clear(struct bitmap1* const bm1, const Addr a1, const Addr a2)
-{
- UWord idx;
- UWord mask;
-
-#if 0
- /* Commented out the statements below because of performance reasons. */
- tl_assert(a1);
- tl_assert(a1 <= a2);
- tl_assert(UWORD_MSB(a1) == UWORD_MSB(a2)
- || UWORD_MSB(a1) == UWORD_MSB(a2 - 1));
-#endif
-
- idx = (a1 & ADDR0_MASK) >> BITS_PER_BITS_PER_UWORD;
- /* mask: a contiguous series of one bits. The first bit set is bit */
- /* UWORD_LSB(a2-1), and the last bit set is UWORD_LSB(a1). */
- mask = UWORD_LSB(a2) ? bm0_mask(a2) - bm0_mask(a1) : - bm0_mask(a1);
- bm1->bm0_r[idx] &= ~mask;
- bm1->bm0_w[idx] &= ~mask;
-}
-
void bm_clear(const struct bitmap* const bm,
const Addr a1,
const Addr a2)
@@ -425,14 +403,14 @@
{
Addr c = b;
/* If the first address in the bitmap that must be cleared does not */
- /* start on an UWord boundary, start clearing the first addresses */
- /* by calling bm1_clear(). */
+ /* start on an UWord boundary, start clearing the first addresses. */
if (UWORD_LSB(c))
{
Addr c_next = UWORD_MSB(c) + BITS_PER_UWORD;
if (c_next > b_next)
c_next = b_next;
- bm1_clear(&p2->bm1, c, c_next);
+ bm0_clear_range(p2->bm1.bm0_r, c & ADDR0_MASK, c_next - c);
+ bm0_clear_range(p2->bm1.bm0_w, c & ADDR0_MASK, c_next - c);
c = c_next;
}
/* If some UWords have to be cleared entirely, do this now. */
@@ -452,12 +430,10 @@
}
}
/* If the last address in the bitmap that must be cleared does not */
- /* fall on an UWord boundary, clear the last addresses by calling */
- /* bm1_clear(). */
- if (c != b_next)
- {
- bm1_clear(&p2->bm1, c, b_next);
- }
+ /* fall on an UWord boundary, clear the last addresses. */
+ /* tl_assert(c <= b_next); */
+ bm0_clear_range(p2->bm1.bm0_r, c & ADDR0_MASK, b_next - c);
+ bm0_clear_range(p2->bm1.bm0_w, c & ADDR0_MASK, b_next - c);
}
}
}
Modified: trunk/exp-drd/drd_bitmap.h
===================================================================
--- trunk/exp-drd/drd_bitmap.h 2008-03-25 17:03:01 UTC (rev 7787)
+++ trunk/exp-drd/drd_bitmap.h 2008-03-25 17:19:20 UTC (rev 7788)
@@ -124,6 +124,20 @@
bm0[a >> BITS_PER_BITS_PER_UWORD] &= ~((UWord)1 << UWORD_LSB(a));
}
+/** Clear all of the addresses in range [ a1 .. a1 + size [ in bitmap bm0. */
+static __inline__ void bm0_clear_range(UWord* bm0,
+ const Addr a1, const SizeT size)
+{
+#if 0
+ tl_assert(a1 < ADDR0_COUNT);
+ tl_assert(size > 0);
+ tl_assert(a1 + size <= ADDR0_COUNT);
+ tl_assert(UWORD_MSB(a1) == UWORD_MSB(a1 + size - 1));
+#endif
+ bm0[a1 >> BITS_PER_BITS_PER_UWORD]
+ &= ~(((UWord)1 << size) - 1) << UWORD_LSB(a1);
+}
+
static __inline__ UWord bm0_is_set(const UWord* bm0, const Addr a)
{
//tl_assert(a < ADDR0_COUNT);
|
|
From: <sv...@va...> - 2008-03-25 17:03:02
|
Author: bart
Date: 2008-03-25 17:03:01 +0000 (Tue, 25 Mar 2008)
New Revision: 7787
Log:
Removed unused function.
Modified:
trunk/exp-drd/drd_bitmap.c
trunk/exp-drd/pub_drd_bitmap.h
Modified: trunk/exp-drd/drd_bitmap.c
===================================================================
--- trunk/exp-drd/drd_bitmap.c 2008-03-24 19:38:57 UTC (rev 7786)
+++ trunk/exp-drd/drd_bitmap.c 2008-03-25 17:03:01 UTC (rev 7787)
@@ -401,25 +401,6 @@
bm1->bm0_w[idx] &= ~mask;
}
-void bm_clear_all(const struct bitmap* const bm)
-{
- struct bitmap2* bm2;
- struct bitmap2ref* bm2ref;
-
- VG_(OSetGen_ResetIter)(bm->oset);
-
- for ( ; (bm2ref = VG_(OSetGen_Next)(bm->oset)) != 0; )
- {
- struct bitmap1* bm1;
-
- bm2 = bm2ref->bm2;
- bm1 = &bm2->bm1;
- tl_assert(bm1);
- VG_(memset)(&bm1->bm0_r[0], 0, sizeof(bm1->bm0_r));
- VG_(memset)(&bm1->bm0_w[0], 0, sizeof(bm1->bm0_w));
- }
-}
-
void bm_clear(const struct bitmap* const bm,
const Addr a1,
const Addr a2)
Modified: trunk/exp-drd/pub_drd_bitmap.h
===================================================================
--- trunk/exp-drd/pub_drd_bitmap.h 2008-03-24 19:38:57 UTC (rev 7786)
+++ trunk/exp-drd/pub_drd_bitmap.h 2008-03-25 17:03:01 UTC (rev 7787)
@@ -78,7 +78,6 @@
const Addr a1, const Addr a2);
UWord bm_has_1(const struct bitmap* const bm,
const Addr address, const BmAccessTypeT access_type);
-void bm_clear_all(const struct bitmap* const bm);
void bm_clear(const struct bitmap* const bm,
const Addr a1, const Addr a2);
Bool bm_has_conflict_with(const struct bitmap* const bm,
|
|
From: Nuno L. <nun...@sa...> - 2008-03-25 15:55:44
|
>> > Or are you doing something else apart from V-V coalescing? >> >> I'm also killing R-V dead stores. (happens when some instruction updates >> e.g. %eax, then %eax is moved to a virtual reg, but it's never used). > > Do you have an example of that, to look at? sure: -- t11 = Shr32(64HIto32(MullU32(0xCCCCCCCD:I32,Add32(Shl32(LDle:I32(t25),0x2:I8),0x27:I32))),0x4:I8) movl $0xCCCCCCCD,%vr139 movl (%vr26),%vr142 movl %vr142,%vr141 shll $2,%vr141 movl %vr141,%vr140 addl $0x27,%vr140 movl %vr140,%eax umull %vr139 movl %edx,%vr138 movl %eax,%vr137 ; <-- dead assignment to: %vr137 movl %vr138,%vr136 shrl $4,%vr136 movl %vr136,%vr12 %vr137 is never referenced after that assignment, so the peephole optimizer removes that line. >> 20 movl 0x2A8(%ebp),%edx ; load %vr30 from memory >> 21 andl $0xFFFF,%edx >> 22 movl 0x2A8(%ebp),%edx ; <-- %vr30 is in %edx, not in memory >> 23 movl %edi,%eax >> 24 call[2] 0x38006C30 >> >> So the problem is that the register allocator gets confused somehow and >> loads %vr30 twice, destroying its value (i.e. the line 22 is bogus and >> could be removed altogether). > > That's very strange. After the reload on line 20, it should indeed > have noted that %vr30 is now in %edx, so then there would be no need > to incorrectly reload it again at line 22. I have no idea why. So well, any idea on how to debug that problem? I have zero knowledge about register allocation algorithms, hence my relutance to get my hands on it.. Regards, Nuno |
|
From: Julian S. <js...@ac...> - 2008-03-25 15:40:47
|
> > Or are you doing something else apart from V-V coalescing? > > I'm also killing R-V dead stores. (happens when some instruction updates > e.g. %eax, then %eax is moved to a virtual reg, but it's never used). Do you have an example of that, to look at? > 20 movl 0x2A8(%ebp),%edx ; load %vr30 from memory > 21 andl $0xFFFF,%edx > 22 movl 0x2A8(%ebp),%edx ; <-- %vr30 is in %edx, not in memory > 23 movl %edi,%eax > 24 call[2] 0x38006C30 > > So the problem is that the register allocator gets confused somehow and > loads %vr30 twice, destroying its value (i.e. the line 22 is bogus and > could be removed altogether). That's very strange. After the reload on line 20, it should indeed have noted that %vr30 is now in %edx, so then there would be no need to incorrectly reload it again at line 22. I have no idea why. J |
|
From: Nuno L. <nun...@sa...> - 2008-03-25 15:08:12
|
>> Currently it only removes redudant MOVs between virtual registers that >> can >> be propagated forward. Imagine this: >> >> 9 movl %vr16,%vr85 ; %vr16 isn't referenced below this line >> 10 subl $0x4,%vr85 >> >> (maps %vr85 to %vr16) >> >> the movl is removed and translated into: >> 9 subl $0x4,%vr16 > > Yes. However the register allocator does the same transformation > (virtual-to-virtual register move coalescing), in the case where > the source register's live range ends at the move instruction and > the destination register's live range starts at the move instruction. > > That allows the instruction selectors to generate apparently-stupid > code with lots of v-v moves, and reg-alloc then cleans it up later. > This makes construction of the instruction selectors much simpler, > especially for 2-address targets (x86, amd64). Uhm, strange.. I must confess that I didn't read the register allocation part of the PLDI paper, as I've no experience with register allocation algorithms. Now looking at it, it seems that part of the moves I'm eliminating should have been covered by the register allocator, but in fact they aren't. If you check my other e-mail, I was able to reduce the number of instructions of a single block (already reg-allocated) from 122 to "just" 108. > Or are you doing something else apart from V-V coalescing? I'm also killing R-V dead stores. (happens when some instruction updates e.g. %eax, then %eax is moved to a virtual reg, but it's never used). >> (memcheck creates some unnecessary moves because >> of the dirty handler arguments). > > Yes .. it could probably do better in cases where a V(irtual) register > is moved to a (R)eal register, and the V's live range ends at that > point. I think I tried to add a "preference" mechanism to regalloc2.c, > which says, for each virtual reg, which real reg it would "prefer" to > be in, for this reason. But I also think that didn't help, because > it constrains regalloc's choice of registers and so just moves the > reg-to-reg moves elsewhere. However, I didn't investigate much; you > may be able to do better. > >> Do you know what might be causing the problem? > > Check carefully the validity of the transformation(s) you do. > It's easy to break stuff at this level. Ah, found the problem.. The problem is in the register allocator. I knew the problem couldn't be from my nice code :P Seriously take a look at this: after peephole optimization: 9 call[1] 0x38007070 10 movl %eax,%vr30 11 movzwl (%vr2),%vr69 12 cmpl $0x0,%vr26 13 callnz[0] 0x38006920 14 andl $0xFFFF,%vr30 15 movl %vr30,%edx 16 movl %vr1,%eax 17 call[2] 0x38006C30 after register allocation: 12 call[1] 0x38007070 13 movl %eax,%edx 14 movl 0x288(%ebp),%ecx 15 movzwl (%ecx),%eax 16 cmpl $0x0,0x2A0(%ebp) 17 movl %edx,0x2A8(%ebp) ; %vr30 to memory 18 movl %eax,0x2B8(%ebp) 19 callnz[0] 0x38006920 20 movl 0x2A8(%ebp),%edx ; load %vr30 from memory 21 andl $0xFFFF,%edx 22 movl 0x2A8(%ebp),%edx ; <-- %vr30 is in %edx, not in memory 23 movl %edi,%eax 24 call[2] 0x38006C30 So the problem is that the register allocator gets confused somehow and loads %vr30 twice, destroying its value (i.e. the line 22 is bogus and could be removed altogether). Thanks, Nuno |
|
From: Julian S. <js...@ac...> - 2008-03-25 11:44:21
|
> Currently it only removes redudant MOVs between virtual registers that can > be propagated forward. Imagine this: > > 9 movl %vr16,%vr85 ; %vr16 isn't referenced below this line > 10 subl $0x4,%vr85 > > (maps %vr85 to %vr16) > > the movl is removed and translated into: > 9 subl $0x4,%vr16 Yes. However the register allocator does the same transformation (virtual-to-virtual register move coalescing), in the case where the source register's live range ends at the move instruction and the destination register's live range starts at the move instruction. That allows the instruction selectors to generate apparently-stupid code with lots of v-v moves, and reg-alloc then cleans it up later. This makes construction of the instruction selectors much simpler, especially for 2-address targets (x86, amd64). Or are you doing something else apart from V-V coalescing? > (memcheck creates some unnecessary moves because > of the dirty handler arguments). Yes .. it could probably do better in cases where a V(irtual) register is moved to a (R)eal register, and the V's live range ends at that point. I think I tried to add a "preference" mechanism to regalloc2.c, which says, for each virtual reg, which real reg it would "prefer" to be in, for this reason. But I also think that didn't help, because it constrains regalloc's choice of registers and so just moves the reg-to-reg moves elsewhere. However, I didn't investigate much; you may be able to do better. > Do you know what might be causing the problem? Check carefully the validity of the transformation(s) you do. It's easy to break stuff at this level. J |
|
From: Nuno L. <nun...@sa...> - 2008-03-25 11:34:49
|
>> Today I've written a simple peephole optimizer that works after the >> instruction selection and before register allocation. So it takes an >> array >> of instructions and outputs another array of instructions. It's also >> independent of the platform. The patch is available at: >> http://web.ist.utl.pt/nuno.lopes/valgrind_vex_peephole_optimizations.txt >> Currently it only removes redudant MOVs between virtual registers that >> can >> be propagated forward. Imagine this: >> >> 9 movl %vr16,%vr85 ; %vr16 isn't referenced below this line >> 10 subl $0x4,%vr85 >> >> (maps %vr85 to %vr16) >> >> the movl is removed and translated into: >> 9 subl $0x4,%vr16 > > Surely, whether %vr16 is reference again later isn't important; but > whether %vr85 is referenced again later is important? Yes, sure. I then replace all references to %vr85 with %vr16. Let's say that I do the 'movl' at compile time, by propagating it through the following references. The optimization I missed was to remove the movl if the destination register isn't used anymore, but that doesn't seem much likely to happen (i.e. I don't think that isel will produce such code, but I didn't check it further). >> With only this simple transformation, I was able to reduce the number of >> instructions of a simple block (instrumented with memcheck) from 120 to >> 106, >> which is quite good. The number of register spills is also hugely reduced >> (on a x86 host)! (memcheck creates some unnecessary moves because of the >> dirty handler arguments). > > The 120-to-106 reduction is on the final generated code? Thats the reduction in this peep-hole optimization pass. The register allocated code has 108 instructions. Without this peephole optimizer, the register allocated code has 122 instructions! (i.e. no redudant 'movl' is removed) > The register allocator can get rid of many register-to-register moves (as > the PLDI paper explains), but perhaps it misses some. Or many. Perhaps > you could send an example block, showing before and after? The example I gave in the previous email. The movl instruction isn't killed by the register allocation code. You can take a look at the output of the optimizer running on an example block: http://web.ist.utl.pt/nuno.lopes/valgrind_block_after_peephole.txt >> The caveats? Well it segfaults *after* compiling all the blocks, which is >> weird.. I get the following error: >> >> ==28498== Invalid read of size 1 >> ==28498== at 0x4015508: (within /lib/ld-2.6.1.so) >> ==28498== by 0x4013CB5: (within /lib/ld-2.6.1.so) >> ==28498== by 0x400134E: (within /lib/ld-2.6.1.so) >> ==28498== by 0x40009A6: (within /lib/ld-2.6.1.so) >> ==28498== Address 0x10090188 is not stack'd, malloc'd or (recently) >> free'd >> ==28498== >> ==28498== Process terminating with default action of signal 11 (SIGSEGV) >> ==28498== Access not within mapped region at address 0x10090188 >> ==28498== at 0x4015508: (within /lib/ld-2.6.1.so) >> ==28498== by 0x4013CB5: (within /lib/ld-2.6.1.so) >> ==28498== by 0x400134E: (within /lib/ld-2.6.1.so) >> ==28498== by 0x40009A6: (within /lib/ld-2.6.1.so) >> >> Do you know what might be causing the problem? > > I can't think of anything, other than the transformation has a bug in it. It's weird, because if I do the register replacement and do *not* remove the 'movl's, thus getting a few 'movl %vrX, %vrX' (really NOPs), it works. Maybe there's some jump that is screwed by the instruction number decrease, which doesn't make much sense and register spill adds additional instructions. >> Also, after this is working correctly (i.e. fixing this segfault and >> running >> the tests), do you think this could be incorporated in valgrind/VEX? > > Quite possibly, although Julian has the final say. It would depend on > whether it actually improves performance -- it's always hard to predict > whether code optimisations have a genuine effect. So far, from the little tests I've run it seems that the optimizer is very useful when running memcheck (reduces the number of instructions up to 12%). I don't have any benchmarks yet (as I can't run them :P). Thanks, Nuno |
|
From: Julian S. <js...@ac...> - 2008-03-25 11:04:32
|
> I've tried to insert VALGRIND_DO_LEAK_CHECK into program's main loop, > but eventually got false positive `definetly lost' blocks in this > place (there's no memleaks when program normally stops in valgrind's > report). > > The question is: > Does VALGRIND_DO_LEAK_CHECK work in ANY cases and I > should model this situation and report a bug, or there is yet some > cases memcheck can't handle? False positives are possible, but unlikely. The probability of a false positive increases as the address space gets more and more used, which is probably why you saw them. Anyway. It sounds like you maybe need to use Valgrind's Massif tool to find the cause of the allocations (--tool=massif). Make sure to use Massif in Valgrind version 3.3.0. Some documentation is here: http://www.valgrind.org/docs/manual/ms-manual.html J |
|
From: Nicholas N. <nj...@cs...> - 2008-03-25 08:33:40
|
On Mon, 24 Mar 2008, Nuno Lopes wrote: > Today I've written a simple peephole optimizer that works after the > instruction selection and before register allocation. So it takes an array > of instructions and outputs another array of instructions. It's also > independent of the platform. The patch is available at: > http://web.ist.utl.pt/nuno.lopes/valgrind_vex_peephole_optimizations.txt > Currently it only removes redudant MOVs between virtual registers that can > be propagated forward. Imagine this: > > 9 movl %vr16,%vr85 ; %vr16 isn't referenced below this line > 10 subl $0x4,%vr85 > > (maps %vr85 to %vr16) > > the movl is removed and translated into: > 9 subl $0x4,%vr16 Surely, whether %vr16 is reference again later isn't important; but whether %vr85 is referenced again later is important? > With only this simple transformation, I was able to reduce the number of > instructions of a simple block (instrumented with memcheck) from 120 to 106, > which is quite good. The number of register spills is also hugely reduced > (on a x86 host)! (memcheck creates some unnecessary moves because of the > dirty handler arguments). The 120-to-106 reduction is on the final generated code? Huh. The register allocator can get rid of many register-to-register moves (as the PLDI paper explains), but perhaps it misses some. Or many. Perhaps you could send an example block, showing before and after? > The caveats? Well it segfaults *after* compiling all the blocks, which is > weird.. I get the following error: > > ==28498== Invalid read of size 1 > ==28498== at 0x4015508: (within /lib/ld-2.6.1.so) > ==28498== by 0x4013CB5: (within /lib/ld-2.6.1.so) > ==28498== by 0x400134E: (within /lib/ld-2.6.1.so) > ==28498== by 0x40009A6: (within /lib/ld-2.6.1.so) > ==28498== Address 0x10090188 is not stack'd, malloc'd or (recently) free'd > ==28498== > ==28498== Process terminating with default action of signal 11 (SIGSEGV) > ==28498== Access not within mapped region at address 0x10090188 > ==28498== at 0x4015508: (within /lib/ld-2.6.1.so) > ==28498== by 0x4013CB5: (within /lib/ld-2.6.1.so) > ==28498== by 0x400134E: (within /lib/ld-2.6.1.so) > ==28498== by 0x40009A6: (within /lib/ld-2.6.1.so) > > Do you know what might be causing the problem? I can't think of anything, other than the transformation has a bug in it. > Also, after this is working correctly (i.e. fixing this segfault and running > the tests), do you think this could be incorporated in valgrind/VEX? Quite possibly, although Julian has the final say. It would depend on whether it actually improves performance -- it's always hard to predict whether code optimisations have a genuine effect. Nick |
|
From: Tom H. <th...@cy...> - 2008-03-25 06:10:22
|
Nightly build on alvis ( i686, Red Hat 7.3 ) started at 2008-03-25 03:15:03 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 330 tests, 76 stderr failures, 1 stdout failure, 29 post failures == memcheck/tests/addressable (stderr) memcheck/tests/badjump (stderr) memcheck/tests/describe-block (stderr) memcheck/tests/erringfds (stderr) memcheck/tests/leak-0 (stderr) memcheck/tests/leak-cycle (stderr) memcheck/tests/leak-pool-0 (stderr) memcheck/tests/leak-pool-1 (stderr) memcheck/tests/leak-pool-2 (stderr) memcheck/tests/leak-pool-3 (stderr) memcheck/tests/leak-pool-4 (stderr) memcheck/tests/leak-pool-5 (stderr) memcheck/tests/leak-regroot (stderr) memcheck/tests/leak-tree (stderr) memcheck/tests/long_namespace_xml (stderr) memcheck/tests/lsframe1 (stderr) memcheck/tests/lsframe2 (stderr) memcheck/tests/malloc_free_fill (stderr) memcheck/tests/match-overrun (stderr) memcheck/tests/noisy_child (stderr) memcheck/tests/partial_load_dflt (stderr) memcheck/tests/partial_load_ok (stderr) memcheck/tests/partiallydefinedeq (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/sigkill (stderr) memcheck/tests/stack_changes (stderr) memcheck/tests/varinfo1 (stderr) memcheck/tests/varinfo2 (stderr) memcheck/tests/varinfo3 (stderr) memcheck/tests/varinfo4 (stderr) memcheck/tests/varinfo5 (stderr) memcheck/tests/varinfo6 (stderr) memcheck/tests/x86/bug152022 (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) memcheck/tests/x86/xor-undef-x86 (stderr) memcheck/tests/xml1 (stderr) massif/tests/alloc-fns-A (post) massif/tests/alloc-fns-B (post) massif/tests/basic (post) massif/tests/basic2 (post) massif/tests/big-alloc (post) massif/tests/culling1 (stderr) massif/tests/culling2 (stderr) massif/tests/custom_alloc (post) massif/tests/deep-A (post) massif/tests/deep-B (stderr) massif/tests/deep-B (post) massif/tests/deep-C (stderr) massif/tests/deep-C (post) massif/tests/deep-D (post) massif/tests/ignoring (post) massif/tests/insig (post) massif/tests/long-names (post) massif/tests/long-time (post) massif/tests/new-cpp (post) massif/tests/null (post) massif/tests/one (post) massif/tests/overloaded-new (post) massif/tests/peak (post) massif/tests/peak2 (stderr) massif/tests/peak2 (post) massif/tests/realloc (stderr) massif/tests/realloc (post) massif/tests/thresholds_0_0 (post) massif/tests/thresholds_0_10 (post) massif/tests/thresholds_10_0 (post) massif/tests/thresholds_10_10 (post) massif/tests/thresholds_5_0 (post) massif/tests/thresholds_5_10 (post) massif/tests/zero1 (post) massif/tests/zero2 (post) none/tests/blockfault (stderr) none/tests/faultstatus (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) none/tests/shell (stderr) none/tests/shell_valid1 (stderr) none/tests/shell_valid2 (stderr) none/tests/shell_valid3 (stderr) helgrind/tests/hg01_all_ok (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/hg06_readshared (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc02_simple_tls (stderr) helgrind/tests/tc03_re_excl (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc07_hbl1 (stderr) helgrind/tests/tc08_hbl2 (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc11_XCHG (stderr) helgrind/tests/tc12_rwl_trivial (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc18_semabuse (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) helgrind/tests/tc23_bogus_condwait (stderr) helgrind/tests/tc24_nonzero_sem (stderr) |
|
From: Tom H. <th...@cy...> - 2008-03-25 04:26:36
|
Nightly build on lloyd ( x86_64, Fedora 7 ) started at 2008-03-25 03:05:05 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 413 tests, 6 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) none/tests/faultstatus (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) |
|
From: Tom H. <th...@cy...> - 2008-03-25 03:51:39
|
Nightly build on aston ( x86_64, Fedora Core 5 ) started at 2008-03-25 03:20:07 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 419 tests, 9 stderr failures, 1 stdout failure, 0 post failures == memcheck/tests/malloc_free_fill (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/x86/scalar (stderr) none/tests/blockfault (stderr) none/tests/faultstatus (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) |
|
From: Tom H. <th...@cy...> - 2008-03-25 03:40:05
|
Nightly build on trojan ( x86_64, Fedora Core 6 ) started at 2008-03-25 03:25:08 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 417 tests, 8 stderr failures, 5 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/bug133694 (stdout) memcheck/tests/x86/bug133694 (stderr) memcheck/tests/x86/scalar (stderr) none/tests/cmdline1 (stdout) none/tests/cmdline2 (stdout) none/tests/faultstatus (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) |
|
From: Tom H. <th...@cy...> - 2008-03-25 03:33:15
|
Nightly build on dellow ( x86_64, Fedora 8 ) started at 2008-03-25 03:10:04 GMT Results differ from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 413 tests, 7 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) none/tests/faultstatus (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc18_semabuse (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Results from 24 hours ago == ================================================= Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 413 tests, 8 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) memcheck/tests/vcpu_fnfns (stdout) memcheck/tests/x86/scalar (stderr) none/tests/faultstatus (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) helgrind/tests/tc18_semabuse (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) ================================================= == Difference between 24 hours ago and now == ================================================= *** old.short Tue Mar 25 03:21:44 2008 --- new.short Tue Mar 25 03:33:16 2008 *************** *** 8,10 **** ! == 413 tests, 8 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) --- 8,10 ---- ! == 413 tests, 7 stderr failures, 2 stdout failures, 0 post failures == memcheck/tests/pointer-trace (stderr) *************** *** 17,19 **** helgrind/tests/tc20_verifywrap (stderr) - helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) --- 17,18 ---- |
|
From: Tom H. <th...@cy...> - 2008-03-25 03:17:06
|
Nightly build on gill ( x86_64, Fedora Core 2 ) started at 2008-03-25 03:00:02 GMT Results unchanged from 24 hours ago Checking out valgrind source tree ... done Configuring valgrind ... done Building valgrind ... done Running regression tests ... failed Regression test results follow == 419 tests, 31 stderr failures, 3 stdout failures, 0 post failures == memcheck/tests/malloc_free_fill (stderr) memcheck/tests/pointer-trace (stderr) memcheck/tests/stack_switch (stderr) memcheck/tests/varinfo6 (stderr) memcheck/tests/x86/scalar (stderr) memcheck/tests/x86/scalar_supp (stderr) none/tests/amd64/insn_ssse3 (stdout) none/tests/amd64/insn_ssse3 (stderr) none/tests/amd64/ssse3_misaligned (stderr) none/tests/blockfault (stderr) none/tests/faultstatus (stderr) none/tests/fdleak_fcntl (stderr) none/tests/mremap (stderr) none/tests/mremap2 (stdout) none/tests/x86/insn_ssse3 (stdout) none/tests/x86/insn_ssse3 (stderr) none/tests/x86/ssse3_misaligned (stderr) helgrind/tests/hg01_all_ok (stderr) helgrind/tests/hg02_deadlock (stderr) helgrind/tests/hg03_inherit (stderr) helgrind/tests/hg04_race (stderr) helgrind/tests/hg05_race2 (stderr) helgrind/tests/tc01_simple_race (stderr) helgrind/tests/tc05_simple_race (stderr) helgrind/tests/tc06_two_races (stderr) helgrind/tests/tc09_bad_unlock (stderr) helgrind/tests/tc14_laog_dinphils (stderr) helgrind/tests/tc16_byterace (stderr) helgrind/tests/tc17_sembar (stderr) helgrind/tests/tc19_shadowmem (stderr) helgrind/tests/tc20_verifywrap (stderr) helgrind/tests/tc21_pthonce (stderr) helgrind/tests/tc22_exit_w_lock (stderr) helgrind/tests/tc23_bogus_condwait (stderr) |