@@ -318,38 +318,63 @@ void SIWholeQuadMode::markDefs(const MachineInstr &UseMI, LiveRange &LR,
318
318
LLVM_DEBUG (dbgs () << " markDefs " << PrintState (Flag) << " : " << UseMI);
319
319
320
320
LiveQueryResult UseLRQ = LR.Query (LIS->getInstructionIndex (UseMI));
321
- if (!UseLRQ.valueIn ())
321
+ const VNInfo *Value = UseLRQ.valueIn ();
322
+ if (!Value)
322
323
return ;
323
324
324
325
// Note: this code assumes that lane masks on AMDGPU completely
325
326
// cover registers.
327
+ const LaneBitmask UseLanes =
328
+ SubReg ? TRI->getSubRegIndexLaneMask (SubReg)
329
+ : (Reg.isVirtual () ? MRI->getMaxLaneMaskForVReg (Reg)
330
+ : LaneBitmask::getNone ());
331
+
332
+ // Perform a depth-first iteration of the LiveRange graph marking defs.
333
+ // Stop processing of a given branch when all use lanes have been defined.
334
+ // The first definition stops processing for a physical register.
335
+ struct PhiEntry {
336
+ const VNInfo *Phi;
337
+ unsigned PredIdx;
338
+ unsigned VisitIdx;
339
+ LaneBitmask DefinedLanes;
340
+
341
+ PhiEntry (const VNInfo *Phi, unsigned PredIdx, unsigned VisitIdx,
342
+ LaneBitmask DefinedLanes)
343
+ : Phi(Phi), PredIdx(PredIdx), VisitIdx(VisitIdx),
344
+ DefinedLanes (DefinedLanes) {}
345
+ };
346
+ SmallSetVector<const VNInfo *, 4 > Visited;
347
+ SmallVector<PhiEntry, 2 > PhiStack;
326
348
LaneBitmask DefinedLanes;
327
- LaneBitmask UseLanes;
328
- if (SubReg) {
329
- UseLanes = TRI->getSubRegIndexLaneMask (SubReg);
330
- } else if (Reg.isVirtual ()) {
331
- UseLanes = MRI->getMaxLaneMaskForVReg (Reg);
332
- }
333
-
334
- SmallPtrSet<const VNInfo *, 4 > Visited;
335
- SmallVector<const VNInfo *, 4 > ToProcess;
336
- ToProcess.push_back (UseLRQ.valueIn ());
349
+ unsigned NextPredIdx; // Only used for processing phi nodes
337
350
do {
338
- const VNInfo *Value = ToProcess.pop_back_val ();
339
- Visited.insert (Value);
351
+ const VNInfo *NextValue = nullptr ;
352
+
353
+ if (!Visited.count (Value)) {
354
+ Visited.insert (Value);
355
+ // On first visit to a phi then start processing first predecessor
356
+ NextPredIdx = 0 ;
357
+ }
340
358
341
359
if (Value->isPHIDef ()) {
342
- // Need to mark all defs used in the PHI node
360
+ // Each predecessor node in the phi must be processed as a subgraph
343
361
const MachineBasicBlock *MBB = LIS->getMBBFromIndex (Value->def );
344
362
assert (MBB && " Phi-def has no defining MBB" );
345
- for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin (),
346
- PE = MBB->pred_end ();
347
- PI != PE; ++PI) {
363
+
364
+ // Find next predecessor to process
365
+ unsigned Idx = NextPredIdx;
366
+ auto PI = MBB->pred_begin () + Idx;
367
+ auto PE = MBB->pred_end ();
368
+ for (; PI != PE && !NextValue; ++PI, ++Idx) {
348
369
if (const VNInfo *VN = LR.getVNInfoBefore (LIS->getMBBEndIdx (*PI))) {
349
370
if (!Visited.count (VN))
350
- ToProcess. push_back (VN) ;
371
+ NextValue = VN ;
351
372
}
352
373
}
374
+
375
+ // If there are more predecessors to process; add phi to stack
376
+ if (PI != PE)
377
+ PhiStack.emplace_back (Value, Idx, Visited.size (), DefinedLanes);
353
378
} else {
354
379
MachineInstr *MI = LIS->getInstructionFromIndex (Value->def );
355
380
assert (MI && " Def has no defining instruction" );
@@ -370,17 +395,20 @@ void SIWholeQuadMode::markDefs(const MachineInstr &UseMI, LiveRange &LR,
370
395
// Record if this instruction defined any of use
371
396
HasDef |= Overlap.any ();
372
397
373
- // Check if all lanes of use have been defined
398
+ // Mark any lanes defined
374
399
DefinedLanes |= OpLanes;
375
- if ((DefinedLanes & UseLanes) != UseLanes) {
376
- // Definition not complete; need to process input value
377
- LiveQueryResult LRQ = LR.Query (LIS->getInstructionIndex (*MI));
378
- if (const VNInfo *VN = LRQ.valueIn ()) {
379
- if (!Visited.count (VN))
380
- ToProcess.push_back (VN);
381
- }
400
+ }
401
+
402
+ // Check if all lanes of use have been defined
403
+ if ((DefinedLanes & UseLanes) != UseLanes) {
404
+ // Definition not complete; need to process input value
405
+ LiveQueryResult LRQ = LR.Query (LIS->getInstructionIndex (*MI));
406
+ if (const VNInfo *VN = LRQ.valueIn ()) {
407
+ if (!Visited.count (VN))
408
+ NextValue = VN;
382
409
}
383
410
}
411
+
384
412
// Only mark the instruction if it defines some part of the use
385
413
if (HasDef)
386
414
markInstruction (*MI, Flag, Worklist);
@@ -389,9 +417,21 @@ void SIWholeQuadMode::markDefs(const MachineInstr &UseMI, LiveRange &LR,
389
417
markInstruction (*MI, Flag, Worklist);
390
418
}
391
419
}
392
- } while (!ToProcess.empty ());
393
420
394
- assert (!Reg.isVirtual () || ((DefinedLanes & UseLanes) == UseLanes));
421
+ if (!NextValue && !PhiStack.empty ()) {
422
+ // Reach end of chain; revert to processing last phi
423
+ PhiEntry &Entry = PhiStack.back ();
424
+ NextValue = Entry.Phi ;
425
+ NextPredIdx = Entry.PredIdx ;
426
+ DefinedLanes = Entry.DefinedLanes ;
427
+ // Rewind visited set to correct state
428
+ while (Visited.size () > Entry.VisitIdx )
429
+ Visited.pop_back ();
430
+ PhiStack.pop_back ();
431
+ }
432
+
433
+ Value = NextValue;
434
+ } while (Value);
395
435
}
396
436
397
437
void SIWholeQuadMode::markOperand (const MachineInstr &MI,
0 commit comments