Volatile insists that each operation with the variables uses the variable from memory. Instead of a cached one in the registers.
Example:
int d; // d is global, otherwise it won't get a memory location
int main(void) {
volatile int vd;
vd++;
vd++;
vd++;
__DMB();
d++;
d++;
d++;
}
Will have 3 read-modify-write cycles. As compared to a non volatile one where it will only have 1 read, 3 modifies, and 1 write.
That makes optimizing much more complicated. But there might still be things to do. For example, I used a NOP instead of an DMB first. But it was inserted between the last two vd++'s. Not wat I typed in C.
34: vd++;
0x080002A6 9800 LDR r0,[sp,#0x00]
0x080002A8 1C40 ADDS r0,r0,#1
0x080002AA 9000 STR r0,[sp,#0x00]
35: vd++;
0x080002AC 9800 LDR r0,[sp,#0x00]
0x080002AE 1C40 ADDS r0,r0,#1
0x080002B0 9000 STR r0,[sp,#0x00]
36: vd++;
37:
0x080002B2 9800 LDR r0,[sp,#0x00]
0x080002B4 1C40 ADDS r0,r0,#1
0x080002B6 9000 STR r0,[sp,#0x00]
38: __DMB();
39:
0x080002B8 F3BF8F5F DMB.W
40: d++;
41: d++;
0x080002BC 4903 LDR r1,[pc,#12] ; @0x080002CC
0x080002BE 6808 LDR r0,[r1,#0x00]
42: d++;
0x080002C0 1CC0 ADDS r0,r0,#3
0x080002C2 6008 STR r0,[r1,#0x00]
43: }
0x080002C4 2000 MOVS r0,#0x00
(yes, its arm)
Registers are volatile defined in the header. Or at least they should be!