Skip to content

Commit

Permalink
fuse common expressions of integer subtraction in IR
Browse files Browse the repository at this point in the history
  • Loading branch information
Viir committed Jan 4, 2025
1 parent ecac387 commit dced648
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 8 deletions.
68 changes: 60 additions & 8 deletions implement/pine/PineVM/PineIRCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,9 @@ public static IReadOnlyList<StackInstruction> CompileKernelApplication_Int_Add(
{
return
[
new StackInstruction(StackInstructionKind.Push_Literal, Literal: PineValueAsInteger.ValueFromSignedInteger(0))
new StackInstruction(
StackInstructionKind.Push_Literal,
Literal: PineValueAsInteger.ValueFromSignedInteger(0))
];
}

Expand All @@ -491,16 +493,33 @@ public static IReadOnlyList<StackInstruction> CompileKernelApplication_Int_Add(
{
var item = listExpr.items[i];

var itemOps =
CompileExpressionTransitive(
item,
localIndexFromExpr);
if (0 < i && TryParseExprAsIntNegation(item) is { } negatedItem)
{
var itemOps =
CompileExpressionTransitive(
negatedItem,
localIndexFromExpr);

addOps.AddRange(itemOps);
addOps.AddRange(itemOps);

if (0 < i)
if (0 < i)
{
addOps.Add(new StackInstruction(StackInstructionKind.Int_Sub_Binary));
}
}
else
{
addOps.Add(new StackInstruction(StackInstructionKind.Int_Add_Binary));
var itemOps =
CompileExpressionTransitive(
item,
localIndexFromExpr);

addOps.AddRange(itemOps);

if (0 < i)
{
addOps.Add(new StackInstruction(StackInstructionKind.Int_Add_Binary));
}
}
}

Expand Down Expand Up @@ -810,4 +829,37 @@ .. CompileExpressionTransitive(input, localIndexFromExpr),
new StackInstruction(StackInstructionKind.Bit_Shift_Right_List)
];
}

public static Expression? TryParseExprAsIntNegation(Expression expression)
{
if (expression is not Expression.KernelApplication kernelApp)
{
return null;
}

if (kernelApp.Function is "negate")
{
return kernelApp.Input;
}

if (kernelApp.Function is "int_mul" &&
kernelApp.Input is Expression.List mulList && mulList.items.Count is 2)
{
if (mulList.items[0] is Expression.Literal literalExpr &&
KernelFunction.SignedIntegerFromValueRelaxed(literalExpr.Value) is { } literalValue &&
literalValue == -1)
{
return mulList.items[1];
}

if (mulList.items[1] is Expression.Literal literalExpr2 &&
KernelFunction.SignedIntegerFromValueRelaxed(literalExpr2.Value) is { } literalValue2 &&
literalValue2 == -1)
{
return mulList.items[0];
}
}

return null;
}
}
123 changes: 123 additions & 0 deletions implement/test-elm-time/PineVMTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,129 @@ public void Compile_stack_frame_instructions()
StackInstruction.Return
])
},

new
{
expression =
(Expression)
new Expression.KernelApplication(
function: "int_add",
input:
Expression.ListInstance(
[
new Expression.KernelApplication(
function: "head",
input:
new Expression.KernelApplication(
function: "skip",
input:
Expression.ListInstance(
[
Expression.LiteralInstance(PineValueAsInteger.ValueFromSignedInteger(1)),
Expression.EnvironmentInstance,
]))),

new Expression.KernelApplication(
function: "negate",
input:
new Expression.KernelApplication(
function: "head",
input:
new Expression.KernelApplication(
function: "skip",
input:
Expression.ListInstance(
[
Expression.LiteralInstance(PineValueAsInteger.ValueFromSignedInteger(2)),
Expression.EnvironmentInstance,
])))),
])),

expected =
new PineVM.StackFrameInstructions(
[
StackInstruction.PushEnvironment,

new StackInstruction(
StackInstructionKind.Skip_Head_Const,
SkipCount: 1),

StackInstruction.PushEnvironment,

new StackInstruction(
StackInstructionKind.Skip_Head_Const,
SkipCount: 2),

new StackInstruction(
StackInstructionKind.Int_Sub_Binary),

StackInstruction.Return,
])
},

new
{
expression =
(Expression)
new Expression.KernelApplication(
function: "int_add",
input:
Expression.ListInstance(
[
new Expression.KernelApplication(
function: "head",
input:
new Expression.KernelApplication(
function: "skip",
input:
Expression.ListInstance(
[
Expression.LiteralInstance(PineValueAsInteger.ValueFromSignedInteger(1)),
Expression.EnvironmentInstance,
]))),

new Expression.KernelApplication(
function: "int_mul",
input:
Expression.ListInstance(
[
Expression.LiteralInstance(PineValueAsInteger.ValueFromSignedInteger(-1)),

new Expression.KernelApplication(
function: "head",
input:
new Expression.KernelApplication(
function: "skip",
input:
Expression.ListInstance(
[
Expression.LiteralInstance(PineValueAsInteger.ValueFromSignedInteger(2)),
Expression.EnvironmentInstance,
])))
])),
])),

expected =
new PineVM.StackFrameInstructions(
[
StackInstruction.PushEnvironment,

new StackInstruction(
StackInstructionKind.Skip_Head_Const,
SkipCount: 1),

StackInstruction.PushEnvironment,

new StackInstruction(
StackInstructionKind.Skip_Head_Const,
SkipCount: 2),

new StackInstruction(
StackInstructionKind.Int_Sub_Binary),

StackInstruction.Return,
])
},
};

var parseCache = new PineVMParseCache();
Expand Down

0 comments on commit dced648

Please sign in to comment.