google / clspv

Clspv is a compiler for OpenCL C to Vulkan compute shaders
Apache License 2.0
602 stars 87 forks source link

Unhandled Constant case in SPIRVProducer #102

Open dneto0 opened 6 years ago

dneto0 commented 6 years ago

On this input:

constant uint scalar = 42;

constant float arr[3] = { 1.0f, 2.0f, 3.0f };

typedef struct {
  float4 u;
  float v;
} S;

constant S structval[2] = {
    {(float4)(10.5f, 11.5f, 12.5f, 13.5f), 14.5f},
    {(float4)(20.5f, 21.5f, 22.5f, 23.5f), 24.5f},
};

// Same data as arr.  Should reuse the same underlying space as arr
constant float arr2[3] = { 1.0f, 2.0f, 3.0f };

void kernel foo(global float *A, uint n)
{
  *A = arr[n] + arr[3-n] + structval[n].u.y + structval[n].v;
}

I get:

clspv: /build/dneto/aglet/SPIRV-LLVM/third_party/llvm/lib/IR/User.cpp:26: void llvm::User::replaceUsesOfWith(llvm::Value, llvm::Value): Assertion `(!isa(this) || isa(this)) && "Cannot call User::replaceUsesOfWith on a constant!"' failed.

dneto0 commented 6 years ago

Occurs even if the body is only: A[3] = structval[n].v;

dneto0 commented 6 years ago

The problem occurs in SPIRVProducer, when changing a __constant variable address space to module-scope Private.

Trouble occurs with this instruction: %v = getelementptr inbounds [2 x %struct.S], [2 x %struct.S] addrspace(2) bitcast (<{ { <4 x float>, float }, { <4 x float>, float } }> addrspace(2) @structval to [2 x %struct.S] addrspace(2)*), i32 0, i32 %n, i32 1

The code is trying to convert the use of @structval to pointer-to-private, but you can't just replace the use in an LLVM-constant expression.