Reduces memory usage compiling backend sources, most notably for AMDGPU by ~98 MB per source on average. AMDGPUGenRegisterInfo.inc is tens of megabytes in size now, and is even larger downstream. At the same time, it is included in nearly all backend sources, typically just for a small portion of its content, resulting in compilation being unnecessarily memory-hungry, which in turn stresses buildbots and wastes their resources. Splitting .inc files also helps avoiding extra ccache misses where changes in .td files don't cause changes in all parts of what previously was a single .inc file. It is thought that rather than building on top of the current single-output-file design of TableGen, e.g., using `split-file`, it would be more preferable to recognise the need for multi-file outputs and give it a proper first-class support directly in TableGen.
183 lines
7.6 KiB
TableGen
183 lines
7.6 KiB
TableGen
// This is to test the scenario where different HwMode attributes coexist.
|
|
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o - 2>&1 >/dev/null | FileCheck %s --check-prefix=CHECK-REG
|
|
// RUN: llvm-tblgen -gen-subtarget -I %p/../../include %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SUBTARGET
|
|
|
|
|
|
include "llvm/Target/Target.td"
|
|
|
|
def TestTargetInstrInfo : InstrInfo;
|
|
|
|
def TestTarget : Target {
|
|
let InstructionSet = TestTargetInstrInfo;
|
|
}
|
|
|
|
def Feat1 : SubtargetFeature<"feat1", "HasFeat1", "true", "enable feature 1">;
|
|
def Feat2 : SubtargetFeature<"feat2", "HasFeat2", "true", "enable feature 2">;
|
|
|
|
def HasFeat1 : Predicate<"Subtarget->hasFeat1()">,
|
|
AssemblerPredicate<(all_of Feat1)>;
|
|
def HasFeat2 : Predicate<"Subtarget->hasFeat2()">,
|
|
AssemblerPredicate<(all_of Feat2)>;
|
|
|
|
def TestMode : HwMode<[HasFeat1]>;
|
|
def TestMode1 : HwMode<[HasFeat2]>;
|
|
def TestMode2 : HwMode<[HasFeat1, HasFeat2]>;
|
|
|
|
class MyReg<string n>
|
|
: Register<n> {
|
|
let Namespace = "Test";
|
|
}
|
|
|
|
class MyClass<int size, list<ValueType> types, dag registers>
|
|
: RegisterClass<"Test", types, size, registers> {
|
|
let Size = size;
|
|
}
|
|
|
|
def X0 : MyReg<"x0">;
|
|
def X1 : MyReg<"x1">;
|
|
def X2 : MyReg<"x2">;
|
|
def X3 : MyReg<"x3">;
|
|
def X4 : MyReg<"x4">;
|
|
def X5 : MyReg<"x5">;
|
|
def X6 : MyReg<"x6">;
|
|
def X7 : MyReg<"x7">;
|
|
def X8 : MyReg<"x8">;
|
|
def X9 : MyReg<"x9">;
|
|
def X10 : MyReg<"x10">;
|
|
def X11 : MyReg<"x11">;
|
|
def X12 : MyReg<"x12">;
|
|
def X13 : MyReg<"x13">;
|
|
def X14 : MyReg<"x14">;
|
|
def X15 : MyReg<"x15">;
|
|
|
|
def ValueModeVT : ValueTypeByHwMode<[DefaultMode, TestMode, TestMode1],
|
|
[i32, i64, f32]>;
|
|
|
|
let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode],
|
|
[RegInfo<32,32,32>, RegInfo<64,64,64>]> in
|
|
def XRegs : MyClass<32, [ValueModeVT], (sequence "X%u", 0, 15)>;
|
|
|
|
def sub_even : SubRegIndex<32> {
|
|
let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode],
|
|
[SubRegRange<32>, SubRegRange<64>]>;
|
|
}
|
|
def sub_odd : SubRegIndex<32, 32> {
|
|
let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode],
|
|
[SubRegRange<32, 32>, SubRegRange<64, 64>]>;
|
|
}
|
|
|
|
def XPairs : RegisterTuples<[sub_even, sub_odd],
|
|
[(decimate (rotl XRegs, 0), 2),
|
|
(decimate (rotl XRegs, 1), 2)]>;
|
|
|
|
let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode],
|
|
[RegInfo<64,64,32>, RegInfo<128,128,64>]> in
|
|
def XPairsClass : MyClass<64, [untyped], (add XPairs)>;
|
|
|
|
// Modes who are not controlling Register related features will be manipulated
|
|
// the same as DefaultMode.
|
|
// CHECK-REG-LABEL: RegisterClass XRegs:
|
|
// CHECK-REG: SpillSize: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
|
|
// CHECK-REG: SpillAlignment: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
|
|
// CHECK-REG: Regs: X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
|
|
|
|
// CHECK-REG-LABEL: RegisterClass XPairsClass:
|
|
// CHECK-REG: SpillSize: { Default:64 TestMode:128 TestMode1:64 TestMode2:64 }
|
|
// CHECK-REG: SpillAlignment: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
|
|
// CHECK-REG: CoveredBySubRegs: 1
|
|
// CHECK-REG: Regs: X0_X1 X2_X3 X4_X5 X6_X7 X8_X9 X10_X11 X12_X13 X14_X15
|
|
|
|
// CHECK-REG-LABEL: SubRegIndex sub_even:
|
|
// CHECK-REG: Offset: { Default:0 TestMode:0 TestMode1:0 TestMode2:0 }
|
|
// CHECK-REG: Size: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
|
|
// CHECK-REG-LABEL: SubRegIndex sub_odd:
|
|
// CHECK-REG: Offset: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
|
|
// CHECK-REG: Size: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
|
|
|
|
//============================================================================//
|
|
//--------------------- Encoding/Decoding parts ------------------------------//
|
|
//============================================================================//
|
|
def fooTypeEncDefault : InstructionEncoding {
|
|
let Size = 8;
|
|
field bits<64> SoftFail = 0;
|
|
bits<64> Inst;
|
|
bits<8> factor;
|
|
let Inst{7...0} = factor;
|
|
let Inst{3...2} = 0b10;
|
|
let Inst{1...0} = 0b00;
|
|
}
|
|
|
|
def fooTypeEncA : InstructionEncoding {
|
|
let Size = 4;
|
|
field bits<32> SoftFail = 0;
|
|
bits<32> Inst;
|
|
bits<8> factor;
|
|
let Inst{7...0} = factor;
|
|
let Inst{3...2} = 0b11;
|
|
let Inst{1...0} = 0b00;
|
|
}
|
|
|
|
|
|
def foo : Instruction {
|
|
bits<32> Inst;
|
|
let OutOperandList = (outs);
|
|
let InOperandList = (ins i32imm:$factor);
|
|
let EncodingInfos = EncodingByHwMode<
|
|
[TestMode2, DefaultMode], [fooTypeEncA, fooTypeEncDefault]
|
|
>;
|
|
let AsmString = "foo $factor";
|
|
}
|
|
|
|
// CHECK-SUBTARGET-LABEL: unsigned TestTargetGenMCSubtargetInfo::getHwModeSet() const {
|
|
// CHECK-SUBTARGET{LITERAL}:[[maybe_unused]] const FeatureBitset &FB = getFeatureBits();
|
|
// CHECK-SUBTARGET-NEXT: // Collect HwModes and store them as a bit set.
|
|
// CHECK-SUBTARGET-NEXT: unsigned Modes = 0;
|
|
// CHECK-SUBTARGET-NEXT: if (FB[TestTarget::Feat1]) Modes |= (1 << 0);
|
|
// CHECK-SUBTARGET-NEXT: if (FB[TestTarget::Feat2]) Modes |= (1 << 1);
|
|
// CHECK-SUBTARGET-NEXT: if (FB[TestTarget::Feat1] && FB[TestTarget::Feat2]) Modes |= (1 << 2);
|
|
// CHECK-SUBTARGET-NEXT: return Modes;
|
|
// CHECK-SUBTARGET-NEXT: }
|
|
|
|
// CHECK-SUBTARGET-LABEL: unsigned TestTargetGenSubtargetInfo::getHwModeSet() const {
|
|
// CHECK-SUBTARGET{LITERAL}:[[maybe_unused]] const auto *Subtarget =
|
|
// CHECK-SUBTARGET-NEXT: static_cast<const TestTargetSubtarget *>(this);
|
|
// CHECK-SUBTARGET-NEXT: // Collect HwModes and store them as a bit set.
|
|
// CHECK-SUBTARGET-NEXT: unsigned Modes = 0;
|
|
// CHECK-SUBTARGET-NEXT: if ((Subtarget->hasFeat1())) Modes |= (1 << 0);
|
|
// CHECK-SUBTARGET-NEXT: if ((Subtarget->hasFeat2())) Modes |= (1 << 1);
|
|
// CHECK-SUBTARGET-NEXT: if ((Subtarget->hasFeat1()) && (Subtarget->hasFeat2())) Modes |= (1 << 2);
|
|
// CHECK-SUBTARGET-NEXT: return Modes;
|
|
// CHECK-SUBTARGET-NEXT: }
|
|
// CHECK-SUBTARGET-LABEL: unsigned TestTargetGenSubtargetInfo::getHwMode(enum HwModeType type) const {
|
|
// CHECK-SUBTARGET: unsigned Modes = getHwModeSet();
|
|
// CHECK-SUBTARGET: if (!Modes)
|
|
// CHECK-SUBTARGET: return Modes;
|
|
// CHECK-SUBTARGET: switch (type) {
|
|
// CHECK-SUBTARGET: case HwMode_Default:
|
|
// CHECK-SUBTARGET: return llvm::countr_zero(Modes) + 1;
|
|
// CHECK-SUBTARGET: case HwMode_ValueType:
|
|
// CHECK-SUBTARGET: Modes &= 3;
|
|
// CHECK-SUBTARGET: if (!Modes)
|
|
// CHECK-SUBTARGET: return Modes;
|
|
// CHECK-SUBTARGET: if (!llvm::has_single_bit<unsigned>(Modes))
|
|
// CHECK-SUBTARGET: llvm_unreachable("Two or more HwModes for ValueType were found!");
|
|
// CHECK-SUBTARGET: return llvm::countr_zero(Modes) + 1;
|
|
// CHECK-SUBTARGET: case HwMode_RegInfo:
|
|
// CHECK-SUBTARGET: Modes &= 1;
|
|
// CHECK-SUBTARGET: if (!Modes)
|
|
// CHECK-SUBTARGET: return Modes;
|
|
// CHECK-SUBTARGET: if (!llvm::has_single_bit<unsigned>(Modes))
|
|
// CHECK-SUBTARGET: llvm_unreachable("Two or more HwModes for RegInfo were found!");
|
|
// CHECK-SUBTARGET: return llvm::countr_zero(Modes) + 1;
|
|
// CHECK-SUBTARGET: case HwMode_EncodingInfo:
|
|
// CHECK-SUBTARGET: Modes &= 4;
|
|
// CHECK-SUBTARGET: if (!Modes)
|
|
// CHECK-SUBTARGET: return Modes;
|
|
// CHECK-SUBTARGET: if (!llvm::has_single_bit<unsigned>(Modes))
|
|
// CHECK-SUBTARGET: llvm_unreachable("Two or more HwModes for EncodingInfo were found!");
|
|
// CHECK-SUBTARGET: return llvm::countr_zero(Modes) + 1;
|
|
// CHECK-SUBTARGET: }
|
|
// CHECK-SUBTARGET: llvm_unreachable("unexpected HwModeType");
|
|
// CHECK-SUBTARGET: return 0; // should not get here
|
|
// CHECK-SUBTARGET: }
|