Hello,

This seems to be causing a build regression on the or1k port.

I have not quite figured it out yet but I have bisected to this commit.

The failure is as below, this seems to be caused by the cstoresi4 instruction 
produced by
or1k.md.  So I think its likely something we are doing funny in the port.

Thanks to Jeff for pointing this out.  If you have any idea let me know.

Log:

    during RTL pass: ce1
    dump file: libgcc2.c.286r.ce1
    /home/shorne/work/gnu-toolchain/gcc/libgcc/libgcc2.c: In function 
'__muldi3':
    /home/shorne/work/gnu-toolchain/gcc/libgcc/libgcc2.c:538:1: internal 
compiler error: in emit_move_multi_word, at expr.cc:4492
      538 | }
          | ^
    0x1b094df internal_error(char const*, ...)
            
/home/shorne/work/gnu-toolchain/gcc/gcc/diagnostic-global-context.cc:517
    0x6459c1 fancy_abort(char const*, int, char const*)
            /home/shorne/work/gnu-toolchain/gcc/gcc/diagnostic.cc:1815
    0x473a2e emit_move_multi_word
            /home/shorne/work/gnu-toolchain/gcc/gcc/expr.cc:4492
    0x93fd7d emit_move_insn(rtx_def*, rtx_def*)
            /home/shorne/work/gnu-toolchain/gcc/gcc/expr.cc:4746
    0x9175f1 copy_to_reg(rtx_def*)
            /home/shorne/work/gnu-toolchain/gcc/gcc/explow.cc:630
    0xd18977 gen_lowpart_general(machine_mode, rtx_def*)
            /home/shorne/work/gnu-toolchain/gcc/gcc/rtlhooks.cc:56
    0x9414c7 convert_mode_scalar
            /home/shorne/work/gnu-toolchain/gcc/gcc/expr.cc:818
    0x9421a1 convert_modes(machine_mode, machine_mode, rtx_def*, int)
            /home/shorne/work/gnu-toolchain/gcc/gcc/expr.cc:961
    0xc0afa0 prepare_operand(insn_code, rtx_def*, int, machine_mode, 
machine_mode, int)
            /home/shorne/work/gnu-toolchain/gcc/gcc/optabs.cc:4637
    0xc0b33a prepare_cmp_insn
            /home/shorne/work/gnu-toolchain/gcc/gcc/optabs.cc:4538
    0xc0f0dd emit_conditional_move(rtx_def*, rtx_comparison, rtx_def*, 
rtx_def*, machine_mode, int)
            /home/shorne/work/gnu-toolchain/gcc/gcc/optabs.cc:5098
    0x192cc7b noce_emit_cmove
            /home/shorne/work/gnu-toolchain/gcc/gcc/ifcvt.cc:1777
    0x193365b try_emit_cmove_seq
            /home/shorne/work/gnu-toolchain/gcc/gcc/ifcvt.cc:3410
    0x193365b noce_convert_multiple_sets_1
            /home/shorne/work/gnu-toolchain/gcc/gcc/ifcvt.cc:3705
    0x1933c71 noce_convert_multiple_sets
            /home/shorne/work/gnu-toolchain/gcc/gcc/ifcvt.cc:3496
    0x1938687 noce_process_if_block
            /home/shorne/work/gnu-toolchain/gcc/gcc/ifcvt.cc:4045
    0x1938687 noce_find_if_block
            /home/shorne/work/gnu-toolchain/gcc/gcc/ifcvt.cc:4726
    0x1938687 find_if_header
            /home/shorne/work/gnu-toolchain/gcc/gcc/ifcvt.cc:4931
    0x1938687 if_convert
            /home/shorne/work/gnu-toolchain/gcc/gcc/ifcvt.cc:6078
    0x1938d01 rest_of_handle_if_conversion
            /home/shorne/work/gnu-toolchain/gcc/gcc/ifcvt.cc:6143

-Stafford

On Thu, May 15, 2025 at 10:33:49PM +0300, Dimitar Dimitrov wrote:
> When a paradoxical subreg is detected, validate_subreg exits early, thus
> skipping the important checks later in the function.
> 
> Fix by continuing with the checks instead of declaring early that the
> paradoxical subreg is valid.
> 
> One of the newly allowed subsequent checks needed to be disabled for
> paradoxical subregs.  It turned out that combine attempts to create
> a paradoxical subreg of mem even for strict-alignment targets.
> That is invalid and should eventually be rejected, but is
> temporarily left allowed to prevent regressions for
> armv8l-unknown-linux-gnueabihf.
> 
> Tests I did:
>  - No regressions were found for C and C++ for the following targets:
>    - native x86_64-pc-linux-gnu
>    - cross riscv64-unknown-linux-gnu
>    - cross riscv32-none-elf
>  - Sanity checked armv8l-unknown-linux-gnueabihf by cross-building
>    up to including libgcc. I'll monitor Linaro CI bot for the
>    full regression test results.
>  - Sanity checked powerpc64-unknown-linux-gnu by building native
>    toolchain, but could not setup qemu-user for DejaGnu testing.
> 
>       PR target/119966
> 
> gcc/ChangeLog:
> 
>       * emit-rtl.cc (validate_subreg): Do not exit immediately for
>       paradoxical subregs.  Filter subsequent tests which are
>       not valid for paradoxical subregs.
> 
> Co-authored-by: Richard Sandiford <richard.sandif...@arm.com>
> Signed-off-by: Dimitar Dimitrov <dimi...@dinux.eu>
> ---
>  gcc/emit-rtl.cc | 25 ++++++++++++++++++-------
>  1 file changed, 18 insertions(+), 7 deletions(-)
> 
> diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
> index 3e2c4309dee..e46b0f9eac4 100644
> --- a/gcc/emit-rtl.cc
> +++ b/gcc/emit-rtl.cc
> @@ -969,10 +969,10 @@ validate_subreg (machine_mode omode, machine_mode imode,
>      }
>  
>    /* Paradoxical subregs must have offset zero.  */
> -  if (maybe_gt (osize, isize))
> -    return known_eq (offset, 0U);
> +  if (maybe_gt (osize, isize) && !known_eq (offset, 0U))
> +    return false;
>  
> -  /* This is a normal subreg.  Verify that the offset is representable.  */
> +  /* Verify that the offset is representable.  */
>  
>    /* For hard registers, we already have most of these rules collected in
>       subreg_offset_representable_p.  */
> @@ -988,9 +988,13 @@ validate_subreg (machine_mode omode, machine_mode imode,
>  
>        return subreg_offset_representable_p (regno, imode, offset, omode);
>      }
> -  /* Do not allow SUBREG with stricter alignment than the inner MEM.  */
> +  /* Do not allow normal SUBREG with stricter alignment than the inner MEM.
> +
> +     FIXME: Combine can create paradoxical mem subregs even for
> +     strict-alignment targets.  Allow it until combine is fixed.  */
>    else if (reg && MEM_P (reg) && STRICT_ALIGNMENT
> -        && MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (omode))
> +        && MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (omode)
> +        && known_le (osize, isize))
>      return false;
>  
>    /* The outer size must be ordered wrt the register size, otherwise
> @@ -999,7 +1003,7 @@ validate_subreg (machine_mode omode, machine_mode imode,
>    if (!ordered_p (osize, regsize))
>      return false;
>  
> -  /* For pseudo registers, we want most of the same checks.  Namely:
> +  /* For normal pseudo registers, we want most of the same checks.  Namely:
>  
>       Assume that the pseudo register will be allocated to hard registers
>       that can hold REGSIZE bytes each.  If OSIZE is not a multiple of 
> REGSIZE,
> @@ -1008,8 +1012,15 @@ validate_subreg (machine_mode omode, machine_mode 
> imode,
>       otherwise it is at the lowest offset.
>  
>       Given that we've already checked the mode and offset alignment,
> -     we only have to check subblock subregs here.  */
> +     we only have to check subblock subregs here.
> +
> +     For paradoxical little-endian registers, this check is redundant.  The
> +     offset has already been validated to be zero.
> +
> +     For paradoxical big-endian registers, this check is not valid
> +     because the offset is zero.  */
>    if (maybe_lt (osize, regsize)
> +      && known_le (osize, isize)
>        && ! (lra_in_progress && (FLOAT_MODE_P (imode) || FLOAT_MODE_P 
> (omode))))
>      {
>        /* It is invalid for the target to pick a register size for a mode
> -- 
> 2.49.0
> 

Reply via email to