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

📄 function.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	      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);#endif		  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);	  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);#endif		    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.  */	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))	    && recog_memoized (insn) >= 0)	  {	    replacement = find_fixup_replacement (replacements, SET_SRC (x));	    if (replacement->new)	      {	      SET_SRC (x) = replacement->new;	      return;	    }	    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);	    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))	    && recog_memoized (insn) >= 0)	  {	    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);	    return;	  }	/* Otherwise, storing into VAR must be handled specially	   by storing into a temporary and copying that into VAR	   with a new insn after this one.  Note that this case	   will be used when storing into a promoted scalar since	   the insn will now have different modes on the input	   and output and hence will be invalid (except for the case	   of setting it to a constant, which does not need any	   change if it is valid).  We generate extra code in that case,	   but combine.c will eliminate it.  */	if (dest == var)	  {	    rtx temp;	    rtx fixeddest = SET_DEST (x);	    /* STRICT_LOW_PART can be discarded, around a MEM.  */	    if (GET_CODE (fixeddest) == STRICT_LOW_PART)	      fixeddest = XEXP (fixeddest, 0);	    /* Convert (SUBREG (MEM)) to a MEM in a changed mode.  */	    if (GET_CODE (fixeddest) == SUBREG)	      fixeddest = fixup_memory_subreg (fixeddest, insn, 0);	    else	      fixeddest = fixup_stack_1 (fixeddest, insn);	    temp = gen_reg_rtx (GET_MODE (SET_SRC (x)) == VOIDmode				? GET_MODE (fixeddest)				: GET_MODE (SET_SRC (x)));	    emit_insn_after (gen_move_insn (fixeddest,					    gen_lowpart (GET_MODE (fixeddest),							 temp)),			     insn);	    SET_DEST (x) = temp;	  }      }    }  /* Nothing special about this RTX; fix its operands.  */  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	fixup_var_refs_1 (var, promoted_mode, &XEXP (x, i), insn, replacements);      if (fmt[i] == 'E')	{	  register int j;	  for (j = 0; j < XVECLEN (x, i); j++)	    fixup_var_refs_1 (var, promoted_mode, &XVECEXP (x, i, j),			      insn, replacements);	}    }}/* Given X, an rtx of the form (SUBREG:m1 (MEM:m2 addr)),   return an rtx (MEM:m1 newaddr) which is equivalent.   If any insns must be emitted to compute NEWADDR, put them before INSN.   UNCRITICAL nonzero means accept paradoxical subregs.   This is used for subregs found inside of ZERO_EXTRACTs.  */static rtxfixup_memory_subreg (x, insn, uncritical)     rtx x;     rtx insn;     int uncritical;{  int offset = SUBREG_WORD (x) * UNITS_PER_WORD;  rtx addr = XEXP (SUBREG_REG (x), 0);  enum machine_mode mode = GET_MODE (x);  rtx saved, result;  /* Paradoxical SUBREGs are usually invalid during RTL generation.  */  if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))      && ! uncritical)    abort ();#if BYTES_BIG_ENDIAN  offset += (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))	     - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));#endif  addr = plus_constant (addr, offset);  if (!flag_force_addr && memory_address_p (mode, addr))    /* Shortcut if no insns need be emitted.  */    return change_address (SUBREG_REG (x), mode, addr);  start_sequence ();  result = change_address (SUBREG_REG (x), mode, addr);  emit_insn_before (gen_sequence (), insn);  end_sequence ();  return result;}/* Do fixup_memory_subreg on all (SUBREG (MEM ...) ...) contained in X.   Replace subexpressions of X in place.   If X itself is a (SUBREG (MEM ...) ...), return the replacement expression.   Otherwise return X, with its contents possibly altered.   If any insns must be emitted to compute NEWADDR, put them before INSN.  */static rtxwalk_fixup_memory_subreg (x, insn)     register rtx x;     rtx insn;{  register enum rtx_code code;  register char *fmt;  register int i;  if (x == 0)    return 0;  code = GET_CODE (x);  if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)    return fixup_memory_subreg (x, insn, 0);  /* Nothing special about this RTX; fix its operands.  */  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn);      if (fmt[i] == 'E')	{	  register int j;	  for (j = 0; j < XVECLEN (x, i); j++)	    XVECEXP (x, i, j)	      = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn);	}    }  return x;}#if 0/* Fix up any references to stack slots that are invalid memory addresses   because they exceed the maximum range of a displacement.  */

⌨️ 快捷键说明

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