E6032

E6032 — An across loop that the topology or its place cannot have: a level the topology does not name, a loop outside a spawn on region or in the wrong order, a size that is not known when the kernel is compiled or is over the limit, or a jump out of the loop.

What the compiler reports

Error[E6032] at 23:{{.*}}the lanes of a block share a tensor that the code of the block makes
Error[E6032] at 36:{{.*}}the lanes of a block share a tensor that the code of the block makes
Error[E6032] at 50:{{.*}}a subgroup has no memory of its own
Error[E6032] at 67:{{.*}}So the size may not call a function

The fragments the test suite holds the compiler to. An ellipsis marks text the test does not constrain; the emitted message also carries a source location.

A program that triggers it

//
// Part of the Vx Project, under the Apache License v2.0 with LLVM Exceptions.
// See LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Code of a block outside its lane loops runs once for the block, so the lanes of the block
// share a tensor that it makes. Such a tensor must be in a memory with `scope: cta` or
// `scope: sm`, such as `Memory::SMEM` of the H100 file. A subgroup has no memory of its own.
// The host computes the size of a loop of blocks before the launch, and the kernel computes it
// again, so the size may not call a function. Each function gets E6032.
//

pub fn tensor_in_default_memory(o : &mut Tensor<f32, [?, 8], Memory::HBM>, n : i32) -> void {
  spawn on(Topology::Device) {
    for b in 0..n across blocks {
      let mut t = Tensor<f32, [8]>::new();
      t[0] = 2.0;
      for l in 0..8 across lanes {
        o[b][l] = t[0];
      }
    }
  }
  return;
}

pub fn tensor_in_device_memory(o : &mut Tensor<f32, [?, 8], Memory::HBM>, n : i32) -> void {
  spawn on(Topology::Device) {
    for b in 0..n across blocks {
      let mut t = unsafe { Tensor<f32, [8], Memory::HBM>::uninit() };
      for l in 0..8 across lanes {
        t[l] = 1.0;
        o[b][l] = t[l];
      }
    }
  }
  return;
}

pub fn tensor_in_subgroup_code(o : &mut Tensor<f32, [?, 32], Memory::HBM>, n : i32) -> void {
  spawn on(Topology::Device) {
    for b in 0..n across blocks {
      for w in 0..4 across subgroups {
        let mut t = unsafe { Tensor<f32, [32], Memory::SMEM>::uninit() };
        for l in 0..32 across lanes {
          t[l] = 1.0;
          o[b * 4 + w][l] = t[l];
        }
      }
    }
  }
  return;
}

fn half(n : i32) on Topology::Device -> i32 {
  return n / 2;
}

pub fn size_that_calls(o : &mut Tensor<f32, [?, 8], Memory::HBM>, n : i32) -> void {
  spawn on(Topology::Device) {
    for b in 0..half(n) across blocks {
      for l in 0..8 across lanes {
        o[b][l] = 1.0;
      }
    }
  }
  return;
}

From tests/frontend/fail/across_block_tensors_and_sizes_that_are_not_allowed.vx, which asserts this diagnostic on every commit.

Related