Skip to content

Commit 4f69056

Browse files
author
Tim Foley
authored
Fix an SSA construction bug (shader-slang#739)
Fixes shader-slang#723 This fixes a case where the SSA construction pass wasn't dealing with the possibility of a phi node that it had provisionally introduced being replaced later. The result was invalid IR (caught with `-validate-ir`) that referenced an instruction nowhere in the IR module (because it was dropped). The fix centralizes the code for dealing with phi nodes that have been replaced, so that the two different paths where variables get "read" during SSA construction can both use the same logic.
1 parent 3e96221 commit 4f69056

File tree

2 files changed

+65
-21
lines changed

2 files changed

+65
-21
lines changed

source/slang/ir-ssa.cpp

+56-21
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,43 @@ void maybeSealBlock(
572572
blockInfo->isSealed = true;
573573
}
574574

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+
575612
IRInst* readVarRec(
576613
ConstructSSAContext* context,
577614
SSABlockInfo* blockInfo,
@@ -664,10 +701,24 @@ IRInst* readVarRec(
664701
// value for the given variable in this block
665702
writeVar(context, blockInfo, var, val);
666703

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+
667717
return val;
668718
}
669719

670720

721+
671722
IRInst* readVar(
672723
ConstructSSAContext* context,
673724
SSABlockInfo* blockInfo,
@@ -682,27 +733,11 @@ IRInst* readVar(
682733
// Hooray, we found a value to use, and we
683734
// can proceed without too many complications.
684735

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);
706741

707742
return val;
708743
}

source/slang/slang.natvis

+9
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,15 @@
9393
</Expand>
9494
</Synthetic>
9595
<Item Name="[parent]">parent</Item>
96+
<Synthetic Name="[children]" Condition="(op &gt;= Slang::kIROp_FirstParentInst) &amp;&amp; (op &lt;= Slang::kIROp_LastParentInst)">
97+
<Expand>
98+
<LinkedListItems>
99+
<HeadPointer>(*((Slang::IRParentInst*) this)).children.first</HeadPointer>
100+
<NextPointer>next</NextPointer>
101+
<ValueNode>this</ValueNode>
102+
</LinkedListItems>
103+
</Expand>
104+
</Synthetic>
96105
<Synthetic Name="[uses]">
97106
<Expand>
98107
<LinkedListItems>

0 commit comments

Comments
 (0)