On Wed, 6 Aug 2025, ywgrit wrote:

> I have the following question:
> 
> // Way.h
> struct waymapt
> {
>   int fillnum;
>   int num;
> };
> typedef waymapt* waymappt;
> 
> class wayobj
> {
> public:
>     int bound;
>     int *maparp;
>     waymappt waymap;
>     int makebound2(int fillnum, int iters);
>     void create(int size);
> };
> 
> 
> // WayInit.cpp
> #include <cstring>
> #include "Way.h"
> 
> void wayobj::create(int size)
> {
>   maparp=new int[size];
>   waymap=new waymapt[size];
> }
> 
> 
> // Way.cpp
> #include "Way.h"
> int wayobj::makebound2(int fillnum, int iters)
> {
>   for (int i = 0; i < iters; i++)
>   {
>     if (waymap[i].fillnum!=fillnum)
>       if (maparp[i]!=0)
>         bound++;
>   }
>   return bound;
> }
> 
> 
> // main.cpp
> #include <cstdio>
> #include "Way.h"
> 
> #define SIZE 16
> int main() {
>   wayobj *woj = new wayobj;
>   woj->create(SIZE);
>   woj->makebound2(10, SIZE);
> 
>   printf("bound == %d\n", woj->bound);
>   return 0;
> }
> 
> Both maparp and waymap of wayobj are arrays, and in the function
> wayobj::create, the same number of elements are allocated for both arrays.
> In function makebound2, if (maparp[i]! = 0) is within if
> (waymap[i].fillnum!=fillnum). So if "if (waymap[i].fillnum!=fillnum)" won't
> trap, then "if (maparp[i]! = 0)" won't trap either. Is there a way we can
> tell that the inner branch won't trap by the relationship between the outer
> branch and the inner branch?

No.  Both data members (the waymap and maparp pointers) can be
freely modified, so even when they closely relate in size at CTOR
time there's no way to prove this relationship holds at
makebound2 time.  Not using constraints imposed by the C++ language
and even less so with constraints that can be exercised by GCCs
middle-end.

For a benchmark hack (which likely ICC has plenty) I'd see to
look for all stores to wayobj::maparp/waymap (but in a somewhat
optimistic way) and see if they are only the allocation sites.

It's usually trivial to do an obfuscated example those benchmark
compilers miscompile (went through that in multiple instances
when trying to figure how the hell ICC can prove a transform
is correct).

The way to go for these kind of cases is to have good performance
analysis tools that suggest the user combine those branches
with a non-short-circuiting &

Richard.

  If this is possible then ifcombine pass can
> do a merge on this nested branch. In spec2006's 473.astar program, this
> nested branch is a hotspot with poor prediction accuracy, so the
> performance improvement after merging this nested branches is very
> significant. Icc merges this nested branch, but gcc doesn't.
> 
> 
> We modified the following source code in spec2006.473.astar
> if (waymap[i].fillnum!=fillnum)
>       if (maparp[i]!=0)
> 
> into
> 
> a = (waymap[index1].fillnum == fillnum) | maparp[index1] ;
> if(!a)
> 
> After the modification, gcc was able to merge the two branches, and we can
> see from the generated assembly that there is only one jmp instruction
> There is significant change in the number of branch-misses:
> gcc-not-combine: 1.5483E+10
> gcc-combine: 8.4778E+9
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to