Inserting instructions when encountered a specific label

Hello,
I’m trying to insert an instruction if a specific label name/string is encountered and would appreciate some guidance on where I should start. Basically when parsing going through this .ll file:

; Function Attrs: noinline nounwind optnone uwtable

define i32 @main(i32, i8**) #0 {

  %3 = alloca i32, align 4

  %4 = alloca i32, align 4

  %5 = alloca i8**, align 8

  %6 = alloca i32, align 4

  %7 = alloca i32, align 4

  store i32 0, i32* %3, align 4

  store i32 %0, i32* %4, align 4

  store i8** %1, i8*** %5, align 8

  store i32 2, i32* %6, align 4

  store i32 3, i32* %7, align 4

  %8 = load i32, i32* %6, align 4

  %9 = load i32, i32* %7, align 4

  %10 = icmp slt i32 %8, %9

  sbr i1 %10, label %true, label %false

true:

  %true1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i32 0, i32 0))

  br label %end

false:

  %false1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.1, i32 0, i32 0))

  br label %end

end:

  %end1 = load i32, i32* %3, align 4

  ret i32 %end1

}

I want to insert a new instruction when I encounter the true, false, and end labels (inside their respective blocks). I tried to detect the label names using " I.printAsOperand(errs(), false);” when parsing the instructions in SelectionDAGBuilder but it was only visiting instructions in the first/main BB and outputted %2. Which pass or phase would be the best to see if the current block’s label matches “true”, “false”, or “end” and insert an instruction inside that block?

Thank you,

Kaarthik A.

Hi Kaarthik,

I want to insert a new instruction when I encounter the true, false, and end labels (inside their respective blocks). I tried to detect the label names using " I.printAsOperand(errs(), false);”

This function prints an instruction as it would be referred to in
another instruction, so for example if the IR was

    %2 = alloca i32

then printAsOperand would print %2. It sounds like you want to
introspect the operands, so you'd probably check you're looking at a
BranchInst and check BI->getSuccessor(0)->getName() (& 1 if it's
conditional).

when parsing the instructions in SelectionDAGBuilder but it was only visiting instructions in the first/main BB and outputted %2.

I'm not sure what's going on there, it would depend on which function
you're modifying in SelectionDAG.

Which pass or phase would be the best to see if the current block’s label matches “true”, “false”, or “end” and insert an instruction inside that block?

To be honest, looking at block names is so hacky that it doesn't
really matter where you put it (for example release mode compilers
often don't add names at all, and generally it's perfectly valid as a
transformation to drop them entirely). It's probably easier if it's
before SelectionDAGBulder (or at the very beginning of its
runOnFunction) so you can modify the IR without worrying about whether
SelectionDAG will notice the new instructions.

If you decide to keep doing this transformation in a more rigorous way
long term, it would probably be put in a new pass (since I'd guess it
would be implementing a change in semantics), but it's possible it
could belong in an existing pass. Depends on exactly what the new
instruction does.

Cheers.

Tim.

Hi Tim,
Thank you for the quick response!

so you'd probably check you're looking at a
BranchInst and check BI->getSuccessor(0)->getName() (& 1 if it's
conditional)
I initially was printing out the result from getName() (I.getParent()->getName()) and it printed out nothing sadly.

when parsing the instructions in SelectionDAGBuilder but it was only visiting instructions in the first/main BB and outputted %2.

I'm not sure what's going on there, it would depend on which function
you're modifying in SelectionDAG.
I am calling it right after each instruction is visited in the visit(…) function. And it prints out the instruction’s number but it prints out only %2 when I call printAsOperand on the instruction’s parent, hence why I assumed that the visit function was going over only the main block.

It's probably easier if it's
before SelectionDAGBulder (or at the very beginning of its
runOnFunction) so you can modify the IR without worrying about whether
SelectionDAG will notice the new instructions.
That’s true. I’m now trying to detect the specific label in the LLParser and hopefully can insert my instruction there. Would creating a new pseudo instruction be a good way to emit “.byte …” assembly code?

Thank you,
Kaarthik A.

I initially was printing out the result from getName() (I.getParent()->getName()) and it printed out nothing sadly.

when parsing the instructions in SelectionDAGBuilder but it was only visiting instructions in the first/main BB and outputted %2.

The instruction's parent is the (unnamed) entry block to the function
(i.e. the block containing the instruction). By LLVM's automatic
numbering system that's %2 in a function with two arguments. So yes,
getName would return an empty string in that case.

I'm not sure what's going on there, it would depend on which function
you're modifying in SelectionDAG.

I am calling it right after each instruction is visited in the visit(…) function. And it prints out the instruction’s number but it prints out only %2 when I call printAsOperand on the instruction’s parent, hence why I assumed that the visit function was going over only the main block.

I'm afraid I still don't have anything very helpful to tell you about that.

That’s true. I’m now trying to detect the specific label in the LLParser and hopefully can insert my instruction there. Would creating a new pseudo instruction be a good way to emit “.byte …” assembly code?

An intrinsic would probably be simpler. You need to modify a lot of
places to invent a new instruction (LL parser, LL printer, Bitcode
parser, Bitcode printer, Codegen, ...)

Cheers.

Tim.

Got it, thank you Tim!

Kaarthik A.