Skip to content

`-optc-O3` getting shadowed by automatically injected -O flags

Consider the following example:

{-# LANGUAGE CApiFFI #-}

{-# OPTIONS_GHC -optc-O3 #-}

module M where

foreign import capi unsafe "stdlib.h exit" c_exit :: Int -> IO ()

However, the -optc-O3 flag has no effect, unless ghc is called without any -O flags, or with -O0.

Here's the resulting C compiler invocations for different -O flags:

$ ghc -fforce-recomp -v -c  m.hs |& grep O3
gcc -fno-stack-protector -DTABLES_NEXT_TO_CODE -O3 -x c /tmp/ghc14023_0/ghc_2.c -o /tmp/ghc14023_0/ghc_3.s -Wimplicit -S -include /opt/ghc/8.2.1/lib/ghc-8.2.1/include/ghcversion.h -I. -I/opt/ghc/8.2.1/lib/ghc-8.2.1/base-4.10.0.0/include -I/opt/ghc/8.2.1/lib/ghc-8.2.1/integer-gmp-1.0.1.0/include -I/opt/ghc/8.2.1/lib/ghc-8.2.1/include
$ ghc -fforce-recomp -O0 -v -c  m.hs |& grep O3
gcc -fno-stack-protector -DTABLES_NEXT_TO_CODE -O3 -x c /tmp/ghc14045_0/ghc_2.c -o /tmp/ghc14045_0/ghc_3.s -Wimplicit -S -include /opt/ghc/8.2.1/lib/ghc-8.2.1/include/ghcversion.h -I. -I/opt/ghc/8.2.1/lib/ghc-8.2.1/base-4.10.0.0/include -I/opt/ghc/8.2.1/lib/ghc-8.2.1/integer-gmp-1.0.1.0/include -I/opt/ghc/8.2.1/lib/ghc-8.2.1/include
$ ghc -fforce-recomp -O1 -v -c  m.hs |& grep O3
gcc -fno-stack-protector -DTABLES_NEXT_TO_CODE -O3 -x c /tmp/ghc14073_0/ghc_2.c -o /tmp/ghc14073_0/ghc_3.s -Wimplicit -S -O -include /opt/ghc/8.2.1/lib/ghc-8.2.1/include/ghcversion.h -I. -I/opt/ghc/8.2.1/lib/ghc-8.2.1/base-4.10.0.0/include -I/opt/ghc/8.2.1/lib/ghc-8.2.1/integer-gmp-1.0.1.0/include -I/opt/ghc/8.2.1/lib/ghc-8.2.1/include
$ ghc -fforce-recomp -O2 -v -c  m.hs |& grep O3
gcc -fno-stack-protector -DTABLES_NEXT_TO_CODE -O3 -x c /tmp/ghc14093_0/ghc_2.c -o /tmp/ghc14093_0/ghc_3.s -Wimplicit -S -O2 -include /opt/ghc/8.2.1/lib/ghc-8.2.1/include/ghcversion.h -I. -I/opt/ghc/8.2.1/lib/ghc-8.2.1/base-4.10.0.0/include -I/opt/ghc/8.2.1/lib/ghc-8.2.1/integer-gmp-1.0.1.0/include -I/opt/ghc/8.2.1/lib/ghc-8.2.1/include
$ ghc -fforce-recomp -O3 -v -c  m.hs |& grep O3
gcc -fno-stack-protector -DTABLES_NEXT_TO_CODE -O3 -x c /tmp/ghc14119_0/ghc_2.c -o /tmp/ghc14119_0/ghc_3.s -Wimplicit -S -O2 -include /opt/ghc/8.2.1/lib/ghc-8.2.1/include/ghcversion.h -I. -I/opt/ghc/8.2.1/lib/ghc-8.2.1/base-4.10.0.0/include -I/opt/ghc/8.2.1/lib/ghc-8.2.1/integer-gmp-1.0.1.0/include -I/opt/ghc/8.2.1/lib/ghc-8.2.1/include

To summarise, here's the resulting effective -O-level passed to gcc:

GHC invocation GCC invocation Effective C `-O`-level
`ghc` `gcc -O3` `-O3`
`ghc -O0` `gcc -O3` `-O3`
`ghc -O1` `gcc -O3 -O1` `-O1`
`ghc -O2` `gcc -O3 -O2` `-O2`
`ghc -O3` `gcc -O3 -O2` `-O2`

Consequently, the only way to have C code compiled with -O3 is to force GHC into -O0 mode; this is obviously not ideal, as it easily kills any benefit you'd gain from passing -O3 to the C compiler... ;-)

I see a few alternatives on how to resolve this:

  1. Have GHC recognise -optc-O[0-9] and suppress automatically injecting any -O<n> of its own
  2. Have GHC inject its automatic -O-flags before user-provided -optc flags
  3. Have GHC inject -optc flags as late as possible on the C compiler command-line
  4. Implement a new variant of the -optc flag which injects its flags as late as possible on the C compiler command-line
Trac metadata
Trac field Value
Version 8.2.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information