Performance LLVM中的参数转发

Performance LLVM中的参数转发,performance,function,llvm,argument-passing,callstack,Performance,Function,Llvm,Argument Passing,Callstack,我需要一些关于将参数“转发”给被调用方的建议(在LLVM-IR中) 假设我有一个函数F,它在模块中所有其他函数的开头被调用。从F我需要访问(读取)传递给其直接调用者的参数 现在要执行此操作,我将调用者中的所有参数都框在结构中,并将指向结构的指针传递到F,旁边还有一个标识符,告诉从哪个调用者调用FF有一个巨大的开关,它可以分支到相应的拆箱代码。必须这样做,因为模块中的函数具有不同的签名(不同的参数/返回值计数和类型;甚至不同的调用约定),但这显然是次优的(从性能和代码大小的角度来看),因为我需要在

我需要一些关于将参数“转发”给被调用方的建议(在LLVM-IR中)

假设我有一个函数
F
,它在模块中所有其他函数的开头被调用。从
F
我需要访问(读取)传递给其直接调用者的参数

现在要执行此操作,我将调用者中的所有参数都框在结构中,并将指向结构的指针传递到
F
,旁边还有一个标识符,告诉从哪个调用者调用
F
F
有一个巨大的开关,它可以分支到相应的拆箱代码。必须这样做,因为模块中的函数具有不同的签名(不同的参数/返回值计数和类型;甚至不同的调用约定),但这显然是次优的(从性能和代码大小的角度来看),因为我需要在堆栈上分配结构,复制其中的参数,将附加指针传递到
F
,然后执行取消装箱

我想知道是否有更好的方法来实现这一点,即从函数访问其直接调用方的堆栈帧的方法(由于标识符,知道调用该函数的调用方),或者更一般地说,从其直接调用方中定义的任意值。有什么建议吗

注意:我所做的全部工作都是使用一个函数
F
来完成所有这些;拆分/内联/专门化/模板化
F
不是一个选项


为了澄清,假设我们有以下函数
FuncA
FuncB
(注意:下面的只是伪C-code,请记住我们在谈论LLVM-IR!)

我需要的是函数
F
执行以下操作的有效方法:

void F() {
  switch (caller) {
    case FuncA:
      // do something with ArgA1
      break;
    case FuncB:
      // do something with ArgB1, ArgB2, ArgB3
      break;
  }
}
正如我在第一部分中所解释的,现在我的
F
如下所示:

struct Args_FuncA { Type2 ArgA1 };
struct Args_FuncB { Type4 ArgB1, Type5 ArgB2, Type6 ArgB3 };

void F(int callerID, void *args) {
  switch (callerID) {
    case ID_FuncA:
      Args_FuncA *ArgsFuncA = (Args_FuncA*)args;
      Type2 ArgA1 = ArgsFuncA->ArgA1;
      // do something with ArgA1
      break;
    case ID_FuncB:
      Args_FuncB *ArgsFuncB = (Args_FuncB*)args;
      Type4 ArgB1 = ArgsFuncB->ArgB1;
      Type5 ArgB2 = ArgsFuncB->ArgB2;
      Type6 ArgB3 = ArgsFuncB->ArgB3;
      // do something with ArgB1, ArgB2, ArgB3
      break;
  }
}
这两个功能变成:

Type1 FuncA(Type2 ArgA1) {
  Args_FuncA args = { ArgA1 };
  F(ID_FuncA, (void*)&args);
  // ...
}

Type3 FuncB(Type4 ArgB1, Type5 ArgB2, Type6 ArgB3) {
  Args_FuncB args = { ArgB1, ArgB2, ArgB3 };
  F(ID_FuncB, (void*)&args);
  // ...
}

我知道你做得对。虽然machinecode汇编中有解决方案,但我担心LLVM汇编中可能没有解决方案,因为它是“更高级别的”。如果您想在某些函数的开头运行函数,是否考虑过检查

  • 调试器源(如gdb)
  • 二进制仪器

我知道这不是直接的答案,但我希望它在某种程度上会有所帮助;)

不确定这是否有帮助,但我遇到了类似的问题,并通过使用LLVM向量存储中间值绕过了LLVM的tbaa分析的限制。LLVM优化过程后来能够优化到标量寄存器中的向量加载/存储


我记得有一些警告。如果您探索这条路线,请告诉我,我可以找到一些代码。

dtrace的操作与CAFxX所描述的完全相同。
Type1 FuncA(Type2 ArgA1) {
  Args_FuncA args = { ArgA1 };
  F(ID_FuncA, (void*)&args);
  // ...
}

Type3 FuncB(Type4 ArgB1, Type5 ArgB2, Type6 ArgB3) {
  Args_FuncB args = { ArgB1, ArgB2, ArgB3 };
  F(ID_FuncB, (void*)&args);
  // ...
}