We are working on getting the documentation cleaned up to the point where it can be released. 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. Micah From: Daniels, Marcus G [mailto:mdaniels at lanl.gov] Sent: Tuesday, December 13, 2011 7:19 AM To: Villmow, Micah Cc: LLVM Developers Mailing List Subject: Re: [LLVMdev] AMD IL Code Generator Backend for OpenCL On Dec 12, 2011, at 9:09 AM, Villmow, Micah wrote: LLVM-IR that isn't generated from AMD's OpenCL frontend does not produce any AMDIL. Is this because of the way metadata is handled? If so, will that technique be documented? Or can it be reasonably inferred from the source code? Thanks, Marcus -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20111213/bfa22f71/attachment.html>
Daniels, Marcus G
2011-Dec-13 21:34 UTC
[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/2649ee01/attachment.html>
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>