GCC optimalizace pro různé ISA

mhi

  • ****
  • 340
    • Zobrazit profil
Re:GCC optimalizace pro různé ISA
« Odpověď #15 kdy: 25. 10. 2021, 14:59:12 »
"gcc v módu jazykového právníka" - tomu nerozumim o co jde.

Ano, neco takoveho jako ty znacky jsem myslel. Podobne znacky pouzivame na oznaceni vlastniho kodu pro snazsi dokazovani hloupe copy&paste kradeze IP (ale jsou spustitelne a kodove neutralni; v jedne je treba v ASCII moje prijmeni nebo jmeno firmy :) ).

Zkusim to tam nekdy dodratovat, no nebude to zase tak jednoduche, treba to ten tail call nakonec vyresi. Udelam pak seriozni strojovou analyzu tech vystupu, to co jsem tady psal je jen to co bylo videt na prvni pohled.

RDa: mel jsem tam po vypoctu eaddr i prirazeni do lokalni promenne s page_index a page_mask, ktere jsem pak pouzival. Mozna mam botu jeste jinde, ze se tam ta inline fce na vypocet eaddr vola treba nejak 2x, tezko rict, ale nenasel jsem to. Ten kod je pro tento ucel dost hrozny, budu to muset prelozit se zakazanym inlinovanim.

Jeste vlastne resim jeden problem, mam generovany .h soubor, ve kterem je 1 .. n konstant. Aktualne je mam jako

#define CODE_CONST0 0x...
#define CODE_CONST1 0x...
#define CODE_CONST2 0x...

potreboval bych udelat makro GET_NEXT_CODE_CONST() ktere vrati prvni konstantu, ktera jeste nebyla pouzita (takhle si vyzobavam opkody). Dobre mi to funguje na variabilni data, ktera mam jako argumenty pres (register int arg1,register int arg2) v tomto stylu ala vararg:

#define instr_get_nip() (++n_arg, (n_arg==1) ? (arg1) :  ((n_arg==2) ? (arg2) : FAILURE))

jenze na ty fixni konstanty se z toho GCC nejak poblazni a prepise mi to do kodu i s tou detekcni promennou FAILURE, prestoze to je jinak uplne stejne jako na ty argumenty. Nechapu to.


Re:GCC optimalizace pro různé ISA
« Odpověď #16 kdy: 25. 10. 2021, 22:33:03 »
"gcc v módu jazykového právníka" - tomu nerozumim o co jde.
Dokumentaci interpretovat spíš jako právník než programátor. Nikdy jste neslyšel pojem "language lawyer"?

mhi

  • ****
  • 340
    • Zobrazit profil
Re:GCC optimalizace pro různé ISA
« Odpověď #17 kdy: 26. 10. 2021, 12:41:36 »
Chapal jsem ten anglicky termin trosku jinak, tak mi to nedavalo smysl k ceskemu. Dekuji za upresneni.

Pridal jsem na konec kodu endmarker, validni instrukci aby to slo objdumpovat, zatim jen pro x86

#define ENDMARKER()  __asm__ __volatile__ ("\n\t .byte 0x3f");  // "AAS"

tail cally to vyresilo spolehlive. Co mne ale prekvapilo, nektere snippety jsou diky tomu kratsi, nekdy i o mnoho bajtu :). Samozrejme u spousty tam ta jedna instrukce pribyla, ale je na konci, takze zkusim pripadne napsat neco co ji zlikviduje. Funguje stejne i toto:

#define ENDMARKER()  __asm__ __volatile__ ("\n\t");  // jen likvidace tail callu

Co mne nyni trapi v tom, abych to generovani nejak mohl automatizoval je nefunkcnost makra, toto je prototyp pro jeden opkod (realne se pak pouzije misto FAILURE rozvoj do dalsich)

mam definovano:
opcodes.h:#define OPCODE_BYTE_1 0xnn

sem by se to melo dosadit:
opcode = instr_get_opcbyte();

toto makro funguje 100%, gcc optimalizuje podle toho define
cpuhelpers.c:#define instr_get_opcbyte() OPCODE_BYTE_1

pred instr_get_opcbyte(); volam:
cpu.c:        n_opcode = 0;

toto makro
cpulelpers.c:#define  instr_get_opcbyte()  (++n_opcode, (n_opcode == 1) ? OPCODE_BYTE_1 : FAILURE)


vubec nefunguje. Zcela identicky ekvivalent pro arg1/arg2 jak jsem psal vyse mi chodi naprosto bez problemu. tady to makro se rozvine z nejakeho zahadneho duvodu, jako kdyby gcc neumelo uvazovat o fixni hodnote n_opcode a predpocitat to na fixni vysledek OPCODE_BYTE_1 ! Netusite nekdo kde delam chybu ? Prijde mi to uplne silene, hlavne kdyz daleko slozitejsi varianta s registrovymi argumenty chodi jak ma. Prijde mi jako kdybych nevidel nejaky preklep nebo tak neco.

Dekuji za pripadne popostrceni.

Re:GCC optimalizace pro různé ISA
« Odpověď #18 kdy: 26. 10. 2021, 18:49:12 »
cpulelpers.c:#define  instr_get_opcbyte()  (++n_opcode, (n_opcode == 1) ? OPCODE_BYTE_1 : FAILURE)
C makroprocessor jen nahrazuje detekovana makra v textu jejich expanzi, takze pri expanzi makra instr_get_opcbyte() je pro nej vse az k OPCODE_BYTE_1 text, ktery kopiruje, OPCODE_BYTE_1 expanduje na 0xnn, pak zase kopiruje (" : "), a nakonec expanze FAILURE. To az kompilator bere v potaz n_opcode = 0 a optimalizuje kod.
Ale asi presne nerozumim vasemu dotazu a ceho presne chcete dosahnout.

Re:GCC optimalizace pro různé ISA
« Odpověď #19 kdy: 26. 10. 2021, 20:21:36 »
Jinak pokud jde o postupne tahani "konstant z pole", co treba pouzit spojeni enum a __COUNTER__:
Kód: [Vybrat]
#include <stdio.h>

enum {
    OPC0 = 0,
    OPC1 = 10,
    OPC2 = 20,
    OPC3 = 30,
    OPC4 = 40
};

#define CONCAT(a, b) a##b
#define CONCATW(a, b) CONCAT(a, b)
#define GETNEXTOPC  CONCATW( OPC, __COUNTER__ )

int main()
{
    int opc = GETNEXTOPC;
    printf("%d\n", opc);
    opc = GETNEXTOPC;
    printf("%d\n", opc);
    opc = GETNEXTOPC;
    printf("%d\n", opc);
    opc = GETNEXTOPC;
    printf("%d\n", opc);
    opc = GETNEXTOPC;
    printf("%d\n", opc);
    return 0;
}
s vysledkem
Kód: [Vybrat]
0
10
20
30
40


mhi

  • ****
  • 340
    • Zobrazit profil
Re:GCC optimalizace pro různé ISA
« Odpověď #20 kdy: 26. 10. 2021, 20:28:10 »
Funkci preprocessoru znam, problem jsem uz nakonec lokalizoval. gcc nedokaze ten otaznikovy vyraz vyhodnotit pokud je v cyklu "while (runonlyonce) { ... }", tedy cyklus probehne jen jednou. V jednom miste jsem to tak mel a rozbilo to vsechno okolo. Zvlastni je, ze jina vyhodnoceni v takovem cyklu necini problem, gcc je napocita a bere je jako konstanty. A ve vysledku ten cyklus nikde ve vystupnim kodu neni ... zvlastni.

__COUNTER__  bohuzel neni pro mne v teto ciste podobe reseni, potreboval bych tech counteru vic - problem jsem trosku zjednodusil.

Kazdopadne diky za pomoc.

Ted musim udelat automat, ktery projde ten opkodovy prostor, a pak zkusim trochu optimalizovat vystupni kod, aby to nebyly takove silene bloby plne opakujiciho se kodu.
« Poslední změna: 26. 10. 2021, 20:32:17 od mhi »

mhi

  • ****
  • 340
    • Zobrazit profil
Re:GCC optimalizace pro různé ISA
« Odpověď #21 kdy: 28. 10. 2021, 13:33:03 »
Zkousim ted jestli se podari nejak elegantne pres inline assembler pro x86-64+ARM udelat vyhodnoceni flagu. Jde o to, ze potrebuju udelat nejakou ALU operaci a ulozit si z ni flagy, abych je pak dodatecne nemusel slozite dopocitavat, resp. vytahnul si z flags registru jestli bylo carry a pracoval s nim nasledne.

Muj kod vypada takto:

vypocet ea
load
pripadny druhy dopocet ea
alu
store
dalsi prace s flagy

mezi alu a "dalsi prace s flagy" nemam zaruceno, ze se mi neprepisou. Takze prepisu alu z C operace na inline asm + store flagu do nejakeho registru, ktery nasledne pouziju pri "dalsi prace s flagy".


U ARMu je to primocare - msr SPSR. Jak to resit u x86-64 ? lahf/sahf nemusi byt podporovane, nejlepsi co mne napada je nejake pushf/pop eax, ale mozna existuje lepsi varianta?

Pripadne pokud tu jsou odbornici i na jine ISA, jak se to dela u nich? Ne ze bych potreboval ten translator mit treba na LX6 nebo MIPS, spis jsem se do toho vystupu zakoukal a ucim se na tom nejake nove veci. Zatim se mi muj napad zda celkem jednoduse realizovatelny, tak bych to mozna ze studijnich duvodu vyzkousel taky.
« Poslední změna: 28. 10. 2021, 13:38:01 od mhi »