加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C / LLVM:运行时代码生成和STL容器

发布时间:2020-12-16 05:06:17 所属栏目:百科 来源:网络整理
导读:假设一个简单的部分评估场景: #include vector/* may be known at runtime */int someConstant();/* can be partially evaluated */double foo(std::vectordouble args) { return args[someConstant()] * someConstant();} 假设someConstant()是已知的并且
假设一个简单的部分评估场景:
#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(即使我不知道如何做)是一秒钟 – 最好的解决方案

解决方法

回答我自己的问题:

虽然我仍然没有针对一般情况的解决方案(例如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的对象级布局是由标准修复的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读