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

📄 loop.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
	      rtx first;	      /* Now move the insns that set the reg.  */	      if (m->partial && m->match)		{		  rtx newpat, i1;		  rtx r1, r2;		  /* Find the end of this chain of matching regs.		     Thus, we load each reg in the chain from that one reg.		     And that reg is loaded with 0 directly,		     since it has ->match == 0.  */		  for (m1 = m; m1->match; m1 = m1->match);		  newpat = gen_move_insn (SET_DEST (PATTERN (m->insn)),					  SET_DEST (PATTERN (m1->insn)));		  i1 = emit_insn_before (newpat, loop_start);		  /* Mark the moved, invariant reg as being allowed to		     share a hard reg with the other matching invariant.  */		  REG_NOTES (i1) = REG_NOTES (m->insn);		  r1 = SET_DEST (PATTERN (m->insn));		  r2 = SET_DEST (PATTERN (m1->insn));		  regs_may_share = gen_rtx (EXPR_LIST, VOIDmode, r1,					    gen_rtx (EXPR_LIST, VOIDmode, r2,						     regs_may_share));		  delete_insn (m->insn);		  if (new_start == 0)		    new_start = i1;		  if (loop_dump_stream)		    fprintf (loop_dump_stream, " moved to %d", INSN_UID (i1));		}	      /* If we are to re-generate the item being moved with a		 new move insn, first delete what we have and then emit		 the move insn before the loop.  */	      else if (m->move_insn)		{		  rtx i1, temp;		  for (count = m->consec; count >= 0; count--)		    {		      /* If this is the first insn of a library call sequence,			 skip to the end.  */		      if (GET_CODE (p) != NOTE			  && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))			p = XEXP (temp, 0);		      /* If this is the last insn of a libcall sequence, then			 delete every insn in the sequence except the last.			 The last insn is handled in the normal manner.  */		      if (GET_CODE (p) != NOTE			  && (temp = find_reg_note (p, REG_RETVAL, NULL_RTX)))			{			  temp = XEXP (temp, 0);			  while (temp != p)			    temp = delete_insn (temp);			}		      p = delete_insn (p);		      while (p && GET_CODE (p) == NOTE)			p = NEXT_INSN (p);		    }		  start_sequence ();		  emit_move_insn (m->set_dest, m->set_src);		  temp = get_insns ();		  end_sequence ();		  add_label_notes (m->set_src, temp);		  i1 = emit_insns_before (temp, loop_start);		  if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))		    REG_NOTES (i1)		      = gen_rtx (EXPR_LIST,				 m->is_equiv ? REG_EQUIV : REG_EQUAL,				 m->set_src, REG_NOTES (i1));		  if (loop_dump_stream)		    fprintf (loop_dump_stream, " moved to %d", INSN_UID (i1));		  /* The more regs we move, the less we like moving them.  */		  threshold -= 3;		}	      else		{		  for (count = m->consec; count >= 0; count--)		    {		      rtx i1, temp;		      /* If first insn of libcall sequence, skip to end. */		      /* Do this at start of loop, since p is guaranteed to 			 be an insn here.  */		      if (GET_CODE (p) != NOTE			  && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))			p = XEXP (temp, 0);		      /* If last insn of libcall sequence, move all			 insns except the last before the loop.  The last			 insn is handled in the normal manner.  */		      if (GET_CODE (p) != NOTE			  && (temp = find_reg_note (p, REG_RETVAL, NULL_RTX)))			{			  rtx fn_address = 0;			  rtx fn_reg = 0;			  rtx fn_address_insn = 0;			  first = 0;			  for (temp = XEXP (temp, 0); temp != p;			       temp = NEXT_INSN (temp))			    {			      rtx body;			      rtx n;			      rtx next;			      if (GET_CODE (temp) == NOTE)				continue;			      body = PATTERN (temp);			      /* Find the next insn after TEMP,				 not counting USE or NOTE insns.  */			      for (next = NEXT_INSN (temp); next != p;				   next = NEXT_INSN (next))				if (! (GET_CODE (next) == INSN				       && GET_CODE (PATTERN (next)) == USE)				    && GET_CODE (next) != NOTE)				  break;			      			      /* If that is the call, this may be the insn				 that loads the function address.				 Extract the function address from the insn				 that loads it into a register.				 If this insn was cse'd, we get incorrect code.				 So emit a new move insn that copies the				 function address into the register that the				 call insn will use.  flow.c will delete any				 redundant stores that we have created.  */			      if (GET_CODE (next) == CALL_INSN				  && GET_CODE (body) == SET				  && GET_CODE (SET_DEST (body)) == REG				  && (n = find_reg_note (temp, REG_EQUAL,							 NULL_RTX)))				{				  fn_reg = SET_SRC (body);				  if (GET_CODE (fn_reg) != REG)				    fn_reg = SET_DEST (body);				  fn_address = XEXP (n, 0);				  fn_address_insn = temp;				}			      /* We have the call insn.				 If it uses the register we suspect it might,				 load it with the correct address directly.  */			      if (GET_CODE (temp) == CALL_INSN				  && fn_address != 0				  && reg_referenced_p (fn_reg, body))				emit_insn_after (gen_move_insn (fn_reg,								fn_address),						 fn_address_insn);			      if (GET_CODE (temp) == CALL_INSN)				{				  i1 = emit_call_insn_before (body, loop_start);				  /* Because the USAGE information potentially				     contains objects other than hard registers				     we need to copy it.  */				  if (CALL_INSN_FUNCTION_USAGE (temp))				    CALL_INSN_FUNCTION_USAGE (i1) =				      copy_rtx (CALL_INSN_FUNCTION_USAGE (temp));				}			      else				i1 = emit_insn_before (body, loop_start);			      if (first == 0)				first = i1;			      if (temp == fn_address_insn)				fn_address_insn = i1;			      REG_NOTES (i1) = REG_NOTES (temp);			      delete_insn (temp);			    }			}		      if (m->savemode != VOIDmode)			{			  /* P sets REG to zero; but we should clear only			     the bits that are not covered by the mode			     m->savemode.  */			  rtx reg = m->set_dest;			  rtx sequence;			  rtx tem;		      			  start_sequence ();			  tem = expand_binop			    (GET_MODE (reg), and_optab, reg,			     GEN_INT ((((HOST_WIDE_INT) 1					<< GET_MODE_BITSIZE (m->savemode)))				      - 1),			     reg, 1, OPTAB_LIB_WIDEN);			  if (tem == 0)			    abort ();			  if (tem != reg)			    emit_move_insn (reg, tem);			  sequence = gen_sequence ();			  end_sequence ();			  i1 = emit_insn_before (sequence, loop_start);			}		      else if (GET_CODE (p) == CALL_INSN)			{			  i1 = emit_call_insn_before (PATTERN (p), loop_start);			  /* Because the USAGE information potentially			     contains objects other than hard registers			     we need to copy it.  */			  if (CALL_INSN_FUNCTION_USAGE (p))			    CALL_INSN_FUNCTION_USAGE (i1) =			      copy_rtx (CALL_INSN_FUNCTION_USAGE (p));			}		      else			i1 = emit_insn_before (PATTERN (p), loop_start);		      REG_NOTES (i1) = REG_NOTES (p);		      /* If there is a REG_EQUAL note present whose value is			 not loop invariant, then delete it, since it may			 cause problems with later optimization passes.			 It is possible for cse to create such notes			 like this as a result of record_jump_cond.  */		      		      if ((temp = find_reg_note (i1, REG_EQUAL, NULL_RTX))			  && ! invariant_p (XEXP (temp, 0)))			remove_note (i1, temp);		      if (new_start == 0)			new_start = i1;		      if (loop_dump_stream)			fprintf (loop_dump_stream, " moved to %d",				 INSN_UID (i1));#if 0		      /* This isn't needed because REG_NOTES is copied			 below and is wrong since P might be a PARALLEL.  */		      if (REG_NOTES (i1) == 0			  && ! m->partial /* But not if it's a zero-extend clr. */			  && ! m->global /* and not if used outside the loop					    (since it might get set outside).  */			  && CONSTANT_P (SET_SRC (PATTERN (p))))			REG_NOTES (i1)			  = gen_rtx (EXPR_LIST, REG_EQUAL,				     SET_SRC (PATTERN (p)), REG_NOTES (i1));#endif		      /* If library call, now fix the REG_NOTES that contain			 insn pointers, namely REG_LIBCALL on FIRST			 and REG_RETVAL on I1.  */		      if (temp = find_reg_note (i1, REG_RETVAL, NULL_RTX))			{			  XEXP (temp, 0) = first;			  temp = find_reg_note (first, REG_LIBCALL, NULL_RTX);			  XEXP (temp, 0) = i1;			}		      delete_insn (p);		      do p = NEXT_INSN (p);		      while (p && GET_CODE (p) == NOTE);		    }		  /* The more regs we move, the less we like moving them.  */		  threshold -= 3;		}	      /* Any other movable that loads the same register		 MUST be moved.  */	      already_moved[regno] = 1;	      /* This reg has been moved out of one loop.  */	      moved_once[regno] = 1;	      /* The reg set here is now invariant.  */	      if (! m->partial)		n_times_set[regno] = 0;	      m->done = 1;	      /* Change the length-of-life info for the register		 to say it lives at least the full length of this loop.		 This will help guide optimizations in outer loops.  */	      if (uid_luid[regno_first_uid[regno]] > INSN_LUID (loop_start))		/* This is the old insn before all the moved insns.		   We can't use the moved insn because it is out of range		   in uid_luid.  Only the old insns have luids.  */		regno_first_uid[regno] = INSN_UID (loop_start);	      if (uid_luid[regno_last_uid[regno]] < INSN_LUID (end))		regno_last_uid[regno] = INSN_UID (end);	      /* Combine with this moved insn any other matching movables.  */	      if (! m->partial)		for (m1 = movables; m1; m1 = m1->next)		  if (m1->match == m)		    {		      rtx temp;		      /* Schedule the reg loaded by M1			 for replacement so that shares the reg of M.			 If the modes differ (only possible in restricted			 circumstances, make a SUBREG.  */		      if (GET_MODE (m->set_dest) == GET_MODE (m1->set_dest))			reg_map[m1->regno] = m->set_dest;		      else			reg_map[m1->regno]			  = gen_lowpart_common (GET_MODE (m1->set_dest),						m->set_dest);		    		      /* Get rid of the matching insn			 and prevent further processing of it.  */		      m1->done = 1;		      /* if library call, delete all insn except last, which			 is deleted below */		      if (temp = find_reg_note (m1->insn, REG_RETVAL,						NULL_RTX))			{			  for (temp = XEXP (temp, 0); temp != m1->insn;			       temp = NEXT_INSN (temp))			    delete_insn (temp);			}		      delete_insn (m1->insn);		      /* Any other movable that loads the same register			 MUST be moved.  */		      already_moved[m1->regno] = 1;		      /* The reg merged here is now invariant,			 if the reg it matches is invariant.  */		      if (! m->partial)			n_times_set[m1->regno] = 0;		    }	    }	  else if (loop_dump_stream)	    fprintf (loop_dump_stream, "not desirable");	}      else if (loop_dump_stream && !m->match)	fprintf (loop_dump_stream, "not safe");      if (loop_dump_stream)	fprintf (loop_dump_stream, "\n");    }  if (new_start == 0)    new_start = loop_start;  /* Go through all the instructions in the loop, making     all the register substitutions scheduled in REG_MAP.  */  for (p = new_start; p != end; p = NEXT_INSN (p))    if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN	|| GET_CODE (p) == CALL_INSN)      {	replace_regs (PATTERN (p), reg_map, nregs, 0);	replace_regs (REG_NOTES (p), reg_map, nregs, 0);	INSN_CODE (p) = -1;      }}#if 0/* Scan X and replace the address of any MEM in it with ADDR.   REG is the address that MEM should have before the replacement.  */static voidreplace_call_address (x, reg, addr)     rtx x, reg, addr;{  register enum rtx_code code;  register int i;  register char *fmt;  if (x == 0)    return;  code = GET_CODE (x);  switch (code)    {    case PC:    case CC0:    case CONST_INT:    case CONST_DOUBLE:    case CONST:    case SYMBOL_REF:    case LABEL_REF:    case REG:      return;    case SET:      /* Short cut for very common case.  */      replace_call_address (XEXP (x, 1), reg, addr);      return;    case CALL:      /* Short cut for very common case.  */      replace_call_address (XEXP (x, 0), reg, addr);      return;    case MEM:      /* If this MEM uses a reg other than the one we expected,	 something is wrong.  */      if (X

⌨️ 快捷键说明

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