|
17 | 17 | #include "llvm/ADT/APSInt.h"
|
18 | 18 | #include "llvm/ADT/ArrayRef.h"
|
19 | 19 | #include "llvm/ADT/BitVector.h"
|
| 20 | +#include "llvm/ADT/DenseSet.h" |
20 | 21 | #include "llvm/ADT/FoldingSet.h"
|
21 | 22 | #include "llvm/ADT/STLExtras.h"
|
22 | 23 | #include "llvm/ADT/SmallPtrSet.h"
|
@@ -12223,7 +12224,56 @@ void SelectionDAG::copyExtraInfo(SDNode *From, SDNode *To) {
|
12223 | 12224 | // Use of operator[] on the DenseMap may cause an insertion, which invalidates
|
12224 | 12225 | // the iterator, hence the need to make a copy to prevent a use-after-free.
|
12225 | 12226 | NodeExtraInfo Copy = I->second;
|
12226 |
| - SDEI[To] = std::move(Copy); |
| 12227 | + if (LLVM_LIKELY(!Copy.PCSections)) { |
| 12228 | + // No deep copy required for the types of extra info set. |
| 12229 | + SDEI[To] = std::move(Copy); |
| 12230 | + return; |
| 12231 | + } |
| 12232 | + |
| 12233 | + // We need to copy NodeExtraInfo to all _new_ nodes that are being introduced |
| 12234 | + // through the replacement of From with To. Otherwise, replacements of a node |
| 12235 | + // (From) with more complex nodes (To and its operands) may result in lost |
| 12236 | + // extra info where the root node (To) is insignificant in further propagating |
| 12237 | + // and using extra info when further lowering to MIR. |
| 12238 | + // |
| 12239 | + // In the first step pre-populate the visited set with the nodes reachable |
| 12240 | + // from the old From node. This avoids copying NodeExtraInfo to parts of the |
| 12241 | + // DAG that is not new and should be left untouched. |
| 12242 | + DenseSet<const SDNode *> Visited; |
| 12243 | + constexpr int MaxDepth = 16; |
| 12244 | + auto VisitFrom = [&Visited](auto &&Self, SDNode *N, int Depth) { |
| 12245 | + if (Depth >= MaxDepth) |
| 12246 | + return; |
| 12247 | + if (!Visited.insert(N).second) |
| 12248 | + return; |
| 12249 | + for (const SDValue &Op : N->op_values()) |
| 12250 | + Self(Self, Op.getNode(), Depth + 1); |
| 12251 | + }; |
| 12252 | + VisitFrom(VisitFrom, From, 0); |
| 12253 | + |
| 12254 | + // Copy extra info to To and all its transitive operands (that are new). |
| 12255 | + auto DeepCopyTo = [this, &Copy, &Visited](auto &&Self, SDNode *To) { |
| 12256 | + if (!Visited.insert(To).second) |
| 12257 | + return true; |
| 12258 | + if (getEntryNode().getNode() == To) { |
| 12259 | + // This should not happen - and if it did, that means From has a depth |
| 12260 | + // greater or equal to MaxDepth, and VisitFrom() could not visit all |
| 12261 | + // common operands. As a result, we're able to reach the entry node. |
| 12262 | + assert(false && "Too complex 'From' node - increase MaxDepth?"); |
| 12263 | + return false; |
| 12264 | + } |
| 12265 | + for (const SDValue &Op : To->op_values()) { |
| 12266 | + if (!Self(Self, Op.getNode())) |
| 12267 | + return false; |
| 12268 | + } |
| 12269 | + SDEI[To] = Copy; |
| 12270 | + return true; |
| 12271 | + }; |
| 12272 | + |
| 12273 | + if (LLVM_UNLIKELY(!DeepCopyTo(DeepCopyTo, To))) { |
| 12274 | + // Fallback - see assert above. |
| 12275 | + SDEI[To] = std::move(Copy); |
| 12276 | + } |
12227 | 12277 | }
|
12228 | 12278 |
|
12229 | 12279 | #ifndef NDEBUG
|
|
0 commit comments