Search code examples
c++compiler-constructionllvmllvm-irllvm-c++-api

Adding appropriate PHI Nodes to llvm-ir


I have the following scenario:

       A
     /   \
     B   C
      \ /
       D
      / \
     E   F
      \ /
      ...

Where A,B,C,D,E,F are all basic blocks, | is a downward pointing arrow.

Now, in B I would have some def , say %mul = ..., that would later be used in the corresponding left-side block E , like ... = %mul ... . I have the appropriate control flow inserted - either only the left branches will be taken, or only the right ones, the problem is that I get a Instruction does not dominate all uses error on the verification pass.

I tried to fix this by adding PHINode instructions, like below:

B:                                     ; preds = %A
  %shl = shl ...
  br label %D

C:                                     ; preds = %A
 ...
 br label %D

D:                                      ; preds = %B , %C
 ...
 br i1 %ctrl, label %E, label %F

E:                                    ; preds = %D
  %phi_nlcs = phi i32 [ %shl, %extra_l_diff ], [ 0, %for.cond ]
  %cmp = icmp slt i32 %phi_nlcs, %1
  br label ...

The ellipses are there to hide the irrelevant details, also I've renamed the blocks but the core logic should be there. As you can see, I have replaced the use of %shl with the PHINode with the appropriate replaceAllUsesWith() call.

However, now I get the following new error:

PHINode should have one entry for each predecessor of its parent basic block! 
%phi_nlcs = phi i32 [ %shl, %extra_l_diff ], [ 0, %for.cond ]

How can I fix this?


Solution

  • The phi node needs to be at the beginning of D.

    D: 
      %phi_nlcs = phi [%shl, B] [undef, C] ; if we've come from B use %shl, if from C an undef value.
      ...
    

    This is because the phi node is saying what the value needs to be be for each of the dominating basic blocks (B and C) so it needs to be placed at the edge where the basic blocks combine.