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

📄 unroll.c

📁 GUN开源阻止下的编译器GCC
💻 C
📖 第 1 页 / 共 5 页
字号:
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 = INTVAL (giv_inc);		    /* Scale this_giv_inc if the multiplicative factors of		       the two givs are different.  */		    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)	    cc0_insn = copy;	  else	    {	      if (cc0_insn)		try_constants (cc0_insn, map);	      cc0_insn = 0;	      try_constants (copy, map);	    }#else	  try_constants (copy, map);#endif	  /* Make split induction variable constants `permanent' since we	     know there are no backward branches across iteration variable	     settings which would invalidate this.  */	  if (dest_reg_was_split)	    {	      int regno = REGNO (SET_DEST (pattern));	      if (regno < map->const_equiv_map_size		  && map->const_age_map[regno] == map->const_age)		map->const_age_map[regno] = -1;	    }	  break;	  	case JUMP_INSN:	  pattern = copy_rtx_and_substitute (PATTERN (insn), map);	  copy = emit_jump_insn (pattern);	  REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);	  if (JUMP_LABEL (insn) == start_label && insn == copy_end	      && ! last_iteration)	    {	      /* This is a branch to the beginning of the loop; this is the		 last insn being copied; and this is not the last iteration.		 In this case, we want to change the original fall through		 case to be a branch past the end of the loop, and the		 original jump label case to fall_through.  */	      if (invert_exp (pattern, copy))		{		  if (! redirect_exp (&pattern,				      map->label_map[CODE_LABEL_NUMBER						     (JUMP_LABEL (insn))],				      exit_label, copy))		    abort ();		}	      else		{		  rtx jmp;		  rtx lab = gen_label_rtx ();		  /* Can't do it by reversing the jump (probably because we		     couldn't reverse the conditions), so emit a new		     jump_insn after COPY, and redirect the jump around		     that.  */		  jmp = emit_jump_insn_after (gen_jump (exit_label), copy);		  jmp = emit_barrier_after (jmp);		  emit_label_after (lab, jmp);		  LABEL_NUSES (lab) = 0;		  if (! redirect_exp (&pattern,				      map->label_map[CODE_LABEL_NUMBER						     (JUMP_LABEL (insn))],				      lab, copy))		    abort ();		}	    }	  #ifdef HAVE_cc0	  if (cc0_insn)	    try_constants (cc0_insn, map);	  cc0_insn = 0;#endif	  try_constants (copy, map);	  /* Set the jump label of COPY correctly to avoid problems with	     later passes of unroll_loop, if INSN had jump label set.  */	  if (JUMP_LABEL (insn))	    {	      rtx label = 0;	      /* Can't use the label_map for every insn, since this may be		 the backward branch, and hence the label was not mapped.  */	      if (GET_CODE (pattern) == SET)		{		  tem = SET_SRC (pattern);		  if (GET_CODE (tem) == LABEL_REF)		    label = XEXP (tem, 0);		  else if (GET_CODE (tem) == IF_THEN_ELSE)		    {		      if (XEXP (tem, 1) != pc_rtx)			label = XEXP (XEXP (tem, 1), 0);		   

⌨️ 快捷键说明

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