示例#1
0
文件: rtl.c 项目: keparo/gcc
int
rtx_equal_p (const_rtx x, const_rtx y)
{
  int i;
  int j;
  enum rtx_code code;
  const char *fmt;

  if (x == y)
    return 1;
  if (x == 0 || y == 0)
    return 0;

  code = GET_CODE (x);
  /* Rtx's of different codes cannot be equal.  */
  if (code != GET_CODE (y))
    return 0;

  /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
     (REG:SI x) and (REG:HI x) are NOT equivalent.  */

  if (GET_MODE (x) != GET_MODE (y))
    return 0;

  /* MEMs referring to different address space are not equivalent.  */
  if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
    return 0;

  /* Some RTL can be compared nonrecursively.  */
  switch (code)
    {
    case REG:
      return (REGNO (x) == REGNO (y));

    case LABEL_REF:
      return XEXP (x, 0) == XEXP (y, 0);

    case SYMBOL_REF:
      return XSTR (x, 0) == XSTR (y, 0);

    case DEBUG_EXPR:
    case VALUE:
    case SCRATCH:
    case CONST_DOUBLE:
    case CONST_INT:
    case CONST_FIXED:
      return 0;

    case DEBUG_IMPLICIT_PTR:
      return DEBUG_IMPLICIT_PTR_DECL (x)
	     == DEBUG_IMPLICIT_PTR_DECL (y);

    case DEBUG_PARAMETER_REF:
      return DEBUG_PARAMETER_REF_DECL (x)
	     == DEBUG_PARAMETER_REF_DECL (y);

    case ENTRY_VALUE:
      return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y));

    default:
      break;
    }

  /* Compare the elements.  If any pair of corresponding elements
     fail to match, return 0 for the whole thing.  */

  fmt = GET_RTX_FORMAT (code);
  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
    {
      switch (fmt[i])
	{
	case 'w':
	  if (XWINT (x, i) != XWINT (y, i))
	    return 0;
	  break;

	case 'n':
	case 'i':
	  if (XINT (x, i) != XINT (y, i))
	    {
#ifndef GENERATOR_FILE
	      if (((code == ASM_OPERANDS && i == 6)
		   || (code == ASM_INPUT && i == 1))
		  && locator_eq (XINT (x, i), XINT (y, i)))
		break;
#endif
	      return 0;
	    }
	  break;

	case 'V':
	case 'E':
	  /* Two vectors must have the same length.  */
	  if (XVECLEN (x, i) != XVECLEN (y, i))
	    return 0;

	  /* And the corresponding elements must match.  */
	  for (j = 0; j < XVECLEN (x, i); j++)
	    if (rtx_equal_p (XVECEXP (x, i, j),  XVECEXP (y, i, j)) == 0)
	      return 0;
	  break;

	case 'e':
	  if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0)
	    return 0;
	  break;

	case 'S':
	case 's':
	  if ((XSTR (x, i) || XSTR (y, i))
	      && (! XSTR (x, i) || ! XSTR (y, i)
		  || strcmp (XSTR (x, i), XSTR (y, i))))
	    return 0;
	  break;

	case 'u':
	  /* These are just backpointers, so they don't matter.  */
	  break;

	case '0':
	case 't':
	  break;

	  /* It is believed that rtx's at this level will never
	     contain anything but integers and other rtx's,
	     except for within LABEL_REFs and SYMBOL_REFs.  */
	default:
	  gcc_unreachable ();
	}
    }
  return 1;
}
示例#2
0
文件: print-rtl.c 项目: hnaik/gcc
static void
print_rtx (const_rtx in_rtx)
{
  int i = 0;
  int j;
  const char *format_ptr;
  int is_insn;

  if (sawclose)
    {
      if (flag_simple)
	fputc (' ', outfile);
      else
	fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, "");
      sawclose = 0;
    }

  if (in_rtx == 0)
    {
      fputs ("(nil)", outfile);
      sawclose = 1;
      return;
    }
  else if (GET_CODE (in_rtx) > NUM_RTX_CODE)
    {
       fprintf (outfile, "(??? bad code %d\n%s%*s)", GET_CODE (in_rtx),
		print_rtx_head, indent * 2, "");
       sawclose = 1;
       return;
    }

  is_insn = INSN_P (in_rtx);

  /* Print name of expression code.  */
  if (flag_simple && CONST_INT_P (in_rtx))
    fputc ('(', outfile);
  else
    fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));

  if (! flag_simple)
    {
      if (RTX_FLAG (in_rtx, in_struct))
	fputs ("/s", outfile);

      if (RTX_FLAG (in_rtx, volatil))
	fputs ("/v", outfile);

      if (RTX_FLAG (in_rtx, unchanging))
	fputs ("/u", outfile);

      if (RTX_FLAG (in_rtx, frame_related))
	fputs ("/f", outfile);

      if (RTX_FLAG (in_rtx, jump))
	fputs ("/j", outfile);

      if (RTX_FLAG (in_rtx, call))
	fputs ("/c", outfile);

      if (RTX_FLAG (in_rtx, return_val))
	fputs ("/i", outfile);

      /* Print REG_NOTE names for EXPR_LIST and INSN_LIST.  */
      if ((GET_CODE (in_rtx) == EXPR_LIST
	   || GET_CODE (in_rtx) == INSN_LIST
	   || GET_CODE (in_rtx) == INT_LIST)
	  && (int)GET_MODE (in_rtx) < REG_NOTE_MAX)
	fprintf (outfile, ":%s",
		 GET_REG_NOTE_NAME (GET_MODE (in_rtx)));

      /* For other rtl, print the mode if it's not VOID.  */
      else if (GET_MODE (in_rtx) != VOIDmode)
	fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));

#ifndef GENERATOR_FILE
      if (GET_CODE (in_rtx) == VAR_LOCATION)
	{
	  if (TREE_CODE (PAT_VAR_LOCATION_DECL (in_rtx)) == STRING_CST)
	    fputs (" <debug string placeholder>", outfile);
	  else
	    print_mem_expr (outfile, PAT_VAR_LOCATION_DECL (in_rtx));
	  fputc (' ', outfile);
	  print_rtx (PAT_VAR_LOCATION_LOC (in_rtx));
	  if (PAT_VAR_LOCATION_STATUS (in_rtx)
	      == VAR_INIT_STATUS_UNINITIALIZED)
	    fprintf (outfile, " [uninit]");
	  sawclose = 1;
	  i = GET_RTX_LENGTH (VAR_LOCATION);
	}
#endif
    }

#ifndef GENERATOR_FILE
  if (CONST_DOUBLE_AS_FLOAT_P (in_rtx))
    i = 5;
#endif

  /* Get the format string and skip the first elements if we have handled
     them already.  */
  format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i;
  for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
    switch (*format_ptr++)
      {
	const char *str;

      case 'T':
	str = XTMPL (in_rtx, i);
	goto string;

      case 'S':
      case 's':
	str = XSTR (in_rtx, i);
      string:

	if (str == 0)
	  fputs (" \"\"", outfile);
	else
	  fprintf (outfile, " (\"%s\")", str);
	sawclose = 1;
	break;

	/* 0 indicates a field for internal use that should not be printed.
	   An exception is the third field of a NOTE, where it indicates
	   that the field has several different valid contents.  */
      case '0':
	if (i == 1 && REG_P (in_rtx))
	  {
	    if (REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx))
	      fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
	  }
#ifndef GENERATOR_FILE
	else if (i == 1 && GET_CODE (in_rtx) == SYMBOL_REF)
	  {
	    int flags = SYMBOL_REF_FLAGS (in_rtx);
	    if (flags)
	      fprintf (outfile, " [flags %#x]", flags);
	  }
	else if (i == 2 && GET_CODE (in_rtx) == SYMBOL_REF)
	  {
	    tree decl = SYMBOL_REF_DECL (in_rtx);
	    if (decl)
	      print_node_brief (outfile, "", decl, dump_flags);
	  }
#endif
	else if (i == 4 && NOTE_P (in_rtx))
	  {
	    switch (NOTE_KIND (in_rtx))
	      {
	      case NOTE_INSN_EH_REGION_BEG:
	      case NOTE_INSN_EH_REGION_END:
		if (flag_dump_unnumbered)
		  fprintf (outfile, " #");
		else
		  fprintf (outfile, " %d", NOTE_EH_HANDLER (in_rtx));
		sawclose = 1;
		break;

	      case NOTE_INSN_BLOCK_BEG:
	      case NOTE_INSN_BLOCK_END:
#ifndef GENERATOR_FILE
		dump_addr (outfile, " ", NOTE_BLOCK (in_rtx));
#endif
		sawclose = 1;
		break;

	      case NOTE_INSN_BASIC_BLOCK:
		{
#ifndef GENERATOR_FILE
		  basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
		  if (bb != 0)
		    fprintf (outfile, " [bb %d]", bb->index);
#endif
		  break;
	        }

	      case NOTE_INSN_DELETED_LABEL:
	      case NOTE_INSN_DELETED_DEBUG_LABEL:
		{
		  const char *label = NOTE_DELETED_LABEL_NAME (in_rtx);
		  if (label)
		    fprintf (outfile, " (\"%s\")", label);
		  else
		    fprintf (outfile, " \"\"");
		}
		break;

	      case NOTE_INSN_SWITCH_TEXT_SECTIONS:
		{
#ifndef GENERATOR_FILE
		  basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
		  if (bb != 0)
		    fprintf (outfile, " [bb %d]", bb->index);
#endif
		  break;
		}

	      case NOTE_INSN_VAR_LOCATION:
	      case NOTE_INSN_CALL_ARG_LOCATION:
#ifndef GENERATOR_FILE
		fputc (' ', outfile);
		print_rtx (NOTE_VAR_LOCATION (in_rtx));
#endif
		break;

	      case NOTE_INSN_CFI:
#ifndef GENERATOR_FILE
		fputc ('\n', outfile);
		output_cfi_directive (outfile, NOTE_CFI (in_rtx));
		fputc ('\t', outfile);
#endif
		break;

	      default:
		break;
	      }
	  }
	else if (i == 8 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL)
	  {
	    /* Output the JUMP_LABEL reference.  */
	    fprintf (outfile, "\n%s%*s -> ", print_rtx_head, indent * 2, "");
	    if (GET_CODE (JUMP_LABEL (in_rtx)) == RETURN)
	      fprintf (outfile, "return");
	    else if (GET_CODE (JUMP_LABEL (in_rtx)) == SIMPLE_RETURN)
	      fprintf (outfile, "simple_return");
	    else
	      fprintf (outfile, "%d", INSN_UID (JUMP_LABEL (in_rtx)));
	  }
	else if (i == 0 && GET_CODE (in_rtx) == VALUE)
	  {
#ifndef GENERATOR_FILE
	    cselib_val *val = CSELIB_VAL_PTR (in_rtx);

	    fprintf (outfile, " %u:%u", val->uid, val->hash);
	    dump_addr (outfile, " @", in_rtx);
	    dump_addr (outfile, "/", (void*)val);
#endif
	  }
	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
	  {
#ifndef GENERATOR_FILE
	    fprintf (outfile, " D#%i",
		     DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (in_rtx)));
#endif
	  }
	else if (i == 0 && GET_CODE (in_rtx) == ENTRY_VALUE)
	  {
	    indent += 2;
	    if (!sawclose)
	      fprintf (outfile, " ");
	    print_rtx (ENTRY_VALUE_EXP (in_rtx));
	    indent -= 2;
	  }
	break;

      case 'e':
      do_e:
	indent += 2;
	if (i == 7 && INSN_P (in_rtx))
	  /* Put REG_NOTES on their own line.  */
	  fprintf (outfile, "\n%s%*s",
		   print_rtx_head, indent * 2, "");
	if (!sawclose)
	  fprintf (outfile, " ");
	print_rtx (XEXP (in_rtx, i));
	indent -= 2;
	break;

      case 'E':
      case 'V':
	indent += 2;
	if (sawclose)
	  {
	    fprintf (outfile, "\n%s%*s",
		     print_rtx_head, indent * 2, "");
	    sawclose = 0;
	  }
	fputs (" [", outfile);
	if (NULL != XVEC (in_rtx, i))
	  {
	    indent += 2;
	    if (XVECLEN (in_rtx, i))
	      sawclose = 1;

	    for (j = 0; j < XVECLEN (in_rtx, i); j++)
	      print_rtx (XVECEXP (in_rtx, i, j));

	    indent -= 2;
	  }
	if (sawclose)
	  fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, "");

	fputs ("]", outfile);
	sawclose = 1;
	indent -= 2;
	break;

      case 'w':
	if (! flag_simple)
	  fprintf (outfile, " ");
	fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i));
	if (! flag_simple)
	  fprintf (outfile, " [" HOST_WIDE_INT_PRINT_HEX "]",
		   (unsigned HOST_WIDE_INT) XWINT (in_rtx, i));
	break;

      case 'i':
	if (i == 5 && INSN_P (in_rtx))
	  {
#ifndef GENERATOR_FILE
	    /*  Pretty-print insn locations.  Ignore scoping as it is mostly
		redundant with line number information and do not print anything
		when there is no location information available.  */
	    if (INSN_LOCATION (in_rtx) && insn_file (in_rtx))
	      fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
#endif
	  }
	else if (i == 6 && GET_CODE (in_rtx) == ASM_OPERANDS)
	  {
#ifndef GENERATOR_FILE
	    fprintf (outfile, " %s:%i",
		     LOCATION_FILE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)),
		     LOCATION_LINE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)));
#endif
	  }
	else if (i == 1 && GET_CODE (in_rtx) == ASM_INPUT)
	  {
#ifndef GENERATOR_FILE
	    fprintf (outfile, " %s:%i",
		     LOCATION_FILE (ASM_INPUT_SOURCE_LOCATION (in_rtx)),
		     LOCATION_LINE (ASM_INPUT_SOURCE_LOCATION (in_rtx)));
#endif
	  }
	else if (i == 6 && NOTE_P (in_rtx))
	  {
	    /* This field is only used for NOTE_INSN_DELETED_LABEL, and
	       other times often contains garbage from INSN->NOTE death.  */
	    if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL
		|| NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_DEBUG_LABEL)
	      fprintf (outfile, " %d",  XINT (in_rtx, i));
	  }
#if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0
	else if (i == 1
		 && GET_CODE (in_rtx) == UNSPEC_VOLATILE
		 && XINT (in_rtx, 1) >= 0
		 && XINT (in_rtx, 1) < NUM_UNSPECV_VALUES)
	  fprintf (outfile, " %s", unspecv_strings[XINT (in_rtx, 1)]);
#endif
#if !defined(GENERATOR_FILE) && NUM_UNSPEC_VALUES > 0
	else if (i == 1
		 && (GET_CODE (in_rtx) == UNSPEC
		     || GET_CODE (in_rtx) == UNSPEC_VOLATILE)
		 && XINT (in_rtx, 1) >= 0
		 && XINT (in_rtx, 1) < NUM_UNSPEC_VALUES)
	  fprintf (outfile, " %s", unspec_strings[XINT (in_rtx, 1)]);
#endif
	else
	  {
	    int value = XINT (in_rtx, i);
	    const char *name;

#ifndef GENERATOR_FILE
	    if (REG_P (in_rtx) && (unsigned) value < FIRST_PSEUDO_REGISTER)
	      fprintf (outfile, " %d %s", value, reg_names[value]);
	    else if (REG_P (in_rtx)
		     && (unsigned) value <= LAST_VIRTUAL_REGISTER)
	      {
		if (value == VIRTUAL_INCOMING_ARGS_REGNUM)
		  fprintf (outfile, " %d virtual-incoming-args", value);
		else if (value == VIRTUAL_STACK_VARS_REGNUM)
		  fprintf (outfile, " %d virtual-stack-vars", value);
		else if (value == VIRTUAL_STACK_DYNAMIC_REGNUM)
		  fprintf (outfile, " %d virtual-stack-dynamic", value);
		else if (value == VIRTUAL_OUTGOING_ARGS_REGNUM)
		  fprintf (outfile, " %d virtual-outgoing-args", value);
		else if (value == VIRTUAL_CFA_REGNUM)
		  fprintf (outfile, " %d virtual-cfa", value);
		else if (value == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM)
		  fprintf (outfile, " %d virtual-preferred-stack-boundary",
			   value);
		else
		  fprintf (outfile, " %d virtual-reg-%d", value,
			   value-FIRST_VIRTUAL_REGISTER);
	      }
	    else
#endif
	      if (flag_dump_unnumbered
		     && (is_insn || NOTE_P (in_rtx)))
	      fputc ('#', outfile);
	    else
	      fprintf (outfile, " %d", value);

#ifndef GENERATOR_FILE
	    if (REG_P (in_rtx) && REG_ATTRS (in_rtx))
	      {
		fputs (" [", outfile);
		if (ORIGINAL_REGNO (in_rtx) != REGNO (in_rtx))
		  fprintf (outfile, "orig:%i", ORIGINAL_REGNO (in_rtx));
		if (REG_EXPR (in_rtx))
		  print_mem_expr (outfile, REG_EXPR (in_rtx));

		if (REG_OFFSET (in_rtx))
		  fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
			   REG_OFFSET (in_rtx));
		fputs (" ]", outfile);
	      }
#endif

	    if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i)
		&& XINT (in_rtx, i) >= 0
		&& (name = get_insn_name (XINT (in_rtx, i))) != NULL)
	      fprintf (outfile, " {%s}", name);
	    sawclose = 0;
	  }
	break;

      /* Print NOTE_INSN names rather than integer codes.  */

      case 'n':
	fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i)));
	sawclose = 0;
	break;

      case 'u':
	if (XEXP (in_rtx, i) != NULL)
	  {
	    rtx sub = XEXP (in_rtx, i);
	    enum rtx_code subc = GET_CODE (sub);

	    if (GET_CODE (in_rtx) == LABEL_REF)
	      {
		if (subc == NOTE
		    && NOTE_KIND (sub) == NOTE_INSN_DELETED_LABEL)
		  {
		    if (flag_dump_unnumbered)
		      fprintf (outfile, " [# deleted]");
		    else
		      fprintf (outfile, " [%d deleted]", INSN_UID (sub));
		    sawclose = 0;
		    break;
		  }

		if (subc != CODE_LABEL)
		  goto do_e;
	      }

	    if (flag_dump_unnumbered
		|| (flag_dump_unnumbered_links && (i == 1 || i == 2)
		    && (INSN_P (in_rtx) || NOTE_P (in_rtx)
			|| LABEL_P (in_rtx) || BARRIER_P (in_rtx))))
	      fputs (" #", outfile);
	    else
	      fprintf (outfile, " %d", INSN_UID (sub));
	  }
	else
	  fputs (" 0", outfile);
	sawclose = 0;
	break;

      case 't':
#ifndef GENERATOR_FILE
	if (i == 0 && GET_CODE (in_rtx) == DEBUG_IMPLICIT_PTR)
	  print_mem_expr (outfile, DEBUG_IMPLICIT_PTR_DECL (in_rtx));
	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_PARAMETER_REF)
	  print_mem_expr (outfile, DEBUG_PARAMETER_REF_DECL (in_rtx));
	else
	  dump_addr (outfile, " ", XTREE (in_rtx, i));
#endif
	break;

      case '*':
	fputs (" Unknown", outfile);
	sawclose = 0;
	break;

      case 'B':
#ifndef GENERATOR_FILE
	if (XBBDEF (in_rtx, i))
	  fprintf (outfile, " %i", XBBDEF (in_rtx, i)->index);
#endif
	break;

      default:
	gcc_unreachable ();
      }

  switch (GET_CODE (in_rtx))
    {
#ifndef GENERATOR_FILE
    case MEM:
      if (__builtin_expect (final_insns_dump_p, false))
	fprintf (outfile, " [");
      else
	fprintf (outfile, " [" HOST_WIDE_INT_PRINT_DEC,
		 (HOST_WIDE_INT) MEM_ALIAS_SET (in_rtx));

      if (MEM_EXPR (in_rtx))
	print_mem_expr (outfile, MEM_EXPR (in_rtx));

      if (MEM_OFFSET_KNOWN_P (in_rtx))
	fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, MEM_OFFSET (in_rtx));

      if (MEM_SIZE_KNOWN_P (in_rtx))
	fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, MEM_SIZE (in_rtx));

      if (MEM_ALIGN (in_rtx) != 1)
	fprintf (outfile, " A%u", MEM_ALIGN (in_rtx));

      if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (in_rtx)))
	fprintf (outfile, " AS%u", MEM_ADDR_SPACE (in_rtx));

      fputc (']', outfile);
      break;

    case CONST_DOUBLE:
      if (FLOAT_MODE_P (GET_MODE (in_rtx)))
	{
	  char s[60];

	  real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
			   sizeof (s), 0, 1);
	  fprintf (outfile, " %s", s);

	  real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
			       sizeof (s), 0, 1);
	  fprintf (outfile, " [%s]", s);
	}
      break;
#endif

    case CODE_LABEL:
      fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx));
      switch (LABEL_KIND (in_rtx))
	{
	  case LABEL_NORMAL: break;
	  case LABEL_STATIC_ENTRY: fputs (" [entry]", outfile); break;
	  case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", outfile); break;
	  case LABEL_WEAK_ENTRY: fputs (" [weak entry]", outfile); break;
	  default: gcc_unreachable ();
	}
      break;

    default:
      break;
    }

  fputc (')', outfile);
  sawclose = 1;
}