Index: llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp =================================================================== --- llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp +++ llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp @@ -41,6 +41,20 @@ STATISTIC(NumReadMemFunctions, "Number of functions that only read memory"); STATISTIC(NumIndirectGlobalVars, "Number of indirect global objects"); +// An option to enable unsafe alias results from the GlobalsModRef analysis. +// When enabled, GlobalsModRef will provide no-alias results which in extremely +// rare cases may not be conservatively correct. In particular, in the face of +// transforms which cause assymetry between how effective GetUnderlyingObject +// is for two pointers, it may produce incorrect results. +// +// These unsafe results have been returned by GMR for many years without +// causing significant issues in the wild and so we provide a mechanism to +// re-enable them for users of LLVM that have a particular performance +// sensitivity and no known issues. The option also makes it easy to evaluate +// the performance impact of these results. +static cl::opt EnableUnsafeGlobalsModRefAliasResults( + "enable-unsafe-globalsmodref-alias-results", cl::init(false), cl::Hidden); + namespace { /// FunctionRecord - One instance of this structure is stored for every /// function in the program. Later, the entries for these functions are @@ -508,10 +522,17 @@ GV2 = nullptr; // If the two pointers are derived from two different non-addr-taken - // globals, or if one is and the other isn't, we know these can't alias. - if ((GV1 || GV2) && GV1 != GV2) + // globals we know these can't alias. + if (GV1 && GV2 && GV1 != GV2) return NoAlias; + // If one is and the other isn't, it isn't strictly safe but we can fake + // this result if necessary for performance. This does not appear to be + // a common problem in practice. + if (EnableUnsafeGlobalsModRefAliasResults) + if ((GV1 || GV2) && GV1 != GV2) + return NoAlias; + // Otherwise if they are both derived from the same addr-taken global, we // can't know the two accesses don't overlap. } @@ -537,12 +558,18 @@ GV2 = AllocsForIndirectGlobals[UV2]; // Now that we know whether the two pointers are related to indirect globals, - // use this to disambiguate the pointers. If either pointer is based on an - // indirect global and if they are not both based on the same indirect global, - // they cannot alias. - if ((GV1 || GV2) && GV1 != GV2) + // use this to disambiguate the pointers. If the pointers are based on + // different indirect globals they cannot alias. + if (GV1 && GV2 && GV1 != GV2) return NoAlias; + // If one is based on an indirect global and the other isn't, it isn't + // strictly safe but we can fake this result if necessary for performance. + // This does not appear to be a common problem in practice. + if (EnableUnsafeGlobalsModRefAliasResults) + if ((GV1 || GV2) && GV1 != GV2) + return NoAlias; + return AliasAnalysis::alias(LocA, LocB); } Index: llvm/trunk/test/Analysis/GlobalsModRef/aliastest.ll =================================================================== --- llvm/trunk/test/Analysis/GlobalsModRef/aliastest.ll +++ llvm/trunk/test/Analysis/GlobalsModRef/aliastest.ll @@ -1,4 +1,7 @@ -; RUN: opt < %s -basicaa -globalsmodref-aa -gvn -S | FileCheck %s +; RUN: opt < %s -basicaa -globalsmodref-aa -gvn -S -enable-unsafe-globalsmodref-alias-results | FileCheck %s +; +; Note that this test relies on an unsafe feature of GlobalsModRef. While this +; test is correct and safe, GMR's technique for handling this isn't generally. @X = internal global i32 4 ; [#uses=1] Index: llvm/trunk/test/Analysis/GlobalsModRef/indirect-global.ll =================================================================== --- llvm/trunk/test/Analysis/GlobalsModRef/indirect-global.ll +++ llvm/trunk/test/Analysis/GlobalsModRef/indirect-global.ll @@ -1,4 +1,7 @@ -; RUN: opt < %s -basicaa -globalsmodref-aa -gvn -instcombine -S | FileCheck %s +; RUN: opt < %s -basicaa -globalsmodref-aa -gvn -instcombine -S -enable-unsafe-globalsmodref-alias-results | FileCheck %s +; +; Note that this test relies on an unsafe feature of GlobalsModRef. While this +; test is correct and safe, GMR's technique for handling this isn't generally. @G = internal global i32* null ; [#uses=3]