On Fri, 11 Sep 2026, Dominic P wrote:

> Hi Richard,
> 
> this grows code with nothing gained on the paths it threads, on arm and
> x86_64 alike.  Reduced from lwip's ip4_frag.c:
> 
>   struct hdr { unsigned int src, dest; unsigned short id; };
>   struct dg { struct dg *next; struct hdr iphdr; unsigned char timer; };
>   struct dg *list;
>   extern int free_dg (struct dg *);
>   int
>   remove_oldest (struct hdr *fh, int needed)
>   {
>     struct dg *r, *oldest;
>     int freed = 0, others;
>     do {
>       oldest = 0;
>       others = 0;
>       for (r = list; r != 0; r = r->next)
>         if (!(r->iphdr.src == fh->src && r->iphdr.dest == fh->dest
>               && r->iphdr.id == fh->id))
>           {
>             others++;
>             if (oldest == 0 || r->timer <= oldest->timer)
>               oldest = r;
>           }
>       if (oldest != 0)
>         freed += free_dg (oldest);
>     } while (freed < needed && others > 1);
>     return freed;
>   }
> 
> At -O2, remove_oldest is 280 -> 336 bytes on arm (-marm
> -mcpu=arm1176jzf-s, trunk 20260722 vs 20260817) and 264 -> 296 on
> x86_64 (16.2.1 vs trunk 20260908); with -fno-thread-jumps both pairs
> are identical, so the whole difference is the two threads threadfull2
> now registers, 15->6->8->22 and 4->5->8->17 on both targets, which end
> on the inner loop's exit and copy the three-compare match chain a second
> time.  The output is unchanged for every input I tried, so it is size
> only.  On the whole firmware this one change is +1.5 KB of 296 KB, 96%
> of the .text growth between those two snapshots.
> 
> Is the loop-exit case meant to be bounded by the same duplication limit
> as the other paths?  --param max-jump-thread-duplication-stmts=14 keeps
> this one out, but also drops threads that were paying for themselves
> before.

The case was supposed to unlock cases that were disabled because
of the duplicating engine support unnecessarily.  It only
duplicates one path,

jump thread: (15, 6) incoming edge;  (6, 8) normal (back) (8, 22) nocopy;

where the threaded edge is not a loop exit but instead
this is a normal thread where I fail to see what should
have failed to handle this before.  The threading removes
one dynamic branch on one of the innermost loops exit
(at the expense of some copying), so exactly what jump
threading is supposed to do.

Richard.

> Thanks,
> Dominic
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to