Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upAdd a target option "merge-functions", and a corresponding -Z flag (works around #57356) #57268
Conversation
rust-highfive
assigned
zackmdavis
Jan 2, 2019
This comment has been minimized.
This comment has been minimized.
|
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @zackmdavis (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
rust-highfive
added
the
S-waiting-on-review
label
Jan 2, 2019
This comment has been minimized.
This comment has been minimized.
rust-highfive
assigned
alexcrichton
and unassigned
zackmdavis
Jan 2, 2019
peterhj
force-pushed the
peterhj:peterhj-optmergefunc
branch
from
7e053a8
to
4aba371
Jan 2, 2019
nagisa
reviewed
Jan 2, 2019
| /// Whether the MergeFunctions LLVM pass should run for this target. | ||
| /// The MergeFunctions pass is generally useful, but some targets may need | ||
| /// to opt out. Defaults to `true`. | ||
| pub merge_functions: bool |
This comment has been minimized.
This comment has been minimized.
nagisa
Jan 2, 2019
Contributor
The target option could probably be forward looking and allow specifying any of merge-functions = disabled, merge-functions = trampolines and merge-functions = aliases.
This comment has been minimized.
This comment has been minimized.
peterhj
Jan 3, 2019
Contributor
The latest commit adds "merge-functions" options for "aliases", "trampolines", and "disabled", as well as a matching -Z flag.
This comment has been minimized.
This comment has been minimized.
|
It would also be nice to gain a
Does the NVPTX target, perchance, support the non- |
This comment has been minimized.
This comment has been minimized.
|
@bors: r+ This seems like a great start! We can always add more bells and whistles in the future too. I'd arguably say that this is an LLVM bug, but I'm fine fixing it on our end |
This comment has been minimized.
This comment has been minimized.
|
|
bors
added
S-waiting-on-bors
and removed
S-waiting-on-review
labels
Jan 2, 2019
This comment has been minimized.
This comment has been minimized.
|
Yes, this is definitely an LLVM bug and it would be good to fix it there in the long term. Would it be possible to do something similar to how weak functions are handled? I.e., when merging functions with the |
This comment has been minimized.
This comment has been minimized.
If we are landing this, then at least an LLVM issue should be filled & cross referenced to a corresponding Rust issue. |
This comment has been minimized.
This comment has been minimized.
The latest commit will add a
Non- |
peterhj
changed the title
Add a target option "merge-functions"
Add a target option "merge-functions", and a corresponding -Z flag
Jan 3, 2019
nagisa
reviewed
Jan 3, 2019
| "aliases" => { | ||
| add("-mergefunc-use-aliases"); | ||
| } | ||
| k => panic!("unknown merge-functions kind: {}", k), |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| @@ -1380,6 +1380,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, | |||
| "whether to use the PLT when calling into shared libraries; | |||
| only has effect for PIC code on systems with ELF binaries | |||
| (default: PLT is disabled if full relro is enabled)"), | |||
| merge_functions: Option<String> = (None, parse_opt_string, [TRACKED], | |||
| "control the operation of the MergeFunctions LLVM pass, taking | |||
| the same values as the target option of the same name"), | |||
This comment has been minimized.
This comment has been minimized.
nagisa
Jan 3, 2019
Contributor
This is going to cause an ICE later when invalid values are provided as an argument, because argument parsing does not verify the valid values. Consider validating this in argument parsing.
rust/src/librustc/session/config.rs
Lines 941 to 948 in 2442823
is a good example of how arguments should be handled.
This comment has been minimized.
This comment has been minimized.
kennytm
added
S-waiting-on-review
and removed
S-waiting-on-bors
labels
Jan 3, 2019
This comment has been minimized.
This comment has been minimized.
|
@bors r+ Thanks! |
This comment has been minimized.
This comment has been minimized.
|
|
bors
added
S-waiting-on-bors
and removed
S-waiting-on-review
labels
Jan 3, 2019
This comment has been minimized.
This comment has been minimized.
|
I've reported https://bugs.llvm.org/show_bug.cgi?id=40232 upstream to track this issue. |
peterhj
referenced this pull request
Jan 5, 2019
Open
MergeFunctions LLVM pass can generate invalid function calls under calling convention #57356
peterhj
force-pushed the
peterhj:peterhj-optmergefunc
branch
from
3cd4013
to
b91d211
Jan 5, 2019
peterhj
changed the title
Add a target option "merge-functions", and a corresponding -Z flag
Add a target option "merge-functions", and a corresponding -Z flag (works around #57356)
Jan 5, 2019
denzp
referenced this pull request
Jan 9, 2019
Open
LLVM ERROR: Module has aliases, which NVPTX does not support. #13
This comment has been minimized.
This comment has been minimized.
|
@bors r=nagisa |
This comment has been minimized.
This comment has been minimized.
|
|
peterhj commentedJan 2, 2019
•
edited
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 #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 assemblerptxas). 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:This error happens because: (1) functions
fooandbarhave 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:What's happening is that MergeFunctions rewrites the
barfunction to callfoo. However, directly calling anextern "ptx-kernel"function from anotherextern "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]
rust/src/librustc_codegen_ssa/back/write.rs
Line 155 in a36b960
[2]
rust/src/librustc_codegen_llvm/llvm_util.rs
Line 64 in a36b960
[3] #56358
[4] #49479