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

📄 jump.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		  /* If INSN uses CC0, we must not separate it from the		     insn that sets cc0.  */		  if (reg_mentioned_p (cc0_rtx, PATTERN (before)))		    before = prev_nonnote_insn (before);#endif		  emit_insns_before (seq, before);		  delete_insn (temp);		  next = NEXT_INSN (insn);		  delete_jump (insn);		  changed = 1;		  continue;		}	      else		end_sequence ();	    }	  /* If branches are expensive, convert	        if (foo) bar++;    to    bar += (foo != 0);	     and similarly for "bar--;" 	     INSN is the conditional branch around the arithmetic.  We set:	     TEMP is the arithmetic insn.	     TEMP1 is the SET doing the arithmetic.	     TEMP2 is the operand being incremented or decremented.	     TEMP3 to the condition being tested.	     TEMP4 to the earliest insn used to find the condition.  */	  if (BRANCH_COST >= 2	      && ! reload_completed	      && this_is_condjump && ! this_is_simplejump	      && (temp = next_nonnote_insn (insn)) != 0	      && (temp1 = single_set (temp)) != 0	      && (temp2 = SET_DEST (temp1),		  GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT)	      && GET_CODE (SET_SRC (temp1)) == PLUS	      && (XEXP (SET_SRC (temp1), 1) == const1_rtx		  || XEXP (SET_SRC (temp1), 1) == constm1_rtx)	      && rtx_equal_p (temp2, XEXP (SET_SRC (temp1), 0))	      /* INSN must either branch to the insn after TEMP or the insn		 after TEMP must branch to the same place as INSN.  */	      && (reallabelprev == temp		  || ((temp3 = next_active_insn (temp)) != 0		      && simplejump_p (temp3)		      && JUMP_LABEL (temp3) == JUMP_LABEL (insn)))	      && (temp3 = get_condition (insn, &temp4)) != 0	      /* We must be comparing objects whose modes imply the size.		 We could handle BLKmode if (1) emit_store_flag could		 and (2) we could find the size reliably.  */	      && GET_MODE (XEXP (temp3, 0)) != BLKmode	      && can_reverse_comparison_p (temp3, insn))	    {	      rtx temp6, target = 0, seq, init_insn = 0, init = temp2;	      enum rtx_code code = reverse_condition (GET_CODE (temp3));	      start_sequence ();	      /* It must be the case that TEMP2 is not modified in the range		 [TEMP4, INSN).  The one exception we make is if the insn		 before INSN sets TEMP2 to something which is also unchanged		 in that range.  In that case, we can move the initialization		 into our sequence.  */	      if ((temp5 = prev_active_insn (insn)) != 0		  && GET_CODE (temp5) == INSN		  && (temp6 = single_set (temp5)) != 0		  && rtx_equal_p (temp2, SET_DEST (temp6))		  && (CONSTANT_P (SET_SRC (temp6))		      || GET_CODE (SET_SRC (temp6)) == REG		      || GET_CODE (SET_SRC (temp6)) == SUBREG))		{		  emit_insn (PATTERN (temp5));		  init_insn = temp5;		  init = SET_SRC (temp6);		}	      if (CONSTANT_P (init)		  || ! reg_set_between_p (init, PREV_INSN (temp4), insn))		target = emit_store_flag (gen_reg_rtx (GET_MODE (temp2)), code,					  XEXP (temp3, 0), XEXP (temp3, 1),					  VOIDmode,					  (code == LTU || code == LEU					   || code == GTU || code == GEU), 1);	      /* If we can do the store-flag, do the addition or		 subtraction.  */	      if (target)		target = expand_binop (GET_MODE (temp2),				       (XEXP (SET_SRC (temp1), 1) == const1_rtx					? add_optab : sub_optab),				       temp2, target, temp2, OPTAB_WIDEN);	      if (target != 0)		{		  /* Put the result back in temp2 in case it isn't already.		     Then replace the jump, possible a CC0-setting insn in		     front of the jump, and TEMP, with the sequence we have		     made.  */		  if (target != temp2)		    emit_move_insn (temp2, target);		  seq = get_insns ();		  end_sequence ();		  emit_insns_before (seq, temp4);		  delete_insn (temp);		  if (init_insn)		    delete_insn (init_insn);		  next = NEXT_INSN (insn);#ifdef HAVE_cc0		  delete_insn (prev_nonnote_insn (insn));#endif		  delete_insn (insn);		  changed = 1;		  continue;		}	      else		end_sequence ();	    }	  /* Simplify   if (...) x = 1; else {...}  if (x) ...	     We recognize this case scanning backwards as well.	     TEMP is the assignment to x;	     TEMP1 is the label at the head of the second if.  */	  /* ?? This should call get_condition to find the values being	     compared, instead of looking for a COMPARE insn when HAVE_cc0	     is not defined.  This would allow it to work on the m88k.  */	  /* ?? This optimization is only safe before cse is run if HAVE_cc0	     is not defined and the condition is tested by a separate compare	     insn.  This is because the code below assumes that the result	     of the compare dies in the following branch.	     Not only that, but there might be other insns between the	     compare and branch whose results are live.  Those insns need	     to be executed.	     A way to fix this is to move the insns at JUMP_LABEL (insn)	     to before INSN.  If we are running before flow, they will	     be deleted if they aren't needed.   But this doesn't work	     well after flow.	     This is really a special-case of jump threading, anyway.  The	     right thing to do is to replace this and jump threading with	     much simpler code in cse.	     This code has been turned off in the non-cc0 case in the	     meantime.  */#ifdef HAVE_cc0	  else if (this_is_simplejump		   /* Safe to skip USE and CLOBBER insns here		      since they will not be deleted.  */		   && (temp = prev_active_insn (insn))		   && no_labels_between_p (temp, insn)		   && GET_CODE (temp) == INSN		   && GET_CODE (PATTERN (temp)) == SET		   && GET_CODE (SET_DEST (PATTERN (temp))) == REG		   && CONSTANT_P (SET_SRC (PATTERN (temp)))		   && (temp1 = next_active_insn (JUMP_LABEL (insn)))		   /* If we find that the next value tested is `x'		      (TEMP1 is the insn where this happens), win.  */		   && GET_CODE (temp1) == INSN		   && GET_CODE (PATTERN (temp1)) == SET#ifdef HAVE_cc0		   /* Does temp1 `tst' the value of x?  */		   && SET_SRC (PATTERN (temp1)) == SET_DEST (PATTERN (temp))		   && SET_DEST (PATTERN (temp1)) == cc0_rtx		   && (temp1 = next_nonnote_insn (temp1))#else		   /* Does temp1 compare the value of x against zero?  */		   && GET_CODE (SET_SRC (PATTERN (temp1))) == COMPARE		   && XEXP (SET_SRC (PATTERN (temp1)), 1) == const0_rtx		   && (XEXP (SET_SRC (PATTERN (temp1)), 0)		       == SET_DEST (PATTERN (temp)))		   && GET_CODE (SET_DEST (PATTERN (temp1))) == REG		   && (temp1 = find_next_ref (SET_DEST (PATTERN (temp1)), temp1))#endif		   && condjump_p (temp1))	    {	      /* Get the if_then_else from the condjump.  */	      rtx choice = SET_SRC (PATTERN (temp1));	      if (GET_CODE (choice) == IF_THEN_ELSE)		{		  enum rtx_code code = GET_CODE (XEXP (choice, 0));		  rtx val = SET_SRC (PATTERN (temp));		  rtx cond		    = simplify_relational_operation (code, GET_MODE (SET_DEST (PATTERN (temp))),						     val, const0_rtx);		  rtx ultimate;		  if (cond == const_true_rtx)		    ultimate = XEXP (choice, 1);		  else if (cond == const0_rtx)		    ultimate = XEXP (choice, 2);		  else		    ultimate = 0;		  if (ultimate == pc_rtx)		    ultimate = get_label_after (temp1);		  else if (ultimate && GET_CODE (ultimate) != RETURN)		    ultimate = XEXP (ultimate, 0);		  if (ultimate)		    changed |= redirect_jump (insn, ultimate);		}	    }#endif#if 0	  /* @@ This needs a bit of work before it will be right.	     Any type of comparison can be accepted for the first and	     second compare.  When rewriting the first jump, we must	     compute the what conditions can reach label3, and use the	     appropriate code.  We can not simply reverse/swap the code	     of the first jump.  In some cases, the second jump must be	     rewritten also.	     For example, 	     <  == converts to >  ==	     <  != converts to ==  >	     etc.	     If the code is written to only accept an '==' test for the second	     compare, then all that needs to be done is to swap the condition	     of the first branch.	     It is questionable whether we want this optimization anyways,	     since if the user wrote code like this because he/she knew that	     the jump to label1 is taken most of the time, then rewriting	     this gives slower code.  */	  /* @@ This should call get_condition to find the values being	     compared, instead of looking for a COMPARE insn when HAVE_cc0	     is not defined.  This would allow it to work on the m88k.  */	  /* @@ This optimization is only safe before cse is run if HAVE_cc0	     is not defined and the condition is tested by a separate compare	     insn.  This is because the code below assumes that the result	     of the compare dies in the following branch.  */	  /* Simplify  test a ~= b		       condjump label1;		       test a == b		       condjump label2;		       jump label3;		       label1:	     rewriting as		       test a ~~= b		       condjump label3		       test a == b		       condjump label2		       label1:	     where ~= is an inequality, e.g. >, and ~~= is the swapped	     inequality, e.g. <.	     We recognize this case scanning backwards.	     TEMP is the conditional jump to `label2';	     TEMP1 is the test for `a == b';	     TEMP2 is the conditional jump to `label1';	     TEMP3 is the test for `a ~= b'.  */	  else if (this_is_simplejump		   && (temp = prev_active_insn (insn))		   && no_labels_between_p (temp, insn)		   && condjump_p (temp)		   && (temp1 = prev_active_insn (temp))		   && no_labels_between_p (temp1, temp)		   && GET_CODE (temp1) == INSN		   && GET_CODE (PATTERN (temp1)) == SET#ifdef HAVE_cc0		   && sets_cc0_p (PATTERN (temp1)) == 1#else		   && GET_CODE (SET_SRC (PATTERN (temp1))) == COMPARE		   && GET_CODE (SET_DEST (PATTERN (temp1))) == REG		   && (temp == find_next_ref (SET_DEST (PATTERN (temp1)), temp1))#endif		   && (temp2 = prev_active_insn (temp1))		   && no_labels_between_p (temp2, temp1)		   && condjump_p (temp2)		   && JUMP_LABEL (temp2) == next_nonnote_insn (NEXT_INSN (insn))		   && (temp3 = prev_active_insn (temp2))		   && no_labels_between_p (temp3, temp2)		   && GET_CODE (PATTERN (temp3)) == SET		   && rtx_equal_p (SET_DEST (PATTERN (temp3)),				   SET_DEST (PATTERN (temp1)))		   && rtx_equal_p (SET_SRC (PATTERN (temp1)),				   SET_SRC (PATTERN (temp3)))		   && ! inequality_comparisons_p (PATTERN (temp))		   && inequality_comparisons_p (PATTERN (temp2)))	    {	      rtx fallthrough_label = JUMP_LABEL (temp2);	      ++LABEL_NUSES (fallthrough_label);	      if (swap_jump (temp2, JUMP_LABEL (insn)))		{		  delete_insn (insn);		  changed = 1;		}	      if (--LABEL_NUSES (fallthrough_label) == 0)		delete_insn (fallthrough_label);	    }#endif	  /* Simplify  if (...) {... x = 1;} if (x) ...	     We recognize this case backwards.	     TEMP is the test of `x';	     TEMP1 is the assignment to `x' at the end of the	     previous statement.  */	  /* @@ This should call get_condition to find the values being	     compared, instead of looking for a COMPARE insn when HAVE_cc0	     is not defined.  This would allow it to work on the m88k.  */	  /* @@ This optimization is only safe before cse is run if HAVE_cc0	     is not defined and the condition is tested by a separate compare	     insn.  This is because the code below assumes that the result	     of the compare dies in the following branch.  */	  /* ??? This has to be turned off.  The problem is that the	     unconditional jump might indirectly end up branching to the	     label between TEMP1 and TEMP.  We can't detect this, in general,	     since it may become a jump to there after further optimizations.	     If that jump is done, it will be deleted, so we will retry	     this optimization in the next pass, thus an infinite loop.	     The present code prevents this by putting the jump after the	     label, but this is not logically correct.  */#if 0	  else if (this_is_condjump		   /* Safe to skip USE and CLOBBER insns here		      since they will not be deleted.  */		   && (temp = prev_active_insn (insn))		   && no_labels_between_p (temp, insn)		   && GET_CODE (temp) == INSN		   && GET_CODE (PATTERN (temp)) == SET#ifdef HAVE_cc0		   && sets_cc0_p (PATTERN (temp)) == 1		   && GET_CODE (SET_SRC (PATTERN (temp))) == REG#else		   /* Temp must be a compare insn, we can not accept a register		      to register move here, since it may not be simply a		      tst insn.  */		   && GET_CODE (SET_SRC (PATTERN (temp))) == COMPARE		   && XEXP (SET_SRC (PATTERN (temp)), 1) == const0_rtx		   && GET_CODE (XEXP (SET_SRC (PATTERN (temp)), 0)) == REG		   && GET_CODE (SET_DEST (PATTERN (temp))) == REG		   && insn == find_next_ref (SET_DEST (PATTERN (temp)), temp)#endif		   /* May skip USE or CLOBBER insns here		      for checking for opportunity, since we		      take care of them later.  */		   && (temp1 = prev_active_insn (temp))		   && GET_CODE (temp1) == INSN		   && GET_CODE (PATTERN (temp1)) == SET#ifdef HAVE_cc0		   && SET_SRC (PATTERN (temp)) == SET_DEST (PATTERN (temp1))#else		   && (XEXP (SET_SRC (PATTERN (temp)), 0)		       == SET_DEST (PATTERN (temp1)))#endif		   && CONSTANT_P (SET_SRC (PATTERN (temp1)))		   /* If this isn't true, cse will do the job.  */		   && ! no_labels_between_p (temp1, temp))	    {	      /* Get the if_then_else from the condjump.  */	      rtx choice = SET_SRC (PATTERN (insn));	      if (GET_CODE (choice) == IF_THEN_ELSE		  && (GET_CODE (XEXP (choice, 0)) == EQ		      || GET_CODE (XEXP (choice, 0)) == NE))		{		  int want_nonzero = (GET_CODE (XEXP (choice, 0)) == NE);		  rtx last_insn;		  rtx ultimate;		  rtx p;		  /* Get the place that condjump will jump to		     if it is reached from here.  */

⌨️ 快捷键说明

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