我正在尝试使用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> 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
}
那部分没关系,问题出在这里(__anon_expr1
):
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
中重新设置一个元素,而不是实际的矢量。我很想知道如何解决这个问题。
答案 0 :(得分:3)
您的第一个问题是您已将@a
定义为函数,特别是始终返回值<1.0, 2.0, 3.0>
的函数。所以无论你在别的地方做什么,你都永远不能打电话给@a()
并取回除了那个价值以外的任何东西。因此,您要做的第一件事就是将@a
转换为全局变量,这样您就可以更改其值。
现在您的下一个问题是insertelement
不会更改给定的向量。它不能,因为向量存储在寄存器中,您无法重新分配寄存器(LLVM使用静态单一赋值形式)。因此,insertelement
生成一个新的向量,其中给定的索引已更改。在您的代码中,您将新的向量存储在%0
中,然后对其执行任何操作。在您@a
成为全局变量之后,您可以将%0
的值存储在@a
中。这将解决您当前的问题。
但是,正如我们已经在评论中讨论的那样,由于以下几个原因,向量并不适合您正在做的事情:
insertelement
创建了一个更改了一个元素的新向量。这意味着整个矢量被复制。如果你创建大型向量,那可能会花费很多。如果使@a
成为数组,则可以获得指向其第二个元素的指针并将新值直接存储到其中。因此,您只需更改要更改的一个元素,而不是创建一个全新的数组并用它替换@a
。这就是你真正想要的。