This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug optimization/15187] New: Inefficient if optimization with -O2 -ffast-math
- From: "uros at kss-loka dot si" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 28 Apr 2004 06:47:24 -0000
- Subject: [Bug optimization/15187] New: Inefficient if optimization with -O2 -ffast-math
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
This testcase compiles with '-O2 -ffast-math' into extremely inefficient asm code:
double test(double x) {
if (x > 0.0)
return cos(x);
else
return sin(x);
}
--cut here--
test:
pushl %ebp
movl %esp, %ebp
fldl 8(%ebp)
fcoml .LC1
fnstsw %ax
fld %st(0)
fcos
sahf
ja .L6
fstp %st(0)
fsin
jmp .L1
.p2align 4,,7
.L6:
fstp %st(1)
.L1:
popl %ebp
ret
--cut here--
It will _always_ call fcos instruction, and - depending on input - overwrite
output of fcos with output of fsin instruction. This problem is not fsin/fcos
specific.
The problem is in ifcvt.c, find_if_case_1() function. Around line 2889, there is
a condition:
/* THEN is small. */
if (count_bb_insns (then_bb) > BRANCH_COST)
return FALSE;
This condition would prevent moving 'else' BB before 'if', if then_bb is not
small. 'Small' means a couple of instructions with default BRANCH_COST (= 1).
However, if an instruction is UNSPEC_*, this instruction can last hundred of
cycles (as it is case with fsin or fcos), but it is still _one_ RTL instruction.
So the case above is not triggered, and fcos is moved before 'if'.
The situation is even worser with '-O2 -ffast-math -march=i686'. fsin and fcos
are called every time...
test:
pushl %ebp
movl %esp, %ebp
fldl 8(%ebp)
fldz
fld %st(1)
fld %st(2)
fxch %st(1)
fcos
fxch %st(3)
popl %ebp
fcomip %st(2), %st
fstp %st(1)
fsin
fcmovnbe %st(1), %st
fstp %st(1)
ret
--
Summary: Inefficient if optimization with -O2 -ffast-math
Product: gcc
Version: 3.5.0
Status: UNCONFIRMED
Severity: critical
Priority: P2
Component: optimization
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: uros at kss-loka dot si
CC: gcc-bugs at gcc dot gnu dot org
GCC build triplet: i686-pc-linux-gnu
GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15187