Newsgroup: it.comp.lang.c++
Titolo: Posizione dichiarazione variabili

Salva,
secondo voi è più veloce:
int i,j;
for(i=0; i<1000000; i++)
   for(j=0;j<1000000; j++)
     ....
oppure
for(int i=0; i<1000000; i++)
   for(int j=0;j<1000000; j++)
     ....
cioè l'allocazione nello stack di "j" per ogni ciclo di "i" richiede 
tempo (suppongo di si perchè viene comunque incrementato e decrementato 
ogni volta il registro puntatore allo stack, giusto?)

secondo voi è più veloce:
Fai un debug del compilato e accertati di cosa fa il tuo compilatore.
Gli ottimizzatori in genere sono abbastanza furbi da usare i registri
del processore come indici, quindi non c'è alcuna allocazione
effettiva su stack.


Non vedo perchè dovrebbe venire incrementato lo stack pointer. A meno 
che i .... non contengano chiamate a funzione. Ma in tal caso 
l'eventuale incremento dello stack pointer è del tutto trascurabile 
rispetto al milione di chiamate a funzione.
E.

 Non vedo perchè dovrebbe venire incrementato lo stack pointer.
Immagino che p51d intenda che ad ogni ciclo venga allocato spazio per
j. Fatto salvo quanto ho detto nella mia risposta (e cioè che molto
presumibilmente il compilatore usa un registro per gli indici dei
cicli), gli ottimizzatori sono comunque abbastanza furbi da spostare -
anche in caso di uso dello stack - l'allocazione al di fuori del
ciclo.


Ho un deja vu, mi pare ne avevamo già discusso. L'allocazione sullo 
stack non ha alcun costo, finchè non chiami una funzione.
in
void f() {
   int x;
   for (int j=0;j<10;j++) {
     for (int k=0;j<20;k++) {
        // bla bla
     }
   }
}
quello che presumibilmente farà il compilatore è usare SP per x, SP+1 
per j, SP+2 per k. Lo SP non verrà mai modificato.
E.

 E.
in gcc 4.2 questo...
int main (int argc, char * const argv[]) {
	int k=0;
	for(int i=0; i<1000; i++)
		for(int j=0; j<1000; j++)
			k++;
}
...viene compilato con...
_main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	movl	$0, -20(%ebp)
	movl	$0, -16(%ebp)
	jmp	L2
L3:
	movl	$0, -12(%ebp)
	jmp	L4
L5:
	leal	-20(%ebp), %eax
	incl	(%eax)
	leal	-12(%ebp), %eax
	incl	(%eax)
L4:
	cmpl	$999, -12(%ebp)
	jle	L5
	leal	-16(%ebp), %eax
	incl	(%eax)
L2:
	cmpl	$999, -16(%ebp)
	jle	L3
	movl	$0, %eax
	leave
	ret
In effetti non mi sembra ci sia nessun incremento/decremento oltre le 
variabili del ciclo.

 variabili del ciclo.
Non saprei, io sono rimasto all'ASM dell'apple ][ (mi pare fosse un 
8086). Però DEVE essere così, se venisse cambiato lo SP ogni volta che 
viene dichiarata una variabile locale, tutti gli indirizzi relativi alle 
altre variabili locali andrebbero modificate.
E.

     ret
return
E.

 capire che succede. Sarò grato a chi vorrà chiarirmi le idee.
Calcola che il codice e` probabilmente generato con l'ottimizzatore 
disabilitato, ho provato a far la stessa cosa con -O3 e mi ha segato del 
tutto i loop.
Bye,
  Gabry

 8086).
Naaaaah... era un 6502 ;-)

p51d ha scritto:
Dovrebbe essere del tutto equivalente.
Se l'ottimizzatore decide di posizionare le variabili nello stack,
e questo si sa a compile time, in entrambi i casi lo spazio viene 
riservato nello stack frame allocato per la funzione in cui ti trovi,
che ha dimensione nota a compile time e che è allocato nel momento della
chiamata alla funzione, con uno scostamento dallo stack pointer noto a 
compile time.
L'ottimizzatore potrebbe sempre decidere di mettere le variabili in un 
registro, in quel caso ancora le due versioni sarebbero analoghe.
COnsidera che ad esempio GCC considera lo scope delle variabili, nel 
secondo caso, uguale al corpo del for, mentre Visual Studio mantiene i e 
j visibili da lì in poi. Ma se non usi i e j più avanti, questo non 
dovrebbe far differenza nella scelta tra allocazione nei registri e 
nello stack.
ciao


stack non ha alcun costo, finchè non chiami una funzione.
Sì, hai perfettamente ragione. Ed è esattamente questo che intendo
quando dico che j non richiede alcuna allocazione specifica: viene
gestita al di fuori del ciclo, nella porzione di stack a cui
appartiene.

Gabriele Greco ha scritto:

Esatto, ho disabilitato l'ottimizzazione altrimenti non si capiva niente 
('sti compilatori sono troppo intelligenti!).

 altre variabili locali andrebbero modificate.
Aspetta. Di fatto lo standard non dice *nemmeno* che deve esserci uno
stack (anche se di fatto leggendo la descrizione delle variabili
automatiche sono proprio gestite "come se fossero su uno stack").
Tipicamente molti compilatori semplicemente calcolano tutta la
dimensione necessaria per le variabili locali di una procedura (a
prescindere se ci si arriva veramente in un dato punto) e modificano lo
SP direttamente durante il preludio. Questo per lo meno su architetture
come PPC dove PUSH e POP di fatto non esistono. 
Ad ogni buon conto quando usi una PUSH o una POP di fatto *stai*
modificando lo stack pointer. Per cui si modificano tutti gli indirizzi
relativi (allo stack pointer). Non a caso i programmatori ASM usano il
*base* pointer per riferirsi alle variabili locali (%ebp su x86, r30 o
r31 su PPC a seconda dell'ABI, IIRC). 
Di fatto in questa maniera hai lo stack pointer che cresce come deve, ma
tu gli indirizzamenti li fai sul base pointer. Poi ci sono opzioni del
compilatore che invece dicono esplicitamente di non usare il base
pointer. Dopo tutto per un umano tenere conto di questi dettagli è
error-prone, per un compilatore no. In questo caso viene fatto tutto con
lo stack pointer. Questo può portare a riduzione della dimensione del
codice e/o della velocità, non so in che misura o in che condizioni (che
potrebbe anche volere dire *mai*, non ho fatto test).
-- 
-riko

 boh?!?! Dovrebbe riprendere il valore di E dallo stack?
Fa quello che fa il classico postambolo:
mov  %ebp, %esp
pop  %ebp
-- 
-riko

 Naaaaah... era un 6502 ;-)
Io ho qui ancora il manualetto di Monteil... 6502 e 6510!
-- 
-riko


Dipende dall' architettura e dall' ottimizzazione, ma in generale
la seconda forma è un poco piu' lenta in quanto le variabili
automatiche hanno visibilità solo all' interno dei blocchi
for: questo implica che <j> viene creata e distrutta <i> volte.
Se c'e' spazio per l' uso di registri e <j> puo' essere un registro
allora la cosa non comporta differenze perche' in realta' non
viene allocata, ma di questo non c'e' nessuna garanzia.
Il dichiarare <register int j> puo' aiutare il compilatore, specie
se il codice e' compilato senza ottimizzazioni (per esempio
la versione di debug). Se si attiva l' ottimizzazione, ci pensa
il compilatore. In ogni caso, se non e' possibile usare
un registro, la seconda forma viene penalizzata leggermente
bye
brix

 un registro, la seconda forma viene penalizzata leggermente
Non c'è motivo per cui le due forme abbiano un codice compilato diverso. 
Il campo di visibilità delle variabili è un concetto che non ha 
riscontro nel codice prodotto.
E.


Non c'e' motivo che le due forme abbiano un codice compilato uguale.
I codici sono uguali *se*  l' implementazione ha deciso cosi' o se l' 
ottimizzazione
lo permette, altrimenti possono essere diversi.
Il concetto di visibilita' impatta sul codice in quanto viene creato 
spazio per le variabili
in questione nel blocco di visibilita'.
All' uscita del blocco, le variabili in questione non sono piu' 
disponibili e sono 'distrutte'.
Se vuoi dire che l' implementazione dipende dal compilatore che puo' 
generare
codice uguale, sono d'accordo, ma non c'e' nessuna garanzia che sia cosi'.
GCC (x86) per esempio calcola lo spazio di stack necessario per tutte le 
variabili
automatiche una sola volta:  in effetti e' come se allocasse tutte le 
variabili
all' inizio del blocco in un solo colpo, come nei compilatori C di buona 
memoria.
Altri compilatori possono non seguire questa regola, specie se si creano 
grosse
strutture dati automatiche (CodeWarrior for embedded per ppc segue 
questa regola,
o almeno nelle versioni che ho usato).
bye, Brix

 Non c'e' motivo che le due forme abbiano un codice compilato uguale.
Non sono d'accordo. Il motivo per cui quelle due scritture debbano
avere compilato uguale (ovvero l'implementatore debba sforzarsi di
renderlo analogo a quello che prevede due indici dichiarati a monte
del ciclo, a dispetto della mancanza di vincoli espliciti nello
standard) è insito nella semantica del linguaggio: la dichiarazione
sul posto degli indici è stata introdotta proprio per facilitare e
rendere più sicure le operazioni con i loop. Bisogna incoraggiare i
programmatori ad usarle. Se a questo non segue un'ottimizzazione
spinta del compilato, allora l'implementazione è veramente molto
scarsa e a quel punto meglio cambiare compilatore.

 questa regola,
Onestamente non capisco come altro si potrebbe fare.
Nel codice
{
   int x;
   // blocco esterno
   {
     int y;
     // blocco interno
   }
}
Quando si entra nel blocco più interno NON HA SENSO modificare lo stack 
pointer (SP). Oltre a produrre codice più lento questo renderebbe più 
difficile la compilazione. Infatti nel blocco interno la variabile x 
avrebbe una posizione diversa rispetto allo SP da quella che avrebbe nel 
blocco esterno. Perché mai un compilatore dovrebbe fare questo?
Avere le variabili dichiarate all'interno dei blocchi aiuta il compito 
del compilatore, che sa che quella variabile non può essere usata al di 
fuori del blocco. Se il compilatore non è in grado di utilizzare questa 
informazione per produrre codice più performante, può benissimo 
compilare il codice come se tutte le variabili fossero state dichiarate 
all'inizio (ovviamente distinguendo eventuali variabili che 
incidentalmente hanno lo stesso nome).
E.

 blocco esterno. Perché mai un compilatore dovrebbe fare questo?
Come ti dicevo, in primo luogo di default i compilatori indirizzano da
un base pointer e non da uno stack pointer (esattamente come gli umani).
Il fatto che su x86 si chiami ebp (e richiami proprio il nome base
pointer) mentre su altre architetture il nome sia meno esplicativo è
completamente secondario.
Poi di fatto puoi anche chiedere al compilatore di indirizzare dallo
stack pointer: l'aritmetica da fare è per un umano tediosa ed
error-prone. Per un compilatore è un giochetto.
A prescindere da questo molte implementazioni *non* modificano lo stack
pointer. Tipo su x86 pure codice come:
#include <stdlib.h>
#define BUF_SIZE (2048-sizeof(int))
struct very_big_area {
    int buffer[BUF_SIZE];
    size_t length;
};
void f(int x) {
    if (x > 0) {
        f(x-1);
    } else {
        struct very_big_area a;
    }
}
void g() {
    struct very_big_area a;
    {
        struct very_big_area b;
    }
}
genera:
        .text
.globl _f
_f:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8216, %esp
        cmpl    $0, 8(%ebp)
        jle     L4
        movl    8(%ebp), %eax
        decl    %eax
        movl    %eax, (%esp)
        call    _f
L4:
        leave
        ret
.globl _g
_g:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $16376, %esp
        leave
        ret
-- 
-riko

 lo permette, altrimenti possono essere diversi.
premettendo che (uso solo x86) condivido l'irrilevanza della 
"creazione" di tipo in testa o inline (dato che trattasi 
soltanto di aggiungere un offset al registro indice EBP, 
quindi che sia una costante o un'altra nulla cambia), mi 
sorge però un dubbio ulteriore, e in questo caso mi chiedo 
se BRIX possa avere ragione ...
che succede se al posto di un contatore uso un qualche sorta 
di iteratore, ossia invece di istanziare un plain int (o 
altri tipi intrinseci) istanzio un oggetto dotato di 
costruttore esplicito ?
In questo secondo caso, può il compilatore legittimamente 
scansarsi la ripetura costruzione (e si presume 
inizializzazione) ? Mi parrebbe di no, quindi in questo caso 
il costrutto a visibilità ristretta comporterebbe enne 
chiamate al costruttore (e magari a NEW), e sarebbe più lento.
Che ne pensate ?
ciao
Soviet:Mario


 Che ne pensate ?
Ribadisco il mio punto di vista: un'implementazione che non riesca ad
ottimizzare l'uso di un indice (fosse anche un iteratore) creando
un'istanza nuova di una classe ad ogni ciclo, quando se ne potrebbe
fare a meno, è un'implementazione scarsa. Ci deve essere un certo
livello di garanzia di ottimizzazione da parte di un'implementazione
perché sia utilizzabile seriamente, anche perché non è possibile
rimettere sempre in gioco aspetti specifici del linguaggio. Il tutto
IMHO, ovviamente.

 no, quindi in questo caso il costrutto a visibilità ristretta 
Quando costruisci un oggetto sullo stack di fatto x il compilatore e` 
una displacement new sulla allocazione sullo stack, quindi il 
compilatore puo` benissimo riservare lo spazio sullo stack all'entry 
point della funzione, ovviamente pero` ad ogni ciclo dovra` chiamare 
costruttore e distruttore dell'oggetto... ovviamente non e` detto che 
tutti i compilatori si comportino cosi`, ma e` ragionevole che lo 
facciano perche` e` il modo + semplice sia come implementazione (non ti 
cambiano gli indici ad ogni blocco) che come performance (operazioni 
minime sul displacement dello stack pointer).

 fare a meno, è un'implementazione scarsa. 
Non direi, il costruttore deve venire chiamato. Considera questo esempio:
class Int {
	int x;
	static int count;
	Int() {
	  count++;
	  x=0;
	}
	void next() {
	  ++x;
	}
	bool end() const {
            return x==10;
         }
	static int getCount() {
            return count;
         }
};
main() {
   for (Int i;!i.end();i.next())
     for (Int j;!j.end();j.next());
   std::cout<< Int::getCount();
}
Non mi dirai che il risultato dipende dall'implementazione...
Lo spazio in cui memorizzare i e j può essere deciso dal compilatore 
quando gli pare. Ma il costruttore va chiamato quando glielo dico io!
E.

 quando gli pare. Ma il costruttore va chiamato quando glielo dico io!
Ni.
Per questo caso specifico non so risponderti con precisione quindi non 
mi pronuncio.
Ma occhio che in generale possono esistere casi in cui un costruttore 
non viene chiamato per via di un'ottimizzazione. Per questo motivo da 
tutte le parti si raccomanda di stare attenti ai side-effects nei 
costruttori!
Il caso che ho in mente (non so se č l'unico ma sicuramente questo 
esiste) č la RVO (Return Value Optimization) o la NRVO (Named RVO)
GM

Non mi dirai che il risultato dipende dall'implementazione...
In questo caso ovviamente no (ti sei volutamente messo nel caso di
codice non ottimizzabile nel senso che dicevo io e grazie tante :-),
ma un ottimizzatore (oggigiorno sono *veramente* furbi) potrebbe
riconoscere il caso in cui chiamare il costruttore ad ogni ciclo può
essere risparmiato. Boh, non so, secondo me è fattibile come controllo
e rientra negli scopi di un ottimizzatore.

 scarsa e a quel punto meglio cambiare compilatore.
Su questo punto invece mi permetto di dissentire.
_alla_maggior_parte dei programmatori dell' efficienza del
compilatore non importa una pippa (o comunque poco).
Di fatto chi lavora con macchine molto performanti, dotate
di memoria cache e altri arzigoli hardware, per la maggior
parte non si accorge nemmeno della differenza tra un compilatore
molto efficiente e uno meno: in fondo funzionano bene persino
molti liguaggi 'virtualizzati'.
La strategia seguita dai vari compilatori segue la logica
del target di utilizzo. Un compilatore per embedded
presenta problematiche di ottimizzazione diverse da quelle di un 
compilatore general-purpose pensato per generare codice su macchine
dove la memoria non e' un problema, tante' che IAR, per esempio,
fa ancora differenza(per efficienza) rispetto ai compilatori tipo
Gcc.
Tra l' altro, se proprio vogliamo buttarla sull' efficienza
le chiamate a funzione espanse nella modalita' classica del C
(con il chiamante responsabile della deallocazione dei parametri
  passati) per quanto semplici da implementare(e anche sicure),
sono anche ben poco efficienti sia in termini di velocita' che
di spazio rispetto alla modalita' tipo 'pascal' in cui e' il
chiamato responsabile del consumo delle variabili passate.
Infatti che molti compilatori per embedded (tra cui gli Intel)
prevedono anche la possibilita' di compilare tutte le funzioni
C direttamente come funzioni 'pascal' (o PL/M :-) ).
E le funzioni inline? se ci si prende la briga di verificare l'
espanso assembly a volte si hanno delle belle sorprese...
bye,
brix


Non credo proprio. E' talmente banale e naturale calcolare la posizione 
di una variabile sullo stack in funzione della sua profondità 
nell'albero dei blocchi di visibilità che non posso immaginare che venga 
fatto diversamente.
E.

compilatore non importa una pippa (o comunque poco).
E' un altro discorso. Chi sviluppa compilatori ha il dovere di
renderli efficienti. Il fatto che la maggior parte di chi li usa, li
fa girare su piattaforme che rendono impercettibili le differenze di
performance non è una giustificazione per l'inefficienza. Anche perché
questa idea sarebbe assolutamente contraria a quella di progresso
scientifico. E poi io dubito sempre di chi dice "per la maggior parte
della gente vale ..." perché presuppongo che conosca la maggior parte
della gente, il che è assolutamente inverosimile :-)


*semanticamente* corretta. Non c'entra *nulla* che sia facile calcolare 
la profondita' dello stack,
ammesso che ci sia uno stack ;-)
E in tal caso è *talmente* banale fare una bel add ebp+size(var) e 
relatva sub nel blocco
che non posso immaginare che venga fatto diversamente perche' in questo 
caso specifico
sarebbe proprio l' ottimizzazione migliore.
B.

 sarebbe proprio l' ottimizzazione migliore.
Non capisco come aggiungere due istruzioni in più possa essere una 
ottimizzazione...
E.

   
C'e sempre da dubitare di chi dubita, no? Siamo d'accordo: e' certo che 
chi sviluppa
compilatori, di sicuro quelli commerciali, punta sull' ottimizzazione, 
specie per i compilatori
embedded dove l' ottimizzazione pesa molto di piu' ed un plus che 
giustifica il prezzo.
Qui pero' non si parla di *conoscere* le persone (infatti ho scritto: 
"programmatori",
sottocategoria  con peculiarita' specifiche, ridotta parte del genere 
umano, il che se
non altro, ne riduce di parecchio il numero), ma  la tendenza all' uso 
dei linguaggi
che si intuisce dalle statistiche e dalle tendenze attuali, messe in 
pratica dalla succitata
categoria.
L' ottimizzazione non e' sostanzialmente un requisito che emerge come 
essenziale, tranne
che per il mondo embedded, e anche qui non sono poi molti a fare le 
pulci ai tools,
(qui sicuramente frena il costo dei buoni tools, dato che per la maggior 
parte delle
applicazioni basta un compilatore decente, e' meglio prendere quello che 
costa meno
e ottimizzare a 'mano')
Ciao,
Brix

 ottimizzazione...
Lo e' se lo fai solo dove serve.

 essenziale
Questo semplicemente non è vero. Vedi sopra: se mi dai dei numeri che
dimostrano quanto dici, è un altro discorso.

 di chi sviluppa compilatori è quella di ottimizzarli e per due motivi:
Aggiungerei che ottimizzare un compilatore ha ricadute su tutto il 
software prodotto con quel compilatore. Dunque non è molto diverso 
dall'aumentare la potenza della CPU, e probabilmente ha costi molto 
minori. Inoltre alcune delle migliorie che vengono fatte alle CPU (ad 
esempio l'aggiunta di nuove istruzioni) non avrebbero ricadute sulla 
velocità di esecuzione se i compilatori non le sfruttassero.
E.

dimostrano quanto dici, è un altro discorso.
Se non hai i numeri non puoi dire nemmeno che non è vero, puoi solo 
dire che non ci sono prove nè in un senso, nè nel altro. Il mio test 
della macchina del caffè acquista così una sua validità :oÞ
-- 
Articolo 33 della Costituzione italiana: L'arte e la scienza sono 
libere e libero ne è l'insegnamento.
Se siete tosti: 
http://www.rexresearch.com/kervran/kervran.htm

 Se non hai i numeri non puoi dire nemmeno che non è vero
In questo caso i numeri ce li ho e sono i compilatori presenti in
giro. Trovami un compilatore che non viene appositamente ottimizzato,
per la serie "tanto chi se ne frega delle performance". Neanche i
Javisti arrivano a tanto (e questo è già molto). Posso dire che non è
vero quello che brix dice perché tutti i compilatori presenti sul
mercato sono iper-ottimizzati e perché è la tendenza delle invenzioni
scientifiche (tutte, in qualsiasi campo) quella di progredire
perfezionando il modo di fare certe cose.

 renderlo efficiente. Mi sembra talmente ovvio da risultare banale.
Guarda su questo siamo assolutamente d'accordo, però ... però ... si fa 
quel che il mercato vuole. Tempo fa, ma sospetto anche oggi, il miglior 
generatore di codice ottimizzato era il compilatore Intel. Guardo qui: 
http://www.intel.com/cd/software/products/asmo-na/eng/compilers/278609.htm
 
e vedo che costa sui 600 $, nemmeno una cifra impossibile.
Non ho mai saputo di gente che facesse la fila per comprarlo. Mi viene 
da pensare che l'ottimizzazione non è una richiesta top.
E personalmente, nella mia ditta, io lo farei comprare appunto per 
questo motivo. Detto tra noi.


 velocità di esecuzione se i compilatori non le sfruttassero.
Dubito che l'aggiunta di istruzioni possa essere in se considerata una
'miglioria'. Ci sono diverse considerazioni (se ti interessa i due libri
di Patterson e Henessey sono piuttosto interessanti a riguardo) che
mostrano come in generale aggiungere un'istruzione è tutt'altro che una
miglioria.
Diverso è aggiungere *set* di istruzioni (SSEx, per dire), ma quelle
sono una miglioria perchè spesso aggiungono o modificano un aggeggio
hardware che va più forte (e le istruzioni sono li per sfruttarlo).
Tipicamente poi le CPU moderne internamente sono macchine RISC con un
numero piuttosto ridotto di operazioni e 'interpretano' le istruzioni
della ISA (specie nel caso di x86). 
-- 
-riko

 da pensare che l'ottimizzazione non č una richiesta top.
Ma non č che gli altri *non* ottimizzano. Gli altri ottimizzano 'meno',
ma se ottimizzano 'abbastanza', quale č il problema?
Oltretutto la differenza fra un programma non ottimizzato e uno
ottimizzato 'poco' (nemmeno 'decentemente') č piuttosto abissale. 
Certo, poi se il programma non calcola mai e fa solo gran query al db e
poi le presenta all'utente, probabilmente la differenza quasi non la
vedi. Esattamente come non la vedi se l'applicazione la fai in Python
oppure in qualcosa d'altro.
-- 
-riko

   
Prima una semplice considerazione: ci sono moltissimi compilatori C/C++ 
di ogni razza
e generere, se si cerca se se trovano a bizzeffe e c'e' chi addirittura 
personalizza i compilers
a richiesta.
Ci sono in giro anche moltissimi siti che offrono comparazioni e tra i 
tantissimi compilatori
ci sono differenze abissali, di size e velocita' ( 'relativamente' 
parlando).
Solo per rimanere in ambito x86, l' intel e' *ottimo* ( ma non del tutto 
su architetture AMD ;-)  )
eppure non e' tra i piu' gettonati neanche per sviluppo su Intel, mi 
pare costi 600$.
In ambiente ARM gcc spopola, ma KEIL e IAR (testati personalmente) sono 
decisamente
piu' performanti (per le mie applicazioni). Come mai i suddetti 
compilatori non sono i piu'
usati? Eppure il loro ambiente di sviluppo non e' affatto male....
Perche' semplicemente *costano* molto di piu'. Quindi il requisito 
fondamentale sembra
essere l'economia dell' ambiente di sviluppo piu' che le performance del 
compilatore.
IMHO, ritengo che in generale i compilatori C/C++ recenti siano 
abbastanza ottimizzati
per soddisfare la maggior parte degli sviluppatori, che pertanto non lo 
ritengono questo
un requisito fondamentale.
Potrei sbagliarmi, ma dammi tu dei dati che *dimostrano* che l' 
ottimizzazione
e' cosi' esplicitamente usata come primario requisito per la scelta di 
un compiler ;-)
Secondo me non lo e' e ritengo che la maggioranza dei *programmatori*  
non se lo ponga
nemmeno come problema.
Seconda considerazione:
http://www.evansdata.com
Fanno ricerche di marketing su prodotti IT edi vario genere, non sono certo
l' unico a conoscere tale organizzazione o equivalente.
Eseguono ciclicamente dei polling su argomenti vari per grosse aziende IT.
Tempo addietro ricevetti un report su IDE e ambienti di sviluppo e 
relative statistiche,
Domande tese a valutare editor, debugger, processo di generazione 
documetazione/codice
Performance compilatore etc..... ne emergeva che le performance del 
compilatore *non*
era al primo posto tra i requisiti.
Le ricerche sono annuali, puoi guardare da te se nell' ultimo report e' 
cambiato qualcosa....
Ciao
B.

 oppure in qualcosa d'altro.
Guarda, tra un buon progettista e programmatore in Python può 
massacrare a livello di prestazioni un mediocre progettista e 
programmatore in C++. Di solito un programma ad uso intensivo di CPU da 
qualche parte deve leggere dei dati, li deve elaborare, e poi deve 
mettere i risultati da qualche parte. C'è moltissimo spazio per 
scrivere con saggezza un programma del genere.
Poi alla fine, per me che lavoro su x86, propongo al capo di prendere 
il compilatore Intel che costa molto meno di una settimana di mio 
lavoro di fine-tuning e sicuramente da risultati migliori.
Proposta ad oggi sempre bocciata, tanto il fine-tuning non serve :-)
 ... e il debug lo farà il cliente :-)


 Proposta ad oggi sempre bocciata, tanto il fine-tuning non serve :-)
Dipende: a volte capita che *bisogna* ottimizzare a atutti i costi 
perche' non
e' possibile o e molto piu' costoso cambiare l' hardware (non solo PC:
riprogettare schede da zero a volte e' parecchio oneroso) e qui si
preferisce la strada 'spartana' delle ottimizzazioi manuali o comprare
i compilatori piu' performanti (non solo velocita', spesso e' lo spazio
la risorsa da massimizzare!)
A volte invece l' approccio e' del tutto diverso: se una applicazione
e' lenta, meglio cambiare l' hardware e via, senza stare a perdere
tempo con il software.
Insomma e' un moldo complesso , non c'e' una risposta sola :-(
B.