www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - safety and auto vectorization

reply Bruce Carneal <bcarneal gmail.com> writes:
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.
Aug 02 2020
next sibling parent Chad Joan <chadjoan gmail.com> writes:
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.
Aug 03 2020
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 8/2/20 1:31 PM, 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.
First, I think this is a bug. A regression in fact. As of 2.077 this works, and before it did not. There is nothing in the spec that says the behavior is defined for this case. Second, it's more than just that. This also runs currently: void main() { auto a = [1, 2, 3]; auto b = [4, 5, 6]; int[] dst = new int[4]; // note the extra element dst[] = a[] + b[]; writeln(dst[3]); } Prior to 2.077, this fails with array length problems. After that it prints (at the moment): 402653184 If I up the size to 5, it fails with a range violation. I strongly suspect some off-by-one errors, but this looks unsafe. -Steve
Aug 03 2020
parent reply Bruce Carneal <bcarneal gmail.com> writes:
On Monday, 3 August 2020 at 18:55:36 UTC, Steven Schveighoffer 
wrote:
 On 8/2/20 1:31 PM, Bruce Carneal wrote:
 import std;
 
 void f0(int[] a, int[] b, int[] dst)  safe {
      dst[] = a[] + b[];
 }
 
[snip of auto-vectorization example]
 
 I was surprised that f0 ran just fine with a.length and 
 b.length geq dst.length.  Is that a bug or a feature?
 
First, I think this is a bug. A regression in fact. As of 2.077 this works, and before it did not. There is nothing in the spec that says the behavior is defined for this case. Second, it's more than just that. This also runs currently: void main() { auto a = [1, 2, 3]; auto b = [4, 5, 6]; int[] dst = new int[4]; // note the extra element dst[] = a[] + b[]; writeln(dst[3]); } Prior to 2.077, this fails with array length problems. After that it prints (at the moment): 402653184 If I up the size to 5, it fails with a range violation. I strongly suspect some off-by-one errors, but this looks unsafe. -Steve
Thanks Steve (and Chad). Summary: underspecified, varying behavior across versions, buggy. Steve, what's the best way for me to report this? Are spec issues lumped in with the other bugzilla reports?
Aug 03 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 8/3/20 3:22 PM, Bruce Carneal wrote:
 
 Thanks Steve (and Chad).  Summary: underspecified, varying behavior 
 across versions, buggy.
 
 Steve, what's the best way for me to report this?  Are spec issues 
 lumped in with the other bugzilla reports?
Yep. You can file under dlang.org with the spec keyword. Although this looks like it's not exactly a spec issue. I'd start it as a dmd bug (I don't know the exact interaction with the compiler and the library). It might also be a druntime bug. -Steve
Aug 03 2020
parent Andy Balba <pwplus7 gmail.com> writes:
On Monday, 3 August 2020 at 19:42:51 UTC, Steven Schveighoffer 
wrote:
 On 8/3/20 3:22 PM, Bruce Carneal wrote:
 
 Thanks Steve (and Chad).  Summary: underspecified, varying 
 behavior across versions, buggy.
 
 Steve, what's the best way for me to report this?  Are spec 
 issues lumped in with the other bugzilla reports?
Yep. You can file under dlang.org with the spec keyword. Although this looks like it's not exactly a spec issue. I'd start it as a dmd bug (I don't know the exact interaction with the compiler and the library). It might also be a druntime bug. -Steve
FWIW ..using gdc Debian 8.3.0-6, dst[]= generates a range error auto a = [1, 2, 3]; auto b = [4, 5, 6]; int[] dst = new int[4]; // note the extra element dst[] = a[] + b[]; writeln(dst[3]);
Aug 04 2020