LLVM JIT fabsf 在使用 powf 时解决错误

LLVM JIT fabsf resolve error when using powf

我正在试验 LLVM 的 JIT 功能,在调用 powf 时我观察到如果我简单地为它添加一个声明,调用 powf 就可以工作

declare float @powf(float, float))

并用两个变量调用它

%4 = call float @powf(float %3, float %2)

然而,当我用 0.5

的常数指数做同样的事情时
%4 = call float @powf(float %3, float 5.000000e-01)

失败并出现以下错误:

LLVM ERROR: Program used external function 'fabsf' which could not be resolved!

powf 调用被以下优化过程替换,所以我知道 fabsf 来自哪里:

%sqrtf = tail call float @sqrtf(float %3) #1
%fabsf = tail call float @fabsf(float %sqrtf) #1
%4 = fcmp oeq float %3, 0xFFF0000000000000
%5 = select i1 %4, float 0x7FF0000000000000, float %fabsf

我尝试在外部注册 fabsf(但显然不正确),但这没有用:

auto float_type = llvm::Type::getFloatTy(context);
std::vector<llvm::Type *> unary_arg_types(1, float_type);
auto unary_op_type = llvm::FunctionType::get(float_type, unary_arg_types, false);
auto fabsf_llvm = llvm::Function::Create(unary_op_type, llvm::Function::ExternalLinkage, "fabsf", module);
ee->addGlobalMapping(fabsf_llvm, reinterpret_cast<void *>(&::fabsf));

我在 Windows 7 上使用 MCJIT ExecutionEngine 和 运行 以及 LLVM 和我用 MinGW 编译的测试程序。

问题一:如何注册fabsf才不会出现这个错误?

问题2:为什么这里需要fabsf

编辑: 看来我偶然发现了一个(已知的)MCJIT 错误:http://llvm.org/bugs/show_bug.cgi?id=20656

是的,这是 MCJIT 中的一个已知错误。

我在 LLVMDev 邮件列表上偶然发现了一个解决方案。 您可以使用位于 llvm/Support/DynamicLibrary.h header 中的 llvm::sys::DynamicLibrary::AddSymbol() 来注册您丢失的符号。这是您问题 1 的答案。

对于问题2:(免责声明:我不是浮点专家,不知道我在这里写的内容是否属实)

由于 powf 被转换为 sqrtfsqrtf 的结果未定义时,您将得到一个 QNaN(安静的 NaN),因为提供了否定参数。在 ISO 754 中,QNaN 表示为 0xFFF00000000000000x7FF0000000000000(符号与 ISO 754 中的 QNaN 无关)。

在 C++ 中,pow 的定义如下:

pow(base, exp) returns NaN and raises FE_INVALID if base is finite and negative and exp is finite and non-integer.

...

pow(±0, exp), where exp is positive non-integer or a positive even integer, returns +0

请注意,它每次都会 return 正值 0

但是 sqrt

If the argument is +∞ or ±0, it is returned, unmodified.

最后回答您的问题:在您的情况下,fabsf 有必要摆脱 sqrt 保留而 pow 将其丢弃的标志。