前回の続き。
データのバイトスワップを行う。C言語では、__builtin_bswap16
, __builtin_bswap32
, __builtin_bswap64
により取得することができる。
これらはそのまま命令に落とし込めないので、IRの生成を抑制する。
func_bswap.cpp
int test_bswap16() { volatile int a = 0x1234; int result = (__builtin_bswap16(a) ^ 0x3412); return result; } int test_bswap32() { volatile int a = 0x1234; int result = (__builtin_bswap32(a) ^ 0x34120000); return result; } int test_bswap64() { volatile int a = 0x1234; int result = (__builtin_bswap64(a) ^ 0x3412000000000000); return result; } int test_bswap() { int result = test_bswap16() + test_bswap32() + test_bswap64(); return result; }
./bin/clang func_bswap.cpp -c -emit-llvm --target=riscv32-unknown-elf -o - | ./bin/llvm-dis -o -
define dso_local i32 @_Z12test_bswap16v() #0 { entry: %a = alloca i32, align 4 %result = alloca i32, align 4 store volatile i32 4660, i32* %a, align 4 %0 = load volatile i32, i32* %a, align 4 %conv = trunc i32 %0 to i16 %1 = call i16 @llvm.bswap.i16(i16 %conv) %conv1 = zext i16 %1 to i32 %xor = xor i32 %conv1, 13330 store i32 %xor, i32* %result, align 4 %2 = load i32, i32* %result, align 4 ret i32 %2 } ... define dso_local i32 @_Z12test_bswap32v() #0 { entry: %1 = call i32 @llvm.bswap.i32(i32 %0) } ... define dso_local i32 @_Z12test_bswap64v() #0 { entry: %1 = call i64 @llvm.bswap.i64(i64 %conv) }
それぞれ、llvm.bswap.i16
, llvm.bswap.i32
, llvm.bswap.i64
が呼ばれていることが分かる。
それぞれ、16ビット、32ビット、64ビットの長さでバイトスワップを行うノードである。
https://llvm.org/docs/LangRef.html#llvm-bswap-intrinsics
このノードも、直接命令として落とし込むことはできない。このノードは、setOperationAction()
の設定で生成を禁止し、より一般的なノードへの置き換えを行う。
llvm-myriscvx80/lib/Target/MYRISCVX/MYRISCVXISelLowering.cpp
MYRISCVXTargetLowering::MYRISCVXTargetLowering(const MYRISCVXTargetMachine &TM, const MYRISCVXSubtarget &STI) ... setOperationAction(ISD::BSWAP, MVT::i16, Expand); setOperationAction(ISD::BSWAP, MVT::i32, Expand); setOperationAction(ISD::BSWAP, MVT::i64, Expand); ... }
BSWAPのコンパイル結果である。バイトスワップの操作が展開されていることが分かる。
_Z12test_bswap16v: # @_Z12test_bswap16v # %bb.0: # %entry addi x2, x2, -8 lui x10, 1 ori x10, x10, 564 sw x10, 4(x2) lw x10, 4(x2) slli x11, x10, 8 lui x12, 4080 and x11, x11, x12 slli x10, x10, 24 or x10, x10, x11 srli x10, x10, 16 lui x11, 3 ori x11, x11, 1042 xor x10, x10, x11 sw x10, 0(x2) lw x10, 0(x2) addi x2, x2, 8 ret