Implementing the top-level interface for the M88k target – Beyond Instruction Selection

Firstly, within llvm/lib/Target/M88k/M88k.h, let’s add two prototypes inside the llvm namespace declaration that will be used later:

  1. The machine function pass that will be implemented will be called M88kDivInstrPass. We will add a function declaration that initializes this pass and takes in the pass registry, which is a class that manages the registration and initialization of all passes:

void initializeM88kDivInstrPass(PassRegistry &);

  1. Next, the actual function that creates the M88kDivInstr pass is declared, with the M88k target machine information as its argument:

FunctionPass *createM88kDivInstr(const M88kTargetMachine &);

Adding the TargetMachine implementation for machine function passes
Next, we will analyze some of the changes that are required in llvm/lib/Target/M88k/M88kTargetMachine.cpp:

  1. Within LLVM, it’s common to give the user the option to toggle passes on or off. So, let’s provide the user the same flexibility with our machine function pass. We’ll start by declaring a command-line option called m88k-no-check-zero-division and initializing it to false, which implies that there will always be a check for zero division unless the user explicitly turns this off. We’ll add this under the llvm namespace declaration and is an option for llc:

using namespace llvm;
static cl::opt
NoZeroDivCheck(“m88k-no-check-zero-division”, cl::Hidden,
cl::desc(“M88k: Don’t trap on integer division by zero.”),
cl::init(false));

  1. It is also customary to create a formal method that returns the command-line value so that we can query it to determine whether the pass will be run. Our original command-line option will be wrapped in the noZeroDivCheck() method so that we can utilize the command-line result later:

M88kTargetMachine::~M88kTargetMachine() {}
bool M88kTargetMachine::noZeroDivCheck() const { return NoZeroDivCheck; }

  1. Next, inside LLVMInitializeM88kTarget(), where the M88k target and passes are registered and initialized, we will insert a call to the initializeM88kDivInstrPass() method that was declared earlier in llvm/lib/Target/M88k/M88k.h:

extern “C” LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM88kTarget() {
RegisterTargetMachine X(getTheM88kTarget());
auto &PR = *PassRegistry::getPassRegistry();
initializeM88kDAGToDAGISelPass(PR);
initializeM88kDivInstrPass(PR);
}

  1. The M88k target also needs to override addMachineSSAOptimization(), which is a method that adds passes to optimize machine instructions when they are in SSA form. Essentially, our machine function pass is added as a type of machine SSA optimization. This method is declared as a function that is to be overridden. We will add the full implementation at the end of M88kTargetMachine.cpp: bool addInstSelector() override;
    void addPreEmitPass() override;
    void addMachineSSAOptimization() override;
    . . .
    void M88kPassConfig::addMachineSSAOptimization() {
    addPass(createM88kDivInstr(getTM()));
    TargetPassConfig::addMachineSSAOptimization();
    }
  2. Our method that returns the command-line option to toggle the machine function pass on and off (the noZeroDivCheck() method) is also declared in M88kTargetMachine.h: ~M88kTargetMachine() override;
    bool noZeroDivCheck() const;

Leave a Reply

Your email address will not be published. Required fields are marked *