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

📄 function.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
	{	  /* If we already have a replacement, use it.  Otherwise, 	     try to fix up this address in case it is invalid.  */	  replacement = find_fixup_replacement (replacements, var);	  if (replacement->new)	    {	      *loc = replacement->new;	      return;	    }	  *loc = replacement->new = x = fixup_stack_1 (x, insn);	  /* Unless we are forcing memory to register or we changed the mode,	     we can leave things the way they are if the insn is valid.  */	     	  INSN_CODE (insn) = -1;	  if (! flag_force_mem && GET_MODE (x) == promoted_mode	      && recog_memoized (insn) >= 0)	    return;	  *loc = replacement->new = gen_reg_rtx (promoted_mode);	  return;	}      /* If X contains VAR, we need to unshare it here so that we update	 each occurrence separately.  But all identical MEMs in one insn	 must be replaced with the same rtx because of the possibility of	 MATCH_DUPs.  */      if (reg_mentioned_p (var, x))	{	  replacement = find_fixup_replacement (replacements, x);	  if (replacement->new == 0)	    replacement->new = copy_most_rtx (x, var);	  *loc = x = replacement->new;	}      break;    case REG:    case CC0:    case PC:    case CONST_INT:    case CONST:    case SYMBOL_REF:    case LABEL_REF:    case CONST_DOUBLE:      return;    case SIGN_EXTRACT:    case ZERO_EXTRACT:      /* Note that in some cases those types of expressions are altered	 by optimize_bit_field, and do not survive to get here.  */      if (XEXP (x, 0) == var	  || (GET_CODE (XEXP (x, 0)) == SUBREG	      && SUBREG_REG (XEXP (x, 0)) == var))	{	  /* Get TEM as a valid MEM in the mode presently in the insn.	     We don't worry about the possibility of MATCH_DUP here; it	     is highly unlikely and would be tricky to handle.  */	  tem = XEXP (x, 0);	  if (GET_CODE (tem) == SUBREG)	    tem = fixup_memory_subreg (tem, insn, 1);	  tem = fixup_stack_1 (tem, insn);	  /* Unless we want to load from memory, get TEM into the proper mode	     for an extract from memory.  This can only be done if the	     extract is at a constant position and length.  */	  if (! flag_force_mem && GET_CODE (XEXP (x, 1)) == CONST_INT	      && GET_CODE (XEXP (x, 2)) == CONST_INT	      && ! mode_dependent_address_p (XEXP (tem, 0))	      && ! MEM_VOLATILE_P (tem))	    {	      enum machine_mode wanted_mode = VOIDmode;	      enum machine_mode is_mode = GET_MODE (tem);	      int width = INTVAL (XEXP (x, 1));	      int pos = INTVAL (XEXP (x, 2));#ifdef HAVE_extzv	      if (GET_CODE (x) == ZERO_EXTRACT)		wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];#endif#ifdef HAVE_extv	      if (GET_CODE (x) == SIGN_EXTRACT)		wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];#endif	      /* If we have a narrower mode, we can do something.  */	      if (wanted_mode != VOIDmode		  && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))		{		  int offset = pos / BITS_PER_UNIT;		  rtx old_pos = XEXP (x, 2);		  rtx newmem;		  /* If the bytes and bits are counted differently, we		     must adjust the offset.  */		  if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)		    offset = (GET_MODE_SIZE (is_mode)			      - GET_MODE_SIZE (wanted_mode) - offset);		  pos %= GET_MODE_BITSIZE (wanted_mode);		  newmem = gen_rtx (MEM, wanted_mode,				    plus_constant (XEXP (tem, 0), offset));		  RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);		  MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);		  MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);		  /* Make the change and see if the insn remains valid.  */		  INSN_CODE (insn) = -1;		  XEXP (x, 0) = newmem;		  XEXP (x, 2) = GEN_INT (pos);		  if (recog_memoized (insn) >= 0)		    return;		  /* Otherwise, restore old position.  XEXP (x, 0) will be		     restored later.  */		  XEXP (x, 2) = old_pos;		}	    }	  /* If we get here, the bitfield extract insn can't accept a memory	     reference.  Copy the input into a register.  */	  tem1 = gen_reg_rtx (GET_MODE (tem));	  emit_insn_before (gen_move_insn (tem1, tem), insn);	  XEXP (x, 0) = tem1;	  return;	}      break;	          case SUBREG:      if (SUBREG_REG (x) == var)	{	  /* If this is a special SUBREG made because VAR was promoted	     from a wider mode, replace it with VAR and call ourself	     recursively, this time saying that the object previously	     had its current mode (by virtue of the SUBREG).  */	  if (SUBREG_PROMOTED_VAR_P (x))	    {	      *loc = var;	      fixup_var_refs_1 (var, GET_MODE (var), loc, insn, replacements);	      return;	    }	  /* If this SUBREG makes VAR wider, it has become a paradoxical	     SUBREG with VAR in memory, but these aren't allowed at this 	     stage of the compilation.  So load VAR into a pseudo and take	     a SUBREG of that pseudo.  */	  if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (var)))	    {	      replacement = find_fixup_replacement (replacements, var);	      if (replacement->new == 0)		replacement->new = gen_reg_rtx (GET_MODE (var));	      SUBREG_REG (x) = replacement->new;	      return;	    }	  /* See if we have already found a replacement for this SUBREG.	     If so, use it.  Otherwise, make a MEM and see if the insn	     is recognized.  If not, or if we should force MEM into a register,	     make a pseudo for this SUBREG.  */	  replacement = find_fixup_replacement (replacements, x);	  if (replacement->new)	    {	      *loc = replacement->new;	      return;	    }	  	  replacement->new = *loc = fixup_memory_subreg (x, insn, 0);	  INSN_CODE (insn) = -1;	  if (! flag_force_mem && recog_memoized (insn) >= 0)	    return;	  *loc = replacement->new = gen_reg_rtx (GET_MODE (x));	  return;	}      break;    case SET:      /* First do special simplification of bit-field references.  */      if (GET_CODE (SET_DEST (x)) == SIGN_EXTRACT	  || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)	optimize_bit_field (x, insn, 0);      if (GET_CODE (SET_SRC (x)) == SIGN_EXTRACT	  || GET_CODE (SET_SRC (x)) == ZERO_EXTRACT)	optimize_bit_field (x, insn, NULL_PTR);      /* If SET_DEST is now a paradoxical SUBREG, put the result of this	 insn into a pseudo and store the low part of the pseudo into VAR. */      if (GET_CODE (SET_DEST (x)) == SUBREG	  && SUBREG_REG (SET_DEST (x)) == var	  && (GET_MODE_SIZE (GET_MODE (SET_DEST (x)))	      > GET_MODE_SIZE (GET_MODE (var))))	{	  SET_DEST (x) = tem = gen_reg_rtx (GET_MODE (SET_DEST (x)));	  emit_insn_after (gen_move_insn (var, gen_lowpart (GET_MODE (var),							    tem)),			   insn);	  break;	}	        {	rtx dest = SET_DEST (x);	rtx src = SET_SRC (x);	rtx outerdest = dest;	while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART	       || GET_CODE (dest) == SIGN_EXTRACT	       || GET_CODE (dest) == ZERO_EXTRACT)	  dest = XEXP (dest, 0);	if (GET_CODE (src) == SUBREG)	  src = XEXP (src, 0);	/* If VAR does not appear at the top level of the SET	   just scan the lower levels of the tree.  */        if (src != var && dest != var)	  break;	/* We will need to rerecognize this insn.  */	INSN_CODE (insn) = -1;#ifdef HAVE_insv	if (GET_CODE (outerdest) == ZERO_EXTRACT && dest == var)	  {	    /* Since this case will return, ensure we fixup all the	       operands here.  */	    fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 1),			      insn, replacements);	    fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 2),			      insn, replacements);	    fixup_var_refs_1 (var, promoted_mode, &SET_SRC (x),			      insn, replacements);	    tem = XEXP (outerdest, 0);	    /* Clean up (SUBREG:SI (MEM:mode ...) 0)	       that may appear inside a ZERO_EXTRACT.	       This was legitimate when the MEM was a REG.  */	    if (GET_CODE (tem) == SUBREG		&& SUBREG_REG (tem) == var)	      tem = fixup_memory_subreg (tem, insn, 1);	    else	      tem = fixup_stack_1 (tem, insn);	    if (GET_CODE (XEXP (outerdest, 1)) == CONST_INT		&& GET_CODE (XEXP (outerdest, 2)) == CONST_INT		&& ! mode_dependent_address_p (XEXP (tem, 0))		&& ! MEM_VOLATILE_P (tem))	      {		enum machine_mode wanted_mode		  = insn_operand_mode[(int) CODE_FOR_insv][0];		enum machine_mode is_mode = GET_MODE (tem);		int width = INTVAL (XEXP (outerdest, 1));		int pos = INTVAL (XEXP (outerdest, 2));		/* If we have a narrower mode, we can do something.  */		if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))		  {		    int offset = pos / BITS_PER_UNIT;		    rtx old_pos = XEXP (outerdest, 2);		    rtx newmem;		    if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)		      offset = (GET_MODE_SIZE (is_mode)				- GET_MODE_SIZE (wanted_mode) - offset);		    pos %= GET_MODE_BITSIZE (wanted_mode);		    newmem = gen_rtx (MEM, wanted_mode,				      plus_constant (XEXP (tem, 0), offset));		    RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (tem);		    MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (tem);		    MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (tem);		    /* Make the change and see if the insn remains valid.  */		    INSN_CODE (insn) = -1;		    XEXP (outerdest, 0) = newmem;		    XEXP (outerdest, 2) = GEN_INT (pos);		    		    if (recog_memoized (insn) >= 0)		      return;		    		    /* Otherwise, restore old position.  XEXP (x, 0) will be		       restored later.  */		    XEXP (outerdest, 2) = old_pos;		  }	      }	    /* If we get here, the bit-field store doesn't allow memory	       or isn't located at a constant position.  Load the value into	       a register, do the store, and put it back into memory.  */	    tem1 = gen_reg_rtx (GET_MODE (tem));	    emit_insn_before (gen_move_insn (tem1, tem), insn);	    emit_insn_after (gen_move_insn (tem, tem1), insn);	    XEXP (outerdest, 0) = tem1;	    return;	  }#endif	/* STRICT_LOW_PART is a no-op on memory references	   and it can cause combinations to be unrecognizable,	   so eliminate it.  */	if (dest == var && GET_CODE (SET_DEST (x)) == STRICT_LOW_PART)	  SET_DEST (x) = XEXP (SET_DEST (x), 0);	/* A valid insn to copy VAR into or out of a register	   must be left alone, to avoid an infinite loop here.	   If the reference to VAR is by a subreg, fix that up,	   since SUBREG is not valid for a memref.	   Also fix up the address of the stack slot.	   Note that we must not try to recognize the insn until	   after we know that we have valid addresses and no	   (subreg (mem ...) ...) constructs, since these interfere	   with determining the validity of the insn.  */	if ((SET_SRC (x) == var	     || (GET_CODE (SET_SRC (x)) == SUBREG		 && SUBREG_REG (SET_SRC (x)) == var))	    && (GET_CODE (SET_DEST (x)) == REG		|| (GET_CODE (SET_DEST (x)) == SUBREG		    && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG))	    && x == single_set (PATTERN (insn)))	  {	    rtx pat;	    replacement = find_fixup_replacement (replacements, SET_SRC (x));	    if (replacement->new)	      SET_SRC (x) = replacement->new;	    else if (GET_CODE (SET_SRC (x)) == SUBREG)	      SET_SRC (x) = replacement->new		= fixup_memory_subreg (SET_SRC (x), insn, 0);	    else	      SET_SRC (x) = replacement->new		= fixup_stack_1 (SET_SRC (x), insn);	    if (recog_memoized (insn) >= 0)	      return;	    /* INSN is not valid, but we know that we want to	       copy SET_SRC (x) to SET_DEST (x) in some way.  So	       we generate the move and see whether it requires more	       than one insn.  If it does, we emit those insns and	       delete INSN.  Otherwise, we an just replace the pattern 	       of INSN; we have already verified above that INSN has	       no other function that to do X.  */	    pat = gen_move_insn (SET_DEST (x), SET_SRC (x));	    if (GET_CODE (pat) == SEQUENCE)	      {		emit_insn_after (pat, insn);		PUT_CODE (insn, NOTE);		NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;		NOTE_SOURCE_FILE (insn) = 0;	      }	    else	      PATTERN (insn) = pat;	    return;	  }	if ((SET_DEST (x) == var	     || (GET_CODE (SET_DEST (x)) == SUBREG		 && SUBREG_REG (SET_DEST (x)) == var))	    && (GET_CODE (SET_SRC (x)) == REG		|| (GET_CODE (SET_SRC (x)) == SUBREG		    && GET_CODE (SUBREG_REG (SET_SRC (x))) == REG))	    && x == single_set (PATTERN (insn)))	  {	    rtx pat;	    if (GET_CODE (SET_DEST (x)) == SUBREG)	      SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, 0);	    else	      SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn);	    if (recog_memoized (insn) >= 0)	      return;	    pat = gen_move_insn (SET_DEST (x), SET_SRC (x));	    if (GET_CODE (pat) == SEQUENCE)	      {		emit_insn_after (pat, insn);		PUT_CODE (insn, NOTE);		NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;		NOTE_SOURCE_FILE (insn) = 0;	      }	    else	      PATTERN (insn) = pat;	    return;	  }	/* Otherwise, storing into VAR must be hand

⌨️ 快捷键说明

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