Skip to content

Commit 0b13638

Browse files
committed
[PredicateInfo] Support existing PredicateType by adding PredicatePHI
when needing introduction of phi nodes Resolves #150606 Currently `ssa.copy` is used mostly for straight line code, i.e, without joins or uses of phi nodes. With this, passes would be able to pick up the relevant info and further optimize the IR.
1 parent ece7a72 commit 0b13638

File tree

2 files changed

+130
-1
lines changed

2 files changed

+130
-1
lines changed

llvm/include/llvm/Transforms/Utils/PredicateInfo.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class Value;
6767
class IntrinsicInst;
6868
class raw_ostream;
6969

70-
enum PredicateType { PT_Branch, PT_Assume, PT_Switch };
70+
enum PredicateType { PT_Branch, PT_Assume, PT_Switch, PT_PHI };
7171

7272
/// Constraint for a predicate of the form "cmp Pred Op, OtherOp", where Op
7373
/// is the value the constraint applies to (the ssa.copy result).
@@ -171,6 +171,19 @@ class PredicateSwitch : public PredicateWithEdge {
171171
}
172172
};
173173

174+
class PredicatePHI : public PredicateBase {
175+
public:
176+
BasicBlock *PHIBlock;
177+
SmallVector<std::pair<BasicBlock *, PredicateBase *>, 4> IncomingPredicates;
178+
179+
PredicatePHI(Value *Op, BasicBlock *PHIBB)
180+
: PredicateBase(PT_PHI, Op, nullptr), PHIBlock(PHIBB) {}
181+
PredicatePHI() = delete;
182+
static bool classof(const PredicateBase *PB) { return PB->Type == PT_PHI; }
183+
184+
LLVM_ABI std::optional<PredicateConstraint> getConstraint() const;
185+
};
186+
174187
/// Encapsulates PredicateInfo, including all data associated with memory
175188
/// accesses.
176189
class PredicateInfo {

llvm/lib/Transforms/Utils/PredicateInfo.cpp

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "llvm/ADT/SmallPtrSet.h"
1717
#include "llvm/Analysis/AssumptionCache.h"
1818
#include "llvm/IR/AssemblyAnnotationWriter.h"
19+
#include "llvm/IR/CFG.h"
1920
#include "llvm/IR/Dominators.h"
2021
#include "llvm/IR/IRBuilder.h"
2122
#include "llvm/IR/InstIterator.h"
@@ -213,6 +214,8 @@ class PredicateInfoBuilder {
213214
// whether it returned a valid result.
214215
DenseMap<Value *, unsigned int> ValueInfoNums;
215216

217+
DenseMap<BasicBlock *, SmallVector<Value *, 4>> PHICandidates;
218+
216219
BumpPtrAllocator &Allocator;
217220

218221
ValueInfo &getOrCreateValueInfo(Value *);
@@ -224,6 +227,10 @@ class PredicateInfoBuilder {
224227
SmallVectorImpl<Value *> &OpsToRename);
225228
void processSwitch(SwitchInst *, BasicBlock *,
226229
SmallVectorImpl<Value *> &OpsToRename);
230+
void identifyPHICandidates(SmallVectorImpl<Value *> &OpsToRename);
231+
void insertPredicatePHIs(Value *Op, BasicBlock *PHIBlock,
232+
SmallVectorImpl<Value *> &OpsToRename);
233+
void processPredicatePHIs(SmallVectorImpl<Value *> &OpsToRename);
227234
void renameUses(SmallVectorImpl<Value *> &OpsToRename);
228235
void addInfoFor(SmallVectorImpl<Value *> &OpsToRename, Value *Op,
229236
PredicateBase *PB);
@@ -452,6 +459,71 @@ void PredicateInfoBuilder::processSwitch(
452459
}
453460
}
454461

462+
void PredicateInfoBuilder::identifyPHICandidates(
463+
SmallVectorImpl<Value *> &OpsToRename) {
464+
for (Value *Op : OpsToRename) {
465+
const auto &ValueInfo = getValueInfo(Op);
466+
SmallPtrSet<BasicBlock *, 4> DefiningBlocks;
467+
for (const auto *PInfo : ValueInfo.Infos) {
468+
if (auto *PBranch = dyn_cast<PredicateBranch>(PInfo)) {
469+
DefiningBlocks.insert(PBranch->To);
470+
} else if (auto *PSwitch = dyn_cast<PredicateSwitch>(PInfo)) {
471+
DefiningBlocks.insert(PSwitch->To);
472+
}
473+
}
474+
475+
if (DefiningBlocks.size() > 1) {
476+
SmallPtrSet<BasicBlock *, 8> PHIBlocks(DefiningBlocks.begin(),
477+
DefiningBlocks.end());
478+
PHICandidates[*PHIBlocks.begin()].push_back(Op);
479+
}
480+
}
481+
}
482+
483+
void PredicateInfoBuilder::insertPredicatePHIs(
484+
Value *Op, BasicBlock *PHIBlock, SmallVectorImpl<Value *> &OpsToRename) {
485+
IRBuilder<> Builder(&PHIBlock->front());
486+
487+
PHINode *PHI = Builder.CreatePHI(Op->getType(), pred_size(PHIBlock),
488+
Op->getName() + ".predicate.phi");
489+
PredicatePHI *PPHI = new (Allocator) PredicatePHI(Op, PHIBlock);
490+
491+
PPHI->RenamedOp = PHI;
492+
493+
const auto &ValueInfo = getValueInfo(Op);
494+
for (BasicBlock *Pred : predecessors(PHIBlock)) {
495+
Value *IncomingValue = nullptr;
496+
for (const auto *PInfo : ValueInfo.Infos) {
497+
if (auto *PBranch = dyn_cast<PredicateBranch>(PInfo)) {
498+
if (PBranch->From == Pred && PBranch->To == PHIBlock) {
499+
PPHI->IncomingPredicates.push_back(
500+
{Pred, const_cast<PredicateBase *>(PInfo)});
501+
IncomingValue = PBranch->OriginalOp;
502+
}
503+
} else if (auto *PSwitch = dyn_cast<PredicateSwitch>(PInfo)) {
504+
if (PSwitch->From == Pred && PSwitch->To == PHIBlock) {
505+
PPHI->IncomingPredicates.push_back(
506+
{Pred, const_cast<PredicateBase *>(PInfo)});
507+
IncomingValue = PSwitch->OriginalOp;
508+
}
509+
}
510+
}
511+
PHI->addIncoming(IncomingValue, Pred);
512+
}
513+
514+
addInfoFor(OpsToRename, Op, PPHI);
515+
}
516+
517+
void PredicateInfoBuilder::processPredicatePHIs(
518+
SmallVectorImpl<Value *> &OpsToRename) {
519+
for (const auto &PHICandidate : PHICandidates) {
520+
BasicBlock *PHIBlock = PHICandidate.first;
521+
for (Value *Op : PHICandidate.second) {
522+
insertPredicatePHIs(Op, PHIBlock, OpsToRename);
523+
}
524+
}
525+
}
526+
455527
// Build predicate info for our function
456528
void PredicateInfoBuilder::buildPredicateInfo() {
457529
DT.updateDFSNumbers();
@@ -478,6 +550,10 @@ void PredicateInfoBuilder::buildPredicateInfo() {
478550
if (DT.isReachableFromEntry(II->getParent()))
479551
processAssume(II, II->getParent(), OpsToRename);
480552
}
553+
554+
identifyPHICandidates(OpsToRename);
555+
processPredicatePHIs(OpsToRename);
556+
481557
// Now rename all our operations.
482558
renameUses(OpsToRename);
483559
}
@@ -535,6 +611,12 @@ Value *PredicateInfoBuilder::materializeStack(unsigned int &Counter,
535611
CreateSSACopy(B, Op, Op->getName() + "." + Twine(Counter++));
536612
PI.PredicateMap.insert({PIC, ValInfo});
537613
Result.Def = PIC;
614+
} else if (isa<PredicatePHI>(ValInfo)) {
615+
auto *PPHI = dyn_cast<PredicatePHI>(ValInfo);
616+
IRBuilder<> B(&*PPHI->PHIBlock->getFirstInsertionPt());
617+
CallInst *PIC = CreateSSACopy(B, Op);
618+
PI.PredicateMap.insert({PIC, ValInfo});
619+
Result.Def = PIC;
538620
} else {
539621
auto *PAssume = dyn_cast<PredicateAssume>(ValInfo);
540622
assert(PAssume &&
@@ -623,6 +705,15 @@ void PredicateInfoBuilder::renameUses(SmallVectorImpl<Value *> &OpsToRename) {
623705
OrderedUses.push_back(VD);
624706
}
625707
}
708+
} else if (const auto *PPHI = dyn_cast<PredicatePHI>(PossibleCopy)) {
709+
VD.LocalNum = LN_First;
710+
auto *DomNode = DT.getNode(PPHI->PHIBlock);
711+
if (DomNode) {
712+
VD.DFSIn = DomNode->getDFSNumIn();
713+
VD.DFSOut = DomNode->getDFSNumOut();
714+
VD.PInfo = PossibleCopy;
715+
OrderedUses.push_back(VD);
716+
}
626717
}
627718
}
628719

@@ -773,10 +864,31 @@ std::optional<PredicateConstraint> PredicateBase::getConstraint() const {
773864
}
774865

775866
return {{CmpInst::ICMP_EQ, cast<PredicateSwitch>(this)->CaseValue}};
867+
case PT_PHI:
868+
return cast<PredicatePHI>(this)->getConstraint();
776869
}
777870
llvm_unreachable("Unknown predicate type");
778871
}
779872

873+
std::optional<PredicateConstraint> PredicatePHI::getConstraint() const {
874+
if (IncomingPredicates.empty())
875+
return std::nullopt;
876+
877+
auto FirstConstraint = IncomingPredicates[0].second->getConstraint();
878+
if (!FirstConstraint)
879+
return std::nullopt;
880+
881+
for (size_t I = 1; I < IncomingPredicates.size(); ++I) {
882+
auto Constraint = IncomingPredicates[I].second->getConstraint();
883+
if (!Constraint || Constraint->Predicate != FirstConstraint->Predicate ||
884+
Constraint->OtherOp != FirstConstraint->OtherOp) {
885+
return std::nullopt;
886+
}
887+
}
888+
889+
return FirstConstraint;
890+
}
891+
780892
void PredicateInfo::verifyPredicateInfo() const {}
781893

782894
// Replace ssa_copy calls created by PredicateInfo with their operand.
@@ -838,6 +950,10 @@ class PredicateInfoAnnotatedWriter : public AssemblyAnnotationWriter {
838950
} else if (const auto *PA = dyn_cast<PredicateAssume>(PI)) {
839951
OS << "; assume predicate info {"
840952
<< " Comparison:" << *PA->Condition;
953+
} else if (const auto *PP = dyn_cast<PredicatePHI>(PI)) {
954+
OS << "; phi predicate info { PHIBlock: ";
955+
PP->PHIBlock->printAsOperand(OS);
956+
OS << " IncomingEdges: " << PP->IncomingPredicates.size();
841957
}
842958
OS << ", RenamedOp: ";
843959
PI->RenamedOp->printAsOperand(OS, false);

0 commit comments

Comments
 (0)