Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Sub peephole #20

Merged
merged 1 commit into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/inst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ void Inst::SetDataInput(id_t index, Inst *inst) {
if (HasControlProp()) {
index++;
}
// For dynamic inputs
if (index != NumAllInputs() && GetRawInput(index) != nullptr) {
GetRawInput(index)->DeleteDataUser(this);
}
SetRawInput(index, inst);
inst->AddDataUser(this);
}
Expand Down Expand Up @@ -268,9 +272,8 @@ ConstantInst *Inst::CastToConstant() {

void Inst::ReplaceDataUsers(Inst *from) {
ASSERT(!HasControlProp());
for (auto it = from->StartIteratorDataUsers(); it != from->GetRawUsers().end(); it++) {
for (auto it = from->StartIteratorDataUsers(); it != from->GetRawUsers().end(); it = from->StartIteratorDataUsers()) {
auto user = *it;
AddDataUser(user);
for (id_t i = 0; i < user->NumDataInputs(); i++) {
if (user->GetDataInput(i) == from) {
user->SetDataInput(i, this);
Expand Down
19 changes: 14 additions & 5 deletions src/inst.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ class Inst
void AddDataUser(Inst *inst);
void DeleteDataUser(Inst *inst);

bool HasSingleDataUser() {
return NumDataUsers() == 1;
}

Inst *GetSingleDataUser() {
ASSERT(HasSingleDataUser());
return GetRawUsers().back();
}

const std::list<Inst *> GetDataUsers();

virtual void DumpInputs([[maybe_unused]] std::ostream &out) {};
Expand Down Expand Up @@ -205,11 +214,11 @@ class Inst

private:
bool inst_placed_ = false;
id_t id_;
LinearNumber linear_number_;
LifeNumber life_number_;
Opcode opc_;
Type type_;
id_t id_ {};
LinearNumber linear_number_ {};
LifeNumber life_number_ {};
Opcode opc_ {};
Type type_ {};

protected:
Inst *prev_ = nullptr;
Expand Down
44 changes: 44 additions & 0 deletions src/optimizations/peepholes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ void Peepholes::VisitSub(Inst *inst) {
if (ConstFoldingBinaryOp(graph_, inst)) {
return;
}
// Some optimization may be applied, so we don't go out from function
TryOptimizeSubSub(inst);

if (TryOptimizeSubZero(inst)) {
return;
Expand All @@ -60,6 +62,13 @@ void Peepholes::VisitOr(Inst *inst) {
}
}

// 1. Constant 0x0 -> v3
// 2. ... -> v3
// 3. Sub v2, v1 -> v4
// ==========>>==========
// 1. Constant 0x0
// 2. ... -> v4
// 3. Sub v2, v1
bool Peepholes::TryOptimizeSubZero(Inst *inst) {
auto input0 = inst->GetDataInput(0);
auto input1 = inst->GetDataInput(1);
Expand All @@ -71,6 +80,41 @@ bool Peepholes::TryOptimizeSubZero(Inst *inst) {
return false;
}

// Optimize sub of sub
// 1. Constant ... -> v3
// 2. Constant ... -> v3
// 3. ... -> v4
// 4. Sub v3, v1 -> v3
// 5. Sub v4, v2 -> v6
// ==========>>==========
// 1. Constant ... -> v3
// 2. Constant ...
// 6. Constant /v1+v2/ -> v5
// 3. ... -> v4
// 4. Sub v3, v1
// 5. Sub v3, v6 -> v6
bool Peepholes::TryOptimizeSubSub(Inst *inst) {
auto input0 = inst->GetDataInput(0);
auto input1 = inst->GetDataInput(1);

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

auto single_user = inst->GetSingleDataUser();
if (single_user->GetOpcode() != Opcode::Sub || !single_user->GetDataInput(1)->IsConst()) {
return false;
}

auto const_near = input1->CastToConstant()->GetImm();
auto const_far = single_user->GetDataInput(1)->CastToConstant()->GetImm();
// Overflow is ok
auto new_const = graph_->CreateConstantInst(const_near + const_far);
single_user->SetDataInput(1, new_const);
single_user->SetDataInput(0, input0);
return true;
}

bool Peepholes::TryOptimizeShlAfterShr(Inst *inst) {
auto input0 = inst->GetDataInput(0);
auto input1 = inst->GetDataInput(1);
Expand Down
1 change: 1 addition & 0 deletions src/optimizations/peepholes.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Peepholes {

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

Expand Down
38 changes: 38 additions & 0 deletions tests/peepholes_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,44 @@ TEST(PeepholesTest, ShrAfterShr) {
GraphComparator(true_graph, graph).Compare();
}

TEST(PeepholesTest, SubSub) {
// Before
auto ic = IrConstructor();
ic.CreateInst<Opcode::Start>(0);
ic.CreateInst<Opcode::End>(1);
ic.CreateInst<Opcode::Parameter>(2);
ic.CreateInst<Opcode::Constant>(3).Imm(10);
ic.CreateInst<Opcode::Constant>(4).Imm(15);
ic.CreateInst<Opcode::Sub>(5).DataInputs(2, 3);
ic.CreateInst<Opcode::Sub>(6).DataInputs(5, 4);
ic.CreateInst<Opcode::Return>(7).CtrlInput(0).DataInputs(6);
ic.CreateInst<Opcode::Jump>(8).CtrlInput(7).JmpTo(1);

auto graph = ic.GetFinalGraph();
auto ph = Peepholes(graph);
ph.Run();

// After
auto ic_true = IrConstructor();
ic_true.CreateInst<Opcode::Start>(0);
ic_true.CreateInst<Opcode::Parameter>(2);
ic_true.CreateInst<Opcode::Constant>(3).Imm(10);
ic_true.CreateInst<Opcode::Constant>(4).Imm(15);
ic_true.CreateInst<Opcode::Constant>(9).Imm(25);

ic_true.CreateInst<Opcode::Sub>(5).DataInputs(2, 3);
ic_true.CreateInst<Opcode::Sub>(6).DataInputs(2, 9);
ic_true.CreateInst<Opcode::Return>(7).CtrlInput(0).DataInputs(6);
ic_true.CreateInst<Opcode::Jump>(8).CtrlInput(7).JmpTo(1);

ic_true.CreateInst<Opcode::End>(1);

auto true_graph = ic_true.GetFinalGraph();

GraphComparator(true_graph, graph).Compare();
}



TEST(ConstFoldingTest, Sub) {
// Before
Expand Down
Loading