This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [testcase] 3.{1,1.1,2} ICE on IA-32
- From: Richard Henderson <rth at redhat dot com>
- To: Jakub Jelinek <jakub at redhat dot com>
- Cc: m dot hayes at elec dot canterbury dot ac dot nz, gcc-patches at gcc dot gnu dot org
- Date: Thu, 1 Aug 2002 15:30:33 -0700
- Subject: Re: [testcase] 3.{1,1.1,2} ICE on IA-32
- References: <20020729190152.G20867@sunsite.ms.mff.cuni.cz>
On Mon, Jul 29, 2002 at 07:01:52PM +0200, Jakub Jelinek wrote:
> Should the fix be some force_reg like function for loop which would try to
> recog the instruction and if it would not recognize it, would go
> inside PLUS, MULT or ASHIFT, maybe others, and first do force_reg on the
> argument, then on the whole pattern with the arguments replaced by the
> registers (and should it add REG_EQUIV in that case or not)?
Something like that. Merging the following two changes should do the job.
I've not tested this except on your test case. Approved for
3.2.1 once the branch is open and this is properly tested.
r~
2002-05-17 Richard Sandiford <rsandifo@redhat.com>
* expr.c (force_operand): Fix reversed move.
Sat May 4 13:20:54 CEST 2002 Jan Hubicka <jh@suse.cz>
* expr.c (force_operand): Use expand_simple_* to handle more
cases.
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.423.2.19
diff -c -p -d -r1.423.2.19 expr.c
*** expr.c 7 May 2002 05:43:11 -0000 1.423.2.19
--- expr.c 1 Aug 2002 22:26:22 -0000
*************** rtx
*** 5434,5449 ****
force_operand (value, target)
rtx value, target;
{
! optab binoptab = 0;
! /* Use a temporary to force order of execution of calls to
! `force_operand'. */
! rtx tmp;
! rtx op2;
/* Use subtarget as the target for operand 0 of a binary operation. */
rtx subtarget = get_subtarget (target);
/* Check for a PIC address load. */
! if ((GET_CODE (value) == PLUS || GET_CODE (value) == MINUS)
&& XEXP (value, 0) == pic_offset_table_rtx
&& (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
|| GET_CODE (XEXP (value, 1)) == LABEL_REF
--- 5434,5446 ----
force_operand (value, target)
rtx value, target;
{
! rtx op1, op2;
/* Use subtarget as the target for operand 0 of a binary operation. */
rtx subtarget = get_subtarget (target);
+ enum rtx_code code = GET_CODE (value);
/* Check for a PIC address load. */
! if ((code == PLUS || code == MINUS)
&& XEXP (value, 0) == pic_offset_table_rtx
&& (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
|| GET_CODE (XEXP (value, 1)) == LABEL_REF
*************** force_operand (value, target)
*** 5455,5514 ****
return subtarget;
}
! if (GET_CODE (value) == PLUS)
! binoptab = add_optab;
! else if (GET_CODE (value) == MINUS)
! binoptab = sub_optab;
! else if (GET_CODE (value) == MULT)
{
! op2 = XEXP (value, 1);
! if (!CONSTANT_P (op2)
! && !(GET_CODE (op2) == REG && op2 != subtarget))
! subtarget = 0;
! tmp = force_operand (XEXP (value, 0), subtarget);
! return expand_mult (GET_MODE (value), tmp,
! force_operand (op2, NULL_RTX),
! target, 1);
}
! if (binoptab)
{
op2 = XEXP (value, 1);
! if (!CONSTANT_P (op2)
! && !(GET_CODE (op2) == REG && op2 != subtarget))
subtarget = 0;
! if (binoptab == sub_optab && GET_CODE (op2) == CONST_INT)
{
! binoptab = add_optab;
op2 = negate_rtx (GET_MODE (value), op2);
}
/* Check for an addition with OP2 a constant integer and our first
! operand a PLUS of a virtual register and something else. In that
! case, we want to emit the sum of the virtual register and the
! constant first and then add the other value. This allows virtual
! register instantiation to simply modify the constant rather than
! creating another one around this addition. */
! if (binoptab == add_optab && GET_CODE (op2) == CONST_INT
&& GET_CODE (XEXP (value, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
&& REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
&& REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
{
! rtx temp = expand_binop (GET_MODE (value), binoptab,
! XEXP (XEXP (value, 0), 0), op2,
! subtarget, 0, OPTAB_LIB_WIDEN);
! return expand_binop (GET_MODE (value), binoptab, temp,
! force_operand (XEXP (XEXP (value, 0), 1), 0),
! target, 0, OPTAB_LIB_WIDEN);
}
! tmp = force_operand (XEXP (value, 0), subtarget);
! return expand_binop (GET_MODE (value), binoptab, tmp,
! force_operand (op2, NULL_RTX),
! target, 0, OPTAB_LIB_WIDEN);
! /* We give UNSIGNEDP = 0 to expand_binop
! because the only operations we are expanding here are signed ones. */
}
#ifdef INSN_SCHEDULING
--- 5452,5539 ----
return subtarget;
}
! if (code == ZERO_EXTEND || code == SIGN_EXTEND)
{
! if (!target)
! target = gen_reg_rtx (GET_MODE (value));
! convert_move (target, force_operand (XEXP (value, 0), NULL),
! code == ZERO_EXTEND);
! return target;
}
! if (GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c')
{
op2 = XEXP (value, 1);
! if (!CONSTANT_P (op2) && !(GET_CODE (op2) == REG && op2 != subtarget))
subtarget = 0;
! if (code == MINUS && GET_CODE (op2) == CONST_INT)
{
! code = PLUS;
op2 = negate_rtx (GET_MODE (value), op2);
}
/* Check for an addition with OP2 a constant integer and our first
! operand a PLUS of a virtual register and something else. In that
! case, we want to emit the sum of the virtual register and the
! constant first and then add the other value. This allows virtual
! register instantiation to simply modify the constant rather than
! creating another one around this addition. */
! if (code == PLUS && GET_CODE (op2) == CONST_INT
&& GET_CODE (XEXP (value, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
&& REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
&& REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
{
! rtx temp = expand_simple_binop (GET_MODE (value), code,
! XEXP (XEXP (value, 0), 0), op2,
! subtarget, 0, OPTAB_LIB_WIDEN);
! return expand_simple_binop (GET_MODE (value), code, temp,
! force_operand (XEXP (XEXP (value,
! 0), 1), 0),
! target, 0, OPTAB_LIB_WIDEN);
}
! op1 = force_operand (XEXP (value, 0), subtarget);
! op2 = force_operand (op2, NULL_RTX);
! switch (code)
! {
! case MULT:
! return expand_mult (GET_MODE (value), op1, op2, target, 1);
! case DIV:
! if (!INTEGRAL_MODE_P (GET_MODE (value)))
! return expand_simple_binop (GET_MODE (value), code, op1, op2,
! target, 1, OPTAB_LIB_WIDEN);
! else
! return expand_divmod (0,
! FLOAT_MODE_P (GET_MODE (value))
! ? RDIV_EXPR : TRUNC_DIV_EXPR,
! GET_MODE (value), op1, op2, target, 0);
! break;
! case MOD:
! return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
! target, 0);
! break;
! case UDIV:
! return expand_divmod (0, TRUNC_DIV_EXPR, GET_MODE (value), op1, op2,
! target, 1);
! break;
! case UMOD:
! return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
! target, 1);
! break;
! case ASHIFTRT:
! return expand_simple_binop (GET_MODE (value), code, op1, op2,
! target, 0, OPTAB_LIB_WIDEN);
! break;
! default:
! return expand_simple_binop (GET_MODE (value), code, op1, op2,
! target, 1, OPTAB_LIB_WIDEN);
! }
! }
! if (GET_RTX_CLASS (code) == '1')
! {
! op1 = force_operand (XEXP (value, 0), NULL_RTX);
! return expand_simple_unop (GET_MODE (value), code, op1, target, 0);
}
#ifdef INSN_SCHEDULING