aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/riscv/riscv.cc46
1 files changed, 41 insertions, 5 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index a38cb72..39489c4 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -4218,11 +4218,29 @@ riscv_noce_conversion_profitable_p (rtx_insn *seq,
riscv_if_info.original_cost += COSTS_N_INSNS (1);
riscv_if_info.max_seq_cost += COSTS_N_INSNS (1);
}
- last_dest = NULL_RTX;
+
rtx dest = SET_DEST (x);
- if (COMPARISON_P (src)
+
+ /* Do something similar for the moves that are likely to
+ turn into NOP moves by the time the register allocator is
+ done. These are also side effects of how our sCC expanders
+ work. We'll want to check and update LAST_DEST here too. */
+ if (last_dest
&& REG_P (dest)
- && GET_MODE (dest) == SImode)
+ && GET_MODE (dest) == SImode
+ && SUBREG_P (src)
+ && SUBREG_PROMOTED_VAR_P (src)
+ && REGNO (SUBREG_REG (src)) == REGNO (last_dest))
+ {
+ riscv_if_info.original_cost += COSTS_N_INSNS (1);
+ riscv_if_info.max_seq_cost += COSTS_N_INSNS (1);
+ if (last_dest)
+ last_dest = dest;
+ }
+ else
+ last_dest = NULL_RTX;
+
+ if (COMPARISON_P (src) && REG_P (dest))
last_dest = dest;
}
else
@@ -4904,13 +4922,31 @@ riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1, bool *in
riscv_extend_comparands (code, &op0, &op1);
op0 = force_reg (word_mode, op0);
+ /* For sub-word targets on rv64, do the computation in DImode
+ then extract the lowpart for the final target, marking it
+ as sign extended. Note that it's also properly zero extended,
+ but it's probably more profitable to expose it as sign extended. */
+ rtx t;
+ if (TARGET_64BIT && GET_MODE (target) == SImode)
+ t = gen_reg_rtx (DImode);
+ else
+ t = target;
+
if (code == EQ || code == NE)
{
rtx zie = riscv_zero_if_equal (op0, op1);
- riscv_emit_binary (code, target, zie, const0_rtx);
+ riscv_emit_binary (code, t, zie, const0_rtx);
}
else
- riscv_emit_int_order_test (code, invert_ptr, target, op0, op1);
+ riscv_emit_int_order_test (code, invert_ptr, t, op0, op1);
+
+ if (t != target)
+ {
+ t = gen_lowpart (SImode, t);
+ SUBREG_PROMOTED_VAR_P (t) = 1;
+ SUBREG_PROMOTED_SET (t, SRP_SIGNED);
+ emit_move_insn (target, t);
+ }
}
/* Like riscv_expand_int_scc, but for floating-point comparisons. */