- CUDA's dynamic parallelism extension allows device-side kernel
launches, which share the identical syntax to host-side launches, e.g.,
kernel<<<Dg, Db, Ns, S>>>(arguments);
but differ from the code generation. That device-side kernel launches is
eventually translated into the following sequence
config = cudaGetParameterBuffer(alignment, size);
// setup arguments by copying them into `config`.
cudaLaunchDevice(func, config, Dg, Db, Ns, S);
- To support the device-side kernel launch, 'CUDAKernelCallExpr' is
reused but its config expr is set to a call to 'cudaLaunchDevice'.
During the code generation, 'CUDAKernelCallExpr' is expanded into the
sequence aforementioned.
- As the device-side kernel launch requires the source to be compiled as
relocatable device code and linked with '-lcudadevrt'. Linkers are
changed to pass relevant link options to 'nvlink'.
36 lines
1.9 KiB
Plaintext
36 lines
1.9 KiB
Plaintext
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
|
|
// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fcuda-is-device -fgpu-rdc -emit-llvm %s -o - | FileCheck %s
|
|
|
|
#include "Inputs/cuda.h"
|
|
|
|
// CHECK-LABEL: define dso_local ptx_kernel void @_Z2g2i(
|
|
// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
|
|
// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
|
|
// CHECK-NEXT: ret void
|
|
//
|
|
__global__ void g2(int x) {}
|
|
|
|
// CHECK-LABEL: define dso_local ptx_kernel void @_Z2g1v(
|
|
// CHECK-SAME: ) #[[ATTR0]] {
|
|
// CHECK-NEXT: [[ENTRY:.*:]]
|
|
// CHECK-NEXT: [[AGG_TMP:%.*]] = alloca [[STRUCT_DIM3:%.*]], align 4
|
|
// CHECK-NEXT: [[AGG_TMP1:%.*]] = alloca [[STRUCT_DIM3]], align 4
|
|
// CHECK-NEXT: [[CALL:%.*]] = call ptr @cudaGetParameterBuffer(i64 noundef 64, i64 noundef 4) #[[ATTR3:[0-9]+]]
|
|
// CHECK-NEXT: [[TMP0:%.*]] = icmp ne ptr [[CALL]], null
|
|
// CHECK-NEXT: br i1 [[TMP0]], label %[[DKCALL_CONFIGOK:.*]], label %[[DKCALL_END:.*]]
|
|
// CHECK: [[DKCALL_CONFIGOK]]:
|
|
// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 0
|
|
// CHECK-NEXT: store i32 42, ptr [[TMP1]], align 64
|
|
// CHECK-NEXT: call void @_ZN4dim3C1Ejjj(ptr noundef nonnull align 4 dereferenceable(12) [[AGG_TMP]], i32 noundef 1, i32 noundef 1, i32 noundef 1) #[[ATTR3]]
|
|
// CHECK-NEXT: call void @_ZN4dim3C1Ejjj(ptr noundef nonnull align 4 dereferenceable(12) [[AGG_TMP1]], i32 noundef 1, i32 noundef 1, i32 noundef 1) #[[ATTR3]]
|
|
// CHECK-NEXT: [[CALL2:%.*]] = call i32 @cudaLaunchDevice(ptr noundef @_Z2g2i, ptr noundef [[CALL]], ptr noundef byval([[STRUCT_DIM3]]) align 4 [[AGG_TMP]], ptr noundef byval([[STRUCT_DIM3]]) align 4 [[AGG_TMP1]], i32 noundef 0, ptr noundef null) #[[ATTR3]]
|
|
// CHECK-NEXT: br label %[[DKCALL_END]]
|
|
// CHECK: [[DKCALL_END]]:
|
|
// CHECK-NEXT: ret void
|
|
//
|
|
__global__ void g1(void) {
|
|
g2<<<1, 1>>>(42);
|
|
}
|