clang branching using label

Hi,

Clang normally generates code that looks like

....
; <label>:22 ; preds = %0
  %23 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([24 x i8]*
@.str, i32 0, i32 0))
  br label %24

; <label>:24 ; preds = %22, %0
  %25 = load i32* %tmphigh, align 4
  %26 = and i32 %25, 65535
  store i32 %26, i32* %high1, align 4
.....

If I insert some instructions before %25 so it will look like:
....
; <label>:22 ; preds = %0
  %23 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([24 x i8]*
@.str, i32 0, i32 0))
  br label %24

; <label>:24
  %var = add i32 %7, 0 ; for testing
  %25 = load i32* %tmphigh, align 4
  %26 = and i32 %25, 65535
  store i32 %26, i32* %high1, align 4
.....

Will %var get evaluated or it will be skipped?
How does the branching work since the label is commented out? Does it assume
%24 is the nop before %25?

How about the following case where a variable assignment does not occur?

....
  %37 = icmp sle i32 %33, %36
  br i1 %37, label %38, label %217

;38:
  store i32 0, i32* %j, align 4
  br label %39

.....
which is changed to

......
  %37 = icmp sle i32 %33, %36
  br i1 %37, label %38, label %217

;38:
  store i32 0, i32* %p, align 4
  store i32 0, i32* %j, align 4
  br label %39
.....

Will both store instructions get executed?
Does the empty line before the commented out label number have any real
function?

Thanks,

Chris

Hi Chris,

Clang normally generates code that looks like

....
;<label>:22 ; preds = %0
   %23 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([24 x i8]*
@.str, i32 0, i32 0))
   br label %24

;<label>:24 ; preds = %22, %0
   %25 = load i32* %tmphigh, align 4
   %26 = and i32 %25, 65535
   store i32 %26, i32* %high1, align 4
.....

If I insert some instructions before %25 so it will look like:
....
;<label>:22 ; preds = %0
   %23 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([24 x i8]*
@.str, i32 0, i32 0))
   br label %24

;<label>:24
   %var = add i32 %7, 0 ; for testing
   %25 = load i32* %tmphigh, align 4
   %26 = and i32 %25, 65535
   store i32 %26, i32* %high1, align 4
.....

Will %var get evaluated or it will be skipped?

It will be evaluated.

How does the branching work since the label is commented out?

Labels and most other names only exist for the convenience of human readers.
LLVM knows that a basic block has ended because of "br label %24". This is
an example of a terminator instruction: an instruction that only occurs as
the last instruction of a basic block (every basic block must finish with
one). Thus LLVM knows where all basic blocks start and end by just looking
at the terminator instructions. It doesn't need labels.

  Does it assume

%24 is the nop before %25?

I didn't understand this question. When printing human readable IR, LLVM prints
a numerical name like %24 for things which have no name internally. It has to
put something since otherwise it wouldn't be able to read the IR back in again.
The numbers it chooses just increment sequentially. This makes it hard to
modify such human readable IR by hand since you have to preserve the sequential
numbering. (If you want everything to have a real name use opt's -instnamer
pass).

How about the following case where a variable assignment does not occur?

I'm not sure what you mean by "a variable assignment does not occur".
An instruction like "%var = add i32 %7, 0" isn't really an assignment to
a variable "%var" since (thanks to SSA form) it isn't possible to "assign"
anything else to "%var" later. Instead "%var" is just a name for the value
of "add i32 %7, 0". In any case it is exactly the same:

....
   %37 = icmp sle i32 %33, %36
   br i1 %37, label %38, label %217

^^ Terminator instruction, so basic block finishes here

;38:
   store i32 0, i32* %j, align 4

^^ Thus this is the first instruction of the next basic block

   br label %39

.....
which is changed to

......
   %37 = icmp sle i32 %33, %36
   br i1 %37, label %38, label %217

^^ Terminator instruction, so basic block finishes here

;38:
   store i32 0, i32* %p, align 4

^^ Thus this is the first instruction of the next basic block

   store i32 0, i32* %j, align 4
   br label %39
.....

Will both store instructions get executed?

Yes.

Does the empty line before the commented out label number have any real
function?

No.

Ciao, Duncan.

Hi Chris,

Clang normally generates code that looks like

....
;<label>:22 ; preds = %0
%23 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([24 x i8]*
@.str, i32 0, i32 0))
br label %24

;<label>:24 ; preds = %22, %0
%25 = load i32* %tmphigh, align 4
%26 = and i32 %25, 65535
store i32 %26, i32* %high1, align 4
.....

If I insert some instructions before %25 so it will look like:
....
;<label>:22 ; preds = %0
%23 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([24 x i8]*
@.str, i32 0, i32 0))
br label %24

;<label>:24
%var = add i32 %7, 0 ; for testing
%25 = load i32* %tmphigh, align 4
%26 = and i32 %25, 65535
store i32 %26, i32* %high1, align 4
.....

Will %var get evaluated or it will be skipped?

It will be evaluated.

How does the branching work since the label is commented out?

Labels and most other names only exist for the convenience of human readers.
LLVM knows that a basic block has ended because of "br label %24". This is
an example of a terminator instruction: an instruction that only occurs as
the last instruction of a basic block (every basic block must finish with
one). Thus LLVM knows where all basic blocks start and end by just looking
at the terminator instructions. It doesn't need labels.

Does clang have any flags for generating readable (named) labels in
LLVM? That could be useful for debugging code.

How does the verifier deal with this? I'm noticing that if I load a clang
compiled function (with -emit-llvm) and run the verifier, there is no
problem. If I start mucking with the function body (adding an instruction),
the verifier is unhappy saying the instructions that would have been in the
commented out block aren't part of a basic block. Does the clang compiled
function have some special attributes?

Duncan Sands wrote:

Sometimes the anonymous numbering confuses things. Try running the .ll file through "opt -instnamer" first.

-Jim