[Bug rtl-optimization/77668] New: register allocation shoud not occupy register for return value early
yumeyao at hotmail dot com
gcc-bugzilla@gcc.gnu.org
Tue Sep 20 18:22:00 GMT 2016
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77668
Bug ID: 77668
Summary: register allocation shoud not occupy register for
return value early
Product: gcc
Version: 7.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: yumeyao at hotmail dot com
Target Milestone: ---
when return value is declared (or, RVO introduced returning this pointer), RA
seems to be very greedy on occupying r0(eax/rax) for the return value, even if
the return value is not used yet.
With such RA strategy, the quick register reserved for return value is no
longer usable for tmp variables.
Here is just one simple example demonstrating this issue:
compile with -m32 -O[anylevel] targeting Intel x86
always able to reproduce on gcc 4.x to 6.2.0 and on 7.0 snapshots.
getA() is where RVO is applied, resulting "this" pointer (for returning)
occupying one register.
In total, 4 registers used. The life-scope of "this" pointer and one tmp
variable don't overlap, where 1 register should be enough, but 2 registers
allocated.
getA_RVO() with the complex syntax is where we 'manually' do the RVO stuff to
make the function prototype identical to RVO'ed getA() (calling convention on
returning stack poping is not same, though)
in getA_RVO(), I just showed up that we can use the same register for ret (eax)
as a temp register before we actually start using it, thus only 3 registers
used.
getA_RVO2() is just a simple test to clarify the problem is not caused by RVO,
as we manually declare the return var and assign to it, but the return var
still extended its life-span. So likely the problem is caused by RA being
greedy on ret reg.
struct A {
int a;
int b;
int c;
A(int i, int j) {
int tmp;
int h = i;
int e;
__asm__ __volatile__( //do something in assembly
"or $123, %0;"
"mov %0, %1;"
"xor $234, %1;"
"lea 20(%0), %2;"
: "+r"(h), "=r"(tmp), "=r"(e)
);
b = h;
c = e;
a = j;
}
};
A getA(int i, int j) {
return A(i, j);
}
getA(int, int):
push %ebx
mov 0x8(%esp),%eax
mov 0xc(%esp),%edx
or $0x7b,%edx
mov %edx,%ebx
xor $0xea,%ebx
lea 0x14(%edx),%ecx
mov %edx,0x4(%eax)
mov 0x10(%esp),%edx
mov %ecx,0x8(%eax)
mov %edx,(%eax)
pop %ebx
ret $0x4
A* getA_RVO(A* src, int i, int j) {
A* ret;
int h = i;
int e;
__asm__ __volatile__(
"or $123, %0;"
"mov %0, %1;"
"xor $234, %1;"
"lea 20(%0), %2;"
"mov %3, %1;" //switch this line with ret = src
: "+r"(h), "=r"(ret), "=r"(e)
: "rm"(src)
);
//ret = src;
ret->b = h;
ret->c = e;
ret->a = j;
return ret;
}
getA_RVO(A*, int, int):
mov 0x8(%esp),%edx
or $0x7b,%edx
mov %edx,%eax
xor $0xea,%eax
lea 0x14(%edx),%ecx
mov 0x4(%esp),%eax
mov %edx,0x4(%eax)
mov 0xc(%esp),%edx
mov %ecx,0x8(%eax)
mov %edx,(%eax)
ret
//switch the commented lines in getA_RVO() to get getA_RVO2
getA_RVO2(A*, int, int):
push %ebx
mov 0x8(%esp),%eax
mov 0xc(%esp),%edx
or $0x7b,%edx
mov %edx,%ebx
xor $0xea,%ebx
lea 0x14(%edx),%ecx
mov %edx,0x4(%eax)
mov 0x10(%esp),%edx
mov %ecx,0x8(%eax)
mov %edx,(%eax)
pop %ebx
ret
More information about the Gcc-bugs
mailing list