This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
PR c/7102
- From: "Eric Botcazou" <ebotcazou at libertysurf dot fr>
- To: <gcc at gcc dot gnu dot org>
- Date: Thu, 4 Jul 2002 21:48:23 +0200
- Subject: PR c/7102
Hello,
I'm investigating PR c/7102 and I narrowed down the problem to the
lack of conversion of (const_int -1) from a QImode operand to a
HImode operand of an unsigned division in optabs.c:expand_binop().
Now about one year ago Alexandre Oliva commited the following patch:
2001-04-12 Alexandre Oliva <aoliva@redhat.com>
* expmed.c (store_bit_field): Truncate CONST_INTs.
(expand_mult_highpart, expand_divmod): Likewise.
* expr.c (convert_modes, store_field): Likewise.
* integrate.c (expand_inline_function): Use promote_mode() to
determine whether to convert_modes() an argument as signed
or unsigned.
* optabs.c (expand_binop): Get CONST_INT operands
sign-extended for their appropriate modes.
* stmt.c (emit_case_nodes): Convert node values to the
appropriate mode.
(expand_end_case): Convert minval and range to the appropriate
mode.
* unroll.c (loop_iterations): Truncate abs_diff to the mode of
the iteration variable.
* varasm.c (immed_double_const): Don't require words to be
narrower than host wide ints to properly sign-extend
CONST_INTs.
The diff for optabs.c reads:
--- gcc/optabs.c 28 Mar 2001 11:03:56 -0000 1.91
+++ gcc/optabs.c 12 Apr 2001 03:41:36 -0000 1.92
@@ -723,17 +723,25 @@
}
/* In case the insn wants input operands in modes different from
- the result, convert the operands. */
+ the result, convert the operands. It would seem that we
+ don't need to convert CONST_INTs, but we do, so that they're
+ a properly sign-extended for their modes. */
- if (GET_MODE (op0) != VOIDmode
- && GET_MODE (op0) != mode0
+ if (GET_MODE (op0) != mode0
&& mode0 != VOIDmode)
- xop0 = convert_to_mode (mode0, xop0, unsignedp);
+ xop0 = convert_modes (mode0,
+ GET_MODE (op0) != VOIDmode
+ ? GET_MODE (op0)
+ : mode0,
+ xop0, unsignedp);
- if (GET_MODE (xop1) != VOIDmode
- && GET_MODE (xop1) != mode1
+ if (GET_MODE (xop1) != mode1
&& mode1 != VOIDmode)
- xop1 = convert_to_mode (mode1, xop1, unsignedp);
+ xop1 = convert_modes (mode1,
+ GET_MODE (op1) != VOIDmode
+ ? GET_MODE (op1)
+ : mode1,
+ xop1, unsignedp);
It seems to me that, contrary to what the comment states, CONST_INTs
are still not converted because the patch is a no-op.
Later, Alexandre commited another patch:
2001-05-06 Alexandre Oliva <aoliva@redhat.com>
* optabs.c (expand_binop): Sign-extend xop0 and xop1 from the
widest mode in narrowing and widening operations.
--- gcc/optabs.c 14 Apr 2001 03:39:22 -0000 1.93
+++ gcc/optabs.c 6 May 2001 19:47:15 -0000 1.94
@@ -725,13 +725,20 @@
/* In case the insn wants input operands in modes different from
the result, convert the operands. It would seem that we
don't need to convert CONST_INTs, but we do, so that they're
- a properly sign-extended for their modes. */
+ a properly sign-extended for their modes; we choose the
+ widest mode between mode and mode[01], so that, in a widening
+ operation, we call convert_modes with different FROM and TO
+ modes, which ensures the value is sign-extended. Shift
+ operations are an exception, because the second operand needs
+ not be extended to the mode of the result. */
if (GET_MODE (op0) != mode0
&& mode0 != VOIDmode)
xop0 = convert_modes (mode0,
GET_MODE (op0) != VOIDmode
? GET_MODE (op0)
+ : GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode0)
+ ? mode
: mode0,
xop0, unsignedp);
@@ -740,6 +747,9 @@
xop1 = convert_modes (mode1,
GET_MODE (op1) != VOIDmode
? GET_MODE (op1)
+ : (GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode1)
+ && ! shift_op)
+ ? mode
: mode1,
xop1, unsignedp);
It seems that Alexandre noticed the problem, but the fix enables truncation
only, neither zero- nor sign-extension. Hence my question: is there anything
that forbids full conversion of the operands in that situation ?
--
Eric Botcazou
ebotcazou@multimania.com