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

"A unique tuple element of return value of function ... is aliased to some other tuple component" ICE #1949

Closed
Programmerino opened this issue May 23, 2023 · 1 comment · Fixed by #1958
Assignees

Comments

@Programmerino
Copy link

This bug occurs on 0.24.3 and 889eeb9 (latest commit):

def fn (arr: *[](i32,i32)) =
    if true then opaque arr else opaque arr

entry test = (fn [(0, 0)])[0]

Error:

[  +0.000027] Reading and type-checking source program
[  +0.201637] Defunctorising
[  +0.000658] Full Normalising
[  +0.005616] Monomorphising
[  +0.051983] Lifting lambdas
[  +0.000278] Defunctionalising
[  +0.000249] Converting to core IR
[  +0.000709] Type-checking internalised program
Internal compiler error.  Please report this:
  https://github.com/diku-dk/futhark/issues
After internalisation:
In function fn_6585
When checking the body aliases: [[arr_6634, arr_6635], [arr_6634, arr_6635]]
A unique tuple element of return value of function fn_6585 is aliased to some other tuple component.
types {
  
}

let {fn_arg_6615 : ({}, [1i64]i32)} =
  [0i32] : []i32
let {fn_arg_6616 : ({}, [1i64]i32)} =
  [0i32] : []i32
let {tmp_6617 : ({}, [1i64]i32),
     tmp_6618 : ({}, [1i64]i32)} =
  -- Consumes fn_arg_6615, fn_arg_6616
  apply fn_6585(1i64, *fn_arg_6615, *fn_arg_6616)
  : {*[1i64]i32, *[1i64]i32}
let {tmp_6619 : ({tmp_6617}, [1i64]i32)} =
  tmp_6617
let {tmp_6620 : ({tmp_6618}, [1i64]i32)} =
  tmp_6618
let {to_i64_6621 : ({}, i64)} =
  sext i32 0i32 to i64
let {x_6622 : ({}, bool)} =
  sle64(0i64, to_i64_6621)
let {y_6623 : ({}, bool)} =
  slt64(to_i64_6621, 1i64)
let {bounds_check_6624 : ({}, bool)} =
  logand(x_6622, y_6623)
let {index_certs_6625 : ({}, unit)} =
  assert(bounds_check_6624, {"Index [", to_i64_6621 : i64, "] out of bounds for array of shape [", 1i64 : i64, "]."}, "bad_2.fut:4:14-29")
let {test_res_6626 : ({}, i32)} =
  #{index_certs_6625}
  tmp_6619[to_i64_6621]
let {test_res_6627 : ({}, i32)} =
  #{index_certs_6625}
  tmp_6620[to_i64_6621]

fun
  opaque_6584 (d_6628 : i64,
               x_6629 : [d_6628]i32,
               x_6630 : [d_6628]i32)
  : {[d_6628]i32,
     [d_6628]i32} = {
  let {opaque_res_6631 : ({x_6629}, [d_6628]i32)} =
    opaque(x_6629)
  let {opaque_res_6632 : ({x_6630}, [d_6628]i32)} =
    opaque(x_6630)
  in {opaque_res_6631, opaque_res_6632}
}

fun
  fn_6585 (d₀_6633 : i64,
           arr_6634 : *[d₀_6633]i32,
           arr_6635 : *[d₀_6633]i32)
  : {*[d₀_6633]i32,
     *[d₀_6633]i32} = {
  let {fn_res_6636 : ({arr_6634, arr_6635, fn_res_6637}, [d₀_6633]i32),
       fn_res_6637 : ({arr_6634, arr_6635, fn_res_6636}, [d₀_6633]i32)} =
    if true
    then {
      let {fn_res_t_res_6638 : ({arr_6634, arr_6635}, [d₀_6633]i32),
           fn_res_t_res_6639 : ({arr_6634, arr_6635}, [d₀_6633]i32)} =
        apply opaque_6584(d₀_6633, arr_6634, arr_6635)
        : {[d₀_6633]i32, [d₀_6633]i32}
      in {fn_res_t_res_6638, fn_res_t_res_6639}
    } else {
      let {fn_res_f_res_6640 : ({arr_6634, arr_6635}, [d₀_6633]i32),
           fn_res_f_res_6641 : ({arr_6634, arr_6635}, [d₀_6633]i32)} =
        apply opaque_6584(d₀_6633, arr_6634, arr_6635)
        : {[d₀_6633]i32, [d₀_6633]i32}
      in {fn_res_f_res_6640, fn_res_f_res_6641}
    }
    : {[d₀_6633]i32,
       [d₀_6633]i32}
  in {fn_res_6636, fn_res_6637}
}

entry("test",
      {},
      {i32,
       i32})
  entry_test ()
  : {i32,
     i32} = {
  {test_res_6626, test_res_6627}
}
@athas athas self-assigned this May 23, 2023
@athas
Copy link
Member

athas commented May 24, 2023

This is the other end of #803. We can either relax internal type checking a bit more or actually solve it properly this time.

athas added a commit that referenced this issue Jun 9, 2023
This is a proper fix of #803 (see also discussion in #1949). The main
issue we address is that in the core language representation of a
function originally returning [](t,t), the two constituent arrays
cannot possibly alias.

This fix complicates the core language, but in a principled way. Each
return type of a function is now accompanied by two lists:

    * Which function parameters the result may alias.
    * Which other results the result may alias.

For simplicity these are integer lists, interpreted as indexes. This
is quite trivial to check in the core typechecker and to propagate in
alias analysis. The main challenge is to infer the lists based on the
source language types, as the source language is not so precise about
aliasing. I don't feel that my current solution is fully principled,
and I'm worried that I might have gotten it wrong (which will manifest
as compiler crashes - not as quietly invalid code generation).

There is also a remaining outstanding question in that we have no
conscious policy on whether a core language function is allowed to
return something that aliases a global variable. We do not permit this
in the source language. We currently do allow this in the core, but I
think the only case where it will currently happen is for entry points
that are non-functions in the source program.

Fixes #1949.
razetime pushed a commit to razetime/futhark that referenced this issue Jul 16, 2023
This is a proper fix of diku-dk#803 (see also discussion in diku-dk#1949). The main
issue we address is that in the core language representation of a
function originally returning [](t,t), the two constituent arrays
cannot possibly alias.

This fix complicates the core language, but in a principled way. Each
return type of a function is now accompanied by two lists:

    * Which function parameters the result may alias.
    * Which other results the result may alias.

For simplicity these are integer lists, interpreted as indexes. This
is quite trivial to check in the core typechecker and to propagate in
alias analysis. The main challenge is to infer the lists based on the
source language types, as the source language is not so precise about
aliasing. I don't feel that my current solution is fully principled,
and I'm worried that I might have gotten it wrong (which will manifest
as compiler crashes - not as quietly invalid code generation).

There is also a remaining outstanding question in that we have no
conscious policy on whether a core language function is allowed to
return something that aliases a global variable. We do not permit this
in the source language. We currently do allow this in the core, but I
think the only case where it will currently happen is for entry points
that are non-functions in the source program.

Fixes diku-dk#1949.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants