numba / llvmlite

A lightweight LLVM python binding for writing JIT compilers
https://llvmlite.pydata.org/
BSD 2-Clause "Simplified" License
1.92k stars 316 forks source link

accessing operands of branch instruction #741

Open akcheung opened 3 years ago

akcheung commented 3 years ago
from llvmlite import binding as llvm

asm_sum = r"""
define i32 @foo(i32 %arg) #0 {
bb:
  %tmp = alloca i32, align 4
  %tmp1 = alloca i32, align 4
  store i32 %arg, i32* %tmp, align 4
  %tmp2 = load i32, i32* %tmp, align 4
  %tmp3 = icmp sgt i32 %tmp2, 10
  br i1 %tmp3, label %bb4, label %bb5

bb4:                                              ; preds = %bb
  store i32 1, i32* %tmp1, align 4
  br label %bb6

bb5:                                              ; preds = %bb
  store i32 2, i32* %tmp1, align 4
  br label %bb6

bb6:                                              ; preds = %bb5, %bb4
  %tmp7 = load i32, i32* %tmp1, align 4
  ret i32 %tmp7
}

"""

ref = llvm.parse_assembly(asm_sum, None)
fn = ref.get_function("foo")

for b in fn.blocks:
  for i in b.instructions:
    if i.opcode == "br":
      print("operands: %s" % [op.name for op in i.operands])

The code above prints operands: ['tmp3', 'bb5', 'bb4'] for the first branch instruction. Is that intentional? I was thinking that it should print operands: ['tmp3', 'bb4', 'bb5'] instead.

gmarkall commented 3 years ago

This is a bit weird, and it's because of the order operands are stored for a branch instruction in the underlying LLVM BranchInst class:

https://github.com/llvm/llvm-project/blob/aa6340cf87d7e1bbb894cf6357f859e5afb8a335/llvm/include/llvm/IR/Instructions.h#L3033

/// Ops list - Branches are strange.  The operands are ordered:
///  [Cond, FalseDest,] TrueDest.  This makes some accessors faster because
/// they don't have to check for cond/uncond branchness.