diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-01-19 09:03:23 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-01-19 09:03:23 +0100 |
| commit | 1dc54b7319d19e942473aea8466ffee4502c59a9 (patch) | |
| tree | 4f541d5a7c47fc4ed220367a78df18b28b3f6cd1 /src/test/ui/thinlto | |
| parent | af73e64423a450d887df32e2998b8831d7ec653e (diff) | |
| parent | b91d211b40300a3c026b330e50a6e3e19d71351c (diff) | |
| download | rust-1dc54b7319d19e942473aea8466ffee4502c59a9.tar.gz rust-1dc54b7319d19e942473aea8466ffee4502c59a9.zip | |
Rollup merge of #57268 - peterhj:peterhj-optmergefunc, r=nagisa
Add a target option "merge-functions", and a corresponding -Z flag (works around #57356)
This commit adds a target option "merge-functions", which takes values in ("disabled", "trampolines", or "aliases" (default is "aliases")), to allow targets to opt out of the MergeFunctions LLVM pass. Additionally, the latest commit also adds an optional -Z flag, "merge-functions", which takes the same values and has precedence over the target option when both are specified.
This works around https://github.com/rust-lang/rust/issues/57356.
cc @eddyb @japaric @oli-obk @nox @nagisa
Also thanks to @denzp and @gnzlbg for discussing this on rust-cuda!
### Motivation
Basically, the problem is that the MergeFunctions pass, which rustc currently enables by default at -O2 and -O3 [1], and `extern "ptx-kernel"` functions (specific to the NVPTX target) are currently not compatible with each other. If the MergeFunctions pass is allowed to run, rustc can generate invalid PTX assembly (i.e. a PTX file that is not accepted by the native PTX assembler `ptxas`). Therefore we would like a way to opt out of the MergeFunctions pass, which is what our target option does.
### Related work
The current behavior of rustc is to enable MergeFunctions at -O2 and -O3 [1], and also to enable the use of function aliases within MergeFunctions [2] [3]. MergeFunctions seems to have some benefits, such as reducing code size and fixing a crash [4], which is why it is enabled. However, MergeFunctions both with and without function aliases is incompatible with the NVPTX target; a more detailed example for both cases is given below.
clang's "solution" is to have a "-fmerge-functions" flag that opts in to the MergeFunctions pass, but it is not enabled by default.
### Examples/more details
Consider an example Rust lib using `extern "ptx-kernel"` functions: https://github.com/peterhj/nvptx-mergefunc-bug/blob/master/nocore.rs. If we try to compile this with nightly rustc, we get the following compiler error:
LLVM ERROR: Module has aliases, which NVPTX does not support.
This error happens because: (1) functions `foo` and `bar` have the same body, so are candidates to be merged by MergeFunctions; and (2) rustc configures MergeFunctions to generate function aliases using the "mergefunc-use-aliases" LLVM option [2] [3], but the NVPTX backend does not support those aliases.
Okay, so we can try omitting "mergefunc-use-aliases", and then rustc will happily emit PTX assembly: https://github.com/peterhj/nvptx-mergefunc-bug/blob/master/nocore-mergefunc-nousealiases-bad.ptx. However, this PTX is invalid! When we try to assemble it with `ptxas` (I'm on the CUDA 9.2 toolchain), we get an assembler error:
ptxas nocore-mergefunc-nousealiases-bad.ptx, line 38; error : Illegal call target, device function expected
ptxas fatal : Ptx assembly aborted due to errors
What's happening is that MergeFunctions rewrites the `bar` function to call `foo`. However, directly calling an `extern "ptx-kernel"` function from another `extern "ptx-kernel"` is wrong.
If we disable the MergeFunctions pass from running at all, rustc generates correct PTX assembly: https://github.com/peterhj/nvptx-mergefunc-bug/blob/master/nocore-nomergefunc-ok.ptx
[1] https://github.com/rust-lang/rust/blob/a36b960df626cbb8bea74f01243318b73f0bd201/src/librustc_codegen_ssa/back/write.rs#L155
[2] https://github.com/rust-lang/rust/blob/a36b960df626cbb8bea74f01243318b73f0bd201/src/librustc_codegen_llvm/llvm_util.rs#L64
[3] https://github.com/rust-lang/rust/pull/56358
[4] https://github.com/rust-lang/rust/pull/49479
Diffstat (limited to 'src/test/ui/thinlto')
0 files changed, 0 insertions, 0 deletions
