On Sep 16, 6:15 am, amgarching <alexei.matv...@gmail.com> wrote:
> The code that inspired me is below.
> Works with Intel fails with Gfortran 4.3.2.
You forgot to define the meaning of "Works"
and "fails". You also forgot to mention the
version of the Intel compiler. And more
importantly, why are you using a 3 year old
compiler that just might have a bug that
may have been fixed sometime in the past
3 years?
> You forgot to define the meaning of "Works"
> and "fails". You also forgot to mention the
> version of the Intel compiler. And more
> importantly, why are you using a 3 year old
> compiler that just might have a bug that
> may have been fixed sometime in the past
> 3 years?
It must have been fixed (if it were a bug and not an unspecified
behavior). Indeed with Gfortran 4.4 the output is identical.
A workaround is obvious. But I hoped for an enlightening
discussion to understand the rules to tell legal and illegal code
apart.
I know that aliasing should be avoided and
call assign(x, x)
may even produce a warning with some compilers telling that the
same argument is associated both with intent(in) and intent(out)
parameters. On the other hand
x = x
must be legal in a sane setup. So what is actually happening
if assignment is redefined?
The second form is closer. More precisely, the standard defines it as
call assign_t_1(x,(array_expression))
Note the parens. Specifically, from 12.3.2.1.2 of f2003
"A defined assignment is treated as a reference to the subroutine,
with the left-hand side as the first argument and the right-hand
side enclosed in parentheses as the second argument)."
The parens have an effect much like that of your second form. This makes
defined assignment act like intrinsic assignment in that the RHS is
conceptually evaluated before any changes are made to the LHS. I say
"conceptually" because there can be obvious optimizations in skipping
the extra copy in cases where it doesn't matter.
-- Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
amgarching <alexei.matv...@gmail.com> wrote:
> I know that aliasing should be avoided and
Well, that's a common overgeneralization. Aliasing is fine in some
cases. It is only when you modify things that are aliased that trouble
arises.
> call assign(x, x)
> may even produce a warning with some compilers telling that the
> same argument is associated both with intent(in) and intent(out)
> parameters.
But
call assign(x,(x))
is fine. See my other post from just a minute or so ago.
-- Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
> Note the parens. Specifically, from 12.3.2.1.2 of f2003
> "A defined assignment is treated as a reference to the subroutine,
> with the left-hand side as the first argument and the right-hand
> side enclosed in parentheses as the second argument)."
> The parens have an effect much like that of your second form. This makes
> defined assignment act like intrinsic assignment in that the RHS is
> conceptually evaluated before any changes are made to the LHS. I say
> "conceptually" because there can be obvious optimizations in skipping
> the extra copy in cases where it doesn't matter.
But how does the compiler know, in general, it is one of the
cases that doesn't matter? For an internal procedure, I suppose
the compiler could look inside and maybe figure it out. For
external or module procedure, though, it would be harder.
It would seem, then, much more likely than for ordinary assignment
that the compiler would use a temporary array.
> But how does the compiler know, in general, it is one of the
> cases that doesn't matter? For an internal procedure, I suppose
> the compiler could look inside and maybe figure it out. For
> external or module procedure, though, it would be harder.
The compiler has to recognize that it is dealing with a defined assignment and look to see if there is any possibility of overlap between the left and right sides. If it can prove that there isn't, then it can optimize by not making a copy of the right-hand side. Many compilers already do this sort of thing with regular assignments. That the assignment is implemented by a procedure call is not important.
-- Steve Lionel
Developer Products Division
Intel Corporation
Merrimack, NH
Steve Lionel <steve.lio...@intel.invalid> wrote:
> On 9/16/2011 2:23 PM, glen herrmannsfeldt wrote:
>> But how does the compiler know, in general, it is one of the
>> cases that doesn't matter? For an internal procedure, I suppose
>> the compiler could look inside and maybe figure it out. For
>> external or module procedure, though, it would be harder.
> The compiler has to recognize that it is dealing with a defined > assignment and look to see if there is any possibility of overlap > between the left and right sides. If it can prove that there isn't, > then it can optimize by not making a copy of the right-hand side. Many > compilers already do this sort of thing with regular assignments. That > the assignment is implemented by a procedure call is not important.
I was thinking about cases where the order matters, but if done
in the appropriate order no temporary is needed.
If there is no possible overlap, then the compiler should know.
>> The second form is closer. More precisely, the standard defines it as
> Thanks, This is the kind of confirmation I was hoping for.
> I assume that the ruling that intent(out) allocatable components
> be deallocated upon
> a = whatever
> translated to "call assign(a, (whatever))" is irrelevant then.
> But doing a manual
> call assign(a, a)
> with "a" having allocatable component is illegal, right?
Right. It's pretty much illegal for any arguments, allocatable or not.
From 12.5.2.13 of F2008
"(1) Action that aff ects the allocation status of the entity or a subobject thereof shall be taken through the dummy argument.
(3) Action that a ffects the value of the entity or any subobject of it shall be taken only through the dummy argument unless [POINTER and TARGET exceptions]."
The basic rule is that dummy arguments that are somehow associated with each other can't be changed.
amgarching <alexei.matv...@gmail.com> wrote:
> > The second form is closer. More precisely, the standard defines it as
> I assume that the ruling that intent(out) allocatable components
> be deallocated upon
> a = whatever
> translated to "call assign(a, (whatever))" is irrelevant then.
> But doing a manual
> call assign(a, a)
> with "a" having allocatable component is illegal, right?
Right, as DIck explains. But then
call asign(a,(a))
is fine and is exactly equivalent to the assignment statement. WIth the
parens, the second actual argument is no longer a. It is an expression.
The expression is pretty trivial and has the same value as a, but it
isn't the same thing as a. The allocatable component of the intent(out)
argument *DOES* get deallocated in both the assignment statement form
and the call form. But that deallocation happens after the evaluation of
the expression in the second argument.
-- Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
> Steve Lionel<steve.lio...@intel.invalid> wrote:
>> The compiler has to recognize that it is dealing with a defined
>> assignment and look to see if there is any possibility of overlap
>> between the left and right sides. If it can prove that there isn't,
>> then it can optimize by not making a copy of the right-hand side. Many
>> compilers already do this sort of thing with regular assignments. That
>> the assignment is implemented by a procedure call is not important.
> I was thinking about cases where the order matters, but if done
> in the appropriate order no temporary is needed.
Since in the case of defined assignment, the compiler does not control the order, it would need to be pessimistic in this regard.
> If there is no possible overlap, then the compiler should know.
> Now, consider:
> x(1:99)=x(2:100)
If this was not a defined assignment, then I would expect a modern optimizing compiler to recognize cases that can be done as simple memory copies in whichever order was needed. But for defined assignment, it's much more complex to analyze and such analysis would need to be later in the compilation process with inlining and such. I'd expect fewer such cases to optimize.
-- Steve Lionel
Developer Products Division
Intel Corporation
Merrimack, NH