Bug 23169

Summary: Fortran INTENT information not used in the middle-end for optimizations
Product: gcc Reporter: Steven Bosscher <steven>
Component: middle-endAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: enhancement CC: dberlin, dfranke, fxcoudert, gcc-bugs, P.Schaffnit, pinskia, tkoenig
Priority: P2 Keywords: alias, missed-optimization
Version: 4.1.0   
Target Milestone: ---   
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34721
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2010-07-13 10:37:16
Bug Depends on: 38691    
Bug Blocks:    

Description Steven Bosscher 2005-08-01 04:47:21 UTC
In the function bar, the INTENT(IN) markers mean that p and q may not be  
modified by bar.  This means that the constants 3 and 12 can be progagated 
in the function foo.  My guess is that there should be some way for alias 
analysis to be taught about this, so I've added the experts to the CC: list. 
 
       integer function foo(a,b,c) 
          integer, intent(out) :: a 
          integer, intent(in) :: b, c 
          integer p, q 
 
          p = 3 
          q = 12 
 
          a = bar(b,c,p,q) 
 
          foo = p*q 
       end function 
 
       integer function bar(b,c,p,q) 
          integer, intent(in) :: b, c, p, q 
          bar = p*b + q*c 
       end function
Comment 1 Andrew Pinski 2005-08-01 12:07:56 UTC
Confirmed.
Comment 2 Andrew Pinski 2005-10-02 21:27:30 UTC
I think this is just another case of PR 23134.
Comment 3 Steven Bosscher 2005-10-03 06:14:31 UTC
No it is not.
Comment 4 Andrew Pinski 2005-10-09 17:41:43 UTC
There are a couple of problems here. First I noticed that bar in foo is not marked as pure even though the IPA mechanism marked it as such, so that looks like a fortran front-end bug in that it has two different DECLs for the same function.

The second issue after that is filed as PR 24287 which talks about pure functions causing local variables to be call clobbered even though they don't escape.  This issue is related to PR 23134 also.

Here is a testcase which we would not get unless we take intent(in) into account:
       integer function foo(b,c) 
          integer, intent(in) :: b, c 
	  integer :: d, e
	  d = b;
	  e = c;
          call bar(b,c)
 
          foo = d-b + e-c;
       end function 
       

foo should always be zero as bar should not be able to touch b or c.
Comment 5 Steven Bosscher 2008-09-21 13:36:04 UTC
A C equivalent test case "works".  Once the infamous multiple-decls-per-function issue in gfortran is fixed, this bug probably will disappear.
Comment 6 Daniel Franke 2008-12-27 00:38:35 UTC
*** Bug 36076 has been marked as a duplicate of this bug. ***
Comment 7 Daniel Franke 2008-12-29 14:25:50 UTC
(In reply to comment #4)
> Here is a testcase which we would not get unless we take intent(in) into
> account:
[...]
> foo should always be zero as bar should not be able to touch b or c.

Is this really related to the INTENT? For the equivalent C/C++ cases, I tried prototypes with int, int*, const int*, int& and const int& respectively -- only if the arguments are passed by value, the return value of foo is optimized to zero (as shown by "-O3 -fdump-tree-optimized").
Comment 8 Richard Biener 2009-01-02 10:29:23 UTC
There is no way to tell the middle-end about anonymous readonly memory.
Comment 9 Thomas Koenig 2009-01-02 11:04:41 UTC
(In reply to comment #8)
> There is no way to tell the middle-end about anonymous readonly memory.

So, we could either

- teach that to the middle-end (I couldn't, though :-)

- make a duplicate variable for intent(in) variables, to transfer
  the test case from comment #4 into

integer function foo(b,c) 
  integer, intent(in) :: b, c
  integer :: b_shadow, c_shadow;
  integer :: d, e
  b_shadow = b;
  c_shadow = c;
  d = b_shadow;
  e = c_shadow;
  call bar(b,c)
  
  foo = d-b_shadow + e-c_shadow;
end function foo
Comment 10 Daniel Franke 2009-01-03 19:46:27 UTC
Maybe realted: PR29697?!
Comment 11 Daniel Franke 2009-04-14 15:20:32 UTC
The original testcase in #0 appears to be fixed if compiled with -fwhole-file.
Andrew's comment #4 appears to be still an issue?!
Comment 12 Francois-Xavier Coudert 2009-05-03 13:32:52 UTC
(In reply to comment #11)
> The original testcase in #0 appears to be fixed if compiled with -fwhole-file.
> Andrew's comment #4 appears to be still an issue?!

Here's a full testcase showing the remaining issue:

integer function foo()
  interface
    integer function bar(b)
      integer, intent(in) :: b
    end function
  end interface

  integer :: b, d, k
  b = 12
  d = b
  k = bar(b)
  foo = d - b
end function


In this code, the return value of function foo should not be computed, because it's guaranteed to be 0. The missed optimization is still present.

This is something that the middle-end should be taught to honour, so I'm switching the component to middle-end.
Comment 13 Steven Bosscher 2010-07-13 10:37:16 UTC
Still present.
Comment 14 Tobias Burnus 2010-07-13 13:32:26 UTC
(In reply to comment #13)
> Still present.

Well, INTENT(IN), nonclobber, and something more is now supported by the middle end through the "fn spec" attribute (space to make sure this attribute stays internal for now). INTENT(OUT) could be added, but has not so far.

Cf. PR fortran/43665.

See also:
- "Call argument flags." in tree.h
- "gimple_call_arg_flags" in gimple.c
- Initial patch: http://gcc.gnu.org/ml/fortran/2010-05/msg00032.html
- Committal: http://gcc.gnu.org/ml/fortran/2010-05/msg00092.html
Comment 15 Dominique d'Humieres 2013-06-25 09:03:38 UTC
This PR seems to have been fixed by revision 165559 or earlier. Closing as FIXED. Please reopen if I am wrong.