#include <vector> /* may be known at runtime */ int someConstant(); /* can be partially evaluated */ double foo(std::vector<double> args) { return args[someConstant()] * someConstant(); }
假设someConstant()是已知的并且在运行时不会改变(例如由用户给出一次)并且可以由相应的int literal替换.如果foo是热门路径的一部分,我预计会有显着的性能提升:
/* partially evaluated,someConstant() == 2 */ double foo(std::vector<double> args) { return args[2] * 2; }
我目前对该问题的看法是在运行时生成LLVM IR,因为我知道部分评估代码的结构(所以我不需要通用的部分求值程序).
所以我想编写一个函数foo_ir,它生成与foo完全相同的IR代码,但不调用someConstant(),因为它在运行时是已知的.
很简单,不是吗?然而,当我查看上面代码生成的IR时:
; Function Attrs: uwtable define double @_Z3fooSt6vectorIdSaIdEE(%"class.std::vector"* %args) #0 { %1 = call i32 @_Z12someConstantv() %2 = sext i32 %1 to i64 %3 = call double* @_ZNSt6vectorIdSaIdEEixEm(%"class.std::vector"* %args,i64 %2) %4 = load double* %3 %5 = call i32 @_Z12someConstantv() %6 = sitofp i32 %5 to double %7 = fmul double %4,%6 ret double %7 } ; Function Attrs: nounwind uwtable define linkonce_odr double* @_ZNSt6vectorIdSaIdEEixEm(%"class.std::vector"* %this,i64 %__n) #1 align 2 { %1 = alloca %"class.std::vector"*,align 8 %2 = alloca i64,align 8 store %"class.std::vector"* %this,%"class.std::vector"** %1,align 8 store i64 %__n,i64* %2,align 8 %3 = load %"class.std::vector"** %1 %4 = bitcast %"class.std::vector"* %3 to %"struct.std::_Vector_base"* %5 = getelementptr inbounds %"struct.std::_Vector_base"* %4,i32 0,i32 0 %6 = getelementptr inbounds %"struct.std::_Vector_base<double,std::allocator<double> >::_Vector_impl"* %5,i32 0 %7 = load double** %6,align 8 %8 = load i64* %2,align 8 %9 = getelementptr inbounds double* %7,i64 %8 ret double* %9 }
我看到,[]包含在STL定义中(函数@ _ZNSt6vectorIdSaIdEEixEm) – 足够公平.问题是:它可能是一些成员函数,甚至是直接数据访问,我根本无法假设数据布局到处都是一样的,所以在开发时,我不知道具体的std :: vector布局主机.
有没有办法使用C元编程在编译时获取所需的信息?即是否有一些方法可以让llvm为std :: vector的[]方法提供IR?
作为奖励:我宁愿不用clang强制编译库,相反,LLVM应该是一个运行时依赖,所以只是在编译时调用clang(即使我不知道如何做)是一秒钟 – 最好的解决方案
@H_404_20@解决方法
虽然我仍然没有针对一般情况的解决方案(例如std :: map),但是对于std :: vector存在一个简单的解决方案:
根据the C++ standard,以下适用于成员函数数据()
Returns a direct pointer to the memory array used internally by the
vector to store its owned elements.Because elements in the vector are guaranteed to be stored in
contiguous storage locations in the same order as represented by the
vector,the pointer retrieved can be offset to access any element in
the array.
所以实际上,std :: vector的对象级布局是由标准修复的.
@H_404_20@ @H_404_20@