Hi,
This is one of two separate small patches to help PR125390 where we
ICE during expand. In riscv's legitimize_move we have a case that
deals with scalar subregs of vectors and in an attempt to fix the ICE
I restricted the (supposedly) optimization to non-tuple types.
Interestingly, this lead to a different infinite loop:
riscv provides OImode but offers no corresponding movoi expander.
In expmed we try to pun with an integer subreg like
(subreg:OI (reg:RVVMF2x2SI ...))
which would normally go via force_reg and emit_move_multi_word which
uses operand_subword.
If the target dosn't have either, a move<mode> or a viable
operand_subword, this patch takes the memory route.
Granted, the guard seems a bit clunky and ad-hoc here, but I didn't find a
great way to fall back later. Better ideas welcome of course.
Bootstrapped and regtested on x86, power10, and aarch64.
Regtested on riscv64.
Regards
Robin
PR middle-end/125390
gcc/ChangeLog:
* expmed.cc (extract_bit_field_1): Guard int-mode punning.
---
gcc/expmed.cc | 10 +++++++++-
gcc/expr.cc | 2 +-
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/gcc/expmed.cc b/gcc/expmed.cc
index da1b5b63287..0efc247ddba 100644
--- a/gcc/expmed.cc
+++ b/gcc/expmed.cc
@@ -1839,7 +1839,14 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize,
poly_uint64 bitnum,
if (MEM_P (op0))
op0 = adjust_bitfield_address_size (op0, op0_mode.else_blk (),
0, MEM_SIZE (op0));
- else if (op0_mode.exists (&imode))
+ /* Vectors can be punned with large integer modes that might
+ not have corresponding mov<mode> insns. The usual route
+ is then through emit_move_multi_word, but that only works if
+ the source register can be split into words. */
+ else if (op0_mode.exists (&imode)
+ && (optab_handler (mov_optab, imode) != CODE_FOR_nothing
+ || operand_subword (gen_lowpart (imode, op0),
+ 1, 0, imode)))
{
op0 = gen_lowpart (imode, op0);
@@ -1854,6 +1861,7 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize,
poly_uint64 bitnum,
rtx mem = assign_stack_temp (GET_MODE (op0), size);
emit_move_insn (mem, op0);
op0 = adjust_bitfield_address_size (mem, BLKmode, 0, size);
+ op0_mode = opt_scalar_int_mode ();
}
}
diff --git a/gcc/expr.cc b/gcc/expr.cc
index e4f0eeb2b5b..b5cd65e8bd1 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -12331,7 +12331,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode
tmode,
/* Check if we're dealing with a vector-tuple type extraction.
If so, and the bitfield size does not overlap multiple
- vectors, force the respective (single) vector into a register
+ vectors, force the respective single vector into a register
and use that for the extraction steps below. */
tree from = TREE_OPERAND (exp, 0);
if (!must_force_mem
--
2.54.0