This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: ARM internal compiler error
- To: gcc-patches at gcc dot gnu dot org
- Subject: PATCH: ARM internal compiler error
- From: Andrew Haley <aph at cambridge dot redhat dot com>
- Date: Thu, 21 Jun 2001 19:24:39 +0100 (BST)
This is a patch for a case where ARM gcc ICEs when a casesi insn has
every label_ref -- even the default -- pointing to the same label.
flow tries to merge two blocks and aborts, complaining that it can't
find a barrier immediately following the last insn in the first basic
block. This isn't surprising as the next real insn is the jump table
for the casesi.
I don't think there's any good reason why flow should abort in this
case: the RTL is correct (if suboptimal) so it makes sense to return 0
at this point and continue rather than abort.
Strictly speaking, only the first part of this patch is a bug fix.
In the interests of efficiency, I also added code to detect the
particular form of casesi used by ARM and convert it to a simple
jump_insn. If we don't do this the code is quite horrible.
I've appended the testcase. It needs to be run on ARM with -O2 -fpic
to demonstrate the failure. I'll check it in to c-torture as "compile
only" if y'all want me to.
Andrew.
2001-06-21 Andrew Haley <aph@cambridge.redhat.com>
* jump.c (jump_optimize_1): Detect a form of casesi and convert it
into a simple jump.
* flow.c (merge_blocks_move_predecessor_nojumps): Don't abort if
we fail to find a barrier.
Index: flow.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flow.c,v
retrieving revision 1.400
diff -c -2 -p -r1.400 flow.c
*** flow.c 2001/06/19 15:03:01 1.400
--- flow.c 2001/06/21 17:27:55
*************** merge_blocks_move_predecessor_nojumps (a
*** 2476,2481 ****
barrier = next_nonnote_insn (end);
if (GET_CODE (barrier) != BARRIER)
! abort ();
flow_delete_insn (barrier);
--- 2476,2485 ----
barrier = next_nonnote_insn (end);
+ /* Don't abort if we fail to find a barrier.
+ Maybe the jump that got us here wasn't a simple jump_insn but
+ something more complex such as a casesi too complex to have been
+ converted by jump optimization. */
if (GET_CODE (barrier) != BARRIER)
! return 0;
flow_delete_insn (barrier);
Index: jump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/jump.c,v
retrieving revision 1.178
diff -c -2 -p -r1.178 jump.c
*** jump.c 2001/06/11 13:49:24 1.178
--- jump.c 2001/06/21 17:27:56
*************** jump_optimize_1 (f, cross_jump, noop_mov
*** 322,329 ****
rtx dispatch = prev_real_insn (insn);
rtx set;
! for (i = 0; i < len; i++)
! if (XEXP (XVECEXP (pat, diff_vec_p, i), 0)
! != XEXP (XVECEXP (pat, diff_vec_p, 0), 0))
break;
--- 322,329 ----
rtx dispatch = prev_real_insn (insn);
rtx set;
+ rtx label0 = XEXP (XVECEXP (pat, diff_vec_p, 0), 0);
! for (i = 1; i < len; i++)
! if (XEXP (XVECEXP (pat, diff_vec_p, i), 0) != label0)
break;
*************** jump_optimize_1 (f, cross_jump, noop_mov
*** 332,346 ****
&& GET_CODE (dispatch) == JUMP_INSN
&& JUMP_LABEL (dispatch) != 0
! /* Don't mess with a casesi insn.
! XXX according to the comment before computed_jump_p(),
all casesi insns should be a parallel of the jump
and a USE of a LABEL_REF. */
- && ! ((set = single_set (dispatch)) != NULL
- && (GET_CODE (SET_SRC (set)) == IF_THEN_ELSE))
&& next_real_insn (JUMP_LABEL (dispatch)) == insn)
{
! redirect_tablejump (dispatch,
! XEXP (XVECEXP (pat, diff_vec_p, 0), 0));
! changed = 1;
}
}
--- 332,363 ----
&& GET_CODE (dispatch) == JUMP_INSN
&& JUMP_LABEL (dispatch) != 0
! /* XXX according to the comment before computed_jump_p(),
all casesi insns should be a parallel of the jump
and a USE of a LABEL_REF. */
&& next_real_insn (JUMP_LABEL (dispatch)) == insn)
{
! if ((set = single_set (dispatch)) != NULL
! && (GET_CODE (SET_SRC (set)) == IF_THEN_ELSE))
! {
! /* casesi insn. Detect
! (set (pc)
! (if_then_else (cond)
! (expr) (label_ref nn)))
! and fix this up if the label_ref is the same as
! all the case labels. */
! rtx elsepart = (XEXP (SET_SRC (set), 2));
! if (SET_DEST (set) == pc_rtx
! && GET_CODE (elsepart) == LABEL_REF
! && (XEXP (elsepart, 0) == label0))
! {
! redirect_tablejump (dispatch, label0);
! changed = 1;
! }
! }
! else /* tablejump insn. */
! {
! redirect_tablejump (dispatch, label0);
! changed = 1;
! }
}
}
int SQLSetConnectOption( void * hDrvDbc,
unsigned nOption,
unsigned long vParam)
{
if ( hDrvDbc == 0 )
return (-2);
switch ( nOption )
{
case 106:
case 107:
case 110:
case 104:
switch ( vParam )
{
case 1UL:
case 0UL:
default:
;
}
break;
case 105:
case 101:
case 102:
default:
;
}
printf( "SQLSetConnectOption.c", "SQLSetConnectOption.c", 49, 1, 1, "SQL_SUCCESS_WITH_INFO Function not fully implemented" );
return 1;
}