Forum: Compiler & IDEs LTO und built-ins bzw libc-funktionen


von LTO (Gast)


Lesenswert?

Folgender Code
1
volatile int a = 851;
2
volatile int b = 33;
3
4
int main() {
5
    int x = a % b;    
6
    int y = a * b;
7
    return x + y;
8
}

führt bei AVR zu:
1
000000e2 <main>:
2
e2:   80 91 02 40     lds     r24, 0x4002     ; 0x804002 <a>
3
e6:   90 91 03 40     lds     r25, 0x4003     ; 0x804003 <a+0x1>
4
ea:   60 91 00 40     lds     r22, 0x4000     ; 0x804000 <b>
5
ee:   70 91 01 40     lds     r23, 0x4001     ; 0x804001 <b+0x1>
6
f2:   c0 91 02 40     lds     r28, 0x4002     ; 0x804002 <a>
7
f6:   d0 91 03 40     lds     r29, 0x4003     ; 0x804003 <a+0x1>
8
fa:   e0 91 00 40     lds     r30, 0x4000     ; 0x804000 <b>
9
fe:   f0 91 01 40     lds     r31, 0x4001     ; 0x804001 <b+0x1>
10
102:   0e 94 8d 00     call    0x11a   ; 0x11a <__divmodhi4>
11
106:   ce 9f           mul     r28, r30
12
108:   90 01           movw    r18, r0
13
10a:   cf 9f           mul     r28, r31
14
10c:   30 0d           add     r19, r0
15
10e:   de 9f           mul     r29, r30
16
110:   30 0d           add     r19, r0
17
112:   11 24           eor     r1, r1
18
114:   82 0f           add     r24, r18
19
116:   93 1f           adc     r25, r19
20
118:   08 95           ret

Wie man sieht, ist der *-Operator (__mulhi3) inline und der %-Operator 
(__divmodhi4) nicht inline bei -Os. Auch bei -flto -fwhole-program 
ändert sich das nicht.

Daher folgende Fragen:

- Warum wird __divmodhi4 hier nicht inline?
- Kann man das irgendwie erzwingen?
- *-Op und &-Op sind als builtins nicht Teil der avr-libc. Deswegen 
wirkt sich hier -flto auch nicht aus, oder?

Und grundsätzliche Fragen:
- Gibt es die avr-libc auch als LTO-Verion?
- Kann ich eine eigene (statische) Bibliothek so gestalten, dass sie 
sowohl  Maschinencode als auch GIMPLE (für LTO) enthält?

Danke für Eure Antworten!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

LTO schrieb:
> Wie man sieht, ist der *-Operator (__mulhi3) inline und der %-Operator
> (__divmodhi4) nicht inline bei -Os. Auch bei -flto -fwhole-program
> ändert sich das nicht.
>
> Daher folgende Fragen:
>
> - Warum wird __divmodhi4 hier nicht inline?

Weil das den Code wesentlich vergrößern würde wenn mehr als 1x geinlinet 
wird.  Auch inline wäre der Code nicht schneller (bis auf CALL/RET, die 
aber im Vergleich zum Rest der Routine zu vernachlässigen sind). avr-gcc 
kennt den Footprint dieser Funktion, der flacher ist als der üblicher 
Calls, z.B. bleibt Z-Reg über den Aufruf erhalten.  Der Registerdruck 
ist also nur so groß wie tatsächlich durch __[u]divmodhi4 gegeben. 
Außerdem berechnen die Funktionen / und %; die Funktion für nur div oder 
nur mod wäre kaum kürzer oder schneller, weil ohnehin immer beide 
Ergebnisse anfallen.

> - Kann man das irgendwie erzwingen?

Dazu müsstest du die GCC-Quellen anpassen, also gcc/config/avr/avr.md 
und den Code dort optinsabhängig inlinen z.B. in insn "[u]divmodhi4".

> - *-Op und &-Op sind als builtins nicht Teil der avr-libc. Deswegen
> wirkt sich hier -flto auch nicht aus, oder?

LTO wirkt sich nur auf die Module aus, für die es gesetzt wird.  Wenn es 
also inline-Funktionen in Headern gibt (z.B. copysign), sind diese dem 
Compiler und damit auch dessen Optimierern zugänglich.  Die statischen 
Libraries (libc.a, libgcc.a etc.) werden aus gutem Grund nicht mit -flto 
generiert.

> Und grundsätzliche Fragen:
> - Gibt es die avr-libc auch als LTO-Verion?

Nein, es sei denn du bastelst deine eigene libgcc / AVR-LibC, die das 
kann.

> - Kann ich eine eigene (statische) Bibliothek so gestalten, dass sie
> sowohl  Maschinencode als auch GIMPLE (für LTO) enthält?

Sollte prinzipiell möglich sein mit -flto -ffat-lto-objects.

Ein Großteil der AVR-LibC besteht jedoch aus handoptimiertem Assembly, 
und bei den großen Brummern wie [v]fprintf würde LTO auch nicht viel 
bringen, weil selbst mit LTO nicht analysiert wird / werden kann, welche 
%-Codes verwendet werden und welche nicht.

Und die Frage ist dann auch, wie der LTO-Plugin an den LTO-Code in den 
Objects der lib*.a kommt, um ihn in lto1 (den LTO-Compiler) zu füttern. 
Eigentlich sind aktuelle Binutils Tools wir ranlib alle LTO-fähig, aber 
ausprobiert hab ich das nie.

Die zu erwartende Verbesserung der Codegüte ist einfach zu gering, zum 
Beispiel sind fast alle Funktionen der libgcc eh in Assembly, außer 
einige Funktionen für 64-Bit double, wo der generierte Code aber auch 
sehr brauchbar ist (außer möglicherweise für avr-gcc v9+ wegen PR90706, 
aber das betrifft dann allen Code, nicht nur den in Libs).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.