diff options
Diffstat (limited to 'llvm/lib/IR/Instructions.cpp')
| -rw-r--r-- | llvm/lib/IR/Instructions.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index f404e11b9c0f..9c5937821399 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -48,6 +48,7 @@ #include <cassert> #include <cstdint> #include <optional> +#include <set> #include <vector> using namespace llvm; @@ -239,6 +240,40 @@ bool PHINode::hasConstantOrUndefValue() const { return true; } +/// If the specified PHI node (possibly via other PHI nodes) merges together the +/// same or identical (i.e. Instruction::isIdenticalTo() returns true) values, +/// return one of the values, otherwise return null. +Value *PHINode::hasIdenticalValue() { + std::vector<PHINode *> Worklist; + std::set<PHINode *> Seen; + Value *Result = nullptr; + Worklist.push_back(this); + while (!Worklist.empty()) { + PHINode *PN = Worklist.back(); + Worklist.pop_back(); + if (!Seen.insert(PN).second) + continue; + for (Value *V : PN->incoming_values()) { + if (auto *PN = dyn_cast<PHINode>(V)) { + Worklist.push_back(PN); + continue; + } + if (!Result) { + Result = V; + continue; + } + if (V == Result) + continue; + if (auto *I = dyn_cast<Instruction>(V)) + if (auto *ResultI = dyn_cast<Instruction>(Result)) + if (I->isIdenticalTo(ResultI)) + continue; + return nullptr; + } + } + return Result; +} + //===----------------------------------------------------------------------===// // LandingPadInst Implementation //===----------------------------------------------------------------------===// |
