Skip to content

Commit

Permalink
Avoid creating result temp for is-expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
alrz committed Jun 26, 2023
1 parent 16d7bbb commit 5f13ffe
Show file tree
Hide file tree
Showing 11 changed files with 398 additions and 220 deletions.
8 changes: 8 additions & 0 deletions src/Compilers/CSharp/Portable/BoundTree/BoundNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,14 @@ private void CheckDeclared(LocalSymbol local)
return null;
}

public override BoundNode? VisitLoweredIsPatternExpression(BoundLoweredIsPatternExpression node)
{
AddAll(node.Locals);
base.VisitLoweredIsPatternExpression(node);
RemoveAll(node.Locals);
return null;
}

public override BoundNode? VisitSwitchStatement(BoundSwitchStatement node)
{
AddAll(node.InnerLocals);
Expand Down
9 changes: 9 additions & 0 deletions src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2265,6 +2265,7 @@
'is not Type t') will need to compensate for negated patterns. IsNegated is set if Pattern is the negated
form of the inner pattern represented by DecisionDag. -->
<Node Name="BoundIsPatternExpression" Base="BoundExpression">
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Expression" Type="BoundExpression" Null="disallow"/>
<Field Name="Pattern" Type="BoundPattern" Null="disallow"/>
<Field Name="IsNegated" Type="bool"/>
Expand All @@ -2273,6 +2274,14 @@
<Field Name="WhenFalseLabel" Type="LabelSymbol" Null="disallow"/>
</Node>

<Node Name="BoundLoweredIsPatternExpression" Base="BoundExpression">
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Locals" Type="ImmutableArray&lt;LocalSymbol&gt;"/>
<Field Name="Statements" Type="ImmutableArray&lt;BoundStatement&gt;"/>
<Field Name="WhenTrueLabel" Type="LabelSymbol"/>
<Field Name="WhenFalseLabel" Type="LabelSymbol"/>
</Node>

<AbstractNode Name="BoundPattern" Base="BoundNode">
<Field Name="InputType" Type="TypeSymbol" Null="disallow"/>
<Field Name="NarrowedType" Type="TypeSymbol" Null="disallow"/>
Expand Down
51 changes: 46 additions & 5 deletions src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@ private void EmitExpressionCore(BoundExpression expression, bool used)
EmitRefValueOperator((BoundRefValueOperator)expression, used);
break;

case BoundKind.LoweredIsPatternExpression:
EmitLoweredIsPatternExpression((BoundLoweredIsPatternExpression)expression, used);
break;

case BoundKind.LoweredConditionalAccess:
EmitLoweredConditionalAccessExpression((BoundLoweredConditionalAccess)expression, used);
break;
Expand Down Expand Up @@ -352,6 +356,33 @@ private void EmitExpressionCore(BoundExpression expression, bool used)
}
}

private void EmitLoweredIsPatternExpression(BoundLoweredIsPatternExpression node, bool used)
{
_builder.AssertStackEmpty();

DefineLocals(node.Syntax, node.Locals);
EmitStatements(node.Statements);

if (!used)
{
_builder.MarkLabel(node.WhenTrueLabel);
_builder.MarkLabel(node.WhenFalseLabel);
}
else
{
var doneLabel = new object();
_builder.MarkLabel(node.WhenTrueLabel);
_builder.EmitBoolConstant(true);
_builder.EmitBranch(ILOpCode.Br, doneLabel);
_builder.AdjustStack(-1);
_builder.MarkLabel(node.WhenFalseLabel);
_builder.EmitBoolConstant(false);
_builder.MarkLabel(doneLabel);
}

FreeLocals(node.Locals);
}

private void EmitThrowExpression(BoundThrowExpression node, bool used)
{
this.EmitThrow(node.Expression);
Expand Down Expand Up @@ -852,29 +883,39 @@ private void EmitSequenceExpression(BoundSequence sequence, bool used)

private void DefineLocals(BoundSequence sequence)
{
if (sequence.Locals.IsEmpty)
DefineLocals(sequence.Syntax, sequence.Locals);
}

private void DefineLocals(SyntaxNode syntax, ImmutableArray<LocalSymbol> locals)
{
if (locals.IsEmpty)
{
return;
}

_builder.OpenLocalScope();

foreach (var local in sequence.Locals)
foreach (var local in locals)
{
DefineLocal(local, sequence.Syntax);
DefineLocal(local, syntax);
}
}

private void FreeLocals(BoundSequence sequence)
{
if (sequence.Locals.IsEmpty)
FreeLocals(sequence.Locals);
}

private void FreeLocals(ImmutableArray<LocalSymbol> locals)
{
if (locals.IsEmpty)
{
return;
}

_builder.CloseLocalScope();

foreach (var local in sequence.Locals)
foreach (var local in locals)
{
FreeLocal(local);
}
Expand Down
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1447,6 +1447,16 @@ public override BoundNode VisitSwitchDispatch(BoundSwitchDispatch node)
return node.Update(boundExpression, node.Cases, node.DefaultLabel, node.LengthBasedStringSwitchDataOpt);
}

public override BoundNode VisitLoweredIsPatternExpression(BoundLoweredIsPatternExpression node)
{
EnsureOnlyEvalStack();
DeclareLocals(node.Locals, stack: 0);
var result = base.VisitLoweredIsPatternExpression(node);
RecordBranch(node.WhenTrueLabel);
RecordBranch(node.WhenFalseLabel);
return result;
}

public override BoundNode VisitConditionalOperator(BoundConditionalOperator node)
{
var origStack = StackDepth();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2973,6 +2973,11 @@ public override BoundNode VisitConditionalReceiver(BoundConditionalReceiver node
return null;
}

public override BoundNode VisitLoweredIsPatternExpression(BoundLoweredIsPatternExpression node)
{
return null;
}

public override BoundNode VisitComplexConditionalReceiver(BoundComplexConditionalReceiver node)
{
var savedState = this.State.Clone();
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 5f13ffe

Please sign in to comment.