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