https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103383

--- Comment #11 from Álvaro "G. M." <alvaro.gamez at hazent dot com> ---
(In reply to Álvaro "G. M." from comment #10)
> Created attachment 62778 [details]
> Patch against 15.2.0 to solve this issue

Hi,

Just wanted to confirm that this bug still exists on gcc-15.2.0

I discovered it because compiling Linux for a microblaze CPU was leaving me
with a functional system but in which I didn't have IP connectivity: not even
ping to localhost. After quite a journey, I discovered that the culprit was in
calls to htons next to a condition. One of them was this function:

static void inline iph_set_totlen(struct iphdr *iph, unsigned int len)
{
        iph->tot_len = (len <= 0xFFFFU) ? htons(len) : 0;
}


Which, when inlined in this function:

int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
        struct iphdr *iph = ip_hdr(skb);

        IP_INC_STATS(net, IPSTATS_MIB_OUTREQUESTS);

        my_iph_set_totlen(iph, skb->len);
        ip_send_check(iph);

        /* if egress device is enslaved to an L3 master device pass the
         * skb to its handler for processing
         */
        skb = l3mdev_ip_out(sk, skb);
        if (unlikely(!skb))
                return 0;

        skb->protocol = htons(ETH_P_IP);

        return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
                       net, sk, skb, NULL, skb_dst_dev(skb),
                       dst_output);
}


will produce code like this:

        lwi     r4,r19,80
        addik   r5,r0,65535
        cmpu    r18,r4,r5
        bgeid   r18,$L608
        swapb r3, r4
   swaph r3, r3
        addk    r3,r0,r0
$L608:
        addk    r5,r22,r0


But when not inlined, it would produce this:

my_iph_set_totlen:
        .frame  r1,0,r15                # vars= 0, regs= 0, args= 0
        .mask   0x00000000
        addik   r4,r0,65535
        cmpu    r18,r6,r4
        bltid   r18,$L59
        addk    r3,r0,r0
        swapb r3, r6
   swaph r3, r3
$L59:
        rtsd    r15,8 

        shi     r3,r5,2
        .end    my_iph_set_totlen


The change from bltid to bgeid will produce that opposite of what is intended,
instead of assigning the value of htons(len), it would effectively set the
variable to 0.

Applying the patch provided by Andrew Pinski in comment #2 solved the issue and
I got kernel kernel 6.12 to work perfectly (as for now) with the full IP stack:


> I think this patch fixes the problem:
> diff --git a/gcc/config/microblaze/microblaze.md
> b/gcc/config/microblaze/microblaze.md
> index 6d77752cbfd..ca4bd976a5c 100644
> --- a/gcc/config/microblaze/microblaze.md
> +++ b/gcc/config/microblaze/microblaze.md
> @@ -372,7 +372,8 @@ (define_insn "bswaphi2"
>    "TARGET_REORDER"
>    "swapb %0, %1
>     swaph %0, %0"
> -)
> +  [(set_attr "length"  "8")
> +   (set_attr "type"     "no_delay_arith")])
> 
>  ;;----------------------------------------------------------------
>  ;; Microblaze delay slot description
> 
> 

If I need to rebase this patch against an specific commit or branch to have
this merged upstream, please let me know.

Thanks

Reply via email to