@@ -572,6 +572,43 @@ void maybeSealBlock(
572
572
blockInfo->isSealed = true ;
573
573
}
574
574
575
+ // In some cases we may have a pointer to an IR value that
576
+ // represents a phi node that has been replaced with another
577
+ // IR value, because we discovered that the phi is no longer
578
+ // needed.
579
+ //
580
+ // The `maybeGetPhiReplacement` function will follow any
581
+ // chain of replacements that might be present, so that we
582
+ // don't end up referencing a dangling/unused value in
583
+ // the code that we generate.
584
+ //
585
+ IRInst* maybeGetPhiReplacement (
586
+ ConstructSSAContext* context,
587
+ IRInst* inVal)
588
+ {
589
+ IRInst* val = inVal;
590
+
591
+ while ( val->op == kIROp_Param )
592
+ {
593
+ // The value is a parameter, but is it a phi?
594
+ IRParam* maybePhi = (IRParam*) val;
595
+ RefPtr<PhiInfo> phiInfo = nullptr ;
596
+ if (!context->phiInfos .TryGetValue (maybePhi, phiInfo))
597
+ break ;
598
+
599
+ // Okay, this is indeed a phi we are adding, but
600
+ // is it one that got replaced?
601
+ if (!phiInfo->replacement )
602
+ break ;
603
+
604
+ // The phi we want to use got replaced, so we
605
+ // had better use the replacement instead.
606
+ val = phiInfo->replacement ;
607
+ }
608
+
609
+ return val;
610
+ }
611
+
575
612
IRInst* readVarRec (
576
613
ConstructSSAContext* context,
577
614
SSABlockInfo* blockInfo,
@@ -664,10 +701,24 @@ IRInst* readVarRec(
664
701
// value for the given variable in this block
665
702
writeVar (context, blockInfo, var, val);
666
703
704
+ // If `val` represents a phi node (block parameter) then
705
+ // it is possible that some of the operations above might
706
+ // have caused it to be replaced with another value,
707
+ // and in that case we had better not return it to
708
+ // be referenced in user code.
709
+ //
710
+ // Note: it is okay for the `valueForVar` map that
711
+ // we update in `writeVar` to use the old value, so long
712
+ // as we do this replacement logic anywhere we might read
713
+ // from that map.
714
+ //
715
+ val = maybeGetPhiReplacement (context, val);
716
+
667
717
return val;
668
718
}
669
719
670
720
721
+
671
722
IRInst* readVar (
672
723
ConstructSSAContext* context,
673
724
SSABlockInfo* blockInfo,
@@ -682,27 +733,11 @@ IRInst* readVar(
682
733
// Hooray, we found a value to use, and we
683
734
// can proceed without too many complications.
684
735
685
- // Well, let's check for one special case here, which
686
- // is when the value we intend to use is a `phi`
687
- // node that we ultimately decided to remove.
688
- while ( val->op == kIROp_Param )
689
- {
690
- // The value is a parameter, but is it a phi?
691
- IRParam* maybePhi = (IRParam*) val;
692
- RefPtr<PhiInfo> phiInfo = nullptr ;
693
- if (!context->phiInfos .TryGetValue (maybePhi, phiInfo))
694
- break ;
695
-
696
- // Okay, this is indeed a phi we are adding, but
697
- // is it one that got replaced?
698
- if (!phiInfo->replacement )
699
- break ;
700
-
701
- // The phi we want to use got replaced, so we
702
- // had better use the replacement instead.
703
- val = phiInfo->replacement ;
704
- }
705
-
736
+ // Just like in the `readVarRec` case above, we need
737
+ // to handle the case where `val` might represent
738
+ // a phi node that has subsequently been replaced.
739
+ //
740
+ val = maybeGetPhiReplacement (context, val);
706
741
707
742
return val;
708
743
}
0 commit comments