FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

LLVMのバックエンドを作るための第一歩 (31. i32よりも小さな値を引数に渡すとどのようなDAGになるのか)

i32型の変数を引数として渡した関数の場合は、レジスタもスタックもサイズはi32で考えているのでこの場合は問題ないのだが、ではi32よりも小さな型の引数を渡す場合にはどのような処理になっているのだろうか。 この場合は呼び出し規約のルールで型の拡張を行っている。この時には、AssertSextもしくはAssertZextノードを挿入する必要がある。このノードは2つのオペランドを持っており、1つは拡張された値そのもの、そしてもう一つは拡張前の値のビットサイズだ。

AssertSext レジスタに保持できる値よりも小さな値を保持している場合に挿入される。オリジナルの値よりも符号拡張された値が格納されていることを示す。 オペランド1: 値そののもの
オペランド2. 符号拡張される前の型
AssertZext レジスタに保持できる値よりも小さな値を保持している場合に挿入される。オリジナルの値よりも符号なし拡張された値が格納されていることを示す。 オペランド1: 値そののもの
オペランド2. 無し拡張される前の型
TRUNCATE 上位ビットを除去する。
  • ch9_1_extend.cpp
int sum_i(short x1, short x2)
{
  int sum = x1 + x2;
  return sum;
}

引数の型がshort(=i16)なのでi32に拡張が行われれ、さらにTRUNCATEが挿入されるはずだ。具体的にDAGを生成してみよう。

./bin/clang -O3 -target mips-unknown-linux-gnu -c ../lbdex/input/ch9_1_extend.cpp -emit-llvm
./bin/llc -view-dag-combine1-dags -march=myriscvx32 -mcpu=simple32 -relocation-model=pic -filetype=asm -target-abi=lp32 ch9_1_extend.bc -o -

DAGをプロットしてみると、以下のようになった。

f:id:msyksphinz:20190627013348p:plain
i32よりも小さな型をレジスタ渡しした場合のDAG

2つの引数について、まずAssertSextが挿入されている。AssertSextの1つ目の分岐には値そのものが接続されており、もう一つの分岐には元の値を示すノードValueType:i16が接続されている。次にtruncateで、上位ビットを削って実際の引数の型を元に戻すノードが挿入されている。