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