I am using BOOST_PP for to do precompile computations in the preprocessor. I am focusing on an application where code size is extremely important to me. (So please don't say the compiler should or usually does that, I need to control what is performed at compile time and what code is generated). However, I want to be able to use the same name of the macro/function for both integer constants and variables. As trivial example, I can have
#define TWICE(n) BOOST_PP_MUL(n,2)
//.....
// somewhere else in code
int a = TWICE(5);
This does what I want it to, evaluating to
int a = 10;
during compile time.
However, I also want it to be used at
int b = 5;
int a = TWICE(b);
This should be preprocessed to
int b = 5;
int a = 5 * 2;
Of course, I can do so by using the traditional macros like
#define TWICE(n) n * 2
But then it doesnt do what I want it to do for integer constants (evaluating them during compile time).
So, my question is, is there a trick to check whether the argument is a literal or a variable, and then use different definitions. i.e., something like this:
#define TWICE(n) BOOST_PP_IF( _IS_CONSTANT(n), \
BOOST_PP_MUL(n,2), \
n * 2 )
edit:
So what I am really after is some way to check if something is a constant available at compile time, and hence a good argument for the BOOST_PP_ functions. I realize that this is different from what most people expect from a preprocessor and general programming recommendations. But there is no wrong way of programming, so please don't hate on the question if you disagree with its philosophy. There is a reason the BOOST_PP library exists, and this question is in the same spirit. It might just not be possible though.
You're trying to do something that is better left to the optimizations of the compiler.
int main (void) {
int b = 5;
int a = b * 2;
return a; // return it so we use a and it's not optimized away
}
gcc -O3 -s t.c
.file "t.c"
.text
.p2align 4,,15
.globl main
.type main, #function
main:
.LFB0:
.cfi_startproc
movl $10, %eax
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Debian 4.5.0-6) 4.5.1 20100617 (prerelease)"
.section .note.GNU-stack,"",#progbits
Optimizing compiler will optimize.
EDIT: I'm aware that you don't want to hear that the compiler "should" or "usually" does that. However, what you are trying to do is not something that is meant to be done in the C preprocessor; the people who designed the C language and the C preprocessor designed it to work with the preprocessing token as it's basic atom. The CPP is, in many ways, "dumb". This is not a bad thing (in fact, this is in many cases what makes it so useful), but at the end of the day, it is a preprocessor. It preprocesses source files before they are parsed. It preprocesses source files before semantic analysis occurs. It preprocesses source files before the validity of a given source file is checked. I understand that you do not want to hear that this is something that the parser and semantic analyzer should handle or usually does. However, this is the reality of the situation. If you want to design code that is incredibly small, then you should rely on your compiler to do it's job instead of trying to create preprocessor constructs to do the work. Think of it this way: thousands of hours of work went into your compiler, so try to reuse as much of that work as possible!
not quite direct approach, however:
struct operation {
template<int N>
struct compile {
static const int value = N;
};
static int runtime(int N) { return N; }
};
operation::compile<5>::value;
operation::runtime(5);
alternatively
operation<5>();
operation(5);
There is no real chance of mixing the two levels (preprocessor and evaluation of variables). From what I understand from you question, b should be a symbolic constant?
I think you should use the traditional one
#define TWICE(n) ((n) * 2)
but then instead of initializing variables with expressions, you should initialize them with compile time constants. The only thing that I see to force evaluation at compile time and to have symbolic constants in C are integral enumeration constants. These are defined to have type int and are evaluated at compile time.
enum { bInit = 5 };
int b = bInit;
enum { aInit = TWICE(bInit) };
int a = aInit;
And generally you should not be too thrifty with const (as for your b) and check the produced assembler with -S.
Related
I'm having this code:
uint16_t swap_bytes(uint16_t x)
{
asm volatile(
"eor, %A0, %B0" "\n\t"
"eor, %B0, %A0" "\n\t"
"eor, %A0, %B0" "\n\t"
: "=r" (x)
: "0" (x)
);
return x;
}
Which translates (by avr-gcc version 4.8.1 with -std=gnu99 -save-temps) to:
.global swap_bytes
.type swap_bytes, #function
swap_bytes:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
/* #APP */
; 43 "..\lib\own\ownlib.c" 1
eor, r24, r25
eor, r25, r24
eor, r24, r25
; 0 "" 2
/* #NOAPP */
ret
.size swap_bytes, .-swap_bytes
But then the compiler is complaining like that:
|65|Error: constant value required|
|65|Error: garbage at end of line|
|66|Error: constant value required|
|66|Error: garbage at end of line|
|67|Error: constant value required|
|67|Error: garbage at end of line|
||=== Build failed: 6 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
The mentioned lines are the ones with the eor commands. Why does the compiler having problems with that? The registers are even upper (>= r16) ones where nearly all operations are possible. constant value required sounds to me like it expects a literal... I dont get it.
Just to clarify for future googlers:
eor, r24, r25
has an extra comma after the eor. This should be written as:
eor r24, r25
I would also encourage you (again) to consider using gcc's __builtin_bswap16. In case you are not familiar with the gcc 'builtin' functions, they are functions that are built into the compiler, and (despite looking like functions) are typically inlined. They have been written and optimized by people who understand all the ins and outs of the various processors and can take into account things you may not have considered.
I understand the desire to keep code as small as possible. And I accept that it is possible that (somehow) this builtin on your specific processor is producing sub-optimal code (I assume you have checked?). On the other hand, it may produce exactly the same code. Or it may use some even more clever trick to do this. Or it might interleave instructions from the surrounding code to take advantage of pipelining (or some other avr-specific thing that I have never heard of because I don't speak 'avr').
What's more, consider this code:
int main()
{
return __builtin_bswap16(12345);
}
Your code always takes 3 instructions to process a swap. However with builtins, the compiler can recognize that the arg is constant and compute the value at compile time instead of at run time. Hard to be more efficient than that.
I could also point out the benefits of "easier to support." Writing inline asm is HARD to do correctly. And future maintainers hate to touch it cuz they're never quite sure how it works. And of course, the builtin is going to be more cross-platform portable.
Still not convinced? My last pitch: Even after you fix the commas, your inline asm code still isn't quite right. Consider this code:
int main(int argc, char *argv[])
{
return swap_bytes(argc) + swap_bytes(argc);
}
Because of the way you have written written swap_bytes (ie using volatile), gcc must compute the value twice (see the definition of volatile). Had you omitted volatile (or if you had used the builtin which does this correctly), it would have realized that argc doesn't change and re-used the output from the first call. Did I mention that correctly writing inline asm is HARD?
I don't know your code, constraints, level of expertise or requirements. Maybe your solution really is the best. The most I can do is to encourage you to think long and hard before using inline asm in production code.
I am using C99 under GCC.
I have a function declared static inline in a header that I cannot modify.
The function never returns but is not marked __attribute__((noreturn)).
How can I call the function in a way that tells the compiler it will not return?
I am calling it from my own noreturn function, and partly want to suppress the "noreturn function returns" warning but also want to help the optimizer etc.
I have tried including a declaration with the attribute but get a warning about the repeated declaration.
I have tried creating a function pointer and applying the attribute to that, but it says the function attribute cannot apply to a pointed function.
From the function you defined, and which calls the external function, add a call to __builtin_unreachable which is built into at least GCC and Clang compilers and is marked noreturn. In fact, this function does nothing else and should not be called. It's only here so that the compiler can infer that program execution will stop at this point.
static inline external_function() // lacks the noreturn attribute
{ /* does not return */ }
__attribute__((noreturn)) void your_function() {
external_function(); // the compiler thinks execution may continue ...
__builtin_unreachable(); // ... and now it knows it won't go beyond here
}
Edit: Just to clarify a few points raised in the comments, and generally give a bit of context:
A function has has only two ways of not returning: loop forever, or short-circuit the usual control-flow (e.g. throw an exception, jump out of the function, terminate the process, etc.)
In some cases, the compiler may be able to infer and prove through static analysis that a function will not return. Even theoretically, this is not always possible, and since we want compilers to be fast only obvious/easy cases are detected.
__attribute__((noreturn)) is an annotation (like const) which is a way for the programmer to inform the compiler that he's absolutely sure a function will not return. Following the trust but verify principle, the compiler tries to prove that the function does indeed not return. If may then issue an error if it proves the function may return, or a warning if it was not able to prove whether the function returns or not.
__builtin_unreachable has undefined behaviour because it is not meant to be called. It's only meant to help the compiler's static analysis. Indeed the compiler knows that this function does not return, so any following code is provably unreachable (except through a jump).
Once the compiler has established (either by itself, or with the programmer's help) that some code is unreachable, it may use this information to do optimizations like these:
Remove the boilerplate code used to return from a function to its caller, if the function never returns
Propagate the unreachability information, i.e. if the only execution path to a code points is through unreachable code, then this point is also unreachable. Examples:
if a function does not return, any code following its call and not reachable through jumps is also unreachable. Example: code following __builtin_unreachable() is unreachable.
in particular, it the only path to a function's return is through unreachable code, the function can be marked noreturn. That's what happens for your_function.
any memory location / variable only used in unreachable code is not needed, therefore settings/computing the content of such data is not needed.
any computations which is probably (1) unnecessary (previous bullet) and (2) has no side effects (such as pure functions) may be removed.
Illustration:
The call to external_function cannot be removed because it might have side-effects. In fact, it probably has at least the side effect of terminating the process!
The return boiler plate of your_function may be removed
Here's another example showing how code before the unreachable point may be removed
int compute(int) __attribute((pure)) { return /* expensive compute */ }
if(condition) {
int x = compute(input); // (1) no side effect => keep if x is used
// (8) x is not used => remove
printf("hello "); // (2) reachable + side effect => keep
your_function(); // (3) reachable + side effect => keep
// (4) unreachable beyond this point
printf("word!\n"); // (5) unreachable => remove
printf("%d\n", x); // (6) unreachable => remove
// (7) mark 'x' as unused
} else {
// follows unreachable code, but can jump here
// from reachable code, so this is reachable
do_stuff(); // keep
}
Several solutions:
redeclaring your function with the __attribute__
You should try to modify that function in its header by adding __attribute__((noreturn)) to it.
You can redeclare some functions with new attribute, as this stupid test demonstrates (adding an attribute to fopen) :
#include <stdio.h>
extern FILE *fopen (const char *__restrict __filename,
const char *__restrict __modes)
__attribute__ ((warning ("fopen is used")));
void
show_map_without_care (void)
{
FILE *f = fopen ("/proc/self/maps", "r");
do
{
char lin[64];
fgets (lin, sizeof (lin), f);
fputs (lin, stdout);
}
while (!feof (f));
fclose (f);
}
overriding with a macro
At last, you could define a macro like
#define func(A) {func(A); __builtin_unreachable();}
(this uses the fact that inside a macro, the macro name is not macro-expanded).
If your never-returning func is declaring as returning e.g. int you'll use a statement expression like
#define func(A) ({func(A); __builtin_unreachable(); (int)0; })
Macro-based solutions like above won't always work, e.g. if func is passed as a function pointer, or simply if some guy codes (func)(1) which is legal but ugly.
redeclaring a static inline with the noreturn attribute
And the following example:
// file ex.c
// declare exit without any standard header
void exit (int);
// define myexit as a static inline
static inline void
myexit (int c)
{
exit (c);
}
// redeclare it as notreturn
static inline void myexit (int c) __attribute__ ((noreturn));
int
foo (int *p)
{
if (!p)
myexit (1);
if (p)
return *p + 2;
return 0;
}
when compiled with GCC 4.9 (from Debian/Sid/x86-64) as gcc -S -fverbose-asm -O2 ex.c) gives an assembly file containing the expected optimization:
.type foo, #function
foo:
.LFB1:
.cfi_startproc
testq %rdi, %rdi # p
je .L5 #,
movl (%rdi), %eax # *p_2(D), *p_2(D)
addl $2, %eax #, D.1768
ret
.L5:
pushq %rax #
.cfi_def_cfa_offset 16
movb $1, %dil #,
call exit #
.cfi_endproc
.LFE1:
.size foo, .-foo
You could play with #pragma GCC diagnostic to selectively disable a warning.
Customizing GCC with MELT
Finally, you could customize your recent gcc using the MELT plugin and coding your simple extension (in the MELT domain specific language) to add the attribute noreturn when encoutering the desired function. It is probably a dozen of MELT lines, using register_finish_decl_first and a match on the function name.
Since I am the main author of MELT (free software GPLv3+) I could perhaps even code that for you if you ask, e.g. here or preferably on gcc-melt#googlegroups.com; give the concrete name of your never-returning function.
Probably the MELT code is looking like:
;;file your_melt_mode.melt
(module_is_gpl_compatible "GPLv3+")
(defun my_finish_decl (decl)
(let ( (tdecl (unbox :tree decl))
)
(match tdecl
(?(tree_function_decl_named
?(tree_identifier ?(cstring_same "your_function_name")))
;;; code to add the noreturn attribute
;;; ....
))))
(register_finish_decl_first my_finish_decl)
The real MELT code is slightly more complex. You want to define your_adding_attr_mode there. Ask me for more.
Once you coded your MELT extension your_melt_mode.melt for your needs (and compiled that MELT extension into your_melt_mode.quicklybuilt.so as documented in the MELT tutorials) you'll compile your code with
gcc -fplugin=melt \
-fplugin-arg-melt-extra=your_melt_mode.quicklybuilt \
-fplugin-arg-melt-mode=your_adding_attr_mode \
-O2 -I/your/include -c yourfile.c
In other words, you just add a few -fplugin-* flags to your CFLAGS in your Makefile !
BTW, I'm just coding in the MELT monitor (on github: https://github.com/bstarynk/melt-monitor ..., file meltmom-process.melt something quite similar.
With a MELT extension, you won't get any additional warning, since the MELT extension would alter the internal GCC AST (a GCC Tree) of the declared function on the fly!
Customizing GCC with MELT is probably the most bullet-proof solution, since it is modifying the GCC internal AST. Of course, it is probably the most costly solution (and it is GCC specific and might need -small- changes when GCC is evolving, e.g. when using the next version of GCC), but as I am trying to show it is quite easy in your case.
PS. In 2019, GCC MELT is an abandoned project. If you want to customize GCC (for any recent version of GCC, e.g. GCC 7, 8, or 9), you need to write your own GCC plugin in C++.
Given this code:
#include <stdio.h>
int main(int argc, char **argv)
{
int x = 1;
printf("Hello x = %d\n", x);
}
I'd like to access and manipulate the variable x in inline assembly. Ideally, I want to change its value using inline assembly. GNU assembler, and using the AT&T syntax.
In GNU C inline asm, with x86 AT&T syntax:
(But https://gcc.gnu.org/wiki/DontUseInlineAsm if you can avoid it).
// this example doesn't really need volatile: the result is the same every time
asm volatile("movl $0, %[some]"
: [some] "=r" (x)
);
after this, x contains 0.
Note that you should generally avoid mov as the first or last instruction of an asm statement. Don't copy from %[some] to a hard-coded register like %%eax, just use %[some] as a register, letting the compiler do register allocation.
See https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html and https://stackoverflow.com/tags/inline-assembly/info for more docs and guides.
Not all compilers support GNU syntax.
For example, for MSVC you do this:
__asm mov x, 0 and x will have the value of 0 after this statement.
Please specify the compiler you would want to use.
Also note, doing this will restrict your program to compile with only a specific compiler-assembler combination, and will be targeted only towards a particular architecture.
In most cases, you'll get as good or better results from using pure C and intrinsics, not inline asm.
asm("mov $0, %1":"=r" (x):"r" (x):"cc"); -- this may get you on the right track. Specify register use as much as possible for performance and efficiency. However, as Aniket points out, highly architecture dependent and requires gcc.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
In gcc-strict-aliasing-and-casting-through-a-union I asked whether anyone had encountered problems with union punning through pointers. So far, the answer seems to be No.
This question is broader: Do you have any horror stories about gcc and strict-aliasing?
Background: Quoting from AndreyT's answer in c99-strict-aliasing-rules-in-c-gcc:
"Strict aliasing rules are rooted in parts of the standard that were present in C and C++ since the beginning of [standardized] times. The clause that prohibits accessing object of one type through a lvalue of another type is present in C89/90 (6.3) as well as in C++98 (3.10/15). ... It is just that not all compilers wanted (or dared) to enforce it or rely on it."
Well, gcc is now daring to do so, with its -fstrict-aliasing switch. And this has caused some problems. See, for example, the excellent article http://davmac.wordpress.com/2009/10/ about a Mysql bug, and the equally excellent discussion in http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html.
Some other less-relevant links:
performance-impact-of-fno-strict-aliasing
strict-aliasing
when-is-char-safe-for-strict-pointer-aliasing
how-to-detect-strict-aliasing-at-compile-time
So to repeat, do you have a horror story of your own? Problems not indicated by -Wstrict-aliasing would, of course, be preferred. And other C compilers are also welcome.
Added June 2nd: The first link in Michael Burr's answer, which does indeed qualify as a horror story, is perhaps a bit dated (from 2003). I did a quick test, but the problem has apparently gone away.
Source:
#include <string.h>
struct iw_event { /* dummy! */
int len;
};
char *iwe_stream_add_event(
char *stream, /* Stream of events */
char *ends, /* End of stream */
struct iw_event *iwe, /* Payload */
int event_len) /* Real size of payload */
{
/* Check if it's possible */
if ((stream + event_len) < ends) {
iwe->len = event_len;
memcpy(stream, (char *) iwe, event_len);
stream += event_len;
}
return stream;
}
The specific complaint is:
Some users have complained that when the [above] code is compiled without the -fno-strict-aliasing, the order of the write and memcpy is inverted (which means a bogus len is mem-copied into the stream).
Compiled code, using gcc 4.3.4 on CYGWIN wih -O3 (please correct me if I am wrong--my assembler is a bit rusty!):
_iwe_stream_add_event:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $20, %esp
movl 8(%ebp), %eax # stream --> %eax
movl 20(%ebp), %edx # event_len --> %edx
leal (%eax,%edx), %ebx # sum --> %ebx
cmpl 12(%ebp), %ebx # compare sum with ends
jae L2
movl 16(%ebp), %ecx # iwe --> %ecx
movl %edx, (%ecx) # event_len --> iwe->len (!!)
movl %edx, 8(%esp) # event_len --> stack
movl %ecx, 4(%esp) # iwe --> stack
movl %eax, (%esp) # stream --> stack
call _memcpy
movl %ebx, %eax # sum --> retval
L2:
addl $20, %esp
popl %ebx
leave
ret
And for the second link in Michael's answer,
*(unsigned short *)&a = 4;
gcc will usually (always?) give a warning. But I believe a valid solution to this (for gcc) is to use:
#define CAST(type, x) (((union {typeof(x) src; type dst;}*)&(x))->dst)
// ...
CAST(unsigned short, a) = 4;
I've asked SO whether this is OK in gcc-strict-aliasing-and-casting-through-a-union, but so far nobody disagrees.
No horror story of my own, but here are some quotes from Linus Torvalds (sorry if these are already in one of the linked references in the question):
http://lkml.org/lkml/2003/2/26/158:
Date Wed, 26 Feb 2003 09:22:15 -0800
Subject Re: Invalid compilation without -fno-strict-aliasing
From Jean Tourrilhes <>
On Wed, Feb 26, 2003 at 04:38:10PM +0100, Horst von Brand wrote:
Jean Tourrilhes <> said:
It looks like a compiler bug to me...
Some users have complained that when the following code is
compiled without the -fno-strict-aliasing, the order of the write and
memcpy is inverted (which mean a bogus len is mem-copied into the
stream).
Code (from linux/include/net/iw_handler.h) :
static inline char *
iwe_stream_add_event(char * stream, /* Stream of events */
char * ends, /* End of stream */
struct iw_event *iwe, /* Payload */
int event_len) /* Real size of payload */
{
/* Check if it's possible */
if((stream + event_len) < ends) {
iwe->len = event_len;
memcpy(stream, (char *) iwe, event_len);
stream += event_len;
}
return stream;
}
IMHO, the compiler should have enough context to know that the
reordering is dangerous. Any suggestion to make this simple code more
bullet proof is welcomed.
The compiler is free to assume char *stream and struct iw_event *iwe point
to separate areas of memory, due to strict aliasing.
Which is true and which is not the problem I'm complaining about.
(Note with hindsight: this code is fine, but Linux's implementation of memcpy was a macro that cast to long * to copy in larger chunks. With a correctly-defined memcpy, gcc -fstrict-aliasing isn't allowed to break this code. But it means you need inline asm to define a kernel memcpy if your compiler doesn't know how turn a byte-copy loop into efficient asm, which was the case for gcc before gcc7)
And Linus Torvald's comment on the above:
Jean Tourrilhes wrote:
>
It looks like a compiler bug to me...
Why do you think the kernel uses "-fno-strict-aliasing"?
The gcc people are more interested in trying to find out what can be
allowed by the c99 specs than about making things actually work. The
aliasing code in particular is not even worth enabling, it's just not
possible to sanely tell gcc when some things can alias.
Some users have complained that when the following code is
compiled without the -fno-strict-aliasing, the order of the write and
memcpy is inverted (which mean a bogus len is mem-copied into the
stream).
The "problem" is that we inline the memcpy(), at which point gcc won't
care about the fact that it can alias, so they'll just re-order
everything and claim it's out own fault. Even though there is no sane
way for us to even tell gcc about it.
I tried to get a sane way a few years ago, and the gcc developers really
didn't care about the real world in this area. I'd be surprised if that
had changed, judging by the replies I have already seen.
I'm not going to bother to fight it.
Linus
http://www.mail-archive.com/linux-btrfs#vger.kernel.org/msg01647.html:
Type-based aliasing is stupid. It's so incredibly stupid that it's not even funny. It's broken. And gcc took the broken notion, and made it more so by making it a "by-the-letter-of-the-law" thing that makes no sense.
...
I know for a fact that gcc would re-order write accesses that were clearly to (statically) the same address. Gcc would suddenly think that
unsigned long a;
a = 5;
*(unsigned short *)&a = 4;
could be re-ordered to set it to 4 first (because clearly they don't alias - by reading the standard), and then because now the assignment of 'a=5' was later, the assignment of 4 could be elided entirely! And if somebody complains that the compiler is insane, the compiler people would say "nyaah, nyaah, the standards people said we can do this", with absolutely no introspection to ask whether it made any SENSE.
SWIG generates code that depends on strict aliasing being off, which can cause all sorts of problems.
SWIGEXPORT jlong JNICALL Java_com_mylibJNI_make_1mystruct_1_1SWIG_12(
JNIEnv *jenv, jclass jcls, jint jarg1, jint jarg2) {
jlong jresult = 0 ;
int arg1 ;
int arg2 ;
my_struct_t *result = 0 ;
(void)jenv;
(void)jcls;
arg1 = (int)jarg1;
arg2 = (int)jarg2;
result = (my_struct_t *)make_my_struct(arg1,arg2);
*(my_struct_t **)&jresult = result; /* <<<< horror*/
return jresult;
}
gcc, aliasing, and 2-D variable-length arrays: The following sample code copies a 2x2 matrix:
#include <stdio.h>
static void copy(int n, int a[][n], int b[][n]) {
int i, j;
for (i = 0; i < 2; i++) // 'n' not used in this example
for (j = 0; j < 2; j++) // 'n' hard-coded to 2 for simplicity
b[i][j] = a[i][j];
}
int main(int argc, char *argv[]) {
int a[2][2] = {{1, 2},{3, 4}};
int b[2][2];
copy(2, a, b);
printf("%d %d %d %d\n", b[0][0], b[0][1], b[1][0], b[1][1]);
return 0;
}
With gcc 4.1.2 on CentOS, I get:
$ gcc -O1 test.c && a.out
1 2 3 4
$ gcc -O2 test.c && a.out
10235717 -1075970308 -1075970456 11452404 (random)
I don't know whether this is generally known, and I don't know whether this a bug or a feature. I can't duplicate the problem with gcc 4.3.4 on Cygwin, so it may have been fixed. Some work-arounds:
Use __attribute__((noinline)) for copy().
Use the gcc switch -fno-strict-aliasing.
Change the third parameter of copy() from b[][n] to b[][2].
Don't use -O2 or -O3.
Further notes:
This is an answer, after a year and a day, to my own question (and I'm a bit surprised there are only two other answers).
I lost several hours with this on my actual code, a Kalman filter. Seemingly small changes would have drastic effects, perhaps because of changing gcc's automatic inlining (this is a guess; I'm still uncertain). But it probably doesn't qualify as a horror story.
Yes, I know you wouldn't write copy() like this. (And, as an aside, I was slightly surprised to see gcc did not unroll the double-loop.)
No gcc warning switches, include -Wstrict-aliasing=, did anything here.
1-D variable-length arrays seem to be OK.
Update: The above does not really answer the OP's question, since he (i.e. I) was asking about cases where strict aliasing 'legitimately' broke your code, whereas the above just seems to be a garden-variety compiler bug.
I reported it to GCC Bugzilla, but they weren't interested in the old 4.1.2, even though (I believe) it is the key to the $1-billion RHEL5. It doesn't occur in 4.2.4 up.
And I have a slightly simpler example of a similar bug, with only one matrix. The code:
static void zero(int n, int a[][n]) {
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
a[i][j] = 0;
}
int main(void) {
int a[2][2] = {{1, 2},{3, 4}};
zero(2, a);
printf("%d\n", a[1][1]);
return 0;
}
produces the results:
gcc -O1 test.c && a.out
0
gcc -O1 -fstrict-aliasing test.c && a.out
4
It seems it is the combination -fstrict-aliasing with -finline which causes the bug.
here is mine:
http://forum.openscad.org/CGAL-3-6-1-causing-errors-but-CGAL-3-6-0-OK-tt2050.html
it caused certain shapes in a CAD program to be drawn incorrectly. thank goodness for the project's leaders work on creating a regression test suite.
the bug only manifested itself on certain platforms, with older versions of GCC and older versions of certain libraries. and then only with -O2 turned on. -fno-strict-aliasing solved it.
The Common Initial Sequence rule of C used to be interpreted as making it
possible to write a function which could work on the leading portion of a
wide variety of structure types, provided they start with elements of matching
types. Under C99, the rule was changed so that it only applied if the structure
types involved were members of the same union whose complete declaration was visible at the point of use.
The authors of gcc insist that the language in question is only applicable if
the accesses are performed through the union type, notwithstanding the facts
that:
There would be no reason to specify that the complete declaration must be visible if accesses had to be performed through the union type.
Although the CIS rule was described in terms of unions, its primary
usefulness lay in what it implied about the way in which structs were
laid out and accessed. If S1 and S2 were structures that shared a CIS,
there would be no way that a function that accepted a pointer to an S1
and an S2 from an outside source could comply with C89's CIS rules
without allowing the same behavior to be useful with pointers to
structures that weren't actually inside a union object; specifying CIS
support for structures would thus have been redundant given that it was
already specified for unions.
The following code returns 10, under gcc 4.4.4. Is anything wrong with the union method or gcc 4.4.4?
int main()
{
int v = 10;
union vv {
int v;
short q;
} *s = (union vv *)&v;
s->v = 1;
return v;
}
Is it possible to compute pow(10,x) at compile time?
I've got a processor without floating point support and slow integer division. I'm trying to perform as many calculations as possible at compile time. I can dramatically speed up one particular function if I pass both x and C/pow(10,x) as arguments (x and C are always constant integers, but they are different constants for each call). I'm wondering if I can make these function calls less error prone by introducing a macro which does the 1/pow(10,x) automatically, instead of forcing the programmer to calculate it?
Is there a pre-processor trick? Can I force the compiler optimize out the library call?
There are very few values possible before you overflow int (or even long). For clarities sake, make it a table!
edit: If you are using floats (looks like you are), then no it's not going to be possible to call the pow() function at compile time without actually writing code that runs in the make process and outputs the values to a file (such as a header file) which is then compiled.
GCC will do this at a sufficiently high optimization level (-O1 does it for me). For example:
#include <math.h>
int test() {
double x = pow(10, 4);
return (int)x;
}
Compiles at -O1 -m32 to:
.file "test.c"
.text
.globl test
.type test, #function
test:
pushl %ebp
movl %esp, %ebp
movl $10000, %eax
popl %ebp
ret
.size test, .-test
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",#progbits
This works without the cast as well - of course, you do get a floating-point load instruction in there, as the Linux ABI passes floating point return values in FPU registers.
You can do it with Boost.Preprocessor:
http://www.boost.org/doc/libs/1_39_0/libs/preprocessor/doc/index.html
Code:
#include <boost/preprocessor/repeat.hpp>
#define _TIMES_10(z, n, data) * 10
#define POW_10(n) (1 BOOST_PP_REPEAT(n, _TIMES_10, _))
int test[4] = {POW_10(0), POW_10(1), POW_10(2), POW_10(3)};
Actually, by exploiting the C preprocessor, you can get it to compute C pow(10, x) for any real C and integral x. Observe that, as #quinmars noted, C allows you to use scientific syntax to express numerical constants:
#define myexp 1.602E-19 // == 1.602 * pow(10, -19)
to be used for constants. With this in mind, and a bit of cleverness, we can construct a preprocessor macro that takes C and x and combine them into an exponentiation token:
#define EXP2(a, b) a ## b
#define EXP(a, b) EXP2(a ## e,b)
#define CONSTPOW(C,x) EXP(C, x)
This can now be used as a constant numerical value:
const int myint = CONSTPOW(3, 4); // == 30000
const double myfloat = CONSTPOW(M_PI, -2); // == 0.03141592653
You can use the scientific notation for floating point values which is part of the C language. It looks like that:
e = 1.602E-19 // == 1.602 * pow(10, -19)
The number before the E ( the E maybe capital or small 1.602e-19) is the fraction part where as the (signed) digit sequence after the E is the exponent part. By default the number is of the type double, but you can attach a floating point suffix (f, F, l or L) if you need a float or a long double.
I would not recommend to pack this semantic into a macro:
It will not work for variables, floating point values, etc.
The scientific notation is more readable.
Actually, you have M4 which is a pre-processor way more powerful than the GCC’s. A main difference between those two is GCC’s is not recursive whereas M4 is. It makes possible things like doing arithmetic at compile-time (and much more!). The below code sample is what you would like to do, isn’t it? I made it bulky in a one-file source; but I usually put M4's macro definitions in separate files and tune my Makefile rules. This way, your code is kept from ugly intrusive M4 definitions into the C source code I've done here.
$ cat foo.c
define(M4_POW_AUX, `ifelse($2, 1, $1, `eval($1 * M4_POW_AUX($1, decr($2)))')')dnl
define(M4_POW, `ifelse($2, 0, 1, `M4_POW_AUX($1, $2)')')dnl
#include <stdio.h>
int main(void)
{
printf("2^0 = %d\n", M4_POW(2, 0));
printf("2^1 = %d\n", M4_POW(2, 1));
printf("2^4 = %d\n", M4_POW(2, 4));
return 0;
}
The command line to compile this code sample uses the ability of GCC and M4 to read from the standard input.
$ cat foo.c | m4 - | gcc -x c -o m4_pow -
$ ./m4_pow
2^0 = 1
2^1 = 2
2^4 = 16
Hope this help!
If you just need to use the value at compile time, use the scientific notation like 1e2 for pow(10, 2)
If you want to populate the values at compile time and then use them later at runtime then simply use a lookup table because there are only 23 different powers of 10 that are exactly representable in double precision
double POW10[] = {1., 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
You can get larger powers of 10 at runtime from the above lookup table to quickly get the result without needing to multiply by 10 again and again, but the result is just a value close to a power of 10 like when you use 10eX with X > 22
double pow10(int x)
{
if (x > 22)
return POW10[22] * pow10(x - 22);
else if (x >= 0)
return POW10[x];
else
return 1/pow10(-x);
}
If negative exponents is not needed then the final branch can be removed.
You can also reduce the lookup table size further if memory is a constraint. For example by storing only even powers of 10 and multiply by 10 when the exponent is odd, the table size is now only a half.
Recent versions of GCC ( around 4.3 ) added the ability to use GMP and MPFR to do some compile-time optimizations by evaluating more complex functions that are constant. That approach leaves your code simple and portable, and trust the compiler to do the heavy lifting.
Of course, there are limits to what it can do. Here's a link to the description in the changelog, which includes a list of functions that are supported by this. 'pow' is one them.
Unfortunately, you can't use the preprocessor to precalculate library calls. If x is integral you could write your own function, but if it's a floating-point type I don't see any good way to do this.
bdonlan's replay is spot on but keep in mind that you can perform nearly any optimization you chose on the compile box provided you are willing to parse and analyze the code in your own custom preprocessor. It is a trivial task in most version of unix to override the implicit rules that call the compiler to call a custom step of your own before it hits the compiler.