diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -1571,6 +1571,7 @@ // Invariants BUILTIN(__builtin_assume, "vb", "nE") +BUILTIN(__builtin_assume_separate_storage, "vvCD*vCD*", "nE") // Multiprecision Arithmetic Builtins. BUILTIN(__builtin_addcb, "UcUcCUcCUcCUc*", "n") diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13384,6 +13384,7 @@ bool SemaBuiltinArithmeticFence(CallExpr *TheCall); bool SemaBuiltinAssume(CallExpr *TheCall); bool SemaBuiltinAssumeAligned(CallExpr *TheCall); + bool SemaBuiltinAssumeSeparateStorage(CallExpr *TheCall); bool SemaBuiltinLongjmp(CallExpr *TheCall); bool SemaBuiltinSetjmp(CallExpr *TheCall); ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult); diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2808,6 +2808,21 @@ Builder.CreateCall(FnAssume, ArgValue); return RValue::get(nullptr); } + case Builtin::BI__builtin_assume_separate_storage: { + // We copy __builtin_assume's semantics and don't let side-effecting + // expressions do anything. Maybe this is the wrong thing? + const Expr *Arg0 = E->getArg(0); + const Expr *Arg1 = E->getArg(1); + + Value *Value0 = EmitScalarExpr(Arg0); + Value *Value1 = EmitScalarExpr(Arg1); + + Value *Values[] = {Value0, Value1}; + OperandBundleDefT OBD("separate_storage", Values); + Builder.CreateAssumption(ConstantInt::getTrue(getLLVMContext()), {OBD}); + return RValue::get(nullptr); + } + case Builtin::BI__arithmetic_fence: { // Create the builtin call if FastMath is selected, and the target // supports the builtin, otherwise just return the argument. diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2169,6 +2169,10 @@ if (SemaBuiltinAssumeAligned(TheCall)) return ExprError(); break; + case Builtin::BI__builtin_assume_separate_storage: + if (SemaBuiltinAssumeSeparateStorage(TheCall)) + return ExprError(); + break; case Builtin::BI__builtin_dynamic_object_size: case Builtin::BI__builtin_object_size: if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3)) @@ -7732,6 +7736,11 @@ return false; } +/// Handle __builtin_assume_separate_storage. For now this is a no-op, but +/// eventually we expect an optional multi-arg variadic version (to handle an +/// excluded range). +bool Sema::SemaBuiltinAssumeSeparateStorage(CallExpr *TheCall) { return false; } + bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) { unsigned BuiltinID = cast(TheCall->getCalleeDecl())->getBuiltinID(); diff --git a/clang/test/CodeGen/builtin-assume-separate-storage.c b/clang/test/CodeGen/builtin-assume-separate-storage.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/builtin-assume-separate-storage.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s +void *nonconst(void); + +// CHECK-LABEL: @test1 +void test1(int *a, int *b) { + // CHECK: store ptr %a, ptr [[A_ADDR:%.+]], align + // CHECK: store ptr %b, ptr [[B_ADDR:%.+]], align + // CHECK: [[A:%.+]] = load ptr, ptr [[A_ADDR]] + // CHECK: [[B:%.+]] = load ptr, ptr [[B_ADDR]] + + // CHECK: call void @llvm.assume(i1 true) [ "separate_storage"(ptr [[A]], ptr [[B]]) ] + __builtin_assume_separate_storage(a, b); +} + +// Separate storage assumptions evaluate their arguments unconditionally, like +// assume_aligned but *unlike* assume. Check that we actually do so. +// CHECK-LABEL: @test2 +void test2(int *a, int *b) { + // CHECK: call ptr @nonconst() + // CHECK: call void @llvm.assume + __builtin_assume_separate_storage(a, nonconst()); +} diff --git a/clang/test/Sema/builtin-assume-separate-storage.c b/clang/test/Sema/builtin-assume-separate-storage.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/builtin-assume-separate-storage.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s + +void *nonconst(void); + +void test1(int *a, int *b) { + __builtin_assume_separate_storage(a, b); + // Separate storage assumptions evaluate their arguments unconditionally, like + // assume_aligned but *unlike* assume. Check that we don't warn on it. + __builtin_assume_separate_storage(a, nonconst()); + __builtin_assume_separate_storage(nonconst(), a); + __builtin_assume_separate_storage(a, 3); // expected-error {{incompatible integer to pointer conversion}} + __builtin_assume_separate_storage(3, a); // expected-error {{incompatible integer to pointer conversion}} +} diff --git a/llvm/include/llvm-c/Transforms/Scalar.h b/llvm/include/llvm-c/Transforms/Scalar.h --- a/llvm/include/llvm-c/Transforms/Scalar.h +++ b/llvm/include/llvm-c/Transforms/Scalar.h @@ -149,6 +149,9 @@ /** See llvm::createTypeBasedAliasAnalysisPass function */ void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM); +/** See llvm::createSeparateStorageAliasAnalysisPass function */ +void LLVMAddSeparateStorageAliasAnalysisPass(LLVMPassManagerRef PM); + /** See llvm::createScopedNoAliasAAPass function */ void LLVMAddScopedNoAliasAAPass(LLVMPassManagerRef PM); diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h --- a/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -901,7 +901,8 @@ SmallVector ResultGetters; + 5> + ResultGetters; template static void getFunctionAAResultImpl(Function &F, diff --git a/llvm/include/llvm/Analysis/SeparateStorageAliasAnalysis.h b/llvm/include/llvm/Analysis/SeparateStorageAliasAnalysis.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/Analysis/SeparateStorageAliasAnalysis.h @@ -0,0 +1,70 @@ +//===- SeparateStorageAliasAnalysis.h ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +// Interface to the separate storage alias analysis pass. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SEPARATESTORAGEALIASANALYSIS +#define LLVM_ANALYSIS_SEPARATESTORAGEALIASANALYSIS + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" + +namespace llvm { +class AssumptionCache; +class DominatorTree; + +/// A simple AA result that uses calls to the separate storage intrinsics. +class SeparateStorageAAResult : public AAResultBase { +public: + SeparateStorageAAResult(AssumptionCache &AC, DominatorTree &DT); + bool invalidate(Function &Fn, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI, const Instruction *I); + +private: + AssumptionCache &AC; + DominatorTree &DT; +}; + +/// Analysis pass providing a never-invalidated alias analysis result. +class SeparateStorageAA : public AnalysisInfoMixin { + friend AnalysisInfoMixin; + + static AnalysisKey Key; + +public: + using Result = SeparateStorageAAResult; + + SeparateStorageAAResult run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Legacy wrapper pass to provide the SeparateStorageAAResult object. +class SeparateStorageAAWrapperPass : public FunctionPass { + std::unique_ptr Result; + +public: + static char ID; + + SeparateStorageAAWrapperPass(); + + SeparateStorageAAResult &getResult() { return *Result; } + const SeparateStorageAAResult &getResult() const { return *Result; } + + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +FunctionPass *createSeparateStorageAAWrapperPass(); +} // namespace llvm + +#endif // LLVM_ANALYSIS_SEPARATESTORAGEALIASANALYSIS diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -708,6 +708,7 @@ ATTR_KIND_FNRETTHUNK_EXTERN = 84, ATTR_KIND_SKIP_PROFILE = 85, ATTR_KIND_MEMORY = 86, + ATTR_KIND_SEPARATE_STORAGE = 87, }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h --- a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h +++ b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h @@ -22,6 +22,7 @@ #include "llvm/Analysis/CFLAndersAliasAnalysis.h" #include "llvm/Analysis/CFLSteensAliasAnalysis.h" #include "llvm/Analysis/ScopedNoAliasAA.h" +#include "llvm/Analysis/SeparateStorageAliasAnalysis.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/CodeGen/ExpandReductions.h" @@ -508,6 +509,7 @@ // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that // BasicAliasAnalysis wins if they disagree. This is intended to help // support "obvious" type-punning idioms. + AA.registerFunctionAnalysis(); AA.registerFunctionAnalysis(); AA.registerFunctionAnalysis(); AA.registerFunctionAnalysis(); diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -178,6 +178,10 @@ /// Function should not be instrumented. def NoProfile : EnumAttr<"noprofile", [FnAttr]>; +/// As an operand bundle on an assume intrinsic, Indicates that its two pointer +/// operands do not alias. +def SeparateStorage : EnumAttr<"separate_storage", [ParamAttr]>; + /// This function should not be instrumented but it is ok to inline profiled // functions into it. def SkipProfile : EnumAttr<"skipprofile", [FnAttr]>; diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -370,6 +370,7 @@ void initializeSafeStackLegacyPassPass(PassRegistry&); void initializeSafepointIRVerifierPass(PassRegistry&); void initializeSelectOptimizePass(PassRegistry &); +void initializeSeparateStorageAAWrapperPassPass(PassRegistry &); void initializeScalarEvolutionWrapperPassPass(PassRegistry&); void initializeScalarizeMaskedMemIntrinLegacyPassPass(PassRegistry &); void initializeScalarizerLegacyPassPass(PassRegistry&); diff --git a/llvm/include/llvm/LinkAllPasses.h b/llvm/include/llvm/LinkAllPasses.h --- a/llvm/include/llvm/LinkAllPasses.h +++ b/llvm/include/llvm/LinkAllPasses.h @@ -32,6 +32,7 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/ScopedNoAliasAA.h" +#include "llvm/Analysis/SeparateStorageAliasAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/CodeGen/Passes.h" @@ -85,6 +86,7 @@ (void) llvm::createCFGSimplificationPass(); (void) llvm::createCFLAndersAAWrapperPass(); (void) llvm::createCFLSteensAAWrapperPass(); + (void)llvm::createSeparateStorageAAWrapperPass(); (void) llvm::createStructurizeCFGPass(); (void) llvm::createLibCallsShrinkWrapPass(); (void) llvm::createCalledValuePropagationPass(); diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp --- a/llvm/lib/Analysis/AliasAnalysis.cpp +++ b/llvm/lib/Analysis/AliasAnalysis.cpp @@ -34,6 +34,7 @@ #include "llvm/Analysis/ObjCARCAliasAnalysis.h" #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/ScopedNoAliasAA.h" +#include "llvm/Analysis/SeparateStorageAliasAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/Analysis/ValueTracking.h" @@ -769,6 +770,7 @@ INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass) INITIALIZE_PASS_DEPENDENCY(ScopedNoAliasAAWrapperPass) INITIALIZE_PASS_DEPENDENCY(TypeBasedAAWrapperPass) +INITIALIZE_PASS_DEPENDENCY(SeparateStorageAAWrapperPass) INITIALIZE_PASS_END(AAResultsWrapperPass, "aa", "Function Alias Analysis Results", false, true) @@ -806,6 +808,9 @@ AAR->addAAResult(WrapperPass->getResult()); if (auto *WrapperPass = getAnalysisIfAvailable()) AAR->addAAResult(WrapperPass->getResult()); + if (auto *WrapperPass = + getAnalysisIfAvailable()) + AAR->addAAResult(WrapperPass->getResult()); if (auto *WrapperPass = getAnalysisIfAvailable()) AAR->addAAResult(WrapperPass->getResult()); if (auto *WrapperPass = getAnalysisIfAvailable()) @@ -836,6 +841,7 @@ // the legacy pass manager. AU.addUsedIfAvailable(); AU.addUsedIfAvailable(); + AU.addUsedIfAvailable(); AU.addUsedIfAvailable(); AU.addUsedIfAvailable(); AU.addUsedIfAvailable(); @@ -864,6 +870,9 @@ AAR.addAAResult(WrapperPass->getResult()); if (auto *WrapperPass = P.getAnalysisIfAvailable()) AAR.addAAResult(WrapperPass->getResult()); + if (auto *WrapperPass = + P.getAnalysisIfAvailable()) + AAR.addAAResult(WrapperPass->getResult()); if (auto *WrapperPass = P.getAnalysisIfAvailable()) AAR.addAAResult(WrapperPass->getResult()); if (auto *WrapperPass = P.getAnalysisIfAvailable()) @@ -957,6 +966,7 @@ AU.addRequired(); AU.addUsedIfAvailable(); AU.addUsedIfAvailable(); + AU.addUsedIfAvailable(); AU.addUsedIfAvailable(); AU.addUsedIfAvailable(); AU.addUsedIfAvailable(); diff --git a/llvm/lib/Analysis/Analysis.cpp b/llvm/lib/Analysis/Analysis.cpp --- a/llvm/lib/Analysis/Analysis.cpp +++ b/llvm/lib/Analysis/Analysis.cpp @@ -77,6 +77,7 @@ initializeRegionOnlyPrinterPass(Registry); initializeSCEVAAWrapperPassPass(Registry); initializeScalarEvolutionWrapperPassPass(Registry); + initializeSeparateStorageAAWrapperPassPass(Registry); initializeStackSafetyGlobalInfoWrapperPassPass(Registry); initializeStackSafetyInfoWrapperPassPass(Registry); initializeTargetTransformInfoWrapperPassPass(Registry); diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -23,7 +23,7 @@ tensorflow/core/protobuf/error_codes tensorflow/core/example/feature tensorflow/core/example/example) - list(APPEND MLLinkDeps + list(APPEND MLLinkDeps tensorflow-lite::tensorflow-lite protobuf::libprotobuf) else() @@ -136,6 +136,7 @@ ScalarEvolutionAliasAnalysis.cpp ScalarEvolutionDivision.cpp ScalarEvolutionNormalization.cpp + SeparateStorageAliasAnalysis.cpp StackLifetime.cpp StackSafetyAnalysis.cpp SyncDependenceAnalysis.cpp diff --git a/llvm/lib/Analysis/SeparateStorageAliasAnalysis.cpp b/llvm/lib/Analysis/SeparateStorageAliasAnalysis.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Analysis/SeparateStorageAliasAnalysis.cpp @@ -0,0 +1,119 @@ +//===- SeparateStorageAliasAnalysis.cpp -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implements the separate storage alias analysis pass. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/SeparateStorageAliasAnalysis.h" +#include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/InitializePasses.h" +#include "llvm/Support/CommandLine.h" + +using namespace llvm; + +static cl::opt EnableSeparateStorageAA("enable-separate-storage-aa", + cl::Hidden, cl::init(false)); + +AnalysisKey SeparateStorageAA::Key; + +SeparateStorageAAResult::SeparateStorageAAResult(AssumptionCache &AC, + DominatorTree &DT) + : AC(AC), DT(DT) {} + +bool SeparateStorageAAResult::invalidate( + Function &Fn, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv) { + return Inv.invalidate(Fn, PA) || + Inv.invalidate(Fn, PA); +} + +AliasResult SeparateStorageAAResult::alias(const MemoryLocation &LocA, + const MemoryLocation &LocB, + AAQueryInfo &AAQI, + const Instruction *I) { + if (!EnableSeparateStorageAA) + return AliasResult::MayAlias; + + if (!I) + return AliasResult::MayAlias; + + const Value *PtrA = LocA.Ptr; + const Value *PtrB = LocB.Ptr; + if (!PtrA || !PtrB) + return AliasResult::MayAlias; + + const Value *UnderlyingA = getUnderlyingObject(PtrA); + const Value *UnderlyingB = getUnderlyingObject(PtrB); + + for (auto &AssumeVH : AC.assumptions()) { + if (!AssumeVH) + continue; + + AssumeInst *Assume = cast(AssumeVH); + + for (unsigned Idx = 0; Idx < Assume->getNumOperandBundles(); Idx++) { + OperandBundleUse OBU = Assume->getOperandBundleAt(Idx); + if (OBU.getTagName() == "separate_storage") { + assert(OBU.Inputs.size() == 2); + const Value *HintA = OBU.Inputs[0].get(); + const Value *HintB = OBU.Inputs[1].get(); + const Value *UnderlyingHintA = getUnderlyingObject(HintA); + const Value *UnderlyingHintB = getUnderlyingObject(HintB); + + if (((UnderlyingA == UnderlyingHintA && + UnderlyingB == UnderlyingHintB) || + (UnderlyingA == UnderlyingHintB && + UnderlyingB == UnderlyingHintA)) && + isValidAssumeForContext(Assume, I, &DT)) + return AliasResult::NoAlias; + break; + } + } + } + return AliasResult::MayAlias; +} + +SeparateStorageAAResult SeparateStorageAA::run(Function &F, + FunctionAnalysisManager &AM) { + auto &AC = AM.getResult(F); + auto &DT = AM.getResult(F); + return SeparateStorageAAResult(AC, DT); +} + +char SeparateStorageAAWrapperPass::ID = 0; +INITIALIZE_PASS(SeparateStorageAAWrapperPass, "separatestorage-aa", + "Separate Storage Alias Analysis", false, true) + +FunctionPass *llvm::createSeparateStorageAAWrapperPass() { + return new SeparateStorageAAWrapperPass(); +} + +SeparateStorageAAWrapperPass::SeparateStorageAAWrapperPass() + : FunctionPass(ID) { + initializeSeparateStorageAAWrapperPassPass(*PassRegistry::getPassRegistry()); +} + +bool SeparateStorageAAWrapperPass::runOnFunction(Function &F) { + auto &ACT = getAnalysis(); + auto &DTWP = getAnalysis(); + + Result.reset(new SeparateStorageAAResult(ACT.getAssumptionCache(F), + DTWP.getDomTree())); + return false; +} + +void SeparateStorageAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); +} diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -742,6 +742,8 @@ return bitc::ATTR_KIND_RETURNED; case Attribute::ReturnsTwice: return bitc::ATTR_KIND_RETURNS_TWICE; + case Attribute::SeparateStorage: + return bitc::ATTR_KIND_SEPARATE_STORAGE; case Attribute::SExt: return bitc::ATTR_KIND_S_EXT; case Attribute::Speculatable: diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -20,6 +20,7 @@ #include "llvm/Analysis/CFLSteensAliasAnalysis.h" #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/ScopedNoAliasAA.h" +#include "llvm/Analysis/SeparateStorageAliasAnalysis.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h" @@ -876,6 +877,7 @@ // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that // BasicAliasAnalysis wins if they disagree. This is intended to help // support "obvious" type-punning idioms. + addPass(createSeparateStorageAAWrapperPass()); addPass(createTypeBasedAAWrapperPass()); addPass(createScopedNoAliasAAWrapperPass()); addPass(createBasicAAWrapperPass()); diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -4977,6 +4977,15 @@ "third argument should be an integer if present", Call); return; } + if (Kind == Attribute::SeparateStorage) { + Check(ArgCount == 2, + "separate_storage assumptions should have 2 arguments", Call); + Check(Call.getOperand(Elem.Begin)->getType()->isPointerTy() && + Call.getOperand(Elem.Begin + 1)->getType()->isPointerTy(), + "arguments to separate_storage assumptions should be pointers", + Call); + return; + } Check(ArgCount <= 2, "too many arguments", Call); if (Kind == Attribute::None) break; diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -68,6 +68,7 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/ScopedNoAliasAA.h" +#include "llvm/Analysis/SeparateStorageAliasAnalysis.h" #include "llvm/Analysis/StackLifetime.h" #include "llvm/Analysis/StackSafetyAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -22,6 +22,7 @@ #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/Analysis/ScopedNoAliasAA.h" +#include "llvm/Analysis/SeparateStorageAliasAnalysis.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/IR/PassManager.h" #include "llvm/Passes/OptimizationLevel.h" @@ -1975,6 +1976,7 @@ // information about aliasing. AA.registerFunctionAnalysis(); AA.registerFunctionAnalysis(); + AA.registerFunctionAnalysis(); // Add support for querying global aliasing information when available. // Because the `AAManager` is a function analysis and `GlobalsAA` is a module diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -247,6 +247,7 @@ FUNCTION_ALIAS_ANALYSIS("objc-arc-aa", objcarc::ObjCARCAA()) FUNCTION_ALIAS_ANALYSIS("scev-aa", SCEVAA()) FUNCTION_ALIAS_ANALYSIS("scoped-noalias-aa", ScopedNoAliasAA()) +FUNCTION_ALIAS_ANALYSIS("separatestorage-aa", SeparateStorageAA()) FUNCTION_ALIAS_ANALYSIS("tbaa", TypeBasedAA()) #undef FUNCTION_ALIAS_ANALYSIS #undef FUNCTION_ANALYSIS diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -19,6 +19,7 @@ #include "llvm/Analysis/CFLSteensAliasAnalysis.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/ScopedNoAliasAA.h" +#include "llvm/Analysis/SeparateStorageAliasAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/IR/LegacyPassManager.h" @@ -131,6 +132,7 @@ // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that // BasicAliasAnalysis wins if they disagree. This is intended to help // support "obvious" type-punning idioms. + PM.add(createSeparateStorageAAWrapperPass()); PM.add(createTypeBasedAAWrapperPass()); PM.add(createScopedNoAliasAAWrapperPass()); } diff --git a/llvm/lib/Transforms/Scalar/Scalar.cpp b/llvm/lib/Transforms/Scalar/Scalar.cpp --- a/llvm/lib/Transforms/Scalar/Scalar.cpp +++ b/llvm/lib/Transforms/Scalar/Scalar.cpp @@ -17,6 +17,7 @@ #include "llvm-c/Transforms/Scalar.h" #include "llvm/Analysis/BasicAliasAnalysis.h" #include "llvm/Analysis/ScopedNoAliasAA.h" +#include "llvm/Analysis/SeparateStorageAliasAnalysis.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Verifier.h" @@ -278,6 +279,10 @@ unwrap(PM)->add(createTypeBasedAAWrapperPass()); } +void LLVMAddSeparateStorageAnalysisPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createSeparateStorageAAWrapperPass()); +} + void LLVMAddScopedNoAliasAAPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createScopedNoAliasAAWrapperPass()); } diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -981,6 +981,7 @@ case Attribute::ReadNone: case Attribute::ReadOnly: case Attribute::Returned: + case Attribute::SeparateStorage: case Attribute::SExt: case Attribute::StructRet: case Attribute::SwiftError: diff --git a/llvm/test/Analysis/SeparateStorageAliasAnalysis/alias_test.ll b/llvm/test/Analysis/SeparateStorageAliasAnalysis/alias_test.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/SeparateStorageAliasAnalysis/alias_test.ll @@ -0,0 +1,122 @@ +; RUN: opt < %s -aa-pipeline=separatestorage-aa,basic-aa -gvn -enable-separate-storage-aa -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +declare void @llvm.assume(i1) + +; Test basic queries. + +; CHECK-LAEBL: @simple_no +; CHECK: ret i8 %loadofstore +define i8 @simple_no(ptr %p1, ptr %p2) { +entry: + store i8 0, ptr %p1 + store i8 1, ptr %p2 + %loadofstore = load i8, ptr %p1 + ret i8 %loadofstore +} + +; CHECK-LABEL: @simple_yes +; CHECK: ret i8 0 +define i8 @simple_yes(ptr %p1, ptr %p2) { +entry: + call void @llvm.assume(i1 1) ["separate_storage"(ptr %p1, ptr %p2)] + store i8 0, ptr %p1 + store i8 1, ptr %p2 + %loadofstore = load i8, ptr %p1 + ret i8 %loadofstore +} + +; CHECK-LABEL: @ptr_to_ptr_no +; CHECK: ret i8 %loadofstore +define i8 @ptr_to_ptr_no(ptr %pp) { +entry: + %p_base = load ptr, ptr %pp + store i8 0, ptr %p_base + %p_base2 = load ptr, ptr %pp + %loadofstore = load i8, ptr %p_base2 + ret i8 %loadofstore +} + +; CHECK-LABEL: @ptr_to_ptr_yes +; CHECK: ret i8 0 +define i8 @ptr_to_ptr_yes(ptr %pp) { +entry: + %p_base = load ptr, ptr %pp + call void @llvm.assume(i1 1) ["separate_storage"(ptr %p_base, ptr %pp)] + store i8 0, ptr %p_base + %p_base2 = load ptr, ptr %pp + %loadofstore = load i8, ptr %p_base2 + ret i8 %loadofstore +} + +; The analysis should only kick in if executed (or will be executed) at the +; given program point. + +; CHECK-LABEL: @flow_sensitive +; CHECK: %loadofstore = phi i8 [ %loadofstore_true, %true_branch ], [ 33, %false_branch ] +define i8 @flow_sensitive(ptr %p1, ptr %p2, i1 %cond) { +entry: + br i1 %cond, label %true_branch, label %false_branch + +true_branch: + store i8 11, ptr %p1 + store i8 22, ptr %p2 + %loadofstore_true = load i8, ptr %p1 + br label %endif + +false_branch: + call void @llvm.assume(i1 1) ["separate_storage"(ptr %p1, ptr %p2)] + store i8 33, ptr %p1 + store i8 44, ptr %p2 + %loadofstore_false = load i8, ptr %p1 + br label %endif + +endif: + %loadofstore = phi i8 [ %loadofstore_true, %true_branch ], [ %loadofstore_false, %false_branch ] + ret i8 %loadofstore +} + +; CHECK-LABEL: @flow_sensitive_with_dominator +; CHECK: %loadofstore = phi i8 [ 11, %true_branch ], [ 33, %false_branch ] +define i8 @flow_sensitive_with_dominator(ptr %p1, ptr %p2, i1 %cond) { +entry: + call void @llvm.assume(i1 1) ["separate_storage"(ptr %p1, ptr %p2)] + br i1 %cond, label %true_branch, label %false_branch + +true_branch: + store i8 11, ptr %p1 + store i8 22, ptr %p2 + %loadofstore_true = load i8, ptr %p1 + br label %endif + +false_branch: + store i8 33, ptr %p1 + store i8 44, ptr %p2 + %loadofstore_false = load i8, ptr %p1 + br label %endif + +endif: + %loadofstore = phi i8 [ %loadofstore_true, %true_branch ], [ %loadofstore_false, %false_branch ] + ret i8 %loadofstore +} + +; Hints are relative to entire regions of storage, not particular pointers +; inside them. We should know that the whole ranges are disjoint given hints at +; offsets. + +; CHECK-LABEL: @offset_agnostic +; CHECK: ret i8 0 +define i8 @offset_agnostic(ptr %p1, ptr %p2) { + %access1 = getelementptr inbounds i8, ptr %p1, i64 12 + %access2 = getelementptr inbounds i8, ptr %p2, i64 34 + + %hint1 = getelementptr inbounds i8, ptr %p1, i64 56 + %hint2 = getelementptr inbounds i8, ptr %p2, i64 78 + call void @llvm.assume(i1 1) ["separate_storage"(ptr %hint1, ptr %hint2)] + + store i8 0, ptr %access1 + store i8 1, ptr %access2 + %loadofstore = load i8, ptr %access1 + ret i8 %loadofstore +} diff --git a/llvm/test/CodeGen/AArch64/O3-pipeline.ll b/llvm/test/CodeGen/AArch64/O3-pipeline.ll --- a/llvm/test/CodeGen/AArch64/O3-pipeline.ll +++ b/llvm/test/CodeGen/AArch64/O3-pipeline.ll @@ -49,6 +49,7 @@ ; CHECK-NEXT: Loop Pass Manager ; CHECK-NEXT: Loop Invariant Code Motion ; CHECK-NEXT: Module Verifier +; CHECK-NEXT: Separate Storage Alias Analysis ; CHECK-NEXT: Loop Pass Manager ; CHECK-NEXT: Canonicalize Freeze Instructions in Loops ; CHECK-NEXT: Induction Variable Users diff --git a/llvm/test/CodeGen/RISCV/O3-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-pipeline.ll --- a/llvm/test/CodeGen/RISCV/O3-pipeline.ll +++ b/llvm/test/CodeGen/RISCV/O3-pipeline.ll @@ -30,6 +30,7 @@ ; CHECK-NEXT: RISCV gather/scatter lowering ; CHECK-NEXT: RISCV CodeGenPrepare ; CHECK-NEXT: Module Verifier +; CHECK-NEXT: Separate Storage Alias Analysis ; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: Scalar Evolution Analysis diff --git a/llvm/test/CodeGen/X86/opt-pipeline.ll b/llvm/test/CodeGen/X86/opt-pipeline.ll --- a/llvm/test/CodeGen/X86/opt-pipeline.ll +++ b/llvm/test/CodeGen/X86/opt-pipeline.ll @@ -16,9 +16,9 @@ ; CHECK-NEXT: Target Pass Configuration ; CHECK-NEXT: Machine Module Information ; CHECK-NEXT: Target Transform Information +; CHECK-NEXT: Assumption Cache Tracker ; CHECK-NEXT: Type-Based Alias Analysis ; CHECK-NEXT: Scoped NoAlias Alias Analysis -; CHECK-NEXT: Assumption Cache Tracker ; CHECK-NEXT: Profile summary info ; CHECK-NEXT: Create Garbage Collector Module Metadata ; CHECK-NEXT: Machine Branch Probability Analysis @@ -33,6 +33,7 @@ ; CHECK-NEXT: Lower AMX type for load/store ; CHECK-NEXT: Module Verifier ; CHECK-NEXT: Dominator Tree Construction +; CHECK-NEXT: Separate Storage Alias Analysis ; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: Canonicalize natural loops diff --git a/llvm/test/Other/new-pass-manager.ll b/llvm/test/Other/new-pass-manager.ll --- a/llvm/test/Other/new-pass-manager.ll +++ b/llvm/test/Other/new-pass-manager.ll @@ -251,6 +251,7 @@ ; CHECK-AA-DEFAULT: Running analysis: BasicAA ; CHECK-AA-DEFAULT: Running analysis: ScopedNoAliasAA ; CHECK-AA-DEFAULT: Running analysis: TypeBasedAA +; CHECK-AA-DEFAULT: Running analysis: SeparateStorageAA ; RUN: opt -disable-output -disable-verify -verify-cfg-preserved=1 -debug-pass-manager %s 2>&1 \ ; RUN: -passes='require,invalidate,aa-eval' -aa-pipeline='basic-aa' \ @@ -352,6 +353,7 @@ ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: BasicAA ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: ScopedNoAliasAA ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: TypeBasedAA +; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: SeparateStorageAA ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: OuterAnalysisManagerProxy ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: ScalarEvolutionAnalysis ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll --- a/llvm/test/Other/new-pm-defaults.ll +++ b/llvm/test/Other/new-pm-defaults.ll @@ -118,6 +118,7 @@ ; CHECK-O-NEXT: Running analysis: BasicAA ; CHECK-O-NEXT: Running analysis: ScopedNoAliasAA ; CHECK-O-NEXT: Running analysis: TypeBasedAA +; CHECK-O-NEXT: Running analysis: SeparateStorageAA ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy ; CHECK-EP-PEEPHOLE-NEXT: Running pass: NoOpFunctionPass ; CHECK-O-NEXT: Running pass: SimplifyCFGPass diff --git a/llvm/test/Other/new-pm-lto-defaults.ll b/llvm/test/Other/new-pm-lto-defaults.ll --- a/llvm/test/Other/new-pm-lto-defaults.ll +++ b/llvm/test/Other/new-pm-lto-defaults.ll @@ -66,6 +66,7 @@ ; CHECK-O1-NEXT: Running analysis: DominatorTreeAnalysis ; CHECK-O-NEXT: Running analysis: ScopedNoAliasAA ; CHECK-O-NEXT: Running analysis: TypeBasedAA +; CHECK-O-NEXT: Running analysis: SeparateStorageAA ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy ; CHECK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: CallGraphAnalysis diff --git a/llvm/test/Other/new-pm-thinlto-defaults.ll b/llvm/test/Other/new-pm-thinlto-defaults.ll --- a/llvm/test/Other/new-pm-thinlto-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-defaults.ll @@ -96,6 +96,7 @@ ; CHECK-O-NEXT: Running analysis: BasicAA ; CHECK-O-NEXT: Running analysis: ScopedNoAliasAA ; CHECK-O-NEXT: Running analysis: TypeBasedAA +; CHECK-O-NEXT: Running analysis: SeparateStorageAA ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running pass: ModuleInlinerWrapperPass diff --git a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll --- a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll @@ -53,6 +53,7 @@ ; CHECK-O-NEXT: Running analysis: BasicAA ; CHECK-O-NEXT: Running analysis: ScopedNoAliasAA ; CHECK-O-NEXT: Running analysis: TypeBasedAA +; CHECK-O-NEXT: Running analysis: SeparateStorageAA ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy ; CHECK-O-NEXT: Running analysis: BlockFrequencyAnalysis on foo ; These next two can appear in any order since they are accessed as parameters diff --git a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll --- a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll @@ -50,6 +50,7 @@ ; CHECK-O-NEXT: Running analysis: BasicAA ; CHECK-O-NEXT: Running analysis: ScopedNoAliasAA ; CHECK-O-NEXT: Running analysis: TypeBasedAA +; CHECK-O-NEXT: Running analysis: SeparateStorageAA ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy ; CHECK-O-NEXT: Running pass: SampleProfileLoaderPass ; CHECK-O-NEXT: Running analysis: ProfileSummaryAnalysis diff --git a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll --- a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll @@ -54,6 +54,7 @@ ; CHECK-O-NEXT: Running analysis: BasicAA ; CHECK-O-NEXT: Running analysis: ScopedNoAliasAA ; CHECK-O-NEXT: Running analysis: TypeBasedAA +; CHECK-O-NEXT: Running analysis: SeparateStorageAA ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O123SZ-NEXT: Running pass: ModuleInlinerWrapperPass @@ -107,6 +108,7 @@ ; CHECK-O-NEXT: Running analysis: DominatorTreeAnalysis ; CHECK-O-NEXT: Running analysis: ScopedNoAliasAA ; CHECK-O-NEXT: Running analysis: TypeBasedAA +; CHECK-O-NEXT: Running analysis: SeparateStorageAA ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy ; CHECK-O3-NEXT: Running pass: ArgumentPromotionPass ; CHECK-O2-NEXT: Running pass: OpenMPOptCGSCCPass diff --git a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll --- a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll @@ -48,6 +48,7 @@ ; CHECK-O-NEXT: Running analysis: BasicAA ; CHECK-O-NEXT: Running analysis: ScopedNoAliasAA ; CHECK-O-NEXT: Running analysis: TypeBasedAA +; CHECK-O-NEXT: Running analysis: SeparateStorageAA ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy ; CHECK-O-NEXT: Running pass: SampleProfileLoaderPass ; CHECK-O-NEXT: Running analysis: ProfileSummaryAnalysis diff --git a/llvm/test/Verifier/assume-bundles.ll b/llvm/test/Verifier/assume-bundles.ll --- a/llvm/test/Verifier/assume-bundles.ll +++ b/llvm/test/Verifier/assume-bundles.ll @@ -24,5 +24,9 @@ call void @llvm.assume(i1 true) ["align"(i32* %P, i32* %P2)] ; CHECK: third argument should be an integer if present call void @llvm.assume(i1 true) ["align"(i32* %P, i32 %P1, i32* %P2)] +; CHECK: separate_storage assumptions should have 2 arguments + call void @llvm.assume(i1 true) ["separate_storage"(i32* %P)] +; CHECK: arguments to separate_storage assumptions should be pointers + call void @llvm.assume(i1 true) ["separate_storage"(i32* %P, i32 123)] ret void } diff --git a/llvm/unittests/Analysis/AliasSetTrackerTest.cpp b/llvm/unittests/Analysis/AliasSetTrackerTest.cpp --- a/llvm/unittests/Analysis/AliasSetTrackerTest.cpp +++ b/llvm/unittests/Analysis/AliasSetTrackerTest.cpp @@ -71,7 +71,7 @@ AliasSetTracker AST(AA); for (auto &BB : *Test) AST.add(BB); - // There should be 2 disjoint alias sets. 1 from each call. + // There should be 2 disjoint alias sets. 1 from each call. ASSERT_EQ((int)AST.getAliasSets().size(), 2); // Directly test aliasesUnknownInst. diff --git a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn @@ -116,6 +116,7 @@ "ScalarEvolutionDivision.cpp", "ScalarEvolutionNormalization.cpp", "ScopedNoAliasAA.cpp", + "SeparateStorageAliasAnalysis.cpp", "StackLifetime.cpp", "StackSafetyAnalysis.cpp", "SyncDependenceAnalysis.cpp", diff --git a/polly/lib/CodeGen/CodegenCleanup.cpp b/polly/lib/CodeGen/CodegenCleanup.cpp --- a/polly/lib/CodeGen/CodegenCleanup.cpp +++ b/polly/lib/CodeGen/CodegenCleanup.cpp @@ -50,6 +50,7 @@ // TODO: How to make parent passes discoverable? // TODO: Should be sensitive to compiler options in PassManagerBuilder, to // which we do not have access here. + FPM->add(createSeparateStorageAAWrapperPass()); FPM->add(createScopedNoAliasAAWrapperPass()); FPM->add(createTypeBasedAAWrapperPass()); FPM->add(createAAResultsWrapperPass());