diff options
Diffstat (limited to 'llvm/lib/Transforms/Utils/Local.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/Local.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 7024c66..3110322 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -2886,3 +2886,41 @@ bool llvm::canReplaceOperandWithVariable(const Instruction *I, unsigned OpIdx) { return true; } } + +using AllocaForValueMapTy = DenseMap<Value *, AllocaInst *>; +AllocaInst *llvm::findAllocaForValue(Value *V, + AllocaForValueMapTy &AllocaForValue) { + if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) + return AI; + // See if we've already calculated (or started to calculate) alloca for a + // given value. + AllocaForValueMapTy::iterator I = AllocaForValue.find(V); + if (I != AllocaForValue.end()) + return I->second; + // Store 0 while we're calculating alloca for value V to avoid + // infinite recursion if the value references itself. + AllocaForValue[V] = nullptr; + AllocaInst *Res = nullptr; + if (CastInst *CI = dyn_cast<CastInst>(V)) + Res = findAllocaForValue(CI->getOperand(0), AllocaForValue); + else if (PHINode *PN = dyn_cast<PHINode>(V)) { + for (Value *IncValue : PN->incoming_values()) { + // Allow self-referencing phi-nodes. + if (IncValue == PN) + continue; + AllocaInst *IncValueAI = findAllocaForValue(IncValue, AllocaForValue); + // AI for incoming values should exist and should all be equal. + if (IncValueAI == nullptr || (Res != nullptr && IncValueAI != Res)) + return nullptr; + Res = IncValueAI; + } + } else if (GetElementPtrInst *EP = dyn_cast<GetElementPtrInst>(V)) { + Res = findAllocaForValue(EP->getPointerOperand(), AllocaForValue); + } else { + LLVM_DEBUG(dbgs() << "Alloca search cancelled on unknown instruction: " + << *V << "\n"); + } + if (Res) + AllocaForValue[V] = Res; + return Res; +} |