[llvm] [PredicateInfo] Support existing `PredicateType` by adding `PredicatePHI` when needing introduction of phi nodes (PR #151132)

Rajveer Singh Bharadwaj via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 20 05:42:27 PDT 2025


Rajveer100 wrote:

@nikic 
There's actually one thing I missed to share with you. Right now, with `PredicatePHI` this is well integrated with the renaming stack and so we don't need to handle anything extra when we place sea copies since the edge predicates would have already been inserted.

After removal:

```c++
    // For edge predicates, we can just place the operand in the block before
    // the terminator. For assume, we have to place it right after the assume
    // to ensure we dominate all uses except assume itself. Always insert
    // right before the terminator or after the assume, so that we insert in
    // proper order in the case of multiple predicateinfo in the same block.
    if (isa<PredicateWithEdge>(ValInfo)) {
      BitCastInst *PIC = CreateSSACopy(getBranchTerminator(ValInfo), Op,
                                       Op->getName() + "." + Twine(Counter++));
      PI.PredicateMap.insert({PIC, ValInfo});
      Result.Def = PIC;
    } else {
      auto *PAssume = dyn_cast<PredicateAssume>(ValInfo);
      assert(PAssume &&
             "Should not have gotten here without it being an assume");
      // Insert the predicate directly after the assume. While it also holds
      // directly before it, assume(i1 true) is not a useful fact.
      BitCastInst *PIC = CreateSSACopy(PAssume->AssumeInst->getNextNode(), Op);
      PI.PredicateMap.insert({PIC, ValInfo});
      Result.Def = PIC;
    }

    for (const auto &Entry : InsertedPHIBlocks) {
      BasicBlock *PHIBlock = Entry.first;
      Value *OpInBlock = Entry.second;
      if (DT.dominates(...)) {
        BitCastInst *PIC =
            CreateSSACopy(&*PHIBlock->getFirstInsertionPt(), OpInBlock);
        Result.Def = PIC;
      }
    }
```

We would need some way to determine to dominated uses for this predicate which is an extra overhead to check for. For this, we would need to do it after we completely materialize the stack and then insert them.

This would mean moving the lambda function for creating ssa copy as well extra checks.

In fact, the rename use definition itself insists on this fact:

```md
// Instead of the standard SSA renaming algorithm, which is O(Number of
// instructions), and walks the entire dominator tree, we walk only the defs +
// uses.  The standard SSA renaming algorithm does not really rely on the
// dominator tree except to order the stack push/pops of the renaming stacks, so
// that defs end up getting pushed before hitting the correct uses.  This does
// not require the dominator tree, only the *order* of the dominator tree. The
// complete and correct ordering of the defs and uses, in dominator tree is
// contained in the DFS numbering of the dominator tree. So we sort the defs and
// uses into the DFS ordering, and then just use the renaming stack as per
// normal, pushing when we hit a def (which is a predicateinfo instruction),
// popping when we are out of the dfs scope for that def, and replacing any uses
// with top of stack if it exists.  In order to handle liveness without
// propagating liveness info, we don't actually insert the predicateinfo
// instruction def until we see a use that it would dominate.  Once we see such
// a use, we materialize the predicateinfo instruction in the right place and
// use it.
//
// TODO: Use this algorithm to perform fast single-variable renaming in
// promotememtoreg and memoryssa.
```

Please try to look into it once again.

https://github.com/llvm/llvm-project/pull/151132


More information about the llvm-commits mailing list