如何调用在 LLVM 3.2 中返回 2 个值的内联 ASM



在C++中,我们可以让内联 asm 返回 2 个值,例如:

ulonglong2 ThreadLoad<cub_modifier, ulonglong2*>(ulonglong2* ptr)
{
    ulonglong2 retval;
    asm volatile ("ld."#ptx_modifier".v2.u64 {%0, %1}, [%2];"
        "=l"(retval.x),
        "=l"(retval.y) :
        _CUB_ASM_PTR_(ptr));
    return retval;
}

我们如何为这种用法创建 LLVM IR?我试过:

%3 = alloca { i32, i32 }, align 8
%40 = getelementptr inbounds { i32, i32 }* %38, i64 %39
%41 = getelementptr inbounds { i32, i32 }* %3, i32 0, i32 0
%42 = getelementptr inbounds { i32, i32 }* %3, i32 0, i32 1
call void asm sideeffect alignstack "ld.cg.v2.u32 9{$0, $1}, [$2];", "=l,=l,l"(i32* %41, i32* %42, { i32, i32 }* %40)
%43 = load { i32, i32 }* %3, align 8

这是行不通的。

我为你的问题做了一个玩具例子:

struct ulonglong2
{
        unsigned long long x;
        unsigned long long y;
};
ulonglong2 ThreadLoad(ulonglong2* ptr)
{
    ulonglong2 retval;
    asm volatile ("ld.cg.v2.u64 {%0, %1}, [%2];" : "=l"(retval.x), "=l"(retval.y) : "l" (ptr));
    return retval;
}
int main() {
    ulonglong2 val;
    ulonglong2 x = ThreadLoad(&val);
    return 0;
}

并让 clang 发出 LLVM IR(命令:clang -emit-llvm test.cpp -c -S -o ptx.ll):

; Function Attrs: nounwind uwtable
define { i64, i64 } @_Z10ThreadLoadP10ulonglong2(%struct.ulonglong2* %ptr) #0 {
  %1 = alloca %struct.ulonglong2, align 8
  %2 = alloca %struct.ulonglong2*, align 8
  store %struct.ulonglong2* %ptr, %struct.ulonglong2** %2, align 8
  %3 = getelementptr inbounds %struct.ulonglong2* %1, i32 0, i32 0
  %4 = getelementptr inbounds %struct.ulonglong2* %1, i32 0, i32 1
  %5 = load %struct.ulonglong2** %2, align 8
  %6 = call { i64, i64 } asm sideeffect "ld.cg.v2.u64 $($0, $1$), [$2];", "=l,=l,l,~{dirflag},~{fpsr},~{flags}"(%struct.ulonglong2* %5) #1, !srcloc !1
  %7 = extractvalue { i64, i64 } %6, 0
  %8 = extractvalue { i64, i64 } %6, 1
  store i64 %7, i64* %3, align 8
  store i64 %8, i64* %4, align 8
  %9 = bitcast %struct.ulonglong2* %1 to { i64, i64 }*
  %10 = load { i64, i64 }* %9, align 1
  ret { i64, i64 } %10
}

该行:

  %6 = call { i64, i64 } asm sideeffect "ld.cg.v2.u64 $($0, $1$), [$2];", "=l,=l,l,~{dirflag},~{fpsr},~{flags}"(%struct.ulonglong2* %5) #1, !srcloc !1

您的 asm 调用需要{i64, i64}作为返回类型,并且只采用一个输入参数(因为您只在 asm 行中声明一个)。其他一切都在向前发展。获取存储两个ulonglong值的位置并存储它的指针。%9之后的所有内容都只是将值作为结构返回。如果将-O3传递给 clang,您将看到除 asm 调用之外的所有内容都消失了,指针直接转发到 asm 调用。

相关内容

  • 没有找到相关文章

最新更新