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

📄 loop.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		  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);			      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);		      else			i1 = emit_insn_before (PATTERN (p), loop_start);		      REG_NOTES (i1) = REG_NOTES (p);		      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);      }}#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 (XEXP (x, 0) != reg)	abort ();      XEXP (x, 0) = addr;      return;    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	replace_call_address (XEXP (x, i), reg, addr);      if (fmt[i] == 'E')	{	  register int j;	  for (j = 0; j < XVECLEN (x, i); j++)	    replace_call_address (XVECEXP (x, i, j), reg, addr);	}    }}#endif/* Return the number of memory refs to addresses that vary   in the rtx X.  */static intcount_nonfixed_reads (x)     rtx x;{  register enum rtx_code code;  register int i;  register char *fmt;  int value;  if (x == 0)    return 0;  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 0;    case MEM:      return ((invariant_p (XEXP (x, 0)) != 1)	      + count_nonfixed_reads (XEXP (x, 0)));    }  value = 0;  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	value += count_nonfixed_reads (XEXP (x, i));      if (fmt[i] == 'E')	{	  register int j;	  for (j = 0; j < XVECLEN (x, i); j++)	    value += count_nonfixed_reads (XVECEXP (x, i, j));	}    }  return value;}#if 0/* P is an instruction that sets a register to the result of a ZERO_EXTEND.   Replace it with an instruction to load just the low bytes   if the machine supports such an instruction,   and insert above LOOP_START an instruction to clear the register.  */static voidconstant_high_bytes (p, loop_start)     rtx p, loop_start;{  register rtx new;  register int insn_code_number;  /* Try to change (SET (REG ...) (ZERO_EXTEND (..:B ...)))     to (SET (STRICT_LOW_PART (SUBREG:B (REG...))) ...).  */  new = gen_rtx (SET, VOIDmode,		 gen_rtx (STRICT_LOW_PART, VOIDmode,			  gen_rtx (SUBREG, GET_MODE (XEXP (SET_SRC (PATTERN (p)), 0)),				   SET_DEST (PATTERN (p)),				   0)),		 XEXP (SET_SRC (PATTERN (p)), 0));  insn_code_number = recog (new, p);  if (insn_code_number)    {      register int i;      /* Clear destination register before the loop.  */      emit_insn_before (gen_rtx (SET, VOIDmode,				 SET_DEST (PATTERN (p)),				 const0_rtx),			loop_star

⌨️ 快捷键说明

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