⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 final.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
			&& GET_CODE (body) == PARALLEL			&& GET_CODE (XVECEXP (body, 0, 0)) == SET			&& GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF))		  new_block = 1;	      }	    break;	  }	/* We have a real machine instruction as rtl.  */	body = PATTERN (insn);#ifdef HAVE_cc0	/* Check for redundant test and compare instructions	   (when the condition codes are already set up as desired).	   This is done only when optimizing; if not optimizing,	   it should be possible for the user to alter a variable	   with the debugger in between statements	   and the next statement should reexamine the variable	   to compute the condition codes.  */	if (optimize	    && GET_CODE (body) == SET	    && GET_CODE (SET_DEST (body)) == CC0	    && insn != last_ignored_compare)	  {	    if (GET_CODE (SET_SRC (body)) == SUBREG)	      SET_SRC (body) = alter_subreg (SET_SRC (body));	    else if (GET_CODE (SET_SRC (body)) == COMPARE)	      {		if (GET_CODE (XEXP (SET_SRC (body), 0)) == SUBREG)		  XEXP (SET_SRC (body), 0)		    = alter_subreg (XEXP (SET_SRC (body), 0));		if (GET_CODE (XEXP (SET_SRC (body), 1)) == SUBREG)		  XEXP (SET_SRC (body), 1)		    = alter_subreg (XEXP (SET_SRC (body), 1));	      }	    if ((cc_status.value1 != 0		 && rtx_equal_p (SET_SRC (body), cc_status.value1))		|| (cc_status.value2 != 0		    && rtx_equal_p (SET_SRC (body), cc_status.value2)))	      {		/* Don't delete insn if it has an addressing side-effect.  */		if (! FIND_REG_INC_NOTE (insn, 0)		    /* or if anything in it is volatile.  */		    && ! volatile_refs_p (PATTERN (insn)))		  {		    /* We don't really delete the insn; just ignore it.  */		    last_ignored_compare = insn;		    break;		  }	      }	  }#endif	/* Following a conditional branch, we have a new basic block.	   But if we are inside a sequence, the new block starts after the	   last insn of the sequence.  */	if (profile_block_flag && final_sequence == 0	    && ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET		 && GET_CODE (SET_SRC (body)) != LABEL_REF)		|| (GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == PARALLEL		    && GET_CODE (XVECEXP (body, 0, 0)) == SET		    && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF)))	  new_block = 1;#ifndef STACK_REGS	/* Don't bother outputting obvious no-ops, even without -O.	   This optimization is fast and doesn't interfere with debugging.	   Don't do this if the insn is in a delay slot, since this	   will cause an improper number of delay insns to be written.  */	if (final_sequence == 0	    && prescan >= 0	    && GET_CODE (insn) == INSN && GET_CODE (body) == SET	    && GET_CODE (SET_SRC (body)) == REG	    && GET_CODE (SET_DEST (body)) == REG	    && REGNO (SET_SRC (body)) == REGNO (SET_DEST (body)))	  break;#endif#ifdef HAVE_cc0	/* If this is a conditional branch, maybe modify it	   if the cc's are in a nonstandard state	   so that it accomplishes the same thing that it would	   do straightforwardly if the cc's were set up normally.  */	if (cc_status.flags != 0	    && GET_CODE (insn) == JUMP_INSN	    && GET_CODE (body) == SET	    && SET_DEST (body) == pc_rtx	    && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE	    /* This is done during prescan; it is not done again	       in final scan when prescan has been done.  */	    && prescan >= 0)	  {	    /* This function may alter the contents of its argument	       and clear some of the cc_status.flags bits.	       It may also return 1 meaning condition now always true	       or -1 meaning condition now always false	       or 2 meaning condition nontrivial but altered.  */	    register int result = alter_cond (XEXP (SET_SRC (body), 0));	    /* If condition now has fixed value, replace the IF_THEN_ELSE	       with its then-operand or its else-operand.  */	    if (result == 1)	      SET_SRC (body) = XEXP (SET_SRC (body), 1);	    if (result == -1)	      SET_SRC (body) = XEXP (SET_SRC (body), 2);	    /* The jump is now either unconditional or a no-op.	       If it has become a no-op, don't try to output it.	       (It would not be recognized.)  */	    if (SET_SRC (body) == pc_rtx)	      {		PUT_CODE (insn, NOTE);		NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;		NOTE_SOURCE_FILE (insn) = 0;		break;	      }	    else if (GET_CODE (SET_SRC (body)) == RETURN)	      /* Replace (set (pc) (return)) with (return).  */	      PATTERN (insn) = body = SET_SRC (body);	    /* Rerecognize the instruction if it has changed.  */	    if (result != 0)	      INSN_CODE (insn) = -1;	  }	/* Make same adjustments to instructions that examine the	   condition codes without jumping (if this machine has them).  */	if (cc_status.flags != 0	    && GET_CODE (body) == SET)	  {	    switch (GET_CODE (SET_SRC (body)))	      {	      case GTU:	      case GT:	      case LTU:	      case LT:	      case GEU:	      case GE:	      case LEU:	      case LE:	      case EQ:	      case NE:		{		  register int result;		  if (XEXP (SET_SRC (body), 0) != cc0_rtx)		    break;		  result = alter_cond (SET_SRC (body));		  if (result == 1)		    validate_change (insn, &SET_SRC (body), const_true_rtx, 0);		  else if (result == -1)		    validate_change (insn, &SET_SRC (body), const0_rtx, 0);		  else if (result == 2)		    INSN_CODE (insn) = -1;		}	      }	  }#endif	/* Do machine-specific peephole optimizations if desired.  */	if (optimize && !flag_no_peephole && !nopeepholes)	  {	    rtx next = peephole (insn);	    /* When peepholing, if there were notes within the peephole,	       emit them before the peephole.  */	    if (next != 0 && next != NEXT_INSN (insn))	      {		rtx prev = PREV_INSN (insn);		rtx note;		for (note = NEXT_INSN (insn); note != next;		     note = NEXT_INSN (note))		  final_scan_insn (note, file, optimize, prescan, nopeepholes);		/* In case this is prescan, put the notes		   in proper position for later rescan.  */		note = NEXT_INSN (insn);		PREV_INSN (note) = prev;		NEXT_INSN (prev) = note;		NEXT_INSN (PREV_INSN (next)) = insn;		PREV_INSN (insn) = PREV_INSN (next);		NEXT_INSN (insn) = next;		PREV_INSN (next) = insn;	      }	    /* PEEPHOLE might have changed this.  */	    body = PATTERN (insn);	  }	/* Try to recognize the instruction.	   If successful, verify that the operands satisfy the	   constraints for the instruction.  Crash if they don't,	   since `reload' should have changed them so that they do.  */	insn_code_number = recog_memoized (insn);	insn_extract (insn);	for (i = 0; i < insn_n_operands[insn_code_number]; i++)	  {	    if (GET_CODE (recog_operand[i]) == SUBREG)	      recog_operand[i] = alter_subreg (recog_operand[i]);	  }#ifdef REGISTER_CONSTRAINTS	if (! constrain_operands (insn_code_number, 1))	  fatal_insn_not_found (insn);#endif	/* Some target machines need to prescan each insn before	   it is output.  */#ifdef FINAL_PRESCAN_INSN	FINAL_PRESCAN_INSN (insn, recog_operand,			    insn_n_operands[insn_code_number]);#endif#ifdef HAVE_cc0	cc_prev_status = cc_status;	/* Update `cc_status' for this instruction.	   The instruction's output routine may change it further.	   If the output routine for a jump insn needs to depend	   on the cc status, it should look at cc_prev_status.  */	NOTICE_UPDATE_CC (body, insn);#endif	debug_insn = insn;	/* If the proper template needs to be chosen by some C code,	   run that code and get the real template.  */	template = insn_template[insn_code_number];	if (template == 0)	  {	    template = (*insn_outfun[insn_code_number]) (recog_operand, insn);	    /* If the C code returns 0, it means that it is a jump insn	       which follows a deleted test insn, and that test insn	       needs to be reinserted.  */	    if (template == 0)	      {		if (prev_nonnote_insn (insn) != last_ignored_compare)		  abort ();		new_block = 0;		return prev_nonnote_insn (insn);	      }	  }	/* If the template is the string "#", it means that this insn must	   be split.  */	if (template[0] == '#' && template[1] == '\0')	  {	    rtx new = try_split (body, insn, 0);	    /* If we didn't split the insn, go away.  */	    if (new == insn && PATTERN (new) == body)	      abort ();	      	    new_block = 0;	    return new;	  }		if (prescan > 0)	  break;	/* Output assembler code from the template.  */	output_asm_insn (template, recog_operand);#if 0	/* It's not at all clear why we did this and doing so interferes	   with tests we'd like to do to use REG_WAS_0 notes, so let's try	   with this out.  */	/* Mark this insn as having been output.  */	INSN_DELETED_P (insn) = 1;#endif	debug_insn = 0;      }    }  return NEXT_INSN (insn);}/* Output debugging info to the assembler file FILE   based on the NOTE-insn INSN, assumed to be a line number.  */static voidoutput_source_line (file, insn)     FILE *file;     rtx insn;{  char ltext_label_name[100];  register char *filename = NOTE_SOURCE_FILE (insn);  last_linenum = NOTE_LINE_NUMBER (insn);  if (write_symbols != NO_DEBUG)    {#ifdef SDB_DEBUGGING_INFO      if (write_symbols == SDB_DEBUG#if 0 /* People like having line numbers even in wrong file!  */	  /* COFF can't handle multiple source files--lose, lose.  */	  && !strcmp (filename, main_input_filename)#endif	  /* COFF relative line numbers must be positive.  */	  && last_linenum > sdb_begin_function_line)	{#ifdef ASM_OUTPUT_SOURCE_LINE	  ASM_OUTPUT_SOURCE_LINE (file, last_linenum);#else	  fprintf (file, "\t.ln\t%d\n",		   ((sdb_begin_function_line > -1)		    ? last_linenum - sdb_begin_function_line : 1));#endif	}#endif#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)      if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)	dbxout_source_line (file, filename, NOTE_LINE_NUMBER (insn));#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */#ifdef DWARF_DEBUGGING_INFO      if (write_symbols == DWARF_DEBUG)	dwarfout_line (filename, NOTE_LINE_NUMBER (insn));#endif    }}/* If X is a SUBREG, replace it with a REG or a MEM,   based on the thing it is a subreg of.  */rtxalter_subreg (x)     register rtx x;{  register rtx y = SUBREG_REG (x);  if (GET_CODE (y) == SUBREG)    y = alter_subreg (y);  if (GET_CODE (y) == REG)    {      /* If the containing reg really gets a hard reg, so do we.  */      PUT_CODE (x, REG);      REGNO (x) = REGNO (y) + SUBREG_WORD (x);    }  else if (GET_CODE (y) == MEM)    {      register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;#if BYTES_BIG_ENDIAN      offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))		 - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));#endif      PUT_CODE (x, MEM);      MEM_VOLATILE_P (x) = MEM_VOLATILE_P (y);      XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);    }  return x;}/* Do alter_subreg on all the SUBREGs contained in X.  */static rtxwalk_alter_subreg (x)     rtx x;{  switch (GET_CODE (x))    {    case PLUS:    case MULT:      XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));      XEXP (x, 1) = walk_alter_subreg (XEXP (x, 1));      break;    case MEM:      XEXP (x, 0) = walk_alter_subreg (XEXP (x, 0));      break;    case SUBREG:      return alter_subreg (x);    }  return x;}#ifdef HAVE_cc0/* Given BODY, the body of a jump instruction, alter the jump condition   as required by the bits that are set in cc_status.flags.   Not all of the bits there can be handled at this level in all cases.   The value is normally 0.   1 means that the condition has become always true.   -1 means that the condition has become always false.   2 means that COND has been altered.  */static intalter_cond (cond)     register rtx cond;{  int value = 0;  if (cc_status.flags & CC_REVERSED)    {      value = 2;      PUT_CODE (cond, swap_condition (GET_CODE (cond)));    }  if (cc_status.flags & CC_INVERTED)    {      value = 2;      PUT_CODE (cond, reverse_condition (GET_CODE (cond)));    }  if (cc_status.flags & CC_NOT_POSITIVE)    switch (GET_CODE (cond))      {      case LE:      case LEU:      case GEU:	/* Jump becomes unconditional.  */	return 1;      case GT:      case GTU:      case LTU:	/* Jump becomes no-op.  */	return -1;      case GE:	PUT_CODE (cond, EQ);	value = 2;	break;      case LT:	PUT_CODE (cond, NE);	value = 2;	break;      }  if (cc_status.flags & CC_NOT_NEGATIVE)    switch (GET_CODE (cond))      {      case GE:      case GEU:	/* Jump becomes unconditional.  */	return 1;      case LT:      case LTU:	/* Jump becomes no-op.  */	return -1;      case LE:      case LEU:	PUT_CODE (cond, EQ);	value = 2;	break;      case GT:      case GTU:	PUT_CODE (cond, NE);	value = 2;	break;      }  if (cc_status.flags & CC_NO_OVERFLOW)    switch (GET_CODE (cond))      {      case GEU:	/* Jump becomes unconditional.  */	return 1;      case LEU:	PUT_CODE (cond, EQ);	value = 2;	break;      case GTU:	PUT_CODE (cond, NE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -