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





Reply via email to