extern bool riscv_split_symbol (rtx, rtx, machine_mode, rtx *);
extern bool riscv_split_symbol_type (enum riscv_symbol_type);
extern rtx riscv_unspec_address (rtx, enum riscv_symbol_type);
-extern void riscv_move_integer (rtx, rtx, HOST_WIDE_INT, machine_mode);
+extern void riscv_move_integer (rtx, rtx, HOST_WIDE_INT);
extern bool riscv_legitimize_move (machine_mode, rtx, rtx);
extern rtx riscv_subword (rtx, bool);
extern bool riscv_split_64bit_move_p (rtx, rtx);
bool eq_neg = (loval == hival) && ((loval & 0x80000000) != 0);
if (eq_neg)
- riscv_move_integer (lo, lo, ~loval & 0xffffffff, mode);
+ riscv_move_integer (lo, lo, ~loval & 0xffffffff);
else
- riscv_move_integer (lo, lo, loval, mode);
+ riscv_move_integer (lo, lo, loval);
if (loval == hival)
hi = gen_rtx_ASHIFT (mode, lo, GEN_INT (32));
else
{
- riscv_move_integer (hi, hi, hival, mode);
+ riscv_move_integer (hi, hi, hival);
hi = gen_rtx_ASHIFT (mode, hi, GEN_INT (32));
}
is the original src mode before promotion. */
void
-riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value,
- machine_mode orig_mode)
+riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value)
{
struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS];
machine_mode mode;
rtx x = NULL_RTX;
mode = GET_MODE (dest);
- /* We use the original mode for the riscv_build_integer call, because HImode
- values are given special treatment. */
- num_ops = riscv_build_integer (codes, value, orig_mode, can_create_pseudo_p ());
+ /* This originally passed in a mode prior to promotions, but what we really
+ need to do is pass in the mode of the destination, that's what ultimately
+ determines how a constant needs to be canonicalized. */
+ num_ops = riscv_build_integer (codes, value, mode, can_create_pseudo_p ());
if (can_create_pseudo_p () && num_ops > 2 /* not a simple constant */
&& num_ops >= riscv_split_integer_cost (value))
/* Split moves of big integers into smaller pieces. */
if (splittable_const_int_operand (src, mode))
{
- riscv_move_integer (dest, dest, INTVAL (src), mode);
+ riscv_move_integer (dest, dest, INTVAL (src));
return;
}
if (splittable_const_int_operand (src, mode))
{
reg = gen_reg_rtx (promoted_mode);
- riscv_move_integer (reg, reg, INTVAL (src), mode);
+ riscv_move_integer (reg, reg, INTVAL (src));
}
else
reg = force_reg (promoted_mode, src);
}
}
+ /* If SRC_EQV is a CONST_INT, try looking up some related
+ constants (logical and arithmetic negation). Those may
+ ultimately be cheaper to re-use. */
+ if (GET_CODE (src) != CONST_INT
+ && GET_CODE (src) != REG
+ && GET_CODE (src) != SUBREG
+ && src_const
+ && GET_CODE (src_const) == CONST_INT)
+ {
+ rtx trial_rtx = GEN_INT (~UINTVAL (src_const));
+ struct table_elt *tmp = lookup (trial_rtx, HASH (trial_rtx, mode), mode);
+ rtx_code code = NOT;
+ if (!tmp)
+ {
+ trial_rtx = GEN_INT (-UINTVAL (src_const));
+ tmp = lookup (trial_rtx, HASH (trial_rtx, mode), mode);
+ code = NEG;
+ }
+
+ if (tmp)
+ {
+ src_related = gen_rtx_fmt_e (code, mode, tmp->first_same_value->exp);
+ src_eqv_here = src_related;
+ src_related_is_const_anchor = true;
+ }
+
+ }
+
/* See if a MEM has already been loaded with a widening operation;
if it has, we can use a subreg of that. Many CISC machines
also have such operations, but this is only likely to be