话说编译时可确定的virtual函数可以被优化么。。
c++吧
全部回复
仅看楼主
level 12
我变成鱼了
楼主
比如这样的:
ObjectInterface* a = new Object();
a->do_something();
一般的编译器优化能否把do_something在编译时确定?
@怪兽大战魔人
@豌豆夹吧
2014年05月29日 01点05分
1
level 14
怪兽大战魔人
这个真不是太清楚
既然是虚函数,应该会丢到运行时来确定吧
虽然具体的例子可能在编译期就能够确定,但我想了下要做到这点有点麻烦,而且也没啥特别的好处,另外也有可能有某些我还没想清楚的风险导致都被丢到运行时了…………
另外,你指的优化是啥?内联?
2014年05月29日 01点05分
2
level 12
我变成鱼了
楼主
@怪兽大战魔人
比如某个stream是这样实现:
struct stream_interface {
virtual char getch() = 0;
};
struct mystream: public stream_interface {
virtual char getch() { ...blabla... };
};
使用的时候:
stream_interface* s = new mystream();
while (bla) {
blabla = s->getch(); // 这里要是还按普通的运行时vtable查地址的话不是慢死了么。。
}
2014年05月29日 01点05分
3
一只大水鱼
编译时应该都是确定的函数地址
2014年05月29日 01点05分
一只大水鱼
stream_interface *s = new mystream(); 时,编译器已经计算出基类地址偏移,后面的getch()是确定的。
2014年05月29日 01点05分
怪兽大战魔人
这个没办法啊,虽然某种意义上确实有优化的可能,但是做起来很麻烦,还要考虑Linkage之类的。反之即使不优化,也就是偏移+load吧……这个只要cache不miss的话也不会慢太多。总之我似乎没见过这样的优化
2014年05月29日 02点05分
我变成鱼了
回复 怪兽大战魔人 :看楼下?试了下确实是编译时确定+inline了
2014年05月29日 02点05分
level 15
幻の上帝
理论上允许优化成非多态调用,至少C++的语义显然没有禁止。
比如a->do_something();中*a在运行时的动态类型如果能被确定,这个调用就可能被优化成a->A::do_something();这个非多态调用。
但是C++也没有指定虚函数多态调用能在编译时求值的特性(比如virtual和constexpr矛盾),因此实现需要自己分析。
这里如果a没有linkage,优化起来会相对容易,整个过程内推断一遍就行。但是只要有linkage,推断*a的动态类型就得靠过程间优化;如果具有external linkage可能得LTO。相当麻烦。
实际实现有多少我没调查过,不过估计指望不上。麻烦是一个原因;另外就算没优化,这种开销一般也不是很大。
2014年05月29日 01点05分
5
我变成鱼了
像上面的例子,要是不能编译时确定+inline的话就慢死了。。
2014年05月29日 01点05分
幻の上帝
回复 RichSelian :也不会慢到哪去,cache干什么吃的。
2014年05月29日 01点05分
level 15
幻の上帝
当然这种优化结合inline以后效果可能是会比较明显。
不过会while里面一个劲调用虚函数然后感觉到瓶颈的C艹用户就没多少……如果会在这里出问题基本上就是用抽了。
最后,要增加优化机会,加final。
2014年05月29日 01点05分
6
level 12
我变成鱼了
楼主
简单验证了下:
struct I {
virtual unsigned X() = 0;
};
struct A: public I {
virtual unsigned X() {
return 12345678;
}
};
int main() {
A a;
I* ia = &a;
return ia->X();
}
用gcc -O -S:
main:
.LFB1:
>>>>.cfi_startproc
>>>>movl>>>>$12345678, %eax
>>>>ret
>>>>.cfi_endproc
2014年05月29日 02点05分
7
怪兽大战魔人
ver?
2014年05月29日 02点05分
怪兽大战魔人
手头的4.3没这么干……我总是用老版本……
2014年05月29日 02点05分
我变成鱼了
回复 怪兽大战魔人 : gcc-4.9.0/clang-3.4.1都可以-O1优化过,gcc-3.4.5 -O3无力。
2014年05月29日 02点05分
幻の上帝
回复 RichSelian :
度娘奇葩,什么年头还用gcc3作死。
2014年05月29日 02点05分
level 11
四元飒
可以被优化,但是不知道有什么编译器这么做了。。
2014年05月29日 02点05分
8
level 14
怪兽大战魔人
这个问题细想还是有点意思
如果是同一个unit下的,理论上确实可以优化
不过因为涉及到函数外的数据段,通常局限于过程的优化是不会干这种事的……撑死是优化到最简的偏移+load出来,然后call
没试过ICC,不知道做了很多过程间优化的ICC会怎么样,总觉得也玄的样子
2014年05月29日 02点05分
9
我变成鱼了
拆开之后gcc -O -flto和clang -O2 -flto还是可以优化的。
2014年05月29日 02点05分
怪兽大战魔人
回复 RichSelian :嗯,搜索了下,我发现我的认知落后了……
2014年05月29日 02点05分
level 11
waegaegr
2014年05月29日 02点05分
10
level 15
幻の上帝
看来g++的-O2启用的-fdevirtualize和-fdevirtualize-speculatively就会干这个。Clang++也没理由没有。
搜了下发现理论早就有了。
还找到两年前ICPC开IPO的bug,把不该内联的内联了……
2014年05月29日 02点05分
11
幻の上帝
https://gcc.gnu.org/ml/gcc-patches/2013-09/msg00007.html
原来才实现不久么……
2014年05月29日 02点05分
我变成鱼了
这种长长的单词是怎么找到的。。
2014年05月29日 02点05分
幻の上帝
回复 RichSelian :就是拿GCC manual的关于优化的部分顺序遍历瞟一遍……
2014年05月29日 02点05分
level 15
幻の上帝
http://stackoverflow.com/questions/7046739/lto-devirtualization-and-virtual-tables
还有dt到不老实用C艹直接艹C的……
2014年05月29日 02点05分
12
我变成鱼了
有种把所有函数都virtual掉的冲动。。
2014年05月29日 02点05分
幻の上帝
回复 RichSelian :疼牛病得治……
2014年05月29日 02点05分
幻の上帝
回复 RichSelian :好吧,其实Java已经就算了。还不如直接拿动态语言艹(defun ...)。
2014年05月29日 02点05分
我变成鱼了
回复 幻の上帝 :主要是没virtual的话gmock艹得疼。。
2014年05月29日 02点05分
level 14
萧の十三郎
virtual在确定绑定的时候可以inline吧 两个关键字不冲突
2014年05月29日 02点05分
13
我变成鱼了
能确定的话inline就顺理成章了。
2014年05月29日 03点05分
level 12
飞翔的天地
-lto什么的都是坑
modulize才是王道
PS:话说final什么的可以标一标么
2014年05月29日 03点05分
14
幻の上帝
只允许一级TU的都是坑。modulize了兼容性也是坑。
2014年05月29日 03点05分
我变成鱼了
标了final怎么做gmock?
2014年05月29日 04点05分
level 12
飞翔的天地
https://tieba.baidu.com/p/2207978953
↑
2014年05月29日 06点05分
15
level 12
贴吧用户_0JNJWtE684
虚个蛋,mcf 一大堆 serializer 都是不虚的,只是包装了个虚的接口类,同时仍然提供非虚的接口。
2014年05月29日 12点05分
17
level 6
钓鱼与不可🍗
我觉得不能,虚函数是一个动态概念,对a的解释只能是以ObjectInterface,真正调用运行的时候需要查询指向对象的虚表,然后才能得到函数入口地址。
2014年05月29日 12点05分
18
1