Jump to page: 1 2
Thread overview
Eliding of slice range checking
Oct 23, 2019
Per Nordlöw
Oct 23, 2019
kinke
Oct 23, 2019
Per Nordlöw
Oct 25, 2019
Stefan Koch
Oct 25, 2019
Ali Çehreli
Oct 25, 2019
Per Nordlöw
Oct 29, 2019
Per Nordlöw
Oct 23, 2019
Per Nordlöw
Oct 23, 2019
kinke
Oct 29, 2019
Per Nordlöw
Oct 23, 2019
kinke
Oct 24, 2019
Per Nordlöw
Oct 24, 2019
welkam
Oct 24, 2019
Per Nordlöw
Oct 25, 2019
welkam
Oct 29, 2019
Kagamin
Oct 31, 2019
Kagamin
October 23, 2019
Does DMD/LDC avoid range-checking in slice-expressions such as the one in my array-overload of `startsWith` defined as

bool startsWith(T)(scope const(T)[] haystack,
                   scope const(T)[] needle)
{
    if (haystack.length >= needle.length)
    {
        return haystack[0 .. needle.length] == needle; // is slice range checking avoid here?
    }
    return false;
}

///
@safe pure nothrow @nogc unittest
{
    auto x = "beta version";
    assert(x.startsWith("beta"));
}

when building in release mode?

I remember a DMD pull from Ian Buclaw that enabled some eliding but I don't remember if it includes the case above.

How can I investigate the codegen myself here?
October 23, 2019
On Wednesday, 23 October 2019 at 11:20:59 UTC, Per Nordlöw wrote:
> How can I investigate the codegen myself here?

Simply check the IR or asm, e.g., on run.dlang.io. If there's a call to `_d_arraybounds` in the function of interest, bounds checks are enabled.

For your example, the template is inferred to be @safe, and `-release` only elides bounds checks in @system functions (corresponding to `-boundscheck=safeonly`). Use `-boundscheck=off` to elide it in all functions.
October 23, 2019
On Wednesday, 23 October 2019 at 11:33:56 UTC, kinke wrote:
> For your example, the template is inferred to be @safe, and `-release` only elides bounds checks in @system functions (corresponding to `-boundscheck=safeonly`). Use `-boundscheck=off` to elide it in all functions.

Thanks. But I'm talking about the compiler being able to figure out that the expression

    haystack[0 .. needle.length]

_never_ (regardless of compiler flags) needs any range checking because it is _only_ run when

    haystack.length >= needle.length

. Do you follow?
October 23, 2019
On Wednesday, 23 October 2019 at 11:33:56 UTC, kinke wrote:
> Simply check the IR or asm, e.g., on run.dlang.io. If there's a call to `_d_arraybounds` in the function of interest, bounds checks are enabled.

The ASM- and IR-output from the following code is pretty messy for

   ldc with flags `-release -O`

Is it possible to remove cluttering?

https://run.dlang.io/is/mAXOm6
October 23, 2019
On Wednesday, 23 October 2019 at 13:08:34 UTC, Per Nordlöw wrote:
> The ASM- and IR-output from the following code is pretty messy for

You call this messy?!

cmpq	%rdi, %rdx
	jae	.LBB0_2
	xorl	%eax, %eax
	retq
.LBB0_2:
	movq	%rdi, %rax
	testq	%rdi, %rdi
	je	.LBB0_3
	pushq	%rax
	.cfi_def_cfa_offset 16
	movq	%rcx, %rdi
	movq	%rax, %rdx
	callq	memcmp@PLT
	testl	%eax, %eax
	sete	%al
	addq	$8, %rsp
	.cfi_def_cfa_offset 8
	retq
.LBB0_3:
	movb	$1, %al
	retq

Anyway, clearly no bounds checks, LLVM's optimizer works as it should.
October 23, 2019
On Wednesday, 23 October 2019 at 13:08:34 UTC, Per Nordlöw wrote:
> Is it possible to remove cluttering?

godbolt.org supports D as well and is way more powerful than run.dlang.io, besides offering way more LDC versions to choose from. It can also be used to remove the 'cluttering': https://d.godbolt.org/z/ejEmrK
October 24, 2019
On Wednesday, 23 October 2019 at 11:20:59 UTC, Per Nordlöw wrote:
> Does DMD/LDC avoid range-checking in slice-expressions such as the one in my array-overload of `startsWith` defined as
>
> bool startsWith(T)(scope const(T)[] haystack,
>                    scope const(T)[] needle)
> {
>     if (haystack.length >= needle.length)
>     {
>         return haystack[0 .. needle.length] == needle; // is slice range checking avoid here?
>     }
>     return false;
> }
>
> ///
> @safe pure nothrow @nogc unittest
> {
>     auto x = "beta version";
>     assert(x.startsWith("beta"));
> }
>
> when building in release mode?
>
> I remember a DMD pull from Ian Buclaw that enabled some eliding but I don't remember if it includes the case above.
>
> How can I investigate the codegen myself here?

I remember in some video Chandler Carruth said that value range propagation across function boundary was implemented in llvm but later removed because it produced no performance improvement for C and C++ code. I wonder how it fare when used on D code.
October 24, 2019
On Wednesday, 23 October 2019 at 14:52:42 UTC, kinke wrote:
> godbolt.org supports D as well and is way more powerful than run.dlang.io, besides offering way more LDC versions to choose from. It can also be used to remove the 'cluttering': https://d.godbolt.org/z/ejEmrK

Very useful. Especially the mouse-over features for if and return statements. Are there any more D-code constructs that gets in assembly?
October 24, 2019
On Thursday, 24 October 2019 at 18:37:05 UTC, welkam wrote:
> I remember in some video Chandler Carruth said that value range propagation across function boundary was implemented in llvm but later removed because it produced no performance improvement for C and C++ code. I wonder how it fare when used on D code.

Interesting. What uses of VRP do you see in D?
October 25, 2019
On Wednesday, 23 October 2019 at 12:01:47 UTC, Per Nordlöw wrote:
> On Wednesday, 23 October 2019 at 11:33:56 UTC, kinke wrote:
>> For your example, the template is inferred to be @safe, and `-release` only elides bounds checks in @system functions (corresponding to `-boundscheck=safeonly`). Use `-boundscheck=off` to elide it in all functions.
>
> Thanks. But I'm talking about the compiler being able to figure out that the expression
>
>     haystack[0 .. needle.length]
>
> _never_ (regardless of compiler flags) needs any range checking because it is _only_ run when
>
>     haystack.length >= needle.length
>
> . Do you follow?

Actually what you want is that the compiler uses a loop-invariant to only to bounds-checking once on the first loop entry?

That's quite tricky to do for all cases.
What you can do manually is to index the .ptr property which will decay the array to a pointer, and on a pointer you cannot and therefore will not do boundschecking

just replace x = a[i] with x = a.ptr[i];
« First   ‹ Prev
1 2