This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR optimization/13041
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 20 Nov 2003 22:32:31 +0100
- Subject: [PATCH] Fix PR optimization/13041
Hi,
This is the kernel miscompilation talked about here:
http://gcc.gnu.org/ml/gcc/2003-11/msg00893.html
a regression on the 3.3 branch.
The attached patch implements the minimal fix.
Bootstrapped/regtested on i586-redhat-linux-gnu (3.3 branch except Ada). I've
attached a reduced testcase but it is not integrable in the testsuite. The
problem can be found by visual inspection (line below the .L4 label).
Ok for mainline and 3.3 branch?
2003-11-20 Eric Botcazou <ebotcazou@libertysurf.fr>
PR optimization/13041
* final.c (frame_pointer_needed): Fix comment.
* reload1.c (reload): Decrease alignment of the frame
pointer if it was used for register allocation.
--
Eric Botcazou
Index: final.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/final.c,v
retrieving revision 1.271.2.1
diff -u -r1.271.2.1 final.c
--- final.c 25 Jan 2003 23:40:06 -0000 1.271.2.1
+++ final.c 20 Nov 2003 10:24:13 -0000
@@ -170,8 +170,8 @@
char regs_ever_live[FIRST_PSEUDO_REGISTER];
/* Nonzero means current function must be given a frame pointer.
- Set in stmt.c if anything is allocated on the stack there.
- Set in reload1.c if anything is allocated on the stack there. */
+ Initialized in function.c to 0. Set only in reload1.c as per
+ the needs of the function. */
int frame_pointer_needed;
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.366.2.6
diff -u -r1.366.2.6 reload1.c
--- reload1.c 7 Jun 2003 05:30:09 -0000 1.366.2.6
+++ reload1.c 20 Nov 2003 10:24:40 -0000
@@ -1291,6 +1291,14 @@
by this, so unshare everything here. */
unshare_all_rtl_again (first);
+#ifdef STACK_BOUNDARY
+ /* init_emit has set the alignment of the hard frame pointer
+ to STACK_BOUNDARY. It is very likely no longer valid if
+ the hard frame pointer was used for register allocation. */
+ if (!frame_pointer_needed)
+ REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = BITS_PER_UNIT;
+#endif
+
return failure;
}
typedef unsigned char u_int8_t;
typedef signed char int8_t;
typedef unsigned short u_int16_t;
typedef signed short int16_t;
typedef unsigned int u_int32_t;
typedef signed int int32_t;
static __inline__ __attribute__((always_inline)) __const__ u_int16_t __fswab16(u_int16_t x)
{
__asm__("xchgb %b0,%h0"
: "=q" (x)
: "0" (x));
return x;
}
typedef struct my_snd_pcm_channel_area {
void *addr;
unsigned int first;
unsigned int step;
} my_snd_pcm_channel_area_t;
typedef struct my_snd_pcm_plugin_channel {
void *aptr;
my_snd_pcm_channel_area_t area;
unsigned int enabled:1;
unsigned int wanted:1;
} my_snd_pcm_plugin_channel_t;
typedef struct my_snd_pcm_plugin_format {
int format;
unsigned int rate;
unsigned int channels;
} my_snd_pcm_plugin_format_t;
struct my_snd_pcm_plugin {
my_snd_pcm_plugin_format_t src_format;
my_snd_pcm_plugin_format_t dst_format;
char extra_data[0];
};
typedef struct {
signed short last_S1;
signed short last_S2;
} rate_channel_t;
typedef struct rate_private_data {
unsigned int pitch;
unsigned int pos;
int get, put;
rate_channel_t channels[0];
} rate_t;
static void resample_expand(struct my_snd_pcm_plugin *plugin,
const my_snd_pcm_plugin_channel_t *src_channels,
my_snd_pcm_plugin_channel_t *dst_channels,
int src_frames, int dst_frames)
{
unsigned int pos = 0;
signed int val;
signed short S1, S2;
char *src, *dst;
unsigned int channel;
int src_step, dst_step;
int src_frames1, dst_frames1;
rate_t *data = (rate_t *)plugin->extra_data;
rate_channel_t *rchannels = data->channels;
static void *get_s16_labels[4 * 2 * 2] = {
&&get_s16_xxx1_xx10,
&&get_s16_xxx1_xx90,
&&get_s16_xxx1_xx10,
&&get_s16_xxx1_xx90,
&&get_s16_xx12_xx12,
&&get_s16_xx12_xx92,
&&get_s16_xx12_xx21,
&&get_s16_xx12_xxA1,
&&get_s16_x123_xx12,
&&get_s16_x123_xx92,
&&get_s16_123x_xx32,
&&get_s16_123x_xxB2,
&&get_s16_1234_xx12,
&&get_s16_1234_xx92,
&&get_s16_1234_xx43,
&&get_s16_1234_xxC3,
};
static void *put_s16_labels[4 * 2 * 2] = {
&&put_s16_xx12_xxx1,
&&put_s16_xx12_xxx9,
&&put_s16_xx12_xxx1,
&&put_s16_xx12_xxx9,
&&put_s16_xx12_xx12,
&&put_s16_xx12_xx92,
&&put_s16_xx12_xx21,
&&put_s16_xx12_xx29,
&&put_s16_xx12_x120,
&&put_s16_xx12_x920,
&&put_s16_xx12_021x,
&&put_s16_xx12_029x,
&&put_s16_xx12_1200,
&&put_s16_xx12_9200,
&&put_s16_xx12_0021,
&&put_s16_xx12_0029,
};
void *get = get_s16_labels[data->get];
void *put = put_s16_labels[data->put];
signed short sample = 0;
for (channel = 0; channel < plugin->src_format.channels; channel++) {
pos = data->pos;
S1 = rchannels->last_S1;
S2 = rchannels->last_S2;
if (!src_channels[channel].enabled) {
if (dst_channels[channel].wanted)
snd_pcm_area_silence(&dst_channels[channel].area, 0, dst_frames, plugin->dst_format.format);
dst_channels[channel].enabled = 0;
continue;
}
dst_channels[channel].enabled = 1;
src = (char *)src_channels[channel].area.addr + src_channels[channel].area.first / 8;
dst = (char *)dst_channels[channel].area.addr + dst_channels[channel].area.first / 8;
src_step = src_channels[channel].area.step / 8;
dst_step = dst_channels[channel].area.step / 8;
while (dst_frames1-- > 0) {
if (pos & ~((1<<11)-1)) {
if (src_frames1-- > 0) {
goto *get;
while(0) {
get_s16_xxx1_xx10: sample = (u_int16_t)(*(u_int8_t*)(src)) << 8; goto after_get;
get_s16_xxx1_xx90: sample = (u_int16_t)((*(u_int8_t*)(src)) ^ 0x80) << 8; goto after_get;
get_s16_xx12_xx12: sample = (*(u_int16_t*)(src)); goto after_get;
get_s16_xx12_xx92: goto after_get;
get_s16_xx12_xx21: goto after_get;
get_s16_xx12_xxA1: goto after_get;
get_s16_x123_xx12: sample = (*(u_int32_t*)(src)) >> 8; goto after_get;
get_s16_x123_xx92: sample = ((*(u_int32_t*)(src)) >> 8) ^ 0x8000; goto after_get;
get_s16_123x_xx32: sample = (*(u_int32_t*)(src)) >> 16; goto after_get;
get_s16_123x_xxB2: sample = (__builtin_constant_p((u_int16_t)(((*(u_int32_t*)(src)) >> 8) ^ 0x8000)) ? ({ u_int16_t __x = ((((*(u_int32_t*)(src)) >> 8) ^ 0x8000)); ((u_int16_t)( (((u_int16_t)(__x) & (u_int16_t)0x00ffU) << 8) | (((u_int16_t)(__x) & (u_int16_t)0xff00U) >> 8) )); }) : __fswab16((((*(u_int32_t*)(src)) >> 8) ^ 0x8000))); goto after_get;
get_s16_1234_xx12: sample = (*(u_int32_t*)(src)) >> 16; goto after_get;
get_s16_1234_xx92: sample = ((*(u_int32_t*)(src)) >> 16) ^ 0x8000; goto after_get;
get_s16_1234_xx43: goto after_get;
get_s16_1234_xxC3: goto after_get;
}
after_get:
S2 = sample;
src += src_step;
}
}
val = S1 + ((S2 - S1) * (signed int)pos) / (1<<11);
sample = val;
goto *put;
while (0) {
put_s16_xx12_xxx1: (*(u_int8_t*)(dst)) = sample >> 8; goto after_put;
put_s16_xx12_xxx9: (*(u_int8_t*)(dst)) = (sample >> 8) ^ 0x80; goto after_put;
put_s16_xx12_xx12: (*(u_int16_t*)(dst)) = sample; goto after_put;
put_s16_xx12_xx92: (*(u_int16_t*)(dst)) = sample ^ 0x8000; goto after_put;
put_s16_xx12_xx21: (*(u_int16_t*)(dst)) = (__builtin_constant_p((u_int16_t)(sample)) ? ({ u_int16_t __x = ((sample)); ((u_int16_t)( (((u_int16_t)(__x) & (u_int16_t)0x00ffU) << 8) | (((u_int16_t)(__x) & (u_int16_t)0xff00U) >> 8) )); }) : __fswab16((sample))); goto after_put;
put_s16_xx12_xx29: (*(u_int16_t*)(dst)) = (__builtin_constant_p((u_int16_t)(sample)) ? ({ u_int16_t __x = ((sample)); ((u_int16_t)( (((u_int16_t)(__x) & (u_int16_t)0x00ffU) << 8) | (((u_int16_t)(__x) & (u_int16_t)0xff00U) >> 8) )); }) : __fswab16((sample))) ^ 0x80; goto after_put;
put_s16_xx12_x120: (*(u_int32_t*)(dst)) = (u_int32_t)sample << 8; goto after_put;
put_s16_xx12_x920: (*(u_int32_t*)(dst)) = (u_int32_t)(sample ^ 0x8000) << 8; goto after_put;
put_s16_xx12_021x: (*(u_int32_t*)(dst)) = (u_int32_t)(__builtin_constant_p((u_int16_t)(sample)) ? ({ u_int16_t __x = ((sample)); ((u_int16_t)( (((u_int16_t)(__x) & (u_int16_t)0x00ffU) << 8) | (((u_int16_t)(__x) & (u_int16_t)0xff00U) >> 8) )); }) : __fswab16((sample))) << 8; goto after_put;
put_s16_xx12_029x: (*(u_int32_t*)(dst)) = (u_int32_t)((__builtin_constant_p((u_int16_t)(sample)) ? ({ u_int16_t __x = ((sample)); ((u_int16_t)( (((u_int16_t)(__x) & (u_int16_t)0x00ffU) << 8) | (((u_int16_t)(__x) & (u_int16_t)0xff00U) >> 8) )); }) : __fswab16((sample))) ^ 0x80) << 8; goto after_put;
put_s16_xx12_1200: (*(u_int32_t*)(dst)) = (u_int32_t)sample << 16; goto after_put;
put_s16_xx12_9200: (*(u_int32_t*)(dst)) = (u_int32_t)(sample ^ 0x8000) << 16; goto after_put;
put_s16_xx12_0021: (*(u_int32_t*)(dst)) = (u_int32_t)(__builtin_constant_p((u_int16_t)(sample)) ? ({ u_int16_t __x = ((sample)); ((u_int16_t)( (((u_int16_t)(__x) & (u_int16_t)0x00ffU) << 8) | (((u_int16_t)(__x) & (u_int16_t)0xff00U) >> 8) )); }) : __fswab16((sample))); goto after_put;
put_s16_xx12_0029: goto after_put;
}
after_put:
dst += dst_step;
pos += data->pitch;
}
rchannels->last_S1 = S1;
rchannels++;
}
data->pos = pos;
}