if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
&& ! SUBREG_PROMOTED_UNSIGNED_P (op)
- && GET_MODE (XEXP (op, 0)) == mode)
- return XEXP (op, 0);
+ && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
+ return rtl_hooks.gen_lowpart_no_emit (mode, op);
#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
if (! POINTERS_EXTEND_UNSIGNED
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
&& SUBREG_PROMOTED_UNSIGNED_P (op) > 0
- && GET_MODE (XEXP (op, 0)) == mode)
- return XEXP (op, 0);
+ && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
+ return rtl_hooks.gen_lowpart_no_emit (mode, op);
#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
if (POINTERS_EXTEND_UNSIGNED > 0
return simplify_gen_binary (code, mode, tem, op1);
}
}
+
+ /* (and X (ior (not X) Y) -> (and X Y) */
+ if (GET_CODE (op1) == IOR
+ && GET_CODE (XEXP (op1, 0)) == NOT
+ && op0 == XEXP (XEXP (op1, 0), 0))
+ return simplify_gen_binary (AND, mode, op0, XEXP (op1, 1));
+
+ /* (and (ior (not X) Y) X) -> (and X Y) */
+ if (GET_CODE (op0) == IOR
+ && GET_CODE (XEXP (op0, 0)) == NOT
+ && op1 == XEXP (XEXP (op0, 0), 0))
+ return simplify_gen_binary (AND, mode, op1, XEXP (op0, 1));
+
tem = simplify_associative_operation (code, mode, op0, op1);
if (tem)
return tem;
&& (unsigned HOST_WIDE_INT) INTVAL (trueop0) == GET_MODE_MASK (mode)
&& ! side_effects_p (op1))
return op0;
+ canonicalize_shift:
+ if (SHIFT_COUNT_TRUNCATED && GET_CODE (op1) == CONST_INT)
+ {
+ val = INTVAL (op1) & (GET_MODE_BITSIZE (mode) - 1);
+ if (val != INTVAL (op1))
+ return simplify_gen_binary (code, mode, op0, GEN_INT (val));
+ }
break;
case ASHIFT:
return op0;
if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1))
return op0;
- break;
+ goto canonicalize_shift;
case LSHIFTRT:
if (trueop1 == CONST0_RTX (mode))
return simplify_gen_relational (EQ, mode, imode,
XEXP (op0, 0), const0_rtx);
}
- break;
+ goto canonicalize_shift;
case SMIN:
if (width <= HOST_BITS_PER_WIDE_INT
if (VECTOR_MODE_P (mode)
&& code == VEC_CONCAT
- && CONSTANT_P (op0) && CONSTANT_P (op1))
+ && (CONST_INT_P (op0)
+ || GET_CODE (op0) == CONST_DOUBLE
+ || GET_CODE (op0) == CONST_FIXED)
+ && (CONST_INT_P (op1)
+ || GET_CODE (op1) == CONST_DOUBLE
+ || GET_CODE (op1) == CONST_FIXED))
{
unsigned n_elts = GET_MODE_NUNITS (mode);
rtvec v = rtvec_alloc (n_elts);
else
{
rtx mmin_rtx, mmax_rtx;
- unsigned int sign_copies = num_sign_bit_copies (trueop0, mode);
get_mode_bounds (mode, sign, mode, &mmin_rtx, &mmax_rtx);
- /* Since unsigned mmin will never be interpreted as negative, use
- INTVAL (and an arithmetic right shift). */
- mmin = INTVAL (mmin_rtx) >> (sign_copies - 1);
- /* Since signed mmax will always be positive, use UINTVAL (and
- a logical right shift). */
- mmax = UINTVAL (mmax_rtx) >> (sign_copies - 1);
+ mmin = INTVAL (mmin_rtx);
+ mmax = INTVAL (mmax_rtx);
+ if (sign)
+ {
+ unsigned int sign_copies = num_sign_bit_copies (trueop0, mode);
+
+ mmin >>= (sign_copies - 1);
+ mmax >>= (sign_copies - 1);
+ }
}
switch (code)
return newx;
if (validate_subreg (outermode, innermostmode,
SUBREG_REG (op), final_offset))
- return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
+ {
+ newx = gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
+ if (SUBREG_PROMOTED_VAR_P (op)
+ && SUBREG_PROMOTED_UNSIGNED_P (op) >= 0
+ && GET_MODE_CLASS (outermode) == MODE_INT
+ && IN_RANGE (GET_MODE_SIZE (outermode),
+ GET_MODE_SIZE (innermode),
+ GET_MODE_SIZE (innermostmode))
+ && subreg_lowpart_p (newx))
+ {
+ SUBREG_PROMOTED_VAR_P (newx) = 1;
+ SUBREG_PROMOTED_UNSIGNED_SET
+ (newx, SUBREG_PROMOTED_UNSIGNED_P (op));
+ }
+ return newx;
+ }
return NULL_RTX;
}
return simplify_gen_binary (ASHIFT, outermode,
XEXP (XEXP (op, 0), 0), XEXP (op, 1));
+ /* Recognize a word extraction from a multi-word subreg. */
+ if ((GET_CODE (op) == LSHIFTRT
+ || GET_CODE (op) == ASHIFTRT)
+ && SCALAR_INT_MODE_P (outermode)
+ && GET_MODE_BITSIZE (outermode) >= BITS_PER_WORD
+ && GET_MODE_BITSIZE (innermode) >= (2 * GET_MODE_BITSIZE (outermode))
+ && GET_CODE (XEXP (op, 1)) == CONST_INT
+ && (INTVAL (XEXP (op, 1)) & (GET_MODE_BITSIZE (outermode) - 1)) == 0
+ && byte == subreg_lowpart_offset (outermode, innermode))
+ {
+ int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT;
+ return simplify_gen_subreg (outermode, XEXP (op, 0), innermode,
+ (WORDS_BIG_ENDIAN
+ ? byte - shifted_bytes : byte + shifted_bytes));
+ }
+
return NULL_RTX;
}