[PATCH] Add reg_truncated_to_mode to rtl_hooks
Adam Nemet
anemet@sonic.net
Fri Feb 17 09:31:00 GMT 2006
This patch adds reg_truncated_to_mode to rtl_hooks. With this we can
now turn TRUNCATEs into SUBREGs in simplify_unary_operation_1. The
patch is similar to the respective part of Paolo Bonzini's patch from
http://gcc.gnu.org/ml/gcc-patches/2006-02/msg00684.html.
With these changes we remove seven truncations in
gcc.c-torture/execute. They all seem to have been unnecessary.
While working on this I noticed a bug in simplify_unary_operation_1:
620 /* If we know that the value is already truncated, we can
621 replace the TRUNCATE with a SUBREG if TRULY_NOOP_TRUNCATION
622 is nonzero for the corresponding modes. But don't do this
623 for an (LSHIFTRT (MULT ...)) since this will cause problems
624 with the umulXi3_highpart patterns. */
625 if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
626 GET_MODE_BITSIZE (GET_MODE (op)))
627 && num_sign_bit_copies (op, GET_MODE (op))
628 >= (unsigned int) (GET_MODE_BITSIZE (mode) + 1)
629 && ! (GET_CODE (op) == LSHIFTRT
630 && GET_CODE (XEXP (op, 0)) == MULT))
631 return rtl_hooks.gen_lowpart_no_emit (mode, op);
I think in the num_sign_bit_copies check the number of sign bits
should be greater than GET_MODE (op) - GET_MODE_BITSIZE (mode). The
code happens to work because this type of truncate is typically used
to truncate to mode half the size of the original mode. I am changing
this piece of code but I would prefer to submit a separate patch with
the fix.
Regression tested on mipsisa64-elf and bootstrapped and
regression-tested on i686-pc-linux-gnu.
OK to apply?
Adam
2006-02-16 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.
Index: rtlhooks.c
===================================================================
*** rtlhooks.c (revision 110908)
--- rtlhooks.c (working copy)
*************** reg_nonzero_bits_general (rtx x ATTRIBUT
*** 117,122 ****
--- 117,129 ----
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.
Index: rtlanal.c
===================================================================
*** rtlanal.c (revision 110908)
--- rtlanal.c (working copy)
*************** get_condition (rtx jump, rtx *earliest,
*** 4786,4791 ****
--- 4786,4801 ----
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);
+ }
+
/* Initialize non_rtx_starting_operands, which is used to speed up
for_each_rtx. */
Index: rtlhooks-def.h
===================================================================
*** rtlhooks-def.h (revision 110908)
--- rtlhooks-def.h (working copy)
*************** Boston, MA 02110-1301, USA. */
*** 27,32 ****
--- 27,33 ----
#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 { \
*************** Boston, MA 02110-1301, USA. */
*** 34,39 ****
--- 35,41 ----
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_nonzero_bits_general (rtx
*** 45,49 ****
--- 47,52 ----
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 */
Index: simplify-rtx.c
===================================================================
*** simplify-rtx.c (revision 110990)
--- simplify-rtx.c (working copy)
*************** simplify_unary_operation_1 (enum rtx_cod
*** 618,631 ****
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),
GET_MODE_BITSIZE (GET_MODE (op)))
! && num_sign_bit_copies (op, GET_MODE (op))
! >= (unsigned int) (GET_MODE_BITSIZE (mode) + 1)
&& ! (GET_CODE (op) == LSHIFTRT
&& GET_CODE (XEXP (op, 0)) == MULT))
return rtl_hooks.gen_lowpart_no_emit (mode, op);
--- 618,634 ----
GET_MODE (XEXP (SUBREG_REG (op), 0)));
/* If we know that the value is already truncated, we can
! 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))
! : truncated_to_mode (mode, op))
&& ! (GET_CODE (op) == LSHIFTRT
&& GET_CODE (XEXP (op, 0)) == MULT))
return rtl_hooks.gen_lowpart_no_emit (mode, op);
Index: rtl.h
===================================================================
*** rtl.h (revision 110908)
--- rtl.h (working copy)
*************** extern bool subreg_offset_representable_
*** 980,985 ****
--- 980,986 ----
extern unsigned int subreg_regno (rtx);
extern unsigned HOST_WIDE_INT nonzero_bits (rtx, enum machine_mode);
extern unsigned int num_sign_bit_copies (rtx, enum machine_mode);
+ extern bool truncated_to_mode (enum machine_mode, rtx);
/* 1 if RTX is a subreg containing a reg that is already known to be
*************** struct rtl_hooks
*** 2190,2197 ****
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 *);
! /* Whenever you add entries here, make sure you adjust hosthooks-def.h. */
};
/* Each pass can provide its own. */
--- 2191,2199 ----
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 rtlhooks-def.h. */
};
/* Each pass can provide its own. */
Index: combine.c
===================================================================
*** combine.c (revision 110908)
--- combine.c (working copy)
*************** static rtx gen_lowpart_or_truncate (enum
*** 457,462 ****
--- 457,465 ----
#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;
More information about the Gcc-patches
mailing list