August 10, 2004
Kind of a contrived example, but still applicable I suppose.  Walter had mentioned defaulting to "noalias" for function parameters.  If the compiler can enforce this for inout and class parameters then I'm all for it.  I can understand how this may not be possible for pointers, however.


Sean


August 10, 2004
On Tue, 10 Aug 2004 19:37:13 +0000 (UTC), Sean Kelly <sean@f4.ca> wrote:

> Kind of a contrived example, but still applicable I suppose.  Walter had
> mentioned defaulting to "noalias" for function parameters.  If the compiler can
> enforce this for inout and class parameters then I'm all for it.  I can
> understand how this may not be possible for pointers, however.


If checking for aliasing is difficult/time consuming then we could only check in debug builds. eg.

void foo(inout int a, inout int b)
{
  //check a and b and assert if aliased (only in debug builds).
}


If aliasing is rare then noalias is a good default, then an 'alias' keyword is required to tell the compiler when a parameter could be aliased:

void bar(alias inout int a, alias inout int b)
{
  //no check and assert (even in debug builds).
}


If aliasing is only a problem with 'inout' parameters instead of a new keyword, what about a new parameter mode, eg:

void bar(alias int a, alias int b)
{
  //no check and assert (even in debug builds).
}

So we have:
'in'    - (as is currently)
'out'   - (as is currently)
'inout' - (should not be aliased, debug check and assert)
'alias' - (same as inout except could be aliased, no debug check)

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
August 11, 2004
On Wed, 11 Aug 2004 10:28:15 +1200, Regan Heath <regan@netwin.co.nz> wrote:

> So we have:
> 'in'    - (as is currently)
> 'out'   - (as is currently)
> 'inout' - (should not be aliased, debug check and assert)
> 'alias' - (same as inout except could be aliased, no debug check)

I understand that making the 'noalias' as a default for out and inout parameters sounds tempting, but because it is then impossible to quarantee the correctness of the program, it shouldn't be done. I think that the decision whether to take the risk or not should be given to the user. It might be a compiler flag ('assume-noalias') or ability to manually mark the parameters with 'noalias' keyword or compiler extensions. And this doesn't mean that the compiler wouldn't optimize the non-aliased variables unless it has been an order to do so. Of course it can take the optimizations that it can be sure of. For example, if the variables that are used at the same time are insulated in a certain scope, the compiler can quite easily see if aliasing would occur. In my opinion, compilers should produce 100% correct code unless the user is willing to take risks and try out some optimizations.

Also, I think that a separation between the meaning of the program code and the optimization performed on it should be made. That's why the keyword noalias feels a bit bad... How about pragmas?

pragma(noalias, a, b)
void foo(inout int a, inout int b)
{

}


Btw, how can i define multiple pragmas that affect same declaration? Should it be

pragma(foo)
{
pragma(bar)
{
void foobar() { }
}
}

? Looks a bit akward.

pragma(foo)
pragma(bar)
void foobar() {}

looks better.

Also, I find it a bit odd that the compiler must report unknown pragmas as an error... if we had some optimization pragmas that not all compilers support, we must wrap them in a version statements. But can't create a pragma that affected a function AND which would affect only certain compiler:

version(DigitalMars)
{
  pragma(noalias)
}
void foobar(inout a, inout b) {}

Or does this work? If it does, it doesn't make sense, because isn't the version statement considered as a block of fully formed statements (which the pragma currently isn't, it's not terminated with ; but instead it's bound the foobar)?

Well, that went a bit OT... sorry :)

-texmex/sampsa lehtonen
-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/m2/
August 11, 2004
In article <opscjfddfc5a2sq9@digitalmars.com>, Regan Heath says...
>
>If checking for aliasing is difficult/time consuming then we could only check in debug builds. eg.
>
>void foo(inout int a, inout int b)
>{
>   //check a and b and assert if aliased (only in debug builds).
>}
>

Is your proposal that the assert's be inserted by the compiler for debug builds? If so, I like it!

It's consistent with other runtime checks for D, like array bounds, so that would make sense, be intuitive and presumably more straightforward to implement for the compiler developer.

I would guess that array bounds are checked at runtime and not compile time for the same reasons it's hard for aliasing (i.e.: it's very hard for the compiler to resolve if array bounds will be violated or not at compile time).

I think it would also have to check the case where the function accessed a variable outside the function scope that is the same type as 'a':

int b;
August 11, 2004
In article <opsckkmb1035qbu1@macray>, Sampsa Lehtonen says...
>
>I understand that making the 'noalias' as a default for out and inout parameters sounds tempting, but because it is then impossible to quarantee the correctness of the program, it shouldn't be done. I think that the

Please refer to my post just ahead of this one. Debug checks are already done for array bounds and I think would be consistent for noalias for value types and arrays if that is clearly spelled out in the language spec. (like here: http://digitalmars.com/d/arrays.html for Array Bounds Checking spec.).

>decision whether to take the risk or not should be given to the user. It might be a compiler flag ('assume-noalias') or ability to manually mark the parameters with 'noalias' keyword or compiler extensions. And this doesn't mean that the compiler wouldn't optimize the non-aliased variables

I don't think the language needs more keyword/type specifier complexity to carry this out, especially if it is clearly outlined in the spec. what the debug build runtime checks would be responsible for.

I'm way against non-spec. compiler extensions. This language is intended to be portable. And I don't want my CD full of code examples to break because I change compilers.

Compiler flags like 'assume-noalias' to me cover the shortcomings of a language and are one of the biggest learning-curve challenges to beginners, and add a lot of time to optimizing/tuning code (i.e.: let see, if I code this and set this flag, it is this fast, hmmmm, what if I code this, and set this flag, or, oh yea, how about this...). Plus, and this is a very 'real-world' scenario, what if some code is changed that 'assume-noalias' breaks and the developer forgets to tell the build-master about it (or change the build him/herself)?

I think flags like this would be one of the biggest nits for people coming from C# or Java too.

Finally, it is possible, given that some of the infrastructure/archtecture is already there for debug array bounds checking, that the 'noalias' debug runtime checks would both keep the compiler implementation simpler and be more consistent with what users expect, as well as warning them on potential aliasing issues when then are not intended.

Referring to my post just ahead of this one, another pitfall to that idea as outlined there.. I realize that COM Interfaces may be a problem, as well as extern and export. An addition to that spec. proposal would be to exempt those from noalias. That again would be consistent with other parts of the language spec.

>unless it has been an order to do so. Of course it can take the optimizations that it can be sure of. For example, if the variables that are used at the same time are insulated in a certain scope, the compiler can quite easily see if aliasing would occur. In my opinion, compilers

Yes - in this case, the compiler should abort/report/warn and not leave it to the runtime debug checks, as is in the spec. for array bounds checking. But if that is difficult to do or makes things more confusing, I think runtime debug checks are good enough.

- Dave


August 11, 2004
Bahhh! This happened again!! Either my browser or the news server somehow cut my post short (Ok, quit clapping <g>).

Here is is again:

;---

In article <opscjfddfc5a2sq9@digitalmars.com>, Regan Heath says...
>
>If checking for aliasing is difficult/time consuming then we could only check in debug builds. eg.
>
>void foo(inout int a, inout int b)
>{
>   //check a and b and assert if aliased (only in debug builds).
>}
>

Is your proposal that the assert's be inserted by the compiler for debug builds?

If so, I like it!

It's consistent with other runtime checks for D, like array bounds, so that would make sense and be intuitive.

I think it would also have to check the case where the function accessed a variable outside the function scope that is the same type as 'a':

int b;
int[] arr;

/* more code */

void foo(inout int a)
{
// (i) debug assert here?
a++;
arr.length = 5;
if(whatever == true) {
// or (ii) debug assert here - depends on a thorough test case?

b++;

// I'm for (ii) because that is consistent with debug build array bounds //  checking now and would be the easiest to implement.

// runtime array bounds error for debug builds happens here now.
arr[5] = b;
}
}

>
>If aliasing is rare then noalias is a good default, then an 'alias' keyword is required to tell the compiler when a parameter could be aliased:
>
>void bar(alias inout int a, alias inout int b)
>{
>   //no check and assert (even in debug builds).
>}
>
>If aliasing is only a problem with 'inout' parameters instead of a new keyword, what about a new parameter mode, eg:

It would be 'out' and 'inout' for value types; in, out and inout for reference types.

However, I think just changing how out and inout are handled for value types and in/out/inout for array refs. would be Ok, since that would be pretty consistent with both how value types vs. reference types are expected to be handled in D now, and arrays are 'built-in' just like other value types like int, double, etc.

The reason I say this is partly to remove complexity, but also partly because the performance/memory advantage of passing objects by ref. instead of copying them probably outweighs the advantages of 'noalias' most of the time (for reference types). Again, consistent with how the language is implemented.

When I say debug check for array objects, I'm not proposing it be done for individual elements. For value types that is covered by 'no overlapping' in the spec. already and for ref. types it wouldn't matter because the are never 'noalias' anyway (so this would be consistent as above).

This would probably even be pretty intuitive for users of other languages like Java too.

>
>void bar(alias int a, alias int b)
>{
>   //no check and assert (even in debug builds).
>}
>

Maybe we could get by w/o a new keyword at all, since pointers can be used for value types if aliasing is desired. This would also enforce the 'noalias for value types' idea for developers.

I think something close to this just may work!

The proposal would be something close to:
- Change the spec. to 'noalias' for out/inout on value types.
- Same for array references, except all of in/out/inout. This is consistent
because arrays are built-in's while other things passed by ref. are not strictly
built-in's like value types, while arrays are.
- Since non-builtin ref. types are always passed by ref., they act as they do
now.
- Mimic the debug build runtime array bounds check for a 'noalias' check.
- (I added this the 2nd time around:) extern and export specifiers would exempt
the noalias.

This idea:
- Shares consistency with how D handles array bounds checks now.
- Shares consistency with how D handles value, ref. types and built-in's now,
providing a clear delineator that can be followed by developers.
- Much easier to implement than strict compile-time checks.
- Allows D a one-up over other languages:
- Warns on aliasing issues (I believe that Fortran does not)
- Allows for aggressive code gen. for these functions (C/C++ does not)
- Shares the by-value/by-ref. func. param. semantics of Java
- Takes into account COM interfaces, I think.

Pitfalls I can think of off-hand:
- pointer struct members or struct members that reference by ref. types.
- How big a problem would this be out in the real world?
- Could the runtime check be applied for each member here as well, w/o jumping
through hoops?
- Could the spec. leave this as undefined perhaps?

Other thoughts?

Thanks,

- Dave


August 11, 2004
"Ilya Minkov" <minkov@cs.tum.edu> escribió en el mensaje
news:cfasdk$30jv$1@digitaldaemon.com
| You mention Fortran doesn't have the problem. How does Fortran deal with
| aliasing?

Fortran doesn't have pointers, so there's no aliasing.

-----------------------
Carlos Santander Bernal


August 11, 2004
In article <cfdm6s$126s$1@digitaldaemon.com>, Carlos Santander B. says...
>
>"Ilya Minkov" <minkov@cs.tum.edu> escribió en el mensaje
>news:cfasdk$30jv$1@digitaldaemon.com
>| You mention Fortran doesn't have the problem. How does Fortran deal with
>| aliasing?
>
>Fortran doesn't have pointers, so there's no aliasing.
>

No, it's more innocuous than that even..

This f77 compiled with g77 (all I have):

I=1
CALL FOO(I,I)
PRINT *,I
END

SUBROUTINE FOO(J,K)
c       D could have a debug build runtime 'assert' placed by the compiler here
c       checking if J & K referenced the same variable, along the sames lines of
c       array bounds checking in D
J = J + K
K = J * K
PRINT *, J, K
END

produces the 'intuitively wrong' results through aliasing w/o any compiler or runtime warnings:

4 4
4

The way (g77 at least) handles it is it expects you to follow the specs. that say not to write code like that.

The proposal I suggested a little earlier today would not 'noalias' pointers or the inside of 'common' data like arrays, only value types and the built-in arrays passed by ref. (with a debug runtime warning as illustrated above, just like what happens with array bounds checking for debug builds now).

- Dave


August 11, 2004
On Wed, 11 Aug 2004 16:19:13 +0300, Sampsa Lehtonen <snlehton@cc.hut.fi> wrote:
> On Wed, 11 Aug 2004 10:28:15 +1200, Regan Heath <regan@netwin.co.nz> wrote:
>
>> So we have:
>> 'in'    - (as is currently)
>> 'out'   - (as is currently)
>> 'inout' - (should not be aliased, debug check and assert)
>> 'alias' - (same as inout except could be aliased, no debug check)
>
> I understand that making the 'noalias' as a default for out and inout  parameters sounds tempting, but because it is then impossible to quarantee  the correctness of the program, it shouldn't be done.

Is it impossible? In a debug build couldn't the compiler insert checks to ensure the variables are not aliased?

I understand that for pointers you cannot determine whether they are aliased or not, but D's arrays can be checked trivially, and pointers (so far) seem much less important in D than in C/C++.

So perhaps 2 statements could be made:
 - pointers are assumed to be aliased unless 'noalias' is used.
 - other variables are assumed not to be aliased, unless 'alias' is used.

And in debug builds the validity of the above could be checked (where possible).

> I think that the  decision whether to take the risk or not should be given to the user. It  might be a compiler flag ('assume-noalias') or ability to manually mark  the parameters with 'noalias' keyword or compiler extensions. And this  doesn't mean that the compiler wouldn't optimize the non-aliased variables  unless it has been an order to do so. Of course it can take the  optimizations that it can be sure of. For example, if the variables that  are used at the same time are insulated in a certain scope, the compiler  can quite easily see if aliasing would occur. In my opinion, compilers  should produce 100% correct code unless the user is willing to take risks  and try out some optimizations.

I agree with the general statement here. The compiler should produce stable code by default.

I think for most variables in D you can verify whether they are aliased or not, pointers being the big exception that comes to mind, so, given that, if a feature was added to the compilter to check them (where it can) in debug builds and optimise them (where it can) in release builds wouldn't we get stable /and/ fast code.

> Also, I think that a separation between the meaning of the program code  and the optimization performed on it should be made. That's why the  keyword noalias feels a bit bad... How about pragmas?

I dislike pragmas in general.

That said, on one hand I see what you're saying, but on the other, an 'alias' keyword does effect the meaning of the program code, or rather describes a property of the variable which then can have an effect on the program code.

> pragma(noalias, a, b)
> void foo(inout int a, inout int b)
> {
>
> }

Lastly, I don't want to have to type that much. :) Some call me lazy, I prefer efficient.

> Btw, how can i define multiple pragmas that affect same declaration?  Should it be
>
> pragma(foo)
> {
> pragma(bar)
> {
> void foobar() { }
> }
> }
>
> ? Looks a bit akward.
>
> pragma(foo)
> pragma(bar)
> void foobar() {}
>
> looks better.

Is foobar missing it's parameters foo and bar?
If so, I prefer

void foobar(alias inout foo, alias inout bar)
{
}

> Also, I find it a bit odd that the compiler must report unknown pragmas as  an error... if we had some optimization pragmas that not all compilers  support, we must wrap them in a version statements. But can't create a  pragma that affected a function AND which would affect only certain  compiler:
>
> version(DigitalMars)
> {
>    pragma(noalias)
> }
> void foobar(inout a, inout b) {}
>
> Or does this work? If it does, it doesn't make sense, because isn't the  version statement considered as a block of fully formed statements (which  the pragma currently isn't, it's not terminated with ; but instead it's  bound the foobar)?
>
> Well, that went a bit OT... sorry :)

NP.. If you want this to get some attention I'd post it as it's own topic (if you haven't already.. I have not checked).

Regards,
Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
August 12, 2004
"Dave" <Dave_member@pathlink.com> escribió en el mensaje
news:cfdr1n$15ba$1@digitaldaemon.com
| No, it's more innocuous than that even..
|
| This f77 compiled with g77 (all I have):
|
| I=1
| CALL FOO(I,I)
| PRINT *,I
| END
|
| SUBROUTINE FOO(J,K)
| c       D could have a debug build runtime 'assert' placed by the compiler
here
| c       checking if J & K referenced the same variable, along the sames lines
of
| c       array bounds checking in D
| J = J + K
| K = J * K
| PRINT *, J, K
| END
|
| produces the 'intuitively wrong' results through aliasing w/o any compiler or
| runtime warnings:
|
| 4 4
| 4
|
| The way (g77 at least) handles it is it expects you to follow the specs. that
| say not to write code like that.
|
| The proposal I suggested a little earlier today would not 'noalias' pointers
or
| the inside of 'common' data like arrays, only value types and the built-in
| arrays passed by ref. (with a debug runtime warning as illustrated above, just
| like what happens with array bounds checking for debug builds now).
|
| - Dave

Sorry about what I said: I had read it here on this ng, so I just repeated it.

I have a copy of Salford FTN77 Compiler (4.03, Personal Edition. Used to be free, not anymore I think), and it produced the exact same result until I used the "/UNSAFE" flag. From the help file: "/UNSAFE: Used in conjunction with /OPTIMISE in order to improve the execution speed of certain programs by using code re-arrangement techniques". With that flag I got 2's instead of 4's.

-----------------------
Carlos Santander Bernal