This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
invalid GET_MODE_WIDER_MODE assumption
- From: DJ Delorie <dj at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 27 May 2005 23:03:44 -0400
- Subject: invalid GET_MODE_WIDER_MODE assumption
expanding multiplies assume that the next wider mode happens to be the
twice-wider mode. This is an invalid assumption, which breaks if you
have partial_int, fractional_int, or even just odd-sized int modes.
This patch makes a separate table for the actual twice-wider modes,
just for the expanding multiply. We use this for an internal port,
I'll do regression testing if this patch is generally acceptable.
* genmodes.c (mode_data): Add wider_2x.
(calc_wider_mode): Calculate twice-wider mode too.
(emit_mode_wider): Emit twice-wider mode too.
* machmode.h (mode_2xwider, GET_MODE_2XWIDER_MODE): New.
* expr.c (expand_expr_real_1): Use it for expanding
multiplies.
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.790
diff -p -U3 -r1.790 expr.c
--- expr.c 17 May 2005 09:55:16 -0000 1.790
+++ expr.c 28 May 2005 02:32:42 -0000
@@ -7747,7 +7747,7 @@ expand_expr_real_1 (tree exp, rtx target
optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab;
this_optab = zextend_p ? umul_widen_optab : smul_widen_optab;
- if (mode == GET_MODE_WIDER_MODE (innermode))
+ if (mode == GET_MODE_2XWIDER_MODE (innermode))
{
if (this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
Index: genmodes.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/genmodes.c,v
retrieving revision 1.15
diff -p -U3 -r1.15 genmodes.c
--- genmodes.c 15 Oct 2004 14:47:07 -0000 1.15
+++ genmodes.c 28 May 2005 02:32:42 -0000
@@ -64,6 +64,7 @@ struct mode_data
struct mode_data *component; /* mode of components */
struct mode_data *wider; /* next wider mode */
+ struct mode_data *wider_2x; /* 2x wider mode */
struct mode_data *contained; /* Pointer to list of modes that have
this mode as a component. */
@@ -80,7 +81,7 @@ static struct mode_data *void_mode;
static const struct mode_data blank_mode = {
0, "<unknown>", MAX_MODE_CLASS,
-1U, -1U, -1U, -1U,
- 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
"<unknown>", 0
};
@@ -717,6 +718,7 @@ calc_wider_mode (void)
for (prev = 0, m = modes[c]; m; m = next)
{
m->wider = void_mode;
+ m->wider_2x = void_mode;
/* this is nreverse */
next = m->next;
@@ -951,6 +953,39 @@ emit_mode_wider (void)
m->name);
print_closer ();
+ print_decl ("unsigned char", "mode_2xwider", "NUM_MACHINE_MODES");
+
+ for_all_modes (c, m)
+ {
+ struct mode_data * m2;
+
+ for (m2 = m;
+ m2 && m2 != void_mode;
+ m2 = m2->wider)
+ {
+ if (m2->bytesize < 2 * m->bytesize)
+ continue;
+ if (m->precision != (unsigned int) -1)
+ {
+ if (m2->precision != 2 * m->precision)
+ continue;
+ }
+ else
+ {
+ if (m2->precision != (unsigned int) -1)
+ continue;
+ }
+
+ break;
+ }
+ if (m2 == void_mode)
+ m2 = 0;
+ tagged_printf ("%smode",
+ m2 ? m2->name : void_mode->name,
+ m->name);
+ }
+
+ print_closer ();
}
static void
Index: machmode.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/machmode.h,v
retrieving revision 1.38
diff -p -U3 -r1.38 machmode.h
--- machmode.h 6 Nov 2003 08:38:50 -0000 1.38
+++ machmode.h 28 May 2005 02:32:42 -0000
@@ -115,6 +115,9 @@ extern const unsigned char mode_nunits[N
extern const unsigned char mode_wider[NUM_MACHINE_MODES];
#define GET_MODE_WIDER_MODE(MODE) mode_wider[MODE]
+extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
+#define GET_MODE_2XWIDER_MODE(MODE) mode_2xwider[MODE]
+
/* Return the mode for data of a given size SIZE and mode class CLASS.
If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
The value is BLKmode if no other mode is found. */