Dropping this here as it looks to be interesting to many:
https://m.eet.com/media/1157397/atc-152paper_shore_v4.pdf
Has anybody seen "__promise" before? I haven't! - gives compiler hints to allow better code generation.
Example from paper:
void f(int *x, int n)
{
int i;
__promise((n > 0) && ((n&7)==0));
for (i = 0; i < n; i++) {
x[i]++;
}
}
It looks like you can convince GCC to perform the same optimization like so:
void f(int *x, int n)
{
int i;
if ((n > 0) && ((n&7)==0)) {
for (i = 0; i < n; i++) {
x[i]++;
}
}
else {
__builtin_unreachable();
}
}
00000000 <f>:
0: 3804 subs r0, #4
2: eb00 0181 add.w r1, r0, r1, lsl #2
6: f850 3f04 ldr.w r3, [r0, #4]!
a: 3301 adds r3, #1
c: 4281 cmp r1, r0
e: 6003 str r3, [r0, #0]
10: d1f9 bne.n 6 <f+0x6>
12: 4770 bx lr
Compare that to the version without:
void g(int *x, int n)
{
int i;
for (i = 0; i < n; i++) {
x[i]++;
}
}
00000014 <g>:
14: 2900 cmp r1, #0
16: dd08 ble.n 2a <g+0x16>
18: 3804 subs r0, #4
1a: eb00 0181 add.w r1, r0, r1, lsl #2
1e: f850 3f04 ldr.w r3, [r0, #4]!
22: 3301 adds r3, #1
24: 4281 cmp r1, r0
26: 6003 str r3, [r0, #0]
28: d1f9 bne.n 1e <g+0xa>
2a: 4770 bx lr
I don't see this as any worse than all other situations where lying to the compiler invokes undefined behaviour, eg. casting unaligned pointers and so on. Static code analyzers will use regular assert()s in their analysis, but I don't know offhand if any compilers do. Maybe in optimized debug builds?
maybe a stupid question but wouldn't this allow the compiler to do the same optimization? ???
void f(int *x, int n)
{
if (((n > 0) && ((n&7)==0)) != true)
return;
int i;
for (i = 0; i < n; i++) {
x[i]++;
}
}
maybe a stupid question but wouldn't this allow the compiler to do the same optimization? ???
void f(int *x, int n)
{
if (((n > 0) && ((n&7)==0)) != true)
return;
int i;
for (i = 0; i < n; i++) {
x[i]++;
}
}
Maybe you haven't read the whole thread, because this is exactly what some of us have said (I being first when saying "if you actually actively CHECK for a condition, the compiler will not only generate code to check it's true, but will also have all hints it needs to optimize the code when it is".
And most of us agree that the ARM optimization hint is a VERY slippery thing.
Now, to be fair, many of us have already encountered the case when you had to write a function that should be very efficient, and in which you didn't want to check for extra conditions each time it's executed, due to the extra overhead (in that case, you'd make sure the conditions always hold true when calling the function). In that case, if again you chose NOT TO actively check parameters, giving the compiler an opportunity to better optimize the code can be interesting, which this "assume" directive is for. It's always risky, but I'd venture many, if not most of us, have done that at least once (silently assuming parameter values are in a given range).
If you do that correctly, the calling code should still include ways of checking the parameters from a higher level, or at least only generate parameters that meet the expected ranges. There again, the compiler WILL have the info if it's not too dumb. Of course, for that to work properly, you should usually put said function in the same source file as where it's called. If it can be called externally, then the compiler will usually not do any kind of cross-file static analysis AFAIK. So my rule and advice here is that if you ever need to write such a function that doesn't check parameters at run-time for optimization reasons, only do that with local functions (local to one source file, declared static).