[llvm] r217334 - Add an Assumption-Tracking Pass

Hal Finkel hfinkel at anl.gov
Mon Sep 8 11:07:01 PDT 2014


----- Original Message -----
> From: "Alexey Samsonov" <vonosmas at gmail.com>
> To: "Hal Finkel" <hfinkel at anl.gov>
> Cc: "llvm-commits" <llvm-commits at cs.uiuc.edu>
> Sent: Monday, September 8, 2014 12:57:52 PM
> Subject: Re: [llvm] r217334 - Add an Assumption-Tracking Pass
> 
> 
> Hi Hal,
> 
> 
> On Sun, Sep 7, 2014 at 5:44 AM, Hal Finkel < hfinkel at anl.gov > wrote:
> 
> 
> Author: hfinkel
> Date: Sun Sep 7 07:44:26 2014
> New Revision: 217334
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=217334&view=rev
> Log:
> Add an Assumption-Tracking Pass
> 
> This adds an immutable pass, AssumptionTracker, which keeps a cache
> of
> @llvm.assume call instructions within a module. It uses callback
> value handles
> to keep stale functions and intrinsics out of the map, and it relies
> on any
> code that creates new @llvm.assume calls to notify it of the new
> instructions.
> The benefit is that code needing to find @llvm.assume intrinsics can
> do so
> directly, without scanning the function, thus allowing the cost of
> @llvm.assume
> handling to be negligible when none are present.
> 
> The current design is intended to be lightweight. We don't keep track
> of
> anything until we need a list of assumptions in some function. The
> first time
> this happens, we scan the function. After that, we add/remove
> @llvm.assume
> calls from the cache in response to registration calls and
> ValueHandle
> callbacks.
> 
> There are no new direct test cases for this pass, but because it
> calls it
> validation function upon module finalization, we'll pick up
> detectable
> inconsistencies from the other tests that touch @llvm.assume calls.
> 
> This pass will be used by follow-up commits that make use of
> @llvm.assume.
> 
> Added:
> llvm/trunk/include/llvm/Analysis/AssumptionTracker.h
> llvm/trunk/lib/Analysis/AssumptionTracker.cpp
> Modified:
> llvm/trunk/include/llvm/InitializePasses.h
> llvm/trunk/include/llvm/Transforms/Utils/Cloning.h
> llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h
> llvm/trunk/lib/Analysis/CMakeLists.txt
> llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp
> llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp
> llvm/trunk/lib/Transforms/IPO/Inliner.cpp
> llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
> llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
> llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
> llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
> llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
> 
> Added: llvm/trunk/include/llvm/Analysis/AssumptionTracker.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AssumptionTracker.h?rev=217334&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/AssumptionTracker.h (added)
> +++ llvm/trunk/include/llvm/Analysis/AssumptionTracker.h Sun Sep 7
> 07:44:26 2014
> @@ -0,0 +1,128 @@
> +//===- llvm/Analysis/AssumptionTracker.h - Track @llvm.assume ---*-
> C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open
> Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains a pass that keeps track of @llvm.assume
> intrinsics in
> +// the functions of a module (allowing assumptions within any
> function to be
> +// found cheaply by other parts of the optimizer).
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_ANALYSIS_ASSUMPTIONTRACKER_H
> +#define LLVM_ANALYSIS_ASSUMPTIONTRACKER_H
> +
> +#include "llvm/ADT/DenseMap.h"
> +#include "llvm/ADT/DenseSet.h"
> +#include "llvm/ADT/SmallSet.h"
> +#include "llvm/IR/Function.h"
> +#include "llvm/IR/Instructions.h"
> +#include "llvm/IR/ValueHandle.h"
> +#include "llvm/Pass.h"
> +#include <memory>
> +
> +namespace llvm {
> +
> +/// An immutable pass that tracks @llvm.assume intrinsics in a
> module.
> +class AssumptionTracker : public ImmutablePass {
> + /// A callback value handle applied to function objects, which we
> use to
> + /// delete our cache of intrinsics for a function when it is
> deleted.
> + class FunctionCallbackVH : public CallbackVH {
> + AssumptionTracker *AT;
> + void deleted() override;
> +
> + public:
> + typedef DenseMapInfo<Value *> DMI;
> +
> + FunctionCallbackVH(Value *V, AssumptionTracker *AT = nullptr)
> + : CallbackVH(V), AT(AT) {}
> + };
> +
> + /// A callback value handle applied to call instructions, which
> keeps
> + /// track of the call's parent function so that we can remove a
> + /// assumption intrinsic call from our cache when the instruction
> is
> + /// deleted.
> + class CallCallbackVH : public CallbackVH {
> + AssumptionTracker *AT;
> + void deleted() override;
> +
> + // We store the function here because we need it to lookup the set
> + // containing this handle when the underlying CallInst is being
> deleted.
> + Function *F;
> +
> + public:
> + typedef DenseMapInfo<Instruction *> DMI;
> +
> + CallCallbackVH(Instruction *I, AssumptionTracker *AT = nullptr)
> + : CallbackVH(I), AT(AT), F(nullptr) {
> + if (I != DMI::getEmptyKey() && I != DMI::getTombstoneKey())
> + F = I->getParent()->getParent();
> + }
> +
> + operator CallInst*() const {
> + Value *V = getValPtr();
> + if (V == DMI::getEmptyKey() || V == DMI::getTombstoneKey())
> + return static_cast<CallInst*>(V);
> 
> 
> 
> ^^ UBSan bootstrap bot reports undefined behavior here:
> 
> /home/dtoolsbot/build/sanitizer-x86_64-linux-bootstrap/build/llvm/include/llvm/Analysis/AssumptionTracker.h:69:18:
> runtime error: downcast of misaligned address 0xfffffffffffffffc for
> type 'llvm::CallInst', which requires 8 byte alignment
> 
> (full log:
> http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/4491/steps/check-llvm%20ubsan/logs/stdio
> )
> 
> 
> The real problem is probably the fact that we don't enforce correct
> alignment on EmptyKey and TombstoneKey in DenseMap<T*, foo>, but
> it's not clear how to do this in the general case:
> correct alignment of "fake pointers" of type T* depends on the
> natural alignment of T, while the definition of T might not be
> available.
> 
> 
> Can you work around this problem somehow, and avoid bogus cast of
> fake pointer here?

Interesting. Would using a reinterpret_cast fix the problem?

 -Hal

> 
> 
> 
> 
> +
> + return cast<CallInst>(V);
> + }
> +
> + CallInst *operator->() const { return cast<CallInst>(getValPtr());
> }
> + CallInst &operator*() const { return *cast<CallInst>(getValPtr());
> }
> + };
> +
> + friend FunctionCallbackVH;
> + friend CallCallbackVH;
> +
> + // FIXME: SmallSet might be better here, but it currently has no
> iterators.
> + typedef DenseSet<CallCallbackVH, CallCallbackVH::DMI>
> CallHandleSet;
> + typedef DenseMap<FunctionCallbackVH,
> std::unique_ptr<CallHandleSet>,
> + FunctionCallbackVH::DMI> FunctionCallsMap;
> + FunctionCallsMap CachedAssumeCalls;
> +
> + /// Scan the provided function for @llvm.assume intrinsic calls.
> Returns an
> + /// iterator to the set for this function in the CachedAssumeCalls
> map.
> + FunctionCallsMap::iterator scanFunction(Function *F);
> +
> +public:
> + /// Remove the cache of @llvm.assume intrinsics for the given
> function.
> + void forgetCachedAssumptions(Function *F);
> +
> + /// Add an @llvm.assume intrinsic to the cache for its parent
> function.
> + void registerAssumption(CallInst *CI);
> +
> + typedef CallHandleSet::iterator assumption_iterator;
> + typedef iterator_range<assumption_iterator> assumption_range;
> +
> + inline assumption_range assumptions(Function *F) {
> + FunctionCallsMap::iterator I = CachedAssumeCalls.find(F);
> + if (I == CachedAssumeCalls.end()) {
> + I = scanFunction(F);
> + }
> +
> + return assumption_range(I->second->begin(), I->second->end());
> + }
> +
> + AssumptionTracker();
> + ~AssumptionTracker();
> +
> + void releaseMemory() override {
> + CachedAssumeCalls.shrink_and_clear();
> + }
> +
> + void verifyAnalysis() const override;
> + bool doFinalization(Module &) override {
> + verifyAnalysis();
> + return false;
> + }
> +
> + static char ID; // Pass identification, replacement for typeid
> +};
> +
> +} // end namespace llvm
> +
> +#endif
> 
> Modified: llvm/trunk/include/llvm/InitializePasses.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/InitializePasses.h (original)
> +++ llvm/trunk/include/llvm/InitializePasses.h Sun Sep 7 07:44:26
> 2014
> @@ -262,6 +262,7 @@ void initializeDataLayoutPassPass(PassRe
> void initializeTargetTransformInfoAnalysisGroup(PassRegistry&);
> void initializeNoTTIPass(PassRegistry&);
> void initializeTargetLibraryInfoPass(PassRegistry&);
> +void initializeAssumptionTrackerPass(PassRegistry &);
> void initializeTwoAddressInstructionPassPass(PassRegistry&);
> void initializeTypeBasedAliasAnalysisPass(PassRegistry&);
> void initializeScopedNoAliasAAPass(PassRegistry&);
> 
> Modified: llvm/trunk/include/llvm/Transforms/Utils/Cloning.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Cloning.h?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Utils/Cloning.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Utils/Cloning.h Sun Sep 7
> 07:44:26 2014
> @@ -44,6 +44,7 @@ class Loop;
> class LoopInfo;
> class AllocaInst;
> class AliasAnalysis;
> +class AssumptionTracker;
> 
> /// CloneModule - Return an exact copy of the specified module
> ///
> @@ -160,14 +161,16 @@ class InlineFunctionInfo {
> public:
> explicit InlineFunctionInfo(CallGraph *cg = nullptr,
> const DataLayout *DL = nullptr,
> - AliasAnalysis *AA = nullptr)
> - : CG(cg), DL(DL), AA(AA) {}
> + AliasAnalysis *AA = nullptr,
> + AssumptionTracker *AT = nullptr)
> + : CG(cg), DL(DL), AA(AA), AT(AT) {}
> 
> /// CG - If non-null, InlineFunction will update the callgraph to
> reflect the
> /// changes it makes.
> CallGraph *CG;
> const DataLayout *DL;
> AliasAnalysis *AA;
> + AssumptionTracker *AT;
> 
> /// StaticAllocas - InlineFunction fills this in with all static
> allocas that
> /// get copied into the caller.
> 
> Modified: llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h Sun Sep 7
> 07:44:26 2014
> @@ -18,6 +18,7 @@
> 
> namespace llvm {
> 
> +class AssumptionTracker;
> class Loop;
> class LoopInfo;
> class LPPassManager;
> @@ -25,7 +26,7 @@ class Pass;
> 
> bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool
> AllowRuntime,
> unsigned TripMultiple, LoopInfo *LI, Pass *PP,
> - LPPassManager *LPM);
> + LPPassManager *LPM, AssumptionTracker *AT);
> 
> bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI,
> LPPassManager* LPM);
> 
> Added: llvm/trunk/lib/Analysis/AssumptionTracker.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AssumptionTracker.cpp?rev=217334&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Analysis/AssumptionTracker.cpp (added)
> +++ llvm/trunk/lib/Analysis/AssumptionTracker.cpp Sun Sep 7 07:44:26
> 2014
> @@ -0,0 +1,113 @@
> +//===- AssumptionTracker.cpp - Track @llvm.assume
> -------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open
> Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains a pass that keeps track of @llvm.assume
> intrinsics in
> +// the functions of a module.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/Analysis/AssumptionTracker.h"
> +#include "llvm/IR/CallSite.h"
> +#include "llvm/IR/Dominators.h"
> +#include "llvm/IR/Function.h"
> +#include "llvm/IR/Instructions.h"
> +#include "llvm/IR/IntrinsicInst.h"
> +#include "llvm/IR/PatternMatch.h"
> +#include "llvm/Support/Debug.h"
> +using namespace llvm;
> +using namespace llvm::PatternMatch;
> +
> +void AssumptionTracker::FunctionCallbackVH::deleted() {
> + AT->forgetCachedAssumptions(cast<Function>(getValPtr()));
> + // 'this' now dangles!
> +}
> +
> +void AssumptionTracker::forgetCachedAssumptions(Function *F) {
> + CachedAssumeCalls.erase(F);
> +}
> +
> +void AssumptionTracker::CallCallbackVH::deleted() {
> + assert(F && "delete callback called on dummy handle");
> + FunctionCallsMap::iterator I = AT->CachedAssumeCalls.find(F);
> + assert(I != AT->CachedAssumeCalls.end() &&
> + "Function cleared from the map without removing the values?");
> +
> + I->second->erase(*this);
> + // 'this' now dangles!
> +}
> +
> +AssumptionTracker::FunctionCallsMap::iterator
> +AssumptionTracker::scanFunction(Function *F) {
> + auto IP =
> + CachedAssumeCalls.insert(std::make_pair(FunctionCallbackVH(F,
> this),
> + std::unique_ptr<CallHandleSet>(
> + new CallHandleSet())));
> + assert(IP.second && "Scanning function already in the map?");
> +
> + FunctionCallsMap::iterator I = IP.first;
> +
> + // Go through all instructions in all blocks, add all calls to
> @llvm.assume
> + // to our cache.
> + for (BasicBlock &B : *F)
> + for (Instruction &II : B)
> + if (match(cast<Value>(&II),
> m_Intrinsic<Intrinsic::assume>(m_Value())))
> + I->second->insert(CallCallbackVH(&II, this));
> +
> + return I;
> +}
> +
> +void AssumptionTracker::verifyAnalysis() const {
> +#ifndef NDEBUG
> + for (const auto &I : CachedAssumeCalls) {
> + for (const BasicBlock &B : cast<Function>(*I.first))
> + for (const Instruction &II : B) {
> + Instruction *C = const_cast<Instruction*>(&II);
> + if (match(C, m_Intrinsic<Intrinsic::assume>(m_Value()))) {
> + assert(I.second->count(CallCallbackVH(C,
> + const_cast<AssumptionTracker*>(this))) &&
> + "Assumption in scanned function not in cache");
> + }
> + }
> + }
> +#endif
> +}
> +
> +void AssumptionTracker::registerAssumption(CallInst *CI) {
> + assert(match(cast<Value>(CI),
> + m_Intrinsic<Intrinsic::assume>(m_Value())) &&
> + "Registered call does not call @llvm.assume");
> + assert(CI->getParent() &&
> + "Cannot register @llvm.assume call not in a basic block");
> +
> + Function *F = CI->getParent()->getParent();
> + assert(F && "Cannot register @llvm.assume call not in a function");
> +
> + FunctionCallsMap::iterator I = CachedAssumeCalls.find(F);
> + if (I == CachedAssumeCalls.end()) {
> + // If this function has not already been scanned, then don't do
> anything
> + // here. This intrinsic will be found, if it still exists, if the
> list of
> + // assumptions in this function is requested at some later point.
> This
> + // maintains the following invariant: if a function is present in
> the
> + // cache, then its list of assumption intrinsic calls is complete.
> + return;
> + }
> +
> + I->second->insert(CallCallbackVH(CI, this));
> +}
> +
> +AssumptionTracker::AssumptionTracker() : ImmutablePass(ID) {
> + initializeAssumptionTrackerPass(*PassRegistry::getPassRegistry());
> +}
> +
> +AssumptionTracker::~AssumptionTracker() {}
> +
> +INITIALIZE_PASS(AssumptionTracker, "assumption-tracker", "Assumption
> Tracker",
> + false, true)
> +char AssumptionTracker::ID = 0;
> +
> 
> Modified: llvm/trunk/lib/Analysis/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/CMakeLists.txt (original)
> +++ llvm/trunk/lib/Analysis/CMakeLists.txt Sun Sep 7 07:44:26 2014
> @@ -5,6 +5,7 @@ add_llvm_library(LLVMAnalysis
> AliasDebugger.cpp
> AliasSetTracker.cpp
> Analysis.cpp
> + AssumptionTracker.cpp
> BasicAliasAnalysis.cpp
> BlockFrequencyInfo.cpp
> BlockFrequencyInfoImpl.cpp
> 
> Modified: llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/InlineAlways.cpp Sun Sep 7 07:44:26
> 2014
> @@ -15,6 +15,7 @@
> #include "llvm/Transforms/IPO.h"
> #include "llvm/ADT/SmallPtrSet.h"
> #include "llvm/Analysis/AliasAnalysis.h"
> +#include "llvm/Analysis/AssumptionTracker.h"
> #include "llvm/Analysis/CallGraph.h"
> #include "llvm/Analysis/InlineCost.h"
> #include "llvm/IR/CallSite.h"
> @@ -67,6 +68,7 @@ char AlwaysInliner::ID = 0;
> INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline",
> "Inliner for always_inline functions", false, false)
> INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
> +INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
> INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
> INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
> INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
> 
> Modified: llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/InlineSimple.cpp Sun Sep 7 07:44:26
> 2014
> @@ -13,6 +13,7 @@
> 
> #include "llvm/Transforms/IPO.h"
> #include "llvm/Analysis/AliasAnalysis.h"
> +#include "llvm/Analysis/AssumptionTracker.h"
> #include "llvm/Analysis/CallGraph.h"
> #include "llvm/Analysis/InlineCost.h"
> #include "llvm/IR/CallSite.h"
> @@ -75,6 +76,7 @@ char SimpleInliner::ID = 0;
> INITIALIZE_PASS_BEGIN(SimpleInliner, "inline",
> "Function Integration/Inlining", false, false)
> INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
> +INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
> INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
> INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
> INITIALIZE_PASS_END(SimpleInliner, "inline",
> 
> Modified: llvm/trunk/lib/Transforms/IPO/Inliner.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/Inliner.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp Sun Sep 7 07:44:26 2014
> @@ -17,6 +17,7 @@
> #include "llvm/ADT/SmallPtrSet.h"
> #include "llvm/ADT/Statistic.h"
> #include "llvm/Analysis/AliasAnalysis.h"
> +#include "llvm/Analysis/AssumptionTracker.h"
> #include "llvm/Analysis/CallGraph.h"
> #include "llvm/Analysis/InlineCost.h"
> #include "llvm/IR/CallSite.h"
> @@ -76,6 +77,7 @@ Inliner::Inliner(char &ID, int Threshold
> /// always explicitly call the implementation here.
> void Inliner::getAnalysisUsage(AnalysisUsage &AU) const {
> AU.addRequired<AliasAnalysis>();
> + AU.addRequired<AssumptionTracker>();
> CallGraphSCCPass::getAnalysisUsage(AU);
> }
> 
> @@ -441,6 +443,7 @@ static bool InlineHistoryIncludes(Functi
> 
> bool Inliner::runOnSCC(CallGraphSCC &SCC) {
> CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
> + AssumptionTracker *AT = &getAnalysis<AssumptionTracker>();
> DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();
> const DataLayout *DL = DLP ? &DLP->getDataLayout() : nullptr;
> const TargetLibraryInfo *TLI =
> getAnalysisIfAvailable<TargetLibraryInfo>();
> @@ -503,7 +506,7 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC
> 
> 
> InlinedArrayAllocasTy InlinedArrayAllocas;
> - InlineFunctionInfo InlineInfo(&CG, DL, AA);
> + InlineFunctionInfo InlineInfo(&CG, DL, AA, AT);
> 
> // Now that we have all of the call sites, loop over them and inline
> them if
> // it looks profitable to do so.
> 
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombine.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombine.h?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombine.h (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombine.h Sun Sep 7
> 07:44:26 2014
> @@ -11,12 +11,14 @@
> #define LLVM_LIB_TRANSFORMS_INSTCOMBINE_INSTCOMBINE_H
> 
> #include "InstCombineWorklist.h"
> +#include "llvm/Analysis/AssumptionTracker.h"
> #include "llvm/Analysis/TargetFolder.h"
> #include "llvm/Analysis/ValueTracking.h"
> #include "llvm/IR/IRBuilder.h"
> #include "llvm/IR/InstVisitor.h"
> #include "llvm/IR/IntrinsicInst.h"
> #include "llvm/IR/Operator.h"
> +#include "llvm/IR/PatternMatch.h"
> #include "llvm/Pass.h"
> #include "llvm/Transforms/Utils/SimplifyLibCalls.h"
> 
> @@ -71,14 +73,20 @@ static inline Constant *SubOne(Constant
> class LLVM_LIBRARY_VISIBILITY InstCombineIRInserter
> : public IRBuilderDefaultInserter<true> {
> InstCombineWorklist &Worklist;
> + AssumptionTracker *AT;
> 
> public:
> - InstCombineIRInserter(InstCombineWorklist &WL) : Worklist(WL) {}
> + InstCombineIRInserter(InstCombineWorklist &WL, AssumptionTracker
> *AT)
> + : Worklist(WL), AT(AT) {}
> 
> void InsertHelper(Instruction *I, const Twine &Name, BasicBlock *BB,
> BasicBlock::iterator InsertPt) const {
> IRBuilderDefaultInserter<true>::InsertHelper(I, Name, BB, InsertPt);
> Worklist.Add(I);
> +
> + using namespace llvm::PatternMatch;
> + if ((match(I, m_Intrinsic<Intrinsic::assume>(m_Value()))))
> + AT->registerAssumption(cast<CallInst>(I));
> }
> };
> 
> @@ -86,6 +94,7 @@ public:
> class LLVM_LIBRARY_VISIBILITY InstCombiner
> : public FunctionPass,
> public InstVisitor<InstCombiner, Instruction *> {
> + AssumptionTracker *AT;
> const DataLayout *DL;
> TargetLibraryInfo *TLI;
> bool MadeIRChange;
> @@ -114,6 +123,8 @@ public:
> 
> void getAnalysisUsage(AnalysisUsage &AU) const override;
> 
> + AssumptionTracker *getAssumptionTracker() const { return AT; }
> +
> const DataLayout *getDataLayout() const { return DL; }
> 
> TargetLibraryInfo *getTargetLibraryInfo() const { return TLI; }
> 
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Sun
> Sep 7 07:44:26 2014
> @@ -996,6 +996,8 @@ Instruction *InstCombiner::visitCallInst
> }
> case Intrinsic::assume: {
> // Canonicalize assume(a && b) -> assume(a); assume(b);
> + // Note: New assumption intrinsics created here are registered by
> + // the InstCombineIRInserter object.
> Value *IIOperand = II->getArgOperand(0), *A, *B,
> *AssumeIntrinsic = II->getCalledValue();
> if (match(IIOperand, m_And(m_Value(A), m_Value(B)))) {
> @@ -1005,8 +1007,10 @@ Instruction *InstCombiner::visitCallInst
> }
> // assume(!(a || b)) -> assume(!a); assume(!b);
> if (match(IIOperand, m_Not(m_Or(m_Value(A), m_Value(B))))) {
> - Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(A),
> II->getName());
> - Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(B),
> II->getName());
> + Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(A),
> + II->getName());
> + Builder->CreateCall(AssumeIntrinsic, Builder->CreateNot(B),
> + II->getName());
> return EraseInstFromFunction(*II);
> }
> break;
> 
> Modified:
> llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
> Sun Sep 7 07:44:26 2014
> @@ -39,6 +39,7 @@
> #include "llvm/ADT/SmallPtrSet.h"
> #include "llvm/ADT/Statistic.h"
> #include "llvm/ADT/StringSwitch.h"
> +#include "llvm/Analysis/AssumptionTracker.h"
> #include "llvm/Analysis/ConstantFolding.h"
> #include "llvm/Analysis/InstructionSimplify.h"
> #include "llvm/Analysis/MemoryBuiltins.h"
> @@ -85,12 +86,14 @@ void LLVMInitializeInstCombine(LLVMPassR
> char InstCombiner::ID = 0;
> INITIALIZE_PASS_BEGIN(InstCombiner, "instcombine",
> "Combine redundant instructions", false, false)
> +INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
> INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
> INITIALIZE_PASS_END(InstCombiner, "instcombine",
> "Combine redundant instructions", false, false)
> 
> void InstCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
> AU.setPreservesCFG();
> + AU.addRequired<AssumptionTracker>();
> AU.addRequired<TargetLibraryInfo>();
> }
> 
> @@ -2907,6 +2910,7 @@ bool InstCombiner::runOnFunction(Functio
> if (skipOptnoneFunction(F))
> return false;
> 
> + AT = &getAnalysis<AssumptionTracker>();
> DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();
> DL = DLP ? &DLP->getDataLayout() : nullptr;
> TLI = &getAnalysis<TargetLibraryInfo>();
> @@ -2918,7 +2922,7 @@ bool InstCombiner::runOnFunction(Functio
> /// instructions into the worklist when they are created.
> IRBuilder<true, TargetFolder, InstCombineIRInserter>
> TheBuilder(F.getContext(), TargetFolder(DL),
> - InstCombineIRInserter(Worklist));
> + InstCombineIRInserter(Worklist, AT));
> Builder = &TheBuilder;
> 
> InstCombinerLibCallSimplifier TheSimplifier(DL, TLI, this);
> 
> Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Sun Sep 7
> 07:44:26 2014
> @@ -13,6 +13,7 @@
> //===----------------------------------------------------------------------===//
> 
> #include "llvm/Transforms/Scalar.h"
> +#include "llvm/Analysis/AssumptionTracker.h"
> #include "llvm/Analysis/CodeMetrics.h"
> #include "llvm/Analysis/LoopPass.h"
> #include "llvm/Analysis/ScalarEvolution.h"
> @@ -102,6 +103,7 @@ namespace {
> /// loop preheaders be inserted into the CFG...
> ///
> void getAnalysisUsage(AnalysisUsage &AU) const override {
> + AU.addRequired<AssumptionTracker>();
> AU.addRequired<LoopInfo>();
> AU.addPreserved<LoopInfo>();
> AU.addRequiredID(LoopSimplifyID);
> @@ -182,6 +184,7 @@ namespace {
> char LoopUnroll::ID = 0;
> INITIALIZE_PASS_BEGIN(LoopUnroll, "loop-unroll", "Unroll loops",
> false, false)
> INITIALIZE_AG_DEPENDENCY(TargetTransformInfo)
> +INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
> INITIALIZE_PASS_DEPENDENCY(LoopInfo)
> INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
> INITIALIZE_PASS_DEPENDENCY(LCSSA)
> @@ -351,6 +354,7 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPa
> LoopInfo *LI = &getAnalysis<LoopInfo>();
> ScalarEvolution *SE = &getAnalysis<ScalarEvolution>();
> const TargetTransformInfo &TTI = getAnalysis<TargetTransformInfo>();
> + AssumptionTracker *AT = &getAnalysis<AssumptionTracker>();
> 
> BasicBlock *Header = L->getHeader();
> DEBUG(dbgs() << "Loop Unroll: F[" << Header->getParent()->getName()
> @@ -493,7 +497,8 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPa
> }
> 
> // Unroll the loop.
> - if (!UnrollLoop(L, Count, TripCount, AllowRuntime, TripMultiple,
> LI, this, &LPM))
> + if (!UnrollLoop(L, Count, TripCount, AllowRuntime, TripMultiple,
> LI, this,
> + &LPM, AT))
> return false;
> 
> return true;
> 
> Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp Sun Sep 7
> 07:44:26 2014
> @@ -30,6 +30,7 @@
> #include "llvm/ADT/STLExtras.h"
> #include "llvm/ADT/SmallPtrSet.h"
> #include "llvm/ADT/Statistic.h"
> +#include "llvm/Analysis/AssumptionTracker.h"
> #include "llvm/Analysis/CodeMetrics.h"
> #include "llvm/Analysis/InstructionSimplify.h"
> #include "llvm/Analysis/LoopInfo.h"
> @@ -126,6 +127,7 @@ namespace {
> class LoopUnswitch : public LoopPass {
> LoopInfo *LI; // Loop information
> LPPassManager *LPM;
> + AssumptionTracker *AT;
> 
> // LoopProcessWorklist - Used to check if second loop needs
> processing
> // after RewriteLoopBodyWithConditionConstant rewrites first loop.
> @@ -164,6 +166,7 @@ namespace {
> /// loop preheaders be inserted into the CFG.
> ///
> void getAnalysisUsage(AnalysisUsage &AU) const override {
> + AU.addRequired<AssumptionTracker>();
> AU.addRequiredID(LoopSimplifyID);
> AU.addPreservedID(LoopSimplifyID);
> AU.addRequired<LoopInfo>();
> @@ -326,6 +329,7 @@ char LoopUnswitch::ID = 0;
> INITIALIZE_PASS_BEGIN(LoopUnswitch, "loop-unswitch", "Unswitch
> loops",
> false, false)
> INITIALIZE_AG_DEPENDENCY(TargetTransformInfo)
> +INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
> INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
> INITIALIZE_PASS_DEPENDENCY(LoopInfo)
> INITIALIZE_PASS_DEPENDENCY(LCSSA)
> @@ -376,6 +380,7 @@ bool LoopUnswitch::runOnLoop(Loop *L, LP
> if (skipOptnoneFunction(L))
> return false;
> 
> + AT = &getAnalysis<AssumptionTracker>();
> LI = &getAnalysis<LoopInfo>();
> LPM = &LPM_Ref;
> DominatorTreeWrapperPass *DTWP =
> @@ -823,6 +828,10 @@ void LoopUnswitch::UnswitchNontrivialCon
> F->getBasicBlockList().splice(NewPreheader, F->getBasicBlockList(),
> NewBlocks[0], F->end());
> 
> + // FIXME: We could register any cloned assumptions instead of
> clearing the
> + // whole function's cache.
> + AT->forgetCachedAssumptions(F);
> +
> // Now we create the new Loop object for the versioned loop.
> Loop *NewLoop = CloneLoop(L, L->getParentLoop(), VMap, LI, LPM);
> 
> 
> Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Sun Sep 7
> 07:44:26 2014
> @@ -18,6 +18,7 @@
> #include "llvm/ADT/SetVector.h"
> #include "llvm/ADT/StringExtras.h"
> #include "llvm/Analysis/AliasAnalysis.h"
> +#include "llvm/Analysis/AssumptionTracker.h"
> #include "llvm/Analysis/CallGraph.h"
> #include "llvm/Analysis/CaptureTracking.h"
> #include "llvm/Analysis/InstructionSimplify.h"
> @@ -982,6 +983,11 @@ bool llvm::InlineFunction(CallSite CS, I
> 
> // Add noalias metadata if necessary.
> AddAliasScopeMetadata(CS, VMap, IFI.DL, IFI.AA);
> +
> + // FIXME: We could register any cloned assumptions instead of
> clearing the
> + // whole function's cache.
> + if ( IFI.AT )
> + IFI.AT->forgetCachedAssumptions(Caller);
> }
> 
> // If there are any alloca instructions in the block that used to be
> the entry
> 
> Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=217334&r1=217333&r2=217334&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Sun Sep 7 07:44:26
> 2014
> @@ -19,6 +19,7 @@
> #include "llvm/Transforms/Utils/UnrollLoop.h"
> #include "llvm/ADT/SmallPtrSet.h"
> #include "llvm/ADT/Statistic.h"
> +#include "llvm/Analysis/AssumptionTracker.h"
> #include "llvm/Analysis/InstructionSimplify.h"
> #include "llvm/Analysis/LoopIterator.h"
> #include "llvm/Analysis/LoopPass.h"
> @@ -154,7 +155,8 @@ FoldBlockIntoPredecessor(BasicBlock *BB,
> /// available from the Pass it must also preserve those analyses.
> bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount,
> bool AllowRuntime, unsigned TripMultiple,
> - LoopInfo *LI, Pass *PP, LPPassManager *LPM) {
> + LoopInfo *LI, Pass *PP, LPPassManager *LPM,
> + AssumptionTracker *AT) {
> BasicBlock *Preheader = L->getLoopPreheader();
> if (!Preheader) {
> DEBUG(dbgs() << " Can't unroll; loop preheader-insertion failed.\n");
> @@ -442,6 +444,10 @@ bool llvm::UnrollLoop(Loop *L, unsigned
> }
> }
> 
> + // FIXME: We could register any cloned assumptions instead of
> clearing the
> + // whole function's cache.
> + AT->forgetCachedAssumptions(F);
> +
> DominatorTree *DT = nullptr;
> if (PP) {
> // FIXME: Reconstruct dom info, because it is not preserved properly.
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> 
> 
> 
> 
> --
> 
> Alexey Samsonov
> vonosmas at gmail.com

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory



More information about the llvm-commits mailing list