[LLVMdev] AMD IL Code Generator Backend for OpenCL

Villmow, Micah Micah.Villmow at amd.com
Tue Dec 13 13:48:17 PST 2011


sgv stands for string global variable, and is a string to represent certain attributes in LLVM-IR. This is fairly ancient and in the future we will be using named metadata/metadata nodes. You can look at AMDILModuleInfo.cpp:parseSGV to see what the string can contain, but for most cases, it can be a zero initialized array of i8 of size 1. FGV stores the filename.
LVGV stores information about local arrays that are declared at the kernel scope in OpenCL.

So, basically the structure looks like this:
struct {
const char* kernel;
const char* sgv;
const char* fgv;
const char* lvgv;
unsigned kernel#;
} llvm_global_annotations a[].

If you encode your function name with __OpenCL_<name>_kernel, it should trigger code generation.

Also, we do not use clang for our frontend, so I'm not sure how it would generate code.

Micah

From: Daniels, Marcus G [mailto:mdaniels at lanl.gov]
Sent: Tuesday, December 13, 2011 1:34 PM
To: Villmow, Micah
Cc: LLVM Developers Mailing List
Subject: Re: [LLVMdev] AMD IL Code Generator Backend for OpenCL

Hi Micah, all,

On Dec 13, 2011, at 8:49 AM, Villmow, Micah wrote:


If you look at the test cases, you can infer what needs to be done. Basically since this is targeted
for OpenCL, we annotate OpenCL kernels slightly different than normal functions and that is
what causes the code to be generated. That being said, on my list of things to do is fix this so that
any function will be generated correctly and also create calling conventions that differentiate
between kernels and non-kernels.

`triple.ll' in your patch has this metadata, but I can't see how to construct it with clang..

%0 = type { i8*, i8*, i8*, i8*, i32 }

@sgv = internal addrspace(2) constant [1 x i8] zeroinitializer
@fgv = internal addrspace(2) constant [1 x i8] zeroinitializer
@lvgv = internal constant [0 x i8*] zeroinitializer
@llvm.global.annotations = appending global [1 x %0] [%0 { i8* bitcast (void ()* @__OpenCL_foo_kernel to i8*), i8* bitcast ([1 x i8] addrspace(2)* @sgv to i8*), i8* bitcast ([1 x i8] addrspace(2)* @fgv to i8*), i8* bitcast ([0 x i8*]* @lvgv to i8*), i32 0 }], section "llvm.metadata"

define void @__OpenCL_foo_kernel() nounwind readnone {
entry:
  ret void
}

Here's my attempt..  I'm guessing that __kernel in OpenCL triggers your annotation, but when I try to use annotate("doesNothing") there's no sign of "doesNothing" in the resulting IR.
Thus, my attempt with the function pointers.   %0 still has a different form, however.
What do "sgv" and "fgv" stand for?  Stack & Frame?   The semantics of these isn't obvious from the test cases.


$ cat a.c
static const char __attribute__ ((address_space(2))) sgv[1];
static const char __attribute__ ((address_space(2))) fgv[1];
static const char* lvgv[0];

void __attribute__ ((annotate("doesNothing"))) func () {
  char val;
  val = sgv[0];
  val = fgv[0];
  val = *lvgv[0];
}

void __attribute__ ((annotate("foobar"))) (*__OpenCL_my_kernel) ()  = func;
$ clang -S -emit-llvm a.c
$ cat a.s
; ModuleID = 'a.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"

%0 = type { i8*, i8*, i8*, i32 }

@sgv = internal addrspace(2) constant [1 x i8] zeroinitializer, align 1
@fgv = internal addrspace(2) constant [1 x i8] zeroinitializer, align 1
@lvgv = internal global [0 x i8*] zeroinitializer, align 8
@__OpenCL_my_kernel = global void (...)* bitcast (void ()* @func to void (...)*), align 8
@__OpenCL_my_kernel1 = private global [7 x i8] c"foobar\00"
@.str = private unnamed_addr global [4 x i8] c"a.c\00"
@llvm.global.annotations = appending global [1 x %0] [%0 { i8* bitcast (void (...)** @__OpenCL_my_kernel to i8*), i8* getelementptr inbounds ([7 x i8]* @__OpenCL_my_kernel1, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 12 }], section "llvm.metadata"

define void @func() nounwind {
  %val = alloca i8, align 1
  %1 = load i8 addrspace(2)* getelementptr inbounds ([1 x i8] addrspace(2)* @sgv, i32 0, i64 0)
  store i8 %1, i8* %val, align 1
  %2 = load i8 addrspace(2)* getelementptr inbounds ([1 x i8] addrspace(2)* @fgv, i32 0, i64 0)
  store i8 %2, i8* %val, align 1
  %3 = load i8** getelementptr inbounds ([0 x i8*]* @lvgv, i32 0, i64 0)
  %4 = load i8* %3
  store i8 %4, i8* %val, align 1
  ret void
}

Adding "__kernel" to "func" does create some metadata when clang is in OpenCL mode, and the IR looks like this:

!opencl.kernels = !{!0}

!0 = metadata !{void ()* @func}

Cheers,

Marcus
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20111213/4d337b7e/attachment.html>


More information about the llvm-dev mailing list