
前回に引き続きLLVMのバックエンドを作るために必要なファイルを読み解いていく。
MYRISCVXSubTarget.{h,cpp}
サブターゲットはMYRISCVXの中でもアーキテクチャのバリエーションを付けるために使用されるもので、その名の通りサブのターゲットだ。
llcにおいてアーキテクチャは-march=myriscvx32で指定するが、サブターゲットは-mcpu=で指定する。
例えば、同じMIPSアーキテクチャの中でも、ISAのバージョン違いや実装の違いによってさまざまなバリエーションがある。
lib/Target/Mips/Mips.td
def FeatureNoABICalls : SubtargetFeature<"noabicalls", "NoABICalls", "true",
"Disable SVR4-style position-independent code">;
def FeaturePTR64Bit : SubtargetFeature<"ptr64", "IsPTR64bit", "true",
"Pointers are 64-bit wide">;
def FeatureGP64Bit : SubtargetFeature<"gp64", "IsGP64bit", "true",
"General Purpose Registers are 64-bit wide">;
def FeatureFP64Bit : SubtargetFeature<"fp64", "IsFP64bit", "true",
"Support 64-bit FP registers">;
...
./bin/llc -march=mips -mcpu=help ... Available features for this target: mips1 - Mips I ISA Support [highly experimental]. mips16 - Mips16 mode. mips2 - Mips II ISA Support [highly experimental]. mips3 - MIPS III ISA Support [highly experimental]. mips32 - Mips32 ISA Support. ... noabicalls - Disable SVR4-style position-independent code. ...
このサブターゲットを定義するためのクラスMYRISCVXSubTargetはMYRISCVX.tdから生成された自動生成クラスMYRISCVXGenSubtargetInfoから生成される。
RISC-Vの場合、アーキテクチャに大きなバリエーションがある訳ではないのだが、ISAのどのモジュールが使用できるのか、例えば乗除算命令は使用できるのか、Compressed命令は使用できるのか、浮動小数点命令は使用できるのかなどのバリエーションが作れそうだ。
lib/Target/MYRISCVX/MYRISCVXSubtarget.h
class MYRISCVXSubtarget : public MYRISCVXGenSubtargetInfo { ... protected: bool is_enable_M = false; bool is_enable_A = false; bool is_enable_F = false; bool is_enable_D = false; ...
lib/Target/MYRISCVX/MYRISCVXSubtarget.cpp
MYRISCVXSubtarget &
MYRISCVXSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS,
const TargetMachine &TM) {
if (TargetTriple.getArch() == Triple::myriscvx32) {
if (CPU.empty() || CPU == "generic") {
CPU = "cpu-rv32";
}
} else if (TargetTriple.getArch() == Triple::myriscvx64) {
if (CPU.empty() || CPU == "generic") {
CPU = "cpu-rv64";
}
} else {
errs() << "!!!Error, TargetTriple.getArch() = " << TargetTriple.getArch()
<< "CPU = " << CPU << "\n";
exit(0);
}
// Parse features string.
ParseSubtargetFeatures(CPU, FS);
// Initialize scheduling itinerary for the specified CPU.
InstrItins = getInstrItineraryForCPU(CPU);
return *this;
}
このSubtargetFeatureではアーキテクチャのバリエーションを指定するので、今回は32ビットモードと64ビットモードのサブターゲットを追加してみる。
デフォルトでは32ビットで、オプションで64ビットに設定されるようにする。
lib/Target/MYRISCVX/MYRISCVX.td
//===----------------------------------------------------------------------===// // MYRISCVX subtarget features and instruction predicates. //===----------------------------------------------------------------------===// def FeatureRV64 : SubtargetFeature<"64bit", "HasRV64", "true", "RV64 support">;
サブターゲットの記述には要素が4つ並んでいる。
- Featureの名前
- Featureの属性(実装時に追加される変数の名前)
- Featureの値(属性に設定される値)
- Featureの説明。
この記述を加えることによって、tdファイルから生成されるMYRISCVXGenSubtargetInfo.incにはSubtargetFeatureに基づく変数制御が追加される。
lib/Target/MYRISCVX/MYRISCVXGenSubtargetInfo.inc
// Sorted (by key) array of values for CPU features. extern const llvm::SubtargetFeatureKV MYRISCVXFeatureKV[] = { { "64bit", "RV64 support", { MYRISCVX::FeatureRV64 }, { } }, }; // Sorted (by key) array of values for CPU subtype. extern const llvm::SubtargetFeatureKV MYRISCVXSubTypeKV[] = { { "cpu-rv32", "Select the cpu-rv32 processor", { }, { } }, { "cpu-rv64", "Select the cpu-rv64 processor", { MYRISCVX::FeatureRV64 }, { } }, }; ... // ParseSubtargetFeatures - Parses features string setting specified // subtarget options. void llvm::MYRISCVXSubtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) { LLVM_DEBUG(dbgs() << "\nFeatures:" << FS); LLVM_DEBUG(dbgs() << "\nCPU:" << CPU << "\n\n"); InitMCProcessorInfo(CPU, FS); const FeatureBitset& Bits = getFeatureBits(); if (Bits[MYRISCVX::FeatureRV64]) HasRV64 = true; }
したがって、MYRISCVXSubtargetクラスにはメンバ変数HasRV64を追加する必要がある。
lib/Target/MYRISCVX/MYRISCVXSubtarget.h
class MYRISCVXSubtarget : public MYRISCVXGenSubtargetInfo { ... bool HasRV64 = false;