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

时间:2015-01-12 11:44:11

标签: assembly llvm

在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 \09{$0, $1}, [$2];", "=l,=l,l"(i32* %41, i32* %42, { i32, i32 }* %40)
%43 = load { i32, i32 }* %3, align 8

这不起作用。

1 个答案:

答案 0 :(得分:1)

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

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调用。