Skip to content

Instantly share code, notes, and snippets.

@mmaxs
Last active Jun 11, 2020
Embed
What would you like to do?
the Visitor pattern
// g++ -std=c++1z -Wall -Wpedantic -pedantic-errors -O2 -D__USE_MINGW_ANSI_STDIO vis-ha.cpp -o vis-ha
#include <cstdio>
#include <typeinfo>
#include <vector>
#include <utility>
class Pass;
// the base class for units
class Unit
{
public:
virtual ~Unit() = default;
virtual void accept(const Pass&) = 0;
};
class ModuleUnit;
class FunctionUnit;
class LoopUnit;
// the base class for passes
class Pass
{
public:
virtual ~Pass() = default;
void visit(Unit &u) const { u.accept(*this); };
// by default a pass does nothing with a unit
virtual void visit(ModuleUnit&) const {};
virtual void visit(FunctionUnit&) const {};
virtual void visit(LoopUnit&) const {};
};
// concrete unit classes:
class ModuleUnit : public Unit
{
void accept(const Pass &p) override { p.visit(*this); }
};
class FunctionUnit : public Unit
{
void accept(const Pass &p) override { p.visit(*this); }
};
class LoopUnit : public Unit
{
void accept(const Pass &p) override { p.visit(*this); }
};
// concrete pass classes:
// (a concrete pass overrides only those functions that relevant to its possible targets)
#define DUMMY_PROCESSING(_u_) printf("\t%s, %p\n", __PRETTY_FUNCTION__, (void*)&_u_)
class ConstPropagationPass : public Pass
{
void visit(ModuleUnit &u) const override { DUMMY_PROCESSING(u); };
void visit(FunctionUnit &u) const override { DUMMY_PROCESSING(u); };
};
class FunctionInliningPass : public Pass
{
void visit(ModuleUnit &u) const override { DUMMY_PROCESSING(u); };
void visit(FunctionUnit &u) const override { DUMMY_PROCESSING(u); };
};
class LoopFusionPass : public Pass
{
void visit(LoopUnit &u) const override { DUMMY_PROCESSING(u); };
};
class LoopUnrollingPass : public Pass
{
void visit(LoopUnit &u) const override { DUMMY_PROCESSING(u); };
};
class SanityCheckPass : public Pass
{
void visit(ModuleUnit &u) const override { DUMMY_PROCESSING(u); };
void visit(FunctionUnit &u) const override { DUMMY_PROCESSING(u); };
void visit(LoopUnit &u) const override { DUMMY_PROCESSING(u); };
};
int main()
{
// example: Cartesian product of two independently arranged vectors
std::vector< Unit* > unit_sequence = {
new ModuleUnit(),
new FunctionUnit(),
new LoopUnit(),
new LoopUnit(),
new FunctionUnit(),
new ModuleUnit()
};
std::vector< Pass* > pass_stages = {
new SanityCheckPass(),
new ConstPropagationPass(),
new FunctionInliningPass(),
new LoopFusionPass(),
new LoopUnrollingPass(),
new SanityCheckPass()
};
for (Unit *u : unit_sequence)
{
printf("\n%s: %p\n", typeid(*u).name(), (void*)u);
for (Pass *p : pass_stages)
{
printf("| %s\n", typeid(*p).name());
p->visit(*u);
};
};
// example: more precisely arranged pipeline
using stage_t = std::pair< Unit*, Pass* >;
std::vector< stage_t > stages = {
stage_t{ new ModuleUnit(), new SanityCheckPass() },
stage_t{ new ModuleUnit(), new ConstPropagationPass() },
stage_t{ new FunctionUnit(), new FunctionInliningPass() },
stage_t{ new FunctionUnit(), new SanityCheckPass() },
stage_t{ new LoopUnit(), new LoopFusionPass() },
stage_t{ new LoopUnit(), new LoopUnrollingPass() },
stage_t{ new ModuleUnit(), new SanityCheckPass() },
};
printf("\nStage pipeline:\n");
for (auto [u, p] : stages)
p->visit(*u);
return 0;
}
@mmaxs

This comment has been minimized.

Copy link
Owner Author

@mmaxs mmaxs commented Jun 11, 2020

Output:

10ModuleUnit: 0000000000786bb0
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(ModuleUnit&) const, 0000000000786bb0
| 20ConstPropagationPass
        virtual void ConstPropagationPass::visit(ModuleUnit&) const, 0000000000786bb0
| 20FunctionInliningPass
        virtual void FunctionInliningPass::visit(ModuleUnit&) const, 0000000000786bb0
| 14LoopFusionPass
| 17LoopUnrollingPass
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(ModuleUnit&) const, 0000000000786bb0

12FunctionUnit: 0000000000786bd0
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(FunctionUnit&) const, 0000000000786bd0
| 20ConstPropagationPass
        virtual void ConstPropagationPass::visit(FunctionUnit&) const, 0000000000786bd0
| 20FunctionInliningPass
        virtual void FunctionInliningPass::visit(FunctionUnit&) const, 0000000000786bd0
| 14LoopFusionPass
| 17LoopUnrollingPass
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(FunctionUnit&) const, 0000000000786bd0

8LoopUnit: 0000000000786bf0
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(LoopUnit&) const, 0000000000786bf0
| 20ConstPropagationPass
| 20FunctionInliningPass
| 14LoopFusionPass
        virtual void LoopFusionPass::visit(LoopUnit&) const, 0000000000786bf0
| 17LoopUnrollingPass
        virtual void LoopUnrollingPass::visit(LoopUnit&) const, 0000000000786bf0
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(LoopUnit&) const, 0000000000786bf0

8LoopUnit: 0000000000786c10
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(LoopUnit&) const, 0000000000786c10
| 20ConstPropagationPass
| 20FunctionInliningPass
| 14LoopFusionPass
        virtual void LoopFusionPass::visit(LoopUnit&) const, 0000000000786c10
| 17LoopUnrollingPass
        virtual void LoopUnrollingPass::visit(LoopUnit&) const, 0000000000786c10
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(LoopUnit&) const, 0000000000786c10

12FunctionUnit: 0000000000786c30
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(FunctionUnit&) const, 0000000000786c30
| 20ConstPropagationPass
        virtual void ConstPropagationPass::visit(FunctionUnit&) const, 0000000000786c30
| 20FunctionInliningPass
        virtual void FunctionInliningPass::visit(FunctionUnit&) const, 0000000000786c30
| 14LoopFusionPass
| 17LoopUnrollingPass
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(FunctionUnit&) const, 0000000000786c30

10ModuleUnit: 0000000000786c50
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(ModuleUnit&) const, 0000000000786c50
| 20ConstPropagationPass
        virtual void ConstPropagationPass::visit(ModuleUnit&) const, 0000000000786c50
| 20FunctionInliningPass
        virtual void FunctionInliningPass::visit(ModuleUnit&) const, 0000000000786c50
| 14LoopFusionPass
| 17LoopUnrollingPass
| 15SanityCheckPass
        virtual void SanityCheckPass::visit(ModuleUnit&) const, 0000000000786c50

Stage pipeline:
        virtual void SanityCheckPass::visit(ModuleUnit&) const, 0000000000786db0
        virtual void ConstPropagationPass::visit(ModuleUnit&) const, 0000000000786df0
        virtual void FunctionInliningPass::visit(FunctionUnit&) const, 0000000000786e30
        virtual void SanityCheckPass::visit(FunctionUnit&) const, 00000000006835c0
        virtual void LoopFusionPass::visit(LoopUnit&) const, 0000000000683540
        virtual void LoopUnrollingPass::visit(LoopUnit&) const, 0000000000683520
        virtual void SanityCheckPass::visit(ModuleUnit&) const, 0000000000683670
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment