@@ -7613,7 +7613,8 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
&& (pos == 0 || REG_P (inner))
&& (inner_mode == tmode
|| !REG_P (inner)
- || TRULY_NOOP_TRUNCATION_MODES_P (tmode, inner_mode)
+ || (known_lt (GET_MODE_SIZE (tmode), GET_MODE_SIZE (inner_mode))
+ && TRULY_NOOP_TRUNCATION_MODES_P (tmode, inner_mode))
|| reg_truncated_to_mode (tmode, inner))
&& (! in_dest
|| (REG_P (inner)
@@ -7856,6 +7857,8 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
/* On the LHS, don't create paradoxical subregs implicitely truncating
the register unless TARGET_TRULY_NOOP_TRUNCATION. */
if (in_dest
+ && known_lt (GET_MODE_SIZE (GET_MODE (inner)),
+ GET_MODE_SIZE (wanted_inner_mode))
&& !TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (inner),
wanted_inner_mode))
return NULL_RTX;
@@ -26707,6 +26707,16 @@ ix86_libm_function_max_error (unsigned cfn, machine_mode mode,
#define TARGET_RUN_TARGET_SELFTESTS selftest::ix86_run_selftests
#endif /* #if CHECKING_P */
+static bool
+ix86_truly_noop_truncation (poly_uint64 outprec, poly_uint64 inprec)
+{
+ gcc_assert (outprec < inprec);
+ return true;
+}
+
+#undef TARGET_TRULY_NOOP_TRUNCATION
+#define TARGET_TRULY_NOOP_TRUNCATION ix86_truly_noop_truncation
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-i386.h"
@@ -651,6 +651,7 @@ store_bit_field_using_insv (const extraction_insn *insv, rtx op0,
X) 0)) is (reg:N X). */
if (GET_CODE (xop0) == SUBREG
&& REG_P (SUBREG_REG (xop0))
+ && paradoxical_subreg_p (xop0)
&& !TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (SUBREG_REG (xop0)),
op_mode))
{
@@ -1585,7 +1586,11 @@ extract_bit_field_using_extv (const extraction_insn *extv, rtx op0,
mode. Instead, create a temporary and use convert_move to set
the target. */
if (REG_P (target)
- && TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (target), ext_mode)
+ && (known_lt (GET_MODE_SIZE (GET_MODE (target)),
+ GET_MODE_SIZE (ext_mode))
+ ? TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (target), ext_mode)
+ : known_eq (GET_MODE_SIZE (GET_MODE (target)),
+ GET_MODE_SIZE (ext_mode)))
&& (temp = gen_lowpart_if_possible (ext_mode, target)))
{
target = temp;
@@ -1626,7 +1631,9 @@ extract_bit_field_as_subreg (machine_mode mode, rtx op0,
if (multiple_p (bitnum, BITS_PER_UNIT, &bytenum)
&& known_eq (bitsize, GET_MODE_BITSIZE (mode))
&& lowpart_bit_field_p (bitnum, bitsize, op0_mode)
- && TRULY_NOOP_TRUNCATION_MODES_P (mode, op0_mode))
+ && (known_lt (GET_MODE_SIZE (mode), GET_MODE_SIZE (op0_mode))
+ ? TRULY_NOOP_TRUNCATION_MODES_P (mode, op0_mode)
+ : known_eq (GET_MODE_SIZE (mode), GET_MODE_SIZE (op0_mode))))
return simplify_gen_subreg (mode, op0, op0_mode, bytenum);
return NULL_RTX;
}
@@ -213,7 +213,7 @@ get_best_extraction_insn (extraction_insn *insn,
FOR_EACH_MODE_FROM (mode_iter, mode)
{
mode = mode_iter.require ();
- if (maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (field_mode))
+ if (maybe_ge (GET_MODE_SIZE (mode), GET_MODE_SIZE (field_mode))
|| TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
field_mode))
break;
@@ -2954,7 +2954,11 @@ expand_parity (scalar_int_mode mode, rtx op0, rtx target)
if (temp)
{
if (mclass != MODE_INT
- || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
+ || (known_lt (GET_MODE_SIZE (mode),
+ GET_MODE_SIZE (wider_mode))
+ ? !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode)
+ : maybe_ne (GET_MODE_SIZE (mode),
+ GET_MODE_SIZE (wider_mode))))
return convert_to_mode (mode, temp, 0);
else
return gen_lowpart (mode, temp);
@@ -66,7 +66,9 @@ gen_lowpart_general (machine_mode mode, rtx x)
scalar_int_mode xmode;
if (is_a <scalar_int_mode> (GET_MODE (x), &xmode)
&& GET_MODE_SIZE (xmode) <= UNITS_PER_WORD
- && TRULY_NOOP_TRUNCATION_MODES_P (mode, xmode)
+ && (known_lt (GET_MODE_SIZE (mode), GET_MODE_SIZE (xmode))
+ ? TRULY_NOOP_TRUNCATION_MODES_P (mode, xmode)
+ : known_eq (GET_MODE_SIZE (mode), GET_MODE_SIZE (xmode)))
&& !reload_completed)
return gen_lowpart_general (mode, force_reg (xmode, x));
@@ -617,7 +617,7 @@ simplify_context::simplify_truncation (machine_mode mode, rtx op,
unsigned int op_precision = GET_MODE_UNIT_PRECISION (op_mode);
scalar_int_mode int_mode, int_op_mode, subreg_mode;
- gcc_assert (precision <= op_precision);
+ gcc_assert (precision < op_precision);
/* Optimize truncations of zero and sign extended values. */
if (GET_CODE (op) == ZERO_EXTEND
@@ -1207,6 +1207,10 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
break;
case TRUNCATE:
+ /* Check for useless truncation. */
+ if (GET_MODE (op) == mode)
+ return op;
+
/* Don't optimize (lshiftrt (mult ...)) as it would interfere
with the umulXi3_highpart patterns. */
if (GET_CODE (op) == LSHIFTRT
@@ -1271,9 +1275,6 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
return temp;
}
- /* Check for useless truncation. */
- if (GET_MODE (op) == mode)
- return op;
break;
case FLOAT_TRUNCATE: