April 03, 2014
On 04/03/14 04:40, Walter Bright wrote:
> On 4/2/2014 6:21 PM, bearophile wrote:
>> Then this feature needs a specific and explicit syntax, or it has _no_ point at all.
> 
> That's like saying inlining has no point because it doesn't have a particular syntax.

Weak inlining *hints* have no point - C learned this the hard way, with "inline" being useless today, and everybody having to use "always_inline/forceinline". The issue isn't about optimizations, which any decent compiler can deal with; it's about the programmer being able to rely on avoiding certain undesirable effects, like excessive stack consumption, unnecessary clobbering of the few precious cpu registers available etc.

What Bearophile is saying is that an optional tail call optimization being
mandated by a spec would be completely useless -- TCO can be legally done
by the compiler anyway; documenting that it could happen does not help the
programmer in any way - (s)he still has to assume that the optimization might
not happen. A syntax like "goto return f();" which mandates TCO would make the
situation different.

[Defining computed gotos would be a better idea, as the tail-call transformation
 would significantly raise the requirements for a compliant D compiler. OTOH
 computed-gotos would lead to more readable D code, are easier to implement,
 and can be easily be made safe in D (by making the type of label-addresses
 unique per-function and avoiding function-cloning)]

artur
April 03, 2014
On 4/2/14, 11:19 PM, monarch_dodra wrote:
> If I were to request the actual "memchr"/"wmemchr"/"dmemchr" functions
> in some "core.???" module, is this something we'd want, and would
> somebody know how to provide an efficient implementation?

Yes. Probably checking stuff with SIMD and a few other approaches would be great.

Andrei
April 03, 2014
03-Apr-2014 10:19, monarch_dodra пишет:

> If I were to request the actual "memchr"/"wmemchr"/"dmemchr" functions
> in some "core.???" module, is this something we'd want, and would
> somebody know how to provide an efficient implementation?

Something I wanted in D since about 2011. Should have put an enhancement request or tipped bearophile ;)

-- 
Dmitry Olshansky
April 03, 2014
03-Apr-2014 05:05, Walter Bright пишет:
> On 4/2/2014 3:06 PM, bearophile wrote:
>> Walter Bright:
>>
>>> I don't see why not. Note that we couldn't do this for extern(C)
>>> functions, or
>>> variadics, or caller functions with parameters that need destruction, or
>>> parameters that may refer to any locals. That last constraint might be a
>>> doozy, however.
>>>
>>> Why not submit an enhancement request to bugzilla?
>>
>> So what does it happen if I (by mistake or by ignorance) try to use
>> this on a
>> function that doesn't satisfy one of those requirements?
>
> Then it won't tail call it.
>
>> D can't give an error in that case because it's a big breaking change.
>> So is D in that case just
>> silently not performing the tail call as the programmer meant?
>
> That's right.
>

From this it seems to me that once again you've walled yourself out of this question and going to frame it as an optimization.

Tail-call has 2 sides to it:

a) An optimization for functions that return with a call expression. I'd leave this case an optimization because it also has an undesirable effect on call stack, hindering debugging.

b) An explicit instruction to switch execution to another function. This doesn't have any unexpected effects, and failing to make a tail-call will change the semantics of code. This is critical for certain kind of code, it simply doesn't work if tail-call is not a jump.

I agree that nothing prevents doing optimization of
return foo(args);
in case a) if optimization is enabled, and this is something GCC/LLVM already do.

But more importantly there should be an explicit tool for the case b), with syntax:
goto foo(args);
that will fail to compile if tail-call is not possible.

Because the alternative of double-checking on every compiler that "return foo(args)" in all the right places is optimized the right way is fragile, and would turn out to be an _ongoing_ waste of time.

-- 
Dmitry Olshansky
April 03, 2014
03-Apr-2014 01:51, Walter Bright пишет:
> On 4/2/2014 1:54 PM, Dmitry Olshansky wrote:
>> If we can alter semantics of
>> return foo(arg);
>> to _always_ be a goto, guarantee a jump and reuse of the stack,  then
>> I'm all
>> for it.
>
> I don't see why not. Note that we couldn't do this for extern(C)
> functions, or variadics, or caller functions with parameters that need
> destruction, or parameters that may refer to any locals. That last
> constraint might be a doozy, however.
>
> Why not submit an enhancement request to bugzilla?

I'd gladly author an enhancement once I'm certain of what exactly to state in it.

Always optimizing return foo(args) to a jump may have impact on debugging experience (curious call-stacks) and cost people hours of wasted time chasing shadows.

Adding an explicit form for it seems to me far more appealing and honest.

-- 
Dmitry Olshansky
April 03, 2014
On Thursday, 3 April 2014 at 19:39:57 UTC, Andrei Alexandrescu wrote:
> On 4/2/14, 11:19 PM, monarch_dodra wrote:
>> If I were to request the actual "memchr"/"wmemchr"/"dmemchr" functions
>> in some "core.???" module, is this something we'd want, and would
>> somebody know how to provide an efficient implementation?
>
> Yes. Probably checking stuff with SIMD and a few other approaches would be great.
>
> Andrei

I filed it here:
https://d.puremagic.com/issues/show_bug.cgi?id=12515

Now, we just need someone to actually do it :)
April 06, 2014
Am Wed, 02 Apr 2014 18:05:32 -0700
schrieb Walter Bright <newshound2@digitalmars.com>:

> On 4/2/2014 3:06 PM, bearophile wrote:
> > Walter Bright:
> >
> >> I don't see why not. Note that we couldn't do this for extern(C) functions, or variadics, or caller functions with parameters that need destruction, or parameters that may refer to any locals. That last constraint might be a doozy, however.
> >>
> >> Why not submit an enhancement request to bugzilla?
> >
> > So what does it happen if I (by mistake or by ignorance) try to use this on a function that doesn't satisfy one of those requirements?
> 
> Then it won't tail call it.

How would `return foo(args)' be used in the C preprocessor example? Would it be implemented like with a jump table?:

char c = ...;
return caseTable[c](args);

What are the benefits over "goto"? I figure with "goto" the semantics are clearer and you can easily access the variables on the stack. Does the TCO version enable any more use-cases? (Note: I consider "far less convoluted code" a valid use-case. :) )

-- 
Marco

April 07, 2014
On 1 April 2014 19:35, Walter Bright <newshound2@digitalmars.com> wrote:
> Try this benchmark comparing various classification schemes:

GDC turns switches into table lookups, and speeds are comparable on my system, though your little hack is appears faster in release builds.

Tests are with 1 million runs.

---
Non-release run:
Milliseconds 1797 1642 1501 1463

Non-release run, no bounds checking:
Milliseconds 1730 1611 1483 1512

Release run:
Milliseconds 1753 1633 1471 1528

Optimised run:
Milliseconds 0 0 0 0
---

It is interesting that switches seem to take longer when bounds checking is turned off, and even longer when in release mode.  However this is not very conclusive as I can't test with optimisations turned on.  Unfortunately for your small program, gcc is too smart and optimises everything away.

---
bool isIdentifierChar3(ubyte c)
{
    switch(c)
    {
        case '0': .. case '9':
        case 'A': .. case 'Z':
        case 'a': .. case 'z':
        case '$':
        case '_':
            return true;

        default:
            return false;
    }
}
April 07, 2014
> on.  Unfortunately for your small program, gcc is too smart and
> optimises everything away.

Haha, that's funny. But why don't you put the data in a separate compilation unit?
April 07, 2014
On 04/01/2014 08:35 PM, Walter Bright wrote:
> Try this benchmark comparing various classification schemes:

Counter example:
https://github.com/D-Programming-Language/phobos/commit/8599d6b4acde0eff886876a56f54ecd8e6b528e9