+8
-18
@@ -31,25 +31,15 @@ void ssa::optimize(const std::unique_ptr<furlang::ir::function>& func) {
|
|||||||
const auto& block = func->blocks()[i];
|
const auto& block = func->blocks()[i];
|
||||||
|
|
||||||
for (const auto& instr : block->instructions()) {
|
for (const auto& instr : block->instructions()) {
|
||||||
switch (instr->type()) {
|
if (instr->has_destination()) {
|
||||||
case furlang::ir::instruction_t::Assign: {
|
if (instr->destination().type() == furlang::ir::operand_t::Register) {
|
||||||
const auto& assign = dynamic_cast<const furlang::ir::assign_instruction&>(*instr);
|
regSites[instr->destination().reg()].insert(i);
|
||||||
regSites[assign.destination().reg()].insert(i);
|
|
||||||
if (assign.source().type() == furlang::ir::operand_t::Register) {
|
|
||||||
regUses[i].insert(assign.source().reg());
|
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
case furlang::ir::instruction_t::BinaryOp: {
|
|
||||||
const auto& binOp = dynamic_cast<const furlang::ir::binary_op_instruction&>(*instr);
|
for (const furlang::ir::operand* src : instr->sources()) {
|
||||||
regSites[binOp.dst().reg()].insert(i);
|
if (src->type() != furlang::ir::operand_t::Register) continue;
|
||||||
if (binOp.lhs().type() == furlang::ir::operand_t::Register) {
|
regUses[i].insert(src->reg());
|
||||||
regUses[i].insert(binOp.lhs().reg());
|
|
||||||
}
|
|
||||||
if (binOp.rhs().type() == furlang::ir::operand_t::Register) {
|
|
||||||
regUses[i].insert(binOp.rhs().reg());
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <stdexcept>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -69,6 +70,41 @@ public:
|
|||||||
* @return The type.
|
* @return The type.
|
||||||
*/
|
*/
|
||||||
virtual instruction_t type() const = 0;
|
virtual instruction_t type() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns whether this instruction has a destination operand.
|
||||||
|
*
|
||||||
|
* @return true if this instruction has the destination operand.
|
||||||
|
*/
|
||||||
|
virtual bool has_destination() const { return false; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns destination operand of this instruction.
|
||||||
|
*
|
||||||
|
* @return The destination operand.
|
||||||
|
*/
|
||||||
|
virtual operand& destination() { throw std::runtime_error("instruction type mismatch"); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns destination operand of this instruction.
|
||||||
|
*
|
||||||
|
* @return The destination operand.
|
||||||
|
*/
|
||||||
|
virtual const operand& destination() const { throw std::runtime_error("instruction type mismatch"); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a list of source operands of this instruction.
|
||||||
|
*
|
||||||
|
* @return The list of source operands.
|
||||||
|
*/
|
||||||
|
virtual std::vector<operand*> sources() { return {}; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a list of source operands of this instruction.
|
||||||
|
*
|
||||||
|
* @return The list of source operands.
|
||||||
|
*/
|
||||||
|
virtual std::vector<const operand*> sources() const { return {}; }
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Prints an instruction to an output stream.
|
* @brief Prints an instruction to an output stream.
|
||||||
@@ -161,18 +197,39 @@ public:
|
|||||||
instruction_t type() const override { return instruction_t::Assign; }
|
instruction_t type() const override { return instruction_t::Assign; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns this instruction's source.
|
* @brief Returns whether this instruction has a destination operand.
|
||||||
*
|
*
|
||||||
* @return The source.
|
* @return true
|
||||||
*/
|
*/
|
||||||
const operand& source() const { return m_source; }
|
bool has_destination() const override { return true; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns this instruction's destination.
|
* @brief Returns this instruction's destination.
|
||||||
*
|
*
|
||||||
* @return The destination.
|
* @return The destination.
|
||||||
*/
|
*/
|
||||||
const operand& destination() const { return m_destination; }
|
operand& destination() override { return m_destination; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns this instruction's destination.
|
||||||
|
*
|
||||||
|
* @return The destination.
|
||||||
|
*/
|
||||||
|
const operand& destination() const override { return m_destination; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a list of this instruction's source operands.
|
||||||
|
*
|
||||||
|
* @return The list of source operands.
|
||||||
|
*/
|
||||||
|
std::vector<operand*> sources() override { return { &m_source }; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a list of this instruction's source operands.
|
||||||
|
*
|
||||||
|
* @return The list of source operands.
|
||||||
|
*/
|
||||||
|
std::vector<const operand*> sources() const override { return { &m_source }; }
|
||||||
private:
|
private:
|
||||||
operand m_source;
|
operand m_source;
|
||||||
operand m_destination;
|
operand m_destination;
|
||||||
@@ -256,6 +313,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
instruction_t type() const override { return instruction_t::BinaryOp; }
|
instruction_t type() const override { return instruction_t::BinaryOp; }
|
||||||
|
|
||||||
|
bool has_destination() const override { return true; }
|
||||||
|
|
||||||
|
operand& destination() override { return m_dst; }
|
||||||
|
|
||||||
|
const operand& destination() const override { return m_dst; }
|
||||||
|
|
||||||
|
std::vector<operand*> sources() override { return { &m_lhs, &m_rhs }; }
|
||||||
|
|
||||||
|
std::vector<const operand*> sources() const override { return { &m_lhs, &m_rhs }; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns this instruction's operation type.
|
* @brief Returns this instruction's operation type.
|
||||||
*
|
*
|
||||||
@@ -445,6 +512,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
instruction_t type() const override { return instruction_t::Return; }
|
instruction_t type() const override { return instruction_t::Return; }
|
||||||
|
|
||||||
|
std::vector<operand*> sources() override {
|
||||||
|
if (m_value.has_value()) return { &*m_value };
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const operand*> sources() const override {
|
||||||
|
if (m_value.has_value()) return { &*m_value };
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns this instruction's return value operand.
|
* @brief Returns this instruction's return value operand.
|
||||||
*
|
*
|
||||||
@@ -469,7 +546,7 @@ protected:
|
|||||||
class phi_instruction final : public instruction {
|
class phi_instruction final : public instruction {
|
||||||
public:
|
public:
|
||||||
phi_instruction(register_operand dst)
|
phi_instruction(register_operand dst)
|
||||||
: m_dst(dst) {}
|
: m_dst(operand::new_reg(dst)) {}
|
||||||
|
|
||||||
~phi_instruction() override = default;
|
~phi_instruction() override = default;
|
||||||
|
|
||||||
@@ -499,7 +576,14 @@ public:
|
|||||||
*
|
*
|
||||||
* @return The register.
|
* @return The register.
|
||||||
*/
|
*/
|
||||||
register_operand destination() const { return m_dst; }
|
operand& destination() override { return m_dst; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns this instruction's destination register.
|
||||||
|
*
|
||||||
|
* @return The register.
|
||||||
|
*/
|
||||||
|
const operand& destination() const override { return m_dst; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns this instruction's labels.
|
* @brief Returns this instruction's labels.
|
||||||
@@ -515,7 +599,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
const std::vector<std::pair<operand, block_index>>& labels() const { return m_labels; }
|
const std::vector<std::pair<operand, block_index>>& labels() const { return m_labels; }
|
||||||
private:
|
private:
|
||||||
register_operand m_dst;
|
operand m_dst;
|
||||||
std::vector<std::pair<operand, block_index>> m_labels;
|
std::vector<std::pair<operand, block_index>> m_labels;
|
||||||
protected:
|
protected:
|
||||||
std::ostream& print(std::ostream& os) const override {
|
std::ostream& print(std::ostream& os) const override {
|
||||||
|
|||||||
@@ -137,6 +137,19 @@ public:
|
|||||||
return operand;
|
return operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Construct a new register operand.
|
||||||
|
*
|
||||||
|
* @param value Value of the new register operand.
|
||||||
|
* @return The register operand.
|
||||||
|
*/
|
||||||
|
static operand new_reg(register_operand value) {
|
||||||
|
operand operand;
|
||||||
|
operand.m_type = operand_t::Register;
|
||||||
|
operand.m_value.reg = value;
|
||||||
|
return operand;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new variable operand.
|
* @brief Construct a new variable operand.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user