簡體   English   中英

Cortex M3、gcc - C 中的邊界更快

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM