[英]Cortex M3, gcc - faster bounding in C
我試圖限制 c 中的 2 個整數之間的差異; 本質上是絕對值 ( a- b) < bound。 有誰知道,對於 Arm Cortex gcc 編譯器,如果我最好采用差異的絕對值:
if (abs( a - b) < bound)
{
.........
}
或者如果我應該做兩個比較:
int diff;
diff = a - b;
if ((bound > diff) && (bound > -diff))
{
.......
}
我知道這與編譯器優化和 Arm 指令集有很大關系,所以這不是我可以隨便確定的。
謝謝
去嘗試一下
#include <stdlib.h>
unsigned int fun0 ( int a, int b, int bound )
{
if (abs( a - b) < bound)
{
return(1);
}
return(0);
}
unsigned int fun1 ( int a, int b, int bound )
{
int diff;
diff = a - b;
if ((bound > diff) && (bound > (-diff)))
{
return(1);
}
return(0);
}
unsigned int fun2 ( int a, int b, int bound )
{
int diff;
diff = a > b ? a-b : b-a;
if(diff < bound)
{
return(1);
}
return(0);
}
gcc 的一個版本
Disassembly of section .text:
00000000 <fun0>:
0: 1a40 subs r0, r0, r1
2: 2800 cmp r0, #0
4: bfb8 it lt
6: 4240 neglt r0, r0
8: 4290 cmp r0, r2
a: bfac ite ge
c: 2000 movge r0, #0
e: 2001 movlt r0, #1
10: 4770 bx lr
12: bf00 nop
00000014 <fun1>:
14: 1a41 subs r1, r0, r1
16: 4291 cmp r1, r2
18: da05 bge.n 26 <fun1+0x12>
1a: 4249 negs r1, r1
1c: 4291 cmp r1, r2
1e: bfac ite ge
20: 2000 movge r0, #0
22: 2001 movlt r0, #1
24: 4770 bx lr
26: 2000 movs r0, #0
28: 4770 bx lr
2a: bf00 nop
0000002c <fun2>:
2c: 4288 cmp r0, r1
2e: bfcc ite gt
30: 1a40 subgt r0, r0, r1
32: 1a08 suble r0, r1, r0
34: 4290 cmp r0, r2
36: bfac ite ge
38: 2000 movge r0, #0
3a: 2001 movlt r0, #1
3c: 4770 bx lr
3e: bf00 nop
fun0 和 fun2 是相同數量的指令,沒有分支,利用條件執行(沒有結果可能有明顯的贏家)。 中間那個,你的替代方案,會產生一個分支,但路徑更短,在這種情況下很難稱它為失敗者。 與 9 和 9 相比,9 或 5 條指令(包括分支)。
目標不同,結果可能不同。
另一種方法:
#include <stdlib.h>
int funct(int a, int b, int bound, int c)
{
if (abs(a-b) < bound) c = 5;
return c;
}
int funct2(const int a, const int b, const int bound, int c)
{
int diff;
diff = a > b ? a-b : b-a;
if ((bound > diff) && (bound > -diff)) c = 4;
return c;
}
00000000 <funct>:
0: 1a40 subs r0, r0, r1
2: 2800 cmp r0, #0
4: bfb8 it lt
6: 4240 neglt r0, r0
8: 4290 cmp r0, r2
a: bfac ite ge
c: 4618 movge r0, r3
e: 2005 movlt r0, #5
10: 4770 bx lr
12: bf00 nop
00000014 <funct2>:
14: 4288 cmp r0, r1
16: bfcc ite gt
18: 1a41 subgt r1, r0, r1
1a: 1a09 suble r1, r1, r0
1c: 4291 cmp r1, r2
1e: da03 bge.n 28 <funct2+0x14>
20: 4249 negs r1, r1
22: 4291 cmp r1, r2
24: bfb8 it lt
26: 2304 movlt r3, #4
28: 4618 mov r0, r3
2a: 4770 bx lr
第二種解決方案有一條指令較少但會產生分支的路徑,另一條路徑較長。
兩者都是未定義的行為。 減法可能會溢出。 您需要檢查評論中提到的@e2-e4,它更大且被減去。 gcc 將對其進行很好的優化。
int funct(int a, int b, int bound, int c)
{
if (abs(a > b ? a-b : b-a) < bound) c = 5;
return c;
}
int funct2(const int a, const int b, const int bound, int c)
{
int diff;
diff = a > b ? a-b : b-a;
if ((bound > diff) && (bound > -diff)) c = 4;
return c;
}
兩者都編譯完全相同的代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.