A reg mode bug in alpha
H.J. Lu
hjl@lucon.org
Fri Feb 13 23:13:00 GMT 1998
Hi,
There is a reg mode related bug on alpha. Here is the sample code. With
# gcc -O -g -mieee -o ieee ieee.c
3 RTLs:
(insn 4 2 5 (set (reg/v:SF 68)
(reg:SF 48 $f16)) 240 {movsf-2} (nil)
(expr_list:REG_DEAD (reg:SF 48 $f16)
(nil)))
(insn 14 8 19 (set (reg:SI 74)
(subreg:SI (reg/v:SF 68) 0)) 244 {movdf+1} (insn_list 4 (nil))
(expr_list:REG_DEAD (reg/v:SF 68)
(nil)))
(insn 19 14 23 (set (reg/v:DI 69)
(sign_extend:DI (reg:SI 74))) 0 {extendsidi2} (insn_list 14 (nil))
(expr_list:REG_DEAD (reg:SI 74)
(nil)))
are combined into 1 RTL:
(insn 19 14 23 (set (reg/v:DI 69)
(sign_extend:DI (subreg:SI (reg:DI 48 $f16) 0))) 0 {extendsidi2} (nil)
(expr_list:REG_DEAD (reg:SF 48 $f16)
(nil)))
As you can see, the reg mode info is only in REG_DEAD. In global_alloc,
this RTL is split into
(insn 95 14 98 (set (mem:DI (plus:DI (reg:DI 30 $30)
(const_int 16)))
(reg:DI 48 $f16)) -1 (nil)
(nil))
(insn 98 95 19 (set (reg:DI 3 $3)
(mem:DI (plus:DI (reg:DI 30 $30)
(const_int 16)))) -1 (nil)
(nil))
(insn:HI 19 98 23 (set (reg/v:DI 9 $9)
(sign_extend:DI (subreg:SI (reg:DI 3 $3) 0))) 0 {extendsidi2} (nil)
(expr_list:REG_DEAD (reg:SF 48 $f16)
(nil)))
As you can see the reg mod info is lost. The result is instead of
sts $f16,16($30)
egcs emits
stt $f16,16($30)
Is there a fix for that? Thanks.
--
H.J. Lu (hjl@gnu.org)
---ieee.c---
typedef int int32_t __attribute__ ((__mode__ ( __SI__ ))) ;
typedef union
{
float value;
int32_t word;
} ieee_float_shape_type;
int isinff(float x)
{
int32_t ix,t;
ieee_float_shape_type gf_u;
gf_u.value = x;
ix = gf_u.word;
if (ix == 0)
abort ();
else
printf ("%x\n", ix);
t = ix & 0x7fffffff;
t ^= 0x7f800000;
t |= -t;
return ~(t >> 31) & (1 - ((ix & 0x80000000) >> 30));
}
main ()
{
float x = 1.0 / 0.0;
printf ("%d\n", isinff (x));
return 0;
}
More information about the Gcc
mailing list