SH4 in Compiler Explorer
Thanks to the effort of Matt Godbolt (who hilariously enough is a former Dreamcast developer himself), the SuperH GCC toolchain is now available for use with Compiler Explorer, along with all of the SH4-specific compiler flags and options typically used when targeting the Dreamcast. This gives us an invaluable tool for getting quick and immediate feedback on how well a given C or C++ source segment tends to translate into SH4 assembly, offering a little sandbox for testing and optimizing code targeting the Dreamcast.
To arrive at a configuration mirroring a Dreamcast development environment, first select one of the GCC compiler versions for the SH architecture. Secondly, the following compiler options should be used as the baseline configuration:
-ml: compile code for the processor in little-endian mode
-m4-single-only: generate code for the SH4 with a floating-point unit that only supports single-precision arithmetic
-ffast-math: breaks strict IEEE compliance and allows for faster floating point approximations
-O3: optimization level 3
-mfsrra: enables emission of the fsrra instruction for reciprocal square root approximations (not available in GCC 4.7.4).
-mfsca: enables emission of the fsca instruction for sine and cosine approximations (not available in GCC 4.7.4).
-matomic-model=soft-imask: enables support for C11 and C++11 atomics by disabling then reenabling interrupts around atomic variable operations
-ftls-model=local-exec: enables the model used by KOS for supporting variables declared with the "thread_local" keyword
The following are pre-configured templates you can use as sample Dreamcast build configurations:
Tips and Notes
- It has been noted that while
-O3is claimed to be the highest optimization level according to recent GCC documentation, some code differences can still be seen under certain circumstances when using
- The compiler seems to ignore both
- It is highly recommended that C code is written to use
-mfsca(builtin sin/cos) over using inline assembly directly, as this seems to give the compiler more context for code optimization around these instructions.
__builtin_prefetchintrinsic does seem to generate a single "pref" instruction and should be preferred over inline assembly.
- The compiler does not seem smart enough to utilize the FIPR (inner/dot product), FMAC (multiply and accumulate), or FTRV (transform vector) instructions regardless of how embarrassingly vectorizable the supplied C code seems to be, so linear algebra routines are forced to use inline assembly to fully leverage the SH4's SIMD instructions.
- Typically smaller code sizes and more tightly optimized code are seen with newer versions of GCC versus the older ones; however, this is not always the case.
- Evidently, even without a branch predictor, the C++20
[[unlikely]]attributes as well as the GCC intrinsic
__builtin_expect()can have a fairly profound impact on code generation and optimization for conditionals and branches. More information can be found here.
-fipa-ptaallows the compiler to analyze pointer and reference usage beyond the scope of the current compiling function, which very often results in pretty decent performance increases at the cost of increased compile times and RAM usage.
-fltoallows GCC to perform optimizations over the entire program and all translation units as a single entity during the linking phase, for the cost of increased compile times and RAM usage. This frequently results in more performant code.
- An in-depth benchmark comparing the run-time performance and compiled binary size output of every toolchain version officially supported by KOS with various optimization levels can be found here.