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

📄 unroll.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	  if (code == IOR)	    increment = GEN_INT (INTVAL (increment) | INTVAL (second_part));	  else if (code == PLUS)	    increment = GEN_INT (INTVAL (increment) + INTVAL (second_part));	  else	    increment = GEN_INT (INTVAL (increment) << INTVAL (second_part));	}      if (GET_CODE (increment) != CONST_INT)	abort ();		        /* The insn loading the constant into a register is no longer needed,	 so delete it.  */      delete_insn (get_last_insn ());    }  if (increment_total)    increment_total = GEN_INT (INTVAL (increment_total) + INTVAL (increment));  else    increment_total = increment;  /* Check that the source register is the same as the register we expected     to see as the source.  If not, something is seriously wrong.  */  if (GET_CODE (XEXP (SET_SRC (pattern), 0)) != REG      || REGNO (XEXP (SET_SRC (pattern), 0)) != regno)    {      /* Some machines (e.g. the romp), may emit two add instructions for	 certain constants, so lets try looking for another add immediately	 before this one if we have only seen one add insn so far.  */      if (tries == 0)	{	  tries++;	  src_insn = PREV_INSN (src_insn);	  pattern = PATTERN (src_insn);	  delete_insn (get_last_insn ());	  goto retry;	}      abort ();    }  return increment_total;}/* Copy REG_NOTES, except for insn references, because not all insn_map   entries are valid yet.  We do need to copy registers now though, because   the reg_map entries can change during copying.  */static rtxinitial_reg_note_copy (notes, map)     rtx notes;     struct inline_remap *map;{  rtx copy;  if (notes == 0)    return 0;  copy = rtx_alloc (GET_CODE (notes));  PUT_MODE (copy, GET_MODE (notes));  if (GET_CODE (notes) == EXPR_LIST)    XEXP (copy, 0) = copy_rtx_and_substitute (XEXP (notes, 0), map);  else if (GET_CODE (notes) == INSN_LIST)    /* Don't substitute for these yet.  */    XEXP (copy, 0) = XEXP (notes, 0);  else    abort ();  XEXP (copy, 1) = initial_reg_note_copy (XEXP (notes, 1), map);  return copy;}/* Fixup insn references in copied REG_NOTES.  */static voidfinal_reg_note_copy (notes, map)     rtx notes;     struct inline_remap *map;{  rtx note;  for (note = notes; note; note = XEXP (note, 1))    if (GET_CODE (note) == INSN_LIST)      XEXP (note, 0) = map->insn_map[INSN_UID (XEXP (note, 0))];}/* Copy each instruction in the loop, substituting from map as appropriate.   This is very similar to a loop in expand_inline_function.  */  static voidcopy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,		unroll_type, start_label, loop_end, insert_before,		copy_notes_from)     rtx copy_start, copy_end;     struct inline_remap *map;     rtx exit_label;     int last_iteration;     enum unroll_types unroll_type;     rtx start_label, loop_end, insert_before, copy_notes_from;{  rtx insn, pattern;  rtx tem, copy;  int dest_reg_was_split, i;  rtx cc0_insn = 0;  rtx final_label = 0;  rtx giv_inc, giv_dest_reg, giv_src_reg;  /* If this isn't the last iteration, then map any references to the     start_label to final_label.  Final label will then be emitted immediately     after the end of this loop body if it was ever used.     If this is the last iteration, then map references to the start_label     to itself.  */  if (! last_iteration)    {      final_label = gen_label_rtx ();      map->label_map[CODE_LABEL_NUMBER (start_label)] = final_label;    }  else    map->label_map[CODE_LABEL_NUMBER (start_label)] = start_label;  start_sequence ();    insn = copy_start;  do    {      insn = NEXT_INSN (insn);            map->orig_asm_operands_vector = 0;            switch (GET_CODE (insn))	{	case INSN:	  pattern = PATTERN (insn);	  copy = 0;	  giv_inc = 0;	  	  /* Check to see if this is a giv that has been combined with	     some split address givs.  (Combined in the sense that 	     `combine_givs' in loop.c has put two givs in the same register.)	     In this case, we must search all givs based on the same biv to	     find the address givs.  Then split the address givs.	     Do this before splitting the giv, since that may map the	     SET_DEST to a new register.  */	  	  if (GET_CODE (pattern) == SET	      && GET_CODE (SET_DEST (pattern)) == REG	      && addr_combined_regs[REGNO (SET_DEST (pattern))])	    {	      struct iv_class *bl;	      struct induction *v, *tv;	      int regno = REGNO (SET_DEST (pattern));	      	      v = addr_combined_regs[REGNO (SET_DEST (pattern))];	      bl = reg_biv_class[REGNO (v->src_reg)];	      	      /* Although the giv_inc amount is not needed here, we must call		 calculate_giv_inc here since it might try to delete the		 last insn emitted.  If we wait until later to call it,		 we might accidentally delete insns generated immediately		 below by emit_unrolled_add.  */	      giv_inc = calculate_giv_inc (pattern, insn, regno);	      /* Now find all address giv's that were combined with this		 giv 'v'.  */	      for (tv = bl->giv; tv; tv = tv->next_iv)		if (tv->giv_type == DEST_ADDR && tv->same == v)		  {		    int this_giv_inc;		    /* If this DEST_ADDR giv was not split, then ignore it.  */		    if (*tv->location != tv->dest_reg)		      continue;		    /* Scale this_giv_inc if the multiplicative factors of		       the two givs are different.  */		    this_giv_inc = INTVAL (giv_inc);		    if (tv->mult_val != v->mult_val)		      this_giv_inc = (this_giv_inc / INTVAL (v->mult_val)				      * INTVAL (tv->mult_val));		       		    tv->dest_reg = plus_constant (tv->dest_reg, this_giv_inc);		    *tv->location = tv->dest_reg;		    		    if (last_iteration && unroll_type != UNROLL_COMPLETELY)		      {			/* Must emit an insn to increment the split address			   giv.  Add in the const_adjust field in case there			   was a constant eliminated from the address.  */			rtx value, dest_reg;						/* tv->dest_reg will be either a bare register,			   or else a register plus a constant.  */			if (GET_CODE (tv->dest_reg) == REG)			  dest_reg = tv->dest_reg;			else			  dest_reg = XEXP (tv->dest_reg, 0);						/* Check for shared address givs, and avoid			   incrementing the shared pseudo reg more than			   once.  */			if (! tv->same_insn)			  {			    /* tv->dest_reg may actually be a (PLUS (REG)			       (CONST)) here, so we must call plus_constant			       to add the const_adjust amount before calling			       emit_unrolled_add below.  */			    value = plus_constant (tv->dest_reg,						   tv->const_adjust);			    /* The constant could be too large for an add			       immediate, so can't directly emit an insn			       here.  */			    emit_unrolled_add (dest_reg, XEXP (value, 0),					       XEXP (value, 1));			  }						/* Reset the giv to be just the register again, in case			   it is used after the set we have just emitted.			   We must subtract the const_adjust factor added in			   above.  */			tv->dest_reg = plus_constant (dest_reg,						      - tv->const_adjust);			*tv->location = tv->dest_reg;		      }		  }	    }	  	  /* If this is a setting of a splittable variable, then determine	     how to split the variable, create a new set based on this split,	     and set up the reg_map so that later uses of the variable will	     use the new split variable.  */	  	  dest_reg_was_split = 0;	  	  if (GET_CODE (pattern) == SET	      && GET_CODE (SET_DEST (pattern)) == REG	      && splittable_regs[REGNO (SET_DEST (pattern))])	    {	      int regno = REGNO (SET_DEST (pattern));	      	      dest_reg_was_split = 1;	      	      /* Compute the increment value for the giv, if it wasn't		 already computed above.  */	      if (giv_inc == 0)		giv_inc = calculate_giv_inc (pattern, insn, regno);	      giv_dest_reg = SET_DEST (pattern);	      giv_src_reg = SET_DEST (pattern);	      if (unroll_type == UNROLL_COMPLETELY)		{		  /* Completely unrolling the loop.  Set the induction		     variable to a known constant value.  */		  		  /* The value in splittable_regs may be an invariant		     value, so we must use plus_constant here.  */		  splittable_regs[regno]		    = plus_constant (splittable_regs[regno], INTVAL (giv_inc));		  if (GET_CODE (splittable_regs[regno]) == PLUS)		    {		      giv_src_reg = XEXP (splittable_regs[regno], 0);		      giv_inc = XEXP (splittable_regs[regno], 1);		    }		  else		    {		      /* The splittable_regs value must be a REG or a			 CONST_INT, so put the entire value in the giv_src_reg			 variable.  */		      giv_src_reg = splittable_regs[regno];		      giv_inc = const0_rtx;		    }		}	      else		{		  /* Partially unrolling loop.  Create a new pseudo		     register for the iteration variable, and set it to		     be a constant plus the original register.  Except		     on the last iteration, when the result has to		     go back into the original iteration var register.  */		  		  /* Handle bivs which must be mapped to a new register		     when split.  This happens for bivs which need their		     final value set before loop entry.  The new register		     for the biv was stored in the biv's first struct		     induction entry by find_splittable_regs.  */		  if (regno < max_reg_before_loop		      && reg_iv_type[regno] == BASIC_INDUCT)		    {		      giv_src_reg = reg_biv_class[regno]->biv->src_reg;		      giv_dest_reg = giv_src_reg;		    }		  #if 0		  /* If non-reduced/final-value givs were split, then		     this would have to remap those givs also.  See		     find_splittable_regs.  */#endif		  		  splittable_regs[regno]		    = GEN_INT (INTVAL (giv_inc)			       + INTVAL (splittable_regs[regno]));		  giv_inc = splittable_regs[regno];		  		  /* Now split the induction variable by changing the dest		     of this insn to a new register, and setting its		     reg_map entry to point to this new register.		     If this is the last iteration, and this is the last insn		     that will update the iv, then reuse the original dest,		     to ensure that the iv will have the proper value when		     the loop exits or repeats.		     Using splittable_regs_updates here like this is safe,		     because it can only be greater than one if all		     instructions modifying the iv are always executed in		     order.  */		  if (! last_iteration		      || (splittable_regs_updates[regno]-- != 1))		    {		      tem = gen_reg_rtx (GET_MODE (giv_src_reg));		      giv_dest_reg = tem;		      map->reg_map[regno] = tem;		    }		  else		    map->reg_map[regno] = giv_src_reg;		}	      /* The constant being added could be too large for an add		 immediate, so can't directly emit an insn here.  */	      emit_unrolled_add (giv_dest_reg, giv_src_reg, giv_inc);	      copy = get_last_insn ();	      pattern = PATTERN (copy);	    }	  else	    {	      pattern = copy_rtx_and_substitute (pattern, map);	      copy = emit_insn (pattern);	    }	  REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);	  #ifdef HAVE_cc0	  /* If this insn is setting CC0, it may need to look at	     the insn that uses CC0 to see what type of insn it is.	     In that case, the call to recog via validate_change will	     fail.  So don't substitute constants here.  Instead,	     do it when we emit the following insn.	     For example, see the pyr.md file.  That machine has signed and	     unsigned compares.  The compare patterns must check the	     following branch insn to see which what kind of compare to	     emit.	     If the previous insn set CC0, substitute constants on it as	     well.  */	  if (sets_cc0_p (PATTERN (copy)) != 0)	   

⌨️ 快捷键说明

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