We’re almost done with implementing our new machine function pass! Now, we need to ensure CMake is aware of the new machine function pass within M88kDivinstr.cpp. This file is then added to llvm/lib/Target/M88k/CMakeLists.txt:
add_llvm_target(M88kCodeGen
M88kAsmPrinter.cpp
M88kDivInstr.cpp
M88kFrameLowering.cpp
M88kInstrInfo.cpp
M88kISelDAGToDAG.cpp
The last step is to build LLVM with our new machine function pass implementation with the following commands. We require the -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=M88k CMake option to build the M88k target:
$ cmake -G Ninja ../llvm-project/llvm -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=M88k -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=”llvm”
$ ninja
With that, we’ve implemented the machine function pass, but wouldn’t it be interesting to see how it works? We can demonstrate the result of this pass by passing LLVM IR through llc.
A glimpse of running a machine function pass with llc
We have the following IR, which contains a division by zero:
$ cat m88k-divzero.ll
target datalayout = “E-m:e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-a:8:16-n32”
target triple = “m88k-unknown-openbsd”
@dividend = dso_local global i32 5, align 4
define dso_local i32 @testDivZero() 0 {
%1 = load i32, ptr @dividend, align 4
%2 = sdiv i32 %1, 0
ret i32 %2
}
Let’s feed it into llc:
$ llc m88k-divzero.ll
By doing this, we’ll see that, in the resulting assembly, by default, the division by zero checks, which are represented by bcnd.n (BCND) and tb0 (TRAP503), are inserted by our new machine function pass:
| %bb.1:
subu %r2, %r0, %r2
bcnd.n ne0, %r0, .LBB0_2
divu %r2, %r2, 0
tb0 0, %r3, 503
. . .
.LBB0_3:
bcnd.n ne0, %r0, .LBB0_4
divu %r2, %r2, 0
tb0 0, %r3, 503
However, let’s see what happens when we specify –m88k-no-check-zero-division to llc:
$ llc m88k-divzero.ll –m88k-no-check-zero-division
This option to the backend instructs llc not to run the pass that checks for the division by zero. The resulting assembly will not contain any BCND or TRAP503 instructions. Here’s an example:
| %bb.1:
subu %r2, %r0, %r2
divu %r2, %r2, 0
jmp.n %r1
subu %r2, %r0, %r2
As we can see, implementing a machine function pass requires several steps, but these procedures can be used as a guideline for you to implement any type of machine function pass that fits your needs. Since we have extensively explored the backend within this section, let’s switch gears and see how we can teach the frontend about the M88k target.