gpt4 book ai didi

c - 循环展开(按位运算)

转载 作者:太空狗 更新时间:2023-10-29 17:23:03 27 4
gpt4 key购买 nike

我正在编写一个 Linux 内核驱动程序(用于 ARM)并且在一个 irq 处理程序中我需要检查中断位。

bit
0/16 End point 0 In/Out interrupt
(very likely, while In is more likely)
1/17 End point 1 In/Out interrupt
...
15/31 End point 15 In/Out interrupt

请注意,一次可以设置多个位。

所以这是代码:

int i;
u32 intr = read_interrupt_register();

/* ep0 IN */
if(likely(intr & (1 << 0))){
handle_ep0_in();
}

/* ep0 OUT */
if(likely(intr & (1 << 16))){
handle_ep0_out();
}

for(i=1;i<16;++i){
if(unlikely(intr & (1 << i))){
handle_ep_in(i);
}
if(unlikely(intr & (1 << (i + 16)))){
handle_ep_out(i);
}
}

(1 << 0)(1 << 16)将在编译时计算,但是 (1 << i)(1 << (i + 16))不会。循环中还会有积分比较和加法。

因为是irq handler,工作应该在最短的时间内完成。这让我考虑是否需要对其进行一些优化。

可能的方法?

1. 拆分循环,好像没什么区别...

/* ep0 IN */
if(likely(intr & (1 << 0))){
handle_ep0_in();
}

/* ep0 OUT */
if(likely(intr & (1 << 16))){
handle_ep0_out();
}

for(i=1;i<16;++i){
if(unlikely(intr & (1 << i))){
handle_ep_in(i);
}
}
for(i=17;i<32;++i){
if(unlikely(intr & (1 << i))){
handle_ep_out(i - 16);
}
}

2. 转移 intr而不是要比较的值?

/* ep0 IN */
if(likely(intr & (1 << 0))){
handle_ep0_in();
}

/* ep0 OUT */
if(likely(intr & (1 << 16))){
handle_ep0_out();
}

for(i=1;i<16;++i){
intr >>= 1;
if(unlikely(intr & 1)){
handle_ep_in(i);
}
}
intr >>= 1;
for(i=1;i<16;++i){
intr >>= 1;
if(unlikely(intr & 1)){
handle_ep_out(i);
}
}

3. 完全展开循环(未显示)。这会使代码有点困惑。

4.还有其他更好的方法吗?

5.还是说编译器实际上会生成最优化的方式?


编辑:我一直在寻找一种方法来告诉 gcc 编译器展开该特定循环,但根据我的搜索,这似乎是不可能的...

最佳答案

如果我们可以假设 intr 中设置位的数量很少(中断掩码通常是这种情况),我们可以优化一点并编写一个只对每个位执行一次的循环:

void handle (int intr)
{
while (intr)
{
// find index of lowest bit set in intr:
int bit_id = __builtin_ffs(intr)-1;

// call handler:
if (bit_id > 16)
handle_ep_out (bit_id-16);
else
handle_ep_in (bit_id);

// clear that bit
// (I think there was a bit-hack out there to simplify this step even further)
intr -= (1<<bit_id);
}
}

在大多数 ARM 架构上,__builtin_ffs 将编译为 CLZ 指令和围绕它的一些算术。除了 ARM7 和更旧的内核之外,它应该这样做。

此外:在嵌入式设备上编写中断处理程序时,函数的大小也会对性能产生影响,因为必须将指令加载到代码缓存中。精益代码通常执行得更快。如果您保存对不太可能在缓存中的内存的内存访问,那么一点开销是可以接受的。

关于c - 循环展开(按位运算),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12401362/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com