Last active
November 27, 2024 14:57
-
-
Save willtebbutt/19de1b203439469942b2b5134cdf99b4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#= | |
Goal: multiple any `SSAValue`s that go into :call / :invoke expressions by 5 before passing them in. So something like | |
```julia | |
Expr(:call, *, %5, 3) | |
``` | |
would become | |
```julia | |
%tmp = Expr(:call, *, 5, %5) | |
Expr(:call, *, %tmp, 3) | |
``` | |
The point is to demonstrate how a simple task which requires insertions into the IR can be done using BBCode. | |
=# | |
using Mooncake | |
import Core.Compiler as CC | |
# Define simple function. | |
function test_function(x) | |
y = sin(x) | |
z = cos(y) | |
a = y * z | |
return a | |
end | |
# Grab the IRCode. | |
ir = Base.code_ircode_by_type(Tuple{typeof(test_function), Float64})[1][1] | |
# Translate it into Mooncake's BBCode. The printing for BBCode is crap, so you should always | |
# just call `IRCode` in it if you want to print it out. | |
bb_ir = Mooncake.BBCode(ir) | |
# We're going to construct a completely new BBCode object. | |
# Iterate through each basic block. | |
new_blocks = map(bb_ir.blocks) do block | |
# Iterate through each statment in the current basic block. Each statement will be | |
# transformed into 1 or more new statments. | |
new_stmts = map(1:length(block)) do n | |
# Get the nth statement, and its associated ID. | |
inst = block.insts[n] | |
stmt = inst.stmt | |
id = block.inst_ids[n] | |
# If the statement is one that we're interested in transform it. | |
if Meta.isexpr(stmt, :invoke) || Meta.isexpr(stmt, :call) | |
# If we have an invoke, drop the method instance. | |
args = Meta.isexpr(stmt, :invoke) ? stmt.args[2:end] : stmt.args | |
# For each argument in the :invoke / :call, construct a statment which | |
# multiplies it by 5. If not statement should be added, return nothing. | |
# Return the ID which should be places in the original instruction. | |
extra_stmts = map(args) do arg | |
if arg isa Mooncake.ID | |
new_inst_id = Mooncake.ID() | |
inst_id_pair = (new_inst_id, Mooncake.new_inst(Expr(:call, *, 5, arg))) | |
return (inst_id_pair, new_inst_id) | |
else | |
return ((Mooncake.ID(), Mooncake.new_inst(nothing)), arg) | |
end | |
end | |
multiplying_stmts = map(first, extra_stmts) | |
new_args = map(last, extra_stmts) | |
return vcat(multiplying_stmts, (id, Mooncake.new_inst(Expr(:call, new_args...)))) | |
else | |
# Since this statment shouldn't be transformed, return the primal id / stmt. | |
return (id, inst)::Tuple{Mooncake.ID, CC.NewInstruction} | |
end | |
end | |
# Just concatenate the new statements. Keep the block id the same. | |
return Mooncake.BBlock(block.id, reduce(vcat, new_stmts)) | |
end | |
# Construct a new `BBCode` which is the same as the old one, just with different blocks. | |
new_bb_ir = Mooncake.BBCode(bb_ir, new_blocks) | |
# Convert the BBCode into an equivalent IRCode. | |
new_ir = CC.IRCode(new_bb_ir) | |
# Run a standard Julia optimisation pass on the IRCode to get rid of redundancies. | |
optimised_ir = Mooncake.optimise_ir!(new_ir) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment