[PATCH] Fix old problem in if-conversion pass
Eric Botcazou
ebotcazou@adacore.com
Tue Nov 8 14:47:00 GMT 2005
Hi,
We've run into a problematic piece of code in ifcvt.c that has been there from
the day the file was added. It's in noce_try_abs:
/* Verify that C is zero. Search backward through the block for
a REG_EQUAL note if necessary. */
if (REG_P (c))
{
rtx insn, note = NULL;
for (insn = earliest;
insn != BB_HEAD (if_info->test_bb);
insn = PREV_INSN (insn))
if (INSN_P (insn)
&& ((note = find_reg_note (insn, REG_EQUAL, c))
|| (note = find_reg_note (insn, REG_EQUIV, c))))
break;
if (! note)
return FALSE;
c = XEXP (note, 0);
}
This code triggers an ICE if 'earliest' doesn't live in the same BB as the
jump (because of -fnon-call-exceptions) as the condition
insn != BB_HEAD (if_info->test_bb);
is never true. The minimal fix could be to avoid searching backwards if
'earliest' doesn't live in the same BB as the jump. However it turns out that
the whole loop is broken:
- it only looks for notes, potentially missing simple sets,
- it invokes find_reg_note (insn, REG_EQUAL, c) but 'c' is a register so it
looks for notes that reference a pseudo! Since the code just below
essentially accepts only the constant 0, the loop is dead and FALSE is always
returned, i.e. it cannot even optimize
float foo(float f)
{
if (f < 0.0)
f = -f;
return f;
}
at -O -march=i686:
foo:
pushl %ebp
movl %esp, %ebp
flds 8(%ebp)
fld %st(0)
fchs
fldz
fucomip %st(2), %st
fcmovbe %st(1), %st
fstp %st(1)
popl %ebp
ret
I think the correct approach is to look only at the insn immediately preceding
'earliest'. This idiom is used elsewhere (noce_get_alt_condition).
But there is yet another problem: a 'neg' is emitted right after the 'abs',
that is the above C code is turned into:
float foo(float f)
{
return - fabs (f);
}
The problem is that noce_try_abs forgets to negate the transformation when the
comparison (f < 0.0) is written as (0.0 > f).
With the attached patch, the code generated at -O -march=i686 for the above C
testcase is:
foo:
pushl %ebp
movl %esp, %ebp
flds 8(%ebp)
fabs
popl %ebp
ret
Bootstrapped/regtested on x86_64-suse-linux. OK for mainline?
2005-11-08 Eric Botcazou <ebotcazou@adacore.com>
* ifcvt.c (noce_try_abs): Negate if the comparison is reversed.
Look only one instruction backwards for a REG_EQUAL note.
--
Eric Botcazou
-------------- next part --------------
A non-text attachment was scrubbed...
Name: e412-010_fsf.diff
Type: text/x-diff
Size: 1874 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20051108/081d3b32/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: fabs.c
Type: text/x-csrc
Size: 98 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20051108/081d3b32/attachment-0001.bin>
More information about the Gcc-patches
mailing list