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

cho*_*ger 5 c++ jit stl llvm

假设一个简单的部分评估场景:

#include <vector>

/* may be known at runtime */
int someConstant();

/* can be partially evaluated */
double foo(std::vector<double> args) {
  return args[someConstant()] * someConstant();
}
Run Code Online (Sandbox Code Playgroud)

假设它someConstant()是已知的并且在运行时不会改变(例如,由用户给出一次)并且可以由相应的int文字替换.如果foo是热门路径的一部分,我预计会有显着的性能提升:

/* partially evaluated, someConstant() == 2 */
double foo(std::vector<double> args) {
  return args[2] * 2;
}
Run Code Online (Sandbox Code Playgroud)

我目前对该问题的看法是在运行时生成LLVM IR,因为我知道部分评估代码的结构(所以我不需要通用的部分求值程序).所以我想编写一个foo_ir生成IR代码的函数,它执行相同的操作foo但不调用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, i32 0
  %7 = load double** %6, align 8
  %8 = load i64* %2, align 8
  %9 = getelementptr inbounds double* %7, i64 %8
  ret double* %9
}
Run Code Online (Sandbox Code Playgroud)

我知道,这[]是从STL定义(功能@_ZNSt6vectorIdSaIdEEixEm)中包含的 - 足够公平.问题是:它可能是一些成员函数,甚至是直接数据访问,我根本无法假设数据布局到处都是一样的,所以在开发时,我不知道std::vector主机的具体布局.

有没有办法使用C++元编程在编译时获取所需的信息?即是有某种方式来问LLVM提供IR std::vector[]方法是什么?

作为奖励:我宁愿不强制铿锵库的编译,相反,LLVM应是运行时的依赖性,所以才调用铛在编译时(即使我不知道如何做到这一点)是第二 - 最好的解决方案

cho*_*ger 3

回答我自己的问题:

虽然我仍然没有针对一般情况的解决方案(例如std::map),但存在一个简单的解决方案std::vector

根据C++ 标准,以下内容适用于成员函数data()

返回指向向量内部使用的内存数组的直接指针,用于存储其拥有的元素。

由于向量中的元素保证以与向量表示的顺序相同的顺序存储在连续的存储位置中,因此可以对检索到的指针进行偏移以访问数组中的任何元素。

所以实际上,对象级别的布局std::vector是由标准固定的。