--- /dev/null
+//===- 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);
+
+ 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
void initializeTargetTransformInfoAnalysisGroup(PassRegistry&);
void initializeNoTTIPass(PassRegistry&);
void initializeTargetLibraryInfoPass(PassRegistry&);
+void initializeAssumptionTrackerPass(PassRegistry &);
void initializeTwoAddressInstructionPassPass(PassRegistry&);
void initializeTypeBasedAliasAnalysisPass(PassRegistry&);
void initializeScopedNoAliasAAPass(PassRegistry&);
class LoopInfo;
class AllocaInst;
class AliasAnalysis;
+class AssumptionTracker;
/// CloneModule - Return an exact copy of the specified module
///
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.
namespace llvm {
+class AssumptionTracker;
class Loop;
class LoopInfo;
class LPPassManager;
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);
--- /dev/null
+//===- 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;
+
AliasDebugger.cpp
AliasSetTracker.cpp
Analysis.cpp
+ AssumptionTracker.cpp
BasicAliasAnalysis.cpp
BlockFrequencyInfo.cpp
BlockFrequencyInfoImpl.cpp
#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"
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",
#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"
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",
#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"
/// always explicitly call the implementation here.
void Inliner::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<AliasAnalysis>();
+ AU.addRequired<AssumptionTracker>();
CallGraphSCCPass::getAnalysisUsage(AU);
}
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>();
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.
#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"
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));
}
};
class LLVM_LIBRARY_VISIBILITY InstCombiner
: public FunctionPass,
public InstVisitor<InstCombiner, Instruction *> {
+ AssumptionTracker *AT;
const DataLayout *DL;
TargetLibraryInfo *TLI;
bool MadeIRChange;
void getAnalysisUsage(AnalysisUsage &AU) const override;
+ AssumptionTracker *getAssumptionTracker() const { return AT; }
+
const DataLayout *getDataLayout() const { return DL; }
TargetLibraryInfo *getTargetLibraryInfo() const { return TLI; }
}
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)))) {
}
// 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;
#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"
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>();
}
if (skipOptnoneFunction(F))
return false;
+ AT = &getAnalysis<AssumptionTracker>();
DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();
DL = DLP ? &DLP->getDataLayout() : nullptr;
TLI = &getAnalysis<TargetLibraryInfo>();
/// 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);
//===----------------------------------------------------------------------===//
#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"
/// 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);
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)
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()
}
// 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;
#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"
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.
/// 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>();
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)
if (skipOptnoneFunction(L))
return false;
+ AT = &getAnalysis<AssumptionTracker>();
LI = &getAnalysis<LoopInfo>();
LPM = &LPM_Ref;
DominatorTreeWrapperPass *DTWP =
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);
#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"
// 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
#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"
/// 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");
}
}
+ // 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.