Compiler construction 向量LLVM的变更元素
我正在尝试使用LLVM IR代码更改向量的一个元素。以下代码:Compiler construction 向量LLVM的变更元素,compiler-construction,llvm,llvm-ir,Compiler Construction,Llvm,Llvm Ir,我正在尝试使用LLVM IR代码更改向量的一个元素。以下代码: extern printd(num); array a [1 2 3]; printd(a[1]); # 2.0 a[1] = 10; printd(a[1]); # 2.0 生成此IR代码: declare double @printd(double) define <4 x double> @a() { entry: %0 = insertelement <4 x double> unde
extern printd(num);
array a [1 2 3];
printd(a[1]); # 2.0
a[1] = 10;
printd(a[1]); # 2.0
生成此IR代码:
declare double @printd(double)
define <4 x double> @a() {
entry:
%0 = insertelement <4 x double> undef, double 1.000000e+00, i32 0
%1 = insertelement <4 x double> %0, double 2.000000e+00, i32 1
%2 = insertelement <4 x double> %1, double 3.000000e+00, i32 2
ret <4 x double> %2
}
define double @__anon_expr0() {
entry:
%calltmp = call <4 x double> @a()
%0 = extractelement <4 x double> %calltmp, i32 1
%calltmp1 = call double @printd(double %0)
ret double %calltmp1
}
define double @__anon_expr1() {
entry:
%calltmp = call <4 x double> @a()
%0 = insertelement <4 x double> %calltmp, double 1.000000e+00, i32 1
ret double 0.000000e+00
}
我试图做的是在向量中重新插入一个值-这不起作用。我怀疑这是两个问题之一:
%calltmp
中的一个元素,而不是实际的向量我很想知道我能做些什么来解决这个问题。您的第一个问题是您已经将
@a
定义为一个函数,特别是一个总是返回值的函数。因此,无论您在其他地方做什么,您都无法调用@a()
,并返回除该值以外的任何内容。因此,您要做的第一件事是将@a
转换为全局变量,以便可以更改其值
现在,您的下一个问题是,insertelement
不会更改给定的向量。它不能,因为向量存储在寄存器中,并且不能重新分配寄存器(LLVM使用静态单赋值形式)。因此,insertelement
会生成一个新的向量,并更改给定的索引。在代码中,您将该新向量存储在%0
中,然后对其不做任何处理。将@a
设置为全局变量后,可以将%0
的值存储在@a
中。这将解决你眼前的问题
然而,正如我们在评论中已经讨论的,向量并不是你所做的事情的合适选择,原因有几个:
insertelement
创建了一个新的向量,其中一个元素发生了更改。这意味着整个向量被复制。如果创建大型向量,那么成本可能会很高如果将
@a
设置为数组,则可以获取指向其第二个元素的指针,并将新值直接存储到其中。因此,不必创建一个全新的数组并用它替换@a
,只需更改一个要更改的元素即可。这就是您真正想要的。您的第一个问题是,您已经将@a
定义为一个函数,特别是一个始终返回值
的函数。因此,无论您在其他地方做什么,您都无法调用@a()
,并返回除该值以外的任何内容。因此,您要做的第一件事是将@a
转换为全局变量,以便可以更改其值
现在,您的下一个问题是,insertelement
不会更改给定的向量。它不能,因为向量存储在寄存器中,并且不能重新分配寄存器(LLVM使用静态单赋值形式)。因此,insertelement
会生成一个新的向量,并更改给定的索引。在代码中,您将该新向量存储在%0
中,然后对其不做任何处理。将@a
设置为全局变量后,可以将%0
的值存储在@a
中。这将解决你眼前的问题
然而,正如我们在评论中已经讨论的,向量并不是你所做的事情的合适选择,原因有几个:
insertelement
创建了一个新的向量,其中一个元素发生了更改。这意味着整个向量被复制。如果创建大型向量,那么成本可能会很高如果将
@a
设置为数组,则可以获取指向其第二个元素的指针,并将新值直接存储到其中。因此,不必创建一个全新的数组并用它替换@a
,只需更改一个要更改的元素即可。这才是您真正想要的。您确定要在此处使用向量吗?您的源程序显示“数组”<代码>插入元件不是就地操作;它会生成一个新的向量(由于您不触摸包含新向量的%0
),因此您永远不会使用该向量)。您永远不能更改现有寄存器的内容(这就是SSA的意思)。还有,为什么a
a函数?@sepp2k我想使用向量,因为我认为向量更具动态性(不是固定大小,等等)。我想最好的办法是创建一个变量,而不是一个返回向量的函数,并将其更改为%0
。谢谢你的帮助和洞察力。向量不是这样的。就像数组一样,向量的大小也是其类型的一部分,所以它们的大小是固定的。向量与数组的区别在于:它们只能包含数字,因为它们是元素类型。它们是一级值,这意味着它们可以存储在寄存器中,并作为参数传递给函数(无需通过指针)等。您可以对它们使用数值操作,如fadd
,然后在适用的情况下编译为SIMD指令(这是它们的主要用途)。你不能在它们上面使用getelementptr
,所以你不能得到指向它们元素的指针。所以在某种意义上,它们的大小甚至比数组更固定,因为使用数组,你至少可以得到指向它们内容的指针,然后将它传递给一个可以dea的函数
define double @__anon_expr1() {
entry:
%calltmp = call <4 x double> @a()
%0 = insertelement <4 x double> %calltmp, double 1.000000e+00, i32 1
ret double 0.000000e+00
}