svn commit: r209604 - head/lib/libc/gmon
Marcel Moolenaar
xcllnt at mac.com
Wed Jun 30 18:15:26 UTC 2010
On Jun 30, 2010, at 2:40 AM, Bruce Evans wrote:
> On Wed, 30 Jun 2010, Marcel Moolenaar wrote:
>
>> Log:
>> On powerpc, calculate s_scale using the non-FP version previously
>> specific to hp300. Since FreeBSD does not support hp300, hp300 has
>> been removed from the condition altogether.
>
> Also, the style of the condition has been regressed from ifndef to
> if !defined().
That's on purpose. Either we eliminate the whole conditional or we
end up adding other platforms to it.
>> The FP version broke profiling on powerpc due to invalid results.
>> Casting to double instead of float resolved the issue, but with
>> Book-E not having a FP unit, the non-FP version looked preferrable.
>> Note that even on AIM hardware the FP version yielded an invalid
>> value for s_scale, so the problem is most likely with the compiler
>> or with the expression itself.
>
> Better use the integer code unconditionally if it works.
I tested it on amd64 and it works. My initial thought was to remove
the conditional entirely and always use the non-FP version, but I
changed my mind and instead went with a targeted change only. The
feedback would then guide me to the right implementation.
I believe that the non-FP works on all platforms.
At least ARM also has a problem with the FP version.
> There are
> minor advantages to never using FP in a program (it saves switching
> FP state in signal handlers on some arches, where the switch can involve
> up to 7 or 9 memory accesses to several hundred bytes of state each),
> but using FP in monstartup() causes every profiled program to use FP
> for most of its life. This is despite gprof using FP extensivly, so
> that FP needs to work for profiling to work.
*nod*
>> Modified: head/lib/libc/gmon/gmon.c
>> ==============================================================================
>> --- head/lib/libc/gmon/gmon.c Wed Jun 30 01:10:08 2010 (r209603)
>> +++ head/lib/libc/gmon/gmon.c Wed Jun 30 01:40:25 2010 (r209604)
>> @@ -111,7 +111,7 @@ monstartup(lowpc, highpc)
>>
>> o = p->highpc - p->lowpc;
>> if (p->kcountsize < o) {
>> -#ifndef hp300
>> +#if !defined(__powerpc__)
>
> The style regression.
>
>> s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1;
>
> I can't see any bugs in this expression. p->kcountsize is < o, and the
> scale factor is only 65536, so there should be no problems with overflow.
This leaves GCC a the problem.
> Using float instead of double is a almost pointless since the expression
> will be evaluated in double precision on most machines. powerpc claims
> that FLT_EVAL_METHOD is 1, so powerpc is one of these machines, so
> changing from float to double should have an especially small effect
> on it.
The effect is enormous actually. Casting to float yields the wrong
result. Casting to double yields the right result. This is on both
FP-capable PowerPC CPUs as well has non-FP PowerPC CPUs.
> So the bug is apparently in powerpc's conversion from u_long
> to float, or in promotion to double. I guess it is in conversion from
> u_long to float.
Possible. Then again, I see the same histogram problems on ARM that
I saw on PowerPC, so this doesn't look like a PowerPC-specific bug.
> Better still, rewrite the integer method using a C99 type, so that it
> is as simple as the FP method:
>
> s_scale = ((uintmax_t)p->kcountsize << SCALE_SHIFT) / o;
>
> C99 uintmax_t now guarantees uintmax_t to have >= 64 bits, and practical
> considerations guarantee p->kcountsize to fit in many fewer than 48 bits
> even on 64-bit arches, so the shift cannot overflow.
I like this. What about the following (white-space corrupted)
simplification:
Index: gmon.c
===================================================================
--- gmon.c (revision 209604)
+++ gmon.c (working copy)
@@ -110,24 +110,9 @@
p->tos[0].link = 0;
o = p->highpc - p->lowpc;
- if (p->kcountsize < o) {
-#if !defined(__powerpc__)
- s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1;
-#else /* avoid floating point */
- int quot = o / p->kcountsize;
+ s_scale = (p->kcountsize < o) ?
+ ((uintmax_t)p->kcountsize << SCALE_1_TO_1) / o : SCALE_1_TO_1;
- if (quot >= 0x10000)
- s_scale = 1;
- else if (quot >= 0x100)
- s_scale = 0x10000 / quot;
- else if (o >= 0x800000)
- s_scale = 0x1000000 / (o / (p->kcountsize >> 8));
- else
- s_scale = 0x1000000 / ((o << 8) / p->kcountsize);
-#endif
- } else
- s_scale = SCALE_1_TO_1;
-
moncontrol(1);
}
--
Marcel Moolenaar
xcllnt at mac.com
More information about the svn-src-head
mailing list