Skip to content

[TableGen][DecoderEmitter] Add option to emit type-specialized code #146593

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
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
7 changes: 6 additions & 1 deletion llvm/include/llvm/Target/Target.td
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,6 @@ class OptionalDefOperand<ValueType ty, dag OpTypes, dag defaultops>
let MIOperandInfo = OpTypes;
}


// InstrInfo - This class should only be instantiated once to provide parameters
// which are global to the target machine.
//
Expand All @@ -1158,6 +1157,12 @@ class InstrInfo {
//
// This option is a temporary migration help. It will go away.
bit guessInstructionProperties = true;

// Option to choose bewteen templated and non-templated code from decoder
// emitter. This means that the generated `decodeInstruction` function will
// use auto-inferred types for the instruction payload instead of generating
// templated code using `InsnType` for the instruction payload.
bit GenerateTemplatedDecoder = false;
}

// Standard Pseudo Instructions.
Expand Down
29 changes: 14 additions & 15 deletions llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/AMDHSAKernelDescriptor.h"
#include "llvm/Support/Compiler.h"
#include <bitset>

using namespace llvm;

Expand Down Expand Up @@ -497,26 +498,24 @@ template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) {
return Res;
}

static inline DecoderUInt128 eat12Bytes(ArrayRef<uint8_t> &Bytes) {
static inline std::bitset<96> eat12Bytes(ArrayRef<uint8_t> &Bytes) {
using namespace llvm::support::endian;
assert(Bytes.size() >= 12);
uint64_t Lo =
support::endian::read<uint64_t, llvm::endianness::little>(Bytes.data());
std::bitset<96> Lo(read<uint64_t, endianness::little>(Bytes.data()));
Bytes = Bytes.slice(8);
uint64_t Hi =
support::endian::read<uint32_t, llvm::endianness::little>(Bytes.data());
std::bitset<96> Hi(read<uint32_t, endianness::little>(Bytes.data()));
Bytes = Bytes.slice(4);
return DecoderUInt128(Lo, Hi);
return (Hi << 64) | Lo;
}

static inline DecoderUInt128 eat16Bytes(ArrayRef<uint8_t> &Bytes) {
static inline std::bitset<128> eat16Bytes(ArrayRef<uint8_t> &Bytes) {
using namespace llvm::support::endian;
assert(Bytes.size() >= 16);
uint64_t Lo =
support::endian::read<uint64_t, llvm::endianness::little>(Bytes.data());
std::bitset<128> Lo(read<uint64_t, endianness::little>(Bytes.data()));
Bytes = Bytes.slice(8);
uint64_t Hi =
support::endian::read<uint64_t, llvm::endianness::little>(Bytes.data());
std::bitset<128> Hi(read<uint64_t, endianness::little>(Bytes.data()));
Bytes = Bytes.slice(8);
return DecoderUInt128(Lo, Hi);
return (Hi << 64) | Lo;
}

void AMDGPUDisassembler::decodeImmOperands(MCInst &MI,
Expand Down Expand Up @@ -598,8 +597,8 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,

// Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2
// encodings
if (isGFX11Plus() && Bytes.size() >= 12 ) {
DecoderUInt128 DecW = eat12Bytes(Bytes);
if (isGFX11Plus() && Bytes.size() >= 12) {
std::bitset<96> DecW = eat12Bytes(Bytes);

if (isGFX11() &&
tryDecodeInst(DecoderTableGFX1196, DecoderTableGFX11_FAKE1696, MI,
Expand Down Expand Up @@ -634,7 +633,7 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,

} else if (Bytes.size() >= 16 &&
STI.hasFeature(AMDGPU::FeatureGFX950Insts)) {
DecoderUInt128 DecW = eat16Bytes(Bytes);
std::bitset<128> DecW = eat16Bytes(Bytes);
if (tryDecodeInst(DecoderTableGFX940128, MI, DecW, Address, CS))
break;

Expand Down
38 changes: 0 additions & 38 deletions llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,44 +32,6 @@ class MCOperand;
class MCSubtargetInfo;
class Twine;

// Exposes an interface expected by autogenerated code in
// FixedLenDecoderEmitter
class DecoderUInt128 {
private:
uint64_t Lo = 0;
uint64_t Hi = 0;

public:
DecoderUInt128() = default;
DecoderUInt128(uint64_t Lo, uint64_t Hi = 0) : Lo(Lo), Hi(Hi) {}
operator bool() const { return Lo || Hi; }
uint64_t extractBitsAsZExtValue(unsigned NumBits,
unsigned BitPosition) const {
assert(NumBits && NumBits <= 64);
assert(BitPosition < 128);
uint64_t Val;
if (BitPosition < 64)
Val = Lo >> BitPosition | Hi << 1 << (63 - BitPosition);
else
Val = Hi >> (BitPosition - 64);
return Val & ((uint64_t(2) << (NumBits - 1)) - 1);
}
DecoderUInt128 operator&(const DecoderUInt128 &RHS) const {
return DecoderUInt128(Lo & RHS.Lo, Hi & RHS.Hi);
}
DecoderUInt128 operator&(const uint64_t &RHS) const {
return *this & DecoderUInt128(RHS);
}
DecoderUInt128 operator~() const { return DecoderUInt128(~Lo, ~Hi); }
bool operator==(const DecoderUInt128 &RHS) {
return Lo == RHS.Lo && Hi == RHS.Hi;
}
bool operator!=(const DecoderUInt128 &RHS) {
return Lo != RHS.Lo || Hi != RHS.Hi;
}
bool operator!=(const int &RHS) { return *this != DecoderUInt128(RHS); }
};

//===----------------------------------------------------------------------===//
// AMDGPUDisassembler
//===----------------------------------------------------------------------===//
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/ARC/ARC.td
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ include "ARCRegisterInfo.td"
include "ARCInstrInfo.td"
include "ARCCallingConv.td"

def ARCInstrInfo : InstrInfo;
def ARCInstrInfo : InstrInfo {
// FIXME: Migrate ARC disassembler to work with non-templated decoder.
let GenerateTemplatedDecoder = true;
}

class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/AVR/AVR.td
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ include "AVRRegisterInfo.td"

include "AVRInstrInfo.td"

def AVRInstrInfo : InstrInfo;
def AVRInstrInfo : InstrInfo {
// FIXME: Migrate AVR disassembler to work with non-templated decoder.
let GenerateTemplatedDecoder = true;
}

//===---------------------------------------------------------------------===//
// Calling Conventions
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/CSKY/CSKY.td
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,10 @@ def : CK860V<"ck860fv", NoSchedModel,
// Define the CSKY target.
//===----------------------------------------------------------------------===//

def CSKYInstrInfo : InstrInfo;
def CSKYInstrInfo : InstrInfo {
// FIXME: Migrate CSKY disassembler to work with non-templated decoder.
let GenerateTemplatedDecoder = true;
}


def CSKYAsmParser : AsmParser {
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/MSP430/MSP430.td
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ include "MSP430CallingConv.td"

include "MSP430InstrInfo.td"

def MSP430InstrInfo : InstrInfo;
def MSP430InstrInfo : InstrInfo {
// FIXME: Migrate MPS430 disassembler to work with non-templated decoder.
let GenerateTemplatedDecoder = true;
}

//===---------------------------------------------------------------------===//
// Assembly Printers
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/Mips/Mips.td
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ include "MipsScheduleP5600.td"
include "MipsScheduleGeneric.td"

def MipsInstrInfo : InstrInfo {
// FIXME: Migrate MIPS disassembler to work with non-templated decoder.
let GenerateTemplatedDecoder = true;
}

//===----------------------------------------------------------------------===//
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/PowerPC/PPC.td
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,8 @@ include "PPCCallingConv.td"

def PPCInstrInfo : InstrInfo {
let isLittleEndianEncoding = 1;
// FIXME: Migrate PPC disassembler to work with non-templated decoder.
let GenerateTemplatedDecoder = true;
}

def PPCAsmWriter : AsmWriter {
Expand Down
13 changes: 5 additions & 8 deletions llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -816,9 +816,7 @@ DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,
}
Size = 4;

// Use uint64_t to match getInstruction48. decodeInstruction is templated
// on the Insn type.
uint64_t Insn = support::endian::read32le(Bytes.data());
uint32_t Insn = support::endian::read32le(Bytes.data());

for (const DecoderListEntry &Entry : DecoderList32) {
if (!Entry.haveContainedFeatures(STI.getFeatureBits()))
Expand Down Expand Up @@ -864,9 +862,7 @@ DecodeStatus RISCVDisassembler::getInstruction16(MCInst &MI, uint64_t &Size,
}
Size = 2;

// Use uint64_t to match getInstruction48. decodeInstruction is templated
// on the Insn type.
uint64_t Insn = support::endian::read16le(Bytes.data());
uint16_t Insn = support::endian::read16le(Bytes.data());

for (const DecoderListEntry &Entry : DecoderList16) {
if (!Entry.haveContainedFeatures(STI.getFeatureBits()))
Expand Down Expand Up @@ -900,9 +896,10 @@ DecodeStatus RISCVDisassembler::getInstruction48(MCInst &MI, uint64_t &Size,
}
Size = 6;

uint64_t Insn = 0;
uint64_t InsnBits = 0;
for (size_t i = Size; i-- != 0;)
Insn += (static_cast<uint64_t>(Bytes[i]) << 8 * i);
InsnBits += (static_cast<uint64_t>(Bytes[i]) << 8 * i);
std::bitset<48> Insn(InsnBits);

for (const DecoderListEntry &Entry : DecoderList48) {
if (!Entry.haveContainedFeatures(STI.getFeatureBits()))
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Target/SystemZ/SystemZ.td
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ include "SystemZInstrHFP.td"
include "SystemZInstrDFP.td"
include "SystemZInstrSystem.td"

def SystemZInstrInfo : InstrInfo { let guessInstructionProperties = 0; }
def SystemZInstrInfo : InstrInfo {
let guessInstructionProperties = 0;
// FIXME: Migrate SystemZ disassembler to work with non-templated decoder.
let GenerateTemplatedDecoder = true;
}

//===----------------------------------------------------------------------===//
// Assembly parser
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/Xtensa/Xtensa.td
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ include "XtensaCallingConv.td"

include "XtensaInstrInfo.td"

def XtensaInstrInfo : InstrInfo;
def XtensaInstrInfo : InstrInfo {
// FIXME: Migrate XTensa disassembler to work with non-templated decoder.
let GenerateTemplatedDecoder = true;
}

//===----------------------------------------------------------------------===//
// Target Declaration
Expand Down
10 changes: 5 additions & 5 deletions llvm/test/TableGen/BitOffsetDecoder.td
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ def baz : Instruction {

}

// CHECK: tmp = fieldFromInstruction(insn, 8, 7);
// CHECK: tmp = fieldFromInstruction(insn, 8, 8) << 3;
// CHECK: insertBits(tmp, fieldFromInstruction(insn, 8, 4), 7, 4);
// CHECK: insertBits(tmp, fieldFromInstruction(insn, 12, 4), 3, 4);
// CHECK: tmp = fieldFromInstruction(insn, 8, 8) << 4;
// CHECK: tmp = fieldFromInstruction(Insn, 8, 7);
// CHECK: tmp = fieldFromInstruction(Insn, 8, 8) << 3;
// CHECK: insertBits(tmp, fieldFromInstruction(Insn, 8, 4), 7, 4);
// CHECK: insertBits(tmp, fieldFromInstruction(Insn, 12, 4), 3, 4);
// CHECK: tmp = fieldFromInstruction(Insn, 8, 8) << 4;
20 changes: 10 additions & 10 deletions llvm/test/TableGen/DecoderEmitterFnTable.td
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ def Inst3 : TestInstruction {
let AsmString = "Inst3";
}

// CHECK-LABEL: DecodeStatus decodeFn0(DecodeStatus S, InsnType insn, MCInst &MI, uint64_t Address, const MCDisassembler *Decoder, bool &DecodeComplete)
// CHECK-LABEL: DecodeStatus decodeFn1(DecodeStatus S, InsnType insn, MCInst &MI, uint64_t Address, const MCDisassembler *Decoder, bool &DecodeComplete)
// CHECK-LABEL: DecodeStatus decodeFn2(DecodeStatus S, InsnType insn, MCInst &MI, uint64_t Address, const MCDisassembler *Decoder, bool &DecodeComplete)
// CHECK-LABEL: DecodeStatus decodeFn3(DecodeStatus S, InsnType insn, MCInst &MI, uint64_t Address, const MCDisassembler *Decoder, bool &DecodeComplete)
// CHECK-LABEL: decodeToMCInst(unsigned Idx, DecodeStatus S, InsnType insn, MCInst &MI, uint64_t Address, const MCDisassembler *Decoder, bool &DecodeComplete)
// CHECK-LABEL: DecodeStatus decodeFn_0(DecodeStatus S, uint8_t Insn, MCInst &MI, uint64_t Address, const MCDisassembler *Decoder, bool &DecodeComplete)
// CHECK-LABEL: DecodeStatus decodeFn_1(DecodeStatus S, uint8_t Insn, MCInst &MI, uint64_t Address, const MCDisassembler *Decoder, bool &DecodeComplete)
// CHECK-LABEL: DecodeStatus decodeFn_2(DecodeStatus S, uint8_t Insn, MCInst &MI, uint64_t Address, const MCDisassembler *Decoder, bool &DecodeComplete)
// CHECK-LABEL: DecodeStatus decodeFn_3(DecodeStatus S, uint8_t Insn, MCInst &MI, uint64_t Address, const MCDisassembler *Decoder, bool &DecodeComplete)
// CHECK-LABEL: decodeToMCInst(unsigned Idx, DecodeStatus S, uint8_t Insn, MCInst &MI, uint64_t Address, const MCDisassembler *Decoder, bool &DecodeComplete)
// CHECK: static constexpr DecodeFnTy decodeFnTable[]
// CHECK-NEXT: decodeFn0,
// CHECK-NEXT: decodeFn1,
// CHECK-NEXT: decodeFn2,
// CHECK-NEXT: decodeFn3,
// CHECK: return decodeFnTable[Idx](S, insn, MI, Address, Decoder, DecodeComplete)
// CHECK-NEXT: decodeFn_0,
// CHECK-NEXT: decodeFn_1,
// CHECK-NEXT: decodeFn_2,
// CHECK-NEXT: decodeFn_3,
// CHECK: return decodeFnTable[Idx](S, Insn, MI, Address, Decoder, DecodeComplete)
6 changes: 3 additions & 3 deletions llvm/test/TableGen/FixedLenDecoderEmitter/InitValue.td
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ def bax : Instruction {

}

// CHECK: tmp = fieldFromInstruction(insn, 9, 7) << 1;
// CHECK: tmp = fieldFromInstruction(Insn, 9, 7) << 1;
// CHECK: tmp = 0x1;
// CHECK: insertBits(tmp, fieldFromInstruction(insn, 9, 7), 1, 7);
// CHECK: insertBits(tmp, fieldFromInstruction(Insn, 9, 7), 1, 7);
// CHECK: tmp = 0x100000000;
// CHECK: insertBits(tmp, fieldFromInstruction(insn, 8, 7), 25, 7);
// CHECK: insertBits(tmp, fieldFromInstruction(Insn, 8, 7), 25, 7);
19 changes: 12 additions & 7 deletions llvm/test/TableGen/HwModeEncodeDecode3.td
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ def unrelated: Instruction {
// exact duplicates and could effectively be merged into one.
// DECODER-LABEL: DecoderTable32[] =
// DECODER-DAG: Opcode: bar
// DECODER-LABEL: DecoderTable64[] =
// DECODER-DAG: Opcode: fooTypeEncDefault:foo
// DECODER-LABEL: DecoderTableAlt32[] =
// DECODER-DAG: Opcode: unrelated
// DECODER-LABEL: DecoderTableAlt_ModeA32[] =
Expand All @@ -138,13 +136,13 @@ def unrelated: Instruction {
// DECODER-LABEL: DecoderTable_ModeC32[] =
// DECODER-DAG: Opcode: fooTypeEncC:foo
// DECODER-DAG: Opcode: bar
// DECODER-LABEL: DecoderTable64[] =
// DECODER-DAG: Opcode: fooTypeEncDefault:foo

// Under the 'O1' optimization level, unnecessary duplicate tables will be eliminated,
// reducing the four ‘Alt’ tables down to just one.
// DECODER-SUPPRESS-O1-LABEL: DecoderTable32[] =
// DECODER-SUPPRESS-O1-DAG: Opcode: bar
// DECODER-SUPPRESS-O1-LABEL: DecoderTable64[] =
// DECODER-SUPPRESS-O1-DAG: Opcode: fooTypeEncDefault:foo
// DECODER-SUPPRESS-O1-LABEL: DecoderTableAlt32[] =
// DECODER-SUPPRESS-O1-DAG: Opcode: unrelated
// DECODER-SUPPRESS-O1-LABEL: DecoderTable_ModeA32[] =
Expand All @@ -157,18 +155,22 @@ def unrelated: Instruction {
// DECODER-SUPPRESS-O1-LABEL: DecoderTable_ModeC32[] =
// DECODER-SUPPRESS-O1-DAG: Opcode: fooTypeEncC:foo
// DECODER-SUPPRESS-O1-DAG: Opcode: bar
// DECODER-SUPPRESS-O1-LABEL: DecoderTable64[] =
// DECODER-SUPPRESS-O1-DAG: Opcode: fooTypeEncDefault:foo

// Under the 'O2' optimization condition, instructions possessing the 'EncodingByHwMode'
// attribute will be extracted from their original DecoderNamespace and placed into their
// respective HwMode tables. Meanwhile, other instructions that do not have the 'EncodingByHwMode'
// attribute but are within the same DecoderNamespace will be stored in the 'Default' table. This
// approach will significantly reduce instruction redundancy, but it necessitates users to thoroughly
// consider the interplay between HwMode and DecoderNamespace for their instructions.
//
// Additionally, no 32-bit instruction will appear in a 64-bit decoder table and
// vice-versa.
//
// DECODER-SUPPRESS-O2-LABEL: DecoderTable32[] =
// DECODER-SUPPRESS-O2-DAG: Opcode: bar
// DECODER-SUPPRESS-O2-LABEL: DecoderTable64[] =
// DECODER-SUPPRESS-O2-NOT: Opcode: bar
// DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncDefault:foo
// DECODER-SUPPRESS-O2-NOT: Opcode: fooTypeEncDefault:foo
// DECODER-SUPPRESS-O2-LABEL: DecoderTableAlt32[] =
// DECODER-SUPPRESS-O2-DAG: Opcode: unrelated
// DECODER-SUPPRESS-O2-LABEL: DecoderTable_ModeA32[] =
Expand All @@ -181,6 +183,9 @@ def unrelated: Instruction {
// DECODER-SUPPRESS-O2-LABEL: DecoderTable_ModeC32[] =
// DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncC:foo
// DECODER-SUPPRESS-O2-NOT: Opcode: bar
// DECODER-SUPPRESS-O2-LABEL: DecoderTable64[] =
// DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncDefault:foo
// DECODER-SUPPRESS-O2-NOT: Opcode: bar

// For 'bar' and 'unrelated', we didn't assign any HwModes for them,
// they should keep the same in the following four tables.
Expand Down
Loading