develooper Front page | perl.perl5.porters | Postings from March 2013


Thread Previous | Thread Next
Steffen Mueller
March 1, 2013 06:42
Message ID:

On 02/28/2013 08:15 PM, bulk88 wrote:
> Steffen Mueller wrote:
>> By the way: did you know that pp_add is a pretty heavy OP? It's thanks
>> to the PRESERVE_UVIV logic relating to switching underlying types in
>> overflow situations and retaining maximum accuracy.
>> I wonder whether there are situations in which we know at compile time
>> that this logic is not needed. Probably not.
> Going to 5.6 (or 5.8) all NV math makes perl practical for math again.
> Perl is the worst or almost worst language you can use for math,
> .
>   I've written about it before
>;spoil=1 . I think the biggest
> problem is you can't check CPU carry/overflow flag in C so the
> "portable" way of doing it is very poor compared to using some asm x86
> and jumping on carry/overflow flag after the add. The other thing to do
> is >> and | INU/V flags on left and right SVs, then do a switch.
> Another idea is factor out the use_left stuff into a different opcode or
> a different optree but I am not sure what use_left is on script
> level/optree level.

A different op-tree!?

> Maybe the targ assignment can be moved after the overload call. The asm
> is probably a DEBUGGING Perl I used due to Perl_pad_sv. It might move by
> itself on some compilers if Perl_pad_sv isnt a function (c compiler's
> peephole didn't look far enough to see targ isn't used after the
> overload call, and on the no overload branch there are no calls, so SP
> or pad array can't be changed by overload in a way that matters).
> Another idea would be trim down some of the sv_set*v to use direct flag
> manipulation, call sv_setiv once with a UV or IV (pun it), then set the
> UV flag in pp_add by macro, dunno if that makes sense.
> Next thing to think about is, if we Sv*VXed, aren't they guaranteed to
> be the correct type already and they can be set with pure macros since
> no upgrade is needed?
> Compiler already did some punning/merging, for example
>     538:             if (buvok)
>     539:                 buv = ((XPVUV *) (svr)->sv_any)->xuv_u.xivu_uv
> +;
> 2807D5E2 8B 09            mov         ecx,dword ptr [ecx]
> 2807D5E4 8B 49 10         mov         ecx,dword ptr [ecx+10h]
> 2807D5E7 23 C7            and         eax,edi
> 2807D5E9 3B C7            cmp         eax,edi
> 2807D5EB 0F 94 C0         sete        al
> 2807D5EE 84 C0            test        al,al
>     540:             else {
> 2807D5F0 75 0A            jne         Perl_pp_add+14Bh (2807D5FCh)
>     541:                 const IV        biv = ((XPVIV *) (svr)->sv_any
> +)->xiv_u.xivu_iv;
>     542:                 if (biv >= 0) {
> "const IV        biv = ((XPVIV *) (svr)->sv_any
> +)->xiv_u.xivu_iv;" has no instructions associated with it.
> Ideally as I mentioned on perlmonks, if there is no eval/do and no bless
> or tie calls on the lexical, and a lexical is never passed to another
> sub, in a sub, use a different set of opcodes to create 2 or 3 paths
> (pure UV, pure IV, or pure NV math), then doing all operators on a
> statement using something close to machine math without using the SV
> abstraction or Perl stack, or place native machine numbers on the Perl
> stack (not SV *). I know NULLs now appear on the Perl stack in some
> cases. There is an unrealistically work level to introducing a 3rd VM
> into perl which is what this idea is. I guess there were plans a long
> time ago to have alternate optree optimizers/opcodes and override at
> runtime the ck_() funcs.

Umm, you've seen my crazy JIT hacks, right? Check github. :)

Currently hit a big snag in that transforming the Perl OP tree isn't 
fundamentally hard, but it's extremely irritating even after doing the 
"hard" part of matching the eligible sections and reorganizing their 
incompatible sub-sections into a linear list.

> A slimmer idea would be an opcode that has a var len bitfield/array, it
> will do arbitrary math ops on a list/perl stack going down/up the stack
> with the intermediate number stored in a C auto. When it reaches the end
> of array it assigns to the last SV on the list.
> $_[1] = (($a * 5) + $_[0])/$main::global;
> pushmark, padsv, const, aelemfast, gvsv, aelemfast, megamathop(mul << 8
> | add << 4 | div), nextstate
> Last choice is remove or deprecate/de-default it from the build process
> PERL_PRESERVE_IVUV as unmaintainable and a performance degradation. If
> you dont like FP rounding/precision, complain to your CPU/CC vendor,
> Perl is just a wrapper around your native C/POSIX support, I hear GCC
> now offers __float128. Perl is not an OS and emulator/hypervisor wrapped
> together in 1 binary.

Perl is a dynamic programming language. It does these things for a 
reason. If you want C, you know where to find it. This will not be 
negotiable. Correctness beats speed in almost all cases.

Something that would be perfectly tractable (and even fundamentally 
doable as an extension!) is maintaining a copy of the respective OP or 
OPs without the PRESERVE_UVIV logic and then using a hook into the 
peephole optimizer and a lexical pragma to opt in to the faster, but 
less accurate behaviour.

You can start from the JIT hacks, ditch all the complicated, nasty bits, 
and then just scan the OP tree, changing the op_ppaddr and the op_type 
in-place on a whole bunch of OPs. With some previous experience, that 
should be doable in a few hours. Without, it probably takes a day or two 
including reading & research.


Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About