Esempio n. 1
0
rtx
compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
		  enum machine_mode mode, rtx size)
{
  enum rtx_code ucode;
  rtx tem;

  /* If one operand is constant, make it the second one.  Only do this
     if the other operand is not constant as well.  */

  if (swap_commutative_operands_p (op0, op1))
    {
      tem = op0;
      op0 = op1;
      op1 = tem;
      code = swap_condition (code);
    }

  if (flag_force_mem)
    {
      op0 = force_not_mem (op0);
      op1 = force_not_mem (op1);
    }

  do_pending_stack_adjust ();

  ucode = unsignedp ? unsigned_condition (code) : code;
  if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0)
    return tem;

#if 0
  /* There's no need to do this now that combine.c can eliminate lots of
     sign extensions.  This can be less efficient in certain cases on other
     machines.  */

  /* If this is a signed equality comparison, we can do it as an
     unsigned comparison since zero-extension is cheaper than sign
     extension and comparisons with zero are done as unsigned.  This is
     the case even on machines that can do fast sign extension, since
     zero-extension is easier to combine with other operations than
     sign-extension is.  If we are comparing against a constant, we must
     convert it to what it would look like unsigned.  */
  if ((code == EQ || code == NE) && ! unsignedp
      && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
    {
      if (GET_CODE (op1) == CONST_INT
          && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1))
        op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0)));
      unsignedp = 1;
    }
#endif

  emit_cmp_insn (op0, op1, code, size, mode, unsignedp);

#if HAVE_cc0
  return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
#else
  return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
#endif
}
Esempio n. 2
0
static rtx
nds32_gen_dup_4_byte_to_word_value_aux (rtx value, rtx value4word)
{
  gcc_assert (GET_MODE (value) == QImode || CONST_INT_P (value));

  if (CONST_INT_P (value))
    {
      unsigned HOST_WIDE_INT val = UINTVAL (value) & GET_MODE_MASK(QImode);
      rtx new_val = gen_int_mode (val | (val << 8)
				  | (val << 16) | (val << 24), SImode);
      /* Just calculate at here if it's constant value.  */
      emit_move_insn (value4word, new_val);
    }
  else
    {
      if (NDS32_EXT_DSP_P ())
	{
	  /* ! prepare word
	     insb    $tmp, $value, 1         ! $tmp  <- 0x0000abab
	     pkbb16  $tmp6, $tmp2, $tmp2   ! $value4word  <- 0xabababab */
	  rtx tmp = gen_reg_rtx (SImode);

	  convert_move (tmp, value, true);

	  emit_insn (
	    gen_insvsi_internal (tmp, gen_int_mode (0x8, SImode), tmp));

	  emit_insn (gen_pkbbsi_1 (value4word, tmp, tmp));
	}
      else
	{
	  /* ! prepare word
	     andi    $tmp1, $value, 0xff       ! $tmp1  <- 0x000000ab
	     slli    $tmp2, $tmp1, 8           ! $tmp2  <- 0x0000ab00
	     or      $tmp3, $tmp1, $tmp2       ! $tmp3  <- 0x0000abab
	     slli    $tmp4, $tmp3, 16          ! $tmp4  <- 0xabab0000
	     or      $val4word, $tmp3, $tmp4   ! $value4word  <- 0xabababab  */

	  rtx tmp1, tmp2, tmp3, tmp4;
	  tmp1 = expand_binop (SImode, and_optab, value,
			       gen_int_mode (0xff, SImode),
			       NULL_RTX, 0, OPTAB_WIDEN);
	  tmp2 = expand_binop (SImode, ashl_optab, tmp1,
			       gen_int_mode (8, SImode),
			       NULL_RTX, 0, OPTAB_WIDEN);
	  tmp3 = expand_binop (SImode, ior_optab, tmp1, tmp2,
			       NULL_RTX, 0, OPTAB_WIDEN);
	  tmp4 = expand_binop (SImode, ashl_optab, tmp3,
			       gen_int_mode (16, SImode),
			       NULL_RTX, 0, OPTAB_WIDEN);

	  emit_insn (gen_iorsi3 (value4word, tmp3, tmp4));
	}
    }

  return value4word;
}
Esempio n. 3
0
/* Function to check if 'btgl' instruction can be used with IVAL.  */
bool
nds32_can_use_btgl_p (HOST_WIDE_INT ival)
{
  int one_bit_count;
  unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);

  /* Caculate the number of 1-bit of ival, if there is only one 1-bit,
     it is ok to perform 'btgl' operation.  */

  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival) & mask);

  /* 'btgl' is a performance extension instruction.  */
  return (TARGET_EXT_PERF && (one_bit_count == 1));
}
Esempio n. 4
0
/* Function to check if 'bclr' instruction can be used with IVAL.  */
bool
nds32_can_use_bclr_p (HOST_WIDE_INT ival)
{
  int one_bit_count;
  unsigned HOST_WIDE_INT mask = GET_MODE_MASK (SImode);

  /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit,
     it means the original ival has only one 0-bit,
     So it is ok to perform 'bclr' operation.  */

  one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival) & mask);

  /* 'bclr' is a performance extension instruction.  */
  return (TARGET_EXT_PERF && (one_bit_count == 1));
}
Esempio n. 5
0
File: ree.c Progetto: aixoss/gcc
static bool
update_reg_equal_equiv_notes (rtx insn, enum machine_mode new_mode,
			      enum machine_mode old_mode, enum rtx_code code)
{
  rtx *loc = &REG_NOTES (insn);
  while (*loc)
    {
      enum reg_note kind = REG_NOTE_KIND (*loc);
      if (kind == REG_EQUAL || kind == REG_EQUIV)
	{
	  rtx orig_src = XEXP (*loc, 0);
	  /* Update equivalency constants.  Recall that RTL constants are
	     sign-extended.  */
	  if (GET_CODE (orig_src) == CONST_INT
	      && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (new_mode))
	    {
	      if (INTVAL (orig_src) >= 0 || code == SIGN_EXTEND)
		/* Nothing needed.  */;
	      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 (old_mode),
				    new_mode);
		  if (!validate_change (insn, &XEXP (*loc, 0),
					new_const_int, true))
		    return false;
		}
	      loc = &XEXP (*loc, 1);
	    }
	  /* Drop all other notes, they assume a wrong mode.  */
	  else if (!validate_change (insn, loc, XEXP (*loc, 1), true))
	    return false;
	}
      else
	loc = &XEXP (*loc, 1);
    }
  return true;
}
Esempio n. 6
0
File: ree.c Progetto: aixoss/gcc
static bool
combine_set_extension (ext_cand *cand, rtx curr_insn, rtx *orig_set)
{
  rtx orig_src = SET_SRC (*orig_set);
  enum machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set));
  rtx new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set)));
  rtx new_set;

  /* 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 (VOIDmode, 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 (INTVAL (orig_src) & GET_MODE_MASK (orig_mode));
	  new_set = gen_rtx_SET (VOIDmode, 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 (VOIDmode, 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 (VOIDmode, 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:\n");
          print_rtl_single (dump_file, curr_insn);
        }
      return true;
    }

  return false;
}
Esempio n. 7
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;
}
Esempio n. 8
0
void
do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
			 enum machine_mode mode, rtx size, rtx if_false_label,
			 rtx if_true_label)
{
  enum rtx_code ucode;
  rtx tem;
  int dummy_true_label = 0;

  /* Reverse the comparison if that is safe and we want to jump if it is
     false.  */
  if (! if_true_label && ! FLOAT_MODE_P (mode))
    {
      if_true_label = if_false_label;
      if_false_label = 0;
      code = reverse_condition (code);
    }

  /* If one operand is constant, make it the second one.  Only do this
     if the other operand is not constant as well.  */

  if (swap_commutative_operands_p (op0, op1))
    {
      tem = op0;
      op0 = op1;
      op1 = tem;
      code = swap_condition (code);
    }

  if (flag_force_mem)
    {
      op0 = force_not_mem (op0);
      op1 = force_not_mem (op1);
    }

  do_pending_stack_adjust ();

  ucode = unsignedp ? unsigned_condition (code) : code;
  if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0)
    {
      if (tem == const_true_rtx)
        {
          if (if_true_label)
            emit_jump (if_true_label);
        }
      else
        {
          if (if_false_label)
            emit_jump (if_false_label);
        }
      return;
    }

#if 0
  /* There's no need to do this now that combine.c can eliminate lots of
     sign extensions.  This can be less efficient in certain cases on other
     machines.  */

  /* If this is a signed equality comparison, we can do it as an
     unsigned comparison since zero-extension is cheaper than sign
     extension and comparisons with zero are done as unsigned.  This is
     the case even on machines that can do fast sign extension, since
     zero-extension is easier to combine with other operations than
     sign-extension is.  If we are comparing against a constant, we must
     convert it to what it would look like unsigned.  */
  if ((code == EQ || code == NE) && ! unsignedp
      && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
    {
      if (GET_CODE (op1) == CONST_INT
          && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1))
        op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0)));
      unsignedp = 1;
    }
#endif

  if (! if_true_label)
    {
      dummy_true_label = 1;
      if_true_label = gen_label_rtx ();
    }

  emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
                           if_true_label);

  if (if_false_label)
    emit_jump (if_false_label);
  if (dummy_true_label)
    emit_label (if_true_label);
}
Esempio n. 9
0
static bool
nds32_expand_setmem_unroll (rtx dstmem, rtx size, rtx value,
			    rtx align ATTRIBUTE_UNUSED,
			    rtx expected_align ATTRIBUTE_UNUSED,
			    rtx expected_size ATTRIBUTE_UNUSED)
{
  unsigned maximum_regs, maximum_bytes, start_regno, regno;
  rtx value4word;
  rtx dst_base_reg, new_base_reg;
  unsigned HOST_WIDE_INT remain_bytes, remain_words, prepare_regs, fill_per_smw;
  unsigned HOST_WIDE_INT real_size;

  if (TARGET_REDUCED_REGS)
    {
      maximum_regs  = 4;
      maximum_bytes = 64;
      start_regno   = 2;
    }
  else
    {
      maximum_regs  = 8;
      maximum_bytes = 128;
      start_regno   = 16;
    }

  real_size = UINTVAL (size) & GET_MODE_MASK(SImode);

  if (!(CONST_INT_P (size) && real_size <= maximum_bytes))
    return false;

  remain_bytes = real_size;

  gcc_assert (GET_MODE (value) == QImode || CONST_INT_P (value));

  value4word = nds32_gen_dup_4_byte_to_word_value (value);

  prepare_regs = remain_bytes / UNITS_PER_WORD;

  dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0));

  if (prepare_regs > maximum_regs)
    prepare_regs = maximum_regs;

  fill_per_smw = prepare_regs * UNITS_PER_WORD;

  regno = start_regno;
  switch (prepare_regs)
    {
    case 2:
    default:
      {
	rtx reg0 = gen_rtx_REG (SImode, regno);
	rtx reg1 = gen_rtx_REG (SImode, regno+1);
	unsigned last_regno = start_regno + prepare_regs - 1;

	emit_move_insn (reg0, value4word);
	emit_move_insn (reg1, value4word);
	rtx regd = gen_rtx_REG (DImode, regno);
	regno += 2;

	/* Try to utilize movd44!  */
	while (regno <= last_regno)
	  {
	    if ((regno + 1) <=last_regno)
	      {
		rtx reg = gen_rtx_REG (DImode, regno);
		emit_move_insn (reg, regd);
		regno += 2;
	      }
	    else
	      {
		rtx reg = gen_rtx_REG (SImode, regno);
		emit_move_insn (reg, reg0);
		regno += 1;
	      }
	  }
	break;
      }
    case 1:
      {
	rtx reg = gen_rtx_REG (SImode, regno++);
	emit_move_insn (reg, value4word);
      }
      break;
    case 0:
      break;
    }

  if (fill_per_smw)
    for (;remain_bytes >= fill_per_smw;remain_bytes -= fill_per_smw)
      {
	emit_insn (nds32_expand_store_multiple (start_regno, prepare_regs,
						dst_base_reg, dstmem,
						true, &new_base_reg));
	dst_base_reg = new_base_reg;
	dstmem = gen_rtx_MEM (SImode, dst_base_reg);
      }

  remain_words = remain_bytes / UNITS_PER_WORD;

  if (remain_words)
    {
      emit_insn (nds32_expand_store_multiple (start_regno, remain_words,
					      dst_base_reg, dstmem,
					      true, &new_base_reg));
      dst_base_reg = new_base_reg;
      dstmem = gen_rtx_MEM (SImode, dst_base_reg);
    }

  remain_bytes = remain_bytes - (remain_words * UNITS_PER_WORD);

  if (remain_bytes)
    {
      value = simplify_gen_subreg (QImode, value4word, SImode,
				   subreg_lowpart_offset(QImode, SImode));
      int offset = 0;
      for (;remain_bytes;--remain_bytes, ++offset)
	{
	  nds32_emit_load_store (value, dstmem, QImode, offset, false);
	}
    }

  return true;
}
Esempio n. 10
0
static int
reload_cse_simplify_set (rtx set, rtx insn)
{
  int did_change = 0;
  int dreg;
  rtx src;
  enum reg_class dclass;
  int old_cost;
  cselib_val *val;
  struct elt_loc_list *l;
#ifdef LOAD_EXTEND_OP
  enum rtx_code extend_op = UNKNOWN;
#endif
  bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));

  dreg = true_regnum (SET_DEST (set));
  if (dreg < 0)
    return 0;

  src = SET_SRC (set);
  if (side_effects_p (src) || true_regnum (src) >= 0)
    return 0;

  dclass = REGNO_REG_CLASS (dreg);

#ifdef LOAD_EXTEND_OP
  /* When replacing a memory with a register, we need to honor assumptions
     that combine made wrt the contents of sign bits.  We'll do this by
     generating an extend instruction instead of a reg->reg copy.  Thus
     the destination must be a register that we can widen.  */
  if (MEM_P (src)
      && GET_MODE_BITSIZE (GET_MODE (src)) < BITS_PER_WORD
      && (extend_op = LOAD_EXTEND_OP (GET_MODE (src))) != UNKNOWN
      && !REG_P (SET_DEST (set)))
    return 0;
#endif

  val = cselib_lookup (src, GET_MODE (SET_DEST (set)), 0);
  if (! val)
    return 0;

  /* If memory loads are cheaper than register copies, don't change them.  */
  if (MEM_P (src))
    old_cost = MEMORY_MOVE_COST (GET_MODE (src), dclass, 1);
  else if (REG_P (src))
    old_cost = REGISTER_MOVE_COST (GET_MODE (src),
				   REGNO_REG_CLASS (REGNO (src)), dclass);
  else
    old_cost = rtx_cost (src, SET, speed);

  for (l = val->locs; l; l = l->next)
    {
      rtx this_rtx = l->loc;
      int this_cost;

      if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx, 0))
	{
#ifdef LOAD_EXTEND_OP
	  if (extend_op != UNKNOWN)
	    {
	      HOST_WIDE_INT this_val;

	      /* ??? I'm lazy and don't wish to handle CONST_DOUBLE.  Other
		 constants, such as SYMBOL_REF, cannot be extended.  */
	      if (GET_CODE (this_rtx) != CONST_INT)
		continue;

	      this_val = INTVAL (this_rtx);
	      switch (extend_op)
		{
		case ZERO_EXTEND:
		  this_val &= GET_MODE_MASK (GET_MODE (src));
		  break;
		case SIGN_EXTEND:
		  /* ??? In theory we're already extended.  */
		  if (this_val == trunc_int_for_mode (this_val, GET_MODE (src)))
		    break;
		default:
		  gcc_unreachable ();
		}
	      this_rtx = GEN_INT (this_val);
	    }
#endif
	  this_cost = rtx_cost (this_rtx, SET, speed);
	}
      else if (REG_P (this_rtx))
	{
#ifdef LOAD_EXTEND_OP
	  if (extend_op != UNKNOWN)
	    {
	      this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx);
	      this_cost = rtx_cost (this_rtx, SET, speed);
	    }
	  else
#endif
	    this_cost = REGISTER_MOVE_COST (GET_MODE (this_rtx),
					    REGNO_REG_CLASS (REGNO (this_rtx)),
					    dclass);
	}
      else
	continue;

      /* If equal costs, prefer registers over anything else.  That
	 tends to lead to smaller instructions on some machines.  */
      if (this_cost < old_cost
	  || (this_cost == old_cost
	      && REG_P (this_rtx)
	      && !REG_P (SET_SRC (set))))
	{
#ifdef LOAD_EXTEND_OP
	  if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD
	      && extend_op != UNKNOWN
#ifdef CANNOT_CHANGE_MODE_CLASS
	      && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
					    word_mode,
					    REGNO_REG_CLASS (REGNO (SET_DEST (set))))
#endif
	      )
	    {
	      rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
	      ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
	      validate_change (insn, &SET_DEST (set), wide_dest, 1);
	    }
#endif

	  validate_unshare_change (insn, &SET_SRC (set), this_rtx, 1);
	  old_cost = this_cost, did_change = 1;
	}
    }

  return did_change;
}