diff --git a/llvm/test/TableGen/RegClassByHwModeCompressPat.td b/llvm/test/TableGen/RegClassByHwModeCompressPat.td new file mode 100644 index 0000000000000..263b53f6fbba5 --- /dev/null +++ b/llvm/test/TableGen/RegClassByHwModeCompressPat.td @@ -0,0 +1,315 @@ +// RUN: llvm-tblgen --gen-compress-inst-emitter -I %p/../../include -I %S %s -o - | FileCheck %s + +include "Common/RegClassByHwModeCommon.td" + +def IsPtr64 : Predicate<"Subtarget->isPtr64()">; +defvar Ptr32 = DefaultMode; +def Ptr64 : HwMode<[IsPtr64]>; +def PtrRC : RegClassByHwMode<[Ptr32, Ptr64], [XRegs, YRegs]>; + + +def X_MOV : TestInstruction { + let OutOperandList = (outs XRegs:$dst); + let InOperandList = (ins XRegs:$src); + let AsmString = "x_mov $dst, $src"; + let opcode = 0; +} + +def X_MOV_SMALL : TestInstruction { + let OutOperandList = (outs XRegs:$dst); + let InOperandList = (ins XRegs:$src); + let AsmString = "x_mov.small $dst, $src"; + let opcode = 1; + let Size = 1; +} +def X_MOV_ZERO : TestInstruction { + let OutOperandList = (outs XRegs:$dst); + let InOperandList = (ins); + let AsmString = "x_mov.zero $dst"; + let opcode = 2; + let Size = 1; +} +def X_MOV_TIED : TestInstruction { + let OutOperandList = (outs XRegs:$dst); + let InOperandList = (ins XRegs:$src); + let Constraints = "$src = $dst"; + let AsmString = "x_mov.tied $dst, $src"; + let opcode = 3; + let Size = 1; +} + +def PTR_MOV : TestInstruction { + let OutOperandList = (outs PtrRC:$dst); + let InOperandList = (ins PtrRC:$src); + let AsmString = "ptr_mov $dst, $src"; + let opcode = 3; +} + +def PTR_MOV_SMALL : TestInstruction { + let OutOperandList = (outs PtrRC:$dst); + let InOperandList = (ins PtrRC:$src); + let AsmString = "ptr_mov.small $dst, $src"; + let opcode = 4; + let Size = 1; +} +def PTR_MOV_ZERO : TestInstruction { + let OutOperandList = (outs PtrRC:$dst); + let InOperandList = (ins); + let AsmString = "ptr_mov.zero $dst"; + let opcode = 3; + let Size = 1; +} +def PTR_MOV_TIED : TestInstruction { + let OutOperandList = (outs PtrRC:$dst); + let InOperandList = (ins PtrRC:$src); + let Constraints = "$src = $dst"; + let AsmString = "ptr_mov.tied $dst, $src"; + let opcode = 3; + let Size = 1; +} + +def : CompressPat<(X_MOV XRegs:$dst, X0), + (X_MOV_ZERO XRegs:$dst)>; +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, PtrRC:$dst), + (PTR_MOV_TIED PtrRC:$dst)>; +def : CompressPat<(PTR_MOV PtrRC:$dst, PtrRC:$src), + (PTR_MOV_SMALL PtrRC:$dst, PtrRC:$src)>; + +// CHECK: static bool compressInst(MCInst &OutInst, +// CHECK-NEXT: const MCInst &MI, +// CHECK-NEXT: const MCSubtargetInfo &STI) { +// CHECK-NEXT: switch (MI.getOpcode()) { +// CHECK-NEXT: default: return false; +// CHECK-NEXT: case MyTarget::PTR_MOV: { +// 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() && +// CHECK-NEXT: MyTargetMCRegisterClasses[STI.getInstrInfo().getOpRegClassID(MI.getDesc().operands()[1])].contains(MI.getOperand(1).getReg())) { +// CHECK-NEXT: // ptr_mov.tied $dst, $src +// CHECK-NEXT: OutInst.setOpcode(MyTarget::PTR_MOV_TIED); +// CHECK-NEXT: // Operand: dst +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); +// CHECK-NEXT: // Operand: src +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); +// CHECK-NEXT: OutInst.setLoc(MI.getLoc()); +// CHECK-NEXT: return true; +// CHECK-NEXT: } // if +// CHECK-NEXT: if (MI.getOperand(0).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[STI.getInstrInfo().getOpRegClassID(MI.getDesc().operands()[0])].contains(MI.getOperand(0).getReg()) && +// CHECK-NEXT: MI.getOperand(1).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[STI.getInstrInfo().getOpRegClassID(MI.getDesc().operands()[1])].contains(MI.getOperand(1).getReg())) { +// CHECK-NEXT: // ptr_mov.small $dst, $src +// CHECK-NEXT: OutInst.setOpcode(MyTarget::PTR_MOV_SMALL); +// CHECK-NEXT: // Operand: dst +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); +// CHECK-NEXT: // Operand: src +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); +// CHECK-NEXT: OutInst.setLoc(MI.getLoc()); +// CHECK-NEXT: return true; +// CHECK-NEXT: } // if +// CHECK-NEXT: break; +// CHECK-NEXT: } // case PTR_MOV +// CHECK-NEXT: case MyTarget::X_MOV: { +// CHECK-NEXT: if (MI.getOperand(1).isReg() && +// CHECK-NEXT: (MI.getOperand(1).getReg() == MyTarget::X0) && +// CHECK-NEXT: MI.getOperand(0).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg())) { +// CHECK-NEXT: // x_mov.zero $dst +// CHECK-NEXT: OutInst.setOpcode(MyTarget::X_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() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(1).getReg())) { +// CHECK-NEXT: // x_mov.tied $dst, $src +// CHECK-NEXT: OutInst.setOpcode(MyTarget::X_MOV_TIED); +// CHECK-NEXT: // Operand: dst +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); +// CHECK-NEXT: // Operand: src +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); +// CHECK-NEXT: OutInst.setLoc(MI.getLoc()); +// CHECK-NEXT: return true; +// CHECK-NEXT: } // if +// CHECK-NEXT: if (MI.getOperand(0).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg()) && +// CHECK-NEXT: MI.getOperand(1).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(1).getReg())) { +// CHECK-NEXT: // x_mov.small $dst, $src +// CHECK-NEXT: OutInst.setOpcode(MyTarget::X_MOV_SMALL); +// CHECK-NEXT: // Operand: dst +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); +// CHECK-NEXT: // Operand: src +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); +// CHECK-NEXT: OutInst.setLoc(MI.getLoc()); +// CHECK-NEXT: return true; +// CHECK-NEXT: } // if +// CHECK-NEXT: break; +// CHECK-NEXT: } // case X_MOV +// CHECK-NEXT: } // switch +// CHECK-NEXT: return false; +// CHECK-NEXT: } + +// CHECK: static bool uncompressInst(MCInst &OutInst, +// CHECK-NEXT: const MCInst &MI, +// CHECK-NEXT: const MCSubtargetInfo &STI) { +// CHECK-NEXT: switch (MI.getOpcode()) { +// CHECK-NEXT: default: return false; +// CHECK-NEXT: case MyTarget::PTR_MOV_SMALL: { +// CHECK-NEXT: if (MI.getOperand(0).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[STI.getInstrInfo().getOpRegClassID(MI.getDesc().operands()[0])].contains(MI.getOperand(0).getReg()) && +// CHECK-NEXT: MI.getOperand(1).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[STI.getInstrInfo().getOpRegClassID(MI.getDesc().operands()[1])].contains(MI.getOperand(1).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(MI.getOperand(1)); +// CHECK-NEXT: OutInst.setLoc(MI.getLoc()); +// CHECK-NEXT: return true; +// CHECK-NEXT: } // if +// CHECK-NEXT: break; +// CHECK-NEXT: } // case PTR_MOV_SMALL +// CHECK-NEXT: case MyTarget::PTR_MOV_TIED: { +// CHECK-NEXT: if (MI.getOperand(0).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[STI.getInstrInfo().getOpRegClassID(MI.getDesc().operands()[0])].contains(MI.getOperand(0).getReg()) && +// CHECK-NEXT: MI.getOperand(0).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[STI.getInstrInfo().getOpRegClassID(MI.getDesc().operands()[0])].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(MI.getOperand(0)); +// CHECK-NEXT: OutInst.setLoc(MI.getLoc()); +// CHECK-NEXT: return true; +// CHECK-NEXT: } // if +// CHECK-NEXT: break; +// CHECK-NEXT: } // case PTR_MOV_TIED +// CHECK-NEXT: case MyTarget::X_MOV_SMALL: { +// CHECK-NEXT: if (MI.getOperand(0).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg()) && +// CHECK-NEXT: MI.getOperand(1).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(1).getReg())) { +// CHECK-NEXT: // x_mov $dst, $src +// CHECK-NEXT: OutInst.setOpcode(MyTarget::X_MOV); +// CHECK-NEXT: // Operand: dst +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); +// CHECK-NEXT: // Operand: src +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(1)); +// CHECK-NEXT: OutInst.setLoc(MI.getLoc()); +// CHECK-NEXT: return true; +// CHECK-NEXT: } // if +// CHECK-NEXT: break; +// CHECK-NEXT: } // case X_MOV_SMALL +// CHECK-NEXT: case MyTarget::X_MOV_TIED: { +// CHECK-NEXT: if (MI.getOperand(0).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg()) && +// CHECK-NEXT: MI.getOperand(0).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg())) { +// CHECK-NEXT: // x_mov $dst, $src +// CHECK-NEXT: OutInst.setOpcode(MyTarget::X_MOV); +// CHECK-NEXT: // Operand: dst +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); +// CHECK-NEXT: // Operand: src +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); +// CHECK-NEXT: OutInst.setLoc(MI.getLoc()); +// CHECK-NEXT: return true; +// CHECK-NEXT: } // if +// CHECK-NEXT: break; +// CHECK-NEXT: } // case X_MOV_TIED +// CHECK-NEXT: case MyTarget::X_MOV_ZERO: { +// CHECK-NEXT: if (MI.getOperand(0).isReg() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg())) { +// CHECK-NEXT: // x_mov $dst, $src +// CHECK-NEXT: OutInst.setOpcode(MyTarget::X_MOV); +// CHECK-NEXT: // Operand: dst +// CHECK-NEXT: OutInst.addOperand(MI.getOperand(0)); +// CHECK-NEXT: // Operand: src +// CHECK-NEXT: OutInst.addOperand(MCOperand::createReg(MyTarget::X0)); +// CHECK-NEXT: OutInst.setLoc(MI.getLoc()); +// CHECK-NEXT: return true; +// CHECK-NEXT: } // if +// CHECK-NEXT: break; +// CHECK-NEXT: } // case X_MOV_ZERO +// CHECK-NEXT: } // switch +// CHECK-NEXT: return false; +// CHECK-NEXT: } + +// CHECK: static bool isCompressibleInst(const MachineInstr &MI, +// CHECK-NEXT: const MyTargetSubtarget &STI) { +// CHECK-NEXT: switch (MI.getOpcode()) { +// CHECK-NEXT: default: return false; +// CHECK-NEXT: case MyTarget::PTR_MOV: { +// CHECK-NEXT: if (MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() && +// CHECK-NEXT: MyTargetMCRegisterClasses[STI.getInstrInfo().getOpRegClassID(MI.getDesc().operands()[0])].contains(MI.getOperand(0).getReg()) && +// CHECK-NEXT: MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isPhysical() && +// CHECK-NEXT: MyTargetMCRegisterClasses[STI.getInstrInfo().getOpRegClassID(MI.getDesc().operands()[1])].contains(MI.getOperand(1).getReg())) { +// CHECK-NEXT: // ptr_mov.small $dst, $src +// CHECK-NEXT: // Operand: dst +// CHECK-NEXT: // Operand: src +// 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() && MI.getOperand(1).getReg().isPhysical() && +// CHECK-NEXT: MyTargetMCRegisterClasses[STI.getInstrInfo().getOpRegClassID(MI.getDesc().operands()[1])].contains(MI.getOperand(1).getReg())) { +// CHECK-NEXT: // ptr_mov.tied $dst, $src +// CHECK-NEXT: // Operand: dst +// CHECK-NEXT: // Operand: src +// CHECK-NEXT: return true; +// CHECK-NEXT: } // if +// CHECK-NEXT: break; +// CHECK-NEXT: } // case PTR_MOV +// CHECK-NEXT: case MyTarget::X_MOV: { +// CHECK-NEXT: if (MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg()) && +// CHECK-NEXT: MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isPhysical() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(1).getReg())) { +// CHECK-NEXT: // x_mov.small $dst, $src +// CHECK-NEXT: // Operand: dst +// CHECK-NEXT: // Operand: src +// 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() && MI.getOperand(1).getReg().isPhysical() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(1).getReg())) { +// CHECK-NEXT: // x_mov.tied $dst, $src +// CHECK-NEXT: // Operand: dst +// 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::X0) && +// CHECK-NEXT: MI.getOperand(0).isReg() && MI.getOperand(0).getReg().isPhysical() && +// CHECK-NEXT: MyTargetMCRegisterClasses[MyTarget::XRegsRegClassID].contains(MI.getOperand(0).getReg())) { +// CHECK-NEXT: // x_mov.zero $dst +// CHECK-NEXT: // Operand: dst +// CHECK-NEXT: return true; +// CHECK-NEXT: } // if +// CHECK-NEXT: break; +// CHECK-NEXT: } // case X_MOV +// CHECK-NEXT: } // switch +// CHECK-NEXT: return false; +// CHECK-NEXT: } + +def MyTargetISA : InstrInfo; +def MyTargetAsmWriter : AsmWriter { + int PassSubtarget = 1; +} +def MyTarget : Target { + let InstructionSet = MyTargetISA; + let AssemblyWriters = [MyTargetAsmWriter]; +} diff --git a/llvm/utils/TableGen/CompressInstEmitter.cpp b/llvm/utils/TableGen/CompressInstEmitter.cpp index 94fe3823fae22..58993ce5b5985 100644 --- a/llvm/utils/TableGen/CompressInstEmitter.cpp +++ b/llvm/utils/TableGen/CompressInstEmitter.cpp @@ -735,7 +735,7 @@ void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &OS, switch (SourceOperandMap[OpNo].Kind) { case OpData::Operand: if (SourceOperandMap[OpNo].OpInfo.TiedOpIdx != -1) { - if (Source.Operands[OpNo].Rec->isSubClassOf("RegisterClass")) + if (Source.Operands[OpNo].Rec->isSubClassOf("RegisterClassLike")) CondStream << CondSep << "MI.getOperand(" << OpNo << ").isReg() && MI.getOperand(" << SourceOperandMap[OpNo].OpInfo.TiedOpIdx @@ -788,11 +788,7 @@ void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &OS, const Record *DagRec = DestOperandMap[OpNo].OpInfo.DagRec; // Check that the operand in the Source instruction fits // the type for the Dest instruction. - if (DagRec->isSubClassOf("RegisterClass") || - DagRec->isSubClassOf("RegisterOperand")) { - auto *ClassRec = DagRec->isSubClassOf("RegisterClass") - ? DagRec - : DagRec->getValueAsDef("RegClass"); + if (auto *ClassRec = Target.getAsRegClassLike(DagRec)) { // This is a register operand. Check the register class. // Don't check register class if this is a tied operand, it was done // for the operand it's tied to. @@ -801,9 +797,14 @@ void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &OS, if (EType == EmitterType::CheckCompress) CondStream << " && MI.getOperand(" << OpIdx << ").getReg().isPhysical()"; - CondStream << CondSep << TargetName << "MCRegisterClasses[" - << TargetName << "::" << ClassRec->getName() - << "RegClassID].contains(MI.getOperand(" << OpIdx + CondStream << CondSep << TargetName << "MCRegisterClasses["; + if (ClassRec->isSubClassOf("RegClassByHwMode")) + CondStream << "STI.getInstrInfo().getOpRegClassID(" + << "MI.getDesc().operands()[" << OpIdx << "])"; + else + CondStream << TargetName << "::" << ClassRec->getName() + << "RegClassID"; + CondStream << "].contains(MI.getOperand(" << OpIdx << ").getReg())"; }