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

📄 combine.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
static voidset_nonzero_bits_and_sign_copies (x, set)     rtx x;     rtx set;{  int num;  if (GET_CODE (x) == REG      && REGNO (x) >= FIRST_PSEUDO_REGISTER      && reg_n_sets[REGNO (x)] > 1      && reg_basic_block[REGNO (x)] < 0      /* If this register is undefined at the start of the file, we can't	 say what its contents were.  */      && ! (basic_block_live_at_start[0][REGNO (x) / REGSET_ELT_BITS]	    & ((REGSET_ELT_TYPE) 1 << (REGNO (x) % REGSET_ELT_BITS)))      && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)    {      if (GET_CODE (set) == CLOBBER)	{	  reg_nonzero_bits[REGNO (x)] = GET_MODE_MASK (GET_MODE (x));	  reg_sign_bit_copies[REGNO (x)] = 0;	  return;	}      /* If this is a complex assignment, see if we can convert it into a	 simple assignment.  */      set = expand_field_assignment (set);      /* If this is a simple assignment, or we have a paradoxical SUBREG,	 set what we know about X.  */      if (SET_DEST (set) == x	  || (GET_CODE (SET_DEST (set)) == SUBREG	      && (GET_MODE_SIZE (GET_MODE (SET_DEST (set)))		  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (set)))))	      && SUBREG_REG (SET_DEST (set)) == x))	{	  rtx src = SET_SRC (set);#ifdef SHORT_IMMEDIATES_SIGN_EXTEND	  /* If X is narrower than a word and SRC is a non-negative	     constant that would appear negative in the mode of X,	     sign-extend it for use in reg_nonzero_bits because some	     machines (maybe most) will actually do the sign-extension	     and this is the conservative approach. 	     ??? For 2.5, try to tighten up the MD files in this regard	     instead of this kludge.  */	  if (GET_MODE_BITSIZE (GET_MODE (x)) < BITS_PER_WORD	      && GET_CODE (src) == CONST_INT	      && INTVAL (src) > 0	      && 0 != (INTVAL (src)		       & ((HOST_WIDE_INT) 1			  << (GET_MODE_BITSIZE (GET_MODE (x)) - 1))))	    src = GEN_INT (INTVAL (src)			   | ((HOST_WIDE_INT) (-1)			      << GET_MODE_BITSIZE (GET_MODE (x))));#endif	  reg_nonzero_bits[REGNO (x)]	    |= nonzero_bits (src, nonzero_bits_mode);	  num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x));	  if (reg_sign_bit_copies[REGNO (x)] == 0	      || reg_sign_bit_copies[REGNO (x)] > num)	    reg_sign_bit_copies[REGNO (x)] = num;	}      else	{	  reg_nonzero_bits[REGNO (x)] = GET_MODE_MASK (GET_MODE (x));	  reg_sign_bit_copies[REGNO (x)] = 0;	}    }}/* See if INSN can be combined into I3.  PRED and SUCC are optionally   insns that were previously combined into I3 or that will be combined   into the merger of INSN and I3.   Return 0 if the combination is not allowed for any reason.   If the combination is allowed, *PDEST will be set to the single    destination of INSN and *PSRC to the single source, and this function   will return 1.  */static intcan_combine_p (insn, i3, pred, succ, pdest, psrc)     rtx insn;     rtx i3;     rtx pred, succ;     rtx *pdest, *psrc;{  int i;  rtx set = 0, src, dest;  rtx p, link;  int all_adjacent = (succ ? (next_active_insn (insn) == succ			      && next_active_insn (succ) == i3)		      : next_active_insn (insn) == i3);  /* Can combine only if previous insn is a SET of a REG, a SUBREG or CC0.     or a PARALLEL consisting of such a SET and CLOBBERs.      If INSN has CLOBBER parallel parts, ignore them for our processing.     By definition, these happen during the execution of the insn.  When it     is merged with another insn, all bets are off.  If they are, in fact,     needed and aren't also supplied in I3, they may be added by     recog_for_combine.  Otherwise, it won't match.      We can also ignore a SET whose SET_DEST is mentioned in a REG_UNUSED     note.     Get the source and destination of INSN.  If more than one, can't      combine.  */       if (GET_CODE (PATTERN (insn)) == SET)    set = PATTERN (insn);  else if (GET_CODE (PATTERN (insn)) == PARALLEL	   && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)    {      for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)	{	  rtx elt = XVECEXP (PATTERN (insn), 0, i);	  switch (GET_CODE (elt))	    {	      /* We can ignore CLOBBERs.  */	    case CLOBBER:	      break;	    case SET:	      /* Ignore SETs whose result isn't used but not those that		 have side-effects.  */	      if (find_reg_note (insn, REG_UNUSED, SET_DEST (elt))		  && ! side_effects_p (elt))		break;	      /* If we have already found a SET, this is a second one and		 so we cannot combine with this insn.  */	      if (set)		return 0;	      set = elt;	      break;	    default:	      /* Anything else means we can't combine.  */	      return 0;	    }	}      if (set == 0	  /* If SET_SRC is an ASM_OPERANDS we can't throw away these CLOBBERs,	     so don't do anything with it.  */	  || GET_CODE (SET_SRC (set)) == ASM_OPERANDS)	return 0;    }  else    return 0;  if (set == 0)    return 0;  set = expand_field_assignment (set);  src = SET_SRC (set), dest = SET_DEST (set);  /* Don't eliminate a store in the stack pointer.  */  if (dest == stack_pointer_rtx      /* If we couldn't eliminate a field assignment, we can't combine.  */      || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == STRICT_LOW_PART      /* Don't combine with an insn that sets a register to itself if it has	 a REG_EQUAL note.  This may be part of a REG_NO_CONFLICT sequence.  */      || (rtx_equal_p (src, dest) && find_reg_note (insn, REG_EQUAL, NULL_RTX))      /* Can't merge a function call.  */      || GET_CODE (src) == CALL      /* Don't eliminate a function call argument.  */      || (GET_CODE (i3) == CALL_INSN	  && (find_reg_fusage (i3, USE, dest)	      || (GET_CODE (dest) == REG		  && REGNO (dest) < FIRST_PSEUDO_REGISTER		  && global_regs[REGNO (dest)])))      /* Don't substitute into an incremented register.  */      || FIND_REG_INC_NOTE (i3, dest)      || (succ && FIND_REG_INC_NOTE (succ, dest))      /* Don't combine the end of a libcall into anything.  */      || find_reg_note (insn, REG_RETVAL, NULL_RTX)      /* Make sure that DEST is not used after SUCC but before I3.  */      || (succ && ! all_adjacent	  && reg_used_between_p (dest, succ, i3))      /* Make sure that the value that is to be substituted for the register	 does not use any registers whose values alter in between.  However,	 If the insns are adjacent, a use can't cross a set even though we	 think it might (this can happen for a sequence of insns each setting	 the same destination; reg_last_set of that register might point to	 a NOTE).  If INSN has a REG_EQUIV note, the register is always	 equivalent to the memory so the substitution is valid even if there	 are intervening stores.  Also, don't move a volatile asm or	 UNSPEC_VOLATILE across any other insns.  */      || (! all_adjacent	  && (((GET_CODE (src) != MEM		|| ! find_reg_note (insn, REG_EQUIV, src))	       && use_crosses_set_p (src, INSN_CUID (insn)))	      || (GET_CODE (src) == ASM_OPERANDS && MEM_VOLATILE_P (src))	      || GET_CODE (src) == UNSPEC_VOLATILE))      /* If there is a REG_NO_CONFLICT note for DEST in I3 or SUCC, we get	 better register allocation by not doing the combine.  */      || find_reg_note (i3, REG_NO_CONFLICT, dest)      || (succ && find_reg_note (succ, REG_NO_CONFLICT, dest))      /* Don't combine across a CALL_INSN, because that would possibly	 change whether the life span of some REGs crosses calls or not,	 and it is a pain to update that information.	 Exception: if source is a constant, moving it later can't hurt.	 Accept that special case, because it helps -fforce-addr a lot.  */      || (INSN_CUID (insn) < last_call_cuid && ! CONSTANT_P (src)))    return 0;  /* DEST must either be a REG or CC0.  */  if (GET_CODE (dest) == REG)    {      /* If register alignment is being enforced for multi-word items in all	 cases except for parameters, it is possible to have a register copy	 insn referencing a hard register that is not allowed to contain the	 mode being copied and which would not be valid as an operand of most	 insns.  Eliminate this problem by not combining with such an insn.	 Also, on some machines we don't want to extend the life of a hard	 register.  */      if (GET_CODE (src) == REG	  && ((REGNO (dest) < FIRST_PSEUDO_REGISTER	       && ! HARD_REGNO_MODE_OK (REGNO (dest), GET_MODE (dest)))	      /* Don't extend the life of a hard register unless it is		 user variable (if we have few registers) or it can't		 fit into the desired register (meaning something special		 is going on).  */	      || (REGNO (src) < FIRST_PSEUDO_REGISTER		  && (! HARD_REGNO_MODE_OK (REGNO (src), GET_MODE (src))#ifdef SMALL_REGISTER_CLASSES		      || ! REG_USERVAR_P (src)#endif		      ))))	return 0;    }  else if (GET_CODE (dest) != CC0)    return 0;  /* Don't substitute for a register intended as a clobberable operand.     Similarly, don't substitute an expression containing a register that     will be clobbered in I3.  */  if (GET_CODE (PATTERN (i3)) == PARALLEL)    for (i = XVECLEN (PATTERN (i3), 0) - 1; i >= 0; i--)      if (GET_CODE (XVECEXP (PATTERN (i3), 0, i)) == CLOBBER	  && (reg_overlap_mentioned_p (XEXP (XVECEXP (PATTERN (i3), 0, i), 0),				       src)	      || rtx_equal_p (XEXP (XVECEXP (PATTERN (i3), 0, i), 0), dest)))	return 0;  /* If INSN contains anything volatile, or is an `asm' (whether volatile     or not), reject, unless nothing volatile comes between it and I3,     with the exception of SUCC.  */  if (GET_CODE (src) == ASM_OPERANDS || volatile_refs_p (src))    for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p))      if (GET_RTX_CLASS (GET_CODE (p)) == 'i'	  && p != succ && volatile_refs_p (PATTERN (p)))	return 0;  /* If there are any volatile insns between INSN and I3, reject, because     they might affect machine state.  */  for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p))    if (GET_RTX_CLASS (GET_CODE (p)) == 'i'	&& p != succ && volatile_insn_p (PATTERN (p)))      return 0;  /* If INSN or I2 contains an autoincrement or autodecrement,     make sure that register is not used between there and I3,     and not already used in I3 either.     Also insist that I3 not be a jump; if it were one     and the incremented register were spilled, we would lose.  */#ifdef AUTO_INC_DEC  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))    if (REG_NOTE_KIND (link) == REG_INC	&& (GET_CODE (i3) == JUMP_INSN	    || reg_used_between_p (XEXP (link, 0), insn, i3)	    || reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (i3))))      return 0;#endif#ifdef HAVE_cc0  /* Don't combine an insn that follows a CC0-setting insn.     An insn that uses CC0 must not be separated from the one that sets it.     We do, however, allow I2 to follow a CC0-setting insn if that insn     is passed as I1; in that case it will be deleted also.     We also allow combining in this case if all the insns are adjacent     because that would leave the two CC0 insns adjacent as well.     It would be more logical to test whether CC0 occurs inside I1 or I2,     but that would be much slower, and this ought to be equivalent.  */  p = prev_nonnote_insn (insn);  if (p && p != pred && GET_CODE (p) == INSN && sets_cc0_p (PATTERN (p))      && ! all_adjacent)    return 0;#endif  /* If we get here, we have passed all the tests and the combination is     to be allowed.  */  *pdest = dest;  *psrc = src;  return 1;}/* LOC is the location within I3 that contains its pattern or the component   of a PARALLEL of the pattern.  We validate that it is valid for combining.   One problem is if I3 modifies its output, as opposed to replacing it   entirely, we can't allow the output to contain I2DEST or I1DEST as doing   so would produce an insn that is not equivalent to the original insns.   Consider:         (set (reg:DI 101) (reg:DI 100))	 (set (subreg:SI (reg:DI 101) 0) <foo>)   This is NOT equivalent to:         (parallel [(set (subreg:SI (reg:DI 100) 0) <foo>)	 	    (set (reg:DI 101) (reg:DI 100))])   Not only does this modify 100 (in which case it might still be valid   if 100 were dead in I2), it sets 101 to the ORIGINAL value of 100.    We can also run into a problem if I2 sets a register that I1   uses and I1 gets directly substituted into I3 (not via I2).  In that   case, we would be getting the wrong value of I2DEST into I3, so we   must reject the combination.  This case occurs when I2 and I1 both   feed into I3, rather than when I1 feeds into I2, which feeds into I3.   If I1_NOT_IN_SRC is non-zero, it means that finding I1 in the source   of a SET must prevent combination from occurring.   On machines where SMALL_REGISTER_CLASSES is defined, we don't combine   if the destination of a SET is a hard register that isn't a user   variable.   Before doing the above check, we first try to expand a field assignment   into a set of logical operations.   If PI3_DEST_KILLED is non-zero, it is a pointer to a location in which   we place a register that is both set and used within I3.  If more than one   such register is detected, we fail.   Return 1 if the combination is valid, zero otherwise.  */static intcombinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed)     rtx i3;

⌨️ 快捷键说明

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