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

Reply via email to