Skip to content

Commit

Permalink
Perf: initial support for functions inlining
Browse files Browse the repository at this point in the history
  • Loading branch information
mrunix00 committed May 25, 2024
1 parent e091e66 commit 89e010e
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
72 changes: 71 additions & 1 deletion src/bytecode/compiler/Optimizer.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "Optimizer.h"
#include <algorithm>

bool Bytecode::Optimizer::is_tail_recursive(const Bytecode::Segment &segment, size_t id) {
const auto &instructions = segment.instructions;
Expand All @@ -18,4 +19,73 @@ void Bytecode::Optimizer::optimize_tail_calls(Segment &segment) {
{.r_param = {number_of_args}},
});
instructions.push_back(new (Instruction){Instruction::Return});
}
}

bool Bytecode::Optimizer::is_inlineable(const Bytecode::Segment &segment, size_t id) {
return std::none_of(
segment.instructions.begin(),
segment.instructions.end(),
[id](Bytecode::Instruction *instruction) {
return (instruction->type == Bytecode::Instruction::Call &&
instruction->params.ri_params.reg == id) ||
// TODO: Fix tail calls later
instruction->type == Bytecode::Instruction::TailCall;
});
}

/* This code is fucking garbage!
* TODO: Clean this shit up */
void Bytecode::Optimizer::inline_function(
Bytecode::Segment &segment,
Bytecode::Segment &to_inline,
size_t id) {
size_t inside_offset = 0;
size_t outside_offset = 0;
for (auto current_instruction = segment.instructions.begin();
current_instruction != segment.instructions.end();
std::advance(current_instruction, 1)) {
if ((*current_instruction)->type == Instruction::Call &&
(*current_instruction)->params.ri_params.reg == id) {
auto number_of_args = (*current_instruction)->params.ri_params.intermediate.data.reg;
current_instruction = segment.instructions.erase(current_instruction);

// Load function arguments
for (size_t i = number_of_args - 1; i != -1; i--) {
auto load_instruction = new Instruction{
Instruction::StoreLocal,
{.r_param = {i}},
};
current_instruction = segment.instructions.insert(current_instruction, load_instruction);
std::advance(current_instruction, 1);
}
inside_offset = current_instruction - segment.instructions.begin();

// inline the function
for (auto new_instruction: to_inline.instructions) {
if (new_instruction->type == Instruction::Return)
break;
if (new_instruction->type == Instruction::Jump ||
new_instruction->type == Instruction::CondJumpIfNot) {
// Align jump locations inside the function
auto jump_instruction = new Instruction{
new_instruction->type,
{.r_param = {new_instruction->params.r_param.reg + inside_offset}},
};
current_instruction = segment.instructions.insert(current_instruction, jump_instruction);
} else {
current_instruction = segment.instructions.insert(current_instruction, new_instruction);
}
std::advance(current_instruction, 1);
outside_offset++;
}
if (current_instruction == segment.instructions.end())
break;
}

// Align jump locations outside the function
if ((*current_instruction)->type == Instruction::Jump ||
(*current_instruction)->type == Instruction::CondJumpIfNot) {
(*current_instruction)->params.r_param.reg += outside_offset;
}
}
}
6 changes: 5 additions & 1 deletion src/bytecode/compiler/Optimizer.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#pragma once

#include "Program.h"
#include "Segment.h"

namespace Bytecode::Optimizer {
bool is_tail_recursive(const Segment &segment, size_t id);
bool is_inlineable(const Segment &segment, size_t id);
void optimize_tail_calls(Segment &segment);
}// namespace Bytecode::Optimizer
void inline_function(Segment &segment, Segment &to_inline, size_t id);
}// namespace Bytecode::Optimizer
8 changes: 8 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "utils/break_lines.h"
#include "utils/dump_bytecode.h"
#include "utils/printTokens.h"
#include <algorithm>
#include <fstream>
#include <getopt.h>
#include <iostream>
Expand Down Expand Up @@ -42,6 +43,13 @@ void exec_program(const std::string &program, struct options opts) {
Bytecode::Optimizer::optimize_tail_calls(*segment);
}

for (size_t i = 0; i < compiled_bytecode.segments.size(); i++) {
for (size_t j = 1; j < compiled_bytecode.segments.size(); j++) {
if (Bytecode::Optimizer::is_inlineable(*compiled_bytecode.segments[j], j))
Bytecode::Optimizer::inline_function(*compiled_bytecode.segments[i], *compiled_bytecode.segments[j], j);
}
}

if (opts.dumpBytecode)
dump_bytecode(compiled_bytecode);

Expand Down

0 comments on commit 89e010e

Please sign in to comment.