Index: lib/Analysis/IPA/GlobalsModRef.cpp =================================================================== --- lib/Analysis/IPA/GlobalsModRef.cpp +++ lib/Analysis/IPA/GlobalsModRef.cpp @@ -304,40 +304,63 @@ // Walk the user list of the global. If we find anything other than a direct // load or store, bail out. - for (User *U : GV->users()) { - if (LoadInst *LI = dyn_cast(U)) { - // The pointer loaded from the global can only be used in simple ways: - // we allow addressing of it and loading storing to it. We do *not* allow - // storing the loaded pointer somewhere else or passing to a function. - std::vector ReadersWriters; - if (AnalyzeUsesOfPointer(LI, ReadersWriters, ReadersWriters)) - return false; // Loaded pointer escapes. - // TODO: Could try some IP mod/ref of the loaded pointer. - } else if (StoreInst *SI = dyn_cast(U)) { - // Storing the global itself. - if (SI->getOperand(0) == GV) return false; - - // If storing the null pointer, ignore it. - if (isa(SI->getOperand(0))) + SmallVector Users; + SmallPtrSet Visited; + Users.push_back(GV); + Visited.insert(GV); + while (!Users.empty()) { + Value *V = Users.pop_back_val(); + for (User *U : V->users()) { + // Recurse through no-op GEPs and bitcasts. + if (auto *GEP = dyn_cast(U)) { + if (!GEP->hasAllZeroIndices()) + return false; + if (Visited.insert(GEP)) + Users.push_back(GEP); continue; + } + if (Operator::getOpcode(U) == Instruction::BitCast) { + if (Visited.insert(U)) + Users.push_back(U); + continue; + } - // Check the value being stored. - Value *Ptr = GetUnderlyingObject(SI->getOperand(0)); - - if (!isAllocLikeFn(Ptr, TLI)) - return false; // Too hard to analyze. - - // Analyze all uses of the allocation. If any of them are used in a - // non-simple way (e.g. stored to another global) bail out. - std::vector ReadersWriters; - if (AnalyzeUsesOfPointer(Ptr, ReadersWriters, ReadersWriters, GV)) - return false; // Loaded pointer escapes. - - // Remember that this allocation is related to the indirect global. - AllocRelatedValues.push_back(Ptr); - } else { - // Something complex, bail out. - return false; + if (LoadInst *LI = dyn_cast(U)) { + // The pointer loaded from the global can only be used in simple ways: + // we allow addressing of it and loading storing to it. We do *not* + // allow storing the loaded pointer somewhere else or passing to + // a function. + std::vector ReadersWriters; + if (AnalyzeUsesOfPointer(LI, ReadersWriters, ReadersWriters)) + return false; // Loaded pointer escapes. + // TODO: Could try some IP mod/ref of the loaded pointer. + } else if (StoreInst *SI = dyn_cast(U)) { + // Storing the global itself. + if (SI->getOperand(0) == GV) + return false; + + // If storing the null pointer, ignore it. + if (isa(SI->getOperand(0))) + continue; + + // Check the value being stored. + Value *Ptr = GetUnderlyingObject(SI->getOperand(0)); + + if (!isAllocLikeFn(Ptr, TLI)) + return false; // Too hard to analyze. + + // Analyze all uses of the allocation. If any of them are used in + // a non-simple way (e.g. stored to another global) bail out. + std::vector ReadersWriters; + if (AnalyzeUsesOfPointer(Ptr, ReadersWriters, ReadersWriters, GV)) + return false; // Loaded pointer escapes. + + // Remember that this allocation is related to the indirect global. + AllocRelatedValues.push_back(Ptr); + } else { + // Something complex, bail out. + return false; + } } } @@ -508,11 +531,13 @@ // is a direct load from an indirect global. GV1 = GV2 = nullptr; if (const LoadInst *LI = dyn_cast(UV1)) - if (GlobalVariable *GV = dyn_cast(LI->getOperand(0))) + if (GlobalVariable *GV = + dyn_cast(LI->getOperand(0)->stripPointerCasts())) if (IndirectGlobals.count(GV)) GV1 = GV; if (const LoadInst *LI = dyn_cast(UV2)) - if (const GlobalVariable *GV = dyn_cast(LI->getOperand(0))) + if (const GlobalVariable *GV = + dyn_cast(LI->getOperand(0)->stripPointerCasts())) if (IndirectGlobals.count(GV)) GV2 = GV;