bool equal_lookahead_tags(ctx_t &ctx, const kernel_t *x, const kernel_t *y)
{
    DASSERT(x->size == y->size);

    if (memcmp(x->thist, y->thist, x->size * sizeof(hidx_t)) == 0) {
        return true;
    }

    typename ctx_t::history_t &thist = ctx.history;
    tag_path_t &p1 = ctx.dc_path1, &p2 = ctx.dc_path2, &p3 = ctx.dc_path3;
    std::vector<uint32_t> &count = ctx.dc_tagcount;

    for (size_t i = 0; i < x->size; ++i) {
        const hidx_t xl = x->thist[i], yl = y->thist[i];

        if (xl == yl) continue;

        unwind<ctx_t>(thist, p1, xl);
        unwind<ctx_t>(thist, p2, yl);

        if (p1.size() != p2.size()) return false;

        group_by_tag(p1, p3, count);
        group_by_tag(p2, p3, count);

        if (p1 != p2) return false;
    }

    return true;
}
bool equal_lookahead_tags(ctx_t &ctx, const kernel_t *x, const kernel_t *y)
{
    DASSERT(x->size == y->size);

    if (memcmp(x->thist, y->thist, x->size * sizeof(hidx_t)) == 0) {
        return true;
    }

    typename ctx_t::history_t &thist = ctx.history;
    tag_path_t &p1 = ctx.dc_path1, &p2 = ctx.dc_path2, &p3 = ctx.dc_path3;
    std::vector<uint32_t> &count = ctx.dc_tagcount;

    for (size_t i = 0; i < x->size; ++i) {
        const hidx_t xl = x->thist[i], yl = y->thist[i];

        if (xl == yl) continue;

        unwind<ctx_t>(thist, p1, xl);
        unwind<ctx_t>(thist, p2, yl);

        if (p1.size() != p2.size()) return false;

        group_by_tag(p1, p3, count);
        group_by_tag(p2, p3, count);

        if (p1 != p2) return false;
    }

    return true;
}