I've found the bug working on direct threaded interpreter for PHP. Moving from
GCC 4.3 to GCC 4.4 caused a significant performance degradation. Looking into
produced assembler code I realized that GCC 4.4 doesn't replace all jmps to
indirect jmp with indirect jmp itself. The reason is the following new
condition in function duplicate_computed_gotos() bb-reorder.c
if (!optimize_bb_for_size_p (bb))
continue;
I thought I would able to fix the problem using "hot" attribute, but
according to this condition, in case I mark function with __attribute__((hot))
duplication doesn't work, and in case I mark it with __attribute__((cold)) it
starts work. As result "hot" function works slower than "cold".
You can use the simplified code to verify it. I ran it with 'gcc -O2 -S
direct.c'
direct.c
#define NEXT goto **ip++
#define guard(n) asm("#" #n)
__attribute__((cold)) void *emu (void **prog)
{
static void *labels[] =
{&&next1,&&next2,&&next3,&&next4,&&next5,&&next6,&&next7,&&next8,&&next9,&&loop};
void **ip;
intcount;
if (!prog) {
return labels;
}
ip=prog;
count = 1000;
NEXT;
next1:
guard(1);
NEXT;
next2:
guard(2);
NEXT;
next3:
guard(3);
NEXT;
next4:
guard(4);
NEXT;
next5:
guard(5);
NEXT;
next6:
guard(6);
NEXT;
next7:
guard(7);
NEXT;
next8:
guard(8);
NEXT;
next9:
guard(9);
NEXT;
loop:
if (count>0) {
count--;
ip=prog;
NEXT;
}
return 0;
}
int main() {
void *prog[] = {(void*)0,(void*)1,
(void*)0,(void*)2,
(void*)0,(void*)3,
(void*)0,(void*)4,
(void*)0,(void*)9};
void **labels = emu(0);
int i;
for (i=0; i < sizeof(prog)/sizeof(prog[0]); i++) {
prog[i] = labels[(int)prog[i]];
}
emu(prog);
return 0;
}
I saw that the check causing the slowdown was removed in trunk, however I can't
check that it was done in a proper way.
--
Summary: GCC doesn't duplicate computed gotos for functions
marked as "hot"
Product: gcc
Version: 4.4.3
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: dmitry at zend dot com
GCC build triplet: i686-redhat-linux
GCC host triplet: i686-redhat-linux
GCC target triplet: i686-redhat-linux
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43686