|
11 | 11 | //===----------------------------------------------------------------------===// |
12 | 12 |
|
13 | 13 | #include "llvm/Transforms/Utils/SSAUpdaterBulk.h" |
| 14 | +#include "llvm/Analysis/InstructionSimplify.h" |
14 | 15 | #include "llvm/Analysis/IteratedDominanceFrontier.h" |
15 | 16 | #include "llvm/IR/BasicBlock.h" |
16 | 17 | #include "llvm/IR/Dominators.h" |
@@ -182,3 +183,49 @@ void SSAUpdaterBulk::RewriteAllUses(DominatorTree *DT, |
182 | 183 | } |
183 | 184 | } |
184 | 185 | } |
| 186 | + |
| 187 | +static bool isEquivalentPHI(PHINode *PHI1, PHINode *PHI2) { |
| 188 | + if (PHI1->getNumIncomingValues() != PHI2->getNumIncomingValues()) |
| 189 | + return false; |
| 190 | + |
| 191 | + unsigned I = 0, NumValues = PHI1->getNumIncomingValues(); |
| 192 | + for (; I != NumValues; ++I) { |
| 193 | + if (PHI1->getIncomingBlock(I) != PHI2->getIncomingBlock(I)) |
| 194 | + break; |
| 195 | + if (PHI1->getIncomingValue(I) != PHI2->getIncomingValue(I)) |
| 196 | + return false; |
| 197 | + } |
| 198 | + // TODO: add procesing if phis have different order of incoming values. |
| 199 | + return I == NumValues; |
| 200 | +} |
| 201 | + |
| 202 | +bool SSAUpdaterBulk::simplifyPass(SmallVectorImpl<PHINode *> &Worklist) { |
| 203 | + if (Worklist.empty()) |
| 204 | + return false; |
| 205 | + |
| 206 | + auto findEquivalentPHI = [](PHINode *PHI) -> Value * { |
| 207 | + BasicBlock *BB = PHI->getParent(); |
| 208 | + for (auto &OtherPHI : BB->phis()) { |
| 209 | + if (PHI != &OtherPHI && isEquivalentPHI(PHI, &OtherPHI)) { |
| 210 | + return &OtherPHI; |
| 211 | + } |
| 212 | + } |
| 213 | + return nullptr; |
| 214 | + }; |
| 215 | + |
| 216 | + const DataLayout &DL = Worklist.front()->getParent()->getDataLayout(); |
| 217 | + bool Change = false; |
| 218 | + for (PHINode *&PHI : Worklist) { |
| 219 | + Value *Replacement = simplifyInstruction(PHI, DL); |
| 220 | + if (!Replacement) |
| 221 | + Replacement = findEquivalentPHI(PHI); |
| 222 | + |
| 223 | + if (Replacement) { |
| 224 | + PHI->replaceAllUsesWith(Replacement); |
| 225 | + PHI->eraseFromParent(); |
| 226 | + PHI = nullptr; // Mark as removed |
| 227 | + Change = true; |
| 228 | + } |
| 229 | + } |
| 230 | + return Change; |
| 231 | +} |
0 commit comments