LLVM GEP和存储与加载和插入值:将值存储到指向聚合的指针

时间:2016-02-05 22:56:27

标签: indexing llvm llvm-ir

将值存储到指向聚合类型的指针时,getelementptrstoreloadinsertvalue之间有什么区别?在某些情况下是首选吗?如果是这样,为什么?或者我完全朝着错误的方向前进?

实施例

; A contrived example
%X = type {i32, i64}

define i32 @main(i32 %argc, i8** %argv) {
entry:
  %sX.0 = alloca %X

  ; change the first value with GEP + store
  %val1 = getelementptr %X, %X* %sX.0, i32 0, i32 0
  store i32 42, i32* %val1

  ; change the second value with load + insertvalue
  %sX.1 = load %X, %X* %sX.0
  %sX.2 = insertvalue %X %sX.1, i64 42, 1
  store %X %sX.2, %X* %sX.0 ; I suppose this could be considered less than ideal
                            ; however in some cases it is nice to have the
                            ; struct `load`ed
  ret i32 0
}

有趣的是,使用llc -O=0 ...他们都编译成相同的指令。相当于以下内容,这是我所希望的。

movl $42, -16(%rsp) # GEP + store
movq $42, -8(%rsp)  # load + insertvalue

背景:

我正在阅读LLVM Language Reference,而我正在阅读insertvalue。该参考文献记录了extractvalue指令与GEP的相似性以及以下差异。

  

与getelementptr索引的主要区别是:

     
      
  • 由于被索引的值不是指针,因此省略第一个索引并假设为零。

  •   
  • 必须至少指定一个索引。

  •   
  • 不仅结构索引而且数组索引必须在边界内。

  •   

关于StackOverflow的以下问题也提到getelementptrinsertvalue的使用,但出于不同的原因。 LLVM insertvalue bad optimized?

1 个答案:

答案 0 :(得分:3)

从语义上讲,load以及store整个对象更加浪费。如果它是一个巨大的结构怎么办?如果它是一系列结构怎么办? GEP允许您访问要加载/存储的内存中的确切位置,而无需加载/存储任何其他内容。

虽然在您的示例中将两个表单降低到相同的说明,但通常不会保证。