#include "cfgbuild.h"
#include "dce.h"
#include "expr.h"
+#include "explow.h"
#include "tree-pass.h"
#include "lower-subreg.h"
#include "rtl-iter.h"
/* Decompose a more than word wide shift (in INSN) of a multiword
pseudo or a multiword zero-extend of a wordmode pseudo into a move
- and 'set to zero' insn. Return a pointer to the new insn when a
- replacement was done. */
+ and 'set to zero' insn. SPEED_P says whether we are optimizing
+ for speed or size, when checking if a ZERO_EXTEND is preferable.
+ Return a pointer to the new insn when a replacement was done. */
static rtx_insn *
-resolve_shift_zext (rtx_insn *insn)
+resolve_shift_zext (rtx_insn *insn, bool speed_p)
{
rtx set;
rtx op;
dest_reg, GET_CODE (op) != ASHIFTRT);
}
- if (dest_reg != src_reg)
- emit_move_insn (dest_reg, src_reg);
- if (GET_CODE (op) != ASHIFTRT)
- emit_move_insn (dest_upper, CONST0_RTX (word_mode));
- else if (INTVAL (XEXP (op, 1)) == 2 * BITS_PER_WORD - 1)
- emit_move_insn (dest_upper, copy_rtx (src_reg));
+ /* Consider using ZERO_EXTEND instead of setting DEST_UPPER to zero
+ if this is considered reasonable. */
+ if (GET_CODE (op) == LSHIFTRT
+ && GET_MODE (op) == twice_word_mode
+ && REG_P (SET_DEST (set))
+ && !choices[speed_p].splitting_zext)
+ {
+ rtx tmp = force_reg (word_mode, copy_rtx (src_reg));
+ tmp = simplify_gen_unary (ZERO_EXTEND, twice_word_mode, tmp, word_mode);
+ emit_move_insn (SET_DEST (set), tmp);
+ }
else
- emit_move_insn (dest_upper, upper_src);
+ {
+ if (dest_reg != src_reg)
+ emit_move_insn (dest_reg, src_reg);
+ if (GET_CODE (op) != ASHIFTRT)
+ emit_move_insn (dest_upper, CONST0_RTX (word_mode));
+ else if (INTVAL (XEXP (op, 1)) == 2 * BITS_PER_WORD - 1)
+ emit_move_insn (dest_upper, copy_rtx (src_reg));
+ else
+ emit_move_insn (dest_upper, upper_src);
+ }
+
insns = get_insns ();
end_sequence ();
{
rtx_insn *decomposed_shift;
- decomposed_shift = resolve_shift_zext (insn);
+ decomposed_shift = resolve_shift_zext (insn, speed_p);
if (decomposed_shift != NULL_RTX)
{
insn = decomposed_shift;