300 lines · c
1// REQUIRES: x86-registered-target2// REQUIRES: nvptx-registered-target3// REQUIRES: amdgpu-registered-target4// REQUIRES: spirv-registered-target5 6// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.elf.o7 8// RUN: llvm-offload-binary -o %t.out --image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_709// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \10// RUN: -fembed-offload-object=%t.out11// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \12// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP,OPENMP-ELF13// RUN: clang-linker-wrapper --print-wrapped-module --dry-run -r --host-triple=x86_64-unknown-linux-gnu \14// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP-ELF,OPENMP-REL15// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-windows-gnu \16// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP,OPENMP-COFF17 18// OPENMP-ELF: @__start_llvm_offload_entries = external hidden constant [0 x %struct.__tgt_offload_entry]19// OPENMP-ELF-NEXT: @__stop_llvm_offload_entries = external hidden constant [0 x %struct.__tgt_offload_entry]20// OPENMP-ELF-NEXT: @__dummy.llvm_offload_entries = internal constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "llvm_offload_entries"21 22// OPENMP-COFF: @__start_llvm_offload_entries = weak_odr hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "llvm_offload_entries$OA"23// OPENMP-COFF-NEXT: @__stop_llvm_offload_entries = weak_odr hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "llvm_offload_entries$OZ"24 25// OPENMP-REL: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD{{.*}}", section ".llvm.offloading.relocatable", align 826 27// OPENMP: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD{{.*}}", section ".llvm.offloading", align 828// OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { ptr getelementptr ([[[BEGIN:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 0, i64 144), ptr getelementptr ([[[END:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 0, i64 144), ptr @__start_llvm_offload_entries, ptr @__stop_llvm_offload_entries }]29// OPENMP-NEXT: @.omp_offloading.descriptor = internal constant %__tgt_bin_desc { i32 1, ptr @.omp_offloading.device_images, ptr @__start_llvm_offload_entries, ptr @__stop_llvm_offload_entries }30// OPENMP-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.omp_offloading.descriptor_reg, ptr null }]31 32// OPENMP: define internal void @.omp_offloading.descriptor_reg() section ".text.startup" {33// OPENMP-NEXT: entry:34// OPENMP-NEXT: call void @__tgt_register_lib(ptr @.omp_offloading.descriptor)35// OPENMP-NEXT: %0 = call i32 @atexit(ptr @.omp_offloading.descriptor_unreg)36// OPENMP-NEXT: ret void37// OPENMP-NEXT: }38 39// OPENMP: define internal void @.omp_offloading.descriptor_unreg() section ".text.startup" {40// OPENMP-NEXT: entry:41// OPENMP-NEXT: call void @__tgt_unregister_lib(ptr @.omp_offloading.descriptor)42// OPENMP-NEXT: ret void43// OPENMP-NEXT: }44 45// RUN: llvm-offload-binary -o %t.out --image=file=%t.elf.o,kind=cuda,triple=nvptx64-nvidia-cuda,arch=sm_7046// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \47// RUN: -fembed-offload-object=%t.out48// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \49// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-ELF50// RUN: clang-linker-wrapper --print-wrapped-module --dry-run -r --host-triple=x86_64-unknown-linux-gnu \51// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-ELF52// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-windows-gnu \53// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-COFF54 55// CUDA-ELF: @__start_llvm_offload_entries = external hidden constant [0 x %struct.__tgt_offload_entry]56// CUDA-ELF-NEXT: @__stop_llvm_offload_entries = external hidden constant [0 x %struct.__tgt_offload_entry]57// CUDA-ELF-NEXT: @__dummy.llvm_offload_entries = internal constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "llvm_offload_entries"58 59// CUDA-COFF: @__start_llvm_offload_entries = weak_odr hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "llvm_offload_entries$OA"60// CUDA-COFF-NEXT: @__stop_llvm_offload_entries = weak_odr hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "llvm_offload_entries$OZ"61 62// CUDA: @.fatbin_image = internal constant [0 x i8] zeroinitializer, section ".nv_fatbin"63// CUDA-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1180844977, i32 1, ptr @.fatbin_image, ptr null }, section ".nvFatBinSegment", align 864// CUDA-NEXT: @.cuda.binary_handle = internal global ptr null65 66// CUDA: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.cuda.fatbin_reg, ptr null }]67 68// CUDA: define internal void @.cuda.fatbin_reg() section ".text.startup" {69// CUDA-NEXT: entry:70// CUDA-NEXT: %0 = call ptr @__cudaRegisterFatBinary(ptr @.fatbin_wrapper)71// CUDA-NEXT: store ptr %0, ptr @.cuda.binary_handle, align 872// CUDA-NEXT: call void @.cuda.globals_reg(ptr %0)73// CUDA-NEXT: call void @__cudaRegisterFatBinaryEnd(ptr %0)74// CUDA-NEXT: %1 = call i32 @atexit(ptr @.cuda.fatbin_unreg)75// CUDA-NEXT: ret void76// CUDA-NEXT: }77//78// CUDA: define internal void @.cuda.fatbin_unreg() section ".text.startup" {79// CUDA-NEXT: entry:80// CUDA-NEXT: %0 = load ptr, ptr @.cuda.binary_handle, align 881// CUDA-NEXT: call void @__cudaUnregisterFatBinary(ptr %0)82// CUDA-NEXT: ret void83// CUDA-NEXT: }84//85// CUDA: define internal void @.cuda.globals_reg(ptr %0) section ".text.startup" {86// CUDA-NEXT: entry:87// CUDA-NEXT: %1 = icmp ne ptr @__start_llvm_offload_entries, @__stop_llvm_offload_entries88// CUDA-NEXT: br i1 %1, label %while.entry, label %while.end89//90// CUDA: while.entry:91// CUDA-NEXT: %entry1 = phi ptr [ @__start_llvm_offload_entries, %entry ], [ %16, %if.end ]92// CUDA-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 493// CUDA-NEXT: %addr = load ptr, ptr %2, align 894// CUDA-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 895// CUDA-NEXT: %aux_addr = load ptr, ptr %3, align 896// CUDA-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 297// CUDA-NEXT: %kind = load i16, ptr %4, align 298// CUDA-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 599// CUDA-NEXT: %name = load ptr, ptr %5, align 8100// CUDA-NEXT: %6 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 6101// CUDA-NEXT: %size = load i64, ptr %6, align 4102// CUDA-NEXT: %7 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 3103// CUDA-NEXT: %flags = load i32, ptr %7, align 4104// CUDA-NEXT: %8 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 7105// CUDA-NEXT: %data = load i64, ptr %8, align 4106// CUDA-NEXT: %9 = trunc i64 %data to i32107// CUDA-NEXT: %type = and i32 %flags, 7108// CUDA-NEXT: %10 = and i32 %flags, 8109// CUDA-NEXT: %extern = lshr i32 %10, 3110// CUDA-NEXT: %11 = and i32 %flags, 16111// CUDA-NEXT: %constant = lshr i32 %11, 4112// CUDA-NEXT: %12 = and i32 %flags, 32113// CUDA-NEXT: %normalized = lshr i32 %12, 5114// CUDA-NEXT: %13 = icmp eq i16 %kind, 2115// CUDA-NEXT: br i1 %13, label %if.kind, label %if.end116//117// CUDA: if.kind:118// CUDA-NEXT: %14 = icmp eq i64 %size, 0119// CUDA-NEXT: br i1 %14, label %if.then, label %if.else120//121// CUDA: if.then:122// CUDA-NEXT: %15 = call i32 @__cudaRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null)123// CUDA-NEXT: br label %if.end124//125// CUDA: if.else:126// CUDA-NEXT: switch i32 %type, label %if.end [127// CUDA-NEXT: i32 0, label %sw.global128// CUDA-NEXT: i32 1, label %sw.managed129// CUDA-NEXT: i32 2, label %sw.surface130// CUDA-NEXT: i32 3, label %sw.texture131// CUDA-NEXT: ]132//133// CUDA: sw.global:134// CUDA-NEXT: call void @__cudaRegisterVar(ptr %0, ptr %addr, ptr %name, ptr %name, i32 %extern, i64 %size, i32 %constant, i32 0)135// CUDA-NEXT: br label %if.end136//137// CUDA: sw.managed:138// CUDA-NEXT: call void @__cudaRegisterManagedVar(ptr %0, ptr %aux_addr, ptr %addr, ptr %name, i64 %size, i32 %9)139// CUDA-NEXT: br label %if.end140//141// CUDA: sw.surface:142// CUDA-NEXT: br label %if.end143//144// CUDA: sw.texture:145// CUDA-NEXT: br label %if.end146//147// CUDA: if.end:148// CUDA-NEXT: %16 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1149// CUDA-NEXT: %17 = icmp eq ptr %16, @__stop_llvm_offload_entries150// CUDA-NEXT: br i1 %17, label %while.end, label %while.entry151//152// CUDA: while.end:153// CUDA-NEXT: ret void154// CUDA-NEXT: }155 156// RUN: llvm-offload-binary -o %t.out --image=file=%t.elf.o,kind=hip,triple=amdgcn-amd-amdhsa,arch=gfx908157// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \158// RUN: -fembed-offload-object=%t.out159// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \160// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-ELF161// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu -r \162// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-ELF163// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-windows-gnu \164// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-COFF165 166// HIP-ELF: @__start_llvm_offload_entries = external hidden constant [0 x %struct.__tgt_offload_entry]167// HIP-ELF-NEXT: @__stop_llvm_offload_entries = external hidden constant [0 x %struct.__tgt_offload_entry]168// HIP-ELF-NEXT: @__dummy.llvm_offload_entries = internal constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "llvm_offload_entries"169 170// HIP-COFF: @__start_llvm_offload_entries = weak_odr hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "llvm_offload_entries$OA"171// HIP-COFF-NEXT: @__stop_llvm_offload_entries = weak_odr hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "llvm_offload_entries$OZ"172 173// HIP: @.fatbin_image = internal constant [0 x i8] zeroinitializer, section ".hip_fatbin"174// HIP-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1212764230, i32 1, ptr @.fatbin_image, ptr null }, section ".hipFatBinSegment", align 8175// HIP-NEXT: @.hip.binary_handle = internal global ptr null176 177// HIP: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.hip.fatbin_reg, ptr null }]178 179// HIP: define internal void @.hip.fatbin_reg() section ".text.startup" {180// HIP-NEXT: entry:181// HIP-NEXT: %0 = call ptr @__hipRegisterFatBinary(ptr @.fatbin_wrapper)182// HIP-NEXT: store ptr %0, ptr @.hip.binary_handle, align 8183// HIP-NEXT: call void @.hip.globals_reg(ptr %0)184// HIP-NEXT: %1 = call i32 @atexit(ptr @.hip.fatbin_unreg)185// HIP-NEXT: ret void186// HIP-NEXT: }187//188// HIP: define internal void @.hip.fatbin_unreg() section ".text.startup" {189// HIP-NEXT: entry:190// HIP-NEXT: %0 = load ptr, ptr @.hip.binary_handle, align 8191// HIP-NEXT: call void @__hipUnregisterFatBinary(ptr %0)192// HIP-NEXT: ret void193// HIP-NEXT: }194//195// HIP: define internal void @.hip.globals_reg(ptr %0) section ".text.startup" {196// HIP-NEXT: entry:197// HIP-NEXT: %1 = icmp ne ptr @__start_llvm_offload_entries, @__stop_llvm_offload_entries198// HIP-NEXT: br i1 %1, label %while.entry, label %while.end199//200// HIP: while.entry:201// HIP-NEXT: %entry1 = phi ptr [ @__start_llvm_offload_entries, %entry ], [ %16, %if.end ]202// HIP-NEXT: %2 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 4203// HIP-NEXT: %addr = load ptr, ptr %2, align 8204// HIP-NEXT: %3 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 8205// HIP-NEXT: %aux_addr = load ptr, ptr %3, align 8206// HIP-NEXT: %4 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 2207// HIP-NEXT: %kind = load i16, ptr %4, align 2208// HIP-NEXT: %5 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 5209// HIP-NEXT: %name = load ptr, ptr %5, align 8210// HIP-NEXT: %6 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 6211// HIP-NEXT: %size = load i64, ptr %6, align 4212// HIP-NEXT: %7 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 3213// HIP-NEXT: %flags = load i32, ptr %7, align 4214// HIP-NEXT: %8 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i32 0, i32 7215// HIP-NEXT: %data = load i64, ptr %8, align 4216// HIP-NEXT: %9 = trunc i64 %data to i32217// HIP-NEXT: %type = and i32 %flags, 7218// HIP-NEXT: %10 = and i32 %flags, 8219// HIP-NEXT: %extern = lshr i32 %10, 3220// HIP-NEXT: %11 = and i32 %flags, 16221// HIP-NEXT: %constant = lshr i32 %11, 4222// HIP-NEXT: %12 = and i32 %flags, 32223// HIP-NEXT: %normalized = lshr i32 %12, 5224// HIP-NEXT: %13 = icmp eq i16 %kind, 4225// HIP-NEXT: br i1 %13, label %if.kind, label %if.end226//227// HIP: if.kind:228// HIP-NEXT: %14 = icmp eq i64 %size, 0229// HIP-NEXT: br i1 %14, label %if.then, label %if.else230//231// HIP: if.then:232// HIP-NEXT: %15 = call i32 @__hipRegisterFunction(ptr %0, ptr %addr, ptr %name, ptr %name, i32 -1, ptr null, ptr null, ptr null, ptr null, ptr null)233// HIP-NEXT: br label %if.end234//235// HIP: if.else:236// HIP-NEXT: switch i32 %type, label %if.end [237// HIP-NEXT: i32 0, label %sw.global238// HIP-NEXT: i32 1, label %sw.managed239// HIP-NEXT: i32 2, label %sw.surface240// HIP-NEXT: i32 3, label %sw.texture241// HIP-NEXT: ]242//243// HIP: sw.global:244// HIP-NEXT: call void @__hipRegisterVar(ptr %0, ptr %addr, ptr %name, ptr %name, i32 %extern, i64 %size, i32 %constant, i32 0)245// HIP-NEXT: br label %if.end246//247// HIP: sw.managed:248// HIP-NEXT: call void @__hipRegisterManagedVar(ptr %0, ptr %aux_addr, ptr %addr, ptr %name, i64 %size, i32 %9)249// HIP-NEXT: br label %if.end250//251// HIP: sw.surface:252// HIP-NEXT: call void @__hipRegisterSurface(ptr %0, ptr %addr, ptr %name, ptr %name, i32 %9, i32 %extern)253// HIP-NEXT: br label %if.end254//255// HIP: sw.texture:256// HIP-NEXT: call void @__hipRegisterTexture(ptr %0, ptr %addr, ptr %name, ptr %name, i32 %9, i32 %normalized, i32 %extern)257// HIP-NEXT: br label %if.end258//259// HIP: if.end:260// HIP-NEXT: %16 = getelementptr inbounds %struct.__tgt_offload_entry, ptr %entry1, i64 1261// HIP-NEXT: %17 = icmp eq ptr %16, @__stop_llvm_offload_entries262// HIP-NEXT: br i1 %17, label %while.end, label %while.entry263//264// HIP: while.end:265// HIP-NEXT: ret void266// HIP-NEXT: }267 268// RUN: llvm-offload-binary -o %t.out --image=file=%t.elf.o,kind=sycl,triple=spirv64-unknown-unknown,arch=generic269// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \270// RUN: -fembed-offload-object=%t.out271// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \272// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=SYCL273// RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu -r \274// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=SYCL275 276// SYCL: %__sycl.tgt_device_image = type { i16, i8, i8, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }277// SYCL-NEXT: %__sycl.tgt_bin_desc = type { i16, i16, ptr, ptr, ptr }278 279// SYCL: @.sycl_offloading.target.0 = internal unnamed_addr constant [1 x i8] zeroinitializer280// SYCL-NEXT: @.sycl_offloading.opts.compile.0 = internal unnamed_addr constant [1 x i8] zeroinitializer281// SYCL-NEXT: @.sycl_offloading.opts.link.0 = internal unnamed_addr constant [1 x i8] zeroinitializer282// SYCL-NEXT: @.sycl_offloading.0.data = internal unnamed_addr constant [0 x i8] zeroinitializer, section ".llvm.offloading"283// SYCL-NEXT: @.offloading.entry_name = internal unnamed_addr constant [5 x i8] c"stub\00", section ".llvm.rodata.offloading", align 1284// SYCL-NEXT: @.offloading.entry.stub = weak constant %struct.__tgt_offload_entry { i64 0, i16 1, i16 8, i32 0, ptr null, ptr @.offloading.entry_name, i64 0, i64 0, ptr null }, section "llvm_offload_entries", align 8285// SYCL-NEXT: @.sycl_offloading.entries_arr = internal constant [1 x %struct.__tgt_offload_entry] [%struct.__tgt_offload_entry { i64 0, i16 1, i16 8, i32 0, ptr null, ptr @.offloading.entry_name, i64 0, i64 0, ptr null }]286// SYCL-NEXT: @.sycl_offloading.device_images = internal unnamed_addr constant [1 x %__sycl.tgt_device_image] [%__sycl.tgt_device_image { i16 3, i8 8, i8 0, ptr @.sycl_offloading.target.0, ptr @.sycl_offloading.opts.compile.0, ptr @.sycl_offloading.opts.link.0, ptr @.sycl_offloading.0.data, ptr @.sycl_offloading.0.data, ptr @.sycl_offloading.entries_arr, ptr getelementptr ([1 x %struct.__tgt_offload_entry], ptr @.sycl_offloading.entries_arr, i64 0, i64 1), ptr null, ptr null }]287// SYCL-NEXT: @.sycl_offloading.descriptor = internal constant %__sycl.tgt_bin_desc { i16 1, i16 1, ptr @.sycl_offloading.device_images, ptr null, ptr null }288 289// SYCL: define internal void @sycl.descriptor_reg() section ".text.startup" {290// SYCL-NEXT: entry:291// SYCL-NEXT: call void @__sycl_register_lib(ptr @.sycl_offloading.descriptor)292// SYCL-NEXT: ret void293// SYCL-NEXT: }294 295// SYCL: define internal void @sycl.descriptor_unreg() section ".text.startup" {296// SYCL-NEXT: entry:297// SYCL-NEXT: call void @__sycl_unregister_lib(ptr @.sycl_offloading.descriptor)298// SYCL-NEXT: ret void299// SYCL-NEXT: }300