simplify-rtx.c (simplify_subreg): Break out from ...

* simplify-rtx.c (simplify_subreg): Break out from ...
	* combine.c (combine_splify_rtx) ... here and ...
	* recog.c (validate_replace_rtx_1): ... here;
	* rtl.h (subreg_lowpart_parts_p, simplify_subreg): Declare.
	* emit-rtl.c (subreg_lowpart_parts_p): Break out from ...
	(subreg_lowpart_p): ... here.

From-SVN: r42199
This commit is contained in:
Jan Hubicka 2001-05-17 17:00:35 +02:00 committed by Jan Hubicka
parent 5d7ef82a5d
commit eea50aa0ab
6 changed files with 260 additions and 295 deletions

View File

@ -1,3 +1,12 @@
Thu May 17 16:59:41 CEST 2001 Jan Hubicka <jh@suse.cz>
* simplify-rtx.c (simplify_subreg): Break out from ...
* combine.c (combine_splify_rtx) ... here and ...
* recog.c (validate_replace_rtx_1): ... here;
* rtl.h (subreg_lowpart_parts_p, simplify_subreg): Declare.
* emit-rtl.c (subreg_lowpart_parts_p): Break out from ...
(subreg_lowpart_p): ... here.
2001-05-17 Bernd Schmidt <bernds@redhat.com>
* stmt.c (expand_asm_operands): For inout operands, make sure

View File

@ -3765,161 +3765,21 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
break;
case SUBREG:
/* (subreg:A (mem:B X) N) becomes a modified MEM unless the SUBREG
is paradoxical. If we can't do that safely, then it becomes
something nonsensical so that this combination won't take place. */
if (op0_mode == VOIDmode)
op0_mode = GET_MODE (SUBREG_REG (x));
if (GET_CODE (SUBREG_REG (x)) == MEM
&& (GET_MODE_SIZE (mode)
<= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
{
rtx inner = SUBREG_REG (x);
int offset = SUBREG_BYTE (x);
/* Don't change the mode of the MEM
if that would change the meaning of the address. */
if (MEM_VOLATILE_P (SUBREG_REG (x))
|| mode_dependent_address_p (XEXP (inner, 0)))
return gen_rtx_CLOBBER (mode, const0_rtx);
/* Note if the plus_constant doesn't make a valid address
then this combination won't be accepted. */
x = gen_rtx_MEM (mode,
plus_constant (XEXP (inner, 0), offset));
MEM_COPY_ATTRIBUTES (x, inner);
return x;
}
/* If we are in a SET_DEST, these other cases can't apply. */
if (in_dest)
return x;
/* Changing mode twice with SUBREG => just change it once,
or not at all if changing back to starting mode. */
if (GET_CODE (SUBREG_REG (x)) == SUBREG)
{
int final_offset;
enum machine_mode outer_mode, inner_mode;
/* If the innermost mode is the same as the goal mode,
and the low word is being referenced in both SUBREGs,
return the innermost element. */
if (mode == GET_MODE (SUBREG_REG (SUBREG_REG (x))))
{
int inner_word = SUBREG_BYTE (SUBREG_REG (x));
int outer_word = SUBREG_BYTE (x);
inner_word = (inner_word / UNITS_PER_WORD) * UNITS_PER_WORD;
outer_word = (outer_word / UNITS_PER_WORD) * UNITS_PER_WORD;
if (inner_word == 0
&& outer_word == 0)
return SUBREG_REG (SUBREG_REG (x));
}
outer_mode = GET_MODE (SUBREG_REG (x));
inner_mode = GET_MODE (SUBREG_REG (SUBREG_REG (x)));
final_offset = SUBREG_BYTE (x) + SUBREG_BYTE (SUBREG_REG(x));
if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
&& GET_MODE_SIZE (outer_mode) > GET_MODE_SIZE (mode)
&& GET_MODE_SIZE (outer_mode) > GET_MODE_SIZE (inner_mode))
{
/* Inner SUBREG is paradoxical, outer is not. On big endian
we have to special case this. */
if (SUBREG_BYTE (SUBREG_REG (x)))
abort(); /* Can a paradoxical subreg have nonzero offset? */
if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
final_offset = SUBREG_BYTE (x) - GET_MODE_SIZE (outer_mode)
+ GET_MODE_SIZE (inner_mode);
else if (WORDS_BIG_ENDIAN)
final_offset = (final_offset % UNITS_PER_WORD)
+ ((SUBREG_BYTE (x) - GET_MODE_SIZE (outer_mode)
+ GET_MODE_SIZE (inner_mode))
* UNITS_PER_WORD) / UNITS_PER_WORD;
else
final_offset = ((final_offset * UNITS_PER_WORD)
/ UNITS_PER_WORD)
+ ((SUBREG_BYTE (x) - GET_MODE_SIZE (outer_mode)
+ GET_MODE_SIZE (inner_mode))
% UNITS_PER_WORD);
}
/* The SUBREG rules are that the byte offset must be
some multiple of the toplevel SUBREG's mode. */
final_offset = (final_offset / GET_MODE_SIZE (mode));
final_offset = (final_offset * GET_MODE_SIZE (mode));
SUBST_INT (SUBREG_BYTE (x), final_offset);
SUBST (SUBREG_REG (x), SUBREG_REG (SUBREG_REG (x)));
}
/* SUBREG of a hard register => just change the register number
and/or mode. If the hard register is not valid in that mode,
suppress this combination. If the hard register is the stack,
frame, or argument pointer, leave this as a SUBREG. */
if (GET_CODE (SUBREG_REG (x)) == REG
&& REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
&& REGNO (SUBREG_REG (x)) != FRAME_POINTER_REGNUM
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
&& REGNO (SUBREG_REG (x)) != HARD_FRAME_POINTER_REGNUM
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& REGNO (SUBREG_REG (x)) != ARG_POINTER_REGNUM
#endif
&& REGNO (SUBREG_REG (x)) != STACK_POINTER_REGNUM)
{
int final_regno = subreg_hard_regno (x, 0);
if (HARD_REGNO_MODE_OK (final_regno, mode))
return gen_rtx_REG (mode, final_regno);
else
return gen_rtx_CLOBBER (mode, const0_rtx);
}
/* For a constant, try to pick up the part we want. Handle a full
word and low-order part. Only do this if we are narrowing
the constant; if it is being widened, we have no idea what
the extra bits will have been set to. */
if (CONSTANT_P (SUBREG_REG (x)) && op0_mode != VOIDmode
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
&& GET_MODE_SIZE (op0_mode) > UNITS_PER_WORD
&& GET_MODE_CLASS (mode) == MODE_INT)
{
temp = operand_subword (SUBREG_REG (x),
(SUBREG_BYTE (x) / UNITS_PER_WORD),
0, op0_mode);
if (temp)
return temp;
}
/* If we want a subreg of a constant, at offset 0,
take the low bits. On a little-endian machine, that's
always valid. On a big-endian machine, it's valid
only if the constant's mode fits in one word. Note that we
cannot use subreg_lowpart_p since SUBREG_REG may be VOIDmode. */
/* simplify_subreg can't use gen_lowpart_for_combine. */
if (CONSTANT_P (SUBREG_REG (x))
&& ((GET_MODE_SIZE (op0_mode) <= UNITS_PER_WORD
|| ! WORDS_BIG_ENDIAN)
? SUBREG_BYTE (x) == 0
: (SUBREG_BYTE (x)
== (GET_MODE_SIZE (op0_mode) - GET_MODE_SIZE (mode))))
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (op0_mode)
&& (! WORDS_BIG_ENDIAN
|| GET_MODE_BITSIZE (op0_mode) <= BITS_PER_WORD))
&& subreg_lowpart_parts_p (mode, op0_mode, SUBREG_BYTE (x)))
return gen_lowpart_for_combine (mode, SUBREG_REG (x));
/* A paradoxical SUBREG of a VOIDmode constant is the same constant,
since we are saying that the high bits don't matter. */
if (CONSTANT_P (SUBREG_REG (x)) && GET_MODE (SUBREG_REG (x)) == VOIDmode
&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (op0_mode))
{
if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD
&& (WORDS_BIG_ENDIAN || SUBREG_BYTE (x) != 0))
return constant_subword (SUBREG_REG (x),
SUBREG_BYTE (x) / UNITS_PER_WORD, mode);
return SUBREG_REG (x);
}
{
rtx temp;
temp = simplify_subreg (mode, SUBREG_REG (x), op0_mode,
SUBREG_BYTE (x));
if (temp)
return temp;
}
/* Note that we cannot do any narrowing for non-constants since
we might have been counting on using the fact that some bits were

View File

@ -1278,6 +1278,27 @@ gen_highpart (mode, x)
else
abort ();
}
/* Return 1 iff (SUBREG:outermode (OP:innermode) byte)
refers to the least significant part of its containing reg. */
int
subreg_lowpart_parts_p (outermode, innermode, byte)
enum machine_mode outermode, innermode;
unsigned int byte;
{
unsigned int offset = 0;
int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode));
if (difference > 0)
{
if (WORDS_BIG_ENDIAN)
offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
if (BYTES_BIG_ENDIAN)
offset += difference % UNITS_PER_WORD;
}
return byte == offset;
}
/* Return 1 iff X, assumed to be a SUBREG,
refers to the least significant part of its containing reg.
@ -1296,15 +1317,8 @@ subreg_lowpart_p (x)
else if (GET_MODE (SUBREG_REG (x)) == VOIDmode)
return 0;
if (difference > 0)
{
if (WORDS_BIG_ENDIAN)
offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
if (BYTES_BIG_ENDIAN)
offset += difference % UNITS_PER_WORD;
}
return SUBREG_BYTE (x) == offset;
return subreg_lowpart_parts_p (GET_MODE (x), GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x));
}

View File

@ -579,145 +579,26 @@ validate_replace_rtx_1 (loc, from, to, object)
/* In case we are replacing by constant, attempt to simplify it to
non-SUBREG expression. We can't do this later, since the information
about inner mode may be lost. */
if (CONSTANT_P (to) && rtx_equal_p (SUBREG_REG (x), from))
if (rtx_equal_p (SUBREG_REG (x), from))
{
int offset, part;
unsigned HOST_WIDE_INT val;
/* A paradoxical SUBREG of a VOIDmode constant is the same constant,
since we are saying that the high bits don't matter. */
if (GET_MODE (to) == VOIDmode
&& (GET_MODE_SIZE (GET_MODE (x))
>= GET_MODE_SIZE (GET_MODE (from))))
rtx temp;
temp = simplify_subreg (GET_MODE (x), to, GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x));
if (temp)
{
rtx new = gen_lowpart_if_possible (GET_MODE (x), to);
if (new)
{
validate_change (object, loc, new, 1);
return;
}
}
offset = SUBREG_BYTE (x) * BITS_PER_UNIT;
switch (GET_CODE (to))
{
case CONST_DOUBLE:
if (GET_MODE (to) != VOIDmode)
break;
part = offset >= HOST_BITS_PER_WIDE_INT;
if ((BITS_PER_WORD > HOST_BITS_PER_WIDE_INT
&& BYTES_BIG_ENDIAN)
|| (BITS_PER_WORD <= HOST_BITS_PER_WIDE_INT
&& WORDS_BIG_ENDIAN))
part = !part;
val = part ? CONST_DOUBLE_HIGH (to) : CONST_DOUBLE_LOW (to);
offset %= HOST_BITS_PER_WIDE_INT;
/* FALLTHROUGH */
case CONST_INT:
if (GET_CODE (to) == CONST_INT)
val = INTVAL (to);
{
/* Avoid creating bogus SUBREGs */
enum machine_mode mode = GET_MODE (x);
enum machine_mode inner_mode = GET_MODE (from);
/* We've already picked the word we want from a double, so
pretend this is actually an integer. */
if (GET_CODE (to) == CONST_DOUBLE)
inner_mode = SImode;
if (GET_MODE_CLASS (mode) != MODE_INT)
{
/* Substitute in something that we know won't be
recognized. */
to = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
validate_change (object, loc, to, 1);
return;
}
if (BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN)
{
if (WORDS_BIG_ENDIAN)
offset = GET_MODE_BITSIZE (inner_mode)
- GET_MODE_BITSIZE (mode) - offset;
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD)
offset = offset + BITS_PER_WORD - GET_MODE_BITSIZE (mode)
- 2 * (offset % BITS_PER_WORD);
}
if (offset >= HOST_BITS_PER_WIDE_INT)
to = ((HOST_WIDE_INT) val < 0) ? constm1_rtx : const0_rtx;
else
{
val >>= offset;
if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)
val = trunc_int_for_mode (val, mode);
to = GEN_INT (val);
}
validate_change (object, loc, to, 1);
return;
}
default:
break;
}
}
/* Changing mode twice with SUBREG => just change it once,
or not at all if changing back to starting mode. */
if (GET_CODE (to) == SUBREG
&& rtx_equal_p (SUBREG_REG (x), from))
{
if (GET_MODE (x) == GET_MODE (SUBREG_REG (to))
&& SUBREG_BYTE (x) == 0 && SUBREG_BYTE (to) == 0)
{
validate_change (object, loc, SUBREG_REG (to), 1);
validate_change (object, loc, temp, 1);
return;
}
/* Make sure the 2 byte counts added together are an even unit
of x's mode, and combine them if so. Otherwise we run
into problems with something like:
(subreg:HI (subreg:QI (SI:55) 3) 0)
we end up with an odd offset into a HI which is invalid. */
if (SUBREG_BYTE (to) % GET_MODE_SIZE (GET_MODE (x)) == 0)
validate_change (object, loc,
gen_rtx_SUBREG (GET_MODE (x), SUBREG_REG (to),
SUBREG_BYTE(x) + SUBREG_BYTE (to)),
1);
else
validate_change (object, loc, to, 1);
return;
}
/* If we have a SUBREG of a register that we are replacing and we are
replacing it with a MEM, make a new MEM and try replacing the
SUBREG with it. Don't do this if the MEM has a mode-dependent address
or if we would be widening it. */
if (GET_CODE (from) == REG
&& GET_CODE (to) == MEM
&& rtx_equal_p (SUBREG_REG (x), from)
&& ! mode_dependent_address_p (XEXP (to, 0))
&& ! MEM_VOLATILE_P (to)
&& GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (to)))
{
int offset = SUBREG_BYTE (x);
enum machine_mode mode = GET_MODE (x);
rtx new;
new = gen_rtx_MEM (mode, plus_constant (XEXP (to, 0), offset));
MEM_COPY_ATTRIBUTES (new, to);
validate_change (object, loc, new, 1);
return;
}
/* Avoid creating of invalid SUBREGS. */
if (GET_MODE (from) == VOIDmode)
{
/* Substitute in something that we know won't be
recognized. */
to = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
validate_change (object, loc, to, 1);
return;
}
}
break;
case ZERO_EXTRACT:

View File

@ -1198,6 +1198,9 @@ extern rtx constant_subword PARAMS ((rtx, int,
extern rtx operand_subword_force PARAMS ((rtx, unsigned int,
enum machine_mode));
extern int subreg_lowpart_p PARAMS ((rtx));
extern int subreg_lowpart_parts_p PARAMS ((enum machine_mode,
enum machine_mode,
unsigned int));
extern rtx make_safe_from PARAMS ((rtx, rtx));
extern rtx convert_memory_address PARAMS ((enum machine_mode, rtx));
extern rtx get_insns PARAMS ((void));
@ -1324,6 +1327,10 @@ extern rtx simplify_gen_relational PARAMS ((enum rtx_code,
enum machine_mode,
enum machine_mode,
rtx, rtx));
extern rtx simplify_subreg PARAMS ((enum machine_mode,
rtx,
enum machine_mode,
unsigned int));
extern rtx simplify_replace_rtx PARAMS ((rtx, rtx, rtx));
extern rtx simplify_rtx PARAMS ((rtx));

View File

@ -2186,6 +2186,200 @@ simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
return 0;
}
/* Simplify SUBREG:OUTERMODE(OP:INNERMODE, BYTE)
Return 0 if no simplifications is possible. */
rtx
simplify_subreg (outermode, op, innermode, byte)
rtx op;
unsigned int byte;
enum machine_mode outermode, innermode;
{
/* Little bit of sanity checking. */
if (innermode == VOIDmode || outermode == VOIDmode
|| innermode == BLKmode || outermode == BLKmode)
abort ();
if (GET_MODE (op) != innermode
&& GET_MODE (op) != VOIDmode)
abort ();
if (byte % GET_MODE_SIZE (outermode)
|| byte >= GET_MODE_SIZE (innermode))
abort ();
/* Attempt to simplify constant to non-SUBREG expression. */
if (CONSTANT_P (op))
{
int offset, part;
unsigned HOST_WIDE_INT val;
/* ??? This code is partly redundant with code bellow, but can handle
the subregs of floats and similar corner cases.
Later it we should move all simplification code here and rewrite
GEN_LOWPART_IF_POSSIBLE, GEN_HIGHPART, OPERAND_SUBWORD and friends
using SIMPLIFY_SUBREG. */
if (subreg_lowpart_parts_p (outermode, innermode, byte))
{
rtx new = gen_lowpart_if_possible (outermode, op);
if (new)
return new;
}
/* Similar comment as above apply here. */
if (GET_MODE_SIZE (outermode) == UNITS_PER_WORD
&& GET_MODE_SIZE (innermode) > UNITS_PER_WORD
&& GET_MODE_CLASS (outermode) == MODE_INT)
{
rtx new = operand_subword (op,
(byte / UNITS_PER_WORD),
0, innermode);
if (new)
return new;
}
offset = byte * BITS_PER_UNIT;
switch (GET_CODE (op))
{
case CONST_DOUBLE:
if (GET_MODE (op) != VOIDmode)
break;
/* We can't handle this case yet. */
if (GET_MODE_BITSIZE (outermode) >= HOST_BITS_PER_WIDE_INT)
return NULL;
part = offset >= HOST_BITS_PER_WIDE_INT;
if ((BITS_PER_WORD > HOST_BITS_PER_WIDE_INT
&& BYTES_BIG_ENDIAN)
|| (BITS_PER_WORD <= HOST_BITS_PER_WIDE_INT
&& WORDS_BIG_ENDIAN))
part = !part;
val = part ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op);
offset %= HOST_BITS_PER_WIDE_INT;
/* We've already picked the word we want from a double, so
pretend this is actually an integer. */
innermode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
/* FALLTHROUGH */
case CONST_INT:
if (GET_CODE (op) == CONST_INT)
val = INTVAL (op);
/* We don't handle synthetizing of non-integral constants yet. */
if (GET_MODE_CLASS (outermode) != MODE_INT)
return NULL;
if (BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN)
{
if (WORDS_BIG_ENDIAN)
offset = (GET_MODE_BITSIZE (innermode)
- GET_MODE_BITSIZE (outermode) - offset);
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
&& GET_MODE_SIZE (outermode) < UNITS_PER_WORD)
offset = (offset + BITS_PER_WORD - GET_MODE_BITSIZE (outermode)
- 2 * (offset % BITS_PER_WORD));
}
if (offset >= HOST_BITS_PER_WIDE_INT)
return ((HOST_WIDE_INT) val < 0) ? constm1_rtx : const0_rtx;
else
{
val >>= offset;
if (GET_MODE_BITSIZE (outermode) < HOST_BITS_PER_WIDE_INT)
val = trunc_int_for_mode (val, outermode);
return GEN_INT (val);
}
default:
break;
}
}
/* Changing mode twice with SUBREG => just change it once,
or not at all if changing back op starting mode. */
if (GET_CODE (op) == SUBREG)
{
enum machine_mode innermostmode = GET_MODE (SUBREG_REG (op));
unsigned int final_offset = byte + SUBREG_BYTE (op);
rtx new;
if (outermode == innermostmode
&& byte == 0 && SUBREG_BYTE (op) == 0)
return SUBREG_REG (op);
if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
&& GET_MODE_SIZE (innermode) > GET_MODE_SIZE (outermode)
&& GET_MODE_SIZE (innermode) > GET_MODE_SIZE (innermostmode))
{
/* Inner SUBREG is paradoxical, outer is not. On big endian
we have to special case this. */
if (SUBREG_BYTE (op))
abort(); /* Can a paradoxical subreg have nonzero offset? */
if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
final_offset = (byte - GET_MODE_SIZE (innermode)
+ GET_MODE_SIZE (innermostmode));
else if (WORDS_BIG_ENDIAN)
final_offset = ((final_offset % UNITS_PER_WORD)
+ ((byte - GET_MODE_SIZE (innermode)
+ GET_MODE_SIZE (innermostmode))
* UNITS_PER_WORD) / UNITS_PER_WORD);
else
final_offset = (((final_offset * UNITS_PER_WORD)
/ UNITS_PER_WORD)
+ ((byte - GET_MODE_SIZE (innermode)
+ GET_MODE_SIZE (innermostmode))
% UNITS_PER_WORD));
}
/* Recurse for futher possible simplifications. */
new = simplify_subreg (outermode, op, GET_MODE (op),
final_offset);
if (new)
return new;
return gen_rtx_SUBREG (outermode, op, final_offset);
}
/* SUBREG of a hard register => just change the register number
and/or mode. If the hard register is not valid in that mode,
suppress this simplification. If the hard register is the stack,
frame, or argument pointer, leave this as a SUBREG. */
if (REG_P (op) == REG
&& REGNO (op) < FIRST_PSEUDO_REGISTER
&& REGNO (op) != FRAME_POINTER_REGNUM
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
&& REGNO (op) != HARD_FRAME_POINTER_REGNUM
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& REGNO (op) != ARG_POINTER_REGNUM
#endif
&& REGNO (op) != STACK_POINTER_REGNUM)
{
int final_regno = subreg_hard_regno (gen_rtx_SUBREG (outermode, op, byte),
0);
if (HARD_REGNO_MODE_OK (final_regno, outermode))
return gen_rtx_REG (outermode, final_regno);
}
/* If we have a SUBREG of a register that we are replacing and we are
replacing it with a MEM, make a new MEM and try replacing the
SUBREG with it. Don't do this if the MEM has a mode-dependent address
or if we would be widening it. */
if (GET_CODE (op) == MEM
&& ! mode_dependent_address_p (XEXP (op, 0))
&& ! MEM_VOLATILE_P (op)
&& GET_MODE_SIZE (outermode) <= GET_MODE_SIZE (GET_MODE (op)))
{
rtx new;
new = gen_rtx_MEM (outermode, plus_constant (XEXP (op, 0), byte));
MEM_COPY_ATTRIBUTES (new, op);
return new;
}
return NULL_RTX;
}
/* Simplify X, an rtx expression.
Return the simplified expression or NULL if no simplifications