亚洲国产成人av在线观看,777米奇色狠狠狠888影视,一二三四在线视频观看社区,小荡货奶真大水真多紧视频

【方輝專欄】ARM嵌入式編譯器(五) 優(yōu)化循環(huán)的4種方法
發(fā)布時間:2022-08-16

摘要: 本文主要對Arm Compiler 6編譯器的優(yōu)化循環(huán)對編寫優(yōu)化代碼的作用進行介紹。

關鍵字:Arm Compiler 6、編譯器、優(yōu)化循環(huán) 、循環(huán)展開、pragma、循環(huán)向量化、循環(huán)終止、無限循環(huán)、


1. 循環(huán)展開

循環(huán)執(zhí)行的時間取決于循環(huán)的次數(shù),循環(huán)中每次檢查是否進行循環(huán)的條件會降低循環(huán)的性能。使用循環(huán)展開可以減少檢查條件的判斷次數(shù),但是展開循環(huán)就意味著增加代碼量。例如:在精確的時鐘周期循環(huán)中,可以使用#pragma unroll (n)來展開循環(huán)。

“pragma”(編譯指示)僅在選擇優(yōu)化等級為-O2/-O3/-Ofast和-Omax時有效。

編譯指示的相關用法:

#pragma unroll (n)展開n次循環(huán)
#pragma unroll_completely展開所有循環(huán)

注:雖然給出了循環(huán)展開的編譯指示,但Arm官方不建議使用,這樣會影響編譯器的展開優(yōu)化和其他循環(huán)優(yōu)化。

不使用循環(huán)展開的代碼使用循環(huán)展開的代碼
int countSetBits1(unsigned int n)
{
int bits = 0;
while (n != 0)
{
if (n & 1) bits++;
n >>= 1;
}
return bits;
}
int countSetBits2(unsigned int n)
{
int bits = 0;
#pragma unroll (4)
while (n != 0)
{
if (n & 1) bits++;
n >>= 1;
}
return bits;
}

將代碼分別復制到file.c文件中,然后使用以下命令進行編譯和反匯編。

armclang --target=arm-arm-none-eabi -march=armv8-a file.c -O2 -S -o file.s

不使用循環(huán)展開的匯編代碼使用循環(huán)展開的匯編代碼
countSetBits1:
mov r1, r0
mov r0, #0
cmp r1, #0
bxeq lr
mov r2, #0
mov r0, #0
.LBB0_1:
and r3, r1, #1
cmp r2, r1, asr #1
add r0, r0, r3
lsr r3, r1, #1
mov r1, r3
bne .LBB0_1
bx lr
countSetBits2:
mov r1, r0
mov r0, #0
cmp r1, #0
bxeq lr
mov r2, #0
mov r0, #0
LBB0_1:
and r3, r1, #1
cmp r2, r1, asr #1
add r0, r0, r3
beq .LBB0_4
@ BB#2:
asr r3, r1, #1
cmp r2, r1, asr #2
and r3, r3, #1
add r0, r0, r3
asrne r3, r1, #2
andne r3, r3, #1
addne r0, r0, r3
cmpne r2, r1, asr #3
beq .LBB0_4
@ BB#3:
asr r3, r1, #3
cmp r2, r1, asr #4
and r3, r3, #1
add r0, r0, r3
asr r3, r1, #4
mov r1, r3
bne .LBB0_1
.LBB0_4:
bx lr

可以看到展開循環(huán)時,代碼執(zhí)行會更快,但代碼量也更大。


2. 循環(huán)向量化

如果編譯的目標含有SIMD單元,那么編譯器就可以使用向量引擎來優(yōu)化代碼的向量部分。在優(yōu)化等級為-O1,可以使用-fvectorize 來啟動優(yōu)化,而在-O2或更高等級時向量優(yōu)化是自動啟用。

要使用向量優(yōu)化,在編寫代碼的時候需要將結構體的成員放到同一個循環(huán)中,而不能使用獨立的循環(huán)。

可以進行SIMD優(yōu)化的代碼不能進行SIMD優(yōu)化的代碼
typedef struct tBuffer {
int a;
int b;
int c;
} tBuffer;
tBuffer buffer[8];
void DoubleBuffer1 (void)
{
int i;
for (i=0; i<8; i++)
{
buffer[i].a *= 2;
buffer[i].b *= 2;
buffer[i].c *= 2;
}
}
typedef struct tBuffer {
int a;
int b;
int c;
} tBuffer;
tBuffer buffer[8];
void DoubleBuffer2 (void)
{
int i;
for (i=0; i<8; i++)
buffer[i].a *= 2;
for (i=0; i<8; i++)
buffer[i].b *= 2;
for (i=0; i<8; i++)
buffer[i].c *= 2;
}

對于每個例子,將代碼分別復制到file.c文件中,然后使用以下命令進行編譯和反匯編。

armclang --target=arm-arm-none-eabi -march=armv8-a file.c -O2 -S -o file.s

向量優(yōu)化后匯編代碼未進行向量優(yōu)化的代碼
DoubleBuffer1:
.fnstart
@ BB#0:
movw r0, :lower16:buffer
movt r0, :upper16:buffer
vld1.64 {d16, d17}, [r0:128]
mov r1, r0
vshl.i32 q8, q8, #1
vst1.32 {d16, d17}, [r1:128]!
vld1.64 {d16, d17}, [r1:128]
vshl.i32 q8, q8, #1
vst1.64 {d16, d17}, [r1:128]
add r1, r0, #32
vld1.64 {d16, d17}, [r1:128]
vshl.i32 q8, q8, #1
vst1.64 {d16, d17}, [r1:128]
add r1, r0, #48
vld1.64 {d16, d17}, [r1:128]
vshl.i32 q8, q8, #1
vst1.64 {d16, d17}, [r1:128]
add r1, r0, #64
add r0, r0, #80
vld1.64 {d16, d17}, [r1:128]
vshl.i32 q8, q8, #1
vst1.64 {d16, d17}, [r1:128]
vld1.64 {d16, d17}, [r0:128]
vshl.i32 q8, q8, #1
vst1.64 {d16, d17}, [r0:128]
bxlr
DoubleBuffer2:
.fnstart
@ BB#0:
movw r0, :lower16:buffer
movt r0, :upper16:buffer
ldr r1, [r0]
lsl r1, r1, #1
str r1, [r0]
ldr r1, [r0, #12]
lsl r1, r1, #1
str r1, [r0, #12]
ldr r1, [r0, #24]
lsl r1, r1, #1
str r1, [r0, #24]
ldr r1, [r0, #36]
lsl r1, r1, #1
str r1, [r0, #36]
ldr r1, [r0, #48]
lsl r1, r1, #1
str r1, [r0, #48]
ldr r1, [r0, #60]
lsl r1, r1, #1
str r1, [r0, #60]
ldr r1, [r0, #72]
lsl r1, r1, #1
str r1, [r0, #72]
ldr r1, [r0, #84]
lsl r1, r1, #1
str r1, [r0, #84]
ldr r1, [r0, #4]
lsl r1, r1, #1
str r1, [r0, #4]
ldr r1, [r0, #16]
lsl r1, r1, #1
...
bx lr

在64位運行狀態(tài)下要避免編譯器使用SIMD向量優(yōu)化可以在-march或-mcpu后+nosimd;

例如:

armclang --target=aarch64-arm-none-eabi -march=armv8-a+nosimd -O2 file.c -S -o file.s

在32位運行狀態(tài)下要避免編譯器使用SIMD向量優(yōu)化,可以通過設置-mfpu=fp-armv8;

例如:

armclang --target=aarch32-arm-none-eabi -march=armv8-a -mfpu=fp-armv8 -O2 file.c -S -o file.s


3. 循環(huán)終止

在寫循環(huán)的時候如果編寫不當會使得代碼的運行效率降低和代碼量增大。建議使用以下的終止條件:

1)使用變量類型為:unsigned int

2)使用向下減少的計數(shù)方式,以減到0作為計數(shù)結束。

3)使用簡單的終止條件。

單獨或組合使用以上原則的終止條件,可以獲得更好的代碼大小或效率。

例如:這是一個實現(xiàn)n!的計算程序。

遞增循環(huán)遞減循環(huán)
int fact1(int n)
{
int i, fact = 1;
for (i = 1; i <= n; i++)
fact *= i;
return (fact);
}
int fact2(int n)
{
unsigned int i, fact = 1;
for (i = n; i != 0; i--)
fact *= i;
return (fact);
}

用以下命令反匯編以下armclang -Os -S --target=arm-arm-none-eabi -march=armv8-a

遞增循環(huán)遞減循環(huán)
fact1:
mov r1, r0
mov r0, #1
cmp r1, #1
bxlt lr
mov r2, #0
.LBB0_1:
add r2, r2, #1
mul r0, r0, r2
cmp r1, r2
bne .LBB0_1
bx lr
fact2:
mov r1, r0
mov r0, #1
cmp r1, #0
bxeq lr
.LBB1_1:
mul r0, r0, r1
subs r1, r1, #1
bne .LBB1_1
bx lr

對比反匯編代碼可以看出在遞減循環(huán)中用SUBS指令代替了遞增循環(huán)中ADD 和CMP兩條指令。這是因為SUBS指令會自動更新Z標志。

此外在遞減循環(huán)中變量n不必再循環(huán)的過程實時使用,從而減少了寄存器的數(shù)量。

如果終止條件是一個函數(shù),則循環(huán)的每次都調(diào)用該函數(shù),這種情況下遞減的循環(huán)優(yōu)勢就更明顯了。例如:

for (...; i < get_limit(); ...);

說明:這種遞減循環(huán)計數(shù)的方式也適用于while-do 命令。


4. 無限循環(huán)

在某些情況下armclang會刪除一些編譯器認為沒有影響的無限循環(huán),從而導致最終程序無法正常運行。

為確保無限循環(huán)的正確編譯執(zhí)行,ARM官方建議在無限循環(huán)中添加__arm volatile的聲明。這個聲明的目的是告訴編譯器刪除這個無限循環(huán)會有影響,不能被優(yōu)化刪除。在無限循環(huán)中,把處理器設置為低功耗模式是一個不錯的做法,當有中斷或事件觸發(fā)時再回到正常模式。

下面是一個包含__arm volatile聲明的無限循環(huán)例子:

void infinite_loop(void) {

while (1)

??__asm volatile("wfe");

}


注:wfe(Wait for Event)是給處理器一個提示,使處理器進入低功耗狀態(tài),直到事件或中斷觸發(fā)。


來源:《Arm? Compiler for Embedded User Guide Version 6.18》


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


關于億道電子

億道電子技術有限公司(英文名稱:Emdoor Electronics Technology Co.,Ltd)是國內(nèi)資深的研發(fā)工具軟件提供商,公司成立于 2002 年,面向中國廣大的制造業(yè)客戶提供研發(fā)、設計、管理過程中使用的各種軟件開發(fā)工具,致力于幫助客戶提高研發(fā)管理效率、縮短產(chǎn)品設計周期,提升產(chǎn)品可靠性。

20 年來,先后與 Altium、ARM、Ansys、QT、Adobe、Visu-IT、Minitab、Testplant、EPLAN、HighTec、GreenHills、PLS、Ashling、MSC Software 、Autodesk、Source Insight、TeamEDA、MicroFocus等多家全球知名公司建立戰(zhàn)略合作伙伴關系,并作為他們在中國區(qū)的主要分銷合作伙伴服務了數(shù)千家中國本土客戶,為客戶提供從芯片級開發(fā)工具、EDA 設計工具、軟件編譯以及測試工具、結構設計工具、仿真工具、電氣設計工具、以及嵌入式 GUI 工具等等。億道電子憑借多年的經(jīng)驗積累,真正的幫助客戶實現(xiàn)了讓研發(fā)更簡單、更可靠、更高效的目標。

歡迎關注“億道電子”公眾號

了解更多研發(fā)工具軟件知識