Does Fortran resolve optional arguments and present statements during compile-time?

前端 未结 2 1930
我在风中等你
我在风中等你 2021-01-20 14:07

After a search without any result I want to ask you a question regarding subroutines containing optional arguments and how they are treated by the compiler (run time/compile

相关标签:
2条回答
  • 2021-01-20 14:22

    The Fortran standards are silent on pretty much every aspect of the implementation of the language other than the syntax and semantics. For example, people often think that Fortran passes arguments by reference but the standard only requires that programs behave as if arguments are passed by reference. Implementers are free to use pass-by-pixies if they wish and if they can thereby produce a convincing simulation of pass by reference.

    That's just a long-winded introduction to telling you that how a particular compiler implements a language feature is, in general, compiler-specific. Implementation details are also know to vary from version to version of the same compiler.

    I think that you are wrong to think that the presence of an optional argument will be checked at compile-time even if it is provable that it could be -- I just don't think that that is something that the current crop of compilers do. I expect the compiler to generate a single implementation of the subroutine with optional arguments. It does, after all, rest with the programmer to ensure that a procedure does not attempt to process absent optional arguments.

    If you, the programmer, know that a procedure will be executed many times and if you suspect that different implementations, one with argument b and without c, one vice-versa, then it's on you to determine if separate implementations will be faster than one implementation with optional arguments. If you are concerned about code duplication you could always have yet a third procedure to implement the common code, and call it from both variants.

    Equally, it is on you to inspect the assembler generated by your compiler to see just what your compiler (version) does with the variations in code that you write.

    0 讨论(0)
  • 2021-01-20 14:39

    I will add an example. This is what gfortran-4.8 does with your code with -Ofast (-fdump-tree-optimized). There is only one copy of the subroutine and the if (present()) calls are changed to if (b_1(D) != 0B). Maybe some smaller subroutine would be inlined. Then I would expect such an optimization to kick in, but not here.

    ;; Function abc (__contains_abc_MOD_abc, funcdef_no=0, decl_uid=1875, cgraph_uid=0)
    
    abc (real(kind=4) & restrict a, real(kind=4) * b, real(kind=4) * c)
    {
      struct __st_parameter_dt dt_parm.1;
      struct __st_parameter_dt dt_parm.0;
    
      <bb 2>:
      if (b_1(D) != 0B)
        goto <bb 3>;
      else
        goto <bb 4>;
    
      <bb 3>:
      dt_parm.0.common.filename = &"opt.f90"[1]{lb: 1 sz: 1};
      dt_parm.0.common.line = 13;
      dt_parm.0.common.flags = 128;
      dt_parm.0.common.unit = 6;
      _gfortran_st_write (&dt_parm.0);
      _gfortran_transfer_character_write (&dt_parm.0, &"Provide c"[1]{lb: 1 sz: 1}, 9);
      _gfortran_st_write_done (&dt_parm.0);
      dt_parm.0 ={v} {CLOBBER};
      goto <bb 6>;
    
      <bb 4>:
      if (c_11(D) != 0B)
        goto <bb 5>;
      else
        goto <bb 6>;
    
      <bb 5>:
      dt_parm.1.common.filename = &"opt.f90"[1]{lb: 1 sz: 1};
      dt_parm.1.common.line = 15;
      dt_parm.1.common.flags = 128;
      dt_parm.1.common.unit = 6;
      _gfortran_st_write (&dt_parm.1);
      _gfortran_transfer_character_write (&dt_parm.1, &"Provide b"[1]{lb: 1 sz: 1}, 9);
      _gfortran_st_write_done (&dt_parm.1);
      dt_parm.1 ={v} {CLOBBER};
    
      <bb 6>:
      return;
    
    }
    
    
    
    ;; Function main (main, funcdef_no=2, decl_uid=1889, cgraph_uid=2) (executed once)
    
    main (integer(kind=4) argc, character(kind=1) * * argv)
    {
      real(kind=4) aa;
      real(kind=4) bb;
      real(kind=4) cc;
      static integer(kind=4) options.2[7] = {68, 1023, 0, 0, 1, 1, 0};
    
      <bb 2>:
      _gfortran_set_args (argc_2(D), argv_3(D));
      _gfortran_set_options (7, &options.2[0]);
      abc (&aa, &bb, 0B);
      abc (&aa, 0B, &cc);
      aa ={v} {CLOBBER};
      bb ={v} {CLOBBER};
      cc ={v} {CLOBBER};
      return 0;
    
    }
    

    I checked this is also the case for the final assembly, but it is much more clearly visible here in GIMPLE.

    0 讨论(0)
提交回复
热议问题