diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc index 645aedba67f..d4e849b12de 100644 --- a/gcc/config/s390/s390.cc +++ b/gcc/config/s390/s390.cc @@ -8238,6 +8238,21 @@ s390_delegitimize_address (rtx orig_x) return plus_constant (Pmode, XVECEXP (y, 0, 0), offset); } + if (GET_CODE (x) == CONST) + { + /* Extract the symbol ref from: + (const:DI (unspec:DI [(symbol_ref:DI ("foo"))] + UNSPEC_PLT/GOTENT)) */ + + y = XEXP (x, 0); + if (GET_CODE (y) == UNSPEC + && (XINT (y, 1) == UNSPEC_GOTENT + || XINT (y, 1) == UNSPEC_PLT31)) + return XVECEXP (y, 0, 0); + else + return orig_x; + } + if (GET_CODE (x) != MEM) return orig_x; diff --git a/gcc/testsuite/gcc.target/s390/delegitimize-1.c b/gcc/testsuite/gcc.target/s390/delegitimize-1.c new file mode 100644 index 00000000000..5c49565db2f --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/delegitimize-1.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-m64 -fPIC -O2 -g -fdump-rtl-final-details" } */ + +struct sk_buff { + struct { + struct { + struct { + int inner_ipproto; + }; + }; + }; +}; +void skb_udp_tunnel_segment(struct sk_buff *skb); +const int *inet_offloads[42], *inet6_offloads[42]; +_Bool skb_udp_tunnel_segment_is_ipv6; +void skb_udp_tunnel_segment(struct sk_buff *skb) { + const int **offloads = + skb_udp_tunnel_segment_is_ipv6 ? inet6_offloads : inet_offloads; + *(volatile typeof(_Generic(0, default : 0)) *)&offloads[skb->inner_ipproto]; +} + +/* { dg-final { scan-rtl-dump-not "Failed to expand as dwarf:" "final" } } */