前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MDK C++中对内联的极度优化

MDK C++中对内联的极度优化

作者头像
大石头
发布2018-01-09 17:44:13
9630
发布2018-01-09 17:44:13
举报
文章被收录于专栏:智能大石头

先来看看我们SmartIRQ的具体实现

代码语言:javascript
复制
// 智能IRQ,初始化时备份,销毁时还原
class SmartIRQ
{
public:
    force_inline SmartIRQ(bool enable = false)
    {
        _state = __get_PRIMASK();
        if(enable)
            __enable_irq();
        else
            __disable_irq();
    }

    force_inline ~SmartIRQ()
    {
        __set_PRIMASK(_state);
    }
    
private:
    uint _state;
};

在构造的时候备份,然后根据参数决定打开还是关闭中断。 在系统内核时钟里面,关键操作需要关闭中断,最后打开,以免其它中断影响关键操作的原子事务性。 于是我们有:

代码语言:javascript
复制
ulong Time::CurrentTicks()
{
    SmartIRQ irq;

    uint value = (SysTick->LOAD - SysTick->VAL);
    if(SysTick->CTRL & SysTick_CTRL_COUNTFLAG)
    {
        Ticks += SysTick->LOAD;
    }

    return Ticks + value;
}

其中irq在离开作用域时被释放,自动调用SmartIRQ的析构函数,还原了中断状态 因为调用极其频繁,最高可能1us调用一次该函数,于是我们给SmartIRQ的构造和析构都加了force_inline强制使用内联。 总所周知,C++的内联其实就是以空间换时间,把一个函数的代码全部搬出来直接使用,省去了调用、压栈、弹栈、返回等操作。 SmartIRQ的析构函数就罢了,但是构造函数代码量还是有好几行的。 怀着试一试的心态调试该函数,直接观察汇编代码:

代码语言:javascript
复制
0x08000804 B570      PUSH     {r4-r6,lr}
0x08000806 F3EF8210  MRS      r2,PRIMASK
0x0800080A B672      CPSID    I
0x0800080C 4D0B      LDR      r5,[pc,#44]  ; @0x0800083C
0x0800080E 6969      LDR      r1,[r5,#0x14]
0x08000810 69AB      LDR      r3,[r5,#0x18]
0x08000812 1ACC      SUBS     r4,r1,r3
0x08000814 6929      LDR      r1,[r5,#0x10]
0x08000816 2300      MOVS     r3,#0x00
0x08000818 03C9      LSLS     r1,r1,#15
0x0800081A 2900      CMP      r1,#0x00
0x0800081C DA06      BGE      0x0800082C
0x0800081E 6886      LDR      r6,[r0,#0x08]
0x08000820 68C1      LDR      r1,[r0,#0x0C]
0x08000822 696D      LDR      r5,[r5,#0x14]
0x08000824 1975      ADDS     r5,r6,r5
0x08000826 4159      ADCS     r1,r1,r3
0x08000828 6085      STR      r5,[r0,#0x08]
0x0800082A 60C1      STR      r1,[r0,#0x0C]
0x0800082C 6885      LDR      r5,[r0,#0x08]
0x0800082E 68C1      LDR      r1,[r0,#0x0C]
0x08000830 1928      ADDS     r0,r5,r4
0x08000832 4159      ADCS     r1,r1,r3
0x08000834 F3828810  MSR      PRIMASK,r2
0x08000838 BD70      POP      {r4-r6,pc}

MDK C++编译器优化到了极度变态的地步! 不仅仅内联了,SmartIRQ里面有两个分支语句,直接被他省略了其中一个,因为参数true已经确定。 更加变态的是,本来采用SmartIRQ内部私有成员_state保存状态,析构时恢复的,它直接把这个状态保存到寄存器r2里面去,连_state的内存都给省了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-09-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档