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

Hoist storage undefined symbol #8141

Closed
abadams opened this issue Mar 6, 2024 · 1 comment
Closed

Hoist storage undefined symbol #8141

abadams opened this issue Mar 6, 2024 · 1 comment
Assignees
Labels

Comments

@abadams
Copy link
Member

abadams commented Mar 6, 2024

This code:

#include "Halide.h"
using namespace Halide;

int main() {
    ImageParam input(UInt(8), 2);
    Var x{"x"}, y{"y"}, yo{"yo"}, yi{"yi"};
    Func f[3];
    f[0] = BoundaryConditions::repeat_edge(input);
    f[1](x, y) = ((f[0]((x / 2) + 2, (y / 2) + 2) + f[0](x / 2, (y / 2) + -2)) + (f[0](x + 1, y) + f[0](x + -1, y + -1)));
    f[2](x, y) = ((f[1](x * 2, (y * 2) + -2) + f[1]((x * 2) + 1, (y * 2) + 2)) + (f[1](x + -1, y + -1) + f[1](x + -2, y + -1)));
    f[2].split(y, yo, yi, 16);
    f[0].hoist_storage(f[2], yo).compute_at(f[1], x);
    f[1].hoist_storage_root().compute_at(f[2], yi);

    f[2].compile_jit();

    printf("Success!\n");

    return 0;
}

produces this compile-time error during codegen

Symbol not found: f3.s0.y.yi

The IR after storage flattening has the following size for the allocation of f[0]:

allocate repeat_edge[uint8 * ((max(((max((f3.extent.0 + f3.min.0)*2, (f3.extent.0 + f3.min.0) + -1) + -1)/2) + 1, max((f3.extent.0 + f3.min.0)*2, (f3.extent.0 + f3.min.0) + -1) + -1) - min(min(f3.min.0*2, f3.min.0 + -2)/2, min(f3.min.0*2, f3.min.0 + -2) + -1)) + 2) * ((max(((((let t43 = min(f3.s0.y.yo*16, f3.extent.1 + -16) in (max((((f3.min.1 + t43) + f3.s0.y.yi)*2) + 3, (f3.min.1 + t43) + f3.s0.y.yi) - min(((f3.min.1 + t43) + f3.s0.y.yi)*2, ((f3.min.1 + t43) + f3.s0.y.yi) + 1))) + min((f3.s0.y.yi + f3.s0.y.yi.base)*2, (f3.s0.y.yi + f3.s0.y.yi.base) + 1)) + -1)/2) + 2, ((let t43 = min(f3.s0.y.yo*16, f3.extent.1 + -16) in (max((((f3.min.1 + t43) + f3.s0.y.yi)*2) + 3, (f3.min.1 + t43) + f3.s0.y.yi) - min(((f3.min.1 + t43) + f3.s0.y.yi)*2, ((f3.min.1 + t43) + f3.s0.y.yi) + 1))) + min((f3.s0.y.yi + f3.s0.y.yi.base)*2, (f3.s0.y.yi + f3.s0.y.yi.base) + 1)) + -1) - min((min((f3.s0.y.yi + f3.s0.y.yi.base)*2, (f3.s0.y.yi + f3.s0.y.yi.base) + 1) + -2)/2, (min((f3.s0.y.yi + f3.s0.y.yi.base)*2, (f3.s0.y.yi + f3.s0.y.yi.base) + 1) + -2) + 1)) + 3)]

It includes references to f3.so.y.yi, but it's outside of that loop. Note that f[1] calls f[0] in a weird way - it adds f[0] to an upsampled version of f[0]. This means the region required by one value of f[1] depends on an amount of f[0] that is a function of x and y.

The storage hoisting code looks like it explicitly tries to account for this, so I'm not sure what's going on.

@abadams abadams added the bug label Mar 6, 2024
abadams added a commit that referenced this issue Mar 7, 2024
Works around issue #8140

It would test hoist storage too, but that's disabled due to issue #8141
@vksnk vksnk self-assigned this Mar 7, 2024
@vksnk
Copy link
Member

vksnk commented Mar 13, 2024

The problem is that bound_of_expr_in_scope is not recursive: when the storage is hoisted, the allocation extents may depend on the loop variables, so we find a maximum bound for them using bound_of_expr_in_scope and the scope which has intervals for each of the loop variables. However, the loop variables themselves may depend on the other loop variables in which case the extent still may refer to loop variables even after calling bound_of_expr_in_scope.

Working on a fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants