Траектория компиляции CUDA в Clang довольно сложная (как в цепочке инструментов NVIDIA), и то, что вы пытаетесь сделать, не может работать. IR LLVM из каждой ветви процесса компиляции должен оставаться отдельным, пока не станут доступны объекты с прямой связью. В результате есть много промежуточных шагов, которые вам нужно будет выполнить вручную.
IR-код LLVM для GPU должен быть сначала скомпилирован в код PTX, а затем собран в двоичную полезную нагрузку, которая может быть связана с хостом. объектные файлы.
Итак, в вашем примере вы сначала делаете что-то вроде:
clang++ -std=c++11 -emit-llvm -c -S test.cu --cuda-gpu-arch=sm_52
, которое испускает два ИК-файла llvm test-cuda-nvptx64-nvidia-cuda-sm_52.ll
и test.ll
. Затем код GPU необходимо скомпилировать в PTX (подробнее о бэкэнде nvptx здесь ):
llc -mcpu=sm_52 test-cuda-nvptx64-nvidia-cuda-sm_52.ll -o test.ptx
Теперь код PTX можно собрать в файл ELF, который позже можно будетсвязаны с помощью nvcc (или компоновщика хоста с парой дополнительных шагов) обычным способом:
ptxas --gpu-name=sm_52 test.ptx -o test.ptx.o
fatbinary --cuda -64 --create test.fatbin --image=profile=sm_52,file=test.ptx.o
Для кода хоста вы делаете что-то вроде
llc test.ll
clang -m64 -c test.s
для получения вывода на ассемблереиз IR LLVM и затем соберите его в объектный файл.
Теперь с помощью файла Fatbin, содержащего CUDA скомпилированный код, и объектного файла, содержащего скомпилированный код хоста, вы можете выполнить связывание. Я не смог протестировать связывание объектного файла хоста с Fatbinary с помощью Clang, это то, что вам нужно будет решить самостоятельно. Будет полезно изучить как подробный вывод clang во время вызова компиляции CUDA, так и документацию nvcc, чтобы лучше понять, как работает система построения кода устройства.