This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
scheduler first pass and destructive scheduling of REG_LIBCALL/REG_RETVAL blocks?
- To: gcc at gcc dot gnu dot org
- Subject: scheduler first pass and destructive scheduling of REG_LIBCALL/REG_RETVAL blocks?
- From: Franz Sirl <Franz dot Sirl-kernel at lauterbach dot com>
- Date: Sat, 31 Mar 2001 23:07:23 +0200
Hi,
I'm currently tracking an excessive stack usage problem with DImode and
inlined functions with gcc-2.95.3 on powerpc with the appended testcase. It
turned out that the problem is still present in 3.0 and mainline.
What I'm not sure about is whether to *first* scheduler pass (before reload)
is allowed to destroy REG_LIBCALL/REG_RETVAL blocks? Are there any rules if
so? The documentation is unclear in this respect.
It seems that the destructive scheduling of these blocks confuses reload and
causes the excessive stack usage. In fact, if I add -fno-schedule-insns the
stack usage is normal (just n DImode-sized stackslots remain for the inlined
return values that we can't currently optimize away), 176 bytes. Otherwise
the stackusage is between 560 and more than 3000 bytes. This is deadly for
the limited kernel stack space in linux and was triggered by ReiserFS on PPC.
Any opinions on that? The appended testcase nicely shows the problem if you
compile it with "-O2 -mcpu=603e -S" and look at the assembler output.
Franz.
typedef long long loff_t;
typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned int __u32;
typedef unsigned long long __u64;
extern __inline__ __const__ __u16 __fswab16(__u16 x)
{
return ({ __u16 __tmp = ( x ) ; ({ __u16 __x = ( __tmp ); ((__u16)( (((__u16)(__x) & (__u16)0x00ffU) << 8) | (((__u16)(__x) & (__u16)0xff00U) >> 8) )); }) ; }) ;
}
extern __inline__ __const__ __u32 __fswab32(__u32 x)
{
return ({ __u32 __tmp = ( x ) ; ({ __u32 __x = ( __tmp ); ((__u32)( (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); }) ; }) ;
}
extern __inline__ __const__ __u64 __fswab64(__u64 x)
{
return ({ __u64 __tmp = ( x ) ; ({ __u64 __x = ( __tmp ); ((__u64)( (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); }) ; }) ;
}
struct offset_v1 {
__u32 k_offset;
__u32 k_uniqueness;
} __attribute__ ((__packed__));
struct offset_v2 {
union {
struct {
__u64 k_type: 4;
__u64 k_offset:60;
} offset;
__u64 em_offset;
} u;
} __attribute__ ((__packed__));
extern inline __u16 offset_v2_k_type( struct offset_v2 *v2 )
{
struct offset_v2 tmp;
tmp.u.em_offset = (__builtin_constant_p((__u64)( ( v2->u.em_offset ) )) ? ({ __u64 __x = ( ( ( v2->u.em_offset ) ) ); ((__u64)( (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); }) : __fswab64(( ( v2->u.em_offset ) ))) ;
return tmp.u.offset.k_type;
}
extern inline void set_offset_v2_k_type( struct offset_v2 *v2, int type )
{
struct offset_v2 tmp;
tmp.u.em_offset = (__builtin_constant_p((__u64)( ( v2->u.em_offset ) )) ? ({ __u64 __x = ( ( ( v2->u.em_offset ) ) ); ((__u64)( (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); }) : __fswab64(( ( v2->u.em_offset ) ))) ;
tmp.u.offset.k_type = type;
v2->u.em_offset = (__builtin_constant_p((__u64)( ( tmp.u.em_offset ) )) ? ({ __u64 __x = ( ( ( tmp.u.em_offset ) ) ); ((__u64)( (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); }) : __fswab64(( ( tmp.u.em_offset ) ))) ;
}
extern inline loff_t offset_v2_k_offset( struct offset_v2 *v2 )
{
struct offset_v2 tmp;
tmp.u.em_offset = (__builtin_constant_p((__u64)( ( v2->u.em_offset ) )) ? ({ __u64 __x = ( ( ( v2->u.em_offset ) ) ); ((__u64)( (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); }) : __fswab64(( ( v2->u.em_offset ) ))) ;
return tmp.u.offset.k_offset;
}
extern inline void set_offset_v2_k_offset( struct offset_v2 *v2, loff_t offset ){
struct offset_v2 tmp;
tmp.u.em_offset = (__builtin_constant_p((__u64)( ( v2->u.em_offset ) )) ? ({ __u64 __x = ( ( ( v2->u.em_offset ) ) ); ((__u64)( (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); }) : __fswab64(( ( v2->u.em_offset ) ))) ;
tmp.u.offset.k_offset = offset;
v2->u.em_offset = (__builtin_constant_p((__u64)( ( tmp.u.em_offset ) )) ? ({ __u64 __x = ( ( ( tmp.u.em_offset ) ) ); ((__u64)( (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); }) : __fswab64(( ( tmp.u.em_offset ) ))) ;
}
struct key {
__u32 k_dir_id;
__u32 k_objectid;
union {
struct offset_v1 k_offset_v1;
struct offset_v2 k_offset_v2;
} __attribute__ ((__packed__)) u;
} __attribute__ ((__packed__));
struct item_head
{
struct key ih_key;
union {
__u16 ih_free_space_reserved;
__u16 ih_entry_count;
} __attribute__ ((__packed__)) u;
__u16 ih_item_len;
__u16 ih_item_location;
__u16 ih_version;
} __attribute__ ((__packed__));
extern inline loff_t le_key_k_offset (int version, struct key * key)
{
return (version == 0 ) ?
(__builtin_constant_p((__u32)( ( key->u.k_offset_v1.k_offset ) )) ? ({ __u32 __x = ( ( ( key->u.k_offset_v1.k_offset ) ) ); ((__u32)( (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); }) : __fswab32(( ( key->u.k_offset_v1.k_offset ) ))) :
offset_v2_k_offset( &(key->u.k_offset_v2) );
}
extern inline loff_t le_ih_k_offset (struct item_head * ih)
{
return le_key_k_offset ((__builtin_constant_p((__u16)( ( ( ih )->ih_version ) )) ? ({ __u16 __x = ( ( ( ( ih )->ih_version ) ) ); ((__u16)( (((__u16)(__x) & (__u16)0x00ffU) << 8) | (((__u16)(__x) & (__u16)0xff00U) >> 8) )); }) : __fswab16(( ( ( ih )->ih_version ) ))) , &(ih->ih_key));
}
void
dummy_function( struct item_head *ih )
{
le_ih_k_offset( ih );
le_ih_k_offset( ih );
le_ih_k_offset( ih );
le_ih_k_offset( ih );
le_ih_k_offset( ih );
le_ih_k_offset( ih );
le_ih_k_offset( ih );
le_ih_k_offset( ih );
le_ih_k_offset( ih );
le_ih_k_offset( ih );
}