In a limited range, you can use a lookup table:
static unsigned int mult7[] = {0, 7, 14, 21, ...}; unsigned int three = 3; unsigned int twenty_one = mult7[three];
This may seem silly (and probably this applies to this particular case), but it often helps for things where there is real value to calculate. I'm just not sure what multiplication by seven considers one of these cases.
To start, multiplying x by 7 (or shifting x three bits left after subtracting x ) is an operation that can be performed entirely inside the CPU. When viewing a table, you can see multiply by four (shift two bits to the left) and then add to get the correct address, but then you need to access the memory to perform the actual search - even with caching and other wonderful tricks that the current ones may have processors are likely to slow down.
There is also a good chance that your compiler will already know all the tricks on how to multiply quickly. If your sevens are constant (either const int or equivalent), the compiler probably already chose the fastest way, and there are good chances that compiler writers know a lot more about this than mere mortals :-) (a)
But for cases when the cost of calculations is relatively high, calculate the values once and implement them in your code, since the search table is one of the standard optimization strategies (response time for space).
(a) Examine the following code:
#include <stdio.h> static int mult7 (int num) { return num * 7; } int main (int argc, char *argv[]) { printf ("%d\n", mult7 (atoi (argv[1]))); return 0; }
During normal compilation on gcc , mult7 appears as a left shift and subtraction of the trick:
_mult7: pushl %ebp ; stack frame setup. movl %esp, %ebp movl 8(%ebp), %edx ; get value to edx movl %edx, %eax ; and eax. sall $3, %eax ; eax <- eax * 8. subl %edx, %eax ; eax <- eax - edx. popl %ebp ; stack frame teardown and return. ret
In -O3 (what I like to call a crazy optimization level), all of this is built into main with:
call _atoi movl $LC0, (%esp) leal 0(,%eax,8), %edx ; these two are the relevant instructions. subl %eax, %edx movl %edx, 4(%esp) call _printf
Please note that this nesting action is possible only because of the static nature of the function - if it were visible to the linker, it would have to be saved as a separate function if another object file was needed to call it.
If you uncheck static , it really saves it without binding with all the settings and deleting the stack frame, but at least it still uses the (supposedly) more efficient trick mentioned below. You can get rid of the stack frame code in gcc if you use -fomit-frame-pointer , if this does not adversely affect the code, but it starts to dig into the dark side a bit :-)
This trick is to use the LEA command to set edx to eax * 8 , and then subtract eax from it. The same theory as sall/subl under normal optimization is slightly different from mechanics.
Down below, trust your compiler. If you want to multiply num by 7, use the following:
num *= 7;
Most likely, no matter what improvement you choose from such an attempt at micro-optimization, you could get a much better improvement by looking at the macro level (choice of algorithm and data structure, etc.).