Index: lib/Analysis/GlobalsModRef.cpp =================================================================== --- lib/Analysis/GlobalsModRef.cpp +++ lib/Analysis/GlobalsModRef.cpp @@ -666,14 +666,13 @@ // non-addr-taken globals. continue; } - if (auto *LI = dyn_cast(Input)) { - // A pointer loaded from a global would have been captured, and we know - // that the global is non-escaping, so no alias. - if (isa(GetUnderlyingObject(LI->getPointerOperand(), DL))) - continue; - - // Otherwise, a load could come from anywhere, so bail. - return false; + if (isa(Input)) { + // For a loaded pointer to alias with a an object, it must contain the + // address of that object plus some offset inside the object. As we know + // the object in this case has never had its address taken, its address + // cannot have ended up in memory to be loaded and therefore the loaded + // value does not alias with the non-addr-taken global. + continue; } // Recurse through a limited number of selects and PHIs. This is an Index: test/Analysis/GlobalsModRef/nonescaping-noalias.ll =================================================================== --- test/Analysis/GlobalsModRef/nonescaping-noalias.ll +++ test/Analysis/GlobalsModRef/nonescaping-noalias.ll @@ -97,3 +97,20 @@ %v = load i32, i32* @g1 ret i32 %v } + +define i32 @test5(i32** %param) { +; Ensure that we can fold a store to a load of a global across a store to +; a parameter that has been dereferenced when the global is non-escaping. +; +; CHECK-LABEL: @test5( +; CHECK: %p = load i32* +; CHECK: store i32 42, i32* @g1 +; CHECK-NOT: load i32 +; CHECK: ret i32 42 +entry: + %p = load i32*, i32** %param + store i32 42, i32* @g1 + store i32 7, i32* %p + %v = load i32, i32* @g1 + ret i32 %v +}