diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -766,9 +766,6 @@ SmallPtrSetImpl &Visited, MemoryAccess *MemAccess, Instruction *OrigInst, BasicBlock *PredBB); - bool OpIsSafeForPHIOfOpsHelper(Value *V, const BasicBlock *PHIBlock, - SmallPtrSetImpl &Visited, - SmallVectorImpl &Worklist); bool OpIsSafeForPHIOfOps(Value *Op, const BasicBlock *PHIBlock, SmallPtrSetImpl &); void addPhiOfOps(PHINode *Op, BasicBlock *BB, Instruction *ExistingValue); @@ -2574,58 +2571,6 @@ isa(I); } -bool NewGVN::OpIsSafeForPHIOfOpsHelper( - Value *V, const BasicBlock *PHIBlock, - SmallPtrSetImpl &Visited, - SmallVectorImpl &Worklist) { - - if (!isa(V)) - return true; - auto OISIt = OpSafeForPHIOfOps.find(V); - if (OISIt != OpSafeForPHIOfOps.end()) - return OISIt->second; - - // Keep walking until we either dominate the phi block, or hit a phi, or run - // out of things to check. - if (DT->properlyDominates(getBlockForValue(V), PHIBlock)) { - OpSafeForPHIOfOps.insert({V, true}); - return true; - } - // PHI in the same block. - if (isa(V) && getBlockForValue(V) == PHIBlock) { - OpSafeForPHIOfOps.insert({V, false}); - return false; - } - - auto *OrigI = cast(V); - // When we hit an instruction that reads memory (load, call, etc), we must - // consider any store that may happen in the loop. For now, we assume the - // worst: there is a store in the loop that alias with this read. - // The case where the load is outside the loop is already covered by the - // dominator check above. - // TODO: relax this condition - if (OrigI->mayReadFromMemory()) - return false; - - for (auto *Op : OrigI->operand_values()) { - if (!isa(Op)) - continue; - // Stop now if we find an unsafe operand. - auto OISIt = OpSafeForPHIOfOps.find(OrigI); - if (OISIt != OpSafeForPHIOfOps.end()) { - if (!OISIt->second) { - OpSafeForPHIOfOps.insert({V, false}); - return false; - } - continue; - } - if (!Visited.insert(Op).second) - continue; - Worklist.push_back(cast(Op)); - } - return true; -} - // Return true if this operand will be safe to use for phi of ops. // // The reason some operands are unsafe is that we are not trying to recursively @@ -2635,13 +2580,56 @@ // be determined to be constant. bool NewGVN::OpIsSafeForPHIOfOps(Value *V, const BasicBlock *PHIBlock, SmallPtrSetImpl &Visited) { - SmallVector Worklist; - if (!OpIsSafeForPHIOfOpsHelper(V, PHIBlock, Visited, Worklist)) - return false; + SmallVector Worklist; + Worklist.push_back(V); while (!Worklist.empty()) { auto *I = Worklist.pop_back_val(); - if (!OpIsSafeForPHIOfOpsHelper(I, PHIBlock, Visited, Worklist)) + if (!isa(I)) + continue; + + auto OISIt = OpSafeForPHIOfOps.find(I); + if (OISIt != OpSafeForPHIOfOps.end()) + return OISIt->second; + + // Keep walking until we either dominate the phi block, or hit a phi, or run + // out of things to check. + if (DT->properlyDominates(getBlockForValue(I), PHIBlock)) { + OpSafeForPHIOfOps.insert({I, true}); + continue; + } + // PHI in the same block. + if (isa(I) && getBlockForValue(I) == PHIBlock) { + OpSafeForPHIOfOps.insert({I, false}); + return false; + } + + auto *OrigI = cast(I); + // When we hit an instruction that reads memory (load, call, etc), we must + // consider any store that may happen in the loop. For now, we assume the + // worst: there is a store in the loop that alias with this read. + // The case where the load is outside the loop is already covered by the + // dominator check above. + // TODO: relax this condition + if (OrigI->mayReadFromMemory()) return false; + + // Check the operands of the current instruction. + for (auto *Op : OrigI->operand_values()) { + if (!isa(Op)) + continue; + // Stop now if we find an unsafe operand. + auto OISIt = OpSafeForPHIOfOps.find(OrigI); + if (OISIt != OpSafeForPHIOfOps.end()) { + if (!OISIt->second) { + OpSafeForPHIOfOps.insert({I, false}); + return false; + } + continue; + } + if (!Visited.insert(Op).second) + continue; + Worklist.push_back(cast(Op)); + } } OpSafeForPHIOfOps.insert({V, true}); return true;