Index: include/llvm/Target/Target.td =================================================================== --- include/llvm/Target/Target.td +++ include/llvm/Target/Target.td @@ -912,6 +912,17 @@ let usesCustomInserter = 1; let mayLoad = 1; } + +// Generic opcode used by the IRTranslator. +// After ISel, this opcode should not appear. +def gADD : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$src1, unknown:$src2); + let AsmString = ""; + let hasSideEffects = 0; + let isCommutable = 1; +} +// TODO: Add the other generic opcodes. } //===----------------------------------------------------------------------===// Index: include/llvm/Target/TargetOpcodes.h =================================================================== --- include/llvm/Target/TargetOpcodes.h +++ include/llvm/Target/TargetOpcodes.h @@ -129,9 +129,27 @@ /// comparisons into existing memory operations. FAULTING_LOAD_OP = 22, + /// The following generic opcodes are not supposed to appear after ISel. + /// This is something we might want to relax, but for now, this is convenient + /// to produce diagnostic. + PRE_ISEL_GENERIC_OPCODE_START, + // Generic opcodes used before ISel are here. + + /// Generic ADD instruction. This is an integer add. + gADD = PRE_ISEL_GENERIC_OPCODE_START, + // TODO: Add more generic opcodes as we move along. + // FIXME: Right now, we have to manually add any new opcode in + // CodeGenTarget.cpp for TableGen to pick them up. + // Moreover the order must match. + + /// Marker for the end of the generic opcode. + /// This is used to check if an opcode is in the range of the + /// generic opcodes. + PRE_ISEL_GENERIC_OPCODE_END, + /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific post-isel opcode values start here. - GENERIC_OP_END = FAULTING_LOAD_OP, + GENERIC_OP_END = PRE_ISEL_GENERIC_OPCODE_END, }; } // end namespace TargetOpcode } // end namespace llvm Index: test/TableGen/trydecode-emission.td =================================================================== --- test/TableGen/trydecode-emission.td +++ test/TableGen/trydecode-emission.td @@ -36,8 +36,8 @@ // CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ... // CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 14, 0, // Skip to: 21 // CHECK-NEXT: /* 7 */ MCD::OPC_CheckField, 2, 2, 0, 5, 0, // Skip to: 18 -// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, 24, 0, 0, 0, // Opcode: InstB, skip to: 18 -// CHECK-NEXT: /* 18 */ MCD::OPC_Decode, 23, 1, // Opcode: InstA +// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, 25, 0, 0, 0, // Opcode: InstB, skip to: 18 +// CHECK-NEXT: /* 18 */ MCD::OPC_Decode, 24, 1, // Opcode: InstA // CHECK-NEXT: /* 21 */ MCD::OPC_Fail, // CHECK: if (DecodeInstB(MI, insn, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; } Index: test/TableGen/trydecode-emission2.td =================================================================== --- test/TableGen/trydecode-emission2.td +++ test/TableGen/trydecode-emission2.td @@ -35,9 +35,9 @@ // CHECK-NEXT: /* 7 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ... // CHECK-NEXT: /* 10 */ MCD::OPC_FilterValue, 0, 22, 0, // Skip to: 36 // CHECK-NEXT: /* 14 */ MCD::OPC_CheckField, 0, 2, 3, 5, 0, // Skip to: 25 -// CHECK-NEXT: /* 20 */ MCD::OPC_TryDecode, 24, 0, 0, 0, // Opcode: InstB, skip to: 25 +// CHECK-NEXT: /* 20 */ MCD::OPC_TryDecode, 25, 0, 0, 0, // Opcode: InstB, skip to: 25 // CHECK-NEXT: /* 25 */ MCD::OPC_CheckField, 3, 2, 0, 5, 0, // Skip to: 36 -// CHECK-NEXT: /* 31 */ MCD::OPC_TryDecode, 23, 1, 0, 0, // Opcode: InstA, skip to: 36 +// CHECK-NEXT: /* 31 */ MCD::OPC_TryDecode, 24, 1, 0, 0, // Opcode: InstA, skip to: 36 // CHECK-NEXT: /* 36 */ MCD::OPC_Fail, // CHECK: if (DecodeInstB(MI, insn, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; } Index: test/TableGen/trydecode-emission3.td =================================================================== --- test/TableGen/trydecode-emission3.td +++ test/TableGen/trydecode-emission3.td @@ -37,8 +37,8 @@ // CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ... // CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 14, 0, // Skip to: 21 // CHECK-NEXT: /* 7 */ MCD::OPC_CheckField, 2, 2, 0, 5, 0, // Skip to: 18 -// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, 24, 0, 0, 0, // Opcode: InstB, skip to: 18 -// CHECK-NEXT: /* 18 */ MCD::OPC_Decode, 23, 1, // Opcode: InstA +// CHECK-NEXT: /* 13 */ MCD::OPC_TryDecode, 25, 0, 0, 0, // Opcode: InstB, skip to: 18 +// CHECK-NEXT: /* 18 */ MCD::OPC_Decode, 24, 1, // Opcode: InstA // CHECK-NEXT: /* 21 */ MCD::OPC_Fail, // CHECK: if (DecodeInstBOp(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; } Index: utils/TableGen/CodeGenTarget.cpp =================================================================== --- utils/TableGen/CodeGenTarget.cpp +++ utils/TableGen/CodeGenTarget.cpp @@ -301,6 +301,9 @@ /// their enum value. void CodeGenTarget::ComputeInstrsByEnum() const { // The ordering here must match the ordering in TargetOpcodes.h. + // FIXME: It would be nice to have the opcode directly extracted + // to avoid potential errors. At the very, least a compile time + // error would be appreciated if the order does not match. static const char *const FixedInstrs[] = { "PHI", "INLINEASM", "CFI_INSTRUCTION", "EH_LABEL", "GC_LABEL", "KILL", "EXTRACT_SUBREG", "INSERT_SUBREG", @@ -308,6 +311,8 @@ "REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START", "LIFETIME_END", "STACKMAP", "PATCHPOINT", "LOAD_STACK_GUARD", "STATEPOINT", "LOCAL_ESCAPE", "FAULTING_LOAD_OP", + // Generic opcodes for GlobalISel start here. + "gADD", nullptr}; const auto &Insts = getInstructions(); for (const char *const *p = FixedInstrs; *p; ++p) {