Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
pubby committed Aug 6, 2022
1 parent 1de83d8 commit d54f0dd
Show file tree
Hide file tree
Showing 12 changed files with 263 additions and 51 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ GIT_COMMIT := "$(shell git describe --abbrev=8 --dirty --always --tags)"

override CXXFLAGS+= \
-std=c++20 \
-O0 \
-O3 \
-pthread \
-g \
-Wall \
Expand All @@ -45,7 +45,7 @@ override CXXFLAGS+= \
$(INCS) \
-DVERSION=\"$(VERSION)\" \
-DGIT_COMMIT=\"$(GIT_COMMIT)\" \
#-DNDEBUG
-DNDEBUG

VPATH=$(SRCDIR)

Expand Down
2 changes: 1 addition & 1 deletion src/asm_proc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ void asm_proc_t::write_assembly(std::ostream& os) const
break;
}

os << '\n';
os << inst.arg << '\n';
}
}

Expand Down
114 changes: 98 additions & 16 deletions src/cg_isel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <functional>
#include <type_traits>
#include <vector>
#include <unordered_map> // TODO
#include "robin_hood.h" // TODO

#include "robin/hash.hpp"
#include "robin/map.hpp"
Expand All @@ -26,8 +28,15 @@ namespace isel
//rh::batman_map<cpu_t, sel_t const*> map;
//rh::batman_map<cpu_t, sel_t const*> next_map;

rh::batman_map<cpu_t, sel_t const*> map;
rh::batman_map<cpu_t, sel_t const*> next_map;
template<typename... T>
using map_t = rh::batman_map<cpu_t, sel_t const*, T...>;
//using map_t = robin_hood::unordered_map<cpu_t, sel_t const*>;
//using map_t = std::unordered_map<cpu_t, sel_t const*, T...>;
//using map_t = std::unordered_map<cpu_t, sel_t const*>;

map_t<> map;
map_t<> next_map;
map_t<isel::approximate_hash_t, isel::approximate_eq_t> approx_map;

array_pool_t<sel_t> sel_pool;

Expand Down Expand Up @@ -165,7 +174,8 @@ namespace isel

unsigned get_cost(sel_t const* sel)
{
return sel ? sel->cost : 0;
assert(sel);
return sel->cost;
}

template<op_t Op>
Expand All @@ -189,9 +199,6 @@ namespace isel
template<op_t Op>
constexpr unsigned cost_fn = (op_cycles(Op) * 256) + op_size(Op) + op_penalty<Op>();

// THIS DETERMINES HOW BIG THE MAP GETS, AND HOW WIDE THE SEARCH IS:
constexpr unsigned COST_CUTOFF = cost_fn<LDA_ABSOLUTE> * 3;

template<op_t Op>
sel_t& alloc_sel(options_t opt, sel_t const* prev, locator_t arg = {}, locator_t ptr_hi = {}, unsigned extra_cost = 0)
{
Expand Down Expand Up @@ -277,11 +284,11 @@ namespace isel
template<bool FinishNode>
void finish(cpu_t const& cpu, sel_t const* sel, cons_t const*)
{
rh::apair<cpu_t, sel_t const*> insertion = { cpu, sel };
state_t::map_t<>::value_type insertion = { cpu, sel };

// If this completes a node's operations, we'll release 'req_store'.
if(FinishNode)
insertion.first.req_store &= ~cg_data(state.ssa_node).isel.last_use;
if(FinishNode) // TODO: remove cast
(std::uint64_t&)insertion.first.req_store &= ~cg_data(state.ssa_node).isel.last_use;

auto result = state.next_map.insert(std::move(insertion));

Expand All @@ -305,6 +312,10 @@ namespace isel
}
#endif

// These determine how extensive the search is.
constexpr unsigned COST_CUTOFF = cost_fn<LDA_ABSOLUTE> * 3;
constexpr unsigned MAX_MAP_SIZE = 512;

// Runs the function and adds the results to the state map.
template<bool FinishNode, typename Fn>
void select_step(Fn fn)
Expand All @@ -314,13 +325,35 @@ namespace isel

cons_t const cont = { finish<FinishNode> };

//std::cout << "BEST COST = " << state.best_cost << std::endl;

for(auto const& pair : state.map)
if(get_cost(pair.second) < state.best_cost + COST_CUTOFF)
fn(pair.first, pair.second, &cont);

if(state.next_map.empty())
throw isel_no_progress_error_t{};

if(state.next_map.size() > MAX_MAP_SIZE)
{
//std::cout << "OLD SIZE = " << state.next_map.size() << std::endl;

state.approx_map.clear();
for(auto const& pair : state.next_map)
{
auto result = state.approx_map.insert(pair);

if(!result.second && get_cost(pair.second) < get_cost(result.first->second))
result.first->second = pair.second;
}

state.next_map.clear();
for(auto const& pair : state.approx_map)
state.next_map.insert(pair);

//std::cout << "NEW SIZE = " << state.next_map.size() << std::endl;
}

state.map.swap(state.next_map);
state.best_cost = state.next_best_cost;
}
Expand Down Expand Up @@ -448,8 +481,8 @@ namespace isel
return bool(arg);
default:
return true;
#endif
}
#endif
}

// Spits out the op specified.
Expand All @@ -458,7 +491,7 @@ namespace isel
// Thus, prefer pick_op.
template<op_t Op> [[gnu::noinline]]
void exact_op(options_t opt, locator_t def, locator_t arg, locator_t ptr_hi, ssa_value_t ssa_def, ssa_value_t ssa_arg,
cpu_t const& cpu, sel_t const* prev, cons_t const* cont)
cpu_t const& cpu, sel_t const* prev, cons_t const* cont, unsigned extra_penalty = 0)
{
constexpr auto mode = op_addr_mode(Op);

Expand All @@ -477,7 +510,7 @@ namespace isel
penalty = handle_req_store_penalty<Op>(cpu_copy, ssa_def, ssa_arg);
}

cont->call(cpu_copy, &alloc_sel<Op>(opt, prev, arg, ptr_hi, penalty));
cont->call(cpu_copy, &alloc_sel<Op>(opt, prev, arg, ptr_hi, penalty + extra_penalty));
}
}

Expand All @@ -492,9 +525,11 @@ namespace isel
template<op_t Op>
void simple_op(options_t opt, locator_t def, locator_t arg, cpu_t const& cpu, sel_t const* prev, cons_t const* cont)
{
#ifndef NDEBUG
constexpr auto mode = op_addr_mode(Op);
assert(mode == MODE_IMPLIED || mode == MODE_RELATIVE || mode == MODE_IMMEDIATE);
assert(valid_arg<Op>(arg));
#endif
cpu_t cpu_copy = cpu;
if(cpu_copy.set_defs_for<Op>(opt, def, arg))
cont->call(cpu_copy, &alloc_sel<Op>(opt, prev, arg, {}, 0));
Expand Down Expand Up @@ -847,6 +882,37 @@ namespace isel
{
using OptN = typename Opt::inc_no_direct;

locator_t const index = array_index<Arg>::value();

if(index.is_const_num())
{
if(AbsoluteX != BAD_OP && cpu.is_known(REG_X))
{
locator_t mem = array_mem<Arg>::trans();
int const offset = int(index.data()) - int(cpu.known[REG_X]);
mem.advance_offset(offset);

exact_op<AbsoluteX>(
OptN::to_struct, Def::value(), mem, locator_t{},
Def::node(), array_mem<Arg>::node(), cpu, prev, cont,
std::abs(offset));

return;
}

if(AbsoluteY != BAD_OP && cpu.is_known(REG_Y))
{
locator_t mem = array_mem<Arg>::trans();
mem.advance_offset(int(index.data()) - int(cpu.known[REG_Y]));

exact_op<AbsoluteY>(
OptN::to_struct, Def::value(), mem, locator_t{},
Def::node(), array_mem<Arg>::node(), cpu, prev, cont);

return;
}
}

if(AbsoluteX != BAD_OP)
{
chain
Expand Down Expand Up @@ -1228,7 +1294,7 @@ namespace isel
type_name_t const lt = type_name_t(h->input(0 ^ Flip).whole());
type_name_t const rt = type_name_t(h->input(1 ^ Flip).whole());

std::cout << "LT " << type_t(lt) << ' ' << type_t(rt) << std::endl;
//std::cout << "LT " << type_t(lt) << ' ' << type_t(rt) << std::endl;

int const lwhole = whole_bytes(lt);
int const rwhole = whole_bytes(rt);
Expand Down Expand Up @@ -2576,16 +2642,32 @@ std::vector<asm_inst_t> select_instructions(fn_t const& fn, cfg_ht cfg_node)
state.best_cost = ~0 - COST_CUTOFF;
state.best_sel = nullptr;

// Starting state:
state.map.insert({ cpu_t{}, nullptr });
//state.map.reserve(1000000);
//state.next_map.reserve(1000000);

state.map.insert({ cpu_t{}, &state.sel_pool.emplace(nullptr, 0, asm_inst_t{ ASM_PRUNED }) });


for(ssa_ht h : cd.schedule)
{
try
{
state.ssa_node = h;
isel_node(h);
std::cout << "MAP SIZE = " << state.map.size() << std::endl;
//std::cout << "MAP SIZE = " << state.map.size() << std::endl;

/*
if(state.map.size() > 10000)
{
for(auto const& pair : state.map)
{
std::cout << "\n\n\n";
for(sel_t const* sel = pair.second; sel; sel = sel->prev)
std::cout << sel->inst << std::endl;
}
throw 0;
}
*/

#ifndef NDEBUG
// TODO: reenable
Expand Down
60 changes: 51 additions & 9 deletions src/cg_isel_cpu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,40 @@ struct cpu_t
bool operator==(cpu_t const& o) const
{
assert(known_array_valid() && o.known_array_valid());
return (req_store == o.req_store && defs == o.defs && known_mask == o.known_mask);
return accurate_eq(o);
//return (req_store == o.req_store && defs == o.defs && known_mask == o.known_mask);
}

bool accurate_eq(cpu_t const& o) const
{
assert(known_array_valid() && o.known_array_valid());
return (req_store == o.req_store && defs == o.defs && known_mask == o.known_mask && known == o.known);
}

bool approximate_eq(cpu_t const& o) const
{
return ((known_mask & REGF_AC) == (o.known_mask & REGF_AC)
&& defs[REG_A] == o.defs[REG_A]);
}

std::size_t accurate_hash() const
{
std::size_t h = req_store;
for(locator_t const& v : defs)
h = rh::hash_combine(h, v.to_uint());
for(unsigned i = 0; i < known.size(); ++i)
h ^= known[i] << i * 8;
for(std::uint8_t k : known)
h = rh::hash_combine(h, k);
h = rh::hash_combine(h, known_mask);
return h;
}

std::size_t approximate_hash() const
{
std::size_t h = known_mask & REGF_AC;
h = rh::hash_combine(h, defs[REG_A].to_uint());
return h;
}

// If we know the value of a register:
Expand Down Expand Up @@ -233,6 +266,22 @@ struct cpu_t
bool set_defs_for(options_t opt, locator_t def, locator_t arg);
};

struct approximate_hash_t
{
std::size_t operator()(isel::cpu_t const& cpu) const noexcept
{
return cpu.approximate_hash();
}
};

struct approximate_eq_t
{
std::size_t operator()(isel::cpu_t const& l, isel::cpu_t const& r) const noexcept
{
return l.approximate_eq(r);
}
};

} // end namespace isel


Expand All @@ -241,15 +290,8 @@ struct std::hash<isel::cpu_t>
{
std::size_t operator()(isel::cpu_t const& cpu) const noexcept
{
std::size_t h = rh::hash_finalize(cpu.req_store);
for(locator_t const& v : cpu.defs)
h ^= v.to_uint();
for(std::uint8_t k : cpu.known)
h ^= k;
h = rh::hash_combine(h, cpu.known_mask);
return h;
return cpu.accurate_hash();
}
};


#endif
5 changes: 3 additions & 2 deletions src/handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ struct pool_handle_t : public handle_t<Derived, std::uint32_t, ~0u>

value_type& safe() const
{
if(compiler_phase() > Phase)
return unsafe_impl();
// TODO
//if(compiler_phase() > Phase)
//return unsafe_impl();
std::lock_guard<std::mutex> lock(m_pool_mutex);
return unsafe_impl();
}
Expand Down
1 change: 0 additions & 1 deletion src/ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -889,7 +889,6 @@ void ir_t::assert_valid() const
{
if((ssa_flags(ssa_node.op()) & SSAF_NULL_INPUT_VALID) && !ssa_node.input(i))
continue;
std::cout << ssa_it << std::endl;
assert(ssa_node.input(i));
if(!ssa_node.input(i).holds_ref())
continue;
Expand Down
12 changes: 9 additions & 3 deletions src/locator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ friend class gmember_locator_manager_t;
}

constexpr void advance_offset(std::uint16_t amount) { set_offset(offset() + amount); }
constexpr locator_t with_advance_offset(std::uint16_t amount) const
{
locator_t loc = *this;
loc.advance_offset(amount);
return loc;
}

gmember_ht gmember() const
{
Expand Down Expand Up @@ -468,9 +474,9 @@ struct std::hash<loc_vec_t>
for(unsigned i = 0; i < n; ++i)
h = rh::hash_combine(h, lh(vec[i]));

// Also hash the last locator:
if(!vec.empty())
h = rh::hash_combine(h, lh(vec.back()));
// Also hash the last 4 locators:
for(unsigned i = 0; i < n; ++i)
h = rh::hash_combine(h, lh(vec.rbegin()[i]));

return h;
}
Expand Down
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ int main(int argc, char** argv)
// Compile each global:
set_compiler_phase(PHASE_COMPILE);
global_t::compile_all();
output_time("compile: ");

set_compiler_phase(PHASE_ALLOC_RAM);
alloc_ram(~static_used_ram, &std::cout);
Expand Down
Loading

0 comments on commit d54f0dd

Please sign in to comment.