[TableGen] Remove code beads

Code beads is useless since the only user, M68k, has moved on to
a new encoding/decoding infrastructure.

Reviewed By: myhsu

Differential Revision: https://reviews.llvm.org/D126349
This commit is contained in:
Sheng
2022-05-30 14:26:38 +08:00
parent a544710cd4
commit 751c7be5b2
8 changed files with 36 additions and 506 deletions

View File

@@ -7,7 +7,6 @@ tablegen(LLVM M68kGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM M68kGenRegisterBank.inc -gen-register-bank)
tablegen(LLVM M68kGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM M68kGenSubtargetInfo.inc -gen-subtarget)
tablegen(LLVM M68kGenMCCodeBeads.inc -gen-code-beads)
tablegen(LLVM M68kGenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM M68kGenMCPseudoLowering.inc -gen-pseudo-lowering)
tablegen(LLVM M68kGenDAGISel.inc -gen-dag-isel)

View File

@@ -26,6 +26,7 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Regex.h"
#include <functional>
@@ -601,40 +602,26 @@ bool M68kInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
bool M68kInstrInfo::isPCRelRegisterOperandLegal(
const MachineOperand &MO) const {
assert(MO.isReg());
const auto *MI = MO.getParent();
const uint8_t *Beads = M68k::getMCInstrBeads(MI->getOpcode());
assert(*Beads);
// Only addressing mode k has (non-pc) register with PCRel
// So we're looking for EA Beads equal to
// `3Bits<011>_1Bit<1>_2Bits<11>`
// FIXME: There is an important caveat and two assumptions
// here: The caveat is that EA encoding always sit on the LSB.
// Where the assumptions are that if there are more than one
// operands, the EA encoding for the source operand always sit
// on the LSB. At the same time, k addressing mode can not be used
// on destination operand.
// The last assumption is kinda dirty so we need to find a way around
// it
const uint8_t EncEAk[3] = {0b011, 0b1, 0b11};
for (const uint8_t Pat : EncEAk) {
uint8_t Bead = *(Beads++);
if (!Bead)
return false;
// Check whether this MO belongs to an instruction with addressing mode 'k',
// Refer to TargetInstrInfo.h for more information about this function.
switch (Bead & 0xF) {
default:
return false;
case M68kBeads::Bits1:
case M68kBeads::Bits2:
case M68kBeads::Bits3: {
uint8_t Val = (Bead & 0xF0) >> 4;
if (Val != Pat)
return false;
}
}
}
return true;
const MachineInstr *MI = MO.getParent();
const unsigned NameIndices = M68kInstrNameIndices[MI->getOpcode()];
StringRef InstrName(&M68kInstrNameData[NameIndices]);
const unsigned OperandNo = MI->getOperandNo(&MO);
// If this machine operand is the 2nd operand, then check
// whether the instruction has destination addressing mode 'k'.
if (OperandNo == 1)
return Regex("[A-Z]+(8|16|32)k[a-z](_TC)?$").match(InstrName);
// If this machine operand is the last one, then check
// whether the instruction has source addressing mode 'k'.
if (OperandNo == MI->getNumExplicitOperands() - 1)
return Regex("[A-Z]+(8|16|32)[a-z]k(_TC)?$").match(InstrName);
return false;
}
void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,

View File

@@ -65,26 +65,6 @@ public:
~M68kMCCodeEmitter() override {}
// TableGen'erated function
const uint8_t *getGenInstrBeads(const MCInst &MI) const {
return M68k::getMCInstrBeads(MI.getOpcode());
}
unsigned encodeBits(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
const MCInstrDesc &Desc, uint64_t &Buffer,
unsigned Offset, SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
unsigned encodeReg(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
unsigned encodeImm(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
void encodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const override;
@@ -237,246 +217,6 @@ void M68kMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &Op,
}
}
unsigned M68kMCCodeEmitter::encodeBits(unsigned ThisByte, uint8_t Bead,
const MCInst &MI,
const MCInstrDesc &Desc,
uint64_t &Buffer, unsigned Offset,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
unsigned Num = 0;
switch (Bead & 0xF) {
case M68kBeads::Bits1:
Num = 1;
break;
case M68kBeads::Bits2:
Num = 2;
break;
case M68kBeads::Bits3:
Num = 3;
break;
case M68kBeads::Bits4:
Num = 4;
break;
}
unsigned char Val = (Bead & 0xF0) >> 4;
LLVM_DEBUG(dbgs() << "\tEncodeBits"
<< " Num: " << Num << " Val: 0x");
LLVM_DEBUG(dbgs().write_hex(Val) << "\n");
Buffer |= (Val << Offset);
return Num;
}
unsigned M68kMCCodeEmitter::encodeReg(unsigned ThisByte, uint8_t Bead,
const MCInst &MI, const MCInstrDesc &Desc,
uint64_t &Buffer, unsigned Offset,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
bool DA, Reg;
switch (Bead & 0xF) {
default:
llvm_unreachable("Unrecognized Bead code for register type");
case M68kBeads::DAReg:
Reg = true;
DA = true;
break;
case M68kBeads::DA:
Reg = false;
DA = true;
break;
case M68kBeads::DReg:
case M68kBeads::Reg:
Reg = true;
DA = false;
break;
}
unsigned Op = (Bead & 0x70) >> 4;
bool Alt = (Bead & 0x80);
LLVM_DEBUG(dbgs() << "\tEncodeReg"
<< " Op: " << Op << ", DA: " << DA << ", Reg: " << Reg
<< ", Alt: " << Alt << "\n");
auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op);
bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
MCOperand MCO;
if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) {
if (IsPCRel) {
assert(Alt &&
"PCRel addresses use Alt bead register encoding by default");
MCO = MI.getOperand(MIOpIdx + M68k::PCRelIndex);
} else {
MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemIndex : M68k::MemBase));
}
} else {
assert(!Alt && "You cannot use Alt register with a simple operand");
MCO = MI.getOperand(MIOpIdx);
}
unsigned RegNum = MCO.getReg();
auto RI = Ctx.getRegisterInfo();
unsigned Written = 0;
if (Reg) {
uint32_t Val = RI->getEncodingValue(RegNum);
Buffer |= (Val & 7) << Offset;
Offset += 3;
Written += 3;
}
if (DA) {
Buffer |= (uint64_t)M68kII::isAddressRegister(RegNum) << Offset;
Written++;
}
return Written;
}
static unsigned EmitConstant(uint64_t Val, unsigned Size, unsigned Pad,
uint64_t &Buffer, unsigned Offset) {
assert(Size + Offset <= 64 && isUIntN(Size, Val) && "Value does not fit");
// Writing Value in host's endianness
Buffer |= (Val & ((1ULL << Size) - 1)) << Offset;
return Size + Pad;
}
unsigned M68kMCCodeEmitter::encodeImm(unsigned ThisByte, uint8_t Bead,
const MCInst &MI, const MCInstrDesc &Desc,
uint64_t &Buffer, unsigned Offset,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
unsigned ThisWord = ThisByte / 2;
unsigned Size = 0;
unsigned Pad = 0;
unsigned FixOffset = 0;
int64_t Addendum = 0;
bool NoExpr = false;
unsigned Type = Bead & 0xF;
unsigned Op = (Bead & 0x70) >> 4;
bool Alt = (Bead & 0x80);
auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op);
bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
// The PC value upon instruction reading of a short jump will point to the
// next instruction, thus we need to compensate 2 bytes, which is the diff
// between the patch point and the PC.
if (IsPCRel && ThisWord == 0)
Addendum -= 2;
switch (Type) {
// ??? what happens if it is not byte aligned
// ??? is it even possible
case M68kBeads::Disp8:
Size = 8;
Pad = 0;
FixOffset = ThisByte + 1;
Addendum += 1;
break;
case M68kBeads::Imm8:
Size = 8;
Pad = 8;
FixOffset = ThisByte;
break;
case M68kBeads::Imm16:
Size = 16;
Pad = 0;
FixOffset = ThisByte;
break;
case M68kBeads::Imm32:
Size = 32;
Pad = 0;
FixOffset = ThisByte;
break;
case M68kBeads::Imm3:
Size = 3;
Pad = 0;
NoExpr = true;
break;
}
LLVM_DEBUG(dbgs() << "\tEncodeImm"
<< " Op: " << Op << ", Size: " << Size << ", Alt: " << Alt
<< "\n");
MCOperand MCO;
if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) {
if (IsPCRel) {
assert(!Alt && "You cannot use ALT operand with PCRel");
MCO = MI.getOperand(MIOpIdx + M68k::PCRelDisp);
} else {
MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemOuter : M68k::MemDisp));
}
if (MCO.isExpr()) {
assert(!NoExpr && "Cannot use expression here");
const MCExpr *Expr = MCO.getExpr();
// This only makes sense for PCRel instructions since PC points to the
// extension word and Disp8 for example is right justified and requires
// correction. E.g. R_68K_PC32 is calculated as S + A - P, P for Disp8
// will be EXTENSION_WORD + 1 thus we need to have A equal to 1 to
// compensate.
// TODO count extension words
if (IsPCRel && Addendum != 0) {
Expr = MCBinaryExpr::createAdd(
Expr, MCConstantExpr::create(Addendum, Ctx), Ctx);
}
Fixups.push_back(MCFixup::create(
FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc()));
// Write zeros
return EmitConstant(0, Size, Pad, Buffer, Offset);
}
} else {
MCO = MI.getOperand(MIOpIdx);
if (MCO.isExpr()) {
assert(!NoExpr && "Cannot use expression here");
const MCExpr *Expr = MCO.getExpr();
if (Addendum != 0) {
Expr = MCBinaryExpr::createAdd(
Expr, MCConstantExpr::create(Addendum, Ctx), Ctx);
}
Fixups.push_back(MCFixup::create(
FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc()));
// Write zeros
return EmitConstant(0, Size, Pad, Buffer, Offset);
}
}
int64_t I = MCO.getImm();
// Store 8 as 0, thus making range 1-8
if (Type == M68kBeads::Imm3 && Alt) {
assert(I && "Cannot encode Alt Imm3 zero value");
I %= 8;
} else {
assert(isIntN(Size, I));
}
uint64_t Imm = I;
// 32 bit Imm requires HI16 first then LO16
if (Size == 32) {
Offset += EmitConstant((Imm >> 16) & 0xFFFF, 16, Pad, Buffer, Offset);
EmitConstant(Imm & 0xFFFF, 16, Pad, Buffer, Offset);
return Size;
}
return EmitConstant(Imm & ((1ULL << Size) - 1), Size, Pad, Buffer, Offset);
}
#include "M68kGenMCCodeBeads.inc"
void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
@@ -490,79 +230,16 @@ void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
APInt EncodedInst(16, 0U);
APInt Scratch(16, 0U);
getBinaryCodeForInstr(MI, Fixups, EncodedInst, Scratch, STI);
if (EncodedInst.getBitWidth()) {
LLVM_DEBUG(dbgs() << "Instruction " << MCII.getName(Opcode) << "(" << Opcode
<< ") is using the new code emitter\n");
ArrayRef<uint64_t> Data(EncodedInst.getRawData(),
EncodedInst.getNumWords());
int64_t InstSize = EncodedInst.getBitWidth();
for (uint64_t Word : Data) {
for (int i = 0; i < 4 && InstSize > 0; ++i, InstSize -= 16) {
support::endian::write<uint16_t>(OS, static_cast<uint16_t>(Word),
support::big);
Word >>= 16;
}
}
return;
}
const uint8_t *Beads = getGenInstrBeads(MI);
if (!Beads || !*Beads) {
llvm_unreachable("*** Instruction does not have Beads defined");
}
uint64_t Buffer = 0;
unsigned Offset = 0;
unsigned ThisByte = 0;
for (uint8_t Bead = *Beads; Bead; Bead = *++Beads) {
// Check for control beads
if (!(Bead & 0xF)) {
switch (Bead >> 4) {
case M68kBeads::Ignore:
continue;
}
}
switch (Bead & 0xF) {
default:
llvm_unreachable("Unknown Bead code");
break;
case M68kBeads::Bits1:
case M68kBeads::Bits2:
case M68kBeads::Bits3:
case M68kBeads::Bits4:
Offset +=
encodeBits(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
break;
case M68kBeads::DAReg:
case M68kBeads::DA:
case M68kBeads::DReg:
case M68kBeads::Reg:
Offset +=
encodeReg(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
break;
case M68kBeads::Disp8:
case M68kBeads::Imm8:
case M68kBeads::Imm16:
case M68kBeads::Imm32:
case M68kBeads::Imm3:
Offset +=
encodeImm(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
break;
}
// Since M68k is Big Endian we need to rotate each instruction word
while (Offset / 16) {
support::endian::write<uint16_t>(OS, Buffer, support::big);
Buffer >>= 16;
Offset -= 16;
ThisByte += 2;
ArrayRef<uint64_t> Data(EncodedInst.getRawData(), EncodedInst.getNumWords());
int64_t InstSize = EncodedInst.getBitWidth();
for (uint64_t Word : Data) {
for (int i = 0; i < 4 && InstSize > 0; ++i, InstSize -= 16) {
support::endian::write<uint16_t>(OS, static_cast<uint16_t>(Word),
support::big);
Word >>= 16;
}
}
assert(Offset == 0 && "M68k Instructions are % 2 bytes");
assert((ThisByte && !(ThisByte % 2)) && "M68k Instructions are % 2 bytes");
}
MCCodeEmitter *llvm::createM68kMCCodeEmitter(const MCInstrInfo &MCII,

View File

@@ -0,0 +1,10 @@
# RUN: llc -O0 -mtriple=m68k -start-after=prologepilog -verify-machineinstrs %s -o - | FileCheck %s
name: is-pcrel-register-operand-legal
body: |
bb.0.entry:
; CHECK: move.l (0,%pc,%a0), (%a1)
; CHECK: move.l (%a0), (0,%pc,%a1)
MOV32jk $a1, 0, $a0, implicit-def $ccr
MOV32kj 0, $a1, $a0, implicit-def $ccr

View File

@@ -8,7 +8,6 @@ add_tablegen(llvm-tblgen LLVM
AsmWriterInst.cpp
Attributes.cpp
CallingConvEmitter.cpp
CodeBeadsGen.cpp
CodeEmitterGen.cpp
CodeGenDAGPatterns.cpp
CodeGenHwModes.cpp

View File

@@ -1,135 +0,0 @@
//===---------- CodeBeadsGen.cpp - Code Beads Generator -------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// CodeBeads are data fields carrying auxiliary information for instructions.
//
// Under the hood it's simply implemented by a `bits` field (with arbitrary
// length) in each TG instruction description, where this TG backend will
// generate a helper function to access it.
//
// This is especially useful for expressing variable length encoding
// instructions and complex addressing modes. Since in those cases each
// instruction is usually associated with large amount of information like
// addressing mode details used on a specific operand. Instead of retreating to
// ad-hoc methods to figure out these information when encoding an instruction,
// CodeBeads provide a clean table for the instruction encoder to lookup.
//===----------------------------------------------------------------------===//
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
using namespace llvm;
namespace {
class CodeBeadsGen {
RecordKeeper &Records;
public:
CodeBeadsGen(RecordKeeper &R) : Records(R) {}
void run(raw_ostream &OS);
};
void CodeBeadsGen::run(raw_ostream &OS) {
CodeGenTarget Target(Records);
std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
// For little-endian instruction bit encodings, reverse the bit order
Target.reverseBitsForLittleEndianEncoding();
ArrayRef<const CodeGenInstruction *> NumberedInstructions =
Target.getInstructionsByEnumValue();
// Emit function declaration
OS << "const uint8_t *llvm::" << Target.getInstNamespace();
OS << "::getMCInstrBeads(unsigned Opcode) {\n";
// First, get the maximum bit length among all beads. And do some
// simple validation
unsigned MaxBitLength = 0;
for (const CodeGenInstruction *CGI : NumberedInstructions) {
Record *R = CGI->TheDef;
if (!R->getValue("Beads"))
continue;
BitsInit *BI = R->getValueAsBitsInit("Beads");
if (!BI->isComplete()) {
PrintFatalError(R->getLoc(), "Record `" + R->getName() +
"', bit field 'Beads' is not complete");
}
MaxBitLength = std::max(MaxBitLength, BI->getNumBits());
}
// Number of bytes
unsigned Parts = MaxBitLength / 8;
// Emit instruction base values
OS << " static const uint8_t InstBits[][" << Parts << "] = {\n";
for (const CodeGenInstruction *CGI : NumberedInstructions) {
Record *R = CGI->TheDef;
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
!R->getValue("Beads")) {
OS << "\t{ 0x0 },\t// ";
if (R->getValueAsBit("isPseudo"))
OS << "(Pseudo) ";
OS << R->getName() << "\n";
continue;
}
BitsInit *BI = R->getValueAsBitsInit("Beads");
// Convert to byte array:
// [dcba] -> [a][b][c][d]
OS << "\t{";
for (unsigned p = 0; p < Parts; ++p) {
unsigned Right = 8 * p;
unsigned Left = Right + 8;
uint8_t Value = 0;
for (unsigned i = Right; i != Left; ++i) {
unsigned Shift = i % 8;
if (auto *B = dyn_cast<BitInit>(BI->getBit(i))) {
Value |= (static_cast<uint8_t>(B->getValue()) << Shift);
} else {
PrintFatalError(R->getLoc(), "Record `" + R->getName() +
"', bit 'Beads[" + Twine(i) +
"]' is not defined");
}
}
if (p)
OS << ',';
OS << " 0x";
OS.write_hex(Value);
OS << "";
}
OS << " }," << '\t' << "// " << R->getName() << "\n";
}
OS << "\t{ 0x0 }\n };\n";
// Emit initial function code
OS << " return InstBits[Opcode];\n"
<< "}\n\n";
}
} // End anonymous namespace
namespace llvm {
void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS) {
emitSourceFileHeader("Machine Code Beads", OS);
CodeBeadsGen(RK).run(OS);
}
} // namespace llvm

View File

@@ -25,7 +25,6 @@ enum ActionType {
NullBackend,
DumpJSON,
GenEmitter,
GenCodeBeads,
GenRegisterInfo,
GenInstrInfo,
GenInstrDocs,
@@ -82,8 +81,6 @@ cl::opt<ActionType> Action(
clEnumValN(DumpJSON, "dump-json",
"Dump all records as machine-readable JSON"),
clEnumValN(GenEmitter, "gen-emitter", "Generate machine code emitter"),
clEnumValN(GenCodeBeads, "gen-code-beads",
"Generate machine code beads"),
clEnumValN(GenRegisterInfo, "gen-register-info",
"Generate registers and register classes info"),
clEnumValN(GenInstrInfo, "gen-instr-info",
@@ -164,9 +161,6 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenEmitter:
EmitCodeEmitter(Records, OS);
break;
case GenCodeBeads:
EmitCodeBeads(Records, OS);
break;
case GenRegisterInfo:
EmitRegisterInfo(Records, OS);
break;

View File

@@ -67,7 +67,6 @@ void EmitAsmMatcher(RecordKeeper &RK, raw_ostream &OS);
void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS);
void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS);
void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS);
void EmitCodeBeads(RecordKeeper &RK, raw_ostream &OS);
void EmitDAGISel(RecordKeeper &RK, raw_ostream &OS);
void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS);
void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);