Cortex M,gcc -C中的更快绑定

blpfk2vs  于 2023-06-30  发布在  其他
关注(0)|答案(2)|浏览(115)

我试图在C中限制2个整数之间的差异;基本上绝对值(a-b)<界。有没有人知道,对于Arm Cortex gcc编译器,如果我最好取差值的绝对值:

if (abs( a - b) < bound)
    {
      .........
    }

或者我应该做两个比较:

int diff;
    diff = a - b;
    if ((bound > diff) && (bound > -diff))
    {
     .......
    }

我知道这与编译器优化和Arm指令集有很大关系,所以这不是我可以随便决定的。

avkwfej4

avkwfej41#

试试看

#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或5条指令(包括分支)与9和9相比。
目标不同,结果可能不同。
另一种方法:

#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

第二种解决方案具有指令较少的路径,但引发分支,另一种路径较长。

fivyi3re

fivyi3re2#

两者都是未定义的行为。减法可能溢出。你需要检查评论中提到的@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;
}

两者编译完全相同的代码。

相关问题