GCC-Go - Optimize builds for specific architecture

2.5k views Asked by At

How does one uses environment variables to optimize a go binary?

For instance, with C and GCC, you would set CFLAGS="-O2 -march=znver1 to build with tier 2 optimizations, with specific optimizations for the Zen microarchitecture. I couldn't find an equivalent environment variable in Golang's documentation.

Go does provide a way to disable them all, but not to specify which one to use in case you are using gccgo as the compiler back-end. It is thus very different from other questions asked about optimizations flags for Go in general (Passing an optimization flag to a Go compiler? for instance)

1

There are 1 answers

0
Antoine Viallon On BEST ANSWER

After searching for a very long while, I found the information I needed. First of all, as Adrian mentionned, the standard gc compiler (which is usually the most up-to-date regarding the Go spec), does not support optimization flags (except for disabling them completely using -N -l as mentionned here).

However, if you use GCCGO, there is an environment variable you can use, which is GOGCCFLAGS. Using go env on my system with gcc-go installed, I saw that its default value was -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build920233973=/tmp/go-build -gno-record-gcc-switches -funwind-tables. One can thus override this environment variable and pass other optimizations, like those described in GCCGO's documentation. Standard gcc options seems to work, like -march=native for instance, which is exactly what I was searching for.

Edit: after more testing, it seems that Go often ignores this environment variable, so you have to add -gccgoflags="${GOGCCFLAGS}".

Edit 25/01/2022: Since Go 1.18, the GOAMD64 environment variable was added, allowing you to choose a target x86_64 feature-level (from v1 to v4). The default is GOAMD64=v1, but if you know you'll only target CPUs newer than Sandy Brige or Bulldozer, you can safely use GOAMD64=v2 to gain some performance.

A similar environment variable exists for ARM. You can have more details here: https://github.com/golang/go/wiki/MinimumRequirements#microarchitecture-support