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

📄 pa.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    }  /* Handle (plus (mult (a) (shadd_constant)) (b)).  */  if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT      && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))      && (OBJECT_P (XEXP (x, 1))	  || GET_CODE (XEXP (x, 1)) == SUBREG)      && GET_CODE (XEXP (x, 1)) != CONST)    {      int val = INTVAL (XEXP (XEXP (x, 0), 1));      rtx reg1, reg2;      reg1 = XEXP (x, 1);      if (GET_CODE (reg1) != REG)	reg1 = force_reg (Pmode, force_operand (reg1, 0));      reg2 = XEXP (XEXP (x, 0), 0);      if (GET_CODE (reg2) != REG)        reg2 = force_reg (Pmode, force_operand (reg2, 0));      return force_reg (Pmode, gen_rtx_PLUS (Pmode,					     gen_rtx_MULT (Pmode,							   reg2,							   GEN_INT (val)),					     reg1));    }  /* Similarly for (plus (plus (mult (a) (shadd_constant)) (b)) (c)).     Only do so for floating point modes since this is more speculative     and we lose if it's an integer store.  */  if (GET_CODE (x) == PLUS      && GET_CODE (XEXP (x, 0)) == PLUS      && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT      && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT      && shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))      && (mode == SFmode || mode == DFmode))    {      /* First, try and figure out what to use as a base register.  */      rtx reg1, reg2, base, idx, orig_base;      reg1 = XEXP (XEXP (x, 0), 1);      reg2 = XEXP (x, 1);      base = NULL_RTX;      idx = NULL_RTX;      /* Make sure they're both regs.  If one was a SYMBOL_REF [+ const],	 then emit_move_sequence will turn on REG_POINTER so we'll know	 it's a base register below.  */      if (GET_CODE (reg1) != REG)	reg1 = force_reg (Pmode, force_operand (reg1, 0));      if (GET_CODE (reg2) != REG)	reg2 = force_reg (Pmode, force_operand (reg2, 0));      /* Figure out what the base and index are.  */      if (GET_CODE (reg1) == REG	  && REG_POINTER (reg1))	{	  base = reg1;	  orig_base = XEXP (XEXP (x, 0), 1);	  idx = gen_rtx_PLUS (Pmode,			      gen_rtx_MULT (Pmode,					    XEXP (XEXP (XEXP (x, 0), 0), 0),					    XEXP (XEXP (XEXP (x, 0), 0), 1)),			      XEXP (x, 1));	}      else if (GET_CODE (reg2) == REG	       && REG_POINTER (reg2))	{	  base = reg2;	  orig_base = XEXP (x, 1);	  idx = XEXP (x, 0);	}      if (base == 0)	return orig;      /* If the index adds a large constant, try to scale the	 constant so that it can be loaded with only one insn.  */      if (GET_CODE (XEXP (idx, 1)) == CONST_INT	  && VAL_14_BITS_P (INTVAL (XEXP (idx, 1))			    / INTVAL (XEXP (XEXP (idx, 0), 1)))	  && INTVAL (XEXP (idx, 1)) % INTVAL (XEXP (XEXP (idx, 0), 1)) == 0)	{	  /* Divide the CONST_INT by the scale factor, then add it to A.  */	  int val = INTVAL (XEXP (idx, 1));	  val /= INTVAL (XEXP (XEXP (idx, 0), 1));	  reg1 = XEXP (XEXP (idx, 0), 0);	  if (GET_CODE (reg1) != REG)	    reg1 = force_reg (Pmode, force_operand (reg1, 0));	  reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, reg1, GEN_INT (val)));	  /* We can now generate a simple scaled indexed address.  */	  return	    force_reg	      (Pmode, gen_rtx_PLUS (Pmode,				    gen_rtx_MULT (Pmode, reg1,						  XEXP (XEXP (idx, 0), 1)),				    base));	}      /* If B + C is still a valid base register, then add them.  */      if (GET_CODE (XEXP (idx, 1)) == CONST_INT	  && INTVAL (XEXP (idx, 1)) <= 4096	  && INTVAL (XEXP (idx, 1)) >= -4096)	{	  int val = INTVAL (XEXP (XEXP (idx, 0), 1));	  rtx reg1, reg2;	  reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, XEXP (idx, 1)));	  reg2 = XEXP (XEXP (idx, 0), 0);	  if (GET_CODE (reg2) != CONST_INT)	    reg2 = force_reg (Pmode, force_operand (reg2, 0));	  return force_reg (Pmode, gen_rtx_PLUS (Pmode,						 gen_rtx_MULT (Pmode,							       reg2,							       GEN_INT (val)),						 reg1));	}      /* Get the index into a register, then add the base + index and	 return a register holding the result.  */      /* First get A into a register.  */      reg1 = XEXP (XEXP (idx, 0), 0);      if (GET_CODE (reg1) != REG)	reg1 = force_reg (Pmode, force_operand (reg1, 0));      /* And get B into a register.  */      reg2 = XEXP (idx, 1);      if (GET_CODE (reg2) != REG)	reg2 = force_reg (Pmode, force_operand (reg2, 0));      reg1 = force_reg (Pmode,			gen_rtx_PLUS (Pmode,				      gen_rtx_MULT (Pmode, reg1,						    XEXP (XEXP (idx, 0), 1)),				      reg2));      /* Add the result to our base register and return.  */      return force_reg (Pmode, gen_rtx_PLUS (Pmode, base, reg1));    }  /* Uh-oh.  We might have an address for x[n-100000].  This needs     special handling to avoid creating an indexed memory address     with x-100000 as the base.     If the constant part is small enough, then it's still safe because     there is a guard page at the beginning and end of the data segment.     Scaled references are common enough that we want to try and rearrange the     terms so that we can use indexing for these addresses too.  Only     do the optimization for floatint point modes.  */  if (GET_CODE (x) == PLUS      && symbolic_expression_p (XEXP (x, 1)))    {      /* Ugly.  We modify things here so that the address offset specified	 by the index expression is computed first, then added to x to form	 the entire address.  */      rtx regx1, regx2, regy1, regy2, y;      /* Strip off any CONST.  */      y = XEXP (x, 1);      if (GET_CODE (y) == CONST)	y = XEXP (y, 0);      if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)	{	  /* See if this looks like		(plus (mult (reg) (shadd_const))		      (const (plus (symbol_ref) (const_int))))	     Where const_int is small.  In that case the const	     expression is a valid pointer for indexing.	     If const_int is big, but can be divided evenly by shadd_const	     and added to (reg).  This allows more scaled indexed addresses.  */	  if (GET_CODE (XEXP (y, 0)) == SYMBOL_REF	      && GET_CODE (XEXP (x, 0)) == MULT	      && GET_CODE (XEXP (y, 1)) == CONST_INT	      && INTVAL (XEXP (y, 1)) >= -4096	      && INTVAL (XEXP (y, 1)) <= 4095	      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT	      && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))	    {	      int val = INTVAL (XEXP (XEXP (x, 0), 1));	      rtx reg1, reg2;	      reg1 = XEXP (x, 1);	      if (GET_CODE (reg1) != REG)		reg1 = force_reg (Pmode, force_operand (reg1, 0));	      reg2 = XEXP (XEXP (x, 0), 0);	      if (GET_CODE (reg2) != REG)	        reg2 = force_reg (Pmode, force_operand (reg2, 0));	      return force_reg (Pmode,				gen_rtx_PLUS (Pmode,					      gen_rtx_MULT (Pmode,							    reg2,							    GEN_INT (val)),					      reg1));	    }	  else if ((mode == DFmode || mode == SFmode)		   && GET_CODE (XEXP (y, 0)) == SYMBOL_REF		   && GET_CODE (XEXP (x, 0)) == MULT		   && GET_CODE (XEXP (y, 1)) == CONST_INT		   && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0		   && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT		   && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))	    {	      regx1		= force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))					     / INTVAL (XEXP (XEXP (x, 0), 1))));	      regx2 = XEXP (XEXP (x, 0), 0);	      if (GET_CODE (regx2) != REG)		regx2 = force_reg (Pmode, force_operand (regx2, 0));	      regx2 = force_reg (Pmode, gen_rtx_fmt_ee (GET_CODE (y), Pmode,							regx2, regx1));	      return		force_reg (Pmode,			   gen_rtx_PLUS (Pmode,					 gen_rtx_MULT (Pmode, regx2,						       XEXP (XEXP (x, 0), 1)),					 force_reg (Pmode, XEXP (y, 0))));	    }	  else if (GET_CODE (XEXP (y, 1)) == CONST_INT		   && INTVAL (XEXP (y, 1)) >= -4096		   && INTVAL (XEXP (y, 1)) <= 4095)	    {	      /* This is safe because of the guard page at the		 beginning and end of the data space.  Just		 return the original address.  */	      return orig;	    }	  else	    {	      /* Doesn't look like one we can optimize.  */	      regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));	      regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));	      regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));	      regx1 = force_reg (Pmode,				 gen_rtx_fmt_ee (GET_CODE (y), Pmode,						 regx1, regy2));	      return force_reg (Pmode, gen_rtx_PLUS (Pmode, regx1, regy1));	    }	}    }  return orig;}/* For the HPPA, REG and REG+CONST is cost 0   and addresses involving symbolic constants are cost 2.   PIC addresses are very expensive.   It is no coincidence that this has the same structure   as GO_IF_LEGITIMATE_ADDRESS.  */static inthppa_address_cost (rtx X){  switch (GET_CODE (X))    {    case REG:    case PLUS:    case LO_SUM:      return 1;    case HIGH:      return 2;    default:      return 4;    }}/* Compute a (partial) cost for rtx X.  Return true if the complete   cost has been computed, and false if subexpressions should be   scanned.  In either case, *TOTAL contains the cost result.  */static boolhppa_rtx_costs (rtx x, int code, int outer_code, int *total){  switch (code)    {    case CONST_INT:      if (INTVAL (x) == 0)	*total = 0;      else if (INT_14_BITS (x))	*total = 1;      else	*total = 2;      return true;    case HIGH:      *total = 2;      return true;    case CONST:    case LABEL_REF:    case SYMBOL_REF:      *total = 4;      return true;    case CONST_DOUBLE:      if ((x == CONST0_RTX (DFmode) || x == CONST0_RTX (SFmode))	  && outer_code != SET)	*total = 0;      else        *total = 8;      return true;    case MULT:      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)        *total = COSTS_N_INSNS (3);      else if (TARGET_PA_11 && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT)	*total = COSTS_N_INSNS (8);      else	*total = COSTS_N_INSNS (20);      return true;    case DIV:      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)	{	  *total = COSTS_N_INSNS (14);	  return true;	}      /* FALLTHRU */    case UDIV:    case MOD:    case UMOD:      *total = COSTS_N_INSNS (60);      return true;    case PLUS: /* this includes shNadd insns */    case MINUS:      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)	*total = COSTS_N_INSNS (3);      else        *total = COSTS_N_INSNS (1);      return true;    case ASHIFT:    case ASHIFTRT:    case LSHIFTRT:      *total = COSTS_N_INSNS (1);      return true;    default:      return false;    }}/* Ensure mode of ORIG, a REG rtx, is MODE.  Returns either ORIG or a   new rtx with the correct mode.  */static inline rtxforce_mode (enum machine_mode mode, rtx orig){  if (mode == GET_MODE (orig))    return orig;  if (REGNO (orig) >= FIRST_PSEUDO_REGISTER)    abort ();  return gen_rtx_REG (mode, REGNO (orig));}/* Emit insns to move operands[1] into operands[0].   Return 1 if we have written out everything that needs to be done to   do the move.  Otherwise, return 0 and the caller will emit the move   normally.   Note SCRATCH_REG may not be in the proper mode depending on how it   will be used.  This routine is responsible for creating a new copy   of SCRATCH_REG in the proper mode.  */intemit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg){  register rtx operand0 = operands[0];  register rtx operand1 = operands[1];  register rtx tem;  /* We can only handle indexed addresses in the destination operand     of floating point stores.  Thus, we need to break out indexed     addresses from the destination operand.  */  if (GET_CODE (operand0) == MEM && IS_INDEX_ADDR_P (XEXP (operand0, 0)))    {      /* This is only safe up to the beginning of life analysis.  */      if (no_new_pseudos)	abort ();      tem = copy_to_mode_reg (Pmode, XEXP (operand0, 0));      operand0 = replace_equiv_address (operand0, tem);    }  /* On targets with non-equivalent space registers, break out unscaled     indexed addresses from the source operand before the final CSE.     We have to do this because the REG_POINTER flag is not correctly     carried through various optimization passes and CSE may substitute     a pseudo without the pointer set for one with the pointer set.  As     a result, we loose various opportunities to create insns with     unscaled indexed addresses.  */  if (!TARGET_NO_SPACE_REGS      && !cse_not_expected      && GET_CODE (operand1) == MEM      && GET_CODE (XEXP (operand1, 0)) == PLUS      && REG_P (XEXP (XEXP (operand1, 0), 0))      && REG_P (XEXP (XEXP (operand1, 0), 1)))    operand1      = replace_equiv_address (operand1,			       copy_to_mode_reg (Pmode, XEXP (operand1, 0)));  if (scratch_reg      && reload_in_progress && GET_CODE (operand0) == REG      && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)

⌨️ 快捷键说明

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