YiTian ECS インスタンス向けに C または C++ ソフトウェアを再コンパイルするには、マクロ、ビルトイン関数、イントリシック関数、およびインラインアセンブリを修正してください。
マクロ
システムマクロはプラットフォームによって異なります。次の表は、ARM ベースのプラットフォーム、x86 プラットフォーム、および両方で定義されているマクロを示しています。
|
ARM ベースのプラットフォーム用マクロ |
x86 プラットフォーム用マクロ |
x86 および ARM ベースのプラットフォーム共通のマクロ |
|
__arm__ |
__amd64__ |
__STDC_HOSTED__ |
|
__thumb__ |
i386 |
__INT64_TYPE__ |
|
__ARM_ARCH_4T__ |
__k8__ |
_LP64 |
|
__aarch64__ |
__SSE2__ |
__WCHAR_MAX__ |
ビルトイン関数
__builtin_ をプレフィックスとする x86 プラットフォーム向けの GCC ビルトイン関数(例:builtin_ia32_xxx)は、YiTian インスタンス上でコンパイルに失敗する可能性があります。
x86 固有のビルトイン関数を ARM 向けの同等関数に置き換えてください。たとえば、CRC 関連の builtin_ia32_crc32qi(a, b) を builtin_aarch64_crc32cb(a, b) に変更します。
イントリシック関数
イントリシック関数は、x86 CPU アーキテクチャに依存した SIMD 操作を呼び出します。ソフトウェアを YiTian インスタンスに移行する際の主な焦点は、SIMD イントリシック関数の移行です。
x86 プラットフォームから YiTian インスタンスへのイントリシック関数の移行手順は以下のとおりです。
-
ARM イントリシックサポートのため、arm_neon.h や arm_sve.h などのヘッダーファイルを追加します。
-
イントリシック関数を置き換えます。詳細については、「Find the Best Architecture for you」(Arm Developer サイト)をご参照ください。
-
上記の手順では、ARM ベースのプラットフォーム向けに命令セットおよびデータの型を修正します。例:
-
x86 の m128 mm_load_ps を ARM の float32x4 vld1q_f32 に変更します。
-
x86 AVX 命令セットは 256 ビットレジスタを使用しますが、AArch64 は 128 ビットレジスタのみをサポートします。セマンティクスが同等となるように命令を拡張してください。たとえば、m256d mm_add_ps を AArch64 上の 2 つの vaddq_f32 SIMD 命令に置き換えます。
-
-
YiTian インスタンスは SVE 命令をサポートしていますが、特殊なプログラミングモードのため、SVE イントリシックの使用は推奨されません。sse2neon などのオープンソースプロジェクトをご利用ください。
インラインアセンブリ
同じセマンティクスを持つ AArch64 向けの同等命令に x86 アセンブリ命令を置き換えてください。たとえば、asm("bswap %0": "=r"(val): "0"(val)) を asm("rev %[dst], %[src]": [dst]"=r"(val): [src]"r"(val)) に変更します。詳細については、「How to Use Inline Assembly Language in C Code」をご参照ください。
サンプルコード
次の例は、x86 から YiTian インスタンスへの移行に向けた C または C++ コードの修正方法を示しています。
修正前のコード:
#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
/* GCC 互換コンパイラ、x86/x86-64 向け */
#include <x86intrin.h>
#endif
uint32_t crc32_4k(uint32_t acc, char* buf) {
for (char* end = buf + 4096; buf < end; buf += 4) {
acc = __builtin_ia32_crc32si(acc, *(uint32_t*)buf);
}
return acc;
}
修正後のコード:
#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
/* GCC 互換コンパイラ、x86/x86-64 向け */
#include <x86intrin.h>
#elif defined(__GNUC__) && defined(__ARM_NEON)
/* GCC 互換コンパイラ、NEON 搭載 ARM 向け */
#include <arm_neon.h>
#if defined(__ARM_FEATURE_SVE)
#include <arm_sve.h>
#endif
#endif
uint32_t crc32_4k(uint32_t acc, char* buf) {
for (char* end = buf + 4096; buf < end; buf += 4) {
acc = __builtin_aarch64_crc32cw(acc, *(uint32_t*)buf);
}
return acc;
}