/* Optimize by combining instructions for GNU compiler.
- Copyright (C) 1987-2018 Free Software Foundation, Inc.
+ Copyright (C) 1987-2019 Free Software Foundation, Inc.
This file is part of GCC.
}
/* Try to split PATTERN found in INSN. This returns NULL_RTX if
- PATTERN can not be split. Otherwise, it returns an insn sequence.
+ PATTERN cannot be split. Otherwise, it returns an insn sequence.
This is a wrapper around split_insns which ensures that the
reg_stat vector is made larger if the splitter creates a new
register. */
/* Don't call nonzero_bits if it cannot change anything. */
if (rsp->nonzero_bits != HOST_WIDE_INT_M1U)
{
- bits = nonzero_bits (src, nonzero_bits_mode);
+ machine_mode mode = GET_MODE (x);
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && HWI_COMPUTABLE_MODE_P (mode))
+ mode = nonzero_bits_mode;
+ bits = nonzero_bits (src, mode);
if (reg_equal && bits)
- bits &= nonzero_bits (reg_equal, nonzero_bits_mode);
+ bits &= nonzero_bits (reg_equal, mode);
rsp->nonzero_bits |= bits;
}
dest = SUBREG_REG (dest);
if (REG_P (src) && REG_P (dest)
&& ((HARD_REGISTER_P (src)
- && ! TEST_HARD_REG_BIT (fixed_reg_set, REGNO (src)))
+ && ! TEST_HARD_REG_BIT (fixed_reg_set, REGNO (src))
+#ifdef LEAF_REGISTERS
+ && ! LEAF_REGISTERS [REGNO (src)])
+#else
+ )
+#endif
|| (HARD_REGISTER_P (dest)
&& ! TEST_HARD_REG_BIT (fixed_reg_set, REGNO (dest))
&& targetm.class_likely_spilled_p (REGNO_REG_CLASS (REGNO (dest))))))
}
/* If we have a PLUS whose second operand is a constant and the
- address is not valid, perhaps will can split it up using
+ address is not valid, perhaps we can split it up using
the machine-specific way to split large constants. We use
the first pseudo-reg (one of the virtual regs) as a placeholder;
it will not remain in the result. */
/* This should have produced two insns, each of which sets our
placeholder. If the source of the second is a valid address,
- we can make put both sources together and make a split point
+ we can put both sources together and make a split point
in the middle. */
if (seq
}
}
+ /* If that didn't work and we have a nested plus, like:
+ ((REG1 * CONST1) + REG2) + CONST2 and (REG1 + REG2) + CONST2
+ is valid address, try to split (REG1 * CONST1). */
+ if (GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
+ && !OBJECT_P (XEXP (XEXP (XEXP (x, 0), 0), 0))
+ && OBJECT_P (XEXP (XEXP (XEXP (x, 0), 0), 1))
+ && ! (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SUBREG
+ && OBJECT_P (SUBREG_REG (XEXP (XEXP (XEXP (x, 0),
+ 0), 0)))))
+ {
+ rtx tem = XEXP (XEXP (XEXP (x, 0), 0), 0);
+ XEXP (XEXP (XEXP (x, 0), 0), 0) = reg;
+ if (memory_address_addr_space_p (GET_MODE (x), XEXP (x, 0),
+ MEM_ADDR_SPACE (x)))
+ {
+ XEXP (XEXP (XEXP (x, 0), 0), 0) = tem;
+ return &XEXP (XEXP (XEXP (x, 0), 0), 0);
+ }
+ XEXP (XEXP (XEXP (x, 0), 0), 0) = tem;
+ }
+ else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
+ && OBJECT_P (XEXP (XEXP (XEXP (x, 0), 0), 0))
+ && !OBJECT_P (XEXP (XEXP (XEXP (x, 0), 0), 1))
+ && ! (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == SUBREG
+ && OBJECT_P (SUBREG_REG (XEXP (XEXP (XEXP (x, 0),
+ 0), 1)))))
+ {
+ rtx tem = XEXP (XEXP (XEXP (x, 0), 0), 1);
+ XEXP (XEXP (XEXP (x, 0), 0), 1) = reg;
+ if (memory_address_addr_space_p (GET_MODE (x), XEXP (x, 0),
+ MEM_ADDR_SPACE (x)))
+ {
+ XEXP (XEXP (XEXP (x, 0), 0), 1) = tem;
+ return &XEXP (XEXP (XEXP (x, 0), 0), 1);
+ }
+ XEXP (XEXP (XEXP (x, 0), 0), 1) = tem;
+ }
+
/* If that didn't work, perhaps the first operand is complex and
needs to be computed separately, so make a split point there.
This will occur on machines that just support REG + CONST
and have a constant moved through some previous computation. */
-
- else if (!OBJECT_P (XEXP (XEXP (x, 0), 0))
- && ! (GET_CODE (XEXP (XEXP (x, 0), 0)) == SUBREG
- && OBJECT_P (SUBREG_REG (XEXP (XEXP (x, 0), 0)))))
+ if (!OBJECT_P (XEXP (XEXP (x, 0), 0))
+ && ! (GET_CODE (XEXP (XEXP (x, 0), 0)) == SUBREG
+ && OBJECT_P (SUBREG_REG (XEXP (XEXP (x, 0), 0)))))
return &XEXP (XEXP (x, 0), 0);
}
&& known_eq (subreg_lowpart_offset (int_mode, int_op0_mode),
SUBREG_BYTE (x))
&& HWI_COMPUTABLE_MODE_P (int_op0_mode)
- && (nonzero_bits (SUBREG_REG (x), int_op0_mode)
- & GET_MODE_MASK (int_mode)) == 0)
+ && ((nonzero_bits (SUBREG_REG (x), int_op0_mode)
+ & GET_MODE_MASK (int_mode)) == 0)
+ && !side_effects_p (SUBREG_REG (x)))
return CONST0_RTX (int_mode);
}
\f
/* Given a REG X of mode XMODE, compute which bits in X can be nonzero.
We don't care about bits outside of those defined in MODE.
+ We DO care about all the bits in MODE, even if XMODE is smaller than MODE.
For most X this is simply GET_MODE_MASK (GET_MODE (MODE)), but if X is
a shift, AND, or zero_extract, we can do better. */
&& subreg_lowpart_p (SET_DEST (setter)))
record_value_for_reg (dest, record_dead_insn,
WORD_REGISTER_OPERATIONS
+ && word_register_operation_p (SET_SRC (setter))
&& paradoxical_subreg_p (SET_DEST (setter))
? SET_SRC (setter)
: gen_lowpart (GET_MODE (dest),
rtx set = single_set (insn);
if (!set)
continue;
+
rtx dest = SET_DEST (set);
- if (dest == pc_rtx)
- continue;
+ if (!(REG_P (dest) && !HARD_REGISTER_P (dest)))
+ continue;
+
rtx src = SET_SRC (set);
if (!(REG_P (src) && HARD_REGISTER_P (src)))
continue;