My code works in debug mode. In release mode, however, I have to disable all optimizations with the -O0 flag. I would like to understand what the problem is and how I could use some optimizations.
I am programming on Linux installed in a SoC FPGA (i.e. an FPGA with a hardware ARM core). To exchange data with the firmware (FPGA side), I map the FPGA memory to the Linux address space and use the following two macros to respectively read from and write to the firmware, on a 32-bit data bus:
#define IORD(base, index) (*(((uint32_t *)base)+index))
#define IOWR(base, index, data) (*(((uint32_t *)base)+index) = data)
Memory mapping and offset calculation:
void *h2f_virtual_base;
uint32_t *ravioliDigProc_addr = NULL;
h2f_virtual_base = mmap(NULL, H2F_SPAN, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, H2F_BASE);
ravioliDigProc_addr = (uint32_t*) ((uint8_t*) h2f_virtual_base + (RAVIOLIDIGPROC_0_BASE & H2F_MASK));
The core of this test code consists in the while loop below. The normal behavior it to read the 2048 values in the firmware buffer and exit the loop.
When optimizations are enabled, no value is read and the loop exits at the 1st iteration. Interestingly, if I swap the test and the fprintf() call, it loops 40000 times and writes the same values 40000 times in the file.
while( (test != 0) && (ne < 40000) ) {
volatile uint32_t data1, data2;
volatile uint32_t d1, d2, d3, d4;
IOWR(ravioliDigProc_addr, 0x0003, 0x00000008);
IOWR(ravioliDigProc_addr, 0x0003, 0x00000000);
data1 = IORD(ravioliDigProc_addr, 0x0004);
data2 = IORD(ravioliDigProc_addr, 0x0005);
myData = IORD(ravioliDigProc_addr, 0x0003);
d1 = data1 & 0xFFFF;
d2 = (data1 & 0xFFFF0000)>>16;
d3 = data2 & 0xFFFF;
d4 = (data2 & 0xFFFF0000)>>16;
test = myData & 0x00010000;
if(!test) {
printf("test == 0: ne = %d\n", ne);
break;
}
fprintf(pFile, "%d,%d,%d,%d\n", d1, d2, d3, d4);
ne++;
}
printf("%d values saved\n", ne);
printf("After while:\t0x%02x: 0x%08x\n", 0x0003, myData);
If disabling all optimization is the only option, is it possible to do so only on some parts of the code or on some files?
My code works in debug mode. In release mode, however, I have to disable all optimizations with the -O0 flag. I would like to understand what the problem is and how I could use some optimizations.
I am programming on Linux installed in a SoC FPGA (i.e. an FPGA with a hardware ARM core). To exchange data with the firmware (FPGA side), I map the FPGA memory to the Linux address space and use the following two macros to respectively read from and write to the firmware, on a 32-bit data bus:
#define IORD(base, index) (*(((uint32_t *)base)+index))
#define IOWR(base, index, data) (*(((uint32_t *)base)+index) = data)
Memory mapping and offset calculation:
void *h2f_virtual_base;
uint32_t *ravioliDigProc_addr = NULL;
h2f_virtual_base = mmap(NULL, H2F_SPAN, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, H2F_BASE);
ravioliDigProc_addr = (uint32_t*) ((uint8_t*) h2f_virtual_base + (RAVIOLIDIGPROC_0_BASE & H2F_MASK));
The core of this test code consists in the while loop below. The normal behavior it to read the 2048 values in the firmware buffer and exit the loop.
When optimizations are enabled, no value is read and the loop exits at the 1st iteration. Interestingly, if I swap the test and the fprintf() call, it loops 40000 times and writes the same values 40000 times in the file.
while( (test != 0) && (ne < 40000) ) {
volatile uint32_t data1, data2;
volatile uint32_t d1, d2, d3, d4;
IOWR(ravioliDigProc_addr, 0x0003, 0x00000008);
IOWR(ravioliDigProc_addr, 0x0003, 0x00000000);
data1 = IORD(ravioliDigProc_addr, 0x0004);
data2 = IORD(ravioliDigProc_addr, 0x0005);
myData = IORD(ravioliDigProc_addr, 0x0003);
d1 = data1 & 0xFFFF;
d2 = (data1 & 0xFFFF0000)>>16;
d3 = data2 & 0xFFFF;
d4 = (data2 & 0xFFFF0000)>>16;
test = myData & 0x00010000;
if(!test) {
printf("test == 0: ne = %d\n", ne);
break;
}
fprintf(pFile, "%d,%d,%d,%d\n", d1, d2, d3, d4);
ne++;
}
printf("%d values saved\n", ne);
printf("After while:\t0x%02x: 0x%08x\n", 0x0003, myData);
If disabling all optimization is the only option, is it possible to do so only on some parts of the code or on some files?
Share Improve this question asked Mar 21 at 9:27 dpengdpeng 4872 gold badges7 silver badges17 bronze badges 4 |1 Answer
Reset to default 0In release mode, however, I have to disable all optimizations with the -O0 flag.
There are only two reasons for this behavior:
- There is a bug in your program -- it exercises some kind of undefined behavior, and compiler optimization takes advantage of that (e.g. by removing all code which would lead to actual execution of UB).
- There is a compiler bug.
In 99.99% of the cases where optimization leads to wrong result, the programmer is at fault.
In the other 0.01% of the cases, there is a compiler bug.
I would like to understand what the problem is and how I could use some optimizations.
Without an MCVE, nobody can really help you (although some comments have already pointed out problematic code).
Your best bet is to make unit tests which can run on your development machine and exercise most of your code, and then run these unit tests with AddressSanitizer, UndefinedBehaviorSanitizer, etc. etc.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744363602a4570590.html
volatile
on local variables doesn't make much sense. – Mat Commented Mar 21 at 9:32(volatile uint32_t *)
. Btw, I think it is fine to use thebase[index]
syntax here (easier to read). – Jérôme Richard Commented Mar 21 at 12:59(uint32_t*) ((uint8_t*) ...
.uintptr_t
should be used for arithmetic instead.std::bit_cast
should also be fine here. Note the offset must be aligned tosizeof(uint32_t)
or this is UB otherwise. – Jérôme Richard Commented Mar 21 at 13:02