KhronosGroup/SPIRV-LLVM

SPIR-V generator is crashed on a simple device execution kernel.

Closed this issue · 6 comments

SPRI-V converter hits the following assert during conversion from the attached LLVM IR to SPIR-V
Assertion `HasVariWC && WC >= WordCount && "Invalid word count"' failed.
To reproduce:
$ llvm-as enqueue.ll.txt -o enqueue.bc && llvm-spirv enqueue.bc
Call stack enqueue.bt.txt

The problematic LLVM IL enqueue.ll.txt is compiled from the following OpenCL C 2.0 source code
void __kernel one(__global float * inout) {
_inout = cos(_inout);
}

void __kernel two(__global float * inout) {
enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange_1D(1), ^{one(inout);});
}

This test is invalid. The LLVM/SPIR-V translator expects arguments of enqueue_kernel follows the SPIR 2.0 format. The attached LLVM IR does not conform to SPIR 2.0.

bader commented

Guys, I've uploaded OpenCL front-end compiler to https://github.com/KhronosGroup/SPIR - 'spirv-1.0' branch. It supports both versions of OpenCL languages - 1.x and 2.0, but I didn't modify blocks implementation for two reasons:

  1. It's not necessary for SPIR-V translation. It was only required for SPIR-2.0 specification.
  2. I'd like to contribute https://github.com/KhronosGroup/SPIR - 'spirv-1.0' branch patches to clang repository (http://llvm.org/svn/llvm-project/cfe/trunk). Modifying blocks for OpenCL doesn't make sense since it's not much different from existing implementation, so I assumed it will be rejected.

I tested this new front-end with conformance tests for 1.2 and 2.0. Everything should be fine, except blocks.
I'm going to write a short readme file with instructions how to generate SPIR-V file from OpenCL using this new front-end compiler and after that I'm going to fix this bug.

Sam, are you OK with switching from SPIR 1.2 ang SPIR 2.0 generators to new clang?

I think we'd better find a way to support blocks in OpenCL.

Since OpenCL does not support function pointer, blocks need to be represented in a way facilitating extraction of invoke function. Also OCL runtime needs to pass kernel arguments to the kernels, there need a way to represent the context pointer, size and alignment.

The SPIR 2.0 blocks do that.

The clang representation has two issues:

  1. stores invoke function and context pointer in stack var, which make them difficult to extract
  2. no context size and alignment info

For now we may temporarily use clang representation of blocks. I want to take a look if it is possible to translate that to SPIR-V. We may revisit this issue later.

Reproduced on LLVM BC compiled from the same OpenCL C with SPIR 2.0 generator (i.e. with spir 2.0 blocks).
spir20.blocks.bc.zip

Seems there is a bug in SPIR 2.0 generator (branch spir_20_provisional). It produces invalid IR for device execution. I'll leave this issue open because of SPIR2.0/Apple blocks discussion.
Just in case attaching correct BC
correct.spir20.blocks.bc.zip

bader commented

I've implemented SPIR 2.0 blocks in spirv-1.0 branch, so now your OpenCL source successfully compiles with 49a8b4a rev.
I suggest closing this issue.