diff --git a/INSTALL.md b/INSTALL.md index cfb6d5d..d0a4a3f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,12 +1,12 @@ Byfl installation ================= -Byfl relies on [LLVM](http://www.llvm.org/) and [Clang](http://clang.llvm.org/) and can take advantage of [DragonEgg](http://dragonegg.llvm.org/). The `llvm-3.5` branch of Byfl is designed to work with LLVM/Clang/DragonEgg release 3.5.*x*. The `llvm-3.6` branch of Byfl is designed to work with LLVM/Clang release 3.6.*x*. The `llvm-3.7` branch of Byfl is designed to work with LLVM/Clang release 3.7.*x*. The `llvm-3.8` branch of Byfl is designed to work with LLVM/Clang release 3.8.*x*. The `master` branch of Byfl is designed to work with LLVM/Clang trunk (i.e., the post-3.8-release development code). +Byfl relies on [LLVM](http://www.llvm.org/) and [Clang](http://clang.llvm.org/) and can take advantage of [Flang](https://github.com/flang-compiler/flang). The `llvm-3.9` branch of Byfl is designed to work with LLVM/Clang release 3.9.*x*. The `llvm-4.0` branch of Byfl is designed to work with LLVM/Clang release 4.0.*x*. The `llvm-5.0` branch of Byfl is designed to work with LLVM/Clang release 5.0.*x*. The `master` branch of Byfl is designed to work with LLVM/Clang trunk (i.e., the post-5.0-release development code), but is often not kept up to date and is best avoided. Basic installation ------------------ -As long as LLVM's `llvm-config` program is in your path, the Free Software Foundation's canonical installation procedure for an out-of-source build should work: +As long as LLVM's `llvm-config` program is in your path, the [Free Software Foundation](https://www.fsf.org/)'s canonical installation procedure for an out-of-source build should work: ```bash mkdir build cd build @@ -27,11 +27,11 @@ libtoolize Run `../configure --help` for usage information. The [FSF's generic installation instructions](http://git.savannah.gnu.org/cgit/automake.git/tree/INSTALL) provide substantially more detail on customizing the configuration. -Note that DragonEgg requires [GCC](http://gcc.gnu.org/) versions 4.5-4.8 and LLVM/Clang 3.5. - Installation on Mac OS X ------------------------ +> These instructions currently apply to a no-longer-supported version of Byfl. They will be updated eventually. + A few extra steps are needed to build Byfl on OS X: 1. Install [Xcode](https://developer.apple.com/xcode/), which provides various standard tools, header files, and libraries. diff --git a/Makefile.am b/Makefile.am index 5ced83a..e050276 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,7 @@ SUBDIRS = include lib tools tests EXTRA_DIST = README.md INSTALL.md LICENSE.md gen_opcode2name # Sneaky trick: Output a sed command that will fully expand the prefix -# and exec_prefix variables in bf-gcc and bf-inst. +# and exec_prefix variables in bf-inst. sed-command: @echo $(SED) \ -e 's,$${exec_prefix},$(exec_prefix),g' \ diff --git a/README.md b/README.md index be681da..6cb78bb 100644 --- a/README.md +++ b/README.md @@ -36,16 +36,14 @@ The name "Byfl" comes from "bytes/flops". The very first version of the code co Installation ------------ -There are eight "release" branches of Byfl on GitHub: +There are four "release" branches of Byfl on GitHub: - * [`master`](https://github.com/lanl/Byfl), corresponding to LLVM trunk (often not up to date; best to avoid) + * [`master`](https://github.com/lanl/Byfl), corresponding to LLVM trunk (usually not up to date; best to avoid) * [`llvm-5.0`](https://github.com/lanl/Byfl/tree/llvm-5.0), corresponding to LLVM 5.0._x_ releases * [`llvm-4.0`](https://github.com/lanl/Byfl/tree/llvm-4.0), corresponding to LLVM 4.0._x_ releases * [`llvm-3.9`](https://github.com/lanl/Byfl/tree/llvm-3.9), corresponding to LLVM 3.9._x_ releases - * [`llvm-3.8`](https://github.com/lanl/Byfl/tree/llvm-3.8), corresponding to LLVM 3.8._x_ releases - * [`llvm-3.7`](https://github.com/lanl/Byfl/tree/llvm-3.7), corresponding to LLVM 3.7._x_ releases - * [`llvm-3.6`](https://github.com/lanl/Byfl/tree/llvm-3.6), corresponding to LLVM 3.6._x_ releases - * [`llvm-3.5`](https://github.com/lanl/Byfl/tree/llvm-3.5), corresponding to LLVM 3.5._x_ releases + +Byfl previously supported LLVM versions 3.5–3.8. Because these Byfl versions are no longer maintained, the corresponding branches have been removed. However, they were first snapshotted as tags [`llvm-3.5`](https://github.com/lanl/Byfl/tree/llvm-3.5-final), [`llvm-3.6`](https://github.com/lanl/Byfl/tree/llvm-3.6-final), [`llvm-3.7`](https://github.com/lanl/Byfl/tree/llvm-3.7-final), and [`llvm-3.8`](https://github.com/lanl/Byfl/tree/llvm-3.8-final) in case Byfl is desperately needed for one of those outdated LLVM versions. Be sure to download the Byfl branch that corresponds to your installed LLVM version. (Run `llvm-config --version` to check.) Then, the usual ```bash diff --git a/configure.ac b/configure.ac index 7f7c72a..cdd136f 100644 --- a/configure.ac +++ b/configure.ac @@ -239,39 +239,6 @@ if test "x$ac_cv_lib_sqlite3_sqlite3_errstr" != xno ; then fi AM_CONDITIONAL([SQLITE3_AVAILABLE], [test $BUILD_BFBIN2SQLITE3 = yes]) -dnl The GCC DragonEgg plugin, while not strictly required by Byfl, -dnl precludes the use of most of the Byfl wrapper scripts. -AC_ARG_VAR([DRAGONEGG], [absolute filename of the GCC DragonEgg plugin]) -if test "${DRAGONEGG:-no}" = no ; then - # The location of the DragonEgg plugin was not specified -- try to find it. - AC_CACHE_CHECK([for dragonegg.so], - [ax_cv_file_dragonegg_so], - [dnl - # Search for dragonegg.so in various likely places. - ax_cv_file_dragonegg_so=no - for dname in `$LLVM_CONFIG --libdir` `echo "$LD_LIBRARY_PATH" | $SED 's/:/\n/g'` /usr/local/lib* /usr/lib* ; do - if test -f "$dname/dragonegg.so" ; then - ax_cv_file_dragonegg_so="$dname/dragonegg.so" - break - fi - done - ]) - if test "x$ax_cv_file_dragonegg_so" = xno ; then - dnl Define where dragonegg.so *ought* to be but isn't. - DRAGONEGG="`$LLVM_CONFIG --libdir`/dragonegg.so" - else - DRAGONEGG="$ax_cv_file_dragonegg_so" - fi -else - ax_cv_file_dragonegg_so="$DRAGONEGG" -fi -AM_CONDITIONAL([HAVE_DRAGONEGG], [test "x$ax_cv_file_dragonegg_so" != xno]) -if test "x$ax_cv_file_dragonegg_so" = xno ; then - AC_SUBST([use_dragonegg], [no]) -else - AC_SUBST([use_dragonegg], [yes]) -fi - dnl Generate all of the Byfl Makefiles and other files. AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([include/Makefile]) @@ -288,12 +255,6 @@ AC_CONFIG_FILES([tools/postproc/bfbin2py], [ [MAKE="$MAKE" GREP="$GREP"]) AC_CONFIG_FILES([tools/wrappers/Makefile]) -AC_CONFIG_FILES([tools/wrappers/bf-gcc], [ - cat tools/wrappers/bf-gcc | `$MAKE -s sed-command | $GREP sed` > tools/wrappers/bf-gcc.tmp - mv tools/wrappers/bf-gcc.tmp tools/wrappers/bf-gcc - ], - [MAKE="$MAKE" - GREP="$GREP"]) AC_CONFIG_FILES([tools/wrappers/bf-clang], [ cat tools/wrappers/bf-clang | `$MAKE -s sed-command | $GREP sed` > tools/wrappers/bf-clang.tmp mv tools/wrappers/bf-clang.tmp tools/wrappers/bf-clang @@ -322,7 +283,3 @@ fi if test $BUILD_BFBIN2SQLITE3 = no ; then AC_MSG_WARN([Not building the bfbin2sqlite3 postprocessor because it requires SQLite3 (v3.7.15+)]) fi -if test "x$ax_cv_file_dragonegg_so" != xno -a ! -e "$DRAGONEGG" ; then - # The location of the DragonEgg plugin was specified but does not exist. - AC_MSG_WARN([$DRAGONEGG does not exist; did you specify an incorrect file for the DRAGONEGG variable?]) -fi diff --git a/tests/Makefile.am b/tests/Makefile.am index 843ccde..0dc683d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -8,7 +8,6 @@ TESTS = \ bf-clang-no-opts.sh \ bf-clang++-no-opts.sh \ bf-flang-no-opts.sh \ - bf-gcc-no-opts.sh \ bf-clang-many-opts.sh \ bfbin2cgrind.sh \ bfbin2csv.sh \ @@ -46,7 +45,6 @@ AM_TESTS_ENVIRONMENT = \ srcdir='$(srcdir)'; export srcdir; \ top_srcdir='$(top_srcdir)'; export top_srcdir; \ top_builddir='$(top_builddir)'; export top_builddir; \ - use_dragonegg='$(use_dragonegg)'; export use_dragonegg; \ use_flang='$(use_flang)'; export use_flang; # Older versions of Automake, such as what Travis CI is running at the time of diff --git a/tests/bf-gcc-no-opts.sh b/tests/bf-gcc-no-opts.sh deleted file mode 100755 index 5a24c37..0000000 --- a/tests/bf-gcc-no-opts.sh +++ /dev/null @@ -1,55 +0,0 @@ -#! /bin/sh - -####################################### -# Try compiling a simple program with # -# bf-gcc and no special Byfl options # -# # -# By Scott Pakin # -####################################### - -# Define some helper variables. The ":-" ones will normally be -# provided by the Makefile. -AWK=${AWK:-awk} -PERL=${PERL:-perl} -srcdir=${srcdir:-../../tests} -top_srcdir=${top_srcdir:-../..} -top_builddir=${top_builddir:-..} -gcc=${BF_GCC:-gcc} -bf_gcc="$top_builddir/tools/wrappers/bf-gcc" -use_dragonegg=${use_dragonegg:-yes} - -# Skip this test if we don't have DragonEgg. -if [ "x$use_dragonegg" != xyes ] ; then - exit 77 -fi - -# Log everything we do. Fail on the first error. -set -e -set -x - -# Test 1: Do the C compiler and linker work at all? -"$gcc" -g -o simple-gcc-no-opts "$srcdir/simple.c" - -# Test 2: Do the C compiler and linker work when invoked from the Byfl -# wrapper script? -"$PERL" -I"$top_srcdir/tools/wrappers" \ - "$bf_gcc" -bf-plugin="$top_builddir/lib/bytesflops/.libs/bytesflops.so" \ - -bf-verbose -g -o simple-gcc-no-opts "$srcdir/simple.c" \ - -L"$top_builddir/lib/byfl/.libs" -bf-disable=byfl - -# Test 3: Can the Byfl wrapper script compile, instrument, and link a program? -"$PERL" -I"$top_srcdir/tools/wrappers" \ - "$bf_gcc" -bf-plugin="$top_builddir/lib/bytesflops/.libs/bytesflops.so" \ - -bf-verbose -g -o simple-gcc-no-opts "$srcdir/simple.c" \ - -L"$top_builddir/lib/byfl/.libs" - -# Test 4: Does the Byfl-instrumented program run without error? -env LD_LIBRARY_PATH="$top_builddir/lib/byfl/.libs:$LD_LIBRARY_PATH" \ - ./simple-gcc-no-opts - -# Test 5: Can we postprocess the binary output? Are the results correct within -# an order of magnitude? -int_ops=`"$top_builddir/tools/postproc/bfbin2csv" --include=Program --flat-output simple-gcc-no-opts.byfl | "$AWK" -F, '$3 ~ /Integer operations/ {print $4}'` -if [ ! -z "$int_ops" ] && [ "$int_ops" -lt 100000 ] ; then - exit 1 -fi diff --git a/tools/postproc/bf_process_byfl_file.pod b/tools/postproc/bf_process_byfl_file.pod index 41da3f5..771605a 100644 --- a/tools/postproc/bf_process_byfl_file.pod +++ b/tools/postproc/bf_process_byfl_file.pod @@ -183,9 +183,8 @@ the F<.byfl> file. =head1 SEE ALSO bfbin2cgrind(1), bfbin2hdf5(1), bfbin2csv(1), bfbin2sqlite3(1), -bfbin2xmlss(1), bf-clang(1), bf-clang++(1), bf-gcc(1), bf-g++(1), -bf-gfortran(1), bf-gccgo(1), L +bfbin2xmlss(1), bf-clang(1), bf-clang++(1), bf-flang(1), +L =head1 AUTHOR diff --git a/tools/postproc/bfbin2cgrind.pod b/tools/postproc/bfbin2cgrind.pod index 819b4eb..f60d66c 100644 --- a/tools/postproc/bfbin2cgrind.pod +++ b/tools/postproc/bfbin2cgrind.pod @@ -37,10 +37,9 @@ KCachegrind for interactive analysis. =head1 SEE ALSO bfbin2csv(1), bfbin2hdf5(1), bfbin2hpctk(1), bfbin2sqlite3(1), -bfbin2xmlss(1), bf-clang(1), bf-clang++(1), bf-gcc(1), bf-g++(1), -bf-gfortran(1), bf-gccgo(1), L, L +bfbin2xmlss(1), bf-clang(1), bf-clang++(1), bf-flang(1), +L, +L =head1 AUTHOR diff --git a/tools/postproc/bfbin2csv.pod b/tools/postproc/bfbin2csv.pod index 096f1e6..ed58858 100644 --- a/tools/postproc/bfbin2csv.pod +++ b/tools/postproc/bfbin2csv.pod @@ -148,5 +148,5 @@ Scott Pakin, I awk(1), perl(1), bfbin2cgrind(1), bfbin2hdf5(1), bfbin2hpctk(1), bfbin2sqlite3(1), bfbin2xmlss(1), bf-clang(1), bf-clang++(1), -bf-gcc(1), bf-g++(1), bf-gfortran(1), bf-gccgo(1), L +bf-flang(1), +L diff --git a/tools/postproc/bfbin2hdf5.pod b/tools/postproc/bfbin2hdf5.pod index 74cd45b..486ef00 100644 --- a/tools/postproc/bfbin2hdf5.pod +++ b/tools/postproc/bfbin2hdf5.pod @@ -44,10 +44,9 @@ on that named pipe: =head1 SEE ALSO bfbin2cgrind(1), bfbin2csv(1), bfbin2hpctk(1), bfbin2sqlite3(1), -bfbin2xmlss(1), bf-clang(1), bf-clang++(1), bf-gcc(1), bf-g++(1), -bf-gfortran(1), bf-gccgo(1), L, L +bfbin2xmlss(1), bf-clang(1), bf-clang++(1), bf-flang(1), +L, +L =head1 AUTHOR diff --git a/tools/postproc/bfbin2hpctk.pod b/tools/postproc/bfbin2hpctk.pod index 71ef72f..545e421 100644 --- a/tools/postproc/bfbin2hpctk.pod +++ b/tools/postproc/bfbin2hpctk.pod @@ -38,10 +38,9 @@ end of the directory name to make it unique. L(1), bfbin2cgrind(1), bfbin2csv(1), bfbin2hdf5(1), bfbin2sqlite3(1), -bfbin2xmlss(1), bf-clang(1), bf-clang++(1), bf-gcc(1), bf-g++(1), -bf-gfortran(1), bf-gccgo(1), L, L +bfbin2xmlss(1), bf-clang(1), bf-clang++(1), bf-flang(1), +L, +L =head1 AUTHOR diff --git a/tools/postproc/bfbin2sqlite3.pod b/tools/postproc/bfbin2sqlite3.pod index 5180da2..aa2a122 100644 --- a/tools/postproc/bfbin2sqlite3.pod +++ b/tools/postproc/bfbin2sqlite3.pod @@ -70,10 +70,10 @@ B on that named pipe: =head1 SEE ALSO sqlite3(1), bfbin2cgrind(1), bfbin2csv(1), bfbin2hdf5(1), -bfbin2hpctk(1), bfbin2xmlss(1), bf-clang(1), bf-clang++(1), bf-gcc(1), -bf-g++(1), bf-gfortran(1), bf-gccgo(1), L, L +bfbin2hpctk(1), bfbin2xmlss(1), bf-clang(1), bf-clang++(1), +bf-flang(1), +L, +L =head1 AUTHOR diff --git a/tools/postproc/bfbin2xmlss.pod b/tools/postproc/bfbin2xmlss.pod index 093ccea..f1b3946 100644 --- a/tools/postproc/bfbin2xmlss.pod +++ b/tools/postproc/bfbin2xmlss.pod @@ -46,10 +46,9 @@ on that named pipe: =head1 SEE ALSO bfbin2cgrind(1), bfbin2csv(1), bfbin2hdf5(1), bfbin2hpctk(1), -bfbin2sqlite3(1), bf-clang(1), bf-clang++(1), bf-gcc(1), bf-g++(1), -bf-gfortran(1), bf-gccgo(1), L, L +bfbin2sqlite3(1), bf-clang(1), bf-clang++(1), bf-flang(1), +L, +L =head1 AUTHOR diff --git a/tools/wrappers/Makefile.am b/tools/wrappers/Makefile.am index 8e1a8bb..2835dea 100644 --- a/tools/wrappers/Makefile.am +++ b/tools/wrappers/Makefile.am @@ -5,17 +5,12 @@ # By Scott Pakin # ############################################ -if HAVE_DRAGONEGG -BF_GCC_SCRIPT=bf-gcc -endif - nodist_bin_SCRIPTS = \ $(BF_GCC_SCRIPT) \ bf-clang \ bf-inst EXTRA_DIST = \ - bf-gcc.in \ bf-clang.in \ bf-inst.in \ ParseCompilerOpts.pm \ @@ -36,32 +31,19 @@ install-parser: $(srcdir)/ParseCompilerOpts.pm $(INSTALL_DATA) -m 0755 -d "$(DESTDIR)$(perlsitelibdir)" $(INSTALL_DATA) "$(srcdir)/ParseCompilerOpts.pm" "$(DESTDIR)$(perlsitelibdir)/ParseCompilerOpts.pm" -install-compiler-scripts: bf-gcc bf-clang +install-compiler-scripts: bf-clang $(LN_S) -f bf-clang $(DESTDIR)$(bindir)/bf-clang++ $(LN_S) -f bf-clang $(DESTDIR)$(bindir)/bf-flang -if HAVE_DRAGONEGG - $(LN_S) -f bf-gcc $(DESTDIR)$(bindir)/bf-g++ - $(LN_S) -f bf-gcc $(DESTDIR)$(bindir)/bf-gfortran - $(LN_S) -f bf-gcc $(DESTDIR)$(bindir)/bf-gccgo -endif install-mpi-scripts: $(srcdir)/make-bf-mpi -if HAVE_DRAGONEGG - $(AM_V_GEN) $(PERL) $(srcdir)/make-bf-mpi mpicc bf-gcc OMPI_CC MPICH_CC $(bindir) > $(DESTDIR)$(bindir)/bf-mpicc - $(AM_V_GEN) $(PERL) $(srcdir)/make-bf-mpi mpicxx bf-g++ OMPI_CXX MPICH_CXX $(bindir) > $(DESTDIR)$(bindir)/bf-mpicxx - $(AM_V_GEN) $(PERL) $(srcdir)/make-bf-mpi mpifort bf-gfortran OMPI_FC MPICH_F90 $(bindir) > $(DESTDIR)$(bindir)/bf-mpifort - $(AM_V_GEN) $(PERL) $(srcdir)/make-bf-mpi mpif90 bf-gfortran OMPI_FC MPICH_F90 $(bindir) > $(DESTDIR)$(bindir)/bf-mpif90 - $(AM_V_GEN) $(PERL) $(srcdir)/make-bf-mpi mpif77 bf-gfortran OMPI_F77 MPICH_F77 $(bindir) > $(DESTDIR)$(bindir)/bf-mpif77 -else $(AM_V_GEN) $(PERL) $(srcdir)/make-bf-mpi mpicc bf-clang OMPI_CC MPICH_CC $(bindir) > $(DESTDIR)$(bindir)/bf-mpicc $(AM_V_GEN) $(PERL) $(srcdir)/make-bf-mpi mpicxx bf-clang++ OMPI_CXX MPICH_CXX $(bindir) > $(DESTDIR)$(bindir)/bf-mpicxx $(AM_V_GEN) $(PERL) $(srcdir)/make-bf-mpi mpifort bf-flang OMPI_FC MPICH_F90 $(bindir) > $(DESTDIR)$(bindir)/bf-mpifort $(AM_V_GEN) $(PERL) $(srcdir)/make-bf-mpi mpif90 bf-flang OMPI_FC MPICH_F90 $(bindir) > $(DESTDIR)$(bindir)/bf-mpif90 $(AM_V_GEN) $(PERL) $(srcdir)/make-bf-mpi mpif77 bf-flang OMPI_F77 MPICH_F77 $(bindir) > $(DESTDIR)$(bindir)/bf-mpif77 -endif chmod 0755 $(DESTDIR)$(bindir)/bf-mpi* -install-man1-pages: bf-gcc bf-clang bf-inst +install-man1-pages: bf-clang bf-inst $(INSTALL) -d "$(DESTDIR)$(mandir)/man1" $(RM) "$(DESTDIR)$(mandir)/man1/bf-clang.1" \ "$(DESTDIR)$(mandir)/man1/bf-clang++.1" \ @@ -76,23 +58,6 @@ install-man1-pages: bf-gcc bf-clang bf-inst "$(DESTDIR)$(mandir)/man1/bf-flang.1" $(AM_V_GEN) $(POD2MAN) --center="$(MAN_CATEGORY)" --release="$(MAN_RELEASE)" bf-inst > \ "$(DESTDIR)$(mandir)/man1/bf-inst.1" -if HAVE_DRAGONEGG - $(RM) "$(DESTDIR)$(mandir)/man1/bf-gcc.1" \ - "$(DESTDIR)$(mandir)/man1/bf-g++.1" \ - "$(DESTDIR)$(mandir)/man1/bf-gfortran.1" \ - "$(DESTDIR)$(mandir)/man1/bf-gccgo.1" - $(AM_V_GEN) $(POD2MAN) --center="$(MAN_CATEGORY)" --release="$(MAN_RELEASE)" bf-gcc > \ - "$(DESTDIR)$(mandir)/man1/bf-gcc.1" - $(AM_V_GEN) cat "$(DESTDIR)$(mandir)/man1/bf-gcc.1" | \ - $(PERL) -ne 's/gcc/g++/g; s/\bC (compiler|code)/C++ $$1/g; s/myprog\.c/myprog.cpp/g; s/BF_GCC/BF_GXX/g; print' > \ - "$(DESTDIR)$(mandir)/man1/bf-g++.1" - $(AM_V_GEN) cat "$(DESTDIR)$(mandir)/man1/bf-gcc.1" | \ - $(PERL) -ne 's/gcc/gfortran/g; s/\bC (compiler|code)/Fortran $$1/g; s/myprog\.c/myprog.f90/g; s/BF_GCC/BF_GFORTRAN/g; print' > \ - "$(DESTDIR)$(mandir)/man1/bf-gfortran.1" - $(AM_V_GEN) cat "$(DESTDIR)$(mandir)/man1/bf-gcc.1" | \ - $(PERL) -ne 's/gcc/gccgo/g; s/\bC (compiler|code)/Go $$1/g; s/myprog\.c/myprog.go/g; s/BF_GCC/BF_GCCGO/g; print' > \ - "$(DESTDIR)$(mandir)/man1/bf-gccgo.1" -endif install-man3-pages: $(srcdir)/ParseCompilerOpts.pm $(INSTALL) -d "$(DESTDIR)$(mandir)/man3" @@ -102,7 +67,7 @@ install-man3-pages: $(srcdir)/ParseCompilerOpts.pm install-exec-local: install-parser install-compiler-scripts install-mpi-scripts install-man1-pages install-man3-pages uninstall-local: - for script in bf-clang bf-clang++ bf-flang bf-gcc bf-g++ bf-gfortran bf-gccgo bf-mpicc bf-mpicxx bf-mpifort bf-mpif90 bf-mpif77 bf-inst ; do \ + for script in bf-clang bf-clang++ bf-flang bf-mpicc bf-mpicxx bf-mpifort bf-mpif90 bf-mpif77 bf-inst ; do \ $(RM) "$(DESTDIR)$(bindir)/$${script}" ; \ $(RM) "$(DESTDIR)$(mandir)/man1/$${script}.1" ; \ done diff --git a/tools/wrappers/ParseCompilerOpts.pm b/tools/wrappers/ParseCompilerOpts.pm index c19ee9c..18869cc 100644 --- a/tools/wrappers/ParseCompilerOpts.pm +++ b/tools/wrappers/ParseCompilerOpts.pm @@ -23,7 +23,7 @@ ParseCompilerOpts - Parse GCC and Clang options into compiler and linker options =head1 DESCRIPTION This module is intended to be used internally by the Byfl wrapper -scripts (bf-gcc, bf-g++, bf-gfortran, and bf-gccgo). +scripts (bf-clang, bf-clang++, and bf-flang). =head1 AUTHOR diff --git a/tools/wrappers/bf-gcc.in b/tools/wrappers/bf-gcc.in deleted file mode 100755 index 72e9b06..0000000 --- a/tools/wrappers/bf-gcc.in +++ /dev/null @@ -1,950 +0,0 @@ -#! /usr/bin/env perl - -################################################## -# Wrap gcc with options for ByFl instrumentation # -# By Scott Pakin # -################################################## - -use constant DEBUG => 0; - -use Cwd qw(abs_path); -use File::Basename; -use File::Copy; -use File::Spec; -use File::Temp qw(tempdir); -use File::stat; -use Getopt::Long qw(GetOptionsFromArray); -use lib '@perlsitelibdir@'; # Find ParseCompilerOpts if installed in a non-standard location. -use ParseCompilerOpts; -use v5.10.1; -use warnings; -no if $] >= 5.017011, warnings => 'experimental::smartmatch'; -use strict; - -# Specify some installation locations. -my $dragonegg = '@DRAGONEGG@'; -my $byfl_plugin = '@plugindir@/bytesflops.so'; -my $byfl_libdir = '@libdir@'; -my $llvm_libdir = '@llvm_libdir@'; - -# Store the name of this script and the name of the underlying compiler. -my $progname = basename $0; -my $compiler = substr($progname, 3); -my $compiler_env_var = "BF_" . uc($compiler); -$compiler_env_var =~ s/\W/X/g; # "G++" --> "GXX", e.g. -$compiler = $ENV{$compiler_env_var} if defined $ENV{$compiler_env_var}; - -# Let the user increase this script's verbosity. -my $verbosity = 0; - -# Let the user request static analysis in addition to instrumentation. -my $static_analysis = 0; - -# Optimization level requested on the command line via -O. Note: Not -# necessary numeric (e.g., "-Os"). -my $optimization_level = "0"; - -# Take bytesflops options from the BF_OPTS environment variable. -my @bf_options = split(" ", $ENV{"BF_OPTS"} || ""); - -# Let the user disable either the bytesflops plugin, DragonEgg IR -# emission, or everything besides command-line filtering. -my $bf_disable = "none"; - -# Apply GCC's -save-temps option to our temporary files as well. -my $save_temps = "no"; - -# Define a function that optionally prints, then executes a system -# command, aborting on failure. If the first argument is "NO FAIL", -# then return an error code rather than aborting. -sub execute_command (@) -{ - my $die_on_fail = 1; - if ($_[0] eq "NO FAIL") { - $die_on_fail = 0; - shift; - } - my @command = @_; - if ($verbosity > 0) { - print STDERR join(" ", map {/\s/ ? "'$_'" : $_} @command), "\n"; - } - return $? >> 8 if system(@command) == 0 || !$die_on_fail; - die "${progname}: Aborting\n"; -} - -# Define a function that removes a set of intermediate files unless -# -save-temps is specified, in which case it either leaves the files -# where they are or moves them to the current directory. -sub remove_files (@) -{ - my @deletable = map {-e $_ ? $_ : ()} @_; - if ($save_temps eq "no") { - # Remove intermediate files. - print STDERR "rm -f @deletable\n" if $verbosity > 0; - unlink(@deletable) || die "${progname}: $!\n"; - } - elsif ($save_temps eq "cwd") { - # Move intermediate files to the current directory. - print STDERR "mv @deletable .\n" if $verbosity > 0; - foreach my $fname (@deletable) { - move($fname, ".") || die "${progname}: $!\n"; - } - } - else { - # Leave intermediate files where they are. - } -} - -# Define a subroutine that initializes the default and gcc-specific -# library search paths. -my @default_lib_path; # Linker's default search path -my @gcc_lib_path; # Additional path elements gcc passes to ld -sub initialize_lib_paths () -{ - # Find the default library path with the compiler and ld's help. - my $sysroot = "/"; # Directory to substitute for "=" in a SEARCH_DIR - if (!@default_lib_path) { - local $/ = undef; - open(GCCINFO, "$compiler -v -Wl,--verbose 2>&1|") || die "${progname}: $!\n"; - my $gccinfo = ; - close GCCINFO; - $sysroot = $1 if $gccinfo =~ /\b--with-sysroot=(\S+)/s; - if ($gccinfo =~ /\bLIBRARY_PATH=([^\n]+)/gs) { - # Search path passed via -L flags from gcc to ld - push @gcc_lib_path, split ":", $1; - } - while ($gccinfo =~ /\bSEARCH_DIR\(\"(.*?)\"\);/gs) { - # Search path from the default linker script - my $dirname = $1; - $dirname =~ s/^=/$sysroot/; - push @default_lib_path, File::Spec->canonpath($dirname); - } - } -} - -# Define a function that finds a .a file specified with "-l" -# given and a search path (list of arguments to -L). -sub find_archive_file ($@) -{ - # Search each path in turn for the given .a file. - my $aname = "lib" . $_[0] . ".a"; - foreach my $dirname (@_[1..$#_], @gcc_lib_path, @default_lib_path) { - my $filespec = File::Spec->catfile($dirname, $aname); - return $filespec if -e $filespec; - } - return undef; -} - -# Define a function that extracts a .bc file from a .o file wrapper. -# This function returns the new filename. -sub extract_bitcode ($) -{ - # Quit early if we can. - my $ofile = $_[0]; - my ($base, $dir, $suffix) = fileparse $ofile, "\\.[^.]+"; - return $ofile if $suffix ne ".o"; - my $bcfile = File::Spec->abs2rel(File::Spec->catfile($dir, $base . ".bc")); - return $bcfile if -e $bcfile; # We've already extracted the .bc file. - - # Extract the bitcode if we can. - return $ofile if execute_command("NO FAIL", - "objcopy", "--output-target=binary", - "--only-section=.bitcode", - $ofile, $bcfile) != 0; - if (-z $bcfile) { - # objcopy successfully found no .bitcode section and returned - # a zero-byte file -- delete it and pretend objcopy failed. - unlink $bcfile; - return $ofile; - } - return $bcfile; -} - -# Define a function that converts a .a file containing LLVM bitcode -# wrapped within a .o wrapper into a .bc file containing real LLVM -# bitcode. This function returns the new filename. -sub convert_archive_file ($) -{ - # Quit early if we can. - my $afile = $_[0]; - return $afile if -e $afile && !-w $afile; # We can't write the file so it must not contain our bitcode wrappers. - - # Create a work directory and cd into it. - my $workdir = tempdir($progname . "-XXXXXX", - DIR => ".", - CLEANUP => 1); - $afile = abs_path($afile); - chdir $workdir || die "${progname}: $!\n"; - local $SIG{"__DIE__"} = sub ($) { - # Leave the work directory before aborting. - chdir ".."; - die $_[0]; - }; - - # Extract the contents of the .a file. - execute_command("ar", ($verbosity > 0 ? "xv" : "x"), $afile); - - # Extract a .bc file from each .o file. - my @bcfiles; - foreach my $ofile (<*.o .*.o>) { - my $bcfile = extract_bitcode $ofile; - push @bcfiles, $bcfile if $bcfile ne $ofile; - } - - # Convert each .bc file to a real .o file. - foreach my $bcfile (@bcfiles) { - execute_command("llc", $bcfile); - my $sfile = $bcfile; - $sfile =~ s/\.bc$/.s/; - my $ofile = $bcfile; - $ofile =~ s/\.bc$/.o/; - execute_command("as", "-o", $ofile, $sfile); - } - - # Re-archive the real .o files into a single .a file. - execute_command("ar", $verbosity > 0 ? "rv" : "r", $afile, glob "*.o .*.o"); - - # Leave the work directory so it can be removed. - chdir ".."; - return $afile; -} - -########################################################################### - -# Parse the command line. -my @constructed_ARGV = (@bf_options, @ARGV); -Getopt::Long::Configure("pass_through"); -GetOptionsFromArray(\@constructed_ARGV, - "bf-verbose+" => \$verbosity, - "bf-static" => \$static_analysis, - "bf-dragonegg=s" => \$dragonegg, - "bf-libdir=s" => \$byfl_libdir, - "bf-plugin=s" => \$byfl_plugin, - "bf-disable=s" => \$bf_disable) - || die "${progname}: Failed to parse the command line\n"; -given ($bf_disable) { - when ("none") { - # Disable nothing; run normally. - } - when ("byfl") { - # Disable the bytesflops plugin. (This case is handled later). - } - when ("bitcode") { - # Use the DragonEgg plugin for code optimization, but generate - # native object files. - exit execute_command($compiler, "-fplugin=$dragonegg", grep {!m/^--?bf-/} @constructed_ARGV); - } - when ("dragonegg") { - # Disable DragonEgg entirely and just use the underlying compiler. - exit execute_command($compiler, grep {!m/^--?bf-/} @constructed_ARGV); - } - default { - die "${progname}: I don't know how to disable \"$bf_disable\"" - . ' (must be one of "none", "byfl", "bitcode", or "dragonegg")' . "\n"; - } -} -@bf_options = grep {/^--?bf-/} @constructed_ARGV; -@bf_options = map {s/^--/-/; $_} @bf_options; -@bf_options = grep {!/^-bf-(verbose|static|dragonegg|libdir|disable)/} @bf_options; -my @parse_info = parse_compiler_options(grep {!/^--?bf-/} @constructed_ARGV); -my %build_type = %{$parse_info[0]}; -my @target_filenames = @{$parse_info[1]}; -my @compiler_opts = @{$parse_info[2]}; -my @linker_opts = @{$parse_info[3]}; -my @leftover_values = @{$parse_info[4]}; - -# Check if we're neither compiling nor linking. -if (!defined $build_type{"compile"} && !defined $build_type{"link"}) { - # Preprocessing only -- pass all of our arguments to the compiler. - exit execute_command(($compiler, @constructed_ARGV)); -} -die "${progname}: No input files specified. Aborting.\n" if !@constructed_ARGV; - -# Define a map from source files to object files. -my %src2obj; # Map from a source-file name to an object-file name -my @source_files; # Subset of @leftover_values that represents source code -my @object_files; # Subset of @target_filenames that represents object code -foreach my $fname (@leftover_values) { - my ($base, $dir, $suffix) = fileparse $fname, "\\.[^.]+"; - push @source_files, $fname if $suffix !~ /\.[oa]$/ && $suffix ne ".so"; -} -if (defined $build_type{"link"}) { - # Linking -- object files are generated implicitly from source files. - foreach my $srcname (@source_files) { - my ($base, $dir, $suffix) = fileparse $srcname, "\\.[^.]+"; - push @object_files, $base . ".o"; - } -} -else { - # Compiling only -- object files are a subset of @target_filenames. - @object_files = grep {/\.o$/} @target_filenames; -} -if ($#source_files != $#object_files) { - my $vs = sprintf "%d vs. %d", 1+$#source_files, 1+$#object_files; - die "${progname}: Source-file list and object-file list contain different number of elements ($vs)"; -} -foreach my $i (0 .. $#source_files) { - $src2obj{$source_files[$i]} = $object_files[$i]; -} - -# Determine if we should keep our intermediate files and if so, where -# to put them. -foreach my $opt_arg (@compiler_opts, @linker_opts) { - my ($opt, $arg) = @$opt_arg; - if ($opt eq "save-temps") { - if (!defined $arg) { - $save_temps = "cwd"; - } - elsif ($arg eq "cwd") { - $save_temps = "cwd"; - } - elsif ($arg eq "obj") { - $save_temps = "obj"; - } - else { - $save_temps = "no"; - } - } -} - -# If we're compiling, then add options to invoke the DragonEgg plugin -# and produce LLVM IR. -if (defined $build_type{"compile"}) { - # Construct a command line. - my @command_line = ($compiler, - "-g", - "-fplugin=$dragonegg", - "-fplugin-arg-dragonegg-emit-ir"); - foreach my $opt_arg (@compiler_opts) { - my ($opt, $arg) = @$opt_arg; - if (defined $arg) { - # The option has an argument. - if ($opt eq "O") { - push @command_line, "-$opt$arg"; - $optimization_level = $arg; - } - elsif ($opt eq "g") { - push @command_line, "-$opt$arg"; - } - elsif ($opt eq "o") { - # Ignore -o. We'll be generating intermediate bitcode - # files and later producing object files from those. - } - elsif ($opt =~ /^([xIJ]|M[FTQ])$/) { - # A few options do not accept an equals sign; they - # require a space. - push @command_line, ("-$opt", $arg); - } - else { - push @command_line, "-$opt=$arg"; - } - } - else { - # The option does not have an argument. - if ($opt eq "c" || substr($opt, 0, 1) eq "g") { - # Ignore -c. We'll soon be replacing it with -S. - # Ignore -g. We'll be adding it in explicitly. - } - else { - push @command_line, "-" . $opt; - } - } - } - push @command_line, "-S"; # Override options that conflict with -S. - push @command_line, @source_files; - - # Execute the command line. - execute_command @command_line; - - # Run the Byfl LLVM pass on each bitcode file generated. Then, - # very sneakily embed the bitcode within a .o file so as not to - # confuse the invoking Makefile. - foreach my $srcfile (@source_files) { - # Prepare to run the Byfl LLVM pass. - my $ofile = $src2obj{$srcfile}; - my $sfile = basename $srcfile; - $sfile =~ s/\.[^.]+$/.s/; - my $bcfile = $sfile; - $bcfile =~ s/\.s$/.bc/; - my $opt_bcfile = $bcfile; - $opt_bcfile =~ s/\.bc$/.opt.bc/; - my $byfl_bcfile = $bcfile; - $byfl_bcfile =~ s/\.bc$/.byfl.bc/; - my @deletable = ($sfile, $bcfile, $opt_bcfile, $byfl_bcfile); - - # Handle the obscure special case of the same input file being - # specified multiple times on the same command line. In this - # case, the .s file is deleted/moved after the first time the - # input file is processed, which would cause opt to fail to - # find its input file and therefore abort. - next if !-e $sfile; - - # add --debug-pass=Structure to debug - # Run the static analyzer if -bf-static was specified. - execute_command("opt", "-load", "$byfl_plugin", - "-bytesflops", @bf_options, - "-analyze", "$sfile") if $static_analysis; - - # Unfortunately, DragonEgg's bitcode generation apparently - # runs *before* GCC code optimizations. This implies that - # Byfl is analyzing unoptimized code, which is likely to - # produce substantially different output from - # binary-instrumentation tools. We therefore explicitly - # run an optimization pass before Byfl instrumentation if - # any optimizations are specified on the command line. - my $infile = $sfile; - my $optlevel = $optimization_level; - if ($optimization_level ne "0") { - # Make a few modifications to the optimization level - # specified on the command line for opt's benefit. - # Specifically, replace "-Ofast" and any "-O" for n>3 - # with "-O3". - $optlevel = "3" if $optlevel eq "fast" || ($optlevel =~ /^(\d+)$/ && $1 > 3); - execute_command("opt", "-O$optlevel", - $infile, "-o", $opt_bcfile); - $infile = $opt_bcfile; - } - - # Instrument with Byfl then optimize the result using the LLVM - # optimizer at -O3 or higher (unless -Os or some other - # non-numeric optimization level is specified). - if ($bf_disable eq "byfl") { - # Disable the bytesflops plugin if so instructed. - if ($optimization_level eq "0") { - execute_command("llvm-as", "-o", $bcfile, $sfile); - } - else { - print STDERR "mv $opt_bcfile $bcfile\n" if $verbosity > 0; - rename($opt_bcfile, $bcfile) || die "${progname}: $!\n"; - } - } - else { - # Normally, we run Byfl instrumentation. - execute_command("opt", "-load", "$byfl_plugin", - "-bytesflops", @bf_options, - $infile, "-o", $byfl_bcfile); - if ($optlevel =~ /^\d+$/ && $optlevel ne "0" ) { - # Numeric optimization level -- round to -O3 or higher - # then run the bitcode through opt. - my $post_byfl_opt = $optlevel; - $post_byfl_opt = "3" if $post_byfl_opt < 3; - execute_command("opt", "-O$post_byfl_opt", - $byfl_bcfile, "-o", $bcfile); - } - else { - # Non-numeric optimization level -- don't run opt. - print STDERR "mv $byfl_bcfile $bcfile\n" if $verbosity > 0; - rename($byfl_bcfile, $bcfile) || die "${progname}: $!\n"; - } - } - - # Embed the LLVM bitcode within a .o file. - execute_command($compiler, "-o", $ofile, "-c", "-x", "c", "/dev/null"); - execute_command("objcopy", "--add-section", ".bitcode=$bcfile", - "--set-section-flags", ".bitcode=alloc", $ofile); - - # Remove the .s and .bc files. - remove_files(@deletable); - } -} - -# If we're linking, extract LLVM bitcode from all of our object files -# and replace ld options with clang options. -if (defined $build_type{"link"}) { - # Convert the linker options from gcc/ld to clang. - my @llvm_ld_options; # Options to pass to clang - my @Ldirs; # Directories listed with -L - my @lfiles; # Libraries listed with -l - foreach my $opt_arg (@linker_opts) { - my ($opt, $arg) = @$opt_arg; - if ($opt eq "L") { - push @Ldirs, $arg; - push @llvm_ld_options, "-L$arg"; - } - elsif ($opt eq "l") { - push @lfiles, $arg; - } - elsif ($opt eq "o") { - push @llvm_ld_options, ("-o", $arg); - } - elsif ($opt eq "rdynamic") { - } - elsif ($opt eq "O") { - # Make a few modifications to the optimization level - # specified on the command line for clang's benefit. - # Specifically, "-Ofast" with "-O3" and any "-O" for - # n>4 with "-O4". - if ($arg eq "fast") { - $arg = "3"; - } - elsif ($arg =~ /^(\d+)$/ && $1 > 4) { - $arg = "4"; - } - push @llvm_ld_options, "-$opt$arg"; - } - elsif ($opt =~ /^(pg|fopenmp)$/) { - push @llvm_ld_options, "-$opt"; - } - elsif ($opt =~ /^(march|mtune)$/) { - push @llvm_ld_options, "-$opt=$arg"; - } - else { - push @llvm_ld_options, ("-Xlinker", "-$opt"); - push @llvm_ld_options, ("-Xlinker", "$arg") if defined $arg; - } - } - - # Add a few default options. We explicitly add the compiler's - # default library search path because it will likely differ from - # clang's. Also, note that we explicitly add "-L$byfl_libdir". - # This is needed to resolve the library dependence specified in - # bytesflops.cpp. - initialize_lib_paths(); - foreach my $dirname (@gcc_lib_path) { - push @llvm_ld_options, "-L" . $dirname; - } - push @llvm_ld_options, ("-L$byfl_libdir", "-L$llvm_libdir", "-lm"); - if ($bf_disable eq "none") { - push @llvm_ld_options, ("-rpath", $byfl_libdir, "-lbyfl"); - push @llvm_ld_options, "-lpthread" if grep {/^-bf-thread-safe$/} @bf_options; - } - push @llvm_ld_options, "-lstdc++" if $progname eq "bf-g++"; - push @llvm_ld_options, "-lgfortran" if $progname eq "bf-gfortran"; - push @llvm_ld_options, ("-lgobegin", "-lgo") if $progname eq "bf-gccgo"; - - # Construct a list of linker inputs. - my @llvm_ld_inputs; # Ordered list of .a and .o files. - foreach my $fname (@leftover_values) { - my $gen_o = $src2obj{$fname}; # A .o file generated from source - if (defined $gen_o) { - push @llvm_ld_inputs, $gen_o; - } - elsif ($fname =~ /\.a$/) { - my $bcafile = convert_archive_file $fname; - if ($bcafile =~ /\.bc$/) { - # Instrumented library - push @llvm_ld_inputs, $bcafile; - } - else { - # Uninstrumented library - push @llvm_ld_options, $fname; - } - } - else { - push @llvm_ld_inputs, $fname; - } - } - @llvm_ld_inputs = map {extract_bitcode $_} @llvm_ld_inputs; - - # Add all libraries specified with -l to the linker inputs. - foreach my $lfile (@lfiles) { - my $afile = find_archive_file($lfile, @Ldirs); - if (!defined $afile) { - push @llvm_ld_options, "-l$lfile"; - next; - } - my $bcafile = convert_archive_file $afile; - if ($bcafile =~ /\.bc$/) { - push @llvm_ld_inputs, $bcafile; - } - else { - push @llvm_ld_options, "-l$lfile"; - } - } - - # Run the linker. - execute_command("clang", @llvm_ld_inputs, @llvm_ld_options); - - # Clean up all of the .bc files we created. - remove_files(grep(/\.bc$/, @llvm_ld_inputs)); -} - -########################################################################### - -__END__ - -=head1 NAME - -bf-gcc - Inject Byfl instrumentation while compiling a program - -=head1 SYNOPSIS - -bf-gcc -[B<-bf-by-func>] -[B<-bf-call-stack>] -[B<-bf-data-structs>] -[B<-bf-types>] -[B<-bf-inst-mix>] -[B<-bf-inst-deps>] -[B<-bf-vectors>] -[B<-bf-unique-bytes>] -[B<-bf-mem-footprint>] -[B<-bf-strides>] -[B<-bf-every-bb>] -[B<-bf-merge-bb>=I] -[B<-bf-reuse-dist>[=loads|stores] -[B<-bf-include>=I[,I]...] -[B<-bf-exclude>=I[,I]...] -[B<-bf-thread-safe>] -[B<-bf-verbose>] -[B<-bf-static>] -[B<-bf-dragonegg>=I] -[B<-bf-libdir>=I] -[B<-bf-plugin>=I] -[B<-bf-disable>=I] -[I...] -[I...] - -=head1 DESCRIPTION - -B is the Byfl project's C compiler. It compiles C code, -instrumenting it to report various I performance counters at -execution time. Software performance counters are analogous to the -hardware performance counters provided by modern processors but -measure program execution in a hardware-independent fashion. That is, -users can expect to observe the same measurements across different -processor architectures. - -B works by using the GCC DragonEgg plugin to convert GCC's -internal representation to LLVM's, instrumenting that with Byfl, and -finally using Clang to generate a native executable. - -=head1 OPTIONS - -=over 4 - -=item B<-bf-by-func> - -Report performance counters for each function individually. - -=item B<-bf-call-stack> - -Report performance counters for each unique call stack. - -=item B<-bf-data-structs> - -Report loads and stores on a per-data-structure basis. - -=item B<-bf-types> - -Tally the number of times each data type is loaded or stored. - -=item B<-bf-inst-mix> - -Tally the number of times each instruction type was executed. - -=item B<-bf-inst-deps> - -Tally what instructions feed into what other instructions. - -=item B<-bf-vectors> - -Report information about the number and type of vector operations -performed. - -=item B<-bf-unique-bytes> - -Report the number of unique memory addresses referenced. - -=item B<-bf-mem-footprint> - -Report the memory capacity requires to hold various percentages of the -dynamic memory accesses. - -=item B<-bf-strides> - -Bin the stride sizes observes by each load and store. - -=item B<-bf-every-bb> - -Report performance counters at the basic-block level. - -=item B<-bf-merge-bb>=I - -Aggregate basic blocks into groups of I to reduce the output -volume. - -=item B<-bf-reuse-dist>[=loads|stores] - -Track data reuse distance. With an argument of C, only loads -are tracked. With an argument of C, only stores are tracked. -With no argument -- or with an argument of C) -- both -loads and stores are tracked. - -=item B<-bf-include>=I[,I]... - -Instrument only the specified functions. - -=item B<-bf-exclude>=I[,I]... - -Do not instrument the specified functions. - -=item B<-bf-thread-safe> - -Prevent corruption caused by simultaneous accesses to the same set of -performance counters. - -=item B<-bf-verbose> - -Make B output all of the helper programs it calls. - -=item B<-bf-static> - -Output static instruction counts at compile time. - -=item B<-bf-dragonegg>=I - -Point B to the DragonEgg plugin. - -=item B<-bf-libdir>=I - -Point B to the directory containing the Byfl library -(F or F). - -=item B<-bf-plugin>=I - -Point B to the Byfl plugin (C). - -=item B<-bf-disable>=I - -Disable certain aspects of B's operation. - -=back - -In addition, B accepts all of the common B options. - -=head1 EXAMPLES - -The simplest usage of B is to compile just like with B: - - bf-gcc -O2 -g -o myprog myprog.c - -The resulting F executable will output a basic set of -performance information at the end of the run. - -More performance information can be requested -- at the cost of slower -execution and a larger memory footprint: - - bf-gcc -bf-by-func -bf-types -bf-inst-mix -bf-vectors \ - -bf-mem-footprint -O2 -g -o myprog myprog.c - -=head1 ENVIRONMENT - -=over 4 - -=item C - -Provide a space-separated list of B command-line arguments. - -=item C - -Prefix each line of output with the contents of the C -environment variable. - -=item C - -Specify the name of a C<.byfl> file to which to write detailed Byfl -output in binary format. - -=item C - -Wrap the specified compiler instead of B. - -=back - -C is used at compile time. Command-line arguments take -precedence over those read from the C environment variable. -The advantage of using the environment variable, however, is that a -user can rebuild a project with different sets of performance counters -without having to modify the project's Fs (or analogue in -another build system) beyond an initial modification to use B -as the C compiler. - -C is used at run time. An important characteristic of the -C environment variable is that it honors POSIX shell-style -variable expansions. For example, if C is set to the -string C, then a line that would -otherwise begin with C will instead begin with C, assuming that the C environment -variable has the value C<3>. - -Although the characters C<|>, C<&>, C<;>, C>, C>, C<(>, -C<)>, C<{>, and C<}> are not normally allowed within C, -C does support backquoted-command evaluation, and the child -command can contain those characters, as in - - BF_PREFIX='`if true; then (echo YES; echo MAYBE); else echo NO; fi`' - -(which prefixes each line with C). - -As a special case, if C expands to a string that begins -with C or C<./>, it is treated not as a prefix but as a filename. -The Byfl-instrumented executable will redirect all of its Byfl output -to that file instead of to the standard output device. - -C is also used at run time. Like C, it honors -POSIX shell-style variable expansions. If C is set to the -empty string, no binary output file will be produced. - -=head1 NOTES - -=head2 Explanation of command-line options - -When B<-bf-call-stack> is specified, a function I is reported -separately when called from function I and when called from -function I). B<-bf-call-stack> overrides B<-bf-by-func>. - -For the purposes of B<-bf-data-structs>, Byfl defines a data structure -as either a statically allocated block of memory (which has a name in -the executable's symbol table) or a collection of data blocks -dynamically allocated from the same program call point (i.e., -instruction address). Byfl assigns the latter a name based on a -textual description of the call point. - -The B<-bf-types> option tallies, for example, the number of loads of -64-bit floating-point values as distinct from loads of 64-bit unsigned -integer values. - -See the L for descriptions of the -instructions that are tallied by B<-bf-inst-mix>. - -B<-bf-inst-deps> tallies each instruction with the instructions that -produced its first two operands. (Ellipses are used to indicate that -the instruction takes more than two operands.) For example, -C represents an exclusive OR with one operand being the -result of a previous integer addition and one being the result of a -previous integer multiplication (i.e., C). - -Use of B<-bf-unique-bytes> consumes one bit of memory per unique -address referenced by the program. - -Use of B<-bf-mem-footprint> consumes S<8 bytes> of memory per unique -address referenced by the program. - -A I is a unit of code that can be entered only at the -first instruction and that branches only at the last instruction. -Because basic blocks tend to be small, B<-bf-every-bb> produces a -substantial amount of output for typical programs. It is recommended -that B<-bf-every-bb> always be used in conjunction with -B<-bf-merge-bb> to reduce the amount of information output. - -The B<-bf-static> option currently lists the static number of loads, -stores, floating-point operations, conditional and indirect branches, -total operations, and basic blocks for each function and the number of -instructions in each inner loop detected. - -The B<-bf-disable> option is quite useful for troubleshooting. Its -option can be one of the following: - -=over 4 - -=item C - -Don't disable any features (the default). - -=item C - -Disable the Byfl plugin (i.e., inject no instrumentation into the code). - -=item C - -Use the DragonEgg plugin for code generation, but generate native -object files. - -=item C - -Disable DragonEgg entirely -- and hence all B functionality -- and -transfer control to the underlying B compiler. - -=back - -That is, if B fails to compile or link an application, try -disabling first C, then C, and finally C to -identify where the problem lies. - -The Byfl plugin proper (F) honors all of the -command-line options listed above except B<-bf-verbose>, -B<-bf-static>, and B<-bf-disable>. Those options are specific to the -B script. - -=head2 Selective instrumentation - -The simplest way to instrument only part of a program is at the module -level. That is, compile the "interesting" modules with B and -the rest with B (and link with B to pull in the Byfl -run-time library). However, B also supports inserting -programmer-defined "calipers" into the code. These can not only -selectively enable and disable performance counters but can also -distinguish blocks of code with a program-defined tag. To enable this -feature, an application must define a function with the following -C-language prototype: - - const char* bf_categorize_counters (void); - -That is, C takes no arguments and returns a -short tag describing the current phase of the application. A return -value of C disables logging of performance counters. - -Application developers should be aware of the following caveats -regarding C: - -=over 4 - -=item * - -C should be written to execute quickly -because it will be invoked extremely frequently (once per basic -block). Consequently, a typical definition is for -C simply to return a global variable and for -the application to assign to that global variable at various points in -the code. - -=item * - -C works only when B<-bf-every-bb> is -specified. (B issues a warning message if the function is -defined but the option is not specified.) If the user is not -interested in seeing per-basic-block counters, these can be -effectively disabled by specified a large argument to B<-bf-merge-bb> -(e.g., C<-bf-merge-bb=18446744073709551615>). - -=item * - -Because B instruments code at compile time while -C works at run time, the implication is that -returning C still pays a performance penalty relative to -uninstrumented code. - -=back - - -=head2 Compiler optimizations - -B first optimizes using the user-specified optimization level -(e.g., B<-O2>), then instruments the code with Byfl, and finally -optimizes again at B<-O3> to speed up execution. This final -optimization step does not affect the counter values that Byfl -reports. As a special case, however, compiling with C<-O0> disables -the final optimization step as well. This can be used to help debug -Byfl itself. - -=head1 FILES - -B is a script that invokes a number of other programs: B, -B, B, B (with the F plugin), B, -B, B, and B. - -=head1 BUGS - -Thread safety is still quite premature. Even with -B<-bf-thread-safe>, instrumented code is likely to crash. - -=head1 AUTHOR - -Scott Pakin, I - -=head1 SEE ALSO - -gcc(1), clang(1), -L