All About Compiler-Generated Code

Where is it? How to compile it?

By default: in a temporary directory, deleted when the compiler exits (only the executable remains).

--savec DIRECTORY:

makes it go to DIRECTORY and stay there.

To recompile:

make -f DIRECTORY/Makefile

--print-commands:

shows commands issued by the compiler

Why are my identifiers renamed in the generated code?

  • Note that all user identifiers are munged by default in Chapel’s generated code to prevent inadvertent conflicts with identifiers from other C libraries and headers against which Chapel is linked (see the chpl man page for --[no-]munge-user-idents for more information). This can have the downside of making the generated code not correspond with the Chapel source in a way that can make reading the code, as well as debugging and profiling it, slightly more complicated. Compiling with the --no-munge-user-idents flag can reduce the degree to which this is done (and for most programs, should still work fine).

  • In some cases, Chapel does additional munging in order to turn legal Chapel into legal C (e.g., Chapel supports overloads but C doesn’t). This munging cannot be disabled by a flag and is typically necessary (though Chapel is sometimes overly conservative in deciding to munge). Generally, the more C-like your code is, the less this should happen.

How to benchmark/time it?

  • in Chapel: you want to time only the important code, excluding the startup time. See the Time Module.

use Time;
var mytimer:Timer;
mytimer.clear();

mytimer.start();

... measured code goes here ...
mytimer.stop();

writeln("time taken: " + mytimer.elapsed() + " seconds");
  • build your runtime optimized:

    cd $CHPL_HOME/runtime
    make clean
    make DEBUG=0 OPTIMIZE=1
    

    Note: currently you can have only one compilation of the runtime.Manipulate $CHPL_HOME/{runtime,lib} yourself if you want to have one copy for timing, another for debugging, etc.

  • when compiling, use:

    --fast

    This option (a) removes safety checks (e.g. for null pointers, array index bounds, etc.), and (b) compiles the generated code with optimization.

  • in C code: mimick the Chapel runtime, for apples-to-apples, e.g:

// from chpltypes.h

typedef double _real64;

#define chpl_seconds_timer(time) ((_real64)((time).tv_sec))

#define chpl_microseconds_timer(time) ((_real64)((time).tv_usec))

// current timer, in fractional seconds
double gettimer(struct timeval *timer) {
   int dummy = gettimeofday(timer, NULL);  // ignore the return code
   return chpl_seconds_timer(*timer) + 1.0e-6 * chpl_microseconds_timer(*timer);
}

struct timeval mytimer;
double start = gettimer(&mytimer);

... measured code goes here ...
double elapsedSeconds = gettimer(&mytimer) - start;

Debugging the generated code

Using gdb and other debugging features are also discussed in:

$CHPL_HOME/doc/rst/usingchapel/debugging.rst

  • If you want to debug the runtime library as well, build your runtime so:

    cd $CHPL_HOME/runtime
    make clean
    make DEBUG=1 OPTIMIZE=0
    

    Note: currently you can have only one compilation of the runtime (see above).

  • When compiling, use:

    -g --savec DIRECTORY

  • By default gdb will step through/refer to the Chapel source code.

    To make gdb find it, put the following in your ~/.gdbinit:

define sdirs
 directory $arg0/modules/internal
 directory $arg0/modules/standard
 directory $arg0/modules/dists
 directory $arg0/modules/layouts
end

then call sdirs from the gdb prompt (do not use ~ or $CHPL_HOME), e.g.:

(gdb) sdirs /users/vass/chapel
(gdb)
  • To have gdb refer to the actual generated C code, compile with:

    -g --savec DIRECTORY2 --c-line-numbers

  • GDB’s TUI mode is discussed in CompilerDebugging.rst and, e.g., here:

  • To see the IDs of the AST nodes in the generated code (see CompilerIRTricks.txt):

    --gen-ids

Profiling the generated code

Some Chapel programmers have had success profiling Chapel’s generated code using gprof using the instructions given below. Others have had successes with the Linux-based perf command, HPCToolkit, or other performance analysis tools (not covered here).

To use gprof:

  • Note that, at present, this is only supported when using the C back-end, not the LLVM back-end. As a result, CHPL_TARGET_COMPILER must be set or inferred to something other than llvm.

  • For best results, be sure your runtime is compiled with OPTIMIZE=1 to reduce the time spent in runtime code. You may also want to build it with PROFILE=1 in order to have it included in your profiling report.

  • When compiling, use:

    --ccflags -pg --ldflags -pg --fast --savec DIRECTORY

    This produces a gprof-enabled executable.

    The use of --fast and --savec are not strictly necessary, but will improve execution time and give you access to the generated C code (in the named directory), respectively.

Miscellanea

grepcomp

greprt

grepmod

Shortcuts in $CHPL_HOME/util/devel to grep the compiler, runtime, and Chapel module sources, resp.