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系列微控制器。
答案 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