* rtl.h (truncated_to_mode): Declare it.
(struct rtl_hooks): Add reg_truncated_to_mode hook.
* rtlhooks-def.h (RTL_HOOKS_REG_TRUNCATED_TO_MODE): New macro.
(RTL_HOOKS_INITIALIZER): Include it.
* rtlhooks.c (reg_truncated_to_mode_general): New function.
* combine.c (RTL_HOOKS_REG_TRUNCATED_TO_MODE): Override to
reg_truncated_to_mode.
* rtlanal.c (truncated_to_mode): Define it.
* simplify-rtx.c (simplify_unary_operation_1): Use it.
Co-Authored-By: Adam Nemet <anemet@caviumnetworks.com>
From-SVN: r111573
+2006-02-28 Paolo Bonzini <bonzini@gnu.org>
+ Adam Nemet <anemet@caviumnetworks.com>
+
+ * rtl.h (truncated_to_mode): Declare it.
+ (struct rtl_hooks): Add reg_truncated_to_mode hook.
+ * rtlhooks-def.h (RTL_HOOKS_REG_TRUNCATED_TO_MODE): New macro.
+ (RTL_HOOKS_INITIALIZER): Include it.
+ * rtlhooks.c (reg_truncated_to_mode_general): New function.
+ * combine.c (RTL_HOOKS_REG_TRUNCATED_TO_MODE): Override to
+ reg_truncated_to_mode.
+ * rtlanal.c (truncated_to_mode): Define it.
+ * simplify-rtx.c (simplify_unary_operation_1): Use it.
+
2006-02-28 Jeff Law <law@redhat.com>
* tree-chrec.c (chrec_convert_aggressive): Do not eliminate
#undef RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES
#define RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES reg_num_sign_bit_copies_for_combine
+#undef RTL_HOOKS_REG_TRUNCATED_TO_MODE
+#define RTL_HOOKS_REG_TRUNCATED_TO_MODE reg_truncated_to_mode
+
static const struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER;
\f
extern unsigned HOST_WIDE_INT nonzero_bits (rtx, enum machine_mode);
extern unsigned int num_sign_bit_copies (rtx, enum machine_mode);
extern bool constant_pool_constant_p (rtx);
+extern bool truncated_to_mode (enum machine_mode, rtx);
/* 1 if RTX is a subreg containing a reg that is already known to be
unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT *);
rtx (*reg_num_sign_bit_copies) (rtx, enum machine_mode, rtx, enum machine_mode,
unsigned int, unsigned int *);
+ bool (*reg_truncated_to_mode) (enum machine_mode, rtx);
- /* Whenever you add entries here, make sure you adjust hosthooks-def.h. */
+ /* Whenever you add entries here, make sure you adjust rtlhooks-def.h. */
};
/* Each pass can provide its own. */
allow_cc_mode, valid_at_insn_p);
}
+/* Suppose that truncation from the machine mode of X to MODE is not a
+ no-op. See if there is anything special about X so that we can
+ assume it already contains a truncated value of MODE. */
+
+bool
+truncated_to_mode (enum machine_mode mode, rtx x)
+{
+ return REG_P (x) && rtl_hooks.reg_truncated_to_mode (mode, x);
+}
+
\f
/* Initialize non_rtx_starting_operands, which is used to speed up
for_each_rtx. */
#define RTL_HOOKS_GEN_LOWPART_NO_EMIT gen_lowpart_no_emit_general
#define RTL_HOOKS_REG_NONZERO_REG_BITS reg_nonzero_bits_general
#define RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES reg_num_sign_bit_copies_general
+#define RTL_HOOKS_REG_TRUNCATED_TO_MODE reg_truncated_to_mode_general
/* The structure is defined in rtl.h. */
#define RTL_HOOKS_INITIALIZER { \
RTL_HOOKS_GEN_LOWPART_NO_EMIT, \
RTL_HOOKS_REG_NONZERO_REG_BITS, \
RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES, \
+ RTL_HOOKS_REG_TRUNCATED_TO_MODE, \
}
extern rtx gen_lowpart_general (enum machine_mode, rtx);
extern rtx reg_num_sign_bit_copies_general (rtx, enum machine_mode, rtx,
enum machine_mode,
unsigned int, unsigned int *);
+extern bool reg_truncated_to_mode_general (enum machine_mode, rtx);
#endif /* GCC_RTL_HOOKS_DEF_H */
return NULL;
}
+bool
+reg_truncated_to_mode_general (enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
/* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a fixed-point
number, return an rtx (MEM, SUBREG, or CONST_INT) that refers to the
least-significant part of X.
GET_MODE (XEXP (SUBREG_REG (op), 0)));
/* If we know that the value is already truncated, we can
- replace the TRUNCATE with a SUBREG if TRULY_NOOP_TRUNCATION
- is nonzero for the corresponding modes. But don't do this
- for an (LSHIFTRT (MULT ...)) since this will cause problems
- with the umulXi3_highpart patterns. */
- if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+ replace the TRUNCATE with a SUBREG. Note that this is also
+ valid if TRULY_NOOP_TRUNCATION is false for the corresponding
+ modes we just have to apply a different definition for
+ truncation. But don't do this for an (LSHIFTRT (MULT ...))
+ since this will cause problems with the umulXi3_highpart
+ patterns. */
+ if ((TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
GET_MODE_BITSIZE (GET_MODE (op)))
- && num_sign_bit_copies (op, GET_MODE (op))
- >= (unsigned int) (GET_MODE_BITSIZE (mode) + 1)
+ ? (num_sign_bit_copies (op, GET_MODE (op))
+ >= (unsigned int) (GET_MODE_BITSIZE (mode) + 1))
+ : truncated_to_mode (mode, op))
&& ! (GET_CODE (op) == LSHIFTRT
&& GET_CODE (XEXP (op, 0)) == MULT))
return rtl_hooks.gen_lowpart_no_emit (mode, op);