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

"referenced after being consumed" ICE #1947

Closed
Programmerino opened this issue May 23, 2023 · 4 comments
Closed

"referenced after being consumed" ICE #1947

Programmerino opened this issue May 23, 2023 · 4 comments

Comments

@Programmerino
Copy link

I tested this bug on 0.24.3 and e82e4c2 (latest commit). I'm sorry it's more complex/weird than usual, everytime I try to simplify it more, the issue goes away:

def consume (a: *[]i64) = a with [0] = 0
entry test (_: i64) =
    let a = [0,1]
    let b = map id a :> [3]i64
    let a_consumed = consume a
    let final = consume (copy (filter (\x -> x > 2) a_consumed))
    in (all (\x -> x == 0) b, final)

Error:

[  +0.000012] Reading and type-checking source program
[  +0.136329] Defunctorising
[  +0.000504] Monomorphising
[  +0.023557] Lifting lambdas
[  +0.000456] Defunctionalising
[  +0.000899] Converting to core IR
[  +0.001540] Type-checking internalised program
[  +0.001640] Running pass simplify
[  +0.001983] Running pass Inline conservatively
[  +0.008389] Running pass simplify
[  +0.000641] Running pass Inline aggressively
[  +0.001410] Running pass simplify
[  +0.001442] Running pass CSE
[  +0.000559] Running pass simplify
[  +0.001681] Running pass Fuse SOACs
[  +0.002391] Running pass CSE
[  +0.000479] Running pass simplify
[  +0.001693] Running pass Remove dead functions
[  +0.000944] Running pass first order transform
[  +0.000499] Running pass simplify
[  +0.001594] Running pass In-place lowering
[  +0.000519] Running pass explicit allocations
[  +0.000202] Running pass CSE
[  +0.000737] Running pass simplify
[  +0.002604] Running pass Entry point memory optimisation
[  +0.000633] Running pass simplify
[  +0.000940] Running pass lift allocations
[  +0.001312] Running pass simplify
Internal compiler error.  Please report this:
  https://github.com/diku-dk/futhark/issues
Type error after pass 'lift allocations':
In function entry_test
When checking function body
Type error:
Variable a_6497 referenced after being consumed.
types {
  
}



entry("test",
      {_: i64},
      {bool,
       *[]i64})
  entry_test (nameless_6421 : i64)
  : {mem,
     i64,
     bool,
     *[?1]i64 @ ?0 ->
     {base: [?1];
      contiguous: true;
      LMADs: [{offset: 0i64;
               strides: [1i64];
               shape: [?1];
               permutation: [0];
               monotonicity: [Inc]}]}} = {
  let {mem_6596 : ({}, mem)} =
    alloc(16i64)
  let {a_6497 : ({}, [2i64]i64 @ mem_6596 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [2i64]; permutation: [0]; monotonicity: [Inc]}]})} =
    [0i64, 1i64] : []i64
  let {consume_res_6551 : ({}, [2i64]i64 @ mem_6596 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [2i64]; permutation: [0]; monotonicity: [Inc]}]})} =
    -- Consumes a_6497
    a_6497 with [0i64] = 0i64
  let {mem_6598 : ({}, mem)} =
    alloc(16i64)
  let {result_6580 : ({}, [2i64]i64 @ mem_6598 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [2i64]; permutation: [0]; monotonicity: [Inc]}]})} =
    scratch(i64, 2i64)
  let {mem_6600 : ({}, mem)} =
    alloc(16i64)
  let {result_6581 : ({}, [2i64]i64 @ mem_6600 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [2i64]; permutation: [0]; monotonicity: [Inc]}]})} =
    scratch(i64, 2i64)
  let {discard_6588 : ({}, i64),
       offsets_6575 : ({}, [2i64]i64 @ mem_6598 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [2i64]; permutation: [0]; monotonicity: [Inc]}]}),
       increments_6576 : ({}, [2i64]i64 @ mem_6600 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [2i64]; permutation: [0]; monotonicity: [Inc]}]})} =
    -- Consumes result_6580, result_6581
    -- Result for scanout_6583 aliases lw_dest_6586
    -- Result for mapout_6584 aliases lw_dest_6587
    loop {scanacc_6582 : i64,
          scanout_6583 : *[2i64]i64 @ mem_6598 ->
                         {base: [2i64];
                          contiguous: true;
                          LMADs: [{offset: 0i64;
                                   strides: [1i64];
                                   shape: [2i64];
                                   permutation: [0];
                                   monotonicity: [Inc]}]},
          mapout_6584 : *[2i64]i64 @ mem_6600 ->
                        {base: [2i64];
                         contiguous: true;
                         LMADs: [{offset: 0i64;
                                  strides: [1i64];
                                  shape: [2i64];
                                  permutation: [0];
                                  monotonicity: [Inc]}]}} = {0i64, result_6580, result_6581}
    for i_6585:i64 < 2i64 do {
      let {x_6563 : ({}, i64)} =
        consume_res_6551[i_6585]
      let {defunc_0_p_res_6564 : ({}, bool)} =
        slt64(2i64, x_6563)
      let {cond_neg_6565 : ({}, bool)} =
        not defunc_0_p_res_6564
      let {defunc_0_lifted_lambda_res_6566 : ({}, i64)} =
        btoi bool cond_neg_6565 to i64
      let {is_i_6567 : ({}, bool)} =
        eq_i64(defunc_0_lifted_lambda_res_6566, 0i64)
      let {cond_neg_6568 : ({}, bool)} =
        not is_i_6567
      let {part_res_6569 : ({}, i64)} =
        btoi bool cond_neg_6568 to i64
      let {part_res_6570 : ({}, i64)} =
        btoi bool is_i_6567 to i64
      let {z_6516 : ({}, i64)} =
        add_nw64(part_res_6570, scanacc_6582)
      let {lw_dest_6586 : ({}, [2i64]i64 @ mem_6598 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [2i64]; permutation: [0]; monotonicity: [Inc]}]})} =
        -- Consumes scanout_6583
        scanout_6583 with [i_6585] = z_6516
      let {lw_dest_6587 : ({}, [2i64]i64 @ mem_6600 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [2i64]; permutation: [0]; monotonicity: [Inc]}]})} =
        -- Consumes mapout_6584
        mapout_6584 with [i_6585] = part_res_6569
      in {z_6516, lw_dest_6586, lw_dest_6587}
    }
  let {last_offset_6518 : ({}, i64)} =
    offsets_6575[1i64]
  let {mem_6622 : ({}, mem)} =
    alloc(16i64)
  let {binop_y_6633 : ({}, i64)} =
    mul_nw64(8i64, last_offset_6518)
  let {bytes_6634 : ({}, i64)} =
    smax64(0i64, binop_y_6633)
  let {mem_6635 : ({}, mem)} =
    alloc(bytes_6634)
  let {defunc_0_reduce_res_6573 : ({}, bool)} =
    loop {redout_6578 : bool} = {true}
    for i_6579:i64 < 3i64 do {
      let {x_6558 : ({}, i64)} =
        a_6497[i_6579]
      let {defunc_0_f_res_6559 : ({}, bool)} =
        eq_i64(x_6558, 0i64)
      let {x_6545 : ({}, bool)} =
        logand(defunc_0_f_res_6559, redout_6578)
      in {x_6545}
    }
  let {partition_dest_6519 : ({}, [2i64]i64 @ mem_6622 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [2i64]; permutation: [0]; monotonicity: [Inc]}]})} =
    scratch(i64, 2i64)
  let {partition_res_6577 : ({}, [2i64]i64 @ mem_6622 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [2i64]; permutation: [0]; monotonicity: [Inc]}]})} =
    -- Consumes partition_dest_6519
    -- Result for write_out_6590 aliases write_out_6594
    loop {write_out_6590 : *[2i64]i64 @ mem_6622 ->
                           {base: [2i64];
                            contiguous: true;
                            LMADs: [{offset: 0i64;
                                     strides: [1i64];
                                     shape: [2i64];
                                     permutation: [0];
                                     monotonicity: [Inc]}]}} = {partition_dest_6519}
    for write_iter_6589:i64 < 2i64 do {
      let {write_iv_6591 : ({}, i64)} =
        increments_6576[write_iter_6589]
      let {write_iv_6592 : ({}, i64)} =
        offsets_6575[write_iter_6589]
      let {write_iv_6593 : ({}, i64)} =
        consume_res_6551[write_iter_6589]
      let {is_this_one_6524 : ({}, bool)} =
        eq_i64(write_iv_6591, 0i64)
      let {this_offset_6525 : ({}, i64)} =
        add_nw64(-1i64, write_iv_6592)
      let {total_res_6526 : ({}, i64)} =
        if is_this_one_6524
        then {this_offset_6525} else {-1i64}
        : {i64}
      let {write_out_6594 : ({}, [2i64]i64 @ mem_6622 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [2i64]; permutation: [0]; monotonicity: [Inc]}]})} =
        -- Consumes write_out_6590
        write_out_6590 with? [total_res_6526] = write_iv_6593
      in {write_out_6594}
    }
  let {empty_slice_6527 : ({}, bool)} =
    eq_i64(last_offset_6518, 0i64)
  let {m_6528 : ({}, i64)} =
    sub64(last_offset_6518, 1i64)
  let {zero_leq_i_p_m_t_s_6529 : ({}, bool)} =
    sle64(0i64, m_6528)
  let {i_p_m_t_s_leq_w_6530 : ({}, bool)} =
    slt64(m_6528, 2i64)
  let {i_lte_j_6531 : ({}, bool)} =
    sle64(0i64, last_offset_6518)
  let {y_6532 : ({}, bool)} =
    logand(zero_leq_i_p_m_t_s_6529, i_p_m_t_s_leq_w_6530)
  let {y_6533 : ({}, bool)} =
    logand(i_lte_j_6531, y_6532)
  let {ok_or_empty_6534 : ({}, bool)} =
    logor(empty_slice_6527, y_6533)
  let {index_certs_6535 : ({}, unit)} =
    assert(ok_or_empty_6534, {"Index [:", last_offset_6518 : i64, "] out of bounds for array of shape [", 2i64 : i64, "]."}, "/prelude/soacs.fut:173:6-16")
  let {defunc_0_filter_res_6536 : ({partition_res_6577}, [last_offset_6518]i64 @ mem_6622 -> {base: [2i64]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [last_offset_6518]; permutation: [0]; monotonicity: [Inc]}]})} =
    #{index_certs_6535}
    partition_res_6577[0i64 :+ last_offset_6518 * 1i64]
  let {smaller_replicate_6537 : ({}, [last_offset_6518]i64 @ mem_6635 -> {base: [last_offset_6518]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [last_offset_6518]; permutation: [0]; monotonicity: [Inc]}]})} =
    copy(defunc_0_filter_res_6536)
  let {y_6554 : ({}, bool)} =
    slt64(0i64, last_offset_6518)
  let {index_certs_6555 : ({}, unit)} =
    assert(y_6554, {"Index [", 0i64 : i64, "] out of bounds for array of shape [", last_offset_6518 : i64, "]."}, "test.fut:1:27-40")
  let {consume_res_6556 : ({}, [last_offset_6518]i64 @ mem_6635 -> {base: [last_offset_6518]; contiguous: true; LMADs: [{offset: 0i64; strides: [1i64]; shape: [last_offset_6518]; permutation: [0]; monotonicity: [Inc]}]})} =
    -- Consumes smaller_replicate_6537
    #{index_certs_6555}
    smaller_replicate_6537 with [0i64] = 0i64
  in {mem_6635, last_offset_6518, defunc_0_reduce_res_6573, consume_res_6556}
}
@athas
Copy link
Member

athas commented May 23, 2023

Minor simplification (mostly to avoid the compiler hypothetically optimising everything away):

def consume (a: *[]i64) = a with [0] = 0
entry test (a: *[2]i64) (_: i64) n =
  let b = map id a :> [n]i64
  let a_consumed = consume a
  let final = consume (copy (filter (\x -> x > 2) a_consumed))
  in (all (\x -> x == 0) b, final)

@athas
Copy link
Member

athas commented May 23, 2023

Ah, I see. The LiftAllocations pass does not properly take consumption into account when reordering code. Should be easy to fix.

@Munksgaard
Copy link
Collaborator

Ah, I see. The LiftAllocations pass does not properly take consumption into account when reordering code. Should be easy to fix.

Want me to take a look?

@athas
Copy link
Member

athas commented May 23, 2023

No need, I can do it.

@athas athas closed this as completed in 889eeb9 May 23, 2023
razetime pushed a commit to razetime/futhark that referenced this issue May 27, 2023
The most invasive change was to make LiftAllocations take aliasing
into account.

I also generally refactored it a bit to further reduce duplication.

I suspect a similar bug lurks in LowerAllocations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants