如何在 LLVM 3.2 中调用 inline asm which returns 2 values
how to call inline asm which returns 2 values in LLVM 3.2
在 C++ 中,我们可以让内联汇编成为 return 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 {[=12=], }, [];", "=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 $([=11=], $), [];", "=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 $([=12=], $), [];", "=l,=l,l,~{dirflag},~{fpsr},~{flags}"(%struct.ulonglong2* %5) #1, !srcloc !1
你的 asm 调用需要 {i64, i64}
作为 return 类型并且只需要一个输入参数(因为你只在你的 asm 行中声明一个)。其他一切都向前推进。获取存储两个 ulonglong
值的指针并将其存储。 %9
之后的所有内容都只是 return 作为结构的值。如果将 -O3
传递给 clang,您会看到除了 asm 调用之外的所有内容都消失了,指针直接转发到 asm 调用。
在 C++ 中,我们可以让内联汇编成为 return 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 {[=12=], }, [];", "=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 $([=11=], $), [];", "=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 $([=12=], $), [];", "=l,=l,l,~{dirflag},~{fpsr},~{flags}"(%struct.ulonglong2* %5) #1, !srcloc !1
你的 asm 调用需要 {i64, i64}
作为 return 类型并且只需要一个输入参数(因为你只在你的 asm 行中声明一个)。其他一切都向前推进。获取存储两个 ulonglong
值的指针并将其存储。 %9
之后的所有内容都只是 return 作为结构的值。如果将 -O3
传递给 clang,您会看到除了 asm 调用之外的所有内容都消失了,指针直接转发到 asm 调用。