Code Comments
Programming Forum and web based access to our favorite programming groups.I was wondering how the intrinsic inquiry function "present" is implemented in present compilers... If it is evaluated at compile time and if a subroutine with optional arguments is is called at one place without its optional arguments and in another place with its optional arguments then the compiler could make two different versions of the subroutine. During optimisation dead code could then be removed from each of the copies and the branches at the "if (present(MyOptionalArg)) then" lines could be removed so that they caused no runtime overhead. But this approach could lead to many copies (2**(the number of optional arguments)) of such a subroutine, so it may be impractical, or? Kind Regards and Thank You in Advance, Sig Kildegård
Post Follow-up to this messageStig Kildegård Andersen wrote: | I was wondering how the intrinsic inquiry function "present" is implemente d | in present compilers... | | If it is evaluated at compile time and if a subroutine with optional | arguments is is called at one place without its optional arguments and in | another place with its optional arguments then the compiler could make two | different versions of the subroutine. During optimisation dead code could | then be removed from each of the copies and the branches at the "if | (present(MyOptionalArg)) then" lines could be removed so that they caused no | runtime overhead. But this approach could lead to many copies (2**(the | number of optional arguments)) of such a subroutine, so it may be | impractical, or? Well, I can tell you how CVF (and IVF) do that. Since everything is by default passed by reference (or descriptor-by-reference in case of pointers and assumed-shapes), the caller (having explicit interface) supplies NULL references for missing arguments. Thus, the stack always contains N arguments (where N is number of dummy arguments), but some are NULL; there's only one version of the routine. Calls to PRESENT(x) are simply inlined as test whether LOC(x).NE.0. This can lead to funny effects occasionally: program Lie integer, pointer:: p p=>NULL() call Foo(p) contains subroutine Foo(i) integer, optional:: i write(*,*) present(i) !prints "F" (FALSE) end subroutine Foo end program Lie Recently I discovered a little related bug in both CVF and IVF. Namely, due to the mechanism I described, arguments with VALUE attribute (CVF/IVF extension) may not have OPTIONAL attribute as well. The compiler will issue an error if you try to. However, they forgot the case when VALUE is added implicitly, i.e. when the routine has also STDCALL or C attribute (which imply VALUE): Program OpenTest call test(6.) !IVF: T | CVF: F call test(6.,0.) !IVF: T | CVF: F call test(6.,1.) !IVF: T | CVF: T contains subroutine Test(a, b) !DEC$ATTRIBUTES STDCALL:: Test real:: a real, optional:: b write (*,*) present(b) end subroutine Test End Program OpenTest -- Jugoslav ___________ www.geocities.com/jdujic Please reply to the newsgroup. You can find my real e-mail on my home page above.
Post Follow-up to this messageThank You for the swift answer I guess I will have to think a little more before I place successive if statements using the present intrinsic in performance critical places. Kind Regards, Stig Kildegard
Post Follow-up to this message"Stig Kildegård Andersen" <stigkildegaardatmaildotdk> wrote in message news:4178ae0f$0$201$edfadb0f@dread12.news.tele.dk... > I was wondering how the intrinsic inquiry function "present" is implemented > in present compilers... > > If it is evaluated at compile time and if a subroutine with optional > arguments is is called at one place without its optional arguments and in > another place with its optional arguments then the compiler could make two > different versions of the subroutine. How can it, in general, be evaluated at compile time? Fortran allows separate compilation of program units, so if the subroutine is, for example, in a module, the compiler cannot necessarily see any calls from program units that might USE the module. Regards, Mike Metcalf
Post Follow-up to this message> How can it, in general, be evaluated at compile time? Fortran allows > separate compilation of program units, so if the subroutine is, for > example, > in a module, the compiler cannot necessarily see any calls from program > units that might USE the module. True. I was thinking of a situation where you compiled all source files of a program together to allow inter procedural optimisations across multiple source files. Kind Regards, Stig Kildegård
Post Follow-up to this messageStig Kildegard Andersen wrote: | Thank You for the swift answer | | I guess I will have to think a little more before I place successive if | statements using the present intrinsic in performance critical places. A common technique is to use a local variable matched with the optional one; if it's PRESENT, copy the contents into the local, otherwise, keep the default value. integer, optional:: foo integer:: locfoo if (present(foo)) then locfoo = foo else locfoo = -1 end if !use only locfoo from now on J. Giles recently proposed an (IMO) elegant extension, which would make these clumsy constructs much nicer: integer, optional:: foo = -1 !If present, use that, otherwise, assign -1 !use foo normally from now on. If the optional argument is a (large) array, instead of copying, you could use a local pointer: integer, optional, target:: foo(:) integer, pointer:: locfoo(:) if (present(foo)) then locfoo => foo else allocate(locfoo(if_you_need_it)) end if !use only locfoo from now on (Side question about an issue I've never completely got: Does the actual argument matching foo *have to* have TARGET attribute for the code above to be legal?) -- Jugoslav ___________ www.geocities.com/jdujic Please reply to the newsgroup. You can find my real e-mail on my home page above.
Post Follow-up to this message"Jugoslav Dujic" <jdujic@yahoo.com> wrote in message news:2trvobF23nrgjU1@uni-berlin.de... > > integer, optional, target:: foo(:) > integer, pointer:: locfoo(:) > > if (present(foo)) then > locfoo => foo > else > allocate(locfoo(if_you_need_it)) > end if > !use only locfoo from now on > > (Side question about an issue I've never completely got: > Does the actual argument matching foo *have to* have TARGET attribute > for the code above to be legal?) Yes or, better, be a valid target (that it becomes by having either the POINTER attribute or the TARGET attribute). Regards, Mike Metcalf
Post Follow-up to this messageJugoslav Dujic wrote: > J. Giles recently proposed an (IMO) elegant extension, which would make > these clumsy constructs much nicer: > > integer, optional:: foo = -1 !If present, use that, otherwise, assign -1 > !use foo normally from now on. I like the idea (Modula-3 handles optional variables in a similar way), but that sort of syntax is already taken for implictly SAVEd variables :-/ Richard
Post Follow-up to this messageRichard Edgar wrote: | Jugoslav Dujic wrote: | || J. Giles recently proposed an (IMO) elegant extension, which would make || these clumsy constructs much nicer: || || integer, optional:: foo = -1 !If present, use that, otherwise, assign -1 || !use foo normally from now on. | | I like the idea (Modula-3 handles optional variables in a similar way), | but that sort of syntax is already taken for implictly SAVEd variables :-/ But a dummy argument cannot be SAVEd so there's no clash. -- Jugoslav ___________ www.geocities.com/jdujic Please reply to the newsgroup. You can find my real e-mail on my home page above.
Post Follow-up to this messageMichael Metcalf wrote: | "Jugoslav Dujic" <jdujic@yahoo.com> wrote in message | news:2trvobF23nrgjU1@uni-berlin.de... || || integer, optional, target:: foo(:) || integer, pointer:: locfoo(:) || || if (present(foo)) then || locfoo => foo || else || allocate(locfoo(if_you_need_it)) || end if || !use only locfoo from now on || || (Side question about an issue I've never completely got: || Does the actual argument matching foo *have to* have TARGET attribute || for the code above to be legal?) | | Yes or, better, be a valid target (that it becomes by having either the | POINTER attribute or the TARGET attribute). Now, the more difficult question that logically follows: /why/? :-) I fail to see a situation where pointing with a local, non-saved pointer to an array which is declared target only locally could possibly produce undesired effects. Perhaps it has something to do with copy-in/copy-out? What's the principal difference between TARGET and non-target dummies (apart that you can't point to the latter)? -- Jugoslav ___________ www.geocities.com/jdujic Please reply to the newsgroup. You can find my real e-mail on my home page above.
Post Follow-up to this messagePowered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.