-
Notifications
You must be signed in to change notification settings - Fork 12k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[LTO] Turn ImportListsTy into a proper class (NFC) #106427
[LTO] Turn ImportListsTy into a proper class (NFC) #106427
Conversation
This patch turns ImportListsTy into a class that wraps DenseMap<StringRef, ImportMapTy>. Here is the background. I'm planning to reduce the memory footprint of ThinLTO indexing. Specifically, ImportMapTy, the list of imports for a given destination module, will be a hash set of integer IDs indexing into a deduplication table of pairs (SourceModule, GUID), which is a lot like string interning. I'm planning to put this deduplication table as part of ImportListsTy and have each instance of ImportMapTy hold a reference to the deduplication table. Another reason to wrap the DenseMap is that I need to intercept operator[]() so that I can construct an instance of ImportMapTy with a reference to the deduplication table. Note that the default implementation of operator[]() would default-construct ImportMapTy, which I am going to disable.
@llvm/pr-subscribers-llvm-transforms Author: Kazu Hirata (kazutakahirata) ChangesThis patch turns ImportListsTy into a class that wraps Here is the background. I'm planning to reduce the memory footprint Another reason to wrap the DenseMap is that I need to intercept Full diff: https://github.com/llvm/llvm-project/pull/106427.diff 1 Files Affected:
diff --git a/llvm/include/llvm/Transforms/IPO/FunctionImport.h b/llvm/include/llvm/Transforms/IPO/FunctionImport.h
index c06d96bbe62e22..78932c12e76ff8 100644
--- a/llvm/include/llvm/Transforms/IPO/FunctionImport.h
+++ b/llvm/include/llvm/Transforms/IPO/FunctionImport.h
@@ -150,7 +150,24 @@ class FunctionImporter {
};
// A map from destination modules to lists of imports.
- using ImportListsTy = DenseMap<StringRef, ImportMapTy>;
+ class ImportListsTy {
+ public:
+ ImportListsTy() = default;
+ ImportListsTy(size_t Size) : ListsImpl(Size) {}
+
+ ImportMapTy &operator[](StringRef DestMod) {
+ return ListsImpl.try_emplace(DestMod).first->second;
+ }
+
+ size_t size() const { return ListsImpl.size(); }
+
+ using const_iterator = DenseMap<StringRef, ImportMapTy>::const_iterator;
+ const_iterator begin() const { return ListsImpl.begin(); }
+ const_iterator end() const { return ListsImpl.end(); }
+
+ private:
+ DenseMap<StringRef, ImportMapTy> ListsImpl;
+ };
/// The set contains an entry for every global value that the module exports.
/// Depending on the user context, this container is allowed to contain
|
This patch turns ImportListsTy into a class that wraps DenseMap<StringRef, ImportMapTy>. Here is the background. I'm planning to reduce the memory footprint of ThinLTO indexing. Specifically, ImportMapTy, the list of imports for a given destination module, will be a hash set of integer IDs indexing into a deduplication table of pairs (SourceModule, GUID), which is a lot like string interning. I'm planning to put this deduplication table as part of ImportListsTy and have each instance of ImportMapTy hold a reference to the deduplication table. Another reason to wrap the DenseMap is that I need to intercept operator[]() so that I can construct an instance of ImportMapTy with a reference to the deduplication table. Note that the default implementation of operator[]() would default-construct ImportMapTy, which I am going to disable.
We've encountered an issue when integrating this change into Rust. The problem is that this commit removed the possibility to fetch the import list without potentially modifying the DenseMap. Rust can read the ImportLists concurrently from multiple threads, and this may result in crashes, as reported at rust-lang/rust#129749 (comment). At least that's my current theory. Rust was previously using |
So, are there two problems here?
I'm happy to switch to |
Revert rust-lang#129749 to fix segfault in LLVM This reverts commit 8c7a7e3, reversing changes made to a00bd75. Reported in rust-lang#129749 (comment). `@nikic's` theory is that the LLVM API changed in a way that makes it impossible to use concurrently from multiple threads (llvm/llvm-project#106427 (comment)). I pinged `@krasimirgg` who was fine with reverting. r? `@rust-lang/wg-llvm`
It's the same in Rust. It's just that previously the part doing the concurrent accesses was using read-only accesses, while it's now doing potential read-write accesses. From an API perspective this is definitely wrong. Of course, it should only actually be an issue if one of the module identifiers is not part of ImportLists when doing the actual imports, so maybe something is wrong on the Rust side... |
I see. I guess it's still handy to have a read-only access to |
Rollup merge of rust-lang#130477 - tmandry:revert-llvm-20-lto, r=tmandry Revert rust-lang#129749 to fix segfault in LLVM This reverts commit 8c7a7e3, reversing changes made to a00bd75. Reported in rust-lang#129749 (comment). `@nikic's` theory is that the LLVM API changed in a way that makes it impossible to use concurrently from multiple threads (llvm/llvm-project#106427 (comment)). I pinged `@krasimirgg` who was fine with reverting. r? `@rust-lang/wg-llvm`
After some further investigation, this issue occurs when empty or mostly empty (e.g. module inline asm only) modules are part of the thin link. And the reason why LLVM did not hit this problem is this code: llvm-project/llvm/lib/LTO/ThinLTOCodeGenerator.cpp Lines 1102 to 1111 in 0dd5685
So LLVM's solution here was to force-initialize all map entries, while Rust's solution was to use read-only access to the maps. |
That is the old LTO API but fyi the new LTO API (used by lld and gold) uses the same approach: llvm-project/llvm/lib/LTO/LTO.cpp Lines 1706 to 1715 in 0dd5685
|
Revert #129749 to fix segfault in LLVM This reverts commit 8c7a7e346be4cdf13e77ab4acbfb5ade819a4e60, reversing changes made to a00bd75b6c5c96d0a35afa2dc07ce3155112d278. Reported in rust-lang/rust#129749 (comment). `@nikic's` theory is that the LLVM API changed in a way that makes it impossible to use concurrently from multiple threads (llvm/llvm-project#106427 (comment)). I pinged `@krasimirgg` who was fine with reverting. r? `@rust-lang/wg-llvm`
This patch turns ImportListsTy into a class that wraps
DenseMap<StringRef, ImportMapTy>.
Here is the background. I'm planning to reduce the memory footprint
of ThinLTO indexing. Specifically, ImportMapTy, the list of imports
for a given destination module, will be a hash set of integer IDs
indexing into a deduplication table of pairs (SourceModule, GUID),
which is a lot like string interning. I'm planning to put this
deduplication table as part of ImportListsTy and have each instance of
ImportMapTy hold a reference to the deduplication table.
Another reason to wrap the DenseMap is that I need to intercept
operator so that I can construct an instance of ImportMapTy with a
reference to the deduplication table. Note that the default
implementation of operator would default-construct ImportMapTy,
which I am going to disable.