# Compiler options

**URL:** <https://fortran-lang.discourse.group/t/compiler-options/3300>\
**Category:** Uncategorized\
**Created:** [April 23, 2022, 4:06am UTC](https://fortran-lang.discourse.group/t/compiler-options/3300 "2022-04-23T04:06:35Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [April 23, 2022, 4:06am UTC](https://fortran-lang.discourse.group/t/compiler-options/3300/1 "2022-04-23T04:06:35Z")

</div>

I have tweeted about the -o and -c compiler options and will link to [Compiler options comparison](https://github.com/flang-compiler/f18-llvm-project/blob/not-main/flang/docs/OptionComparison.md). What compiler options do you think are worth mentioning, especially those that people are unaware of?

I plan to write about

**limiting the number of error messages**  
`gfortran -fmax-errors=n`  
`ifort -error-limit:n`

**redirecting compiler errors with 2\>**

**standard-conformance options**

**dusty-deck options**  
such as gfortran -std=legacy

**optimization options**  
-O1 -O2 -O3, -march=native, and for gfortran --ffast-math, but with caveats

**debugging options**  
such as gfortran -fbounds-check -g

**options to promote single to double precision**  
primarily to demonstrate that problems that can arise when relying on such options

Options related to coarrays or OpenMP will be discussed when topics are.

---

<div class="post-metadata">

**Author:** ![plevold](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/plevold/32/754_2.png) [@plevold](https://fortran-lang.discourse.group/u/plevold)\
**Post date:** [April 23, 2022, 6:56am UTC](https://fortran-lang.discourse.group/t/compiler-options/3300/2 "2022-04-23T06:56:46Z")

</div>

One thing I think many is unaware of is that it’s perfectly fine to compile with optimization (like - O2) and debug information (-g) at the same time. This can be useful to debug issues in long and running computations. The compiler may have reordered some code etc. so the debugging experience might not be as intuitive as with -Od/-debug though.

---

<div class="post-metadata">

**Author:** ![sblionel](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/sblionel/32/853_2.png) [@sblionel](https://fortran-lang.discourse.group/u/sblionel)\
**Post date:** [April 23, 2022, 9:42pm UTC](https://fortran-lang.discourse.group/t/compiler-options/3300/4 "2022-04-23T21:42:46Z")

</div>

Standard conformance options are of two kinds, both of which useful. One gives diagnostics when non-standard features are used - this is useful in the development process as sometimes it highlights a usage you had not intended. The second adjusts how the compiler behaves, such as ifort’s -standard-semantics. Compilers with a long history often have default behaviors that don’t match what the current standard says. I have seen many users complain that something doesn’t work right when in fact they were getting the compiler’s traditional, but now non-standard, behavior.

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [April 26, 2022, 2:38pm UTC](https://fortran-lang.discourse.group/t/compiler-options/3300/5 "2022-04-26T14:38:22Z")

</div>

I may mention that

> gfortran -c -fdump-fortran-original -fdump-tree-original a.f90  
> prints the internal representation of the Fortran abstract syntax tree  
> to standard output and writes a C-like representation that is passed  
> to the middle end.

For example, the

> **Fortran code to compute Fibonacci numbers**
>
> ```auto
> module fib_mod
> implicit none
> contains
> elemental function fib(i) result(ifib)
> integer, intent(in) :: i
> integer :: ifib,j,fib_old(2)
> ifib = merge(0, 1, i<1)
> if (i < 3) return
> fib_old = [1,1]
> do j=3,i
> ifib = fib_old(1) + fib_old(2)
> if (j == i) exit
> fib_old = [ifib,fib_old(1)]
> end do
> end function fib
> end module fib_mod
> !
> program test_fib
> use fib_mod, only: fib
> implicit none
> print*,"fib(6) =",fib(6) ! 8
> end program test_fib
> 
> ```

> **gives an AST**
>
> ```auto
> Namespace: A-Z: (UNKNOWN 0)
> procedure name = fib_mod
> symtree: 'fib' || symbol: 'fib'          
> type spec : (INTEGER 4)
> attributes: (PROCEDURE MODULE-PROC FUNCTION ELEMENTAL PURE CONTAINED ALWAYS-EXPLICIT)
> result: ifib
> Formal arglist: i
> symtree: 'fib_mod' || symbol: 'fib_mod'      
> type spec : (UNKNOWN 0)
> attributes: (MODULE )
> 
> code:
> CONTAINS
> 
> Namespace: A-Z: (UNKNOWN 0)
> procedure name = fib
> symtree: 'fib' || symbol: 'fib' from namespace 'fib_mod'
> symtree: 'fib_old' || symbol: 'fib_old'      
> type spec : (INTEGER 4)
> attributes: (VARIABLE DIMENSION)
> Array spec:(1 [0] AS_EXPLICIT 1 2 )
> symtree: 'i' || symbol: 'i'            
> type spec : (INTEGER 4)
> attributes: (VARIABLE DUMMY(IN))
> symtree: 'ifib' || symbol: 'ifib'         
> type spec : (INTEGER 4)
> attributes: (VARIABLE RESULT ALWAYS-EXPLICIT)
> symtree: 'j' || symbol: 'j'            
> type spec : (INTEGER 4)
> attributes: (VARIABLE )
> symtree: 'merge' || symbol: 'merge'        
> type spec : (UNKNOWN 0)
> attributes: (PROCEDURE INTRINSIC-PROC FUNCTION ARRAY-OUTER-DEPENDENCY)
> result: merge
> 
> code:
> ASSIGN fib:ifib __merge_i4[[((0) (1) ((< fib:i 1)))]]
> IF (< fib:i 3)
> RETURN 
> ENDIF
> ASSIGN fib:fib_old(FULL) (/ 1 , 1 /)
> DO fib:j=3 fib:i 1
> ASSIGN fib:ifib (+ fib:fib_old(1) fib:fib_old(2))
> IF (== fib:j fib:i)
> EXIT
> ENDIF
> ASSIGN fib:fib_old(FULL) (/ fib:ifib , fib:fib_old(1) /)
> END DO
>     
> 
> Namespace: A-Z: (UNKNOWN 0)
> procedure name = test_fib
> symtree: 'fib' || symbol: 'fib'          
> type spec : (INTEGER 4)
> attributes: (PROCEDURE MODULE-PROC USE-ASSOC(fib_mod) FUNCTION ELEMENTAL PURE ALWAYS-EXPLICIT)
> result: ifib
> Formal arglist: i
> symtree: 'fib_mod' || symbol: 'fib_mod'      
> type spec : (UNKNOWN 0)
> attributes: (MODULE USE-ASSOC(fib_mod))
> symtree: 'test_fib' || symbol: 'test_fib'     
> type spec : (UNKNOWN 0)
> attributes: (PROGRAM PUBLIC SUBROUTINE IS-MAIN-PROGRAM)
> 
> code:
> WRITE UNIT=6 FMT=-1
> TRANSFER 'fib(6) ='
> TRANSFER fib[[((6))]]
> DT_END
> 
> ```

> **and C-like representation**
>
> ```auto
> __attribute__ ((fn spec (". r ")))
> integer(kind=4) fib (integer(kind=4) & restrict i)
> {
> integer(kind=4) fib_old[2];
> integer(kind=4) ifib;
> integer(kind=4) j;
> 
> {
> static integer(kind=4) A.0[2] = {1, 1};
> 
> ifib = (integer(kind=4)) (*i > 0);
> if (*i <= 2)
> {
> return ifib;
> }
> L.1:;
> (void) __builtin_memcpy ((void *) &fib_old, (void *) &A.0, 8);
> {
> integer(kind=4) D.4223;
> 
> D.4223 = *i;
> j = 3;
> while (1)
> {
> {
> logical(kind=4) D.4226;
> 
> D.4226 = j > D.4223;
> if (D.4226) goto L.3;
> ifib = fib_old[0] + fib_old[1];
> if (*i == j) goto L.3;
> L.4:;
> {
> struct array01_integer(kind=4) atmp.1;
> integer(kind=4) A.2[2];
> 
> typedef integer(kind=4) [2];
> atmp.1.dtype = {.elem_len=4, .rank=1, .type=1};
> atmp.1.dim[0].stride = 1;
> atmp.1.dim[0].lbound = 0;
> atmp.1.dim[0].ubound = 1;
> atmp.1.span = 4;
> atmp.1.data = (void * restrict) &A.2;
> atmp.1.offset = 0;
> (*(integer(kind=4)[2] * restrict) atmp.1.data)[0] = ifib;
> (*(integer(kind=4)[2] * restrict) atmp.1.data)[1] = fib_old[0];
> {
> integer(kind=8) S.4;
> 
> S.4 = 0;
> while (1)
> {
> if (S.4 > 1) goto L.5;
> fib_old[S.4] = (*(integer(kind=4)[2] * restrict) atmp.1.data)[S.4];
> S.4 = S.4 + 1;
> }
> L.5:;
> }
> }
> L.2:;
> j = j + 1;
> }
> }
> L.3:;
> }
> }
> return ifib;
> }
> 
> __attribute__ ((fn spec (". ")))
> void test_fib ()
> {
> {
> struct __st_parameter_dt dt_parm.5;
> 
> dt_parm.5.common.filename = &"fib.f90"[1]{lb: 1 sz: 1};
> dt_parm.5.common.line = 21;
> dt_parm.5.common.flags = 128;
> dt_parm.5.common.unit = 6;
> _gfortran_st_write (&dt_parm.5);
> _gfortran_transfer_character_write (&dt_parm.5, &"fib(6) ="[1]{lb: 1 sz: 1}, 8);
> {
> static integer(kind=4) C.4258 = 6;
> integer(kind=4) D.4259;
> 
> D.4259 = fib (&C.4258);
> _gfortran_transfer_integer_write (&dt_parm.5, &D.4259, 4);
> }
> _gfortran_st_write_done (&dt_parm.5);
> }
> }
> 
> __attribute__ ((externally_visible))
> integer(kind=4) main (integer(kind=4) argc, character(kind=1) * * argv)
> {
> static integer(kind=4) options.6[7] = {2116, 4095, 0, 1, 1, 0, 31};
> 
> _gfortran_set_args (argc, argv);
> _gfortran_set_options (7, &options.6[0]);
> test_fib ();
> return 0;
> }
> 
> ```

Looking at these stages will be useful to a compiler developer when there is a problem. When would it be helpful to an end user? I noticed that when

`integer :: ifib,j,fib_old(2)`

is replaced by the equivalent

```auto
integer :: ifib,j
integer, dimension(2) :: fib_old

```

that the AST’s of the two codes are the same. Maybe looking at intermediate stages could be used to verify that cosmetic code changes have not changed the output of a code (although comparing the results of executables is the first thing to do.)

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [April 26, 2022, 4:48pm UTC](https://fortran-lang.discourse.group/t/compiler-options/3300/6 "2022-04-26T16:48:36Z")

</div>

> [@Beliavsky](#):
>
> Maybe looking at intermediate stages could be used to verify that cosmetic code changes have not changed the output of a code

A project I work on actually did this in early stages. We used a tool to convert from fixed format to free format and used the AST output of a compiler to verify that the converted code was equivalent, since the produced AST was identical.
