gcc bug vagy en vagyok a hulye (szokas szerint)?

Fórumok

Van egy kb 25 eve irt kodreszlet, ami akkoriban (2.9x gcc-vel) mukodott jol, most pedig gcc 11.x-el mar nem mindig (nehez reprodukalni, nem mindig szar csak ritkan). Ha belerakok egy printf-et akkor viszont jol mukodik, ezert gondolom h valami optimalizalasi bug lehet. Probaltam volatile-t is irni a deklaraciohoz, bar elvileg nem kene, de az sem segitett rajta. Ha a hibakezelest (if..return 0) is kivettem, akkor se lett jobb.

Mi a hiba? :)

 

INLINE static int afs_fread_dword(dword *ptr,int s1,int s2,afs_FILE *f){
  int s=s1*s2/4;
  while(s>0){
    volatile dword c;
    if(afs_fread(&c,sizeof(c),1,f)!=1) return 0;
    printf("   s=%d c=0x%08X ptr=%p\n",s,c,ptr);
#ifdef REVERSE_BYTEORDER
    c= ((c>>24)&0xFF) | (((c>>16)&0xFF)<<8) | (((c>>8)&0xFF)<<16) | ((c&0xFF)<<24);
#endif
    *ptr=c; ++ptr;
    --s;
  }
  return s2;
}

 

kiirattam a parameteretekt, az s2 mindig 1, az s1 pedig 4/8/12/16/32 tehat nem lehet az a baja, hogy nem oszthato 4-el (dword merete)

ha az egesz fuggveny belsejet kicserelem erre az 1 sorra, akkor is jol mukodik:   return afs_fread(ptr,s1,s2,f);

Hozzászólások

Mit csinal? Mit nem kellene csinalnia?

A strange game. The only winning move is not to play. How about a nice game of chess?

ugyanazt mint a posix/libc fread(), csak extrakent opcionalisan kezeli a byteorder swap-et. szoval semmi extrat.

ha csak siman meghivja az fread-et akkor mukodik, de ha dwordonkent kulon hivogatja akkor meg nem jo neha. persze a printf megjavitja, szoval nem az fread reszevel van a baja, hanem a ciklust optimalizalja neha szarul a gcc...

A kodot elolvastam, es ertem. Mit jelent az, hogy "nem mukodik"?

Amugy milyen architektura, es a REVERSE_BYTEORDER be van kapcsolva, amikor nem megy? gcc -S-sel esetleg meg lehet nezni mire fordul. Ha tudod a bithosszt, uint32_t jobb dword helyett, bar itt nem azon mulik. Plusz te nyilvan tudod a muveleti sorrendet, de ezeket szeretem zarojelezni, mert tobb nyelvet hasznalok parhuzamosan, es fene tudja hol mi undefined behaviour: (s1*s2)/4 (ugye ha s2 mondjuk 3, es elobb osztja, s 0 lesz, es kilep)

Amugy asszem ha a forditott bytesorrend inaktiv, siman visszaternek az fread-del. A bitcserelgetesre is van muvelet, pl. itt alapvetoen nem jo ezeket ciklussal ujrairni, nem is lesz gyors, mas atgondolta helyettem, optimalizalta, es tesztelte.

Multithread kornyezet amugy? Amiatt is lehet ritkan elojovo hiba.

A strange game. The only winning move is not to play. How about a nice game of chess?

Arra, hogy ugyanide masik szalon is beter, mas thread is elkezd ebbol olvasgatni, es hulyeseg lesz az eredmeny. A printf megkavarja az idoziteseket, es ugy a szerencses veletlennek koszonhetoen kevesbe akad ossze.

A strange game. The only winning move is not to play. How about a nice game of chess?

> Mit jelent az, hogy "nem mukodik"?

ez egy .3ds file loaderben van, 3d modelleket tolt be es jelenit meg opengl-el, es neha el van fordulva 90 fokkal (gondolom valamelyik matrix szar) vagy 5x akkora meretu meg ilyenek. de mondjuk 20 filebol 1-nel van hiba, es mindig mas jellegu. megvan a 2000 novemberben forditott linuxos binarisom, az jol mukodik ugyanazzal az inputtal, es ugyanabbol a forrasbol most ujra forditva ujabb gcc-vel meg nem.

> REVERSE_BYTEORDER be van kapcsolva

most nincs. anno portoltam SGI irixre is, asszem amiatt kerult bele.

> uint32_t jobb dword helyett

ugyanaz, arra van typedefelve egy .h fileban.

> (s1*s2)/4 (ugye ha s2 mondjuk 3, es elobb osztja

elvileg (e smegneztem, gyakorlatilag is) mindig 4-el oszthato az input. szoval itt mind1.

> A bitcserelgetesre is van muvelet

tudom persze, de azert is kezdtem azzal hogy ez 25+ eves kod. es nem is linuxos volt eredetileg, dos alatt mas lehetosegek voltak.

> Multithread kornyezet amugy?

dehogy. ez meg dos-ra irt 25+ eves kod, amit anno watcom c-vel, aztan linuxon/irixen/aixen gcc-vel forditottam.

> siman visszaternek az fread-del

igen erre irtam at en is es ugy mukodik jol, csak kivancsi lennek mi a fenti kodban a hiba... mert regen az is ment :)

es neha el van fordulva 90 fokkal (gondolom valamelyik matrix szar) vagy 5x akkora meretu meg ilyenek

Akkor nem hinnem hogy itt ebben a kodreszletben lesz a hiba... ha egy float stream-be akarcsak egy bithiba csuszik, akkor teljesen osszeomlik egy ilyen modell, nemhogy "ja, csak el van forgatva", vagy "ja, kicsit nagyobb de hasonlo az eredetihez".  Ott nezd meg ahol az inline hivas tortenik. Vagy probald ki azt hogy ezt a fuggvenyt kiteszed egy masik *.c fileba, ugy forditod ossze a kettot hogy meg veletlenul se lehessen inline optimalizacio es ne legyen semmi side effect-je barmi code reordering es/vagy interleavingnak. Nem kizart hogy a printf() megakadalyozza ezutobbit, es akkor ugy mar jo, egyebkent meg annyira cafatokra optimalizalhato hogy a hivo oldalon valami bug beszivarog oda oszt kesz is a baj. 

nekem is fura. amugy van olyan model ami total szet van esve, 1 van aahol kb 5x akkora lett 1 object (de a tobbi obj jo), meg van egy ami el van fordulva. az elfordultast akar az is okozhatna ha el van csuszva 1-el, igy az x-bol y lesz, az y-bol z stb.

> "ja, csak el van forgatva"

emlekeim szerint a 3ds-ben euler forgatas volt, tehat a tengelyenkenti elforgatasi szog volt tarolva. ha ez kinullazodik, az okozhatja ezt (gondolom a legtobb obj-nel ez eleve 0,0,0 de lehet nehany ahol mondjuk 90,0,0 es ha abbol 0,0,0 lesz akkor elfordul)

a meret elteres is lehet akar abbol hogy az az obj sokkal kozelebb van a "kamerahoz" ezert tunik csak nagynak, ezt meg okozhatja a transzormacios vektor nullazodasa.

> Ott nezd meg ahol az inline hivas tortenik

hat 57 helyrol hivja ezt, rakas chunk tipus van es mindegyikben van nehany call.

> Vagy probald ki azt

az a baj hogy szinte barmit modositok a kodon, megjavul. ezert is gyanaxom gcc bugra, hogy valamit elront optimalizalaskor.

csak arra voltam kivancsi, hogy en neztem be valamit, vagy a kod elvileg jo csak a compiler hulye (vagy mashol van valami bug, ami emiatt triggerelodik)

Egyre erdekesebb ez a problema, tenyleg :)

Akkor azt probalnam meg hogy beolvasas utan visszairnam egy file-ba az egeszet es megnezem hogy hol esik szet, melyik ponton es mi modusul (sima hexdump -v, es a ket hexet tkdiff-fel osszenezni, ilyesmi). Akkor be tudod hatarolni azt a pontot az 57-bol (leszukiteni joesetben 1-re, rosszabb esetben nehanyra) ahol szetcsuszik es a hivo oldalon is korulneznek mindenfele bugok kapcsan. 

Koszi a valaszokat! Az afs_fread-et meg betenned ide?

Egyebkent siman lehet az is, hogy a gcc valami SIMD trukkozest probal, es a printf megakadalyozza ebben. De ez persze a masik fuggvenytol is fugg (afs_fread). Ha az egyszeru, akkor lehet ez a gond.

A strange game. The only winning move is not to play. How about a nice game of chess?

int afs_fread(void *ptr,int elemsize,int elemno,afs_FILE* f){
  int size=elemsize*elemno;
//  printf("AFS: fread %d x %d, current pos=%d\n",elemsize,elemno,f->pos);
  if(size>f->size-f->pos) size=f->size-f->pos;
  memcpy(ptr,f->ptr+f->pos,size);
  f->pos+=size;
  return size/elemsize;
}

 

azt hittem fread()-ot itt hivja de nem, az afs_fopen()-nel beolvassa memoriaba az egeszet. gondolom azert lett igy megoldva mert elesben mindig egy nagy tomoritett filebol toltotte be a cuccot, csak fejleszteshez/teszteleshez volt kozvetlen file olvasas.

de nem hiszem hogy ennek sok jelentosege van, ez nem inline es egy kulon lib-ben van.

Ennyit mondjuk siman inline-olhat. (foleg, ha rajon, hogy a size fixen 4, es a memcpy is kioptimalizalhato belole)

szerk: (szerk. utan) akkor nincs inline

A strange game. The only winning move is not to play. How about a nice game of chess?

Generált kódot kiíratni a gcc-vel (azt hiszem tud ilyet) és megnézni mi a különbség a működő és nem működő között? Ha valamit elront, ott látni.

"Az élet tele van kérdésekkel. Az idióták tele vannak válaszokkal."

"Its easier to fool a man than it is to convince they have been fooled"

Szerkesztve: 2023. 12. 10., v – 16:01

Én azt nem értem, miért van a c deklarálása a ciklusmagon belül. Az mire jó? Az INLINE nagybetű?

Azon tűnődöm, hogy amikor ez inline, akkor bekerül közvetlenül a kódba a hívás helyére. Amikor c-t deklarálod, létrejön adott címen, de engem frusztrál, hogy mi van többszöri hívás esetén. Az &c hivatkozás fordítási időben dönti el c címét, de ennek az inline függvénynek a c változója hova allokálódik? Lehet, a while-on kívülre a függvény elejére tenném valahogy így:

static dword c;

Mert akkor az valahova le van téve, nem akar máshova kerülni, fordítási időben meg lehet álmodni a címét. Vagy a másik lehetőség, hogy ne legyen inline.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

> miért van a c deklarálása a ciklusmagon belül.

eredetileg a while-on kivul volt (de nem static), csak probaltam berakni, de nem valtoztatott semmin.

amugy sima local variable, miert ne lehetne belul?

> Az INLINE nagybetű?

az egy makro. inline-ra van definalva, csak ez a kod eredetileg watcom c-re volt irva es ott _inline kellett (legalabbis ezt hamoztam ki a config.h-bol)

> amikor ez inline, akkor bekerül közvetlenül a kódba a hívás helyére.

igen, igy van. gondolom ezert van hogy csak neha bugos, az esetek nagy reszeben jol mukodik.

Igazad van, közben gondolkodtam ezen. Ez valójában a hívó függvényben lesz egy lokális változó a stack-en, aminek érzésem szerint fordítási időpen a stack pointerhez képesti offsettje meglesz, futásidőben pedig ez a konstans offset és a stack pointer összeadódik, s a tényleges cím így lesz meg.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Na jo, de hogy szar? :) Nem fut le a byte reverse? Hulyeseg kerul bele? Elobb abbafejezi mint kene? Segfault? Mi ez az afs_ prefix es miert ha "ugyanazt kene csinalnia mint az fread()-nek csak byte reversallal"?

Igy elsore semmi extrat nem latok (az afs_ prefixeken kivul), bar most mar inkabb uint32_t-t irnek ki mindenfele `dword`-ok helyett. De nem is biztos hogy itt van a hiba hanem az afs_fread()-ban is lehetnek meglepetesek, barmi is legyen az :]

Ettol fuggetlenul en inkabb optimalizan csinalnam - szoval egy fread()-del kiolvasod mintha mi sem tortent volna, majd utana johet a reversal. Ha ugy csinalod akkor mit kapsz? Ha nem sajat reversal-t hasznalsz hanem mondjuk ntohl()-t akkor mi tortenik? 

> Na jo, de hogy szar? :) Hulyeseg kerul bele?

neha (eleg ritkan) nem az kerul a memoriaba mint ami a fileban volt. csak ugye nem tudom kiiratni a rosszat, mert a printf-tol megjavul, nem tudom pontosan mikor es hogy romlik el :)

> Mi ez az afs_ prefix

az egy wrapper, mivel ez nem posix kod volt eredetileg, dos alatt pl. mast hiv, meg tud tomoritett filebol (.afs file, innen a prefix neve) is olvasni stb. esetemben most az fread()-ot hivja 1:1-ben.

> most mar inkabb uint32_t-t irnek ki mindenfele `dword`-ok helyett.

most mar en is... amugy linuxon arra van typedefelve.

> egy fread()-del kiolvasod mintha mi sem tortent volna, majd utana johet a reversal.

en is igy csinalnam, nem is ertem, hogy miert igy lett ez anno megirva. emiatt is gyanus hogy ezt nem is en irtam (tobben dolgoztunk akkor a kodon, bar a nagy resze az en muvem, de ilyet en nem szoktam csinalni, bar fiatal voltam meg es kellett a penz stb)

> Ha nem sajat reversal-t hasznalsz

az most mind1 mert a byteswap resz most nem aktiv (x86on nem kell)

Jobban megnezve, eme kodod nem azt csinalja amit a posix varian opcionalisan byte order cserevel kiegeszitve. Ha elfogy a file, akkor ez 0-t ad vissza, az fread() meg eredetileg ugye kulturaltan annyit ad vissza mennyi a file merete volt (osztva a member merettel). Szoval csak ugy "esz nelkul" nem cserelheted ki ezt a sajat implementaciot egy fread()-re ha fel is hasznalod kesobb a return value-t. Extrem esetben azt is el tudom kepzelni hogy az fread() hivas az valami extra layeren keresztul (VDSO?) van implementalva, es ott esik szet a valami. 

> Ha elfogy a file, akkor ez 0-t ad vissza, az fread() meg eredetileg ugye kulturaltan

igen ez jogos eszrevetel, de a gyakorlatban sose fogy el, mert nem hibasak a fileok :) es eleve csak annyit olvas amennyinek ott kell lennie.

nyilvan ez az egesz kod kuka, mert nem optimalis es meg bugos is, csak erdekelt volna hogy hol a hiba... mert en azt nem talalom :)

de nem kizart az se, hogy a bug nem is itt van, csak ez triggereli valahogy (pl. uninitialized valtozo tartalma ettol megvaltozik)

Hiba/EOF esetén nem a sikeres olvasás hosszával kéne visszatérnie 0 helyett ?

Amit nem lehet megirni assemblyben, azt nem lehet megirni.

UPDATE: sikerult megoldani, hogy kiirassam a memoriat a beolvasas utan a jo es a rossz mukodes eseten is, es meglepo modon bytera ugyanaz. tehat nem itt van a hiba... hanem vmi mas bugot triggerel ez eleg viccesen :(

mondjuk eredetileg is valami uninitialized warningot nezegettem es onnan jutottam ebbe a func-ba, szoval vissza kell terni oda ;)

Szerkesztve: 2023. 12. 10., v – 19:46

na talan sikerult megtalalni a(z egyik) bunost:

typedef float c_MATRIX[3][4];

static void mat_swap (c_MATRIX a)
{
/*
  swap_mat: swap y/z in matrix.
*/
  int   i;
  float tmp;
#ifdef ast3d_SWAP_YZ
  phex(a,sizeof(c_MATRIX));
  for (i = 0; i < 3; i++) { /* swap columns */
    tmp = a[i][Y];
    a[i][Y] = a[i][Z];
    a[i][Z] = tmp;
  }
  phex(a,sizeof(c_MATRIX));
  for (i = 0; i < 4; i++) { /* swap rows */
    tmp = a[Y][i];
    a[Y][i] = a[Z][i];
    a[Z][i] = tmp;
  }
  phex(a,sizeof(c_MATRIX));
#endif
}

 

diff, a - a hibas, a + a jo verzio kimenete:   (phex kiirja hexaban a memoriat)

  24 EE F8 41 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 03 C2 D3 36 20 EE F8 41 00 00 00 00 00 00 00 80 C2 26 31 C2 9B B2 16 37 00 00 00 00
- 24 EE F8 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 00 00 00 00 80 00 00 80 3F 00 00 00 00 00 00 00 00
- 24 EE F8 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 80 3F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 00
+ 24 EE F8 41 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 20 EE F8 41 03 C2 D3 36 00 00 00 00 00 00 00 80 9B B2 16 37 C2 26 31 C2 00 00 00 00
+ 24 EE F8 41 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 9B B2 16 37 C2 26 31 C2 00 00 00 00 00 00 00 00 20 EE F8 41 03 C2 D3 36 00 00 00 00

azok konstansok:

#define X 0
#define Y 1
#define Z 2
#define W 3

biztos, hogy valami baja a 'mat' valtozoval van. ha ele irom hogy static, akkor jol mukodik. ha volatile-t irok ele akkor maskepp bugzik (majdnem jo de egyik iranyban meg van nyujtva a 3d object). ha atrakom mashova a deklaraciot az nem befolyasol. ha a mat_swap() tartalmat masolom oda fv hivas helyett (ugy latom sehol mashol nem hasznalja ezt ugyse) akkor se jobb:

 

  int       i, j;
  c_MATRIX  mat;

  mat_identity (mat);
  for (i = 0; i < 3; i++)
    for (j = 0; j < 3; j++)
      if (afs_fread_float(&(mat[i][j]), sizeof (float), 1, f) != 1) return ast3d_err_badfile;

//  mat_swap (mat);
#ifdef ast3d_SWAP_YZ
  phex(mat,sizeof(c_MATRIX));
  for (i = 0; i < 3; i++) { /* swap columns */
    float tmp = mat[i][Y];
    mat[i][Y] = mat[i][Z];
    mat[i][Z] = tmp;
  }
  phex(mat,sizeof(c_MATRIX));
  for (i = 0; i < 4; i++) { /* swap rows */
    float tmp = mat[Y][i];
    mat[Y][i] = mat[Z][i];
    mat[Z][i] = tmp;
  }
  phex(mat,sizeof(c_MATRIX));
#endif

ize, ha 3x4-es a matrixod akkor miert nem az egeszet toldot fel? miert csak egy 3x3-as almatrixat?

illetve nem tudom mi az a mat_identity(), vagyis csak kicsit sejtem, mert a 3x4-as matrixok vilagaban nincs identitas. ha csak a 3x3as reszebe teszi be a kr-deltat akkor kesz a baj. olyasmirol ne is beszeljunk hogy mi van akkor ha egy 3x3as objektumot var :) 

szerk: igen, most fogom fel a fentebbit is, szoval ha static a mat akkor inicializalt a [*][3], ha nem, akkor meg ugye nem: az valodi memoriaszemet lesz az elejen. foleg ha mat_identity sem teszi rendbe (ami ezalapjan eselyes). a volatile meg ugye egy kulon allatfaj :) 

mert a fileban csak 3x3 float van. a mat_identity tolti fel az egeszet ezzel:

static c_MATRIX Tidentity = {
  {1, 0, 0, 0},
  {0, 1, 0, 0},
  {0, 0, 1, 0},
};

nem inicializalas hiba, mert a betoltes utan a mat tartalma (mind a 3x4) meg jo minden esetben, a cserebereknel cseszodik csak el. de ha berakok egy printf-et az fread-be akkor az is jo. ez ilyen wtf bug mar.

hat ezt igy nem fogod sztem reprodukalni... kell hozza az fread-es cucc is, meg akkor se jon ki a hiba minden esetben.

majd felrakom az egesz cuccot a githubra valamikor, de egyelore masfel napig tartott mig sikerult egyaltalan buildelni, annyi sok biszbasz libbol es filebol all amikhez 25 eve nem nyult senki, eleg sokat kellett mar javitgatni. ez a 3ds loader csak egy kis resze.

igy nez ki asm-ben:

https://pastebin.com/dzBvXR3j

az elso 2 'call phex' kozotti resz az erdekes, ott cseszodik el a mat tartalma.

xmm regiszterekkel mokol valamit, de ezt a gnu asm-et sose vagtam, meg az sse utasitasokat se, szoval passz.

	movl	$0, -168(%rbp)
	jmp	.L184
.L185:
	movl	-168(%rbp), %eax
	cltq
	salq	$4, %rax
	addq	%rbp, %rax
	subq	$60, %rax
	movss	(%rax), %xmm0
	movss	%xmm0, -156(%rbp)
	movl	-168(%rbp), %eax
	cltq
	salq	$4, %rax
	addq	%rbp, %rax
	subq	$56, %rax
	movss	(%rax), %xmm0
	movl	-168(%rbp), %eax
	cltq
	salq	$4, %rax
	addq	%rbp, %rax
	subq	$60, %rax
	movss	%xmm0, (%rax)
	movl	-168(%rbp), %eax
	cltq
	salq	$4, %rax
	addq	%rbp, %rax
	subq	$56, %rax
	movss	-156(%rbp), %xmm0
	movss	%xmm0, (%rax)
	addl	$1, -168(%rbp)
.L184:
	cmpl	$2, -168(%rbp)
	jle	.L185

 

ez mar tenyleg ilyen wtf... ha a jol mukodo verziot nezem asm-ben, a fenti resz (a 2 phex kozotti ciklus) pont ugyanigy nez ki. de megis mas lesz az eredmeny...

szerk: nem jo, -O4 nelkul futott a -S, -O4-el tok mas de ott kioptimalizalta meg a phex-et is belole ;)

unaligned access problema? ha 

c_MATRIX  mat  __attribute__ ((aligned (16)));

modon deklaralod azt? mondjuk hogy a stack-re hogy tud egyszeruen aligned accesst csinalni az is jo kerdes, de sztem megoldja. bar igen, hogyha automatikus es nem statikus a valtozo akkor minek farassza magat stack-kel ha a regiszterekben is elfer igy vagy ugy... 3 darab xmm{0,1,2}-be elfer az egesz matrix, csak azokon operal, aztan csak akkor irja be memoriaba ha nagyon muszaj.

Nezd meg a mat cimet (printf("%p\n",(void *)(&mat[0][0]));) igy is meg ugy is. 

A hexdump alapjan mintha visszairna(?) a foatlobeli 1-eseket (3f800000). Kulon bonusz a -0-ert, de azzal nem kene hogy gond legyen :)

szerk: nem, csak xmm0-t hasznal, de azzal is meg ugy onmagaban rafuthat ilyen alignment dolgokra. nem minthogya x86(_64) eseten ennek valodi hatasa kene hogy legyen, de ez mar ilyen francsetudja dolog :/

az aligned nem segitett rajta.

ezutan beleirtam a prtintf-et, es ettol megjavult :)

  c_MATRIX  mat;
  printf("mat.ptr = %p\n",(void *)(&mat[0][0]));

ha kikommentezem a printf-et akkor nem jo :)

megneztem az -O4-el forditott asm-eket is, teljesen mas a jo es a nem jo verzio, masik xmm regiszterekbe rakja, mas a sorok szama is stb, diff-elve alig talalt azonosat kozte. a phex-et is inlineozta, es olyan mintha parhuzamosan menne a kiiras es az xmm-ek kozotti muveletek.

Ha kikommentezed a printf-et akkor nem lesz szukseg arra hogy a mat a memoriaban legyen, ez idaig oke. Ha nincs a memoriaban akkor mindent az xmm*-okban machinal,es abbol kozvetlenul bontja ki a hexdump-hoz is a karaktereket. Ez is eselyes. Kene egy minimal working example.

Meg azt neznem meg hogy melyk -Ox optimization level valtja ki (en max -O3-ig szoktam elmenni, szoval az most nincs az agyamban hogy az -O4 az mit is kapcsol be).

parhuzamosan menne a kiiras es az xmm-ek kozotti muveletek.

igen, minimalizalja a pipeline stall/bubble allapotok szamanak varhato ertekeit... ez is ertheto

igen en is arra jutottam, hogy xmm-ben van a matrix, ezert a memorias piszkalas nem megy.

> Meg azt neznem meg hogy melyk -Ox optimization level valtja ki

hat ez egy erdekes kerdes. -O3 es -O4 biztosan (nem tudom az O4 mi, en sose hasznaltam, de ennek a makefilejaban az volt).

viszont -O3 nelkul nem fordul le a kod, pontosabban a linker nem talal meg olyan func-okat amik amugy ott vannak... az O3 meg gondolom inlineolja oket es ezert akkor nem is keresi :)   ezzel is tervezek majd kuzdeni, de egyelore otletem sincs wtf.

az is erdekes, hogy O3/O4 eseten vannak ilyen warningok, -Ox nelkul viszont nincs:

file_3ds.c:1498:5: warning: ‘pos’ may be used uninitialized [-Wmaybe-uninitialized]
 1498 |     vec_make (pos[0], pos[1], pos[2], &key->val._vect);
 

egyebkent iszonyat gaz ez az egesz kod, mar biztos vagyok benne hogy nem en irtam, es ahogy nezem nem is sokban ter el az eredeti CLAX kodjatol, amibol anno forkoltuk:

https://github.com/joric/j3de/blob/master/clax/src/file_3ds.c#L564

Hat, probaltam egy minimal working example-t csinalni a dologbol, de gcc-10 es gcc-12 mellett is hibatlanul fut. Ami mondjuk fura hogy nem inline-olja be a phex-et nekem itten. 

Illetve azoknak a warningoknak is utanamennek... nem veletlenul vannak vsz ott, foleg az ilyen inicializalatlan biszbaszok temaban lehet vicces az is.

Mit szolnal mondjuk egy ilyenhez? Ha a loop-okat unrollozod, az 3+4 csere. Ebbol 2-t meg tudsz sporolni, ha az Y-Z csereket atlosan hajtod vegre. A gcc-t is valoszinuleg az zavarja meg, hogy beteszi az xmm0-ba, de utana masik iranyba tekered ugyanannak az eredmenyet.

Szivem szerint irnek egy inline cserelo fuggvenyt, de ezek utan nem merek.. :)

static void mat_swap (c_MATRIX a)
{
/*
  swap_mat: swap y/z in matrix.
*/
  int   i;
  float tmp;
#ifdef ast3d_SWAP_YZ
  phex(a,sizeof(c_MATRIX));

  // horizontal swap
  tmp = a[X][Y]; a[X][Y] = a[X][Z]; a[X][Z] = tmp;
  // vertical swaps
  tmp = a[Y][X]; a[Y][X] = a[Z][X]; a[Z][X] = tmp;
  tmp = a[Y][W]; a[Y][W] = a[Z][W]; a[Z][W] = tmp;
  // diagonal swaps
  tmp = a[Y][Y]; a[Y][Y] = a[Z][Z]; a[Z][Z] = tmp;
  tmp = a[Y][Z]; a[Y][Z] = a[Z][Y]; a[Z][Y] = tmp;

  phex(a,sizeof(c_MATRIX));
#endif
}

A strange game. The only winning move is not to play. How about a nice game of chess?

le tudod buildeni/futtatni ASAN+UBSAN-el? hatha kidob valami hasznosat...