3

If I write

template<int sign>
inline int add_sign(int x) {
    return sign * x;
}

template int add_sign<-1>(int x);
template int add_sign<1>(int x);

Are most C++ compilers smart enough to optimize the multiplication by 1 or -1 into some faster operation (no-op or negation)?

dspyz
  • 5,280
  • 2
  • 25
  • 63
  • 6
    Why don't you just check your compiler's assembly output? Will most likely answer your question. – Mat Mar 09 '14 at 07:43
  • I don't know how. How do I do that? – dspyz Mar 09 '14 at 07:44
  • @Mat The question is whether most compilers are smart, so checking on one compiler isn't so efficient. – elyashiv Mar 09 '14 at 07:45
  • 1
    First step would be to search for "[your compiler] generate assembly" – Mat Mar 09 '14 at 07:45
  • use dissasembler to get machine instructions from object file. – Dejan Mar 09 '14 at 07:45
  • 1
    [Yes.](http://gcc.godbolt.org/) – jrok Mar 09 '14 at 07:46
  • @dspyz if you are using linux, run `objdum -d -Mintel a.out > somefile` some file will have the asm output. – elyashiv Mar 09 '14 at 07:46
  • @elyashiv: then check two. or three. of fifty if your code's going to be compiled by fifty compilers. And make sure to check all versions of those, since optimizers change. And make sure to check all possible contexts where this could be used. The better option would be not to worry about it, unless you have a concrete performance problem coming from an unoptimized int mult... – Mat Mar 09 '14 at 07:46
  • If you have a source file called `Foo.cc`, use `g++ -S Foo.cc` to get the asm from `g++`. – merlin2011 Mar 09 '14 at 07:46
  • @merlin2011 You don't need `-c` unless you want to generate the object file as well. – Jason Mar 09 '14 at 07:48
  • Ok, I tried -S (with gcc). It looks like it is optimized. I don't see any multiplication operation anywhere. And when I change it to -1, I see the negation operation. – dspyz Mar 09 '14 at 07:51
  • 3
    Define 'modern'. The first Fortran compiler was doing this in 1957. – user207421 Mar 09 '14 at 08:30

3 Answers3

7

Yes. This is part of a class of simple optimizations known as arithmetic local optimizations. For example 1 * x can be simplified statically to x, likewise -1 * x can be simplified to -x. Production compilers all do this and far more complex optimizations as well.

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
3

For g++, use g++ -S Foo.cc to view the assembler and determine whether the template has been optimized or not. For clang, take a look at this question. For Visual Studio, take a look at this question.

Community
  • 1
  • 1
merlin2011
  • 71,677
  • 44
  • 195
  • 329
1

Although in this case compiler do optimization for you, in more complex cases it may be necessary to write different variants of optimal code for different template arguments. Hence you may use template specialization to do it:

template<int sign>
inline int add_sign(int x);

template<>
inline int add_sign<-1>(int x) {
    return -x;
}

template<>
inline int add_sign<1>(int x) {
    return x;
}

With such fully specialized function you are not required to write explicit instantiations for it.

Constructor
  • 7,273
  • 2
  • 24
  • 66