The def-use information can be extracted directly by Use . It is useful to identify the original allocated object, which helps to update the states in typestate problems, such as the file property simulation. The source code refer to tutorialpass/pass/FileSimulatorPass

Example

int main() {
	int a;
	int b=10;
	int c=10;
	a=b+c;
  return 0;
}

In LLVM IR compiled with -g

define dso_local i32 @main() #0 !dbg !7 {
entry:
  %retval = alloca i32, align 4
  %a = alloca i32, align 4
  %b = alloca i32, align 4
  %c = alloca i32, align 4
  store i32 0, i32* %retval, align 4
  call void @llvm.dbg.declare(metadata i32* %a, metadata !11, metadata !DIExpression()), !dbg !12
  call void @llvm.dbg.declare(metadata i32* %b, metadata !13, metadata !DIExpression()), !dbg !14
  store i32 10, i32* %b, align 4, !dbg !14
  call void @llvm.dbg.declare(metadata i32* %c, metadata !15, metadata !DIExpression()), !dbg !16
  store i32 10, i32* %c, align 4, !dbg !16
  %0 = load i32, i32* %b, align 4, !dbg !17
  %1 = load i32, i32* %c, align 4, !dbg !18
  %add = add nsw i32 %0, %1, !dbg !19
  store i32 %add, i32* %a, align 4, !dbg !20
  ret i32 0, !dbg !21
}

Def-use chain

bool runOnFunction(Function &F){
    errs() << "digraph " + F.getName() + "{\n";
    errs() << "\n";
    for (auto block = F.getBasicBlockList().begin(); block != F.getBasicBlockList().end(); block++) {
        for (auto inst = block->begin(); inst != block->end(); inst++) {
            for (Use &U:inst->operands()) {
                Value *v = U.get();
                if (dyn_cast<Instruction>(v)) {
                    errs() << "\"" << *dyn_cast<Instruction>(v) << "\"" << " -> " << "\"" << *inst << "\"" << ";\n";
                }
            }
        }
    }
    errs() << "\n}\n";
}

The result is

"  %retval = alloca i32, align 4" -> "  store i32 0, i32* %retval, align 4"
"  %b = alloca i32, align 4" -> "  store i32 10, i32* %b, align 4, !dbg !14"
"  %c = alloca i32, align 4" -> "  store i32 10, i32* %c, align 4, !dbg !16"
"  %b = alloca i32, align 4" -> "  %0 = load i32, i32* %b, align 4, !dbg !17"
"  %c = alloca i32, align 4" -> "  %1 = load i32, i32* %c, align 4, !dbg !18"
"  %0 = load i32, i32* %b, align 4, !dbg !17" -> "  %add = add nsw i32 %0, %1, !dbg !19"
"  %1 = load i32, i32* %c, align 4, !dbg !18" -> "  %add = add nsw i32 %0, %1, !dbg !19"
"  %add = add nsw i32 %0, %1, !dbg !19" -> "  store i32 %add, i32* %a, align 4, !dbg !20"
"  %a = alloca i32, align 4" -> "  store i32 %add, i32* %a, align 4, !dbg !20"

For example, if we concerns about the data dependance of a at the statement a=b+c, we can track the def-use chain backward:

store i32 %add, i32* %a, align 4, !dbg !20
->
%add = add nsw i32 %0, %1, !dbg !19
->
%0 = load i32, i32* %b, align 4, !dbg !17
  -> %b = alloca i32, align 4
%1 = load i32, i32* %c, align 4, !dbg !18
  -> %c = alloca i32, align 4

The backward tracking ends until alloca is reached. b and c are the data dependency of a

Related Paper

Reference