BOOST_FOREACH less efficient than handcoded loop for some testcases

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I made some tests of BOOST_FOREACH (from boost-1.34) to see if it
generates as good code as a handcoded loop. The answer is that it does
under certain circumstances. I tested g++-4.2.0 and g++-4.1.2 and the
optimizations levels O3, O2 and Os. Here is the first testcase (where a
reference to the vector is passed as a parameter):

//////////////////////////////////////////////////////////////////////////////

void f(float);
#include <boost/foreach.hpp>
#include <vector>

void g(const std::vector<float> & v) {

   BOOST_FOREACH(float i, v)
      f(i);
}

//////////////////////////////////////////////////////////////////////////////

This is as efficient as a handcoded loop if and only if the g++ version is 4.2.0 and the optimization level is O3. There will be 21 assembly instructions.

Here is the other testcase:
//////////////////////////////////////////////////////////////////////////////
void f(float);
#include <boost/foreach.hpp>
#include <vector>

struct A {
   void g() const;
   char name[52];
   std::vector<float> const v;
};

void A::g() const {

   BOOST_FOREACH(float i, v)
      f(i);
}
//////////////////////////////////////////////////////////////////////////////

Unfortunately this gives as much as 24 instructions, while then handcoded version still gives only 21 instructions.

I attach the script I used for testing. If you want to try it yourself, put the script in an empty directory and run from there; it will create some files. After running it, it may be interesting to compare the generated code, for example:
diff -dU2 iterate_vector-member-g++-4.2.0-O3.s BOOST_FOREACH-member-g++-4.2.0-O3.s|kompare -

Can gcc be fixed so that it optimizes BOOST_FOREACH to be as efficient as a handcoded loop? Should I report it to the bugtracker?

#! /bin/sh

ITERATIONS="0 1 2"
ITERATION_NAMES=(handcoded iterate_vector BOOST_FOREACH)
ITERATION_CODES=(\
"
   std::vector<float>::const_iterator const v_end = v.end();
   for (std::vector<float>::const_iterator it = v.begin(); it != v_end; ++it)
      f(*it);" \
"
#define iterate_vector_const(value_type, it, v)                              \\
   for                                                                       \\
      (struct {                                                              \\
          std::vector<value_type>::const_iterator       current;             \\
          std::vector<value_type>::const_iterator const end;                 \\
          value_type const & operator*() {return *current;}                  \\
       } it = {v.begin(), v.end()};                                          \\
       it.current != it.end;                                                 \\
       ++it.current)                                                         \\

   iterate_vector_const(float, it, v)
      f(*it);" \
"
   BOOST_FOREACH(float i, v)
      f(i);")

EXAMPLES="0 1 2"
EXAMPLE_NAMES=(parameter member member_with_local)
EXAMPLE_CODES=(\
"
void g(const std::vector<float> & v) {" \
"
struct A {
   void g() const;
   char name[52];
   std::vector<float> const v;
};

void A::g() const {" \
"
struct A {
   void g() const;
   char name[52];
   std::vector<float> const m_v;
};

void A::g() const {
   std::vector<float> const & v = m_v; 
")

COMPILER_VERSIONS="4.2.0 4.1.2"
OPTIMIZATOINS="3 2 s"

unset TABLE_HEADER
for optimization in $OPTIMIZATOINS; do
	TABLE_HEADER="$TABLE_HEADER O$optimization"
done
echo "Optimizations:  $TABLE_HEADER"
for iteration in $ITERATIONS; do
	echo ${ITERATION_NAMES[$iteration]}:
	for example in $EXAMPLES; do
		NAME=${ITERATION_NAMES[$iteration]}-${EXAMPLE_NAMES[$example]}
		IN=$NAME.cc
		rm -f $IN
		echo "void f(float);"                                              >> $IN
		echo "#include <boost/foreach.hpp>"                                >> $IN
		echo "#include <vector>"                                           >> $IN
		echo "${EXAMPLE_CODES[$example]}"                                  >> $IN
		echo "${ITERATION_CODES[$iteration]}"                              >> $IN
		echo "}"                                                           >> $IN
		echo "   ${EXAMPLE_NAMES[$example]}:"
		for compiler_version in $COMPILER_VERSIONS; do
			MESSAGE=g++-$compiler_version:
			for optimization in $OPTIMIZATOINS; do
				OUT=$NAME-g++-$compiler_version-O$optimization.s
				g++-$compiler_version -Wall -Wextra -O$optimization -S $IN -o $OUT
				MESSAGE="$MESSAGE $(egrep -v "^([	 ]*\\.|_)" $OUT|wc -l)"
			done
			echo "      $MESSAGE"
		done
	done
done

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux