Skip to content

Commit

Permalink
Added peepholes and const folding rules
Browse files Browse the repository at this point in the history
+ Peepholes and const folding rules for Sub, Shl, Or
+ Added tests
  • Loading branch information
techie-mike committed Mar 6, 2024
1 parent 49aaa48 commit fa6c9b6
Show file tree
Hide file tree
Showing 10 changed files with 517 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ set(COMPILER_SOURCES
${CMAKE_SOURCE_DIR}/src/optimizations/analysis/linear_order.cpp
${CMAKE_SOURCE_DIR}/src/optimizations/analysis/liveness_analyzer.cpp
${CMAKE_SOURCE_DIR}/src/optimizations/linear_scan.cpp
${CMAKE_SOURCE_DIR}/src/optimizations/peepholes.cpp
${CMAKE_SOURCE_DIR}/src/optimizations/constant_folding.cpp
)

add_subdirectory(tests)
Expand Down
19 changes: 19 additions & 0 deletions src/inst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,4 +260,23 @@ IfInst *Inst::CastToIf() {
return static_cast<IfInst *>(this);
}

ConstantInst *Inst::CastToConstant() {
ASSERT(GetOpcode() == Opcode::Constant);
return static_cast<ConstantInst *>(this);
}

void Inst::ReplaceDataUsers(Inst *from) {
ASSERT(!HasControlProp());
for (auto it = from->StartIteratorDataUsers(); it != from->GetRawUsers().end(); it++) {
auto user = *it;
AddDataUser(user);
for (id_t i = 0; i < user->NumDataInputs(); i++) {
if (user->GetDataInput(i) == from) {
user->SetDataInput(i, this);
}
}
}
from->GetRawUsers().erase(from->StartIteratorDataUsers(), from->GetRawUsers().end());
}

}
28 changes: 28 additions & 0 deletions src/inst.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ std::string TypeToString(Type type);

class RegionInst;
class IfInst;
class ConstantInst;

class Inst
{
Expand Down Expand Up @@ -150,6 +151,10 @@ class Inst
prev_ = inst;
}

bool IsConst() const {
return GetOpcode() == Opcode::Constant;
}

Inst *GetPrev() {
return prev_;
}
Expand All @@ -164,6 +169,7 @@ class Inst

RegionInst *CastToRegion();
IfInst *CastToIf();
ConstantInst *CastToConstant();

bool IsPlaced() const {
return inst_placed_;
Expand All @@ -189,6 +195,8 @@ class Inst
return life_number_;
}

void ReplaceDataUsers(Inst *from);

private:
auto StartIteratorDataUsers() {
return HasControlProp() ? ++GetRawUsers().begin() : GetRawUsers().begin();
Expand Down Expand Up @@ -367,6 +375,19 @@ class ControlProp : public T
}
};

class UnaryOperation : public FixedInputs<1>
{
public:
UnaryOperation():
FixedInputs<1>() {}

UnaryOperation(Opcode opc):
FixedInputs<1>(opc) {}

UnaryOperation(Opcode opc, Type type, Inst *input0):
FixedInputs<1>(opc, type, {{input0}}) {}
};

class BinaryOperation : public FixedInputs<2>
{
public:
Expand All @@ -376,6 +397,9 @@ class BinaryOperation : public FixedInputs<2>
BinaryOperation(Opcode opc):
FixedInputs<2>(opc) {}

BinaryOperation(Type type, Inst *input0, Inst *input1):
FixedInputs<2>(Opcode::NONE, type, {{input0, input1}}) {}

BinaryOperation(Opcode opc, Type type, Inst *input0, Inst *input1):
FixedInputs<2>(opc, type, {{input0, input1}}) {}
};
Expand All @@ -386,6 +410,10 @@ class ConstantInst : public Inst, public ImmidiateProperty
Inst(Opcode::Constant, Type::INT64),
ImmidiateProperty(0) {}

ConstantInst(ImmType value):
Inst(Opcode::Constant, Type::INT64),
ImmidiateProperty(value) {}

virtual void DumpInputs(std::ostream &out) override {
out << std::string("0x") << std::hex << GetImm() << std::dec;
}
Expand Down
4 changes: 4 additions & 0 deletions src/opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ namespace compiler {
ACTION( Sub , BinaryOperation ) \
ACTION( Mul , BinaryOperation ) \
ACTION( Div , BinaryOperation ) \
ACTION( Shl , BinaryOperation ) \
ACTION( Shr , BinaryOperation ) \
ACTION( And , BinaryOperation ) \
ACTION( Or , BinaryOperation ) \
ACTION( Constant , ConstantInst ) \
ACTION( If , IfInst ) \
ACTION( Jump , JumpInst ) \
Expand Down
35 changes: 35 additions & 0 deletions src/optimizations/constant_folding.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "constant_folding.h"
#include "graph.h"

namespace compiler {

bool ConstFoldingBinaryOp(Graph *graph, Inst *inst) {
auto input0 = inst->GetDataInput(0);
auto input1 = inst->GetDataInput(1);

if (!input0->IsConst() || !input1->IsConst()) {
return false;
}

Inst *new_const = nullptr;
auto imm0 = input0->CastToConstant()->GetImm();
auto imm1 = input1->CastToConstant()->GetImm();

switch (inst->GetOpcode()) {
case Opcode::Sub:
new_const = graph->CreateConstantInst(imm0 - imm1);
break;
case Opcode::Shl:
new_const = graph->CreateConstantInst(imm0 << imm1);
break;
case Opcode::Or:
new_const = graph->CreateConstantInst(imm0 | imm1);
break;
default:
UNREACHABLE();
}
new_const->ReplaceDataUsers(inst);
return true;
}

}
10 changes: 10 additions & 0 deletions src/optimizations/constant_folding.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

namespace compiler {

class Inst;
class Graph;

bool ConstFoldingBinaryOp(Graph *graph, Inst *inst);

}
108 changes: 108 additions & 0 deletions src/optimizations/peepholes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#include <limits>

#include "peepholes.h"
#include "analysis/rpo.h"
#include "constant_folding.h"

namespace compiler {

void Peepholes::Run() {
auto rpo = RpoInsts(graph_);
rpo.Run();
auto rpo_vector = rpo.GetVector();
for (auto inst : rpo_vector) {
AnalysisInst(inst);
}
}

void Peepholes::AnalysisInst(Inst *inst) {
switch (inst->GetOpcode()) {
case Opcode::Sub:
VisitSub(inst);
break;
case Opcode::Shl:
VisitShl(inst);
break;
case Opcode::Or:
VisitOr(inst);
break;
default:
break;
}
}

void Peepholes::VisitSub(Inst *inst) {
if (ConstFoldingBinaryOp(graph_, inst)) {
return;
}

if (TryOptimizeSubZero(inst)) {
return;
}
}

void Peepholes::VisitShl(Inst *inst) {
if (ConstFoldingBinaryOp(graph_, inst)) {
return;
}

if (TryOptimizeShlAfterShr(inst)) {
return;
}
}

void Peepholes::VisitOr(Inst *inst) {
if (ConstFoldingBinaryOp(graph_, inst)) {
return;
}
if (TryOptimizeOrZero(inst)) {
return;
}
}

bool Peepholes::TryOptimizeSubZero(Inst *inst) {
auto input0 = inst->GetDataInput(0);
auto input1 = inst->GetDataInput(1);

if (input1->IsConst() && input1->CastToConstant()->GetImm() == 0) {
input0->ReplaceDataUsers(inst);
return true;
}
return false;
}

bool Peepholes::TryOptimizeShlAfterShr(Inst *inst) {
auto input0 = inst->GetDataInput(0);
auto input1 = inst->GetDataInput(1);

if (input1->IsConst() &&
input0->GetOpcode() == Opcode::Shr &&
input0->GetDataInput(1)->IsConst() &&
input0->GetDataInput(1)->CastToConstant()->GetImm() == input1->CastToConstant()->GetImm()) {

auto input_shr = input0->GetDataInput(0);
auto shift = input1->CastToConstant()->GetImm();
auto new_const = graph_->CreateConstantInst(std::numeric_limits<ImmType>::max() & (0xffffffffffffffff << shift));
auto inst_and = graph_->CreateAndInst(input_shr->GetType(), input_shr, new_const);
inst_and->ReplaceDataUsers(inst);
return true;
}
return false;
}

bool Peepholes::TryOptimizeOrZero(Inst *inst) {
auto input0 = inst->GetDataInput(0);
auto input1 = inst->GetDataInput(1);

if (input0->IsConst()) {
std::swap(input0, input1);
}

if (input1->IsConst() && input1->CastToConstant()->GetImm() == 0) {
input0->ReplaceDataUsers(inst);
return true;
}
return false;
}

}
31 changes: 31 additions & 0 deletions src/optimizations/peepholes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include "graph.h"

namespace compiler {

class Peepholes {
public:
Peepholes(Graph *graph):
graph_(graph) {}

void Run();

private:
void AnalysisInst(Inst *inst);

// Process instruction
void VisitSub(Inst *inst);
void VisitShl(Inst *inst);
void VisitOr(Inst *inst);

// Cases of optimization
bool TryOptimizeSubZero(Inst *inst);
bool TryOptimizeShlAfterShr(Inst *inst);
bool TryOptimizeOrZero(Inst *inst);

private:
Graph *graph_;
};

}
23 changes: 22 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,28 @@ add_custom_target(
COMMAND analysis_tests
)

add_executable(
peepholes_tests
peepholes_tests.cpp
graph_comparator.cpp
${COMPILER_SOURCES}
)
target_include_directories(peepholes_tests PUBLIC "${CMAKE_SOURCE_DIR}/src")

gtest_discover_tests(peepholes_tests)

target_link_libraries(
peepholes_tests
GTest::gtest_main
)

add_custom_target(
peepholes_tests_gtest
COMMAND peepholes_tests
)


add_custom_target(
tests
DEPENDS graph_tests_gtest analysis_tests_gtest
DEPENDS graph_tests_gtest analysis_tests_gtest peepholes_tests_gtest
)
Loading

0 comments on commit fa6c9b6

Please sign in to comment.