16
16
#include " llvm/ADT/SmallPtrSet.h"
17
17
#include " llvm/Analysis/AssumptionCache.h"
18
18
#include " llvm/IR/AssemblyAnnotationWriter.h"
19
+ #include " llvm/IR/CFG.h"
19
20
#include " llvm/IR/Dominators.h"
20
21
#include " llvm/IR/IRBuilder.h"
21
22
#include " llvm/IR/InstIterator.h"
@@ -213,6 +214,8 @@ class PredicateInfoBuilder {
213
214
// whether it returned a valid result.
214
215
DenseMap<Value *, unsigned int > ValueInfoNums;
215
216
217
+ DenseMap<BasicBlock *, SmallVector<Value *, 4 >> PHICandidates;
218
+
216
219
BumpPtrAllocator &Allocator;
217
220
218
221
ValueInfo &getOrCreateValueInfo (Value *);
@@ -224,6 +227,10 @@ class PredicateInfoBuilder {
224
227
SmallVectorImpl<Value *> &OpsToRename);
225
228
void processSwitch (SwitchInst *, BasicBlock *,
226
229
SmallVectorImpl<Value *> &OpsToRename);
230
+ void identifyPHICandidates (SmallVectorImpl<Value *> &OpsToRename);
231
+ void insertPredicatePHIs (Value *Op, BasicBlock *PHIBlock,
232
+ SmallVectorImpl<Value *> &OpsToRename);
233
+ void processPredicatePHIs (SmallVectorImpl<Value *> &OpsToRename);
227
234
void renameUses (SmallVectorImpl<Value *> &OpsToRename);
228
235
void addInfoFor (SmallVectorImpl<Value *> &OpsToRename, Value *Op,
229
236
PredicateBase *PB);
@@ -452,6 +459,71 @@ void PredicateInfoBuilder::processSwitch(
452
459
}
453
460
}
454
461
462
+ void PredicateInfoBuilder::identifyPHICandidates (
463
+ SmallVectorImpl<Value *> &OpsToRename) {
464
+ for (Value *Op : OpsToRename) {
465
+ const auto &ValueInfo = getValueInfo (Op);
466
+ SmallPtrSet<BasicBlock *, 4 > DefiningBlocks;
467
+ for (const auto *PInfo : ValueInfo.Infos ) {
468
+ if (auto *PBranch = dyn_cast<PredicateBranch>(PInfo)) {
469
+ DefiningBlocks.insert (PBranch->To );
470
+ } else if (auto *PSwitch = dyn_cast<PredicateSwitch>(PInfo)) {
471
+ DefiningBlocks.insert (PSwitch->To );
472
+ }
473
+ }
474
+
475
+ if (DefiningBlocks.size () > 1 ) {
476
+ SmallPtrSet<BasicBlock *, 8 > PHIBlocks (DefiningBlocks.begin (),
477
+ DefiningBlocks.end ());
478
+ PHICandidates[*PHIBlocks.begin ()].push_back (Op);
479
+ }
480
+ }
481
+ }
482
+
483
+ void PredicateInfoBuilder::insertPredicatePHIs (
484
+ Value *Op, BasicBlock *PHIBlock, SmallVectorImpl<Value *> &OpsToRename) {
485
+ IRBuilder<> Builder (&PHIBlock->front ());
486
+
487
+ PHINode *PHI = Builder.CreatePHI (Op->getType (), pred_size (PHIBlock),
488
+ Op->getName () + " .predicate.phi" );
489
+ PredicatePHI *PPHI = new (Allocator) PredicatePHI (Op, PHIBlock);
490
+
491
+ PPHI->RenamedOp = PHI;
492
+
493
+ const auto &ValueInfo = getValueInfo (Op);
494
+ for (BasicBlock *Pred : predecessors (PHIBlock)) {
495
+ Value *IncomingValue = nullptr ;
496
+ for (const auto *PInfo : ValueInfo.Infos ) {
497
+ if (auto *PBranch = dyn_cast<PredicateBranch>(PInfo)) {
498
+ if (PBranch->From == Pred && PBranch->To == PHIBlock) {
499
+ PPHI->IncomingPredicates .push_back (
500
+ {Pred, const_cast <PredicateBase *>(PInfo)});
501
+ IncomingValue = PBranch->OriginalOp ;
502
+ }
503
+ } else if (auto *PSwitch = dyn_cast<PredicateSwitch>(PInfo)) {
504
+ if (PSwitch->From == Pred && PSwitch->To == PHIBlock) {
505
+ PPHI->IncomingPredicates .push_back (
506
+ {Pred, const_cast <PredicateBase *>(PInfo)});
507
+ IncomingValue = PSwitch->OriginalOp ;
508
+ }
509
+ }
510
+ }
511
+ PHI->addIncoming (IncomingValue, Pred);
512
+ }
513
+
514
+ addInfoFor (OpsToRename, Op, PPHI);
515
+ }
516
+
517
+ void PredicateInfoBuilder::processPredicatePHIs (
518
+ SmallVectorImpl<Value *> &OpsToRename) {
519
+ for (const auto &PHICandidate : PHICandidates) {
520
+ BasicBlock *PHIBlock = PHICandidate.first ;
521
+ for (Value *Op : PHICandidate.second ) {
522
+ insertPredicatePHIs (Op, PHIBlock, OpsToRename);
523
+ }
524
+ }
525
+ }
526
+
455
527
// Build predicate info for our function
456
528
void PredicateInfoBuilder::buildPredicateInfo () {
457
529
DT.updateDFSNumbers ();
@@ -478,6 +550,10 @@ void PredicateInfoBuilder::buildPredicateInfo() {
478
550
if (DT.isReachableFromEntry (II->getParent ()))
479
551
processAssume (II, II->getParent (), OpsToRename);
480
552
}
553
+
554
+ identifyPHICandidates (OpsToRename);
555
+ processPredicatePHIs (OpsToRename);
556
+
481
557
// Now rename all our operations.
482
558
renameUses (OpsToRename);
483
559
}
@@ -535,6 +611,12 @@ Value *PredicateInfoBuilder::materializeStack(unsigned int &Counter,
535
611
CreateSSACopy (B, Op, Op->getName () + " ." + Twine (Counter++));
536
612
PI.PredicateMap .insert ({PIC, ValInfo});
537
613
Result.Def = PIC;
614
+ } else if (isa<PredicatePHI>(ValInfo)) {
615
+ auto *PPHI = dyn_cast<PredicatePHI>(ValInfo);
616
+ IRBuilder<> B (&*PPHI->PHIBlock ->getFirstInsertionPt ());
617
+ CallInst *PIC = CreateSSACopy (B, Op);
618
+ PI.PredicateMap .insert ({PIC, ValInfo});
619
+ Result.Def = PIC;
538
620
} else {
539
621
auto *PAssume = dyn_cast<PredicateAssume>(ValInfo);
540
622
assert (PAssume &&
@@ -623,6 +705,15 @@ void PredicateInfoBuilder::renameUses(SmallVectorImpl<Value *> &OpsToRename) {
623
705
OrderedUses.push_back (VD);
624
706
}
625
707
}
708
+ } else if (const auto *PPHI = dyn_cast<PredicatePHI>(PossibleCopy)) {
709
+ VD.LocalNum = LN_First;
710
+ auto *DomNode = DT.getNode (PPHI->PHIBlock );
711
+ if (DomNode) {
712
+ VD.DFSIn = DomNode->getDFSNumIn ();
713
+ VD.DFSOut = DomNode->getDFSNumOut ();
714
+ VD.PInfo = PossibleCopy;
715
+ OrderedUses.push_back (VD);
716
+ }
626
717
}
627
718
}
628
719
@@ -773,10 +864,31 @@ std::optional<PredicateConstraint> PredicateBase::getConstraint() const {
773
864
}
774
865
775
866
return {{CmpInst::ICMP_EQ, cast<PredicateSwitch>(this )->CaseValue }};
867
+ case PT_PHI:
868
+ return cast<PredicatePHI>(this )->getConstraint ();
776
869
}
777
870
llvm_unreachable (" Unknown predicate type" );
778
871
}
779
872
873
+ std::optional<PredicateConstraint> PredicatePHI::getConstraint () const {
874
+ if (IncomingPredicates.empty ())
875
+ return std::nullopt;
876
+
877
+ auto FirstConstraint = IncomingPredicates[0 ].second ->getConstraint ();
878
+ if (!FirstConstraint)
879
+ return std::nullopt;
880
+
881
+ for (size_t I = 1 ; I < IncomingPredicates.size (); ++I) {
882
+ auto Constraint = IncomingPredicates[I].second ->getConstraint ();
883
+ if (!Constraint || Constraint->Predicate != FirstConstraint->Predicate ||
884
+ Constraint->OtherOp != FirstConstraint->OtherOp ) {
885
+ return std::nullopt;
886
+ }
887
+ }
888
+
889
+ return FirstConstraint;
890
+ }
891
+
780
892
void PredicateInfo::verifyPredicateInfo () const {}
781
893
782
894
// Replace ssa_copy calls created by PredicateInfo with their operand.
@@ -838,6 +950,10 @@ class PredicateInfoAnnotatedWriter : public AssemblyAnnotationWriter {
838
950
} else if (const auto *PA = dyn_cast<PredicateAssume>(PI)) {
839
951
OS << " ; assume predicate info {"
840
952
<< " Comparison:" << *PA->Condition ;
953
+ } else if (const auto *PP = dyn_cast<PredicatePHI>(PI)) {
954
+ OS << " ; phi predicate info { PHIBlock: " ;
955
+ PP->PHIBlock ->printAsOperand (OS);
956
+ OS << " IncomingEdges: " << PP->IncomingPredicates .size ();
841
957
}
842
958
OS << " , RenamedOp: " ;
843
959
PI->RenamedOp ->printAsOperand (OS, false );
0 commit comments