@@ -362,12 +362,21 @@ class HashVisitor : public SILInstructionVisitor<HashVisitor, llvm::hash_code> {
362
362
Operands.begin (),
363
363
Operands.end ()));
364
364
}
365
+
365
366
hash_code visitMarkDependenceInst (MarkDependenceInst *X) {
366
367
OperandValueArrayRef Operands (X->getAllOperands ());
367
368
return llvm::hash_combine (
368
369
X->getKind (), X->getType (),
369
370
llvm::hash_combine_range (Operands.begin (), Operands.end ()));
370
371
}
372
+
373
+ hash_code visitOpenExistentialRefInst (OpenExistentialRefInst *X) {
374
+ auto ArchetypeTy = cast<ArchetypeType>(X->getType ().getSwiftRValueType ());
375
+ auto ConformsTo = ArchetypeTy->getConformsTo ();
376
+ return llvm::hash_combine (
377
+ X->getKind (), X->getOperand (),
378
+ llvm::hash_combine_range (ConformsTo.begin (), ConformsTo.end ()));
379
+ }
371
380
};
372
381
} // end anonymous namespace
373
382
@@ -381,14 +390,33 @@ bool llvm::DenseMapInfo<SimpleValue>::isEqual(SimpleValue LHS,
381
390
if (LHS.isSentinel () || RHS.isSentinel ())
382
391
return LHSI == RHSI;
383
392
393
+ if (isa<OpenExistentialRefInst>(LHSI) && isa<OpenExistentialRefInst>(RHSI)) {
394
+ if (LHSI->getNumOperands () != RHSI->getNumOperands ())
395
+ return false ;
396
+
397
+ // Check operands.
398
+ for (unsigned i = 0 , e = LHSI->getNumOperands (); i != e; ++i)
399
+ if (LHSI->getOperand (i) != RHSI->getOperand (i))
400
+ return false ;
401
+
402
+ // Consider the types of two open_existential_ref instructions to be equal,
403
+ // if the sets of protocols they conform to are equal.
404
+ auto LHSArchetypeTy =
405
+ cast<ArchetypeType>(LHSI->getType ().getSwiftRValueType ());
406
+ auto LHSConformsTo = LHSArchetypeTy->getConformsTo ();
407
+ auto RHSArchetypeTy =
408
+ cast<ArchetypeType>(RHSI->getType ().getSwiftRValueType ());
409
+ auto RHSConformsTo = RHSArchetypeTy->getConformsTo ();
410
+ return LHSConformsTo == RHSConformsTo;
411
+ }
384
412
return LHSI->getKind () == RHSI->getKind () && LHSI->isIdenticalTo (RHSI);
385
413
}
386
414
387
415
// ===----------------------------------------------------------------------===//
388
416
// CSE Interface
389
417
// ===----------------------------------------------------------------------===//
390
418
391
- namespace {
419
+ namespace swift {
392
420
393
421
// / CSE - This pass does a simple depth-first walk over the dominator tree,
394
422
// / eliminating trivially redundant instructions and using simplifyInstruction
@@ -476,6 +504,8 @@ class CSE {
476
504
};
477
505
478
506
bool processNode (DominanceInfoNode *Node);
507
+ bool processOpenExistentialRef (SILInstruction *Inst, ValueBase *V,
508
+ SILBasicBlock::iterator &I);
479
509
};
480
510
} // end anonymous namespace
481
511
@@ -525,6 +555,95 @@ bool CSE::processFunction(SILFunction &Fm, DominanceInfo *DT) {
525
555
return Changed;
526
556
}
527
557
558
+ namespace {
559
+ // A very simple cloner for cloning instructions inside
560
+ // the same function. The only interesting thing it does
561
+ // is remapping the archetypes when it is required.
562
+ class InstructionCloner : public SILCloner <InstructionCloner> {
563
+ friend class SILCloner <InstructionCloner>;
564
+ friend class SILVisitor <InstructionCloner>;
565
+ SILInstruction *Result = nullptr ;
566
+ public:
567
+ InstructionCloner (SILFunction *F) : SILCloner(*F) {}
568
+
569
+ static SILInstruction *doIt (SILInstruction *I) {
570
+ InstructionCloner TC (I->getFunction ());
571
+ return TC.clone (I);
572
+ }
573
+
574
+ SILInstruction *clone (SILInstruction *I) {
575
+ visit (I);
576
+ return Result;
577
+ }
578
+
579
+ void postProcess (SILInstruction *Orig, SILInstruction *Cloned) {
580
+ assert (Orig->getFunction () == &getBuilder ().getFunction () &&
581
+ " cloning between functions is not supported" );
582
+
583
+ Result = Cloned;
584
+ SILCloner<InstructionCloner>::postProcess (Orig, Cloned);
585
+ }
586
+ SILValue remapValue (SILValue Value) {
587
+ return Value;
588
+ }
589
+ SILBasicBlock *remapBasicBlock (SILBasicBlock *BB) { return BB; }
590
+ };
591
+ }
592
+
593
+ // / Handle CSE of open_existential_ref instructions.
594
+ // / Returns true if uses of open_existential_ref can
595
+ // / be replaced by a dominating instruction.
596
+ // / \Inst is the open_existential_ref instruction
597
+ // / \V is the dominating open_existential_ref instruction
598
+ // / \I is the iterator referring to the current instruction.
599
+ bool CSE::processOpenExistentialRef (SILInstruction *Inst, ValueBase *V,
600
+ SILBasicBlock::iterator &I) {
601
+ assert (isa<OpenExistentialRefInst>(Inst));
602
+ llvm::SmallSetVector<SILInstruction *, 16 > Candidates;
603
+ // Collect all candidates that may contain opened archetypes
604
+ // that need to be replaced.
605
+ for (auto Use : Inst->getUses ()) {
606
+ auto User = Use->getUser ();
607
+ if (User->mayHaveOpenedArchetypeOperands ()) {
608
+ if (canHandle (User)) {
609
+ auto It = AvailableValues->begin (User);
610
+ if (It != AvailableValues->end ()) {
611
+ return false ;
612
+ }
613
+ }
614
+ Candidates.insert (User);
615
+ }
616
+ }
617
+ // Now process candidates.
618
+ auto OldOpenedArchetype = getOpenedArchetypeOf (Inst);
619
+ auto NewOpenedArchetype = getOpenedArchetypeOf (dyn_cast<SILInstruction>(V));
620
+ // TODO: Move it to CSE instance to avoid recreating it every time?
621
+ SILOpenedArchetypesTracker OpenedArchetypesTracker (*Inst->getFunction ());
622
+ // Register the new archetype to be used.
623
+ OpenedArchetypesTracker.registerOpenedArchetypes (dyn_cast<SILInstruction>(V));
624
+ // Use a cloner. It makes copying the instruction and remaping of
625
+ // opened archetypes trivial.
626
+ InstructionCloner Cloner (I->getFunction ());
627
+ Cloner.registerOpenedExistentialRemapping (
628
+ OldOpenedArchetype->castTo <ArchetypeType>(), NewOpenedArchetype);
629
+ auto &Builder = Cloner.getBuilder ();
630
+ Builder.setOpenedArchetypesTracker (&OpenedArchetypesTracker);
631
+
632
+ // Now clone each candidate and replace the opened archetype
633
+ // by a dominating one.
634
+ for (auto Candidate : Candidates) {
635
+ Builder.getOpenedArchetypes ().addOpenedArchetypeOperands (
636
+ Candidate->getOpenedArchetypeOperands ());
637
+ Builder.setInsertionPoint (Candidate);
638
+ auto NewI = Cloner.clone (Candidate);
639
+ Candidate->replaceAllUsesWith (NewI);
640
+ if (I == Candidate->getIterator ())
641
+ I = NewI->getIterator ();
642
+ eraseFromParentWithDebugInsts (Candidate, I);
643
+ }
644
+ return true ;
645
+ }
646
+
528
647
bool CSE::processNode (DominanceInfoNode *Node) {
529
648
SILBasicBlock *BB = Node->getBlock ();
530
649
bool Changed = false ;
@@ -572,11 +691,17 @@ bool CSE::processNode(DominanceInfoNode *Node) {
572
691
// instruction has an available value. If so, use it.
573
692
if (ValueBase *V = AvailableValues->lookup (Inst)) {
574
693
DEBUG (llvm::dbgs () << " SILCSE CSE: " << *Inst << " to: " << *V << ' \n ' );
575
- Inst->replaceAllUsesWith (V);
576
- Inst->eraseFromParent ();
577
- Changed = true ;
578
- ++NumCSE;
579
- continue ;
694
+ // Instructions producing a new opened archetype need a special handling,
695
+ // because replacing these intructions may require a replacement
696
+ // of the opened archetype type operands in some of the uses.
697
+ if (!isa<OpenExistentialRefInst>(Inst) ||
698
+ processOpenExistentialRef (Inst, V, I)) {
699
+ Inst->replaceAllUsesWith (V);
700
+ Inst->eraseFromParent ();
701
+ Changed = true ;
702
+ ++NumCSE;
703
+ continue ;
704
+ }
580
705
}
581
706
582
707
// Otherwise, just remember that this value is available.
@@ -687,6 +812,7 @@ bool CSE::canHandle(SILInstruction *Inst) {
687
812
case ValueKind::ThinFunctionToPointerInst:
688
813
case ValueKind::PointerToThinFunctionInst:
689
814
case ValueKind::MarkDependenceInst:
815
+ case ValueKind::OpenExistentialRefInst:
690
816
return true ;
691
817
default :
692
818
return false ;
0 commit comments