Breakage in flow with table jumps

Andrew Haley aph@cambridge.redhat.com
Wed Jun 20 11:05:00 GMT 2001


I've been trying to sort out a problem in ARM gcc, with a testcase
that looks like this:

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

When compiled with -fpic -O2, the compiler aborts in flow when trying
to merge a block that ends like this:

(jump_insn 52 51 53 (parallel[ 
            (set (pc)
                (if_then_else (leu (reg:SI 3 r3 [37])
                        (const_int 9 [0x9]))
                    (mem:SI (plus:SI (mult:SI (reg:SI 3 r3 [37])
                                (const_int 4 [0x4]))
                            (label_ref 53)) 0)
                    (label_ref 56)))
            (clobber (reg:CC 24 cc))
            (use (label_ref 53))
        ] ) 263 {casesi_internal} (insn_list 51 (nil))
    (nil))

and a table like this:

(jump_insn 54 15 55 (addr_diff_vec:SI (label_ref:SI 53)
        [ 
            (label_ref:SI 56)
            (label_ref:SI 56)
            (label_ref:SI 56)
            (label_ref:SI 56)
            (label_ref:SI 56)
            (label_ref:SI 56)
            (label_ref:SI 56)
            (label_ref:SI 56)
            (label_ref:SI 56)
            (label_ref:SI 56)
        ] 
        (const_int 0 [0x0])
        (const_int 0 [0x0])) -1 (nil)
    (nil))

with a block that begins like this:

(code_label 56 43 101 3 "" "" [11 uses])

The compiler quite properly notices that the basic blocks have only a
single edge; the jump table and the if-then-else in insn 52 all have
label 56 as their destination.  However, the merge fails when we get
to merge_blocks_move_predecessor_nojumps:

  barrier = next_nonnote_insn (end);
  if (GET_CODE (barrier) != BARRIER)
    abort ();

and the compiler aborts.

I could just replace 

  if (GET_CODE (barrier) != BARRIER)
    abort ();

with

  if (GET_CODE (barrier) != BARRIER)
    return 0;

which seems to work OK.

Thoughts?

Andrew.



More information about the Gcc-bugs mailing list