首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于OpenCL本地阵列访问的LLVM-IR GEP

用于OpenCL本地阵列访问的LLVM-IR GEP
EN

Stack Overflow用户
提问于 2014-01-09 00:32:35
回答 1查看 800关注 0票数 0

我通过llvm在我的OpenCL内核中创建了一个本地数组,称为大小为256 x i32的可查找数组。稍后,我通过llvm插入代码,用值填充数组。我的问题是,当我试图生成访问数组的代码时,我似乎无法正确地隔离指向我想要的元素的指针。如果使用名为平坦的模糊局部变量,则可能会错误地对元素进行索引:

代码语言:javascript
复制
Value *xs_ys_mul   = builder.CreateMul(shifted_x_size, y_size, "xs_ys_mul");
Value *xs_ys_z_mul = builder.CreateMul(xs_ys_mul, z, "xs_ys_z_mul");
Value *xs_y_mul    = builder.CreateMul(shifted_x_size, y, "xs_y_mul");
Value *sum_1       = builder.CreateAdd(xs_ys_z_mul, xs_y_mul, "sum_1");
Value *flattened   = builder.CreateAdd(sum_1, shifted_x, "FLATTENED");

这将是维度上扁平的本地工作组id。不过,这是无关紧要的。

GEP就是这样创建的(构建器是IRBuilder的一个实例):

代码语言:javascript
复制
std::vector<llvm::Value *> tmp_args;
tmp_args.push_back(builder.getInt32(0));
tmp_args.push_back(flattened);
Value *table_addr = builder.CreateGEP(M.getNamedGlobal(tablename), tmp_args, tablename+"_IDX");

在本例中,M是Module对象。产生的table_addr是:

代码语言:javascript
复制
%i32_cllocal_TABLE_IDX = getelementptr [256 x i32] addrspace(3)* @i32_cllocal_TABLE, i32 0, i32 %FLATTENED

但是,如果我想用for循环我的代码遍历LLVM中的索引来正确地填充它(省略循环结构,其中"index“是i32循环计数器):

代码语言:javascript
复制
std::vector<llvm::Value *> tmp_args;
tmp_args.push_back(builder.getInt32(0));
tmp_args.push_back(builder.getInt32(index));
Value *table_addr = builder.CreateGEP(M.getNamedGlobal(tablename), tmp_args, tablename+"_IDX");

在这种情况下,table_addr的转储()是(当index==0):

代码语言:javascript
复制
i32 addrspace(3)* getelementptr inbounds ([256 x i32] addrspace(3)* @i32_cllocal_CRC32_TABLE, i32 0, i32 0)

这意味着当我去商店的时候:

代码语言:javascript
复制
store_inst = builder.CreateStore(builder.getInt32(tablevalues[index]), table_addr);

我得到了这个输出:

代码语言:javascript
复制
store volatile i32 0, i32 addrspace(3)* getelementptr inbounds ([256 x i32] addrspace(3)* @i32_cllocal_TABLE, i32 0, i32 0), align 4

这看起来不太正确,但更重要的是,当"index“>0时,我得到了一个断言的SIGABRT:

代码语言:javascript
复制
Casting.h:194: typename llvm::cast_retty<To, From>::ret_type llvm::cast(const Y&) [with X = llvm::CompositeType, Y = llvm::Type*]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.

我有点卡住了。我不明白给数组索引的显式值与在运行时计算的一些模糊值之间的区别。任何见解都将不胜感激。

更新:我最后做的是这个(alloc只做了一次,我只是为了视觉目的将它包含在这个代码块中,它实际上在for循环之外):

代码语言:javascript
复制
std::vector<llvm::Value *> tmp_args;
tmp_args.push_back(builder.getInt32(0));
idxInst = builder.CreateAlloca(builder.getInt32Ty(), 0, "idxvalue");
//----- Inside the loop below --------------------------------------
idxStore = builder.CreateStore(builder.getInt32(index), idxInst);
indexValue = builder.CreateLoad(idxInst, "INDEX_VAL");
tmp_args.push_back(indexValue);
table_addr = builder.CreateGEP(table_ptr, tmp_args, "_IDX_PUT");
tmp_args.pop_back();
store_inst = builder.CreateStore(builder.getInt32(tableValues[index]), table_addr, "_ELEM_STORE");
store_inst->setAlignment(4);

发出此代码(用于索引== 0和1):

代码语言:javascript
复制
%idxvalue = alloca i32
store i32 0, i32* %idxvalue
%INDEX_VAL = load i32* %idxvalue
%i32_cllocal_TABLE_IDX_PUT = getelementptr [256 x i32] addrspace(3)*  @i32_cllocal_TABLE, i32 0, i32 %INDEX_VAL
store volatile i32 0, i32 addrspace(3)* %i32_cllocal_TABLE_IDX_PUT, align 4
store i32 1, i32* %idxvalue
%INDEX_VAL1 = load i32* %idxvalue
%i32_cllocal_TABLE_IDX_PUT2 = getelementptr [256 x i32] addrspace(3)* @i32_cllocal_TABLE, i32 0, i32 %INDEX_VAL1
store volatile i32 1996959894, i32 addrspace(3)* %i32_cllocal_TABLE_IDX_PUT2, align 4

现在它看起来是正确的,但在我看来,这似乎是一种奇怪的emi代码方式,因为我正在存储,然后立即加载,但是我想这将得到优化,或者我将尝试使用那个mem2reg。谢谢你的帮助@Oak。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-09 06:23:25

这个片段有问题:

代码语言:javascript
复制
std::vector<llvm::Value *> tmp_args;
tmp_args.push_back(builder.getInt32(0));
tmp_args.push_back(builder.getInt32(index));
Value *table_addr = builder.CreateGEP(M.getNamedGlobal(tablename), tmp_args, tablename+"_IDX");

IRBuilder::getInt32创建一个常量int。因此,GEP将始终访问数组中的第一个项,这不是您想要的。这也是为什么IR显示的是恒定表达GEP而不是真正的GEP指令。您需要的是创建一个Value并使用它作为第二个索引--就像在第一个示例中所做的那样。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21009523

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档