目次: OpenCL
前回に続いてpoclとClang/LLVMの関係について説明します。Clangは引数の体系が2つあります。1つは通常使用するGCCと互換があるオプション、もう1つはclang -cc1オプションを指定したときに使う内部用オプションです。正式な名前がわからないので適当に呼んでいます。正式な名前をご存知の方は教えていただけると嬉しいです。
前者と後者は -Iや -oのように同じ名前の場合もありますし、顕著に異なる場合もあります。RISC-V向けのmarchやmabiは差が顕著なので、例として紹介します。
$ riscv32-unknown-elf-gcc b.c -c -march=rv32gc -mabi=ilp32f $ clang --target=riscv32 b.c -c -march=rv32gc -mabi=ilp32f
GCCとClangのオプションがほぼ同じですね。次にClang内部用のオプションを確認します。内部用のオプションは -vを指定すると表示できます。
$ clang --target=riscv32 b.c -c -march=rv32gc -mabi=ilp32f -v Debian clang version 11.0.1-2 Target: riscv32-- Thread model: posix InstalledDir: /usr/bin (in-process) "/usr/lib/llvm-11/bin/clang" -cc1 -triple riscv32-- -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name b.c -mrelocation-model static -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -nostdsysteminc -target-feature +m -target-feature +a -target-feature +f -target-feature +d -target-feature +c -target-feature +relax -target-feature -save-restore -target-abi ilp32f -msmall-data-limit 8 -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /usr/lib/llvm-11/lib/clang/11.0.1 -internal-isystem include -fdebug-compilation-dir /home/katsuhiro/share/projects/c/clang_test -ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -fcolor-diagnostics -faddrsig -o b.o -x c b.c clang -cc1 version 11.0.1 based upon LLVM 11.0.1 default target x86_64-pc-linux-gnu ignoring nonexistent directory "include" #include "..." search starts here: #include <...> search starts here: /usr/lib/llvm-11/lib/clang/11.0.1/include End of search list.
先ほどと全く違うことがわかると思います。このままだと色々ごちゃごちゃ表示されていてわかりにくいので、対応するオプションだけ抜粋します。
--target=riscv32: -triple riscv32-- -march=rv32gc : -target-feature +m -target-feature +a -target-feature +f -target-feature +d -target-feature +c -mabi=ilp32f : -target-abi ilp32f
なお -target-featureはカンマ区切りで複数指定することもできるようです。上記で言えば -target-feature +m,+a,+f,+d,+cにしても良いです。
なぜこの話をしたのかというとpocl内でLLVMを呼び出す際は、Clang内部用オプションを使わなければならない箇所があるからです。一番わかりやすい(文字列の形でオプションを指定している)のはpocl_llvm_build_program() です。
// pocl/lib/CL/pocl_llvm_build.cc
int pocl_llvm_build_program(cl_program program,
unsigned device_i,
const char *user_options_cstr,
char *program_bc_path,
cl_uint num_input_headers,
const cl_program *input_headers,
const char **header_include_names,
int linking_program)
{
...
CompilerInvocation &pocl_build = CI.getInvocation();
...
// This is required otherwise the initialization fails with
// unknown triple ''
ss << "-triple=" << device->llvm_target_triplet << " "; //★これ
if (device->llvm_cpu != NULL)
ss << "-target-cpu " << device->llvm_cpu << " "; //★これも同様
...
std::istream_iterator<std::string> begin(ss);
std::istream_iterator<std::string> end;
std::istream_iterator<std::string> i = begin;
std::vector<const char*> itemcstrs;
std::vector<std::string> itemstrs;
while (i != end) {
itemstrs.push_back(*i); //★std::vectorにオプションのstd::stringを並べる
++i;
}
for (unsigned idx = 0; idx < itemstrs.size(); idx++) {
// note: if itemstrs is modified after this, itemcstrs will be full
// of invalid pointers! Could make copies, but would have to clean up then...
itemcstrs.push_back(itemstrs[idx].c_str()); //★std::vectorにオプションの文字列のポインタを並べる
}
...
//★コンパイラに上記のオプションを指定する(この時点ではまだコンパイラは起動しない)
if (!CompilerInvocation::CreateFromArgs(
pocl_build, //★CompilerInvocation
#ifndef LLVM_OLDER_THAN_10_0
ArrayRef<const char *>(itemcstrs.data(),
itemcstrs.data() + itemcstrs.size()),
#else
itemcstrs.data(), itemcstrs.data() + itemcstrs.size(),
#endif
diags)) {
あとはpocl_llvm_codegen() も同様ですが、指定の方法が違います。-target-feature +mのような文字列ではなく、TargetMachineのメソッドを呼び出して指定します。コードで見たほうがわかりやすいでしょう。
// pocl/lib/CL/pocl_llvm_wg.cc
int pocl_llvm_codegen(cl_device_id Device, void *Modp, char **Output,
uint64_t *OutputSize) {
...
llvm::Triple Triple(Device->llvm_target_triplet);
llvm::TargetMachine *Target = GetTargetMachine(Device, Triple);
// First try direct object code generation from LLVM, if supported by the
// LLVM backend for the target.
bool LLVMGeneratesObjectFiles = true;
SmallVector<char, 4096> Data;
llvm::raw_svector_ostream SOS(Data);
bool cannotEmitFile;
cannotEmitFile = Target->addPassesToEmitFile(PMObj, SOS,
#ifndef LLVM_OLDER_THAN_7_0
nullptr,
#endif
CODEGEN_FILE_TYPE_NS::CGFT_ObjectFile);
Target->setTargetFeatureString("+m,+a,+f"); //★-target-feature +m,+a,+fに相当する
独自アクセラレータ向けの実装を行う際にClang/LLVMのオプションを変えたくなることは多々ありますから、今回のオプションの違いは今後の説明でも登場するはずです。たぶん。
< | 2021 | > | ||||
<< | < | 07 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | - | - | 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
合計:
本日:
管理者: Katsuhiro Suzuki(katsuhiro( a t )katsuster.net)
This is Simple Diary 1.0
Copyright(C) Katsuhiro Suzuki 2006-2023.
Powered by PHP 8.2.15.
using GD bundled (2.1.0 compatible)(png support.)