This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

PATCH: ARM internal compiler error


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;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]