Adding register and instruction information – Instruction Selection-2
By Peggy Johnston / November 11, 2023 / No Comments / Adding the M88k backend to LLVM, Creating the disassembler, Global instruction selection, Implementing M88kSubtarget, ITCertification Exams
The M88kInstrInfo class has many hook methods we can override to accomplish special tasks, for example, for branch analysis and rematerialization. For now, we’re only overriding the expandPostRAPseudo() method, in which we expand the pseudo-instruction RET. Let’s begin with the header file, M88kInstrInfo.h:
- The header file begins with including the generated code:
define GET_INSTRINFO_HEADER
include “M88kGenInstrInfo.inc”
- The M88kInstrInfo class derives from the generated M88kGenInstrInfo class. Besides overriding the expandPostRAPseudo() method, the only other addition is that this class owns an instance of the previously defined class, M88kRegisterInfo:
namespace llvm {
class M88kInstrInfo : public M88kGenInstrInfo {
const M88kRegisterInfo RI;
[[maybe_unused]] M88kSubtarget &STI;
virtual void anchor();
public:
explicit M88kInstrInfo(M88kSubtarget &STI);
const M88kRegisterInfo &getRegisterInfo() const {
return RI;
}
bool
expandPostRAPseudo(MachineInstr &MI) const override;
} // end namespace llvm
The implementation is stored in the M88kInstrInfo.cpp class:
- Like the header file, the implementation begins with including the generated code:
define GET_INSTRINFO_CTOR_DTOR
define GET_INSTRMAP_INFO
include “M88kGenInstrInfo.inc”
- Then, we define the anchor() method, which is used to pin the vtable to this file:
void M88kInstrInfo::anchor() {}
- Finally, we expand RET in the expandPostRAPseudo() method. As its name suggests, this method is invoked after the register allocator runs and is intended to expand the pseudo-instruction, which may still be mixed with the machine code. If the opcode of the machine instruction, MI, is the pseudo-instruction, RET, we must insert the jmp %r1 jump instruction, which is the instruction to exit a function. Then, we copy all implicit operands that represent the values to return and we delete the pseudo instruction. If we need other pseudo-instructions during code generation, then we can extend this function to expand them here too:
bool M88kInstrInfo::expandPostRAPseudo(
MachineInstr &MI) const {
MachineBasicBlock &MBB = *MI.getParent();
switch (MI.getOpcode()) {
default:
return false;
case M88k::RET: {
MachineInstrBuilder MIB =
BuildMI(MBB, &MI, MI.getDebugLoc(),
get(M88k::JMP))
.addReg(M88k::R1, RegState::Undef);
for (auto &MO : MI.operands()) {
if (MO.isImplicit())
MIB.add(MO);
}
break;
}
}
MBB.erase(MI);
return true;
}
Both classes have minimal implementations. If you continue to develop the target, then many more methods need to be overridden. It is worth reading the comments in the TargetInstrInfo and TargetRegisterInfo base classes, which you can find in the llvm/include/llvm/CodeGen directory.
We still need more classes to get the instruction selection running. Next, we’ll look at frame lowering.