This is an archive of the discontinued LLVM Phabricator instance.

SSAUpdater: Add mode when Phi creation is not allowed
AbandonedPublic

Authored by skatkov on Jul 17 2017, 12:58 AM.

Details

Summary

Add one more parameter to SSAUpdater to disable PHI node creation.
SSAUpdater will find a Phi node if it exists but will return undef value if
new Phi node should be created.

By default the behavior is not changed. Phi nodes can be created.

I need this patch for implementation of PR26223.

Diff Detail

Event Timeline

skatkov created this revision.Jul 17 2017, 12:58 AM
efriedma added inline comments.Jul 17 2017, 1:53 PM
include/llvm/Transforms/Utils/SSAUpdaterImpl.h
97

This is bad: the caller has no way to tell what happened if you return undef (is the value actually undef at the given point, or did PHI construction fail?).

I need this patch for implementation of PR26223.

Can you share more details, looking at that bug, i do not understand why this mode would be needed, at all.

I also don't see the point in using ssaupdater if it doesn't allow phi node creation.
In such a situation, all the answers are pre-determined and don't require the updater at all.

Hi Daniel, I plan to upload the patch for PR26233 this week. I'd like to think a bit more about relation of recursion and the patch I have - whether it works correctly and whether SSAUpdater work correctly with this pattern.

For now, shortly, the idea of future patch is as follows: in CodeGenPrepare::OptimizeMemoryInst I'd like to collect all cases where address computation is identical but base might be different. So to sink address computation to memory instruction I need to find a common Phi node for all bases which can be used in BB where memory instruction is located. For that purpose I'd like to use SSAUpdater. However it is possible that Phi node for bases may not exists (for example if there is no further uses of base it can be removed).

It is not clear that creation of new Phi node is profitable with respect to folding of address computation to memory instruction.
I'd like to add an option which allows/disallows creation of Phi nodes. For that I need this patch.

SSAUpdater is able to correctly answer to the question: if I know the different values in different basic blocks is there any merge of these values in BB I'm interested in. In general it is not so easy and straightforward in complex CFG.

I also can just use SSAUpdater as is and after that remove the created Phi nodes if needed but this approach seems better to me.

I hope it answers why I'd like to use this utility in the mode when I need only to check whether there is a Phi node merging all my values.

include/llvm/Transforms/Utils/SSAUpdaterImpl.h
97

I see. Is nullptr better?

Hi Daniel, I plan to upload the patch for PR26233 this week. I'd like to think a bit more about relation of recursion and the patch I have - whether it works correctly and whether SSAUpdater work correctly with this pattern.

For now, shortly, the idea of future patch is as follows: in CodeGenPrepare::OptimizeMemoryInst I'd like to collect all cases where address computation is identical but base might be different. So to sink address computation to memory instruction I need to find a common Phi node for all bases which can be used in BB where memory instruction is located. For that purpose I'd like to use SSAUpdater. However it is possible that Phi node for bases may not exists (for example if there is no further uses of base it can be removed).

Please don't use SSA updater for this.
This is trivial to do without it., and SSAUpdater can't do it any faster than you can.

It is not clear that creation of new Phi node is profitable with respect to folding of address computation to memory instruction.
I'd like to add an option which allows/disallows creation of Phi nodes. For that I need this patch.

I'm really strongly opposed to doing it for this use case.

SSAUpdater is able to correctly answer to the question: if I know the different values in different basic blocks is there any merge of these values in BB I'm interested in. In general it is not so easy and straightforward in complex CFG.

I strongly disagree.
The algorithm is < 100 lines of code.
SSAUpdater is not going to perform any magic here.

The algorithm you are looking for is a simple walking algorithm that looks like this (taken from a paper i can give you if you like).

(The code below supports tracking multiple variables at once, you could remove unsigned Var if you only ever are trying one at a time)

CurrentDef is a map from std::pair{varnum, bb} to a definition of varnum in BB.
Fill it in with your existing values.

void writeVariable(unsigned Var, BasicBlock *BB, Value *V) {
  CurrentDef[{Var, BB}] = V;
}
Value *GetExistingVariableOrCreate(unsigned Var, BasicBlock *BB) {
  auto CDI = CurrentDefs.find({Var, BB});
  if (CDI != CurrentDefs.end())
    return CDI->second;
  return GetVariableInBlock(Var, BB);
}
Value *GetVariableInBlock(unsigned int VarNum, BasicBlock *BB)
{
  Value *Result;

  // Single predecessor case, just recurse
  if (BasicBlock *Pred = BB->getSinglePredecessor()) {
    Result = GetVariableInBlock(Var, Pred);
  } else if (VisitedBlocks.count({Var, BB})) {
    // We hit our node again, meaning we had a cycle, we must insert a phi
    // node to break it.
   Result = Create an empty phi we'll fill in later.
    {Search for PHI Node here, you need one, if you don't find one, you need a phi but don't have one}
  } else {
    // Mark us visited so we can detect a cycle
    VisitedBlocks.insert({Var, BB});
    SmallVector<Value *, 8> PHIOps;

    // Recurse to get the values in our predecessors. This will look for phi nodes if we cycle.
    for (auto *Pred : predecessors(BB))
      PHIOps.push_back(GetVariableInBlock(Var, Pred));
      Result = {Search for PHI that has PHIOps in BB}

 writeVariable(Var, BB, Result);
 return Result;
}

Using the current SSAUpdater to do this will compute dominance frontiers, etc, all which is a complete waste of time for you.
You are just trying to see if there are merge blocks that values reach.

The above is one way of doing it (by walking up).

If you are only concerned about existing phis, you can also just look at the uses.

Hi Daniel,
thank you much for a hint. I'm looking into this direction right now.

Side question: what is a primary goal for SSAUpdater then?

SSA Updater exists to perform SSA Updates for complicated cases (I also have a patch out to rewrite it, because it's super-slow. The algorithm i gave you is a variant of that patch. See https://reviews.llvm.org/D28934).

Most algorithms in LLVM are pretty straightforward to update, but things like "copying a loop and then unrolling + vectorizing it", may be difficult.

SSAUpdater can perform the updating for these cases. You give it a set of existing values, and tell it what block you are trying to place a new value in, and it will insert the right set of phi nodes.

You are using it as an available value finder, which it's not really meant for, and there are much faster ways of doing.

Without seeing your patch, i would expect you could just look at the uses of your defs to see if a phi node exists that meets your specifications.
But if you have to understand what such a phi node would look like, the algorithm i gave should do it.

In any case, SSAUpdater is really not the right mechanism to go find what phis match a certain set of values.
:)

skatkov abandoned this revision.Jul 31 2017, 12:21 AM

Hi Daniel,

I've come up with the following implementation basing on your idea: https://reviews.llvm.org/D36073

Please take into account that finally I realized that I could not use SSAUpdater API because it is possible that I can observe the base instruction in the same BB but the difference might be in the path I can get it.
Simple example:
p1 = b1 + 40
p2 = b2 + 40
p = p1
if (cond) p = p2
v = *(p)

So I have p1 and p2 in the same basic block, so I cannot say to SSA update that I saw b1 and b2 in the same basic block to get the right phi node merging b1 and b2.
I hope the right implementation may b found in D36073