c++/10528: Unexpected loop un-optimization when removing a field of a class
have@ann.jussieu.fr
have@ann.jussieu.fr
Mon Apr 28 22:06:00 GMT 2003
>Number: 10528
>Category: c++
>Synopsis: Unexpected loop un-optimization when removing a field of a class
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: unassigned
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Apr 28 22:06:01 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator: have@ann.jussieu.fr
>Release: 3.3
>Organization:
>Environment:
Linux i686
>Description:
Removing a field of a class implies a loop un-optimization [2 useless mov in asm code]
Asm code of main loop of go1 function, with 'optimize' field
.L5:
cmpl %ecx, %eax
je .L21
addl (%eax), %ebx # c
addl $4, %eax
jmp .L5
Asm code without 'optimize' field
.L5:
movl 4(%ebx), %eax
cmpl %edx, %eax
je .L20
addl (%eax), %ecx # c
addl $4, %eax
movl %eax, 4(%ebx) # <variable>._M_current
jmp .L5
We can see that 2 movl operations slow down the code.
Previous release of g++ never optimize this part [same (slow) code with or without the field]
>How-To-Repeat:
No flag about alignement, loop or reg moves optimizations change this behaviour.
Compile the following piece of code (extracted from STL vector by removing unused code and templates) and look at asm code.
Removing comment on 'optimize' field (WI class) optimizes go1 function loop.
[go2 function is given as reference]
-----------%<-----------------------------
class const_iterator {
protected:
typedef const int * _Iterator;
typedef const int & _Reference;
_Iterator _M_current;
public:
const_iterator () : _M_current(0) { }
const_iterator (const _Iterator& __i) : _M_current(__i) { }
_Reference operator*() const { return *_M_current; }
const_iterator & operator++() { ++_M_current; return *this; }
const _Iterator& base() const { return _M_current; }
};
inline bool operator==(const const_iterator & __lhs,
const const_iterator & __rhs)
{ return __lhs.base() == __rhs.base(); }
inline bool operator!=(const const_iterator & __lhs,
const const_iterator & __rhs)
{ return __lhs.base() != __rhs.base(); }
class vector {
protected:
int* _M_start;
int* _M_finish;
int* _M_end_of_storage;
public:
typedef int value_type;
public:
const_iterator begin() const { return const_iterator (_M_start); }
const_iterator end() const { return const_iterator (_M_finish); }
explicit vector(unsigned __n) {
_M_start = new int[__n];
_M_finish = _M_start;
}
};
class WI {
private:
const vector & object;
const_iterator _iterator;
// int optimize;
public:
WI(const vector &in) : object(in), _iterator(in.begin()) { }
inline void operator++() { ++_iterator; }
inline int operator*() const { return *_iterator; }
inline bool end() const { return _iterator == object.end(); }
};
int go1(const vector & v1) {
int c = 0;
for(WI i(v1);!i.end();++i) c += *i;
return c;
}
int go2(const vector & v2) {
int c = 0;
for(const_iterator i = v2.begin();i != v2.end();++i) c += *i;
return c;
}
int main(void) {
vector v(10);
go1(v); go2(v);
}
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the Gcc-prs
mailing list