@@ -26,7 +26,6 @@ SPDX-License-Identifier: MIT
2626#include " common/LLVMWarningsPop.hpp"
2727#include " GenISAIntrinsics/GenIntrinsics.h"
2828#include " Probe/Assertion.h"
29- #include < functional> // for std::function
3029
3130using namespace llvm ;
3231using namespace IGC ;
@@ -89,7 +88,6 @@ namespace {
8988 AU.setPreservesCFG ();
9089 AU.addRequired <CodeGenContextWrapper>();
9190 AU.addRequired <MetaDataUtilsWrapper>();
92- AU.addRequired <LoopInfoWrapperPass>();
9391 }
9492 };
9593
@@ -216,24 +214,23 @@ char DeadPHINodeElimination::ID = 0;
216214#undef PASS_ANALYSIS
217215
218216#define PASS_FLAG " igc-phielimination"
219- #define PASS_DESC " Remove Dead Recurisive PHINode"
217+ #define PASS_DESC " Remove dead recurisive PHINode"
220218#define PASS_CFG_ONLY false
221219#define PASS_ANALYSIS false
222220namespace IGC {
223221 IGC_INITIALIZE_PASS_BEGIN (DeadPHINodeElimination, PASS_FLAG, PASS_DESC, PASS_CFG_ONLY, PASS_ANALYSIS)
224222 IGC_INITIALIZE_PASS_DEPENDENCY (CodeGenContextWrapper)
225223 IGC_INITIALIZE_PASS_DEPENDENCY (MetaDataUtilsWrapper)
226- IGC_INITIALIZE_PASS_DEPENDENCY (LoopInfoWrapperPass)
227224 IGC_INITIALIZE_PASS_END (DeadPHINodeElimination, PASS_FLAG, PASS_DESC, PASS_CFG_ONLY, PASS_ANALYSIS)
228225}
229226
230227FunctionPass* IGC::createDeadPHINodeEliminationPass () {
231228 return new DeadPHINodeElimination ();
232229}
233230
234- static bool eliminateDeadPHINodes (Function& F)
231+ bool DeadPHINodeElimination::runOnFunction (Function& F)
235232{
236- // This is to eliminate potential recursive phi like the following:
233+ // This is to eliminate potential recurive phi like the following:
237234 // Bx: x = phi [y0, B0], ...[z, Bz]
238235 // Bz: z = phi [x, Bx], ...[]
239236 // x and z are recursive phi's that are not used anywhere but in those phi's.
@@ -334,218 +331,3 @@ static bool eliminateDeadPHINodes(Function& F)
334331
335332 return (toBeDeleted.size () > 0 );
336333}
337-
338- using BlockValueMap = DenseMap<const BasicBlock*, PHINode*>;
339- using BlockValueMapVector = SmallVector<BlockValueMap, 16 >;
340- using BlockValueMapDuplicateIDs = SmallVector<SmallVector<size_t , 2 >, 16 >;
341-
342- static BlockValueMapVector getNodeLoops (const Loop* L) {
343- // Traverse the loop L and collect all the phi nodes
344- // and their phi node predecessors.
345-
346- std::function<bool (BlockValueMap&, PHINode*)> CollectConnected =
347- [&CollectConnected](BlockValueMap& BlockMap, PHINode* P) {
348- // Check if we have never met phi node parent (basic block) before
349- auto Inserted = BlockMap.insert (make_pair (P->getParent (), P));
350-
351- if (Inserted.second ) {
352- // New pair of phi node and basic block inserted
353- // Traverse node's incoming values
354- for (auto & V : P->incoming_values ()) {
355- if (auto N = dyn_cast<PHINode>(V))
356- if (!CollectConnected (BlockMap, N))
357- return false ;
358- }
359-
360- // Return true if phi node P and all its incoming phi nodes N
361- // have been successfully inserted into a block map
362- return true ;
363- }
364-
365- // Return true if phi node P have already been inserted into a block map before
366- return Inserted.first ->second == P;
367- };
368-
369- BlockValueMapVector BlockMaps;
370- // Start with phi node in a header
371- for (auto & I : *L->getHeader ())
372- if (auto P = dyn_cast<PHINode>(&I)) {
373- BlockValueMap BlockMap;
374- if (CollectConnected (BlockMap, P)) {
375- BlockMaps.push_back (BlockMap);
376- }
377- }
378-
379- return BlockMaps;
380- }
381-
382- static bool isSameTopology (const BlockValueMap& BlockMapX, const BlockValueMap& BlockMapY) {
383- // Check if phi node recursive loops x and y
384- // are of the same topology, e.g. each node in x
385- // loop has unique node in y loop corresponding
386- // to the same block.
387-
388- if (BlockMapX.size () != BlockMapY.size ())
389- return false ;
390-
391- for (auto & PairX : BlockMapX) {
392- auto BlockX = PairX.first ;
393- auto ValueX = PairX.second ;
394- auto PairY = BlockMapY.find (BlockX);
395-
396- // Return false if loop of y blocks are different
397- if (PairY == BlockMapY.end ())
398- return false ;
399-
400- auto ValueY = PairY->second ;
401-
402- // Compare two phi nodes x and y
403- // Check if every non-phi node incomming value of x
404- // has matching incoming value of y
405-
406- // Loop over all incoming values of phi node x
407- for (unsigned int i = 0 ; i < ValueX->getNumIncomingValues (); ++i) {
408- auto IncomingValueX = ValueX->getIncomingValue (i);
409- auto IncomingBlockX = ValueX->getIncomingBlock (i);
410-
411- // Skip phi node incoming value being part of a loop
412- if (auto IncomingPHINodeX = dyn_cast<PHINode>(IncomingValueX))
413- if (BlockMapX.find (IncomingPHINodeX->getParent ()) != BlockMapX.end ())
414- continue ;
415-
416- bool Found = false ;
417-
418- // Loop over all incoming values of phi node y
419- for (unsigned int j = 0 ; j < ValueY->getNumIncomingValues (); ++j) {
420- auto IncomingValueY = ValueY->getIncomingValue (j);
421- auto IncomingBlockY = ValueY->getIncomingBlock (j);
422-
423- if (IncomingValueX == IncomingValueY && IncomingBlockX == IncomingBlockY) {
424- // Found a match
425- Found = true ;
426- break ;
427- }
428- }
429-
430- // Return false if there is a non-phi node incoming value of phi node x
431- // having no match among the incoming values of y
432- if (!Found)
433- return false ;
434- }
435- }
436-
437- return true ;
438- }
439-
440- static BlockValueMapDuplicateIDs splitLoopsIntoDuplicateGroups (const BlockValueMapVector& BlockMaps) {
441- // Split all found recursive phi node loops into
442- // groups of duplicates by comparing each loop
443- // to all others.
444-
445- BlockValueMapDuplicateIDs DuplicatesIDs;
446- if (BlockMaps.size ()) {
447- SmallVector<bool , 16 > Found (BlockMaps.size (), false );
448-
449- for (size_t i = 0 ; i < BlockMaps.size () - 1 ; ++i) {
450- SmallVector<size_t , 2 > Duplicates;
451-
452- for (size_t j = i + 1 ; j < BlockMaps.size (); ++j)
453- if (!Found[j] && isSameTopology (BlockMaps[i], BlockMaps[j])) {
454- Duplicates.push_back (j);
455- Found[j] = true ;
456- }
457-
458- if (Duplicates.size ()) {
459- Duplicates.push_back (i);
460- DuplicatesIDs.push_back (Duplicates);
461- Found[i] = true ;
462- }
463- }
464- }
465-
466- return DuplicatesIDs;
467- }
468-
469- static bool replaceNonPHINodeUses (const BlockValueMapVector& BlockMaps, const BlockValueMapDuplicateIDs& DuplicatesIDs) {
470- // Replace all non-phi uses of nodes x with nodes y
471- // within a group according to the correspondence maps.
472-
473- bool Changed = false ;
474- for (size_t i = 0 ; i < DuplicatesIDs.size (); ++i) {
475- auto & Duplicates = DuplicatesIDs[i];
476- IGC_ASSERT_MESSAGE (Duplicates.size () >= 2 , " Number of duplicates is expected to be at least 2" );
477-
478- // Let y be the first loop
479- auto & BlockMapY = BlockMaps[Duplicates[0 ]];
480-
481- for (auto & PairY : BlockMapY) {
482- auto BlockY = PairY.first ;
483- auto ValueY = PairY.second ;
484-
485- // All other loops are considered x
486- for (size_t j = 1 ; j < Duplicates.size (); ++j) {
487- auto & BlockMapX = BlockMaps[Duplicates[j]];
488-
489- auto PairX = BlockMapX.find (BlockY);
490- IGC_ASSERT_MESSAGE (PairX != BlockMapX.end (), " Inconsistent duplicate maps" );
491- auto ValueX = PairX->second ;
492-
493- if (ValueX != ValueY)
494- ValueX->replaceAllUsesWith (ValueY);
495- }
496- }
497- }
498-
499- return Changed;
500- }
501-
502- static bool resolveDuplicateLoops (Function& F, const Loop* L) {
503- // This is to eliminate duplicate recursive phis like the following:
504- // B0: x0 = phi [v, ...], [xN, BN]
505- // B0: y0 = phi [v, ...], [yN, BN]
506- // ...
507- // B1: x1 = phi [x0, B0], ...
508- // B1: y1 = phi [y0, B0], ...
509- // ...
510- // t = add %x1, 1.0
511- // ...
512- // B2: x2 = phi [t, ...], [x1, B1]
513- // B2: y2 = phi [t, ...], [y1, B1]
514- // ...
515- // store yN ...
516- // xi are recursive duplicate of yi, and are not used anywhere but in those phis.
517- // Thus, they can be eliminated.
518-
519- // Find all recursive phis within current loop L:
520- // loops of xi, yi, etc.
521- auto BlockMaps = getNodeLoops (L);
522-
523- // Group all recursive phis within current loop L
524- // into duplicate groups:
525- // xi duplicates yi, so put then into the same group
526- auto DuplicatesIDs = splitLoopsIntoDuplicateGroups (BlockMaps);
527-
528- // Replace x1 with y1 in t = add %x1, 1.0,
529- // so all xi become unused anywhere except in xi
530- // Unused phi nodes will be eliminated by upcomming
531- // call to eliminateDeadPHINodes(F)
532- return replaceNonPHINodeUses (BlockMaps, DuplicatesIDs);
533- }
534-
535- bool DeadPHINodeElimination::runOnFunction (Function& F) {
536- bool Changed = false ;
537-
538- if (eliminateDeadPHINodes (F))
539- Changed = true ;
540-
541- auto LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo ();
542- for (auto & L : LI->getLoopsInPreorder ()) {
543- if (resolveDuplicateLoops (F, L))
544- Changed = true ;
545-
546- if (eliminateDeadPHINodes (F))
547- Changed = true ;
548- }
549-
550- return Changed;
551- }
0 commit comments