Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions llvm/include/llvm/Target/Target.td
Original file line number Diff line number Diff line change
Expand Up @@ -1078,6 +1078,16 @@ class RegisterOperand<RegisterClassLike regclass, string pm = "printOperand">
Register GIZeroRegister = ?;
}

/// RegisterByHwMode - Useful for InstAliases with a hardcoded register operand
/// where the operand type is a RegClassByHwMode.
class RegisterByHwMode<RegisterClassLike RegClass, list<HwMode> Modes,
list<Register> Registers>
: HwModeSelect<Modes, !size(Registers)>, RegisterOperand<RegClass> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it need RegisterClassLike?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So that the type of the register can be a RegClassByHwMode instead of just a fixed RegisterClass. I need this in the RVY changes since I need to use a PtrRC that is either the normal GPR register class (RVI mode) or the extended YGPR class (RVY mode).

list<Register> Objects = Registers;
// Note: No assertions to validate the registers against the
// register class here, this is done inside llvm-tblgen.
}

let OperandType = "OPERAND_IMMEDIATE" in {
def i1imm : Operand<i1>;
def i8imm : Operand<i8>;
Expand Down
92 changes: 92 additions & 0 deletions llvm/test/TableGen/Common/RegisterByHwModeCommon.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
include "llvm/Target/Target.td"

/// A minimal reduced version of the RISC-V RVY register variants where pointers
/// use either Xn or Xn_Y registers depending on CapMode and 64-bit predicates.
/// Define HWModes for the full cross-product here since we can only match one
/// HWMode at any given time.
def Is32Bit : Predicate<"!Subtarget->is64Bit()">;
def Is64Bit : Predicate<"Subtarget->is64Bit()">;
def UseYRegForPtr : Predicate<"Subtarget->useYRegForPtr()">;
def UseXRegForPtr : Predicate<"!Subtarget->useYRegForPtr()">;
defvar XPtr32 = DefaultMode;
def XPtr64 : HwMode<[Is64Bit, UseXRegForPtr]>;
def YPtr32 : HwMode<[Is32Bit, UseYRegForPtr]>;
def YPtr64 : HwMode<[Is64Bit, UseYRegForPtr]>;

class MyReg<string n> : Register<n> {
let Namespace = "MyTarget";
}

def X0 : MyReg<"x0">;
def X1 : MyReg<"x1">;
def X2 : MyReg<"x2">;
def X3 : MyReg<"x3">;

def Y0 : MyReg<"y0">;
def Y1 : MyReg<"y1">;
def Y2 : MyReg<"y2">;
def Y3 : MyReg<"y3">;

def XLenVT : ValueTypeByHwMode<[XPtr32, XPtr64, YPtr32, YPtr64],
[i32, i64, i32, i64]>;
def YLenVT : ValueTypeByHwMode<[XPtr32, XPtr64, YPtr32, YPtr64],
[c64, c128, c64, c128]>;
def PtrVT : ValueTypeByHwMode<[XPtr32, XPtr64, YPtr32, YPtr64],
[XLenVT, XLenVT, YLenVT, YLenVT]>;
defvar RegInfo32 = RegInfo<32,32,32>;
defvar RegInfo64 = RegInfo<64,64,64>;
def XLenRI : RegInfoByHwMode<[XPtr32, XPtr64, YPtr32, YPtr64],
[RegInfo32, RegInfo32, RegInfo64, RegInfo64]>;
def XRegs : RegisterClass<"MyTarget", [XLenVT], 32, (add X0, X1, X2, X3)> {
let RegInfos = XLenRI; // Needed to determine size of registers
}
defvar RegInfo128 = RegInfo<128,128,128>;
def YLenRI : RegInfoByHwMode<[XPtr32, XPtr64, YPtr32, YPtr64],
[RegInfo64, RegInfo64, RegInfo128, RegInfo128]>;

def YRegs : RegisterClass<"MyTarget", [YLenVT], 64, (add Y0, Y1, Y2, Y3)> {
let RegInfos = YLenRI; // Needed to determine size of registers
}
def PtrRC : RegClassByHwMode<[XPtr32, XPtr64, YPtr32, YPtr64],
[XRegs, XRegs, YRegs, YRegs]>;

def PtrRegOperand : RegisterOperand<PtrRC>;

def NullReg : RegisterByHwMode<PtrRC, [XPtr32, XPtr64, YPtr32, YPtr64],
[X0, X0, Y0, Y0]>;

class TestInstruction : Instruction {
let Size = 2;
let Namespace = "MyTarget";
let hasSideEffects = false;
let hasExtraSrcRegAllocReq = false;
let hasExtraDefRegAllocReq = false;

field bits<16> Inst;
bits<3> dst;
bits<3> src;
bits<3> opcode;

let Inst{2-0} = dst;
let Inst{5-3} = src;
let Inst{7-5} = opcode;
}

def TEST_XREG : TestInstruction {
let OutOperandList = (outs XRegs:$dst);
let InOperandList = (ins XRegs:$src);
let AsmString = "test_x $dst, $src";
let opcode = 0;
}
def TEST_YREG : TestInstruction {
let OutOperandList = (outs YRegs:$dst);
let InOperandList = (ins YRegs:$src);
let AsmString = "test_y $dst, $src";
let opcode = 1;
}
def TEST_PTRREG : TestInstruction {
let OutOperandList = (outs PtrRegOperand:$dst);
let InOperandList = (ins PtrRegOperand:$src);
let AsmString = "test_ptr $dst, $src";
let opcode = 2;
}
34 changes: 28 additions & 6 deletions llvm/test/TableGen/RegClassByHwModeAlias.td
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def EvenXRegs : RegisterClass<"MyTarget", [i64], 64, (add X0, X2, X4, X6)>;
def EvenYRegs : RegisterClass<"MyTarget", [i64], 64, (add Y0, Y2, Y4, Y6)>;
def PtrRC : RegClassByHwMode<[PtrX, PtrY], [XRegs, YRegs]>;
def EvenPtrRC : RegClassByHwMode<[PtrX, PtrY], [EvenXRegs, EvenYRegs]>;
def NullReg : RegisterByHwMode<PtrRC, [PtrX, PtrY], [X0, Y0]>;

def TEST_XREG : TestInstruction {
let OutOperandList = (outs XRegs:$dst);
Expand All @@ -28,21 +29,42 @@ def TEST_PTR : TestInstruction {
def MY_T_X : InstAlias<"t_x $src", (TEST_XREG X0, XRegs:$src)>;
def MY_T_X_EVEN : InstAlias<"t_x.even $src", (TEST_XREG EvenXRegs:$dst, EvenXRegs:$src)>;

// TODO: Can't use a fixed register for this instruction, would need RegisterByHwMode.
// def MY_T_PTR : InstAlias<"t_ptr $src", (TEST_PTR X0, XRegs:$src)>;
def MY_T_PTR : InstAlias<"t_ptr $src", (TEST_PTR NullReg, PtrRC:$src)>;
def MY_T_PTR_EVEN : InstAlias<"t_ptr.even $src", (TEST_PTR EvenPtrRC:$dst, EvenPtrRC:$src)>;

// CHECK-LABEL: static const AliasPatternCond Conds[] = {
// CHECK-NEXT: // (TEST_PTR EvenPtrRC:$dst, EvenPtrRC:$src) - 0
// CHECK-NEXT: // (TEST_PTR NullReg, PtrRC:$src) - 0
// CHECK-NEXT: {AliasPatternCond::K_Custom, 1/*NullReg*/},
// CHECK-NEXT: {AliasPatternCond::K_RegClassByHwMode, MyTarget::PtrRC},
// CHECK-NEXT: // (TEST_PTR EvenPtrRC:$dst, EvenPtrRC:$src) - 2
// CHECK-NEXT: {AliasPatternCond::K_RegClassByHwMode, MyTarget::EvenPtrRC},
// CHECK-NEXT: {AliasPatternCond::K_RegClassByHwMode, MyTarget::EvenPtrRC},
// CHECK-NEXT: // (TEST_XREG X0, XRegs:$src) - 2
// CHECK-NEXT: // (TEST_XREG X0, XRegs:$src) - 4
// CHECK-NEXT: {AliasPatternCond::K_Reg, MyTarget::X0},
// CHECK-NEXT: {AliasPatternCond::K_RegClass, MyTarget::XRegsRegClassID},
// CHECK-NEXT: // (TEST_XREG EvenXRegs:$dst, EvenXRegs:$src) - 4
// CHECK-NEXT: // (TEST_XREG EvenXRegs:$dst, EvenXRegs:$src) - 6
// CHECK-NEXT: {AliasPatternCond::K_RegClass, MyTarget::EvenXRegsRegClassID},
// CHECK-NEXT: {AliasPatternCond::K_RegClass, MyTarget::EvenXRegsRegClassID},
// CHECK-NEXT: };

// CHECK-LABEL: static bool MyTargetInstPrinterValidateMCOperand(const MCOperand &MCOp,
// CHECK-NEXT: const MCSubtargetInfo &STI,
// CHECK-NEXT: unsigned PredicateIndex) {
// CHECK-NEXT: switch (PredicateIndex) {
// CHECK-NEXT: default:
// CHECK-NEXT: llvm_unreachable("Unknown MCOperandPredicate kind");
// CHECK-NEXT: break;
// CHECK-NEXT: case 1: {
// CHECK-NEXT: return MCOp.isReg() && MCOp.getReg() == MyTarget::RegisterByHwMode::getNullReg(STI.getHwMode(MCSubtargetInfo::HwMode_RegInfo));
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }

def MyTargetISA : InstrInfo;
def MyTarget : Target { let InstructionSet = MyTargetISA; }
def MyTargetAsmWriter : AsmWriter {
int PassSubtarget = 1;
}
def MyTarget : Target {
let InstructionSet = MyTargetISA;
let AssemblyWriters = [MyTargetAsmWriter];
}
40 changes: 36 additions & 4 deletions llvm/test/TableGen/RegClassByHwModeCompressPat.td
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def IsPtr64 : Predicate<"Subtarget->isPtr64()">;
defvar Ptr32 = DefaultMode;
def Ptr64 : HwMode<[IsPtr64]>;
def PtrRC : RegClassByHwMode<[Ptr32, Ptr64], [XRegs, YRegs]>;

def NullReg : RegisterByHwMode<PtrRC, [Ptr32, Ptr64], [X0, Y0]>;

def X_MOV : TestInstruction {
let OutOperandList = (outs XRegs:$dst);
Expand Down Expand Up @@ -74,9 +74,8 @@ def : CompressPat<(X_MOV XRegs:$dst, XRegs:$dst),
(X_MOV_TIED XRegs:$dst)>;
def : CompressPat<(X_MOV XRegs:$dst, XRegs:$src),
(X_MOV_SMALL XRegs:$dst, XRegs:$src)>;
// TODO: Should also be able to use a fixed register with RegClassByHwMode
// def : CompressPat<(PTR_MOV PtrRC:$dst, X0),
// (PTR_MOV_ZERO PtrRC:$dst)>;
def : CompressPat<(PTR_MOV PtrRC:$dst, NullReg),
(PTR_MOV_ZERO PtrRC:$dst)>;
def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$dst),
(PTR_MOV_TIED PtrRC:$dst)>;
def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$src),
Expand All @@ -89,6 +88,17 @@ def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$src),
// CHECK-NEXT: switch (MI.getOpcode()) {
// CHECK-NEXT: default: return false;
// CHECK-NEXT: case MyTarget::PTR_MOV: {
// CHECK-NEXT: if (MI.getOperand(1).isReg() &&
// CHECK-NEXT: (MI.getOperand(1).getReg() == MyTarget::RegisterByHwMode::getNullReg(HwModeId)) &&
// CHECK-NEXT: MI.getOperand(0).isReg() &&
// CHECK-NEXT: MyTargetMCRegisterClasses[MyTargetRegClassByHwModeTables[HwModeId][MyTarget::PtrRC]].contains(MI.getOperand(0).getReg())) {
// CHECK-NEXT: // ptr_mov.zero $dst
// CHECK-NEXT: OutInst.setOpcode(MyTarget::PTR_MOV_ZERO);
// CHECK-NEXT: // Operand: dst
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0));
// CHECK-NEXT: OutInst.setLoc(MI.getLoc());
// CHECK-NEXT: return true;
// CHECK-NEXT: } // if
// CHECK-NEXT: if (MI.getOperand(1).isReg() && MI.getOperand(0).isReg() &&
// CHECK-NEXT: (MI.getOperand(1).getReg() == MI.getOperand(0).getReg()) &&
// CHECK-NEXT: MI.getOperand(1).isReg() &&
Expand Down Expand Up @@ -199,6 +209,20 @@ def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$src),
// CHECK-NEXT: } // if
// CHECK-NEXT: break;
// CHECK-NEXT: } // case PTR_MOV_TIED
// CHECK-NEXT: case MyTarget::PTR_MOV_ZERO: {
// CHECK-NEXT: if (MI.getOperand(0).isReg() &&
// CHECK-NEXT: MyTargetMCRegisterClasses[MyTargetRegClassByHwModeTables[HwModeId][MyTarget::PtrRC]].contains(MI.getOperand(0).getReg())) {
// CHECK-NEXT: // ptr_mov $dst, $src
// CHECK-NEXT: OutInst.setOpcode(MyTarget::PTR_MOV);
// CHECK-NEXT: // Operand: dst
// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0));
// CHECK-NEXT: // Operand: src
// CHECK-NEXT: OutInst.addOperand(MCOperand::createReg(MyTarget::RegisterByHwMode::getNullReg(HwModeId)));
// CHECK-NEXT: OutInst.setLoc(MI.getLoc());
// CHECK-NEXT: return true;
// CHECK-NEXT: } // if
// CHECK-NEXT: break;
// CHECK-NEXT: } // case PTR_MOV_ZERO
// CHECK-NEXT: case MyTarget::X_MOV_SMALL: {
// CHECK-NEXT: if (MI.getOperand(0).isReg() &&
// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg()) &&
Expand Down Expand Up @@ -273,6 +297,14 @@ def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$src),
// CHECK-NEXT: // Operand: src
// CHECK-NEXT: return true;
// CHECK-NEXT: } // if
// CHECK-NEXT: if (MI.getOperand(1).isReg() &&
// CHECK-NEXT: (MI.getOperand(1).getReg() == MyTarget::RegisterByHwMode::getNullReg(HwModeId)) &&
// CHECK-NEXT: MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() &&
// CHECK-NEXT: MyTargetMCRegisterClasses[MyTargetRegClassByHwModeTables[HwModeId][MyTarget::PtrRC]].contains(MI.getOperand(0).getReg())) {
// CHECK-NEXT: // ptr_mov.zero $dst
// CHECK-NEXT: // Operand: dst
// CHECK-NEXT: return true;
// CHECK-NEXT: } // if
// CHECK-NEXT: break;
// CHECK-NEXT: } // case PTR_MOV
// CHECK-NEXT: case MyTarget::X_MOV: {
Expand Down
3 changes: 1 addition & 2 deletions llvm/test/TableGen/RegClassByHwModeErrors.td
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ def PTR_ZERO_SMALL : TestInstruction {
/// This should fail since X0 is not necessarily part of PtrRC.
def : CompressPat<(PTR_MOV PtrRC:$dst, X0),
(PTR_ZERO_SMALL PtrRC:$dst)>;
// CHECK: [[#@LINE-2]]:1: error: cannot resolve HwMode for PtrRC
// CHECK: Common.td:7:5: note: PtrRC defined here
// CHECK: [[#@LINE-2]]:1: error: Error in Dag '(PTR_MOV PtrRC:$dst, X0)': Register 'X0' is not in register class 'PtrRC'
def MyTargetISA : InstrInfo;
def MyTarget : Target { let InstructionSet = MyTargetISA; }

Expand Down
Loading