This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Omitted conversion float -> double in x86 back-end


On 11/21/06, Roberto COSTA <roberto.costa@st.com> wrote:
Hello,
I've just noticed that, in a sequence of conversions signed long long ->
float -> double, x86 back-end eats the intermediate conversion away.
In this case, the conversion to float isn't redundant because it lowers
the precision of the computation (which is something a programmer may
want to do).
It looks to me this this is a bug; I'm not completely sure because of my
ignorance of what C standards state about it.
Before filing a report, I'd like to hear other opinions.

Here is a simple example:

------------- float_conv.c ------------
double foo(signed long long l)
{
     return (float)l;
}
---------------------------------------

Files float_conv.c.026t.fixupcfg and float_conv.s are the outcome of the
following compilation:
     gcc -O0 float_conv.c -S -fdump-tree-all

------ float_conv.c.026t.fixupcfg -----
;; Function foo (foo)

foo (l)
{
   float D.1524;
   double D.1523;

<bb 2>:
   D.1524 = (float) l;
   D.1523 = (double) D.1524;
   return D.1523;
}
---------------------------------------

------------- float_conv.s ------------
         .file   "float_conv.c"
         .text
.globl foo
         .type   foo, @function
foo:
         pushl   %ebp
         movl    %esp, %ebp
         subl    $8, %esp
         movl    8(%ebp), %eax
         movl    %eax, -8(%ebp)
         movl    12(%ebp), %eax
         movl    %eax, -4(%ebp)
         fildll  -8(%ebp)
         leave
         ret
         .size   foo, .-foo
         .ident  "GCC: (GNU) 4.2.0 20060826 (experimental)"
         .section        .note.GNU-stack,"",@progbits
---------------------------------------

The conversion is still there at the end of GIMPLE passes, which leads
me to the conclusion that it is removed in RTL compilation.

Yes, with -O2 after expand we have


;; return (double) (float) l
(insn 10 9 11 (set (reg:SF 62)
       (float:SF (reg/v:DI 60 [ l ]))) -1 (nil)
   (nil))

(insn 11 10 12 (set (reg:DF 61)
       (float_extend:DF (reg:SF 62))) -1 (nil)
   (nil))

(insn 12 11 13 (set (reg:DF 59 [ <result> ])
       (reg:DF 61)) -1 (nil)
   (nil))

which is ok. Even after combine it's ok:

(insn 10 7 15 2 (set (reg:SF 62)
       (float:SF (mem/c/i:DI (reg/f:SI 16 argp) [3 l+0 S8 A32]))) 172
{*floatdisf2_i387} (nil)
   (nil))

(note 15 10 18 2 NOTE_INSN_FUNCTION_END)

(insn 18 15 24 2 (set (reg/i:DF 8 st [ <result> ])
       (float_extend:DF (reg:SF 62))) 125 {*extendsfdf2_i387}
(insn_list:REG_DEP_TRUE 10 (nil))
   (expr_list:REG_DEAD (reg:SF 62)
       (nil)))

(insn 24 18 0 2 (use (reg/i:DF 8 st [ <result> ])) -1
(insn_list:REG_DEP_TRUE 18 (nil))
   (nil))

but then regstack comes along and

(insn:TI 10 32 33 2 (set (reg:SF 8 st)
       (float:SF (mem/c/i:DI (plus:SI (reg/f:SI 6 bp)
                   (const_int 8 [0x8])) [3 l+0 S8 A32]))) 172
{*floatdisf2_i387} (nil)
   (nil))

(note 33 10 34 2 NOTE_INSN_EPILOGUE_BEG)

(insn:TI 34 33 24 2 (parallel [
           (set (reg/f:SI 6 bp)
               (mem:SI (reg/f:SI 7 sp) [0 S4 A8]))
           (set (reg/f:SI 7 sp)
               (plus:SI (reg/f:SI 7 sp)
                   (const_int 4 [0x4])))
       ]) 37 {popsi1} (nil)
   (nil))

(insn 24 34 35 2 (use (reg/i:DF 8 st [ <result> ])) -1 (nil)
   (nil))

where the *floatdisf2_i387 pattern misses the truncation to SFmode.

(you should file a bugzilla about this)

Richard.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]