1 | //===-- LegalizeTypes.cpp - Common code for DAG type legalizer ------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements the SelectionDAG::LegalizeTypes method. It transforms |
10 | // an arbitrary well-formed SelectionDAG to only consist of legal types. This |
11 | // is common code shared among the LegalizeTypes*.cpp files. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "LegalizeTypes.h" |
16 | #include "llvm/ADT/SetVector.h" |
17 | #include "llvm/IR/DataLayout.h" |
18 | #include "llvm/Support/CommandLine.h" |
19 | #include "llvm/Support/ErrorHandling.h" |
20 | #include "llvm/Support/raw_ostream.h" |
21 | using namespace llvm; |
22 | |
23 | #define DEBUG_TYPE "legalize-types" |
24 | |
25 | static cl::opt<bool> |
26 | EnableExpensiveChecks("enable-legalize-types-checking" , cl::Hidden); |
27 | |
28 | /// Do extensive, expensive, basic correctness checking. |
29 | void DAGTypeLegalizer::PerformExpensiveChecks() { |
30 | // If a node is not processed, then none of its values should be mapped by any |
31 | // of PromotedIntegers, ExpandedIntegers, ..., ReplacedValues. |
32 | |
33 | // If a node is processed, then each value with an illegal type must be mapped |
34 | // by exactly one of PromotedIntegers, ExpandedIntegers, ..., ReplacedValues. |
35 | // Values with a legal type may be mapped by ReplacedValues, but not by any of |
36 | // the other maps. |
37 | |
38 | // Note that these invariants may not hold momentarily when processing a node: |
39 | // the node being processed may be put in a map before being marked Processed. |
40 | |
41 | // Note that it is possible to have nodes marked NewNode in the DAG. This can |
42 | // occur in two ways. Firstly, a node may be created during legalization but |
43 | // never passed to the legalization core. This is usually due to the implicit |
44 | // folding that occurs when using the DAG.getNode operators. Secondly, a new |
45 | // node may be passed to the legalization core, but when analyzed may morph |
46 | // into a different node, leaving the original node as a NewNode in the DAG. |
47 | // A node may morph if one of its operands changes during analysis. Whether |
48 | // it actually morphs or not depends on whether, after updating its operands, |
49 | // it is equivalent to an existing node: if so, it morphs into that existing |
50 | // node (CSE). An operand can change during analysis if the operand is a new |
51 | // node that morphs, or it is a processed value that was mapped to some other |
52 | // value (as recorded in ReplacedValues) in which case the operand is turned |
53 | // into that other value. If a node morphs then the node it morphed into will |
54 | // be used instead of it for legalization, however the original node continues |
55 | // to live on in the DAG. |
56 | // The conclusion is that though there may be nodes marked NewNode in the DAG, |
57 | // all uses of such nodes are also marked NewNode: the result is a fungus of |
58 | // NewNodes growing on top of the useful nodes, and perhaps using them, but |
59 | // not used by them. |
60 | |
61 | // If a value is mapped by ReplacedValues, then it must have no uses, except |
62 | // by nodes marked NewNode (see above). |
63 | |
64 | // The final node obtained by mapping by ReplacedValues is not marked NewNode. |
65 | // Note that ReplacedValues should be applied iteratively. |
66 | |
67 | // Note that the ReplacedValues map may also map deleted nodes (by iterating |
68 | // over the DAG we never dereference deleted nodes). This means that it may |
69 | // also map nodes marked NewNode if the deallocated memory was reallocated as |
70 | // another node, and that new node was not seen by the LegalizeTypes machinery |
71 | // (for example because it was created but not used). In general, we cannot |
72 | // distinguish between new nodes and deleted nodes. |
73 | SmallVector<SDNode*, 16> NewNodes; |
74 | for (SDNode &Node : DAG.allnodes()) { |
75 | // Remember nodes marked NewNode - they are subject to extra checking below. |
76 | if (Node.getNodeId() == NewNode) |
77 | NewNodes.push_back(Elt: &Node); |
78 | |
79 | for (unsigned i = 0, e = Node.getNumValues(); i != e; ++i) { |
80 | SDValue Res(&Node, i); |
81 | bool Failed = false; |
82 | // Don't create a value in map. |
83 | auto ResId = ValueToIdMap.lookup(Val: Res); |
84 | |
85 | unsigned Mapped = 0; |
86 | if (ResId) { |
87 | auto I = ReplacedValues.find(Val: ResId); |
88 | if (I != ReplacedValues.end()) { |
89 | Mapped |= 1; |
90 | // Check that remapped values are only used by nodes marked NewNode. |
91 | for (SDUse &U : Node.uses()) |
92 | if (U.getResNo() == i) |
93 | assert(U.getUser()->getNodeId() == NewNode && |
94 | "Remapped value has non-trivial use!" ); |
95 | |
96 | // Check that the final result of applying ReplacedValues is not |
97 | // marked NewNode. |
98 | auto NewValId = I->second; |
99 | I = ReplacedValues.find(Val: NewValId); |
100 | while (I != ReplacedValues.end()) { |
101 | NewValId = I->second; |
102 | I = ReplacedValues.find(Val: NewValId); |
103 | } |
104 | SDValue NewVal = getSDValue(Id&: NewValId); |
105 | (void)NewVal; |
106 | assert(NewVal.getNode()->getNodeId() != NewNode && |
107 | "ReplacedValues maps to a new node!" ); |
108 | } |
109 | if (PromotedIntegers.count(Val: ResId)) |
110 | Mapped |= 2; |
111 | if (SoftenedFloats.count(Val: ResId)) |
112 | Mapped |= 4; |
113 | if (ScalarizedVectors.count(Val: ResId)) |
114 | Mapped |= 8; |
115 | if (ExpandedIntegers.count(Val: ResId)) |
116 | Mapped |= 16; |
117 | if (ExpandedFloats.count(Val: ResId)) |
118 | Mapped |= 32; |
119 | if (SplitVectors.count(Val: ResId)) |
120 | Mapped |= 64; |
121 | if (WidenedVectors.count(Val: ResId)) |
122 | Mapped |= 128; |
123 | if (PromotedFloats.count(Val: ResId)) |
124 | Mapped |= 256; |
125 | if (SoftPromotedHalfs.count(Val: ResId)) |
126 | Mapped |= 512; |
127 | } |
128 | |
129 | if (Node.getNodeId() != Processed) { |
130 | // Since we allow ReplacedValues to map deleted nodes, it may map nodes |
131 | // marked NewNode too, since a deleted node may have been reallocated as |
132 | // another node that has not been seen by the LegalizeTypes machinery. |
133 | if ((Node.getNodeId() == NewNode && Mapped > 1) || |
134 | (Node.getNodeId() != NewNode && Mapped != 0)) { |
135 | dbgs() << "Unprocessed value in a map!" ; |
136 | Failed = true; |
137 | } |
138 | } else if (isTypeLegal(VT: Res.getValueType()) || IgnoreNodeResults(N: &Node)) { |
139 | if (Mapped > 1) { |
140 | dbgs() << "Value with legal type was transformed!" ; |
141 | Failed = true; |
142 | } |
143 | } else { |
144 | if (Mapped == 0) { |
145 | SDValue NodeById = IdToValueMap.lookup(Val: ResId); |
146 | // It is possible the node has been remapped to another node and had |
147 | // its Id updated in the Value to Id table. The node it remapped to |
148 | // may not have been processed yet. Look up the Id in the Id to Value |
149 | // table and re-check the Processed state. If the node hasn't been |
150 | // remapped we'll get the same state as we got earlier. |
151 | if (NodeById->getNodeId() == Processed) { |
152 | dbgs() << "Processed value not in any map!" ; |
153 | Failed = true; |
154 | } |
155 | } else if (Mapped & (Mapped - 1)) { |
156 | dbgs() << "Value in multiple maps!" ; |
157 | Failed = true; |
158 | } |
159 | } |
160 | |
161 | if (Failed) { |
162 | if (Mapped & 1) |
163 | dbgs() << " ReplacedValues" ; |
164 | if (Mapped & 2) |
165 | dbgs() << " PromotedIntegers" ; |
166 | if (Mapped & 4) |
167 | dbgs() << " SoftenedFloats" ; |
168 | if (Mapped & 8) |
169 | dbgs() << " ScalarizedVectors" ; |
170 | if (Mapped & 16) |
171 | dbgs() << " ExpandedIntegers" ; |
172 | if (Mapped & 32) |
173 | dbgs() << " ExpandedFloats" ; |
174 | if (Mapped & 64) |
175 | dbgs() << " SplitVectors" ; |
176 | if (Mapped & 128) |
177 | dbgs() << " WidenedVectors" ; |
178 | if (Mapped & 256) |
179 | dbgs() << " PromotedFloats" ; |
180 | if (Mapped & 512) |
181 | dbgs() << " SoftPromoteHalfs" ; |
182 | dbgs() << "\n" ; |
183 | llvm_unreachable(nullptr); |
184 | } |
185 | } |
186 | } |
187 | |
188 | #ifndef NDEBUG |
189 | // Checked that NewNodes are only used by other NewNodes. |
190 | for (SDNode *N : NewNodes) { |
191 | for (SDNode *U : N->users()) |
192 | assert(U->getNodeId() == NewNode && "NewNode used by non-NewNode!" ); |
193 | } |
194 | #endif |
195 | } |
196 | |
197 | /// This is the main entry point for the type legalizer. This does a top-down |
198 | /// traversal of the dag, legalizing types as it goes. Returns "true" if it made |
199 | /// any changes. |
200 | bool DAGTypeLegalizer::run() { |
201 | bool Changed = false; |
202 | |
203 | // Create a dummy node (which is not added to allnodes), that adds a reference |
204 | // to the root node, preventing it from being deleted, and tracking any |
205 | // changes of the root. |
206 | HandleSDNode Dummy(DAG.getRoot()); |
207 | Dummy.setNodeId(Unanalyzed); |
208 | |
209 | // The root of the dag may dangle to deleted nodes until the type legalizer is |
210 | // done. Set it to null to avoid confusion. |
211 | DAG.setRoot(SDValue()); |
212 | |
213 | // Walk all nodes in the graph, assigning them a NodeId of 'ReadyToProcess' |
214 | // (and remembering them) if they are leaves and assigning 'Unanalyzed' if |
215 | // non-leaves. |
216 | for (SDNode &Node : DAG.allnodes()) { |
217 | if (Node.getNumOperands() == 0) { |
218 | Node.setNodeId(ReadyToProcess); |
219 | Worklist.push_back(Elt: &Node); |
220 | } else { |
221 | Node.setNodeId(Unanalyzed); |
222 | } |
223 | } |
224 | |
225 | // Now that we have a set of nodes to process, handle them all. |
226 | while (!Worklist.empty()) { |
227 | #ifndef EXPENSIVE_CHECKS |
228 | if (EnableExpensiveChecks) |
229 | #endif |
230 | PerformExpensiveChecks(); |
231 | |
232 | SDNode *N = Worklist.pop_back_val(); |
233 | assert(N->getNodeId() == ReadyToProcess && |
234 | "Node should be ready if on worklist!" ); |
235 | |
236 | // Preserve fast math flags |
237 | SDNodeFlags FastMathFlags = N->getFlags() & SDNodeFlags::FastMathFlags; |
238 | SelectionDAG::FlagInserter FlagsInserter(DAG, FastMathFlags); |
239 | |
240 | LLVM_DEBUG(dbgs() << "\nLegalizing node: " ; N->dump(&DAG)); |
241 | if (IgnoreNodeResults(N)) { |
242 | LLVM_DEBUG(dbgs() << "Ignoring node results\n" ); |
243 | goto ScanOperands; |
244 | } |
245 | |
246 | // Scan the values produced by the node, checking to see if any result |
247 | // types are illegal. |
248 | for (unsigned i = 0, NumResults = N->getNumValues(); i < NumResults; ++i) { |
249 | EVT ResultVT = N->getValueType(ResNo: i); |
250 | LLVM_DEBUG(dbgs() << "Analyzing result type: " << ResultVT << "\n" ); |
251 | switch (getTypeAction(VT: ResultVT)) { |
252 | case TargetLowering::TypeLegal: |
253 | LLVM_DEBUG(dbgs() << "Legal result type\n" ); |
254 | break; |
255 | case TargetLowering::TypeScalarizeScalableVector: |
256 | report_fatal_error( |
257 | reason: "Scalarization of scalable vectors is not supported." ); |
258 | // The following calls must take care of *all* of the node's results, |
259 | // not just the illegal result they were passed (this includes results |
260 | // with a legal type). Results can be remapped using ReplaceValueWith, |
261 | // or their promoted/expanded/etc values registered in PromotedIntegers, |
262 | // ExpandedIntegers etc. |
263 | case TargetLowering::TypePromoteInteger: |
264 | PromoteIntegerResult(N, ResNo: i); |
265 | Changed = true; |
266 | goto NodeDone; |
267 | case TargetLowering::TypeExpandInteger: |
268 | ExpandIntegerResult(N, ResNo: i); |
269 | Changed = true; |
270 | goto NodeDone; |
271 | case TargetLowering::TypeSoftenFloat: |
272 | SoftenFloatResult(N, ResNo: i); |
273 | Changed = true; |
274 | goto NodeDone; |
275 | case TargetLowering::TypeExpandFloat: |
276 | ExpandFloatResult(N, ResNo: i); |
277 | Changed = true; |
278 | goto NodeDone; |
279 | case TargetLowering::TypeScalarizeVector: |
280 | ScalarizeVectorResult(N, ResNo: i); |
281 | Changed = true; |
282 | goto NodeDone; |
283 | case TargetLowering::TypeSplitVector: |
284 | SplitVectorResult(N, ResNo: i); |
285 | Changed = true; |
286 | goto NodeDone; |
287 | case TargetLowering::TypeWidenVector: |
288 | WidenVectorResult(N, ResNo: i); |
289 | Changed = true; |
290 | goto NodeDone; |
291 | case TargetLowering::TypePromoteFloat: |
292 | PromoteFloatResult(N, ResNo: i); |
293 | Changed = true; |
294 | goto NodeDone; |
295 | case TargetLowering::TypeSoftPromoteHalf: |
296 | SoftPromoteHalfResult(N, ResNo: i); |
297 | Changed = true; |
298 | goto NodeDone; |
299 | } |
300 | } |
301 | |
302 | ScanOperands: |
303 | // Scan the operand list for the node, handling any nodes with operands that |
304 | // are illegal. |
305 | { |
306 | unsigned NumOperands = N->getNumOperands(); |
307 | bool NeedsReanalyzing = false; |
308 | unsigned i; |
309 | for (i = 0; i != NumOperands; ++i) { |
310 | if (IgnoreNodeResults(N: N->getOperand(Num: i).getNode())) |
311 | continue; |
312 | |
313 | const auto &Op = N->getOperand(Num: i); |
314 | LLVM_DEBUG(dbgs() << "Analyzing operand: " ; Op.dump(&DAG)); |
315 | EVT OpVT = Op.getValueType(); |
316 | switch (getTypeAction(VT: OpVT)) { |
317 | case TargetLowering::TypeLegal: |
318 | LLVM_DEBUG(dbgs() << "Legal operand\n" ); |
319 | continue; |
320 | case TargetLowering::TypeScalarizeScalableVector: |
321 | report_fatal_error( |
322 | reason: "Scalarization of scalable vectors is not supported." ); |
323 | // The following calls must either replace all of the node's results |
324 | // using ReplaceValueWith, and return "false"; or update the node's |
325 | // operands in place, and return "true". |
326 | case TargetLowering::TypePromoteInteger: |
327 | NeedsReanalyzing = PromoteIntegerOperand(N, OpNo: i); |
328 | Changed = true; |
329 | break; |
330 | case TargetLowering::TypeExpandInteger: |
331 | NeedsReanalyzing = ExpandIntegerOperand(N, OpNo: i); |
332 | Changed = true; |
333 | break; |
334 | case TargetLowering::TypeSoftenFloat: |
335 | NeedsReanalyzing = SoftenFloatOperand(N, OpNo: i); |
336 | Changed = true; |
337 | break; |
338 | case TargetLowering::TypeExpandFloat: |
339 | NeedsReanalyzing = ExpandFloatOperand(N, OpNo: i); |
340 | Changed = true; |
341 | break; |
342 | case TargetLowering::TypeScalarizeVector: |
343 | NeedsReanalyzing = ScalarizeVectorOperand(N, OpNo: i); |
344 | Changed = true; |
345 | break; |
346 | case TargetLowering::TypeSplitVector: |
347 | NeedsReanalyzing = SplitVectorOperand(N, OpNo: i); |
348 | Changed = true; |
349 | break; |
350 | case TargetLowering::TypeWidenVector: |
351 | NeedsReanalyzing = WidenVectorOperand(N, OpNo: i); |
352 | Changed = true; |
353 | break; |
354 | case TargetLowering::TypePromoteFloat: |
355 | NeedsReanalyzing = PromoteFloatOperand(N, OpNo: i); |
356 | Changed = true; |
357 | break; |
358 | case TargetLowering::TypeSoftPromoteHalf: |
359 | NeedsReanalyzing = SoftPromoteHalfOperand(N, OpNo: i); |
360 | Changed = true; |
361 | break; |
362 | } |
363 | break; |
364 | } |
365 | |
366 | // The sub-method updated N in place. Check to see if any operands are new, |
367 | // and if so, mark them. If the node needs revisiting, don't add all users |
368 | // to the worklist etc. |
369 | if (NeedsReanalyzing) { |
370 | assert(N->getNodeId() == ReadyToProcess && "Node ID recalculated?" ); |
371 | |
372 | N->setNodeId(NewNode); |
373 | // Recompute the NodeId and correct processed operands, adding the node to |
374 | // the worklist if ready. |
375 | SDNode *M = AnalyzeNewNode(N); |
376 | if (M == N) |
377 | // The node didn't morph - nothing special to do, it will be revisited. |
378 | continue; |
379 | |
380 | // The node morphed - this is equivalent to legalizing by replacing every |
381 | // value of N with the corresponding value of M. So do that now. |
382 | assert(N->getNumValues() == M->getNumValues() && |
383 | "Node morphing changed the number of results!" ); |
384 | for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) |
385 | // Replacing the value takes care of remapping the new value. |
386 | ReplaceValueWith(From: SDValue(N, i), To: SDValue(M, i)); |
387 | assert(N->getNodeId() == NewNode && "Unexpected node state!" ); |
388 | // The node continues to live on as part of the NewNode fungus that |
389 | // grows on top of the useful nodes. Nothing more needs to be done |
390 | // with it - move on to the next node. |
391 | continue; |
392 | } |
393 | |
394 | if (i == NumOperands) { |
395 | LLVM_DEBUG(dbgs() << "Legally typed node: " ; N->dump(&DAG)); |
396 | } |
397 | } |
398 | NodeDone: |
399 | |
400 | // If we reach here, the node was processed, potentially creating new nodes. |
401 | // Mark it as processed and add its users to the worklist as appropriate. |
402 | assert(N->getNodeId() == ReadyToProcess && "Node ID recalculated?" ); |
403 | N->setNodeId(Processed); |
404 | |
405 | for (SDNode *User : N->users()) { |
406 | int NodeId = User->getNodeId(); |
407 | |
408 | // This node has two options: it can either be a new node or its Node ID |
409 | // may be a count of the number of operands it has that are not ready. |
410 | if (NodeId > 0) { |
411 | User->setNodeId(NodeId-1); |
412 | |
413 | // If this was the last use it was waiting on, add it to the ready list. |
414 | if (NodeId-1 == ReadyToProcess) |
415 | Worklist.push_back(Elt: User); |
416 | continue; |
417 | } |
418 | |
419 | // If this is an unreachable new node, then ignore it. If it ever becomes |
420 | // reachable by being used by a newly created node then it will be handled |
421 | // by AnalyzeNewNode. |
422 | if (NodeId == NewNode) |
423 | continue; |
424 | |
425 | // Otherwise, this node is new: this is the first operand of it that |
426 | // became ready. Its new NodeId is the number of operands it has minus 1 |
427 | // (as this node is now processed). |
428 | assert(NodeId == Unanalyzed && "Unknown node ID!" ); |
429 | User->setNodeId(User->getNumOperands() - 1); |
430 | |
431 | // If the node only has a single operand, it is now ready. |
432 | if (User->getNumOperands() == 1) |
433 | Worklist.push_back(Elt: User); |
434 | } |
435 | } |
436 | |
437 | #ifndef EXPENSIVE_CHECKS |
438 | if (EnableExpensiveChecks) |
439 | #endif |
440 | PerformExpensiveChecks(); |
441 | |
442 | // If the root changed (e.g. it was a dead load) update the root. |
443 | DAG.setRoot(Dummy.getValue()); |
444 | |
445 | // Remove dead nodes. This is important to do for cleanliness but also before |
446 | // the checking loop below. Implicit folding by the DAG.getNode operators and |
447 | // node morphing can cause unreachable nodes to be around with their flags set |
448 | // to new. |
449 | DAG.RemoveDeadNodes(); |
450 | |
451 | // In a debug build, scan all the nodes to make sure we found them all. This |
452 | // ensures that there are no cycles and that everything got processed. |
453 | #ifndef NDEBUG |
454 | for (SDNode &Node : DAG.allnodes()) { |
455 | bool Failed = false; |
456 | |
457 | // Check that all result types are legal. |
458 | if (!IgnoreNodeResults(&Node)) |
459 | for (unsigned i = 0, NumVals = Node.getNumValues(); i < NumVals; ++i) |
460 | if (!isTypeLegal(Node.getValueType(i))) { |
461 | dbgs() << "Result type " << i << " illegal: " ; |
462 | Node.dump(&DAG); |
463 | Failed = true; |
464 | } |
465 | |
466 | // Check that all operand types are legal. |
467 | for (unsigned i = 0, NumOps = Node.getNumOperands(); i < NumOps; ++i) |
468 | if (!IgnoreNodeResults(Node.getOperand(i).getNode()) && |
469 | !isTypeLegal(Node.getOperand(i).getValueType())) { |
470 | dbgs() << "Operand type " << i << " illegal: " ; |
471 | Node.getOperand(i).dump(&DAG); |
472 | Failed = true; |
473 | } |
474 | |
475 | if (Node.getNodeId() != Processed) { |
476 | if (Node.getNodeId() == NewNode) |
477 | dbgs() << "New node not analyzed?\n" ; |
478 | else if (Node.getNodeId() == Unanalyzed) |
479 | dbgs() << "Unanalyzed node not noticed?\n" ; |
480 | else if (Node.getNodeId() > 0) |
481 | dbgs() << "Operand not processed?\n" ; |
482 | else if (Node.getNodeId() == ReadyToProcess) |
483 | dbgs() << "Not added to worklist?\n" ; |
484 | Failed = true; |
485 | } |
486 | |
487 | if (Failed) { |
488 | Node.dump(&DAG); dbgs() << "\n" ; |
489 | llvm_unreachable(nullptr); |
490 | } |
491 | } |
492 | #endif |
493 | |
494 | return Changed; |
495 | } |
496 | |
497 | /// The specified node is the root of a subtree of potentially new nodes. |
498 | /// Correct any processed operands (this may change the node) and calculate the |
499 | /// NodeId. If the node itself changes to a processed node, it is not remapped - |
500 | /// the caller needs to take care of this. Returns the potentially changed node. |
501 | SDNode *DAGTypeLegalizer::AnalyzeNewNode(SDNode *N) { |
502 | // If this was an existing node that is already done, we're done. |
503 | if (N->getNodeId() != NewNode && N->getNodeId() != Unanalyzed) |
504 | return N; |
505 | |
506 | // Okay, we know that this node is new. Recursively walk all of its operands |
507 | // to see if they are new also. The depth of this walk is bounded by the size |
508 | // of the new tree that was constructed (usually 2-3 nodes), so we don't worry |
509 | // about revisiting of nodes. |
510 | // |
511 | // As we walk the operands, keep track of the number of nodes that are |
512 | // processed. If non-zero, this will become the new nodeid of this node. |
513 | // Operands may morph when they are analyzed. If so, the node will be |
514 | // updated after all operands have been analyzed. Since this is rare, |
515 | // the code tries to minimize overhead in the non-morphing case. |
516 | |
517 | std::vector<SDValue> NewOps; |
518 | unsigned NumProcessed = 0; |
519 | for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { |
520 | SDValue OrigOp = N->getOperand(Num: i); |
521 | SDValue Op = OrigOp; |
522 | |
523 | AnalyzeNewValue(Val&: Op); // Op may morph. |
524 | |
525 | if (Op.getNode()->getNodeId() == Processed) |
526 | ++NumProcessed; |
527 | |
528 | if (!NewOps.empty()) { |
529 | // Some previous operand changed. Add this one to the list. |
530 | NewOps.push_back(x: Op); |
531 | } else if (Op != OrigOp) { |
532 | // This is the first operand to change - add all operands so far. |
533 | llvm::append_range(C&: NewOps, R: N->ops().take_front(N: i)); |
534 | NewOps.push_back(x: Op); |
535 | } |
536 | } |
537 | |
538 | // Some operands changed - update the node. |
539 | if (!NewOps.empty()) { |
540 | SDNode *M = DAG.UpdateNodeOperands(N, Ops: NewOps); |
541 | if (M != N) { |
542 | // The node morphed into a different node. Normally for this to happen |
543 | // the original node would have to be marked NewNode. However this can |
544 | // in theory momentarily not be the case while ReplaceValueWith is doing |
545 | // its stuff. Mark the original node NewNode to help basic correctness |
546 | // checking. |
547 | N->setNodeId(NewNode); |
548 | if (M->getNodeId() != NewNode && M->getNodeId() != Unanalyzed) |
549 | // It morphed into a previously analyzed node - nothing more to do. |
550 | return M; |
551 | |
552 | // It morphed into a different new node. Do the equivalent of passing |
553 | // it to AnalyzeNewNode: expunge it and calculate the NodeId. No need |
554 | // to remap the operands, since they are the same as the operands we |
555 | // remapped above. |
556 | N = M; |
557 | } |
558 | } |
559 | |
560 | // Calculate the NodeId. |
561 | N->setNodeId(N->getNumOperands() - NumProcessed); |
562 | if (N->getNodeId() == ReadyToProcess) |
563 | Worklist.push_back(Elt: N); |
564 | |
565 | return N; |
566 | } |
567 | |
568 | /// Call AnalyzeNewNode, updating the node in Val if needed. |
569 | /// If the node changes to a processed node, then remap it. |
570 | void DAGTypeLegalizer::AnalyzeNewValue(SDValue &Val) { |
571 | Val.setNode(AnalyzeNewNode(N: Val.getNode())); |
572 | if (Val.getNode()->getNodeId() == Processed) |
573 | // We were passed a processed node, or it morphed into one - remap it. |
574 | RemapValue(V&: Val); |
575 | } |
576 | |
577 | /// If the specified value was already legalized to another value, |
578 | /// replace it by that value. |
579 | void DAGTypeLegalizer::RemapValue(SDValue &V) { |
580 | auto Id = getTableId(V); |
581 | V = getSDValue(Id); |
582 | } |
583 | |
584 | void DAGTypeLegalizer::RemapId(TableId &Id) { |
585 | auto I = ReplacedValues.find(Val: Id); |
586 | if (I != ReplacedValues.end()) { |
587 | assert(Id != I->second && "Id is mapped to itself." ); |
588 | // Use path compression to speed up future lookups if values get multiply |
589 | // replaced with other values. |
590 | RemapId(Id&: I->second); |
591 | Id = I->second; |
592 | |
593 | // Note that N = IdToValueMap[Id] it is possible to have |
594 | // N.getNode()->getNodeId() == NewNode at this point because it is possible |
595 | // for a node to be put in the map before being processed. |
596 | } |
597 | } |
598 | |
599 | namespace { |
600 | /// This class is a DAGUpdateListener that listens for updates to nodes and |
601 | /// recomputes their ready state. |
602 | class NodeUpdateListener : public SelectionDAG::DAGUpdateListener { |
603 | DAGTypeLegalizer &DTL; |
604 | SmallSetVector<SDNode*, 16> &NodesToAnalyze; |
605 | public: |
606 | explicit NodeUpdateListener(DAGTypeLegalizer &dtl, |
607 | SmallSetVector<SDNode*, 16> &nta) |
608 | : SelectionDAG::DAGUpdateListener(dtl.getDAG()), |
609 | DTL(dtl), NodesToAnalyze(nta) {} |
610 | |
611 | void NodeDeleted(SDNode *N, SDNode *E) override { |
612 | assert(N->getNodeId() != DAGTypeLegalizer::ReadyToProcess && |
613 | N->getNodeId() != DAGTypeLegalizer::Processed && |
614 | "Invalid node ID for RAUW deletion!" ); |
615 | // It is possible, though rare, for the deleted node N to occur as a |
616 | // target in a map, so note the replacement N -> E in ReplacedValues. |
617 | assert(E && "Node not replaced?" ); |
618 | DTL.NoteDeletion(Old: N, New: E); |
619 | |
620 | // In theory the deleted node could also have been scheduled for analysis. |
621 | // So remove it from the set of nodes which will be analyzed. |
622 | NodesToAnalyze.remove(X: N); |
623 | |
624 | // In general nothing needs to be done for E, since it didn't change but |
625 | // only gained new uses. However N -> E was just added to ReplacedValues, |
626 | // and the result of a ReplacedValues mapping is not allowed to be marked |
627 | // NewNode. So if E is marked NewNode, then it needs to be analyzed. |
628 | if (E->getNodeId() == DAGTypeLegalizer::NewNode) |
629 | NodesToAnalyze.insert(X: E); |
630 | } |
631 | |
632 | void NodeUpdated(SDNode *N) override { |
633 | // Node updates can mean pretty much anything. It is possible that an |
634 | // operand was set to something already processed (f.e.) in which case |
635 | // this node could become ready. Recompute its flags. |
636 | assert(N->getNodeId() != DAGTypeLegalizer::ReadyToProcess && |
637 | N->getNodeId() != DAGTypeLegalizer::Processed && |
638 | "Invalid node ID for RAUW deletion!" ); |
639 | N->setNodeId(DAGTypeLegalizer::NewNode); |
640 | NodesToAnalyze.insert(X: N); |
641 | } |
642 | }; |
643 | } |
644 | |
645 | |
646 | /// The specified value was legalized to the specified other value. |
647 | /// Update the DAG and NodeIds replacing any uses of From to use To instead. |
648 | void DAGTypeLegalizer::ReplaceValueWith(SDValue From, SDValue To) { |
649 | assert(From.getNode() != To.getNode() && "Potential legalization loop!" ); |
650 | |
651 | // If expansion produced new nodes, make sure they are properly marked. |
652 | AnalyzeNewValue(Val&: To); |
653 | |
654 | // Anything that used the old node should now use the new one. Note that this |
655 | // can potentially cause recursive merging. |
656 | SmallSetVector<SDNode*, 16> NodesToAnalyze; |
657 | NodeUpdateListener NUL(*this, NodesToAnalyze); |
658 | do { |
659 | |
660 | // The old node may be present in a map like ExpandedIntegers or |
661 | // PromotedIntegers. Inform maps about the replacement. |
662 | auto FromId = getTableId(V: From); |
663 | auto ToId = getTableId(V: To); |
664 | |
665 | if (FromId != ToId) |
666 | ReplacedValues[FromId] = ToId; |
667 | DAG.ReplaceAllUsesOfValueWith(From, To); |
668 | |
669 | // Process the list of nodes that need to be reanalyzed. |
670 | while (!NodesToAnalyze.empty()) { |
671 | SDNode *N = NodesToAnalyze.pop_back_val(); |
672 | if (N->getNodeId() != DAGTypeLegalizer::NewNode) |
673 | // The node was analyzed while reanalyzing an earlier node - it is safe |
674 | // to skip. Note that this is not a morphing node - otherwise it would |
675 | // still be marked NewNode. |
676 | continue; |
677 | |
678 | // Analyze the node's operands and recalculate the node ID. |
679 | SDNode *M = AnalyzeNewNode(N); |
680 | if (M != N) { |
681 | // The node morphed into a different node. Make everyone use the new |
682 | // node instead. |
683 | assert(M->getNodeId() != NewNode && "Analysis resulted in NewNode!" ); |
684 | assert(N->getNumValues() == M->getNumValues() && |
685 | "Node morphing changed the number of results!" ); |
686 | for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { |
687 | SDValue OldVal(N, i); |
688 | SDValue NewVal(M, i); |
689 | if (M->getNodeId() == Processed) |
690 | RemapValue(V&: NewVal); |
691 | // OldVal may be a target of the ReplacedValues map which was marked |
692 | // NewNode to force reanalysis because it was updated. Ensure that |
693 | // anything that ReplacedValues mapped to OldVal will now be mapped |
694 | // all the way to NewVal. |
695 | auto OldValId = getTableId(V: OldVal); |
696 | auto NewValId = getTableId(V: NewVal); |
697 | DAG.ReplaceAllUsesOfValueWith(From: OldVal, To: NewVal); |
698 | if (OldValId != NewValId) |
699 | ReplacedValues[OldValId] = NewValId; |
700 | } |
701 | // The original node continues to exist in the DAG, marked NewNode. |
702 | } |
703 | } |
704 | // When recursively update nodes with new nodes, it is possible to have |
705 | // new uses of From due to CSE. If this happens, replace the new uses of |
706 | // From with To. |
707 | } while (!From.use_empty()); |
708 | } |
709 | |
710 | void DAGTypeLegalizer::SetPromotedInteger(SDValue Op, SDValue Result) { |
711 | assert(Result.getValueType() == |
712 | TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && |
713 | "Invalid type for promoted integer" ); |
714 | AnalyzeNewValue(Val&: Result); |
715 | |
716 | auto &OpIdEntry = PromotedIntegers[getTableId(V: Op)]; |
717 | assert((OpIdEntry == 0) && "Node is already promoted!" ); |
718 | OpIdEntry = getTableId(V: Result); |
719 | |
720 | DAG.transferDbgValues(From: Op, To: Result); |
721 | } |
722 | |
723 | void DAGTypeLegalizer::SetSoftenedFloat(SDValue Op, SDValue Result) { |
724 | #ifndef NDEBUG |
725 | EVT VT = Result.getValueType(); |
726 | LLVMContext &Ctx = *DAG.getContext(); |
727 | assert((VT == EVT::getIntegerVT(Ctx, 80) || |
728 | VT == TLI.getTypeToTransformTo(Ctx, Op.getValueType())) && |
729 | "Invalid type for softened float" ); |
730 | #endif |
731 | AnalyzeNewValue(Val&: Result); |
732 | |
733 | auto &OpIdEntry = SoftenedFloats[getTableId(V: Op)]; |
734 | assert((OpIdEntry == 0) && "Node is already converted to integer!" ); |
735 | OpIdEntry = getTableId(V: Result); |
736 | } |
737 | |
738 | void DAGTypeLegalizer::SetPromotedFloat(SDValue Op, SDValue Result) { |
739 | assert(Result.getValueType() == |
740 | TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && |
741 | "Invalid type for promoted float" ); |
742 | AnalyzeNewValue(Val&: Result); |
743 | |
744 | auto &OpIdEntry = PromotedFloats[getTableId(V: Op)]; |
745 | assert((OpIdEntry == 0) && "Node is already promoted!" ); |
746 | OpIdEntry = getTableId(V: Result); |
747 | } |
748 | |
749 | void DAGTypeLegalizer::SetSoftPromotedHalf(SDValue Op, SDValue Result) { |
750 | assert(Result.getValueType() == MVT::i16 && |
751 | "Invalid type for soft-promoted half" ); |
752 | AnalyzeNewValue(Val&: Result); |
753 | |
754 | auto &OpIdEntry = SoftPromotedHalfs[getTableId(V: Op)]; |
755 | assert((OpIdEntry == 0) && "Node is already promoted!" ); |
756 | OpIdEntry = getTableId(V: Result); |
757 | } |
758 | |
759 | void DAGTypeLegalizer::SetScalarizedVector(SDValue Op, SDValue Result) { |
760 | // Note that in some cases vector operation operands may be greater than |
761 | // the vector element type. For example BUILD_VECTOR of type <1 x i1> with |
762 | // a constant i8 operand. |
763 | |
764 | // We don't currently support the scalarization of scalable vector types. |
765 | assert(Result.getValueSizeInBits().getFixedValue() >= |
766 | Op.getScalarValueSizeInBits() && |
767 | "Invalid type for scalarized vector" ); |
768 | AnalyzeNewValue(Val&: Result); |
769 | |
770 | auto &OpIdEntry = ScalarizedVectors[getTableId(V: Op)]; |
771 | assert((OpIdEntry == 0) && "Node is already scalarized!" ); |
772 | OpIdEntry = getTableId(V: Result); |
773 | } |
774 | |
775 | void DAGTypeLegalizer::GetExpandedInteger(SDValue Op, SDValue &Lo, |
776 | SDValue &Hi) { |
777 | std::pair<TableId, TableId> &Entry = ExpandedIntegers[getTableId(V: Op)]; |
778 | assert((Entry.first != 0) && "Operand isn't expanded" ); |
779 | Lo = getSDValue(Id&: Entry.first); |
780 | Hi = getSDValue(Id&: Entry.second); |
781 | } |
782 | |
783 | void DAGTypeLegalizer::SetExpandedInteger(SDValue Op, SDValue Lo, |
784 | SDValue Hi) { |
785 | assert(Lo.getValueType() == |
786 | TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && |
787 | Hi.getValueType() == Lo.getValueType() && |
788 | "Invalid type for expanded integer" ); |
789 | // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. |
790 | AnalyzeNewValue(Val&: Lo); |
791 | AnalyzeNewValue(Val&: Hi); |
792 | |
793 | // Transfer debug values. Don't invalidate the source debug value until it's |
794 | // been transferred to the high and low bits. |
795 | if (DAG.getDataLayout().isBigEndian()) { |
796 | DAG.transferDbgValues(From: Op, To: Hi, OffsetInBits: 0, SizeInBits: Hi.getValueSizeInBits(), InvalidateDbg: false); |
797 | DAG.transferDbgValues(From: Op, To: Lo, OffsetInBits: Hi.getValueSizeInBits(), |
798 | SizeInBits: Lo.getValueSizeInBits()); |
799 | } else { |
800 | DAG.transferDbgValues(From: Op, To: Lo, OffsetInBits: 0, SizeInBits: Lo.getValueSizeInBits(), InvalidateDbg: false); |
801 | DAG.transferDbgValues(From: Op, To: Hi, OffsetInBits: Lo.getValueSizeInBits(), |
802 | SizeInBits: Hi.getValueSizeInBits()); |
803 | } |
804 | |
805 | // Remember that this is the result of the node. |
806 | std::pair<TableId, TableId> &Entry = ExpandedIntegers[getTableId(V: Op)]; |
807 | assert((Entry.first == 0) && "Node already expanded" ); |
808 | Entry.first = getTableId(V: Lo); |
809 | Entry.second = getTableId(V: Hi); |
810 | } |
811 | |
812 | void DAGTypeLegalizer::GetExpandedFloat(SDValue Op, SDValue &Lo, |
813 | SDValue &Hi) { |
814 | std::pair<TableId, TableId> &Entry = ExpandedFloats[getTableId(V: Op)]; |
815 | assert((Entry.first != 0) && "Operand isn't expanded" ); |
816 | Lo = getSDValue(Id&: Entry.first); |
817 | Hi = getSDValue(Id&: Entry.second); |
818 | } |
819 | |
820 | void DAGTypeLegalizer::SetExpandedFloat(SDValue Op, SDValue Lo, |
821 | SDValue Hi) { |
822 | assert(Lo.getValueType() == |
823 | TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && |
824 | Hi.getValueType() == Lo.getValueType() && |
825 | "Invalid type for expanded float" ); |
826 | // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. |
827 | AnalyzeNewValue(Val&: Lo); |
828 | AnalyzeNewValue(Val&: Hi); |
829 | |
830 | std::pair<TableId, TableId> &Entry = ExpandedFloats[getTableId(V: Op)]; |
831 | assert((Entry.first == 0) && "Node already expanded" ); |
832 | Entry.first = getTableId(V: Lo); |
833 | Entry.second = getTableId(V: Hi); |
834 | } |
835 | |
836 | void DAGTypeLegalizer::GetSplitVector(SDValue Op, SDValue &Lo, |
837 | SDValue &Hi) { |
838 | std::pair<TableId, TableId> &Entry = SplitVectors[getTableId(V: Op)]; |
839 | Lo = getSDValue(Id&: Entry.first); |
840 | Hi = getSDValue(Id&: Entry.second); |
841 | assert(Lo.getNode() && "Operand isn't split" ); |
842 | ; |
843 | } |
844 | |
845 | void DAGTypeLegalizer::SetSplitVector(SDValue Op, SDValue Lo, |
846 | SDValue Hi) { |
847 | assert(Lo.getValueType().getVectorElementType() == |
848 | Op.getValueType().getVectorElementType() && |
849 | Lo.getValueType().getVectorElementCount() * 2 == |
850 | Op.getValueType().getVectorElementCount() && |
851 | Hi.getValueType() == Lo.getValueType() && |
852 | "Invalid type for split vector" ); |
853 | // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. |
854 | AnalyzeNewValue(Val&: Lo); |
855 | AnalyzeNewValue(Val&: Hi); |
856 | |
857 | // Remember that this is the result of the node. |
858 | std::pair<TableId, TableId> &Entry = SplitVectors[getTableId(V: Op)]; |
859 | assert((Entry.first == 0) && "Node already split" ); |
860 | Entry.first = getTableId(V: Lo); |
861 | Entry.second = getTableId(V: Hi); |
862 | } |
863 | |
864 | void DAGTypeLegalizer::SetWidenedVector(SDValue Op, SDValue Result) { |
865 | assert(Result.getValueType() == |
866 | TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && |
867 | "Invalid type for widened vector" ); |
868 | AnalyzeNewValue(Val&: Result); |
869 | |
870 | auto &OpIdEntry = WidenedVectors[getTableId(V: Op)]; |
871 | assert((OpIdEntry == 0) && "Node already widened!" ); |
872 | OpIdEntry = getTableId(V: Result); |
873 | } |
874 | |
875 | |
876 | //===----------------------------------------------------------------------===// |
877 | // Utilities. |
878 | //===----------------------------------------------------------------------===// |
879 | |
880 | /// Convert to an integer of the same size. |
881 | SDValue DAGTypeLegalizer::BitConvertToInteger(SDValue Op) { |
882 | unsigned BitWidth = Op.getValueSizeInBits(); |
883 | return DAG.getNode(Opcode: ISD::BITCAST, DL: SDLoc(Op), |
884 | VT: EVT::getIntegerVT(Context&: *DAG.getContext(), BitWidth), Operand: Op); |
885 | } |
886 | |
887 | /// Convert to a vector of integers of the same size. |
888 | SDValue DAGTypeLegalizer::BitConvertVectorToIntegerVector(SDValue Op) { |
889 | assert(Op.getValueType().isVector() && "Only applies to vectors!" ); |
890 | unsigned EltWidth = Op.getScalarValueSizeInBits(); |
891 | EVT EltNVT = EVT::getIntegerVT(Context&: *DAG.getContext(), BitWidth: EltWidth); |
892 | auto EltCnt = Op.getValueType().getVectorElementCount(); |
893 | return DAG.getNode(Opcode: ISD::BITCAST, DL: SDLoc(Op), |
894 | VT: EVT::getVectorVT(Context&: *DAG.getContext(), VT: EltNVT, EC: EltCnt), Operand: Op); |
895 | } |
896 | |
897 | SDValue DAGTypeLegalizer::CreateStackStoreLoad(SDValue Op, |
898 | EVT DestVT) { |
899 | SDLoc dl(Op); |
900 | // Create the stack frame object. Make sure it is aligned for both |
901 | // the source and destination types. |
902 | |
903 | // In cases where the vector is illegal it will be broken down into parts |
904 | // and stored in parts - we should use the alignment for the smallest part. |
905 | Align DestAlign = DAG.getReducedAlign(VT: DestVT, /*UseABI=*/false); |
906 | Align OpAlign = DAG.getReducedAlign(VT: Op.getValueType(), /*UseABI=*/false); |
907 | Align Align = std::max(a: DestAlign, b: OpAlign); |
908 | SDValue StackPtr = |
909 | DAG.CreateStackTemporary(Bytes: Op.getValueType().getStoreSize(), Alignment: Align); |
910 | // Emit a store to the stack slot. |
911 | SDValue Store = DAG.getStore(Chain: DAG.getEntryNode(), dl, Val: Op, Ptr: StackPtr, |
912 | PtrInfo: MachinePointerInfo(), Alignment: Align); |
913 | // Result is a load from the stack slot. |
914 | return DAG.getLoad(VT: DestVT, dl, Chain: Store, Ptr: StackPtr, PtrInfo: MachinePointerInfo(), Alignment: Align); |
915 | } |
916 | |
917 | /// Replace the node's results with custom code provided by the target and |
918 | /// return "true", or do nothing and return "false". |
919 | /// The last parameter is FALSE if we are dealing with a node with legal |
920 | /// result types and illegal operand. The second parameter denotes the type of |
921 | /// illegal OperandNo in that case. |
922 | /// The last parameter being TRUE means we are dealing with a |
923 | /// node with illegal result types. The second parameter denotes the type of |
924 | /// illegal ResNo in that case. |
925 | bool DAGTypeLegalizer::CustomLowerNode(SDNode *N, EVT VT, bool LegalizeResult) { |
926 | // See if the target wants to custom lower this node. |
927 | if (TLI.getOperationAction(Op: N->getOpcode(), VT) != TargetLowering::Custom) |
928 | return false; |
929 | |
930 | SmallVector<SDValue, 8> Results; |
931 | if (LegalizeResult) |
932 | TLI.ReplaceNodeResults(N, Results, DAG); |
933 | else |
934 | TLI.LowerOperationWrapper(N, Results, DAG); |
935 | |
936 | if (Results.empty()) |
937 | // The target didn't want to custom lower it after all. |
938 | return false; |
939 | |
940 | // Make everything that once used N's values now use those in Results instead. |
941 | assert(Results.size() == N->getNumValues() && |
942 | "Custom lowering returned the wrong number of results!" ); |
943 | for (unsigned i = 0, e = Results.size(); i != e; ++i) { |
944 | ReplaceValueWith(From: SDValue(N, i), To: Results[i]); |
945 | } |
946 | return true; |
947 | } |
948 | |
949 | |
950 | /// Widen the node's results with custom code provided by the target and return |
951 | /// "true", or do nothing and return "false". |
952 | bool DAGTypeLegalizer::CustomWidenLowerNode(SDNode *N, EVT VT) { |
953 | // See if the target wants to custom lower this node. |
954 | if (TLI.getOperationAction(Op: N->getOpcode(), VT) != TargetLowering::Custom) |
955 | return false; |
956 | |
957 | SmallVector<SDValue, 8> Results; |
958 | TLI.ReplaceNodeResults(N, Results, DAG); |
959 | |
960 | if (Results.empty()) |
961 | // The target didn't want to custom widen lower its result after all. |
962 | return false; |
963 | |
964 | // Update the widening map. |
965 | assert(Results.size() == N->getNumValues() && |
966 | "Custom lowering returned the wrong number of results!" ); |
967 | for (unsigned i = 0, e = Results.size(); i != e; ++i) { |
968 | // If this is a chain output or already widened just replace it. |
969 | bool WasWidened = SDValue(N, i).getValueType() != Results[i].getValueType(); |
970 | if (WasWidened) |
971 | SetWidenedVector(Op: SDValue(N, i), Result: Results[i]); |
972 | else |
973 | ReplaceValueWith(From: SDValue(N, i), To: Results[i]); |
974 | } |
975 | return true; |
976 | } |
977 | |
978 | SDValue DAGTypeLegalizer::DisintegrateMERGE_VALUES(SDNode *N, unsigned ResNo) { |
979 | for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) |
980 | if (i != ResNo) |
981 | ReplaceValueWith(From: SDValue(N, i), To: SDValue(N->getOperand(Num: i))); |
982 | return SDValue(N->getOperand(Num: ResNo)); |
983 | } |
984 | |
985 | /// Use ISD::EXTRACT_ELEMENT nodes to extract the low and high parts of the |
986 | /// given value. |
987 | void DAGTypeLegalizer::GetPairElements(SDValue Pair, |
988 | SDValue &Lo, SDValue &Hi) { |
989 | SDLoc dl(Pair); |
990 | EVT NVT = TLI.getTypeToTransformTo(Context&: *DAG.getContext(), VT: Pair.getValueType()); |
991 | std::tie(args&: Lo, args&: Hi) = DAG.SplitScalar(N: Pair, DL: dl, LoVT: NVT, HiVT: NVT); |
992 | } |
993 | |
994 | /// Build an integer with low bits Lo and high bits Hi. |
995 | SDValue DAGTypeLegalizer::JoinIntegers(SDValue Lo, SDValue Hi) { |
996 | // Arbitrarily use dlHi for result SDLoc |
997 | SDLoc dlHi(Hi); |
998 | SDLoc dlLo(Lo); |
999 | EVT LVT = Lo.getValueType(); |
1000 | EVT HVT = Hi.getValueType(); |
1001 | EVT NVT = EVT::getIntegerVT(Context&: *DAG.getContext(), |
1002 | BitWidth: LVT.getSizeInBits() + HVT.getSizeInBits()); |
1003 | |
1004 | EVT ShiftAmtVT = TLI.getShiftAmountTy(LHSTy: NVT, DL: DAG.getDataLayout()); |
1005 | Lo = DAG.getNode(Opcode: ISD::ZERO_EXTEND, DL: dlLo, VT: NVT, Operand: Lo); |
1006 | Hi = DAG.getNode(Opcode: ISD::ANY_EXTEND, DL: dlHi, VT: NVT, Operand: Hi); |
1007 | Hi = DAG.getNode(Opcode: ISD::SHL, DL: dlHi, VT: NVT, N1: Hi, |
1008 | N2: DAG.getConstant(Val: LVT.getSizeInBits(), DL: dlHi, VT: ShiftAmtVT)); |
1009 | return DAG.getNode(Opcode: ISD::OR, DL: dlHi, VT: NVT, N1: Lo, N2: Hi); |
1010 | } |
1011 | |
1012 | /// Promote the given target boolean to a target boolean of the given type. |
1013 | /// A target boolean is an integer value, not necessarily of type i1, the bits |
1014 | /// of which conform to getBooleanContents. |
1015 | /// |
1016 | /// ValVT is the type of values that produced the boolean. |
1017 | SDValue DAGTypeLegalizer::PromoteTargetBoolean(SDValue Bool, EVT ValVT) { |
1018 | return TLI.promoteTargetBoolean(DAG, Bool, ValVT); |
1019 | } |
1020 | |
1021 | /// Return the lower LoVT bits of Op in Lo and the upper HiVT bits in Hi. |
1022 | void DAGTypeLegalizer::SplitInteger(SDValue Op, |
1023 | EVT LoVT, EVT HiVT, |
1024 | SDValue &Lo, SDValue &Hi) { |
1025 | SDLoc dl(Op); |
1026 | assert(LoVT.getSizeInBits() + HiVT.getSizeInBits() == |
1027 | Op.getValueSizeInBits() && "Invalid integer splitting!" ); |
1028 | Lo = DAG.getNode(Opcode: ISD::TRUNCATE, DL: dl, VT: LoVT, Operand: Op); |
1029 | unsigned ReqShiftAmountInBits = |
1030 | Log2_32_Ceil(Value: Op.getValueType().getSizeInBits()); |
1031 | MVT ShiftAmountTy = |
1032 | TLI.getScalarShiftAmountTy(DAG.getDataLayout(), Op.getValueType()); |
1033 | if (ReqShiftAmountInBits > ShiftAmountTy.getSizeInBits()) |
1034 | ShiftAmountTy = MVT::getIntegerVT(BitWidth: NextPowerOf2(A: ReqShiftAmountInBits)); |
1035 | Hi = DAG.getNode(Opcode: ISD::SRL, DL: dl, VT: Op.getValueType(), N1: Op, |
1036 | N2: DAG.getConstant(Val: LoVT.getSizeInBits(), DL: dl, VT: ShiftAmountTy)); |
1037 | Hi = DAG.getNode(Opcode: ISD::TRUNCATE, DL: dl, VT: HiVT, Operand: Hi); |
1038 | } |
1039 | |
1040 | /// Return the lower and upper halves of Op's bits in a value type half the |
1041 | /// size of Op's. |
1042 | void DAGTypeLegalizer::SplitInteger(SDValue Op, |
1043 | SDValue &Lo, SDValue &Hi) { |
1044 | EVT HalfVT = |
1045 | EVT::getIntegerVT(Context&: *DAG.getContext(), BitWidth: Op.getValueSizeInBits() / 2); |
1046 | SplitInteger(Op, LoVT: HalfVT, HiVT: HalfVT, Lo, Hi); |
1047 | } |
1048 | |
1049 | |
1050 | //===----------------------------------------------------------------------===// |
1051 | // Entry Point |
1052 | //===----------------------------------------------------------------------===// |
1053 | |
1054 | /// This transforms the SelectionDAG into a SelectionDAG that only uses types |
1055 | /// natively supported by the target. Returns "true" if it made any changes. |
1056 | /// |
1057 | /// Note that this is an involved process that may invalidate pointers into |
1058 | /// the graph. |
1059 | bool SelectionDAG::LegalizeTypes() { |
1060 | return DAGTypeLegalizer(*this).run(); |
1061 | } |
1062 | |