Can GCC optimize methods of a class with compile-time constant variables? - c++

Preamble
I'm using avr-g++ for programming AVR microcontrollers and therefore I always need to get very efficient code.
GCC usually can optimize a function if its argument are compile-time constants, e.g. I have function pin_write(uint8_t pin, bool val) which determine AVR's registers for the pin (using my special map from integer pin to a pair port/pin) and write to these registers correspondent values. This function isn't too small, because of its generality. But if I call this function with compile-time constant pin and val, GCC can make all calculations at compile-time and eliminate this call to a couple of AVR instructions, e.g.
sbi PORTB,1
sbi DDRB,1
Amble
Let's write a code like this:
class A {
int x;
public:
A(int x_): x(x_) {}
void foo() { pin_write(x, 1); }
};
A a(8);
int main() {
a.foo();
}
We have only one object of class A and it's initialized with a constant (8). So, it's possible to make all calculations at compile-time:
foo() -> pin_write(x,1) -> pin_write(8,1) -> a couple of asm instructions
But GCC doesn't do so.
Surprisely, but if I remove global A a(8) and write just
A(8).foo()
I get exactly what I want:
00000022 <main>:
22: c0 9a sbi 0x18, 0 ; 24
24: b8 9a sbi 0x17, 0 ; 23
Question
So, is there a way to force GCC make all possible calculation at compile-time for single global objects with constant initializers?
Because of this trouble I have to manually expand such cases and replace my original code with this:
const int x = 8;
class A {
public:
A() {}
void foo() { pin_write(x, 1); }
}
UPD. It very wonderful: A(8).foo() inside main optimized to 2 asm instructions. A a(8); a.foo() too! But if I declare A a(8) as global -- compiler produce big general code. I tried to add static -- it didn't help. Why?

But if I declare A a(8) as global -- compiler produce big general code. I tried to add static -- it didn't help. Why?
In my experience, gcc is very reluctant if the object / function has external linkage. Since we don't have your code to compile, I made a slightly modified version of your code:
#include <cstdio>
class A {
int x;
public:
A(int x_): x(x_) {}
int f() { return x*x; }
};
A a(8);
int main() {
printf("%d", a.f());
}
I have found 2 ways to achive that the generated assembly corresponds to this:
int main() {
printf("%d", 64);
}
In words: to eliminate everything at compile time so that only the necessary minimum remains.
One way to achive this both with clang and gcc is:
#include <cstdio>
class A {
int x;
public:
constexpr A(int x_): x(x_) {}
constexpr int f() const { return x*x; }
};
constexpr A a(8);
int main() {
printf("%d", a.f());
}
gcc 4.7.2 already eliminates everything at -O1, clang 3.5 trunk needs -O2.
Another way to achieve this is:
#include <cstdio>
class A {
int x;
public:
A(int x_): x(x_) {}
int f() const { return x*x; }
};
static const A a(8);
int main() {
printf("%d", a.f());
}
It only works with clang at -O3. Apparently the constant folding in gcc is not that aggressive. (As clang shows, it can be done but gcc 4.7.2 did not implement it.)

You can force the compiler to fully optimize the function with all known constants by changing the pin_write function into a template. I don't know if the particular behavior is guaranteed by the standard though.
template< int a, int b >
void pin_write() { some_instructions; }
This will probably require fixing all lines where pin_write is used.
Additionally, you can declare the function as inline. The compiler isn't guaranteed to inline the function (the inline keyword is just an hint), but if it does, it has a greater chance to optimize compile time constants away (assuming the compiler can know it is an compile time constant, which may be not always the case).

Your a has external linkage, so the compiler can't be sure that there isn't other code somewhere modifying it.
If you were to declare a const then you make clear it shouldn't change, and also stop it having external linkage; both of those should help the compiler to be less pessimistic.
(I'd probably declare x const too - it may not help here, but if nothing else it makes it clear to the compiler and the next reader of the code that you never change it.)

Related

Is clang's global-constructors warning too strict?

In our project we often use a construct like this (simplified for clarity, we actually use a more safe to use version):
struct Info
{
Info(int x, int y) : m_x(x), m_y(y)
{}
int m_x;
int m_y;
};
struct Data
{
static const Info M_INFO_COLLECTION[3];
};
const Info Data::M_INFO_COLLECTION[] = // global-constructors warning
{
Info(1, 2),
Info(10, 9),
Info(0, 1)
};
M_INFO_COLLECTION can contain a large number of data points. The initialization part resides in the cpp file, which is often code-generated.
Now this structure gives us a fair amount of global-constructors-warnings in clang across our code base. I've read in a blog post that using warnings in the -Weverything group is a bad idea for nightly builds and I agree, and even the clang docdoes not recommend to use it.
Since the decision to switch off the warning is out of my hands, I could use a helpful trick to get rid of the warning (and a potential static initialization order fiasco), by converting the static member into a function initializing and returning a local static variable.
However, since our project does not use dynamically allocated memory as a rule, the original idea has to be used without a pointer, which can lead to deinitialization problems when my Data class is used by other objects in a weird way.
So, long story short: The global-constructors warning points to a piece of code that I can review as safe, since I know what the Data class does. I could get rid of it using a workaround that can lead to problems if other classes use Data in a particular way, but this won't generate a warning. My conclusion is that I would be better off just leaving the code as it is and ignore the warning.
So now I am stuck with a bunch of warnings, that may in some cases point to a SIOF and which I would like to address, but which get buried unter a mountain of warnings that I deliberately do not want to fix, because the fix would actually make things worse.
This brings me to my actual question: Is clang too strict in its interpretation of the warning? From my limited compiler understanding, shouldn't it be possible for the compiler to realize that in this particular case, the static member M_INFO_COLLECTION cannot possibly lead to a SIOF, since all its dependencies are non-static?
I played around with this issue a bit and even this piece of code gets the warning:
//at global scope
int get1()
{
return 1;
}
int i = get1(); // global-constructors warning
Whereas this works fine, as I would expect:
constexpr int get1()
{
return 1;
}
int i = 1; // no warning
int j = get1(); // no warning
This looks fairly trivial to me. Am I missing something or should clang be able to suppress the warning for this example (and possibly my original example above as well)?
The problem is that it is not constant initialized. This means that M_INFO_COLLECTION may be zero-initialized and then dynamically initialized at run time.
Your code generates assembley to set M_INFO_COLLECTION dynamically because of the "global constructor" (non-constant initialization): https://godbolt.org/z/45x6q6
An example where this leads to unexpected behaviour:
// data.h
struct Info
{
Info(int x, int y) : m_x(x), m_y(y)
{}
int m_x;
int m_y;
};
struct Data
{
static const Info M_INFO_COLLECTION[3];
};
// data.cpp
#include "data.h"
const Info Data::M_INFO_COLLECTION[] =
{
Info(1, 2),
Info(10, 9),
Info(0, 1)
};
// main.cpp
#include "data.h"
const int first = Data::M_INFO_COLLECTION[0].m_x;
int main() {
return first;
}
Now if you compile main.cpp before data.cpp, first may access Info out of it's lifetime. In practice, this UB just makes first 0.
E.g.,
$ clang++ -I. main.cpp data.cpp -o test
$ ./test ; echo $?
0
$ clang++ -I. data.cpp main.cpp -o test
$ ./test ; echo $?
1
Of course, this is undefined behaviour. At -O1, this issue disappears, and clang behaves as if M_INFO_COLLECTION is constant initialized (as-if it reordered the dynamic initialization to before first's dynamic initialization (and every other dynamic initialization), which it is allowed to do).
The fix to this is to not use global constructors. If your static storage duration variable is able to be constant initialized, make the relevant functions/constructors constexpr.
If you are not able to add constexprs or have to use a non-constant initialized variable, then you can resolve the static initialization order fiasco without dynamic memory using placement-new:
// data.h
struct Info
{
Info(int x, int y) : m_x(x), m_y(y)
{}
int m_x;
int m_y;
};
struct Data
{
static auto M_INFO_COLLECTION() -> const Info(&)[3];
static const Info& M_ZERO();
};
// data.cpp
#include "data.h"
#include <new>
auto Data::M_INFO_COLLECTION() -> const Info(&)[3] {
// Need proxy type for array reference
struct holder {
const Info value[3];
};
alignas(holder) static char storage[sizeof(holder)];
static auto& data = (new (storage) holder{{
Info(1, 2),
Info(10, 9),
Info(0, 1)
}})->value;
return data;
}
const Info& Data::M_ZERO() {
// Much easier for non-array types
alignas(Info) static char storage[sizeof(Info)];
static const Info& result = *new (storage) Info(0, 0);
return result;
}
Though this does have minor runtime overhead for each access, especially the very first, compared to regular static storage duration variables. It should be faster than the new T(...) trick, since it doesn't call a memory allocation operator.
In short, it's probably best to add constexpr to be able to constant initialize your static storage duration variables.

Does g++ empty function removal work recursively?

To the best of my knowledge, g++ with optimization turned on will remove the function call to bar entirely in the following case:
int bar() { }
int foo() { bar(); }
However, consider the following two cases, with bar defined as above:
Case 1:
int foo(int a, int b) {
if (a > b) bar();
}
Case 2:
int foo() { bar(); }
int foo2() {foo(); }
In Case 1, will the if statement also be removed, since it executes dead code even if the condition is true?
In Case 2:, will the call to foo inside foo2 be removed?
Following the suggestions in the comments, I tried this myself and it appears that the empty function calls are indeed removed recursively and completely in both cases I described, at least for gcc 4.8.1 and g++ 4.8.1.
I compiled the following two programs, first with gcc -S and then with gcc -S -O2.
Program 1:
int bar() { }
int foo() { bar(); }
int main() {
foo();
}
Program 2:
int bar() { }
int foo(int a, int b) {
if (a > b) bar();
}
int main() {
foo(2,1);
}
I also tried with foo's arguments passed in from the command line, to make sure the removal was not because of constants passed to foo.
int main(int argc, char** argv) {
foo(argc,1);
}
The compiler doesn't remove entire functions, the linker does.
If you're building an executable (or the functions are not exported out of a library), then the linker will remove all the orphan functions. If it doesn't, it's a bug :).
BTW, storing the address of a function (e.g. in a variable or passing it to another function) guaranties that the function will stay.
Edit
Just, to be clear, the optimizing compiler will inline functions, effectively removing the function calls where it deems necessary. In the above case (super simple functions) there's no doubt it will inline them. BTW, STL implementations (and boost) depend on this feature heavily.

G++: Can __attribute__((__may_alias__)) be used for pointer to class instance rather than to class definition itself?

I'm looking to the answer to the following question: is may_alias suitable as attribute for pointer to an object of some class Foo? Or must it be used at class level only?
Consider the following code(it is based on a real-world example which is more complex):
#include <iostream>
using namespace std;
#define alias_hack __attribute__((__may_alias__))
template <typename T>
class Foo
{
private:
/*alias_hack*/ char Data[sizeof (T)];
public:
/*alias_hack*/ T& GetT()
{
return *((/*alias_hack*/ T*)Data);
}
};
struct Bar
{
int Baz;
Bar(int baz)
: Baz(baz)
{}
} /*alias_hack*/; // <- uncommeting this line apparently solves the problem, but does so on class-level(rather than pointer-level)
// uncommenting previous alias_hack's doesn't help
int main()
{
Foo<Bar> foo;
foo.GetT().Baz = 42;
cout << foo.GetT().Baz << endl;
}
Is there any way to tell gcc that single pointer may_alias some another?
BTW, please note that gcc detection mechanism of such problem is imperfect, so it is very easy to just make this warning go away without actually solving the problem.
Consider the following snippet of code:
#include <iostream>
using namespace std;
int main()
{
long i = 42;
long* iptr = &i;
//(*(short*)&i) = 3; // with warning
//(*(short*)iptr) = 3; // without warning
cout << i << endl;
}
Uncomment one of the lines to see the difference in compiler output.
Simple answer - sorry, no.
__attrbite__ gives instructions to the compiler. Objects exist in the memory of the executed program. Hence nothing in __attribute__ list can relate to the run-time execution.
Dimitar is correct. may_alias is a type attribute. It can only apply to a type, not an instance of the type. What you'd like is what gcc calls a "variable attribute". It would not be easy to disable optimizations for one specific pointer. What would the compiler do if you call a function with this pointer? The function is potentially already compiled and will behave based on the type passed to the function, not based on the address store in the pointer (you should see now why this is a type attribute)
Now depending on your code something like that might work:
#define define_may_alias_type(X) class X ## _may alias : public X { } attribute ((may_alias));
You'd just pass your pointer as Foo_may_alias * (instead of Foo *) when it might alias. That's hacky though
Wrt your question about the warning, it's because -Wall defaults to -Wstrict-aliasing=3 which is not 100% accurate. Actually, -Wstrict-aliasing is never 100% accurate but depending on the level you'll get more or less false negatives (and false positives). If you pass -Wstrict-aliasing=1 to gcc, you'll see a warning for both

how to load (mov) a class variable into cpu register

I would like to load an int value defined as class member to eax cpu register. smt like this:
class x
{
int a;
x() { a=5; }
do_stuff()
{
__asm
{
mov eax, a; // mov a varbiale content into register
};
}
};
how can I do that with any variable in any class? thanks...
If you are using gcc or icc, this does exactly what you want:
class x
{
int a;
x() { a=5; }
do_stuff()
{
asm("mov %0, %%eax; // mov a varbiale content into register \n"
:
: "r" (a)
: "%eax"
);
}
};
An explanation of rgister constrains and clobber lists is at http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html if you are still interested. On MS VC I would not recommend using inline assembly, because the MS compiler is not good at mixing inline and generated assmbely and produces a lot of overhead.
The best way to load a class variable into a register is by letting the compiler do it for you.
Since the compiler always have to assume the worst, when it comes to reading things from memory, it might be forced to read the value from a class member multiple times, despite the fact that you know that the value has not changed.
For example, in the code below in the function do_stuff, the compiler can not assume that the value of mX is unchanged over the call to foo(). Hence, it is not allowed to place it in a processor register.
int glob;
int glob2;
void foo();
class Test
{
public:
Test(int x) : mX(x) { }
void do_stuff();
private:
int mX;
};
void Test::do_stuff()
{
glob = mX;
foo();
glob2 = mX;
}
On the other hand, in the following case, the source code is written so that tmp can't change over the function call, so the compiler is safe to place it in a register.
void Test::do_stuff()
{
int tmp = mX;
glob = tmp;
foo();
glob2 = tmp;
}
When it comes to inline assembler, I would strongly discourage you from using it. When introducing C++ the situation is even worse, as the underlying representation of a class object is not as straight-forward as that of a C struct (which must be laid out in memory exactly as declared). This mean that a slight change in the class or a migration to a newer compiler could break your code.
You need to get the address of of the instance of class "x" you're working with (mov eax,this), and the offset of "a" relative to the start of "x" (offsetof macro).
It's a lot easier if you just add "a" or "&a" as a parameter of the do_stuff() function.

is it possible in C or C++ to create a function inside another?

Could someone please tell me if this is possible in C or C++?
void fun_a();
//int fun_b();
...
main(){
...
fun_a();
...
int fun_b(){
...
}
...
}
or something similar, as e.g. a class inside a function?
thanks for your replies,
Wow, I'm surprised nobody has said yes! Free functions cannot be nested, but functors and classes in general can.
void fun_a();
//int fun_b();
...
main(){
...
fun_a();
...
struct { int operator()() {
...
} } fun_b;
int q = fun_b();
...
}
You can give the functor a constructor and pass references to local variables to connect it to the local scope. Otherwise, it can access other local types and static variables. Local classes can't be arguments to templates, though.
C++ does not support nested functions, however you can use something like boost::lambda.
C — Yes for gcc as an extension.
C++ — No.
you can't create a function inside another function in C++.
You can however create a local class functor:
int foo()
{
class bar
{
public:
int operator()()
{
return 42;
}
};
bar b;
return b();
}
in C++0x you can create a lambda expression:
int foo()
{
auto bar = []()->int{return 42;};
return bar();
}
No but in C++0x you can http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions which may take another few years to fully support. The standard is not complete at the time of this writing.
-edit-
Yes
If you can use MSVC 2010. I ran the code below with success
void test()
{
[]() { cout << "Hello function\n"; }();
auto fn = [](int x) -> int { cout << "Hello function (" << x << " :))\n"; return x+1; };
auto v = fn(2);
fn(v);
}
output
Hello function
Hello function (2 :))
Hello function (3 :))
(I wrote >> c:\dev\loc\uniqueName.txt in the project working arguments section and copy pasted this result)
The term you're looking for is nested function. Neither standard C nor C++ allow nested functions, but GNU C allows it as an extension. Here is a good wikipedia article on the subject.
Clang/Apple are working on 'blocks', anonymous functions in C! :-D
^ ( void ) { printf("hello world\n"); }
info here and spec here, and ars technica has a bit on it
No, and there's at least one reason why it would complicate matters to allow it. Nested functions are typically expected to have access to the enclosing scope. This makes it so the "stack" can no longer be represented with a stack data structure. Instead a full tree is needed.
Consider the following code that does actually compile in gcc as KennyTM suggests.
#include <stdio.h>
typedef double (*retdouble)();
retdouble wrapper(double a) {
double square() { return a * a; }
return square;
}
int use_stack_frame(double b) {
return (int)b;
}
int main(int argc, char** argv) {
retdouble square = wrapper(3);
printf("expect 9 actual %f\n", square());
printf("expect 3 actual %d\n", use_stack_frame(3));
printf("expect 16 actual %f\n", wrapper(4)());
printf("expect 9 actual %f\n", square());
return 0;
}
I've placed what most people would expect to be printed, but in fact, this gets printed:
expect 9 actual 9.000000
expect 3 actual 3
expect 16 actual 16.000000
expect 9 actual 16.000000
Notice that the last line calls the "square" function, but the "a" value it accesses was modified during the wrapper(4) call. This is because a separate "stack" frame is not created for every invocation of "wrapper".
Note that these kinds of nested functions are actually quite common in other languages that support them like lisp and python (and even recent versions of Matlab). They lead to some very powerful functional programming capabilities, but they preclude the use of a stack for holding local scope frames.
void foo()
{
class local_to_foo
{
public: static void another_foo()
{ printf("whatevs"); }
};
local_to_foo::another_foo();
}
Or lambda's in C++0x.
You can nest a local class within a function, in which case the class will only be accessible to that function. You could then write your nested function as a member of the local class:
#include <iostream>
int f()
{
class G
{
public:
int operator()()
{
return 1;
}
} g;
return g();
}
int main()
{
std::cout << f() << std::endl;
}
Keep in mind, though, that you can't pass a function defined in a local class to an STL algorithm, such as sort().
int f()
{
class G
{
public:
bool operator()(int i, int j)
{
return false;
}
} g;
std::vector<int> v;
std::sort(v.begin(), v.end(), g); // Fails to compile
}
The error that you would get from gcc is "test.cpp:18: error: no matching function for call to `sort(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, f()::G&)'
"
It is not possible to declare a function within a function. You may, however, declare a function within a namespace or within a class in C++.
Not in standard C, but gcc and clang support them as an extension. See the gcc online manual.
Though C and C++ both prohibit nested functions, a few compilers support them anyway (e.g., if memory serves, gcc can, at least with the right flags). A nested functor is a lot more portable though.
No nested functions in C/C++, unfortunately.
As other answers have mentioned, standard C and C++ do not permit you to define nested functions. (Some compilers might allow it as an extension, but I can't say I've seen it used).
You can declare another function inside a function so that it can be called, but the definition of that function must exist outside the current function:
#include <stdlib.h>
#include <stdio.h>
int main( int argc, char* argv[])
{
int foo(int x);
/*
int bar(int x) { // this can't be done
return x;
}
*/
int a = 3;
printf( "%d\n", foo(a));
return 0;
}
int foo( int x)
{
return x+1;
}
A function declaration without an explicit 'linkage specifier' has an extern linkage. So while the declaration of the name foo in function main() is scoped to main(), it will link to the foo() function that is defined later in the file (or in a another file if that's where foo() is defined).