Hi,
I encountered a problem on test 'gcc.c-torture/execute/loop-7.c' (gcc4.7.3) on
my private port during test case "-O2 -flto -fuse-linker-plugin
-fno-fat-lto-objects"
Here is the tested code :
void foo (unsigned int n)
{
int i, j = -1;
for (i = 0; i < 10 && j < 0; i++)
{
if ((1UL << i) == n)
j = i;
}
if (j < 0)
abort ();
}
main()
{
foo (64);
exit (0);
}
The LTO option merge the foo function into the main function.
I'll try present my problem by simplifying the resulting assembler.
<main>:
:L1
[...] << content of the loop
compare 0, $R0 << test to know if the loop goes on or stop
($R0 synthetize the whole loop end condition)
jump_delayed.ifNE L1 << conditional delayed jump : the loop end if $R0
== 0
nop #delayslot1
sll $R1, 1, $R0 #delayslot2 << instruction which is part of the loop content
but placed into the 2nd delay slot of jump_delayed.ifNE instruction
compare -1, $R2 << test if (j < 0)
branch.ifeq abort << conditional branch to abort
branch exit << branch to exit which expect a 0 into
$R0 as first parameter
The test fail, not because abort is called, but because exit is called with $R0
containing 0x80 and not 0.
I think GCC expect $R0 to be equal to 0 when the loop end (so no need to set
explicitly $R0 to 0)
But in this case the 'sll' instruction placed into the delay slot of the
conditional delayed jump modify $R0 even if no jump is performed.
Is it a bug due to LTO merging the 'foo' and 'main' function ?
Or does GCC really thinks that the instructions placed into the delay slot of
conditional jump are executed only if the condition is true ?
Or is it simply a GCC incompatibility between 'conditional jump' & 'delay
slots' ?
Here are some parts of my backend relative to delay slot and conditional jump
(nothing formidable :) ):
(define_delay (ior (eq_attr "type" "jump") (eq_attr "type" "cond_jump"))
[(and (eq_attr "delayable" "yes") (eq_attr "length" "1")) (nil) (nil)
(and (eq_attr "delayable" "yes") (eq_attr "length" "1")) (nil) (nil)])
(define_insn "jumpif"
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(match_operand 2 "cc_register" "") (const_int 0)])
(label_ref (match_operand 1 "" ""))
(pc)))]
""
{ [...] // use final_sequence to detect delay slot }
[set_attr "type" "cond_jump")
(set_attr "delayable" "no")]
Regards,
Selim