`-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:
- Have GHC recognise
-optc-O[0-9]and suppress automatically injecting any-O<n>of its own - Have GHC inject its automatic
-O-flags before user-provided-optcflags - Have GHC inject
-optcflags as late as possible on the C compiler command-line - Implement a new variant of the
-optcflag 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 |