int
crx_memory_move_cost (enum machine_mode mode,
		  enum reg_class rclass ATTRIBUTE_UNUSED,
		  int in ATTRIBUTE_UNUSED)
{
  /* One LD or ST takes twice the time of a simple reg-reg move */
  if (reg_classes_intersect_p (rclass, GENERAL_REGS))
    {
      /* printf ("GENERAL_REGS LD/ST = %d\n", 4 * HARD_REGNO_NREGS (0, mode));*/
      return 4 * HARD_REGNO_NREGS (0, mode);
    }	
  else if (reg_classes_intersect_p (rclass, HILO_REGS))
    {
      /* HILO to memory and vice versa */
      /* printf ("HILO_REGS %s = %d\n", in ? "LD" : "ST",
	     (REGISTER_MOVE_COST (mode,
				 in ? GENERAL_REGS : HILO_REGS,
				 in ? HILO_REGS : GENERAL_REGS) + 4)
	* HARD_REGNO_NREGS (0, mode)); */
      return (REGISTER_MOVE_COST (mode,
				 in ? GENERAL_REGS : HILO_REGS,
				 in ? HILO_REGS : GENERAL_REGS) + 4)
	* HARD_REGNO_NREGS (0, mode);
    }
  else /* default (like in i386) */
    {
      /* printf ("ANYREGS = 100\n"); */
      return 100;
    }
}
Example #2
0
static bool
combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set)
{
  rtx orig_src = SET_SRC (*orig_set);
  machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set));
  rtx new_set;
  rtx cand_pat = PATTERN (cand->insn);

  /* If the extension's source/destination registers are not the same
     then we need to change the original load to reference the destination
     of the extension.  Then we need to emit a copy from that destination
     to the original destination of the load.  */
  rtx new_reg;
  bool copy_needed
    = (REGNO (SET_DEST (cand_pat)) != REGNO (XEXP (SET_SRC (cand_pat), 0)));
  if (copy_needed)
    new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (cand_pat)));
  else
    new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set)));

#if 0
  /* Rethinking test.  Temporarily disabled.  */
  /* We're going to be widening the result of DEF_INSN, ensure that doing so
     doesn't change the number of hard registers needed for the result.  */
  if (HARD_REGNO_NREGS (REGNO (new_reg), cand->mode)
      != HARD_REGNO_NREGS (REGNO (SET_DEST (*orig_set)),
			   GET_MODE (SET_DEST (*orig_set))))
	return false;
#endif

  /* Merge constants by directly moving the constant into the register under
     some conditions.  Recall that RTL constants are sign-extended.  */
  if (GET_CODE (orig_src) == CONST_INT
      && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (cand->mode))
    {
      if (INTVAL (orig_src) >= 0 || cand->code == SIGN_EXTEND)
	new_set = gen_rtx_SET (new_reg, orig_src);
      else
	{
	  /* Zero-extend the negative constant by masking out the bits outside
	     the source mode.  */
	  rtx new_const_int
	    = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (orig_mode),
			    GET_MODE (new_reg));
	  new_set = gen_rtx_SET (new_reg, new_const_int);
	}
    }
  else if (GET_MODE (orig_src) == VOIDmode)
    {
      /* This is mostly due to a call insn that should not be optimized.  */
      return false;
    }
  else if (GET_CODE (orig_src) == cand->code)
    {
      /* Here is a sequence of two extensions.  Try to merge them.  */
      rtx temp_extension
	= gen_rtx_fmt_e (cand->code, cand->mode, XEXP (orig_src, 0));
      rtx simplified_temp_extension = simplify_rtx (temp_extension);
      if (simplified_temp_extension)
        temp_extension = simplified_temp_extension;
      new_set = gen_rtx_SET (new_reg, temp_extension);
    }
  else if (GET_CODE (orig_src) == IF_THEN_ELSE)
    {
      /* Only IF_THEN_ELSE of phi-type copies are combined.  Otherwise,
         in general, IF_THEN_ELSE should not be combined.  */
      return false;
    }
  else
    {
      /* This is the normal case.  */
      rtx temp_extension
	= gen_rtx_fmt_e (cand->code, cand->mode, orig_src);
      rtx simplified_temp_extension = simplify_rtx (temp_extension);
      if (simplified_temp_extension)
        temp_extension = simplified_temp_extension;
      new_set = gen_rtx_SET (new_reg, temp_extension);
    }

  /* This change is a part of a group of changes.  Hence,
     validate_change will not try to commit the change.  */
  if (validate_change (curr_insn, orig_set, new_set, true)
      && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode,
				       cand->code))
    {
      if (dump_file)
        {
          fprintf (dump_file,
		   "Tentatively merged extension with definition %s:\n",
		   (copy_needed) ? "(copy needed)" : "");
          print_rtl_single (dump_file, curr_insn);
        }
      return true;
    }

  return false;
}