LLVM
https://llvm.org/docs/WritingAnLLVMPass.html LLVMについて、バックエンドの部分はある程度勉強したけど、そういえばPassの作り方をまじめに勉強したことが無かった。 LLVMと言えばPassだろう!ということでPassの作り方について勉強することにした。これ…
https://llvm.org/docs/WritingAnLLVMPass.html LLVMについて、バックエンドの部分はある程度勉強したけど、そういえばPassの作り方をまじめに勉強したことが無かった。 LLVMと言えばPassだろう!ということでPassの作り方について勉強することにした。これ…
https://llvm.org/docs/WritingAnLLVMPass.html LLVMについて、バックエンドの部分はある程度勉強したけど、そういえばPassの作り方をまじめに勉強したことが無かった。 LLVMと言えばPassだろう!ということでPassの作り方について勉強することにした。これ…
https://llvm.org/docs/WritingAnLLVMPass.html LLVMについて、バックエンドの部分はある程度勉強したけど、そういえばPassの作り方をまじめに勉強したことが無かった。 LLVMと言えばPassだろう!ということでPassの作り方について勉強することにした。これ…
LLVMバックエンドの開発で、これまで使用していたrelease/12.xブランチからrelease/13.xに移行したときのAPIの変更点について確認した。 今回はAPIの変更点が少ない。 namespace llvm { // 以下のコードを追加 class formatted_raw_ostream; MCTargetDesc/MY…
MLIRの勉強のために、CIRCTにSystemVerilogの新しいツールを追加してみよう。やり方が分からないので試行錯誤でやってみる。FIRRTLのディレクトリを参考にしながら以下のようにファイルを追加してみる。 Dialect/SV/Import CMakeLists.txt SVAnnotations.cpp…
llvm.org LLVM 10.0がリリースされた。メジャーバージョンアップの頻度が3か月に1回程度となっており追いかけるのも大変だ。 また、メジャーバージョンがアップデートされる度にAPIの仕様が大きく変更されており、プロジェクトを移行させるのも並大抵ではな…
RV64の64ビットモードでLLVMがアセンブラを生成できるように格闘している。とりあえずサンプルプログラムとして以下を用意した。 xlen64_func.cpp int64_t func() { int64_t a0 = 10; int64_t a1 = 20; int64_t ans = a0 + a1; return ans; } いろいろ奮闘し…
RV64の64ビットモードでLLVMがアセンブラを生成できるように格闘している。とりあえずサンプルプログラムとして以下を用意した。 xlen64_func.cpp #include <stdint.h> int64_t func() { return 0x100; } 要点としては、0x100の戻り値をint64_tのデータ型で返せるか、</stdint.h>…
RISC-Vの命令セットは基本的に32ビット長だが、Compresed命令という16ビット長の短縮命令が定義されている。これはArmのThumb命令のようなもので、命令フェッチのサイズを減らし、性能を向上させることを目的としている。 今回はこのCompressed命令をLLVMに…
RISC-Vには32ビットモード(RV32)、64ビットモード(RV64)、128ビットモード(RV128)が定義されている。これまではRV32による32ビットのみをサポートしてきたが、RV64もサポートしたい。具体的に言えば、 RV64モードの時にレジスタ幅を64ビットとして取り扱う(…
比較命令以外にも、浮動小数点の様々な演算をサポートする。例えば、以下のようなものが挙げられる。 SQRT 浮動小数点符号反転 浮動小数点絶対値 符号付整数から浮動小数点への変換、符号なし整数から浮動小数点への変換 浮動小数点から符号付整数への変換、…
RISC-Vには、浮動小数の比較命令命令として以下が定義されている。 funct7 rs2 rs1 funct3 rd opcode FMIN.D 0010101 rs2 rs1 000 rd 1010011 FMAX.D 0010101 rs2 rs1 001 rd 1010011 FEQ.D 1010001 rs2 rs1 010 rd 1010011 FLT.D 1010001 rs2 rs1 001 rd 10…
浮動小数点演算命令を使った算術演算は生成できるようになったが、まだ関数の引数として浮動小数点型を使用することができない。 これは、MYRISCVXのCalling Conventionに、浮動小数点を追加していないからだ。 RISC-VのCalling Conventionでは、浮動小数点…
浮動小数点のロードストア命令が生成できるようになったので、次は簡単な算術演算ができるようにする。とりあえずは、加減乗除、そして積和演算ができるようになりたい。 私たちはすでに命令定義のクラスとテンプレートを持っているので、そこに当てはめるだ…
では、まずは簡単な浮動小数点命令の実装から入る。 演算命令を定義するところから始めてもよいが、そのまえに必ずロードストア命令が必要になるので、ロードストア命令から入る。 RISC-Vでは、単精度浮動小数点用のFLW / FSW、倍精度浮動小数点用のFLD / FS…
前章まででMYRISCVXの整数命令に関してLLVMバックエンドへの実装を進めてきた。 これだけでも随分と完成度が上がってきたが、まだ足りていないものがある。その一つとして、浮動小数点命令のサポートだ。 RISC-Vでは現状では2種類の浮動小数点命令が定義され…
LR/SCを用いたAtomicコードの生成 以下のようなコードを考える。 cpp_atomic.cpp #include <stdint.h> #include <atomic> std::atomic<int32_t> x32; std::atomic<int16_t> x16; std::atomic<int8_t > x8; int32_t test_32() { x32.fetch_add(2); return x32.load(); } int16_t test_16() { x16.fetch_add(</int8_t></int16_t></int32_t></atomic></stdint.h>…
C++ではスレッド機能がサポートされており、ClangでもLLVM IRがサポートされている。例えば、以下のようなコードでIRを出力してみる。 cpp_atomic.cpp #include <stdint.h> #include <atomic> int test_32() { std::atomic<int> x(3); int before = x.fetch_add(2); return x.load()</int></atomic></stdint.h>…
次にコンパイルしたいのは、以下のようなCコードだ。 inline_assembly2.cpp int global_data = 200; void test () { int add_res; int b = 200, c = 300; __asm__ __volatile__("add %0,%1,%2" :"=r"(add_res) :"r"(b), "r"(c) ); int lw_res; int *lw_p = (…
llcにアセンブラをサポートする。具体的には、インラインアセンブリなどのC言語の内部にアセンブラを埋め込む処理をサポートする。これまで、さんざんアセンブリ言語のサポートを追加してきたじゃないか、と思うかもしれないが、インラインアセンブリでのア…
LLVM IRをサポートするためのIntrinsicsのサポート LLVM IRには、いくつかの特殊な構文が存在し、これらをサポートすることでより多くのコードを生成できるようになる。 これらについては、clang側からIntrinsic関数を呼び出すことでLLVM IRを生成し、llcに…
現状、llvm-objdumpを実行すると以下のようになってしまう。これをサポートする。 % ./bin/llvm-objdump -d if_ctrl.o if_ctrl.o: file format ELF32-myriscvx if_ctrl.o': can't find target: : error: unable to get target for 'unknown--', see --versio…
現状、llvm-objdumpを実行すると以下のようになってしまう。これをサポートする。 % ./bin/llvm-objdump -d results/if_ctrl-O0_-march=mips_-relocation-model=static/if_ctrl.bc ./bin/llvm-objdump: error: 'results/if_ctrl-O0_-march=mips_-relocation-…
前回の続き。サンプルプログラムをコンパイルして、どのようなアセンブリ言語が出力されるのか観察する。 vararg.cpp #include <stdarg.h> int sum_i(int amount, ...) { int i = 0; int val = 0; int sum = 0; va_list vl; va_start(vl, amount); for (i = 0; i < amo</stdarg.h>…
C言語の可変長引数では、例えば以下のような記述が可能となる。 vararg.cpp #include <stdarg.h> int sum_i(int amount, ...) { int i = 0; int val = 0; int sum = 0; va_list vl; va_start(vl, amount); for (i = 0; i < amount; i++) { val = va_arg(vl, int); sum </stdarg.h>…
C言語の可変長引数では、例えば以下のような記述が可能となる。 vararg.cpp #include <stdarg.h> int sum_i(int amount, ...) { int i = 0; int val = 0; int sum = 0; va_list vl; va_start(vl, amount); for (i = 0; i < amount; i++) { val = va_arg(vl, int); sum </stdarg.h>…
ByVal属性の値を関数の引数として受け渡す処理の続き。 それでは、次に呼び出し側はどのようになっているのだろうか。呼び出し側でも、ByVal属性のついた引数を一つ一つコピーして関数呼び出され側に渡す必要がある。関数呼び出し側は、MYRISCVXTargetLoweri…
今までの関数処理の中で、引数は基本的にポインタか値渡し、そして値も何らかの型の値を1つずつ渡していくという形式だった。しかし、C言語では構造体などの複数の要素をまとめた型を渡すことができる。また、C言語では構造体の値をそのまま値渡しで引数とし…
最後に、アセンブリの生成です。TAILCALLとTAILCALL_Rは疑似命令なのでそのままではアセンブリ命令を出力することができない。これを置き換える処理は、tdファイルからすでに生成されている。MYRISCVXGenMCPseudoLowering.incを見てみみる。 build-myriscvx/…