On Sunday, 2 August 2020 at 17:31:45 UTC, Bruce Carneal wrote:
import std;

void f0(int[] a, int[] b, int[] dst) @safe {
    dst[] = a[] + b[];
}

void f1(int[] a, int[] b, int[] dst) @trusted {
    const minLen = min(a.length, b.length, dst.length);
    dst[0..minLen] = a[0..minLen] + b[0..minLen];
    assert(dst.length == minLen);
}

I was surprised that f0 ran just fine with a.length and b.length geq dst.length. Is that a bug or a feature?

Assuming it's a feature, are f0 and f1 morally equivalent? I ask because f1 auto-vectorizes in ldc while f0 does not. Not sure why. As a guess I'd say that the front end doesn't hoist bounds checks in f0 or at least doesn't convey the info to the back end in a comprehensible fashion. Non-guesses welcome.

I don't know what's going on auto-vectorization-wise, but to address the behavioral issues, the next thing I would do if I were in your shoes is something like this:

import std.stdio;
int[100]  a, b, dst;
a[]   = 2;
b[]   = 3;
dst[] = 42;
f0(a[0..$], b[0..$], dst[0..50]); // Notice: dst is a smaller slice.
writefln("dst[49] == %d", dst[49]); // Should be 5.
writefln("dst[50] == %d", dst[50]); // 42 or 5?

On my machine (Linux 64-bit DMD v2.093.0) it prints this:
dst[49] == 5
dst[50] == 42

Which suggests that it is doing the minimum-length calculation, as the dst[] values outside of the lesser-sized slice were untouched.

This was DMD, so it's going to be worth trying on your compiler to see what you get.

Reply via email to