FPBench Logo

Writing FPCore using FPImp

An imperative intermediate language

The FPBench project's FPCore format is a common format for the floating-point research community. However, it can be challenging to translate source code originally written in an imperative language to FPCore. To help, FPBench provides FPImp, an imperative language that can be used as an intermediate language from which to generate FPCore.

This page describes the semantics of FPImp and describes the tools FPBench provides to manipulate it.

FPImp syntax and semantics

FPImp is a simple imperative programming language that compiles to FPCore. Like FPCore, it uses a simple S-expression syntax.

FPImp
( FPImp (symbol)* property* cmd* ( output expr* ))
cmd
[ = symbol expr ]
( while expr cmd* )
( if if-branch* )
if-branch
[ expr cmd* ]
[ else cmd* ]
High-level grammar of FPImp, an imperative intermediate language for writing FPCore. In an if statement, the else if-branch must come last.

Unlike FPCore, which is expression-oriented, FPImp has both statements and expressions. Expressions may be any FPCore expression, while the statements come in three types: assignments, while loops, and many-way if statements. The semantics of assignments, while, and if statements is standard.

FPImp also allows multiple outputs. This is helpful for translating code with Fortran out parameters or C pointer arguments. Note that output cmds are only valid at the end of an FPImp program—FPImp does not allow multiple exits from the a program.

Compiling FPImp to FPCore

The imp2core tool, which ships in the tools/ directory of the FPBench codebase, can compile FPImp programs to FPCore. Run:

racket tools/imp2core.rkt [options] < file.fpimp > file.fpcore

The imp2core compiler preserves propertys, and compiles each FPImp program to multiple FPCore computations, one for each output of the FPImp program.

imp2core accepts two options that modify its behavior:

--substitute
Do not produce FPCore let bindings, instead expanding the let bindings by substituting the bound variable's value in the final expression. Can produce much larger programs.
--canonicalize
Expand additions, subtractions, multiplications, and divisions with more than two arguments into binary operators. This option allows using shorthand arithmetic operators, but makes the actual order of operations, important for floating-point computation, less clear.
--one-to-one
For some uses, it is important that one FPImp program compile to a single FPCore program, even if the FPImp program contains multiple outputs. The --one-to-one option can be set to first to use only the first output of the FPImp expression, or to add, min, max, or mult to use that operator to combine the outputs of the FPImp expression.

FPImp reference interpreter

An FPImp reference interpreter is also located in the tools/ directory of the FPBench codebase, and can be run with:

racket tools/fpimp.rkt arguments ... < file.fpimp

The arguments in this case are real numbers using the standard floating-point number syntax. For example, running:

racket tools/fpimp.rkt 1.0 2.0
(FPImp (x y) [= z (+ x y)] (output z))

produces output 3.0.