FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages

"Creating an LLVM Backend for the Cpu0 Architecture"をやってみる(12. Int型以外のサポート)

f:id:msyksphinz:20181123225150p:plain

Cpu0のバックエンドをLLVMに追加するプロジェクト、7章では、これまでint型だけであった型のサポートを拡張する。

今回も非常にファイル量が多くて、とりあえずLLVMをビルドするためだけにパッチを作って当てているが、LLVM 7.0は未サポートになっている部分が多く、ソースコードを書き直す必要があった。

  • Chapter7の実装を追加したもの

github.com

ローカル変数ポインタのサポート

ローカル変数のポインタを扱うためには、EffectiveAddressを計算する要素が必要になる。

class EffectiveAddress<string instr_asm, RegisterClass RC, Operand Mem> :
  FMem<0x09, (outs RC:$ra), (ins Mem:$addr),
     instr_asm, [(set RC:$ra, addr:$addr)], IIAlu>;
}

char, short, int, bool型のサポート

それぞれの型をサポートするために以下のdefを追加する。 lb/lhは符号付バイト型、符号付ショート型のための命令であり、lbu/lhuは符号なしバイト型、符号なしショート型のための命令である。

let Predicates = [Ch7_1] in {
defm LB     : LoadM32<0x03, "lb",  sextloadi8>;
defm LBu    : LoadM32<0x04, "lbu", zextloadi8>;
defm SB     : StoreM32<0x05, "sb", truncstorei8>;
defm LH     : LoadM32<0x06, "lh",  sextloadi16_a>;
defm LHu    : LoadM32<0x07, "lhu", zextloadi16_a>;
defm SH     : StoreM32<0x08, "sh", truncstorei16_a>;
}

long long型

Long Longをサポートするために、SHL_PARTS, SRA_PARTS, SRL_PARTSをサポートする。

  // Handle i64 shl
  setOperationAction(ISD::SHL_PARTS,          MVT::i32,   Expand);
  setOperationAction(ISD::SRA_PARTS,          MVT::i32,   Expand);
  setOperationAction(ISD::SRL_PARTS,          MVT::i32,   Expand);

配列と構造体のサポート

配列と構造体は、Chapter7_1の実装ですでにサポートされている。

Vector型(SIMD)のサポート

Vector型は、型としては一応サポートされているが、結果的にはひたすらLoadを繰り返して演算するというコードが生成される。

typedef long   vector8long   __attribute__((__vector_size__(32)));
typedef long   vector8short   __attribute__((__vector_size__(16)));


int test_cmplt_short() {
  volatile vector8short a0 = {0, 1, 2, 3};
  volatile vector8short b0 = {2, 2, 2, 2};
  volatile vector8short c0;
  c0 = a0 < b0; // c0[0] = -2147483647=0x80000001, c0[1] = -2147483647=0x80000001, c0[2] = 0, c0[3] = 0
  
  return (int)(c0[0]+c0[1]+c0[2]+c0[3]); // 2
}


int test_cmplt_long() {
  volatile vector8long a0 = {2, 2, 2, 2, 1, 1, 1, 1};
  volatile vector8long b0 = {1, 1, 1, 1, 2, 2, 2, 2};
  volatile vector8long c0;
  c0 = a0 < b0; // c0[0..3] = {0, 0, ...}, c0[4..7] = {-2147483647=0x80000001, ...}
  
  return (c0[0]+c0[1]+c0[2]+c0[3]+c0[4]+c0[5]+c0[6]+c0[7]); //4
}