//===- ScalarEvolutionAliasAnalysis.cpp - SCEV-based Alias Analysis -------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the ScalarEvolutionAliasAnalysis pass, which implements a // simple alias analysis implemented in terms of ScalarEvolution queries. // // ScalarEvolution has a more complete understanding of pointer arithmetic // than BasicAliasAnalysis' collection of ad-hoc analyses. // //===----------------------------------------------------------------------===// #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/Passes.h" #include "llvm/Pass.h" #include "llvm/Support/Compiler.h" using namespace llvm; namespace { /// ScalarEvolutionAliasAnalysis - This is a simple alias analysis /// implementation that uses ScalarEvolution to answer queries. class ScalarEvolutionAliasAnalysis : public FunctionPass, public AliasAnalysis { ScalarEvolution *SE; public: static char ID; // Class identification, replacement for typeinfo ScalarEvolutionAliasAnalysis() : FunctionPass(&ID), SE(0) {} private: virtual void getAnalysisUsage(AnalysisUsage &AU) const; virtual bool runOnFunction(Function &F); virtual AliasResult alias(const Value *V1, unsigned V1Size, const Value *V2, unsigned V2Size); Value *GetUnderlyingIdentifiedObject(const SCEV *S); }; } // End of anonymous namespace // Register this pass... char ScalarEvolutionAliasAnalysis::ID = 0; static RegisterPass X("scev-aa", "ScalarEvolution-based Alias Analysis", false, true); // Declare that we implement the AliasAnalysis interface static RegisterAnalysisGroup Y(X); FunctionPass *llvm::createScalarEvolutionAliasAnalysisPass() { return new ScalarEvolutionAliasAnalysis(); } void ScalarEvolutionAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequiredTransitive(); AU.setPreservesAll(); AliasAnalysis::getAnalysisUsage(AU); } bool ScalarEvolutionAliasAnalysis::runOnFunction(Function &F) { InitializeAliasAnalysis(this); SE = &getAnalysis(); return false; } /// GetUnderlyingIdentifiedObject - Given an expression, try to find an /// "identified object" (see AliasAnalysis::isIdentifiedObject) base /// value. Return null is none was found. Value * ScalarEvolutionAliasAnalysis::GetUnderlyingIdentifiedObject(const SCEV *S) { if (const SCEVAddRecExpr *AR = dyn_cast(S)) { // In an addrec, assume that the base will be in the start, rather // than the step. return GetUnderlyingIdentifiedObject(AR->getStart()); } else if (const SCEVAddExpr *A = dyn_cast(S)) { // If there's a pointer operand, it'll be sorted at the end of the list. const SCEV *Last = A->getOperand(A->getNumOperands()-1); if (isa(Last->getType())) return GetUnderlyingIdentifiedObject(Last); } else if (const SCEVUnknown *U = dyn_cast(S)) { // Determine if we've found an Identified object. Value *V = U->getValue(); if (isIdentifiedObject(V)) return V; } // No Identified object found. return 0; } AliasAnalysis::AliasResult ScalarEvolutionAliasAnalysis::alias(const Value *A, unsigned ASize, const Value *B, unsigned BSize) { // This is ScalarEvolutionAliasAnalysis. Get the SCEVs! const SCEV *AS = SE->getSCEV(const_cast(A)); const SCEV *BS = SE->getSCEV(const_cast(B)); // If they evaluate to the same expression, it's a MustAlias. if (AS == BS) return MustAlias; // If something is known about the difference between the two addresses, // see if it's enough to prove a NoAlias. if (SE->getEffectiveSCEVType(AS->getType()) == SE->getEffectiveSCEVType(BS->getType())) { unsigned BitWidth = SE->getTypeSizeInBits(AS->getType()); APInt AI(BitWidth, ASize); const SCEV *BA = SE->getMinusSCEV(BS, AS); if (AI.ule(SE->getUnsignedRange(BA).getUnsignedMin())) { APInt BI(BitWidth, BSize); const SCEV *AB = SE->getMinusSCEV(AS, BS); if (BI.ule(SE->getUnsignedRange(AB).getUnsignedMin())) return NoAlias; } } // If ScalarEvolution can find an underlying object, form a new query. // The correctness of this depends on ScalarEvolution not recognizing // inttoptr and ptrtoint operators. Value *AO = GetUnderlyingIdentifiedObject(AS); Value *BO = GetUnderlyingIdentifiedObject(BS); if ((AO && AO != A) || (BO && BO != B)) if (alias(AO ? AO : A, AO ? ~0u : ASize, BO ? BO : B, BO ? ~0u : BSize) == NoAlias) return NoAlias; // Forward the query to the next analysis. return AliasAnalysis::alias(A, ASize, B, BSize); }