diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index 890df0d96d08..41c1e66efca0 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -583,11 +583,15 @@ class EncodingByHwMode Ms = [], list Ts = []> list Objects = Ts; } +class OperandRegClass { + RegisterClass RegClass = Reg; + int OperandIdx = OperIdx; +} + // Allows to specify instrution Itineraries based on RegClass used -class ItinRegClassPair { +class ItinRegClassPair RegType> { InstrItinClass Itinerary = Itin; - RegisterClass Regclass = Reg; - int OperandIdx = OperIdx; + list RegTypeList = RegType; } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AIE/AIE2GenInstrInfo.td b/llvm/lib/Target/AIE/AIE2GenInstrInfo.td index cf94c0314aa9..32fb028b27c3 100644 --- a/llvm/lib/Target/AIE/AIE2GenInstrInfo.td +++ b/llvm/lib/Target/AIE/AIE2GenInstrInfo.td @@ -430,9 +430,9 @@ let Itinerary = II_JZ, hasDelaySlot = true in { } let Itinerary = II_MOVA, isMoveImm = 1, isReMaterializable = 1, isAsCheapAsAMove = 1 in { - let ItineraryRegPairs = [ItinRegClassPair, ItinRegClassPair, - ItinRegClassPair, ItinRegClassPair, - ItinRegClassPair, ItinRegClassPair] in { + let ItineraryRegPairs = [ItinRegClassPair]>, ItinRegClassPair]>, + ItinRegClassPair]>, ItinRegClassPair]>, + ItinRegClassPair]>, ItinRegClassPair]>] in { def MOVA_lda_cg : AIE2_lda_cg_inst_lda<(outs OP_mLdaCg:$mLdaCg), (ins simm11:$c11s), "mova", "$mLdaCg, $c11s">; } @@ -538,10 +538,10 @@ let Itinerary = II_PADD_3D in { // MOV & MOVXM instruction have identical itineraries, they differ only in slot usage let Itinerary = II_MOV, isMoveImm = 1, isReMaterializable = 1 in { - let ItineraryRegPairs = [ItinRegClassPair, ItinRegClassPair, - ItinRegClassPair, ItinRegClassPair, - ItinRegClassPair, ItinRegClassPair, - ItinRegClassPair] in { + let ItineraryRegPairs = [ItinRegClassPair]>, ItinRegClassPair]>, + ItinRegClassPair]>, ItinRegClassPair]>, + ItinRegClassPair]>, ItinRegClassPair]>, + ItinRegClassPair]>] in { // MOVXM is quite expensive in code size, and will block an extra slot, so we don't // mark it as isAsCheapAsAMove let isAsCheapAsAMove = 0 in { @@ -556,10 +556,10 @@ let Itinerary = II_MOV, isMoveImm = 1, isReMaterializable = 1 in { } let Itinerary = II_MOV_SCL, isMoveReg = 1 in { - let ItineraryRegPairs = [ItinRegClassPair, ItinRegClassPair, - ItinRegClassPair, ItinRegClassPair, - ItinRegClassPair, ItinRegClassPair, - ItinRegClassPair] in { + let ItineraryRegPairs = [ItinRegClassPair]>, ItinRegClassPair]>, + ItinRegClassPair]>, ItinRegClassPair]>, + ItinRegClassPair]>, ItinRegClassPair]>, + ItinRegClassPair]>] in { def MOV_mv_scl : AIE2_mv_scl_inst_mv<(outs OP_mMvSclDst:$mMvSclDst), (ins OP_mMvSclSrc:$mMvSclSrc), "mov", "$mMvSclDst, $mMvSclSrc">; } diff --git a/llvm/test/TableGen/aie-variable-instr-itinerary.td b/llvm/test/TableGen/aie-variable-instr-itinerary.td index b99eb36c5ae1..6319e720e594 100644 --- a/llvm/test/TableGen/aie-variable-instr-itinerary.td +++ b/llvm/test/TableGen/aie-variable-instr-itinerary.td @@ -42,26 +42,39 @@ class MOVInstruction : TestInstruction { let Itinerary = II_MOV in def MOV_instr : MOVInstruction<>; -let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair] in +let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair]>] in def MOV_instr_GPR : MOVInstruction<>; -let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair] in +let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair]>] in def MOV_instr_PTR : MOVInstruction<>; -let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair, ItinRegClassPair] in +let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair]>, ItinRegClassPair]>] in def MOV_instr_GPR_PTR : MOVInstruction<>; +let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair,OperandRegClass<1, PTR>]>] in + def MOV_instr_GP : MOVInstruction<>; -let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair] in { +let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair,OperandRegClass<1, GPR>]>] in + def MOV_instr_PG : MOVInstruction<>; + +let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair,OperandRegClass<1, PTR>]>, ItinRegClassPair,OperandRegClass<0, PTR>]>] in + def MOV_instr_GP_PG : MOVInstruction<>; + +let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair]>] in { def MOV_instr_GPR_1 : MOVInstruction<>; def MOV_instr_GPR_2 : MOVInstruction<>; } -let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair, ItinRegClassPair] in { +let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair]>, ItinRegClassPair]>] in { def MOV_instr_GPR_PTR_1 : MOVInstruction<>; def MOV_instr_GPR_PTR_2 : MOVInstruction<>; } +let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair,OperandRegClass<1, PTR>]>, ItinRegClassPair,OperandRegClass<0, PTR>]>] in { + def MOV_instr_GP_PG_1 : MOVInstruction<>; + def MOV_instr_GP_PG_2 : MOVInstruction<>; +} + // CHECK: unsigned TestAIEInstrInfo::getSchedClass( // CHECK-NEXT: const MCInstrDesc &Desc, // CHECK-NEXT: iterator_range Operands, @@ -92,6 +105,29 @@ let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair // CHECK-NEXT: << Desc.getOpcode() << "\n"); // CHECK-NEXT: return Desc.getSchedClass(); // CHECK-NEXT: } +// CHECK-NEXT: case TestAIE::MOV_instr_GP: +// CHECK-NEXT: { +// CHECK-NEXT: if (checkRCForOperand(TestAIE::GPRRegClass,0) && +// CHECK-NEXT: checkRCForOperand(TestAIE::PTRRegClass,1)) +// CHECK-NEXT: return TestAIE::Sched::II_MOV_GPR; +// CHECK-NEXT: LLVM_DEBUG(dbgs() << "No matching RegClass found for instruction: " +// CHECK-NEXT: << Desc.getOpcode() << "\n"); +// CHECK-NEXT: return Desc.getSchedClass(); +// CHECK-NEXT: } +// CHECK-NEXT: case TestAIE::MOV_instr_GP_PG: +// CHECK-NEXT: case TestAIE::MOV_instr_GP_PG_1: +// CHECK-NEXT: case TestAIE::MOV_instr_GP_PG_2: +// CHECK-NEXT: { +// CHECK-NEXT: if (checkRCForOperand(TestAIE::GPRRegClass,0) && +// CHECK-NEXT: checkRCForOperand(TestAIE::PTRRegClass,1)) +// CHECK-NEXT: return TestAIE::Sched::II_MOV_GPR; +// CHECK-NEXT: if (checkRCForOperand(TestAIE::GPRRegClass,1) && +// CHECK-NEXT: checkRCForOperand(TestAIE::PTRRegClass,0)) +// CHECK-NEXT: return TestAIE::Sched::II_MOV_PTR; +// CHECK-NEXT: LLVM_DEBUG(dbgs() << "No matching RegClass found for instruction: " +// CHECK-NEXT: << Desc.getOpcode() << "\n"); +// CHECK-NEXT: return Desc.getSchedClass(); +// CHECK-NEXT: } // CHECK-NEXT: case TestAIE::MOV_instr_GPR_PTR: // CHECK-NEXT: case TestAIE::MOV_instr_GPR_PTR_1: // CHECK-NEXT: case TestAIE::MOV_instr_GPR_PTR_2: @@ -104,6 +140,15 @@ let Itinerary = II_MOV, ItineraryRegPairs = [ItinRegClassPair // CHECK-NEXT: << Desc.getOpcode() << "\n"); // CHECK-NEXT: return Desc.getSchedClass(); // CHECK-NEXT: } +// CHECK-NEXT: case TestAIE::MOV_instr_PG: +// CHECK-NEXT: { +// CHECK-NEXT: if (checkRCForOperand(TestAIE::PTRRegClass,0) && +// CHECK-NEXT: checkRCForOperand(TestAIE::GPRRegClass,1)) +// CHECK-NEXT: return TestAIE::Sched::II_MOV_GPR; +// CHECK-NEXT: LLVM_DEBUG(dbgs() << "No matching RegClass found for instruction: " +// CHECK-NEXT: << Desc.getOpcode() << "\n"); +// CHECK-NEXT: return Desc.getSchedClass(); +// CHECK-NEXT: } // CHECK-NEXT: case TestAIE::MOV_instr_PTR: // CHECK-NEXT: { // CHECK-NEXT: if (checkRCForOperand(TestAIE::PTRRegClass,0)) diff --git a/llvm/utils/TableGen/AIEVariableInstrItineraryEmitter.cpp b/llvm/utils/TableGen/AIEVariableInstrItineraryEmitter.cpp index 8201692575d7..53a7dc3cbc00 100644 --- a/llvm/utils/TableGen/AIEVariableInstrItineraryEmitter.cpp +++ b/llvm/utils/TableGen/AIEVariableInstrItineraryEmitter.cpp @@ -24,8 +24,10 @@ namespace { class AIEVariableInstrItineraryEmitter { - std::map>, - std::vector> + std::map< + std::vector>>>, + std::vector> UniqueRegItineraryOpIdx; public: @@ -81,9 +83,18 @@ void AIEVariableInstrItineraryEmitter::emitAltItineraryInfo(raw_ostream &OS) { for (const auto &Instr : Instrs) OS << " case " << CurrentNamespace << "::" << Instr << ":\n"; OS << " {\n"; - for (const auto &[RegClass, Itinerary, OpIdx] : RegItineraryPairs) { - OS << " if (checkRCForOperand(" << CurrentNamespace << "::" << RegClass - << "RegClass," << OpIdx << "))\n"; + for (const auto &[Itinerary, RegClassList] : RegItineraryPairs) { + assert(!RegClassList.empty() && "RegClassList cannot be empty"); + OS << " if ("; + unsigned Count = 0; + for (const auto &[RegClass, OpIdx] : RegClassList) { + if (Count) + OS << " &&\n "; + OS << "checkRCForOperand(" << CurrentNamespace << "::" << RegClass + << "RegClass," << OpIdx << ")"; + Count++; + } + OS << ")\n"; OS << " return " << CurrentNamespace << "::" << "Sched" << "::" << Itinerary << ";\n"; } @@ -111,21 +122,32 @@ void AIEVariableInstrItineraryEmitter::run(raw_ostream &OS) { std::vector AltItinary = R->getValueAsListOfDefs("ItineraryRegPairs"); if (AltItinary.size()) { - int FirstOperandIdx = AltItinary[0]->getValueAsInt("OperandIdx"); - for (const auto AltItinerary : AltItinary) - if (FirstOperandIdx != AltItinerary->getValueAsInt("OperandIdx")) - llvm_unreachable("All alternate itineraries for an instruction must " - "have the same operand index"); - - std::vector> + std::vector>>> RegItineraryPairs; for (const auto AltItinerary : AltItinary) { + std::vector OpRegType = + AltItinerary->getValueAsListOfDefs("RegTypeList"); + std::vector> OperandRegClass; + + auto checkUnique = [&OperandRegClass](unsigned OpIdx) { + return !std::any_of( + OperandRegClass.begin(), OperandRegClass.end(), + [OpIdx](const auto &Operand) { return Operand.second == OpIdx; }); + }; + + for (const auto RegType : OpRegType) { + unsigned OpIdx = RegType->getValueAsInt("OperandIdx"); + assert(checkUnique(OpIdx) && "OperandIdx must be unique"); + OperandRegClass.push_back(std::make_pair( + RegType->getValueAsDef("RegClass")->getName(), OpIdx)); + } + + assert(!OperandRegClass.empty() && "OperandRegClass cannot be empty"); RegItineraryPairs.push_back( - std::make_tuple(AltItinerary->getValueAsDef("Regclass")->getName(), - AltItinerary->getValueAsDef("Itinerary")->getName(), - FirstOperandIdx)); + std::make_tuple(AltItinerary->getValueAsDef("Itinerary")->getName(), + OperandRegClass)); } - UniqueRegItineraryOpIdx[RegItineraryPairs].push_back(R->getName()); } }