Bug 89270

Summary: [11/12/13 regression] AVR ICE: verify_gimple failed
Product: gcc Reporter: gandalf
Component: targetAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: jakub, jsm28, rguenth, saaadhu
Priority: P4 Keywords: addr-space, ice-on-valid-code
Version: 9.0   
Target Milestone: 11.5   
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112830
Host: Target: avr
Build: Known to work: 14.0
Known to fail: Last reconfirmed: 2023-12-04 00:00:00

Description gandalf 2019-02-09 20:10:57 UTC
I get an ICE on the following code with GCC 9.0.1 20190209 (experimental) compiled for AVR. Works in GCC 8.x.

void test()
{
  extern const unsigned char __memx __data_load_end;
  __uint24 top=(__uint24)&__data_load_end;
}

# avr-gcc -v -save-temps -mmcu=atmega1284p -c test2.c -o test.o
Using built-in specs.
Reading specs from /usr/local/avr/lib/gcc/avr/9.0.1/device-specs/specs-atmega1284p
COLLECT_GCC=avr-gcc
Target: avr
Configured with: ../configure --target=avr --prefix=/usr/local/avr --disable-nls --enable-languages=c --disable-bootstrap --disable-libssp
Thread model: single
gcc version 9.0.1 20190209 (experimental) (GCC) 
COLLECT_GCC_OPTIONS='-v' '-save-temps'  '-c' '-o' 'test.o' '-specs=device-specs/specs-atmega1284p' '-mmcu=avr51'
 /usr/local/avr/libexec/gcc/avr/9.0.1/cc1 -E -quiet -v -imultilib avr51 -D__AVR_ATmega1284P__ -D__AVR_DEVICE_NAME__=atmega1284p test2.c -mn-flash=2 -mno-skip-bug -mmcu=avr51 -fpch-preprocess -o test2.i
ignoring nonexistent directory "/usr/local/avr/lib/gcc/avr/9.0.1/../../../../avr/sys-include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/avr/lib/gcc/avr/9.0.1/include
 /usr/local/avr/lib/gcc/avr/9.0.1/include-fixed
 /usr/local/avr/lib/gcc/avr/9.0.1/../../../../avr/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-save-temps'  '-c' '-o' 'test.o' '-specs=device-specs/specs-atmega1284p' '-mmcu=avr51'
 /usr/local/avr/libexec/gcc/avr/9.0.1/cc1 -fpreprocessed test2.i -mn-flash=2 -mno-skip-bug -quiet -dumpbase test2.c -mmcu=avr51 -auxbase-strip test.o -version -o test2.s
GNU C17 (GCC) version 9.0.1 20190209 (experimental) (avr)
        compiled by GNU C version 8.2.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0, isl version none
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
GNU C17 (GCC) version 9.0.1 20190209 (experimental) (avr)
        compiled by GNU C version 8.2.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0, isl version none
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Compiler executable checksum: 7a3227a0716f5444cb50a3b2fc4e4212
test2.c: In function 'test':
test2.c:1:6: error: invalid types in nop conversion
    1 | void test()
      |      ^~~~
long int
const <address-space-7> unsigned char *
_1 = (long int) &__data_load_end;
test2.c:1:6: internal compiler error: verify_gimple failed
0xc5df1d verify_gimple_in_seq(gimple*)
        ../../gcc/tree-cfg.c:5094
0x9f42f5 gimplify_body(tree_node*, bool)
        ../../gcc/gimplify.c:13701
0x9f44e4 gimplify_function_tree(tree_node*)
        ../../gcc/gimplify.c:13791
0x86ac77 cgraph_node::analyze()
        ../../gcc/cgraphunit.c:667
0x86d803 analyze_functions
        ../../gcc/cgraphunit.c:1126
0x86e4e2 symbol_table::finalize_compilation_unit()
        ../../gcc/cgraphunit.c:2834
Comment 1 Richard Biener 2019-02-14 09:56:22 UTC
Not sure, but possibly not returning false here:

static bool
verify_gimple_assign_unary (gassign *stmt)
{
..
        /* Allow conversions from pointer type to integral type only if
           there is no sign or zero extension involved.
           For targets were the precision of ptrofftype doesn't match that
           of pointers we need to allow arbitrary conversions to ptrofftype.  */
        if ((POINTER_TYPE_P (lhs_type)
             && INTEGRAL_TYPE_P (rhs1_type))
            || (POINTER_TYPE_P (rhs1_type)
                && INTEGRAL_TYPE_P (lhs_type)
                && (TYPE_PRECISION (rhs1_type) >= TYPE_PRECISION (lhs_type)
                    || ptrofftype_p (lhs_type))))
          return false;

elsewhere I suggested that instead of special-casing ptrofftype_p we need
this special case only if POINTERS_EXTEND_UNSIGNED is defined and for
Pmode and word_mode lhs_type mode.

Not sure how named address-spaces are handled here since POINTERS_EXTEND_UNSIGNED
doesn't talk about them.
Comment 2 Georg-Johann Lay 2019-04-07 13:19:38 UTC
(In reply to gandalf from comment #0)
> I get an ICE

For the time being, you can work around this by a macro from AVR-LibC or some equivalent inline asm:

#include <avr/pgmspace.h>

void test()
{
    extern const char __data_load_end[];
    __uint24 top = (__uint24) pgm_get_far_address (__data_load_end);
}
Comment 3 gandalf 2019-04-07 16:56:32 UTC
(In reply to Georg-Johann Lay from comment #2)
> For the time being, you can work around this by a macro from AVR-LibC or
> some equivalent inline asm

Thanks, that workaround does indeed work (and with slightly smaller code generated as well).
Comment 4 Jakub Jelinek 2019-05-03 09:16:22 UTC
GCC 9.1 has been released.
Comment 5 Jakub Jelinek 2019-08-12 08:55:29 UTC
GCC 9.2 has been released.
Comment 6 Jakub Jelinek 2020-03-12 11:58:45 UTC
GCC 9.3.0 has been released, adjusting target milestone.
Comment 7 Richard Biener 2021-06-01 08:13:03 UTC
GCC 9.4 is being released, retargeting bugs to GCC 9.5.
Comment 8 Richard Biener 2022-05-27 09:40:11 UTC
GCC 9 branch is being closed
Comment 9 Jakub Jelinek 2022-06-28 10:36:39 UTC
GCC 10.4 is being released, retargeting bugs to GCC 10.5.
Comment 10 Richard Biener 2023-07-07 10:34:49 UTC
GCC 10 branch is being closed.
Comment 11 Andrew Pinski 2023-12-03 21:59:18 UTC
*** Bug 91354 has been marked as a duplicate of this bug. ***
Comment 12 Richard Biener 2023-12-04 13:03:07 UTC
Confirmed.  We have a NOP_EXPR from the 24bit pointer __memx address-space
to long int (32bit).  That's an extension and we don't know how to do that
since POINTERS_EXTEND_UNSIGNED is not defined for AVR.  Note that
for GIMPLE verification the exception would be

#if defined(POINTERS_EXTEND_UNSIGNED)
                    || (TYPE_MODE (rhs1_type) == ptr_mode
                        && (TYPE_PRECISION (lhs_type)
                              == BITS_PER_WORD /* word_mode */
                            || (TYPE_PRECISION (lhs_type)
                                  == GET_MODE_PRECISION (Pmode))))
#endif

but that's currently written without address-spaces in mind (because
POINTERS_EXTEND_UNSIGNED is defined without address-spaces in mind).

I think the "bug" is that the C frontend emits

  extern const <address-space-7> unsigned char __data_load_end;
  __uint24 top = (__uint24) (long int) &__data_load_end;

so it inserts the widening to 'long int' here.  And that's the fault of
convert.cc:convert_to_integer_1 which does

      /* Convert to an unsigned integer of the correct width first, and from
         there widen/truncate to the required type.  Some targets support the
         coexistence of multiple valid pointer sizes, so fetch the one we need
         from the type.  */
      if (!dofold)
        return build1 (CONVERT_EXPR, type, expr);
      expr = fold_build1 (CONVERT_EXPR,
                          lang_hooks.types.type_for_size
                            (TYPE_PRECISION (intype), 0),
                          expr);
      return fold_convert (type, expr);

using type_for_mode would have yielded the __int24 type here.

The code is more or less present since the original version of convert.c

I'd argue the most correct way to deal with this is to _remove_ the
intermediate conversion done by convert.c since it only papers over
possible user errors?  The C standard says the only supported conversion
is to/from [u]intptr_t, that's probably what the above tried to do.
But then it looks like it doesn't achieve its intent.

Now, c_common_type_for_size doesn't handle registered_builtin_types
like c_common_type_for_mode does, so extending that to cover these
fixes the issue as well.
Comment 13 GCC Commits 2023-12-05 07:35:32 UTC
The master branch has been updated by Richard Biener <rguenth@gcc.gnu.org>:

https://gcc.gnu.org/g:4dd02d62abd76a69f65d9f3fed6febeed53fc90a

commit r14-6134-g4dd02d62abd76a69f65d9f3fed6febeed53fc90a
Author: Richard Biener <rguenther@suse.de>
Date:   Mon Dec 4 14:03:37 2023 +0100

    c/89270 - honor registered_builtin_types in type_for_size
    
    The following fixes the intermediate conversions inserted by
    convert_to_integer when facing address-spaces and converts
    to their effective [u]intptr_t when they are registered_builtin_types
    by considering those also from c_common_type_for_size and not
    only from c_common_type_for_mode.
    
            PR c/89270
    gcc/c-family/
            * c-common.cc (c_common_type_for_size): Consider
            registered_builtin_types.
    
    gcc/testsuite/
            * gcc.target/avr/pr89270.c: New testcase.
Comment 14 Richard Biener 2023-12-05 07:37:50 UTC
Fixed on trunk sofar.  Joseph correctly mentioned that iff AVR would define
__int24 using INT_N in avr-modes.def the issue would have been mitigated as well
(that's a comparatively "modern" way of registering additional integer types).

So it's really also a target issue.

I'm not planning to backport this frontend change given a more targeted fix would be available.