Skip to content

Commit

Permalink
Merge pull request #110 from AnyDSL/arr_opt
Browse files Browse the repository at this point in the history
Arr opt
  • Loading branch information
leissa authored Dec 5, 2022
2 parents 8d9c0c5 + bf924e1 commit a1a1cbe
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 8 deletions.
15 changes: 15 additions & 0 deletions lit/arr_pack_performance.thorin.disabled
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// RUN: %thorin %s -o -

// If compiling this takes forever, there is some loophole that Thorin does sth 100000000 times.
.import mem;

.let I32 = .Idx 4294967296;
.let size = 100000000;

.cn .extern main [mem: %mem.M, argc: I32, argv : %mem.Ptr («⊤:.Nat; %mem.Ptr («⊤:.Nat; .Idx 256», 0:.Nat)», 0:.Nat), return : .Cn [%mem.M, I32]] = {
.let (alloc_mem, arr) = %mem.alloc (<<size; I32>>, 0) (mem);
.let lea = %mem.lea (size, <size; I32>, 0) (arr, 0:(.Idx 100));
.let (load_mem, val) = %mem.load (I32, 0) (alloc_mem, lea);

return ( load_mem, 1:I32 )
};
5 changes: 3 additions & 2 deletions thorin/analyses/scope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ const F_CFG& Scope::f_cfg() const { return cfa().f_cfg(); }
const B_CFG& Scope::b_cfg() const { return cfa().b_cfg(); }

bool is_free(Def* nom, const Def* def) {
// optimize common cases
if (auto var = nom->var()) {
// optimize common cases first
if (def->num_ops() == 0) return false;
if (var == def) return true;
for (auto v : var->nom()->vars())
if (var == v) return true;
Expand All @@ -101,7 +102,7 @@ bool is_free(Def* nom, const Def* def) {
return scope.bound(def);
}

return true;
return false;
}

} // namespace thorin
5 changes: 3 additions & 2 deletions thorin/check.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,22 @@ namespace thorin {

const Def* infer_type_level(World&, Defs);

/// Keeps track of α-equivalence.
class Checker {
public:
Checker(World& world)
: world_(&world) {}

World& world() const { return *world_; }

/// Are @p d1 and @p d2 alpha-equivalent?
/// Are @p d1 and @p d2 α-equivalent?
bool equiv(const Def* d1, const Def* d2, const Def* dbg);

/// Can @p value be assigned to sth of @p type?
/// @note This is different from `equiv(type, value->type(), dbg)` since @p type may be dependent.
bool assignable(const Def* type, const Def* value, const Def* dbg);

/// Yields `defs.front()`, if all @p defs are alpha-equiv%alent and `nullptr` otherwise.
/// Yields `defs.front()`, if all @p defs are α-equiv%alent and `nullptr` otherwise.
const Def* is_uniform(Defs defs, const Def* dbg);

static void swap(Checker& c1, Checker& c2) { std::swap(c1.world_, c2.world_); }
Expand Down
10 changes: 8 additions & 2 deletions thorin/def.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,19 @@ const Sigma* Sigma::restructure() {

const Def* Arr::restructure() {
auto& w = world();
if (auto n = isa_lit(shape())) return w.sigma(DefArray(*n, [&](size_t i) { return reduce(w.lit_idx(*n, i)); }));
if (auto n = isa_lit(shape())) {
if (is_free(this, body())) return w.sigma(DefArray(*n, [&](size_t i) { return reduce(w.lit_idx(*n, i)); }));
return w.arr(shape(), body());
}
return nullptr;
}

const Def* Pack::restructure() {
auto& w = world();
if (auto n = isa_lit(shape())) return w.tuple(DefArray(*n, [&](size_t i) { return reduce(w.lit_idx(*n, i)); }));
if (auto n = isa_lit(shape())) {
if (is_free(this, body())) return w.tuple(DefArray(*n, [&](size_t i) { return reduce(w.lit_idx(*n, i)); }));
return w.pack(shape(), body());
}
return nullptr;
}

Expand Down
13 changes: 11 additions & 2 deletions thorin/world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ const Type* World::type(const Def* level, const Def* dbg) {
const Def* World::app(const Def* callee, const Def* arg, const Def* dbg) {
auto pi = callee->type()->isa<Pi>();

// (a, b)#i arg where a = A -> B; b = A -> B
if (auto extract = callee->type()->isa<Extract>()) {
if (auto tuple = extract->tuple()->isa<Tuple>()) {
if (auto uni = checker().is_uniform(tuple->ops(), dbg)) pi = uni->isa<Pi>();
}
}

if (err()) {
if (!pi)
err()->err(dbg->loc(), "called expression '{}' : '{}' is not of function type", callee, callee->type());
Expand Down Expand Up @@ -108,7 +115,8 @@ const Def* World::sigma(Defs ops, const Def* dbg) {
auto n = ops.size();
if (n == 0) return sigma();
if (n == 1) return ops[0];
if (auto uni = checker().is_uniform(ops, dbg)) return arr(n, uni, dbg);
auto front = ops.front();
if (std::ranges::all_of(ops.skip_front(), [front](auto op) { return front == op; })) return arr(n, front, dbg);
return unify<Sigma>(ops.size(), infer_type_level(*this, ops), ops, dbg);
}

Expand Down Expand Up @@ -138,7 +146,8 @@ const Def* World::tuple(const Def* type, Defs ops, const Def* dbg) {
if (!type->isa_nom<Sigma>()) {
if (n == 0) return tuple();
if (n == 1) return ops[0];
if (auto uni = checker().is_uniform(ops, dbg)) return pack(n, uni, dbg);
auto front = ops.front();
if (std::ranges::all_of(ops.skip_front(), [front](auto op) { return front == op; })) return pack(n, front, dbg);
}

if (n != 0) {
Expand Down

0 comments on commit a1a1cbe

Please sign in to comment.