In comments in generated files and in -register-info-debug output, use the standard name "DefaultMode" for consistency, instead of hard coding an alternative name "Default".
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: { DefaultMode:32 TestMode:64 TestMode1:32 TestMode2:32 }
|
|
// CHECK-REG: SpillAlignment: { DefaultMode: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: { DefaultMode:64 TestMode:128 TestMode1:64 TestMode2:64 }
|
|
// CHECK-REG: SpillAlignment: { DefaultMode: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: { DefaultMode:0 TestMode:0 TestMode1:0 TestMode2:0 }
|
|
// CHECK-REG: Size: { DefaultMode:32 TestMode:64 TestMode1:32 TestMode2:32 }
|
|
// CHECK-REG-LABEL: SubRegIndex sub_odd:
|
|
// CHECK-REG: Offset: { DefaultMode:32 TestMode:64 TestMode1:32 TestMode2:32 }
|
|
// CHECK-REG: Size: { DefaultMode: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: }
|