函数调用中参数的数据类型对处理速度的影响

时间:2018-01-03 06:53:53

标签: assembly microcontroller data-processing

uint16_t fn1 (uint8_t a, uint8_t b) { return (a+b) }  
uint32_t fn2 (uint32_t a, uint32_t b) { return (a+b) }  

在8位和32位微控制器上哪个更快? 用于演示差异的任何等效汇编代码。

例如,采用带有CA78K0编译器的8位Renesas 78K系列微控制器和带RX-CC编译器的32位Renesas rx600系列微控制器。

2 个答案:

答案 0 :(得分:0)

通常,使用与寄存器宽度匹配的类型可以获得最有效的代码。 (或者至少有一个本机操作数大小,例如32位通常在大多数64位架构上都很好。)

更窄的类型几乎从不更多高效(除非你有一个数组,在这种情况下,缓存占用/内存带宽有利于窄类型)。但是,根据你所做的事情,他们可能效率不高。

在具有特定琐碎函数的更新问题中,答案与问题的第一个版本(具有空函数)非常相似:内联一个add比{{1}的开销便宜因此,编译器始终内联此函数是有利可图的,并且希望除非您需要将其地址作为回调或其他内容传递。

call函数的非内联版本主要取决于32位CPU上的调用约定。

如果args可能有高垃圾(在前24位),你必须分别对每个输入进行零扩展,因为你需要一个正确的9位结果,而不仅仅是8(但输入的第9位可以保持垃圾)。

如果8位args已经零扩展到32位寄存器(like ARM32's standard calling convention),或者你必须从内存加载它们(所以你可以使用零扩展字节加载)然后没有额外的32位CPU上的任一功能都需要工作。 32位加法将正确生成16位结果。实际上,链接ARM问题是调用约定对窄整数运算成本影响的另一个很好的例子,或者是在内联时使用比uint16_t = uint8_t + uint8_t更复杂的内容将高垃圾清零的必要性。

如果返回类型也是add,则ARM需要额外的指令来对扩展结果进行零扩展(以清除进位到第9位)。

其他功能的问题没有“一般”答案。在32位CPU上使用窄函数args /返回值可能会或可能不会花费额外成本。它取决于函数,调用约定和指令集。 (你在32位CC-RX编译器的评论中提到了a calling convention that packs narrow args into separate bytes of a single register的内容吗?这听起来效率低下,并且会严重惩罚狭窄的args。但这很不寻常.x86-64 System V只对窄结构执行此操作成员按值传递结构时,而不是单独的args。)

显然,像AVR这样纯粹的8位CPU需要ADD / ADC x3来添加uint32_t args,因此它显然要贵得多。 (请注意,uint8_t在AVR上是16位,因此如果您确实需要32,则仅使用int。)

以下是问题的第一个版本的答案,当函数为空时。后来的编辑改变了问题,询问OP显然打算首先提出什么问题。

它们都是相同的速度,因为空函数内联并优化到无指令。调用站点甚至不必计算arg值,因此uint32_t的多寄存器args实际上不会花费每个arg 4个指令。

您正在将简单的函数放在头文件中,或使用链接时优化,对吗?

是的,即使对于代码大小至关重要的微控制器,当编译器的主体小于指令设置+调用时,内联函数也是有利可图的。因此,期望编译器甚至使用fn2或其他任何内容进行此优化是合理的。

答案 1 :(得分:0)

亲自尝试一下。 Inst那个作业分配的全部内容?

unsigned char fun1 ( unsigned char a, unsigned char b)
{
    return (a+b);
}  
unsigned int fun2 ( unsigned int a, unsigned int b)
{
    return (a+b);
}
unsigned long fun3 ( unsigned long a, unsigned long b)
{
    return (a+b);
}

没有/想要你的编译器,但在你开始这个练习之前它应该是显而易见的。如果您将高级语言变量/操作数大小与架构不匹配,则架构可直接提供解决方案,或者架构必须屏蔽或级联。

我在这里展示了一系列不同的架构:

00000000 <fun1>:
   0:   e0800001    add r0, r0, r1
   4:   e20000ff    and r0, r0, #255    ; 0xff
   8:   e12fff1e    bx  lr

0000000c <fun2>:
   c:   e0800001    add r0, r0, r1
  10:   e12fff1e    bx  lr

00000000 <_fun1>:
   0:   1166            mov r5, -(sp)
   2:   1185            mov sp, r5
   4:   9d40 0004       movb    4(r5), r0
   8:   9d41 0006       movb    6(r5), r1
   c:   6040            add r1, r0
   e:   1585            mov (sp)+, r5
  10:   0087            rts pc

00000012 <_fun2>:
  12:   1166            mov r5, -(sp)
  14:   1185            mov sp, r5
  16:   1d40 0004       mov 4(r5), r0
  1a:   6d40 0006       add 6(r5), r0
  1e:   1585            mov (sp)+, r5
  20:   0087            rts pc

00000022 <_fun3>:
  22:   1166            mov r5, -(sp)
  24:   1185            mov sp, r5
  26:   1d40 0004       mov 4(r5), r0
  2a:   1d41 0006       mov 6(r5), r1
  2e:   6d40 0008       add 10(r5), r0
  32:   6d41 000a       add 12(r5), r1
  36:   0b40            adc r0
  38:   1585            mov (sp)+, r5
  3a:   0087            rts pc

00000000 <fun1>:
   0:   86 0f           add r24, r22
   2:   08 95           ret

00000004 <fun2>:
   4:   86 0f           add r24, r22
   6:   97 1f           adc r25, r23
   8:   08 95           ret

0000000a <fun3>:
   a:   62 0f           add r22, r18
   c:   73 1f           adc r23, r19
   e:   84 1f           adc r24, r20
  10:   95 1f           adc r25, r21
  12:   08 95           ret

00000000 <fun1>:
   0:   4f 5e           add.b   r14,    r15 
   2:   30 41           ret         

00000004 <fun2>:
   4:   0f 5e           add r14,    r15 
   6:   30 41           ret         

00000008 <fun3>:
   8:   0e 5c           add r12,    r14 
   a:   0f 6d           addc    r13,    r15 
   c:   30 41           ret         

0000000000000000 <fun1>:
   0:   12001c21    and w1, w1, #0xff
   4:   0b200020    add w0, w1, w0, uxtb
   8:   d65f03c0    ret
   c:   d503201f    nop

0000000000000010 <fun2>:
  10:   0b010000    add w0, w0, w1
  14:   d65f03c0    ret

00000000 <fun1>:
   0:   00851021    addu    $2,$4,$5
   4:   03e00008    jr  $31
   8:   304200ff    andi    $2,$2,0xff

0000000c <fun2>:
   c:   03e00008    jr  $31
  10:   00851021    addu    $2,$4,$5

看看作业中的编译器为您的特定代码生成了什么,因为我对其进行了一些修改(并修复了错误),我的输入和输出匹配,让它们不匹配只会为此作业增添更多乐趣。

修改

是的8位加8位是9位,适合16或18或24,32,36,64等等,但是其中一些没有很多寄存器并通过内存工作不同的优势。

00000000 <ufun>:
   0:   e0800001    add r0, r0, r1
   4:   e12fff1e    bx  lr

00000008 <sfun>:
   8:   e0800001    add r0, r0, r1
   c:   e12fff1e    bx  lr


0000000000000000 <ufun>:
   0:   12001c21    and w1, w1, #0xff
   4:   0b200020    add w0, w1, w0, uxtb
   8:   d65f03c0    ret
   c:   d503201f    nop

0000000000000010 <sfun>:
  10:   13001c21    sxtb    w1, w1
  14:   0b208020    add w0, w1, w0, sxtb
  18:   d65f03c0    ret
  1c:   d503201f    nop

00000000 <ufun>:
   0:   03e00008    jr  $31
   4:   00851021    addu    $2,$4,$5

00000008 <sfun>:
   8:   03e00008    jr  $31
   c:   00851021    addu    $2,$4,$5

00000000 <ufun>:
   0:   4f 4f           mov.b   r15,    r15 
   2:   4e 4e           mov.b   r14,    r14 
   4:   0f 5e           add r14,    r15 
   6:   30 41           ret         

00000008 <sfun>:
   8:   8f 11           sxt r15     
   a:   8e 11           sxt r14     
   c:   0f 5e           add r14,    r15 
   e:   30 41           ret         

00000000 <ufun>:
   0:   70 e0           ldi r23, 0x00   ; 0
   2:   26 2f           mov r18, r22
   4:   37 2f           mov r19, r23
   6:   28 0f           add r18, r24
   8:   31 1d           adc r19, r1
   a:   82 2f           mov r24, r18
   c:   93 2f           mov r25, r19
   e:   08 95           ret

00000010 <sfun>:
  10:   06 2e           mov r0, r22
  12:   00 0c           add r0, r0
  14:   77 0b           sbc r23, r23
  16:   26 2f           mov r18, r22
  18:   37 2f           mov r19, r23
  1a:   28 0f           add r18, r24
  1c:   31 1d           adc r19, r1
  1e:   87 fd           sbrc    r24, 7
  20:   3a 95           dec r19
  22:   82 2f           mov r24, r18
  24:   93 2f           mov r25, r19
  26:   08 95           ret

00000000 <_ufun>:
   0:   1166            mov r5, -(sp)
   2:   1185            mov sp, r5
   4:   9d41 0004       movb    4(r5), r1
   8:   45c1 ff00       bic $-400, r1
   c:   9d40 0006       movb    6(r5), r0
  10:   45c0 ff00       bic $-400, r0
  14:   6040            add r1, r0
  16:   1585            mov (sp)+, r5
  18:   0087            rts pc

0000001a <_sfun>:
  1a:   1166            mov r5, -(sp)
  1c:   1185            mov sp, r5
  1e:   9d41 0004       movb    4(r5), r1
  22:   9d40 0006       movb    6(r5), r0
  26:   6040            add r1, r0
  28:   1585            mov (sp)+, r5
  2a:   0087            rts pc

00000000 <ufun>:
   0:   952e                    add x10,x10,x11
   2:   8082                    ret

00000004 <sfun>:
   4:   952e                    add x10,x10,x11
   6:   8082                    ret