Jump to page: 1 2
Thread overview
[Issue 13381] Two cases of array literal that can be stack-allocated
[Issue 13381] One case of array literal that can be stack-allocated
Aug 31, 2014
yebblies
Aug 31, 2014
yebblies
Aug 31, 2014
yebblies
Aug 31, 2014
yebblies
Aug 31, 2014
yebblies
Aug 31, 2014
yebblies
Sep 14, 2021
Dennis
Dec 17, 2022
Iain Buclaw
August 31, 2014
https://issues.dlang.org/show_bug.cgi?id=13381

yebblies <yebblies@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |yebblies@gmail.com
           Hardware|x86                         |All
                 OS|Windows                     |All

--- Comment #1 from yebblies <yebblies@gmail.com> ---
I agree.

--
August 31, 2014
https://issues.dlang.org/show_bug.cgi?id=13381

--- Comment #2 from bearophile_hugs@eml.cc ---
Given this code:

void foo(uint[] a) @nogc {
    if (a == [1, 2]) {}
}


One way to rewrite it is (the immutable can't be always used):


void foo(uint[] a) @nogc {
    immutable static uint[2] __foo_aux0 == [1, 2];
    if (a == __foo_aux0) {}
}


Or more efficient:

void foo(uint[] a) @nogc {
    if (a.length == 2 && a[0] == 1 && a[1] == 2) {}
}

--
August 31, 2014
https://issues.dlang.org/show_bug.cgi?id=13381

--- Comment #3 from yebblies <yebblies@gmail.com> ---
(In reply to bearophile_hugs from comment #2)
> 
> One way to rewrite it is (the immutable can't be always used):
> 

While re-writes are certainly the simplest way to explain it, using them in the compiler often leads to complications, especially with error messages referring to the re-written code instead of the original.

For this case, and similar cases, the compiler can simply type the array literal as a static array, because it knows that == can't escape any references.  It already does something like this for indexing array literals.

--
August 31, 2014
https://issues.dlang.org/show_bug.cgi?id=13381

--- Comment #4 from bearophile_hugs@eml.cc ---
(In reply to yebblies from comment #3)

> For this case, and similar cases, the compiler can simply type the array literal as a static array, because it knows that == can't escape any references.  It already does something like this for indexing array literals.

I see. I have suggested a rewrite like this:

if (a.length == 2 && a[0] == 1 && a[1] == 2) {}

Because most array literals used for equality or comparison are short or very short, so calling == or < on few single items is much more efficient than calling a runtime function that works on whole arrays.

--
August 31, 2014
https://issues.dlang.org/show_bug.cgi?id=13381

--- Comment #5 from yebblies <yebblies@gmail.com> ---
(In reply to bearophile_hugs from comment #4)
> (In reply to yebblies from comment #3)
> 
> > For this case, and similar cases, the compiler can simply type the array literal as a static array, because it knows that == can't escape any references.  It already does something like this for indexing array literals.
> 
> I see. I have suggested a rewrite like this:
> 
> if (a.length == 2 && a[0] == 1 && a[1] == 2) {}
> 
> Because most array literals used for equality or comparison are short or very short, so calling == or < on few single items is much more efficient than calling a runtime function that works on whole arrays.

Ideally the optimizer would do this by itself, once the literal is stack-allocated.  I suspect it already does in some cases for gdc/ldc.

--
August 31, 2014
https://issues.dlang.org/show_bug.cgi?id=13381

--- Comment #6 from bearophile_hugs@eml.cc ---
(In reply to yebblies from comment #5)

> Ideally the optimizer would do this by itself, once the literal is stack-allocated.  I suspect it already does in some cases for gdc/ldc.

If I compile this program:


bool foo(in int[] a) {
    return a == [1, 2, 3];
}
void main() {}


With the latest ldc2 with:

ldmd2 -O -release -inline -noboundscheck -output-s test.d


The asm of foo is:

__D4test3fooFxAiZb:
    subl    $20, %esp
    movl    $3, 4(%esp)
    movl    $__D12TypeInfo_xAi6__initZ, (%esp)
    calll   __d_newarrayvT
    movl    $3, 8(%edx)
    movl    $2, 4(%edx)
    movl    $1, (%edx)
    movl    %edx, 12(%esp)
    movl    %eax, 8(%esp)
    movl    28(%esp), %eax
    movl    %eax, 4(%esp)
    movl    24(%esp), %eax
    movl    %eax, (%esp)
    movl    $__D12TypeInfo_Axi6__initZ, 16(%esp)
    calll   __adEq2
    testl   %eax, %eax
    setne   %al
    addl    $20, %esp
    ret $8

--
August 31, 2014
https://issues.dlang.org/show_bug.cgi?id=13381

--- Comment #7 from yebblies <yebblies@gmail.com> ---
(In reply to bearophile_hugs from comment #6)
> (In reply to yebblies from comment #5)
> 
> > Ideally the optimizer would do this by itself, once the literal is stack-allocated.  I suspect it already does in some cases for gdc/ldc.
> 
> If I compile this program:
> 

Like I said, once the literal is stack-allocated it's more likely to work.

--
August 31, 2014
https://issues.dlang.org/show_bug.cgi?id=13381

--- Comment #8 from bearophile_hugs@eml.cc ---
(In reply to yebblies from comment #7)

> Like I said, once the literal is stack-allocated it's more likely to work.

OK, another experiment:


bool foo(in int[] a) {
    immutable static int[3] aux = [1, 2, 3];
    return a == aux;
}
void main() {}


__D4test3fooFxAiZb:
    subl    $20, %esp
    movl    28(%esp), %eax
    movl    %eax, 4(%esp)
    movl    24(%esp), %eax
    movl    %eax, (%esp)
    movl    $__D12TypeInfo_Axi6__initZ, 16(%esp)
    movl    $__D4test3fooFxAiZb3auxyG3i, 12(%esp)
    movl    $3, 8(%esp)
    calll   __adEq2
    testl   %eax, %eax
    setne   %al
    addl    $20, %esp
    ret $8

--
August 31, 2014
https://issues.dlang.org/show_bug.cgi?id=13381

--- Comment #9 from yebblies <yebblies@gmail.com> ---
(In reply to bearophile_hugs from comment #8)
> (In reply to yebblies from comment #7)
> 
> > Like I said, once the literal is stack-allocated it's more likely to work.
> 
> OK, another experiment:
> 
> 
> bool foo(in int[] a) {
>     immutable static int[3] aux = [1, 2, 3];
>     return a == aux;
> }
> void main() {}
> 
> 
> __D4test3fooFxAiZb:
>     subl    $20, %esp
>     movl    28(%esp), %eax
>     movl    %eax, 4(%esp)
>     movl    24(%esp), %eax
>     movl    %eax, (%esp)
>     movl    $__D12TypeInfo_Axi6__initZ, 16(%esp)
>     movl    $__D4test3fooFxAiZb3auxyG3i, 12(%esp)
>     movl    $3, 8(%esp)
>     calll   __adEq2
>     testl   %eax, %eax
>     setne   %al
>     addl    $20, %esp
>     ret $8

Which compiler?  I'd say it's worth filing an optimizer enhancement.

--
August 31, 2014
https://issues.dlang.org/show_bug.cgi?id=13381

--- Comment #10 from bearophile_hugs@eml.cc ---
(In reply to yebblies from comment #9)

> Which compiler?

The latest ldc2, version   0.14.0 (DMD v2.065, LLVM 3.4.2).

dmd is not doing better.
I don't know what gdc does in this case.


> I'd say it's worth filing an optimizer enhancement.

I don't know.

--
« First   ‹ Prev
1 2