// 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 /dev/null 2>&1 | 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 TestMode : HwMode<"+feat", []>; def TestMode1 : HwMode<"+feat1", []>; def TestMode2 : HwMode<"+feat2", []>; class MyReg : Register { let Namespace = "Test"; } class MyClass 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 TestTargetGenSubtargetInfo::getHwModeSet() const { // CHECK-SUBTARGET: unsigned Modes = 0; // CHECK-SUBTARGET: if (checkFeatures("+feat")) Modes |= (1 << 0); // CHECK-SUBTARGET: if (checkFeatures("+feat1")) Modes |= (1 << 1); // CHECK-SUBTARGET: if (checkFeatures("+feat2")) Modes |= (1 << 2); // CHECK-SUBTARGET: return Modes; // CHECK-SUBTARGET: } // 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(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(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(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: }