On Thu, Aug 20, 2020 at 04:56:02PM +0200, Rasmus Villemoes wrote: > On 18/08/2020 23.41, Arvind Sankar wrote: > > > > Note that -fno-builtin-foo seems to mean slightly different things in > > clang and gcc. From experimentation, clang will neither optimize a call > > to foo, nor perform an optimization that introduces a call to foo. gcc > > will avoid optimizing calls to foo, but it can still generate new calls > > to foo while optimizing something else. Which means that > > -fno-builtin-{bcmp,stpcpy} only solves things for clang, not gcc. It's > > just that gcc doesn't seem to have implemented those optimizations. > > > > I think it's more than that. I've always read gcc's documentation > > '-fno-builtin' > '-fno-builtin-FUNCTION' > Don't recognize built-in functions that do not begin with > '__builtin_' as prefix. ... > > GCC normally generates special code to handle certain built-in > functions more efficiently; for instance, calls to 'alloca' may > become single instructions which adjust the stack directly, and > calls to 'memcpy' may become inline copy loops. > ... > > to mean exactly that observed above and nothing more, i.e. that > -fno-builtin-foo merely means that gcc stops treating a call of a > function named foo to mean a call to a function implementing the > standard function by that name (and hence allows it to e.g. replace a > memcpy(d, s, 1) by byte load+store). It does not mean to prevent > emitting calls to foo, and I don't think it ever will - it's a bit sad > that clang has chosen to interpret these options differently. That documentation is misleading, as it also goes on to say: "...nor can you change the behavior of the functions by linking with a different library" which implies that you _can_ change the behavior if you use the option, and which is what your "i.e." is saying as well. My point is that this is not completely true: in gcc, foo by default is defined to be __builtin_foo, and -fno-builtin-foo simply removes this definition. So the effect is just that calls to foo in the original source will be left alone. But in order for an optimization that introduces a new call to foo to be valid, foo _must_ have standard semantics: strchr(s,'\0') is not s + strlen(s) unless strlen has standard semantics. This is an oversight in gcc's optimizations: it converts to s + __builtin_strlen(s), which then (normally) becomes s + strlen(s). Check out this horror: https://godbolt.org/z/a1r9fK Clang will disable this optimization if -fno-builtin-strlen is specified. Clang's interpretation is more useful for embedded, since you can use -fno-builtin-foo and avoid calling __builtin_foo directly, and be guaranteed that there will be no calls to foo that you didn't write explicitly (outside of memcpy/memset/memcmp). In this case you are free to implement foo with non-standard semantics, or avoid implementing it altogether, and be reasonably confident that it will all work. > > Thinking out load, it would be useful if both compilers grew > > -fassume-provided-std-foo > > and > > -fno-assume-provided-std-foo > > options to tell the compiler that a function named foo with standard > semantics can be assumed (or not) to be provided by the execution > environment; i.e. one half of what -f(no-)builtin-foo apparently does > for clang currently. Not following: -fno-assume-provided-std-foo sounds like it would have exactly the same semantics as Clang's -fno-builtin-foo, except maybe in addition it should cause the compiler to error on seeing __builtin_foo if it can't implement that without calling foo. > > And yes, the positive -fbuiltin-foo would also be quite useful in order > to get the compiler to recognize a few important functions (memcpy, > memcmp) while using -ffreestanding (or just plain -fno-builtin) to tell > it to avoid assuming anything about most std functions - I've worked on > a VxWorks target where snprintf() didn't have the correct "return what > would be written" semantics but rather behaved like the kernel's > non-standard scnprintf(), and who knows what other odd quirks that libc had. > > Rasmus