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

📄 combine.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	inner_dest = XEXP (inner_dest, 0);      return (GET_CODE (inner_dest) == REG	      && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER	      && FUNCTION_ARG_REGNO_P (REGNO (inner_dest)));    }  return 0;}/* 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 non-zero, 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;     rtx *loc;     rtx i2dest;     rtx i1dest;     int i1_not_in_src;     rtx *pi3dest_killed;{  rtx x = *loc;  if (GET_CODE (x) == SET)    {      rtx set = expand_field_assignment (x);      rtx dest = SET_DEST (set);      rtx src = SET_SRC (set);      rtx inner_dest = dest, inner_src = src;      SUBST (*loc, set);      while (GET_CODE (inner_dest) == STRICT_LOW_PART	     || GET_CODE (inner_dest) == SUBREG	     || GET_CODE (inner_dest) == ZERO_EXTRACT)	inner_dest = XEXP (inner_dest, 0);  /* We probably don't need this any more now that LIMIT_RELOAD_CLASS     was added.  */#if 0      while (GET_CODE (inner_src) == STRICT_LOW_PART	     || GET_CODE (inner_src) == SUBREG	     || GET_CODE (inner_src) == ZERO_EXTRACT)	inner_src = XEXP (inner_src, 0);      /* If it is better that two different modes keep two different pseudos,	 avoid combining them.  This avoids producing the following pattern	 on a 386:	  (set (subreg:SI (reg/v:QI 21) 0)	       (lshiftrt:SI (reg/v:SI 20)	           (const_int 24)))	 If that were made, reload could not handle the pair of	 reg 20/21, since it would try to get any GENERAL_REGS	 but some of them don't handle QImode.  */      if (rtx_equal_p (inner_src, i2dest)	  && GET_CODE (inner_dest) == REG	  && ! MODES_TIEABLE_P (GET_MODE (i2dest), GET_MODE (inner_dest)))	return 0;#endif      /* Check for the case where I3 modifies its output, as	 discussed above.  */      if ((inner_dest != dest	   && (reg_overlap_mentioned_p (i2dest, inner_dest)	       || (i1dest && reg_overlap_mentioned_p (i1dest, inner_dest))))	  /* This is the same test done in can_combine_p except that we	     allow a hard register with SMALL_REGISTER_CLASSES if SRC is a	     CALL operation. Moreover, we can't test all_adjacent; we don't	     have to, since this instruction will stay in place, thus we are	     not considering increasing the lifetime of INNER_DEST.	     Also, if this insn sets a function argument, combining it with	     something that might need a spill could clobber a previous	     function argument; the all_adjacent test in can_combine_p also	     checks this; here, we do a more specific test for this case.  */	     	  || (GET_CODE (inner_dest) == REG	      && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER	      && (! HARD_REGNO_MODE_OK (REGNO (inner_dest),					GET_MODE (inner_dest))		 || (SMALL_REGISTER_CLASSES && GET_CODE (src) != CALL		     && ! REG_USERVAR_P (inner_dest)		     && (FUNCTION_VALUE_REGNO_P (REGNO (inner_dest))			 || (FUNCTION_ARG_REGNO_P (REGNO (inner_dest))			     && i3 != 0			     && sets_function_arg_p (prev_nonnote_insn (i3)))))))	  || (i1_not_in_src && reg_overlap_mentioned_p (i1dest, src)))	return 0;      /* If DEST is used in I3, it is being killed in this insn,	 so record that for later. 	 Never add REG_DEAD notes for the FRAME_POINTER_REGNUM or the	 STACK_POINTER_REGNUM, since these are always considered to be	 live.  Similarly for ARG_POINTER_REGNUM if it is fixed.  */      if (pi3dest_killed && GET_CODE (dest) == REG	  && reg_referenced_p (dest, PATTERN (i3))	  && REGNO (dest) != FRAME_POINTER_REGNUM#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM	  && REGNO (dest) != HARD_FRAME_POINTER_REGNUM#endif#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM	  && (REGNO (dest) != ARG_POINTER_REGNUM	      || ! fixed_regs [REGNO (dest)])#endif	  && REGNO (dest) != STACK_POINTER_REGNUM)	{	  if (*pi3dest_killed)	    return 0;	  *pi3dest_killed = dest;	}    }  else if (GET_CODE (x) == PARALLEL)    {      int i;      for (i = 0; i < XVECLEN (x, 0); i++)	if (! combinable_i3pat (i3, &XVECEXP (x, 0, i), i2dest, i1dest,				i1_not_in_src, pi3dest_killed))	  return 0;    }  return 1;}/* Try to combine the insns I1 and I2 into I3.   Here I1 and I2 appear earlier than I3.   I1 can be zero; then we combine just I2 into I3.    It we are combining three insns and the resulting insn is not recognized,   try splitting it into two insns.  If that happens, I2 and I3 are retained   and I1 is pseudo-deleted by turning it into a NOTE.  Otherwise, I1 and I2   are pseudo-deleted.   Return 0 if the combination does not work.  Then nothing is changed.    If we did the combination, return the insn at which combine should   resume scanning.  */static rtxtry_combine (i3, i2, i1)     register rtx i3, i2, i1;{  /* New patterns for I3 and I3, respectively.  */  rtx newpat, newi2pat = 0;  /* Indicates need to preserve SET in I1 or I2 in I3 if it is not dead.  */  int added_sets_1, added_sets_2;  /* Total number of SETs to put into I3.  */  int total_sets;  /* Nonzero is I2's body now appears in I3.  */  int i2_is_used;  /* INSN_CODEs for new I3, new I2, and user of condition code.  */  int insn_code_number, i2_code_number, other_code_number;  /* Contains I3 if the destination of I3 is used in its source, which means     that the old life of I3 is being killed.  If that usage is placed into     I2 and not in I3, a REG_DEAD note must be made.  */  rtx i3dest_killed = 0;  /* SET_DEST and SET_SRC of I2 and I1.  */  rtx i2dest, i2src, i1dest = 0, i1src = 0;  /* PATTERN (I2), or a copy of it in certain cases.  */  rtx i2pat;  /* Indicates if I2DEST or I1DEST is in I2SRC or I1_SRC.  */  int i2dest_in_i2src = 0, i1dest_in_i1src = 0, i2dest_in_i1src = 0;  int i1_feeds_i3 = 0;  /* Notes that must be added to REG_NOTES in I3 and I2.  */  rtx new_i3_notes, new_i2_notes;  /* Notes that we substituted I3 into I2 instead of the normal case.  */  int i3_subst_into_i2 = 0;  /* Notes that I1, I2 or I3 is a MULT operation.  */  int have_mult = 0;  /* Number of clobbers of SCRATCH we had to add.  */  int i3_scratches = 0, i2_scratches = 0, other_scratches = 0;  int maxreg;  rtx temp;  register rtx link;  int i;  /* If any of I1, I2, and I3 isn't really an insn, we can't do anything.     This can occur when flow deletes an insn that it has merged into an     auto-increment address.  We also can't do anything if I3 has a     REG_LIBCALL note since we don't want to disrupt the contiguity of a     libcall.  */  if (GET_RTX_CLASS (GET_CODE (i3)) != 'i'      || GET_RTX_CLASS (GET_CODE (i2)) != 'i'      || (i1 && GET_RTX_CLASS (GET_CODE (i1)) != 'i')      || find_reg_note (i3, REG_LIBCALL, NULL_RTX))    return 0;  combine_attempts++;  undobuf.undos = undobuf.previous_undos = 0;  undobuf.other_insn = 0;  /* Save the current high-water-mark so we can free storage if we didn't     accept this combination.  */  undobuf.storage = (char *) oballoc (0);  /* Reset the hard register usage information.  */  CLEAR_HARD_REG_SET (newpat_used_regs);  /* If I1 and I2 both feed I3, they can be in any order.  To simplify the     code below, set I1 to be the earlier of the two insns.  */  if (i1 && INSN_CUID (i1) > INSN_CUID (i2))    temp = i1, i1 = i2, i2 = temp;  added_links_insn = 0;  /* First check for one important special-case that the code below will     not handle.  Namely, the case where I1 is zero, I2 has multiple sets,     and I3 is a SET whose SET_SRC is a SET_DEST in I2.  In that case,     we may be able to replace that destination with the destination of I3.     This occurs in the common code where we compute both a quotient and     remainder into a structure, in which case we want to do the computation     directly into the structure to avoid register-register copies.     We make very conservative checks below and only try to handle the     most common cases of this.  For example, we only handle the case     where I2 and I3 are adjacent to avoid making difficult register     usage tests.  */  if (i1 == 0 && GET_CODE (i3) == INSN && GET_CODE (PATTERN (i3)) == SET      && GET_CODE (SET_SRC (PATTERN (i3))) == REG      && REGNO (SET_SRC (PATTERN (i3))) >= FIRST_PSEUDO_REGISTER      && (! SMALL_REGISTER_CLASSES	  || (GET_CODE (SET_DEST (PATTERN (i3))) != REG	      || REGNO (SET_DEST (PATTERN (i3))) >= FIRST_PSEUDO_REGISTER	      || REG_USERVAR_P (SET_DEST (PATTERN (i3)))))      && find_reg_note (i3, REG_DEAD, SET_SRC (PATTERN (i3)))      && GET_CODE (PATTERN (i2)) == PARALLEL      && ! side_effects_p (SET_DEST (PATTERN (i3)))      /* If the dest of I3 is a ZERO_EXTRACT or STRICT_LOW_PART, the code	 below would need to check what is inside (and reg_overlap_mentioned_p	 doesn't support those codes anyway).  Don't allow those destinations;	 the resulting insn isn't likely to be recognized anyway.  */      && GET_CODE (SET_DEST (PATTERN (i3))) != ZERO_EXTRACT      && GET_CODE (SET_DEST (PATTERN (i3))) != STRICT_LOW_PART      && ! reg_overlap_mentioned_p (SET_SRC (PATTERN (i3)),				    SET_DEST (PATTERN (i3)))      && next_real_insn (i2) == i3)    {      rtx p2 = PATTERN (i2);      /* Make sure that the destination of I3,	 which we are going to substitute into one output of I2,	 is not used within another output of I2.  We must avoid making this:	 (parallel [(set (mem (reg 69)) ...)		    (set (reg 69) ...)])	 which is not well-defined as to order of actions.	 (Besides, reload can't handle output reloads for this.)	 The problem can also happen if the dest of I3 is a memory ref,	 if another dest in I2 is an indirect memory ref.  */      for (i = 0; i < XVECLEN (p2, 0); i++)	if ((GET_CODE (XVECEXP (p2, 0, i)) == SET	     || GET_CODE (XVECEXP (p2, 0, i)) == CLOBBER)	    && reg_overlap_mentioned_p (SET_DEST (PATTERN (i3)),					SET_DEST (XVECEXP (p2, 0, i))))	  break;      if (i == XVECLEN (p2, 0))	for (i = 0; i < XVECLEN (p2, 0); i++)	  if (SET_DEST (XVECEXP (p2, 0, i)) == SET_SRC (PATTERN (i3)))	    {	      combine_merges++;	      subst_insn = i3;	      subst_low_cuid = INSN_CUID (i2);	      added_sets_2 = added_sets_1 = 0;	      i2dest = SET_SRC (PATTERN (i3));	      /* Replace the dest in I2 with our dest and make the resulting		 insn the new pattern for I3.  Then skip to where we		 validate the pattern.  Everything was set up above.  */	      SUBST (SET_DEST (XVECEXP (p2, 0, i)), 		     SET_DEST (PATTERN (i3)));	      newpat = p2;	      i3_subst_into_i2 = 1;	      goto validate_replacement;	    }    }#ifndef HAVE_cc0  /* If we have no I1 and I2 looks like:	(parallel [(set (reg:CC X) (compare:CC OP (const_int 0)))		   (set Y OP)])     make up a dummy I1 that is	(set Y OP)     and change I2 to be        (set (reg:CC X) (compare:CC Y (const_int 0)))     (We can ignore any trailing CLOBBERs.)     This undoes a previous combination and allows us to match a branch-and-     decrement insn.  */  if (i1 == 0 && GET_CODE (PATTERN (i2)) == PARALLEL      && XVECLEN (PATTERN (i2), 0) >= 2      && GET_CODE (XVECEXP (PATTERN (i2), 0, 0)) == SET      && (GET_MODE_CLASS (GET_MODE (SET_DEST (XVECEXP (PATTERN (i2), 0, 0))))	  == MODE_CC)      && GET_CODE (SET_SRC (XVECEXP (PATTERN (i2), 0, 0))) == COMPARE      && XEXP (SET_SRC (XVECEXP (PATTERN (i2), 0, 0)), 1) == const0_rtx      && GET_CODE (XVECEXP (PATTERN (i2), 0, 1)) == SET      && GET_CODE (SET_DEST (XVECEXP (PATTERN (i2), 0, 1))) == REG      && rtx_equal_p (XEXP (SET_SRC (XVECEXP (PATTERN (i2), 0, 0)), 0),		      SET_SRC (XVECEXP (PATTERN (i2), 0, 1))))    {      for (i =  XVECLEN (PATTERN (i2), 0) - 1; i >= 2; i--)	if (GET_CODE (XVECEXP (PATTERN (i2), 0, i)) != CLOBBER)	  break;      if (i == 1)	{	  /* We make I1 with the same INSN_UID as I2.  This gives it

⌨️ 快捷键说明

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