开发者社区> 长征6号> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

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

简介:
+关注继续查看

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

复制代码
// 智能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;
};
复制代码

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

于是我们有:

复制代码
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的析构函数就罢了,但是构造函数代码量还是有好几行的。
怀着试一试的心态调试该函数,直接观察汇编代码:

复制代码
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的内存都给省了。

 

我不相信神话,我只相信汗水!我不相信命运,我只相信双手!
分类: C++

本文转自大石头博客园博客,原文链接:http://www.cnblogs.com/nnhy/p/mdk_cpp_inline.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
运筹优化学习09:一个示例带你入门如何使用C++、C#、Java、Python、Matlab调用Cplex(下)
运筹优化学习09:一个示例带你入门如何使用C++、C#、Java、Python、Matlab调用Cplex
0 0
运筹优化学习09:一个示例带你入门如何使用C++、C#、Java、Python、Matlab调用Cplex(上)
运筹优化学习09:一个示例带你入门如何使用C++、C#、Java、Python、Matlab调用Cplex
0 0
二次规划问题用MindOpt C++怎么进行建模优化
MindOpt是达摩院决策智能实验室研究的一款优化求解器,目前在优化求解线性规划问题这一功能上取得不错的成绩,希望大家能够帮我们多多打磨其他功能(混合整数线性规划、二次规划、半定规划目前都在公测),让我们的MindOpt在优化求解器这板块成为国产之光。
0 0
【力扣·每日一题】689. 三个无重叠子数组的最大和 (C++ 前缀和优化dp 保存路径)
【力扣·每日一题】689. 三个无重叠子数组的最大和 (C++ 前缀和优化dp 保存路径)
0 0
非线性优化--NLopt算法使用及C++实例
非线性优化--NLopt算法使用及C++实例
0 0
冒泡排序极其优化(c/c++版本)
冒泡排序极其优化 算法步骤 1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。 2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。 3.针对所有的元素重复以上的步骤,除了最后一个。 4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
0 0
【C++ 语言】面向对象 ( 函数重载 | 运算符重载 | 运算符重载两种定义方式 | 拷贝构造方法 | RVO 优化 | NRVO 优化 )(二)
【C++ 语言】面向对象 ( 函数重载 | 运算符重载 | 运算符重载两种定义方式 | 拷贝构造方法 | RVO 优化 | NRVO 优化 )(二)
0 0
【C++ 语言】面向对象 ( 函数重载 | 运算符重载 | 运算符重载两种定义方式 | 拷贝构造方法 | RVO 优化 | NRVO 优化 )(一)
【C++ 语言】面向对象 ( 函数重载 | 运算符重载 | 运算符重载两种定义方式 | 拷贝构造方法 | RVO 优化 | NRVO 优化 )(一)
0 0
C++高并发场景下读多写少的优化方案
C++高并发场景下读多写少的优化方案 述 一谈到高并发的优化方案,往往能想到模块水平拆分、数据库读写分离、分库分表,加缓存、加mq等,这些都是从系统架构上解决。单模块作为系统的组成单元,其性能好坏也能很大的影响整体性能,本文从单模块下读多写少的场景出发,探讨其解决方案,以其更好的实现高并发。 不同的业务场景,读和写的频率各有侧重,有两种常见的业务场景: 读多写少:典型场景如广告检索端、白名单更新维护、loadbalancer 读少写多:典型场景如qps统计 本文针对读多写少(也称一写多读)场景下遇到的问题进行分析,并探讨一种合适的解决方案。
0 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
C++课程-对象模型
立即下载
使用C++开发PHP7扩展
立即下载
C++对象模型
立即下载