xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===----------------------- AlignmentFromAssumptions.cpp -----------------===//
20b57cec5SDimitry Andric //                  Set Load/Store Alignments From Assumptions
30b57cec5SDimitry Andric //
40b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric //
80b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric //
100b57cec5SDimitry Andric // This file implements a ScalarEvolution-based transformation to set
110b57cec5SDimitry Andric // the alignments of load, stores and memory intrinsics based on the truth
120b57cec5SDimitry Andric // expressions of assume intrinsics. The primary motivation is to handle
130b57cec5SDimitry Andric // complex alignment assumptions that apply to vector loads and stores that
140b57cec5SDimitry Andric // appear after vectorization and unrolling.
150b57cec5SDimitry Andric //
160b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
200b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
210b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
220b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
230b57cec5SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
240b57cec5SDimitry Andric #include "llvm/Analysis/LoopInfo.h"
250b57cec5SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpressions.h"
260b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
270b57cec5SDimitry Andric #include "llvm/IR/Dominators.h"
280b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
2981ad6265SDimitry Andric #include "llvm/IR/Instructions.h"
305ffd83dbSDimitry Andric #include "llvm/IR/IntrinsicInst.h"
310b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
320b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
33fe6060f1SDimitry Andric 
3406c3fb27SDimitry Andric #define DEBUG_TYPE "alignment-from-assumptions"
350b57cec5SDimitry Andric using namespace llvm;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric STATISTIC(NumLoadAlignChanged,
380b57cec5SDimitry Andric   "Number of loads changed by alignment assumptions");
390b57cec5SDimitry Andric STATISTIC(NumStoreAlignChanged,
400b57cec5SDimitry Andric   "Number of stores changed by alignment assumptions");
410b57cec5SDimitry Andric STATISTIC(NumMemIntAlignChanged,
420b57cec5SDimitry Andric   "Number of memory intrinsics changed by alignment assumptions");
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric // Given an expression for the (constant) alignment, AlignSCEV, and an
450b57cec5SDimitry Andric // expression for the displacement between a pointer and the aligned address,
460b57cec5SDimitry Andric // DiffSCEV, compute the alignment of the displaced pointer if it can be reduced
470b57cec5SDimitry Andric // to a constant. Using SCEV to compute alignment handles the case where
480b57cec5SDimitry Andric // DiffSCEV is a recurrence with constant start such that the aligned offset
490b57cec5SDimitry Andric // is constant. e.g. {16,+,32} % 32 -> 16.
505ffd83dbSDimitry Andric static MaybeAlign getNewAlignmentDiff(const SCEV *DiffSCEV,
510b57cec5SDimitry Andric                                       const SCEV *AlignSCEV,
520b57cec5SDimitry Andric                                       ScalarEvolution *SE) {
530b57cec5SDimitry Andric   // DiffUnits = Diff % int64_t(Alignment)
548bcb0991SDimitry Andric   const SCEV *DiffUnitsSCEV = SE->getURemExpr(DiffSCEV, AlignSCEV);
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "\talignment relative to " << *AlignSCEV << " is "
570b57cec5SDimitry Andric                     << *DiffUnitsSCEV << " (diff: " << *DiffSCEV << ")\n");
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   if (const SCEVConstant *ConstDUSCEV =
600b57cec5SDimitry Andric       dyn_cast<SCEVConstant>(DiffUnitsSCEV)) {
610b57cec5SDimitry Andric     int64_t DiffUnits = ConstDUSCEV->getValue()->getSExtValue();
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric     // If the displacement is an exact multiple of the alignment, then the
640b57cec5SDimitry Andric     // displaced pointer has the same alignment as the aligned pointer, so
650b57cec5SDimitry Andric     // return the alignment value.
660b57cec5SDimitry Andric     if (!DiffUnits)
675ffd83dbSDimitry Andric       return cast<SCEVConstant>(AlignSCEV)->getValue()->getAlignValue();
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric     // If the displacement is not an exact multiple, but the remainder is a
700b57cec5SDimitry Andric     // constant, then return this remainder (but only if it is a power of 2).
710b57cec5SDimitry Andric     uint64_t DiffUnitsAbs = std::abs(DiffUnits);
720b57cec5SDimitry Andric     if (isPowerOf2_64(DiffUnitsAbs))
735ffd83dbSDimitry Andric       return Align(DiffUnitsAbs);
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric 
76bdd1243dSDimitry Andric   return std::nullopt;
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric // There is an address given by an offset OffSCEV from AASCEV which has an
800b57cec5SDimitry Andric // alignment AlignSCEV. Use that information, if possible, to compute a new
810b57cec5SDimitry Andric // alignment for Ptr.
825ffd83dbSDimitry Andric static Align getNewAlignment(const SCEV *AASCEV, const SCEV *AlignSCEV,
830b57cec5SDimitry Andric                              const SCEV *OffSCEV, Value *Ptr,
840b57cec5SDimitry Andric                              ScalarEvolution *SE) {
850b57cec5SDimitry Andric   const SCEV *PtrSCEV = SE->getSCEV(Ptr);
86*5f757f3fSDimitry Andric 
870b57cec5SDimitry Andric   const SCEV *DiffSCEV = SE->getMinusSCEV(PtrSCEV, AASCEV);
88fe6060f1SDimitry Andric   if (isa<SCEVCouldNotCompute>(DiffSCEV))
89fe6060f1SDimitry Andric     return Align(1);
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   // On 32-bit platforms, DiffSCEV might now have type i32 -- we've always
920b57cec5SDimitry Andric   // sign-extended OffSCEV to i64, so make sure they agree again.
930b57cec5SDimitry Andric   DiffSCEV = SE->getNoopOrSignExtend(DiffSCEV, OffSCEV->getType());
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // What we really want to know is the overall offset to the aligned
960b57cec5SDimitry Andric   // address. This address is displaced by the provided offset.
97fe6060f1SDimitry Andric   DiffSCEV = SE->getAddExpr(DiffSCEV, OffSCEV);
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "AFI: alignment of " << *Ptr << " relative to "
1000b57cec5SDimitry Andric                     << *AlignSCEV << " and offset " << *OffSCEV
1010b57cec5SDimitry Andric                     << " using diff " << *DiffSCEV << "\n");
1020b57cec5SDimitry Andric 
1035ffd83dbSDimitry Andric   if (MaybeAlign NewAlignment = getNewAlignmentDiff(DiffSCEV, AlignSCEV, SE)) {
1045ffd83dbSDimitry Andric     LLVM_DEBUG(dbgs() << "\tnew alignment: " << DebugStr(NewAlignment) << "\n");
1055ffd83dbSDimitry Andric     return *NewAlignment;
1065ffd83dbSDimitry Andric   }
1070b57cec5SDimitry Andric 
1085ffd83dbSDimitry Andric   if (const SCEVAddRecExpr *DiffARSCEV = dyn_cast<SCEVAddRecExpr>(DiffSCEV)) {
1090b57cec5SDimitry Andric     // The relative offset to the alignment assumption did not yield a constant,
1100b57cec5SDimitry Andric     // but we should try harder: if we assume that a is 32-byte aligned, then in
1110b57cec5SDimitry Andric     // for (i = 0; i < 1024; i += 4) r += a[i]; not all of the loads from a are
1120b57cec5SDimitry Andric     // 32-byte aligned, but instead alternate between 32 and 16-byte alignment.
1130b57cec5SDimitry Andric     // As a result, the new alignment will not be a constant, but can still
1140b57cec5SDimitry Andric     // be improved over the default (of 4) to 16.
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric     const SCEV *DiffStartSCEV = DiffARSCEV->getStart();
1170b57cec5SDimitry Andric     const SCEV *DiffIncSCEV = DiffARSCEV->getStepRecurrence(*SE);
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\ttrying start/inc alignment using start "
1200b57cec5SDimitry Andric                       << *DiffStartSCEV << " and inc " << *DiffIncSCEV << "\n");
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric     // Now compute the new alignment using the displacement to the value in the
1230b57cec5SDimitry Andric     // first iteration, and also the alignment using the per-iteration delta.
1240b57cec5SDimitry Andric     // If these are the same, then use that answer. Otherwise, use the smaller
1250b57cec5SDimitry Andric     // one, but only if it divides the larger one.
1265ffd83dbSDimitry Andric     MaybeAlign NewAlignment = getNewAlignmentDiff(DiffStartSCEV, AlignSCEV, SE);
1275ffd83dbSDimitry Andric     MaybeAlign NewIncAlignment =
1285ffd83dbSDimitry Andric         getNewAlignmentDiff(DiffIncSCEV, AlignSCEV, SE);
1290b57cec5SDimitry Andric 
1305ffd83dbSDimitry Andric     LLVM_DEBUG(dbgs() << "\tnew start alignment: " << DebugStr(NewAlignment)
1315ffd83dbSDimitry Andric                       << "\n");
1325ffd83dbSDimitry Andric     LLVM_DEBUG(dbgs() << "\tnew inc alignment: " << DebugStr(NewIncAlignment)
1335ffd83dbSDimitry Andric                       << "\n");
1340b57cec5SDimitry Andric 
1355ffd83dbSDimitry Andric     if (!NewAlignment || !NewIncAlignment)
1365ffd83dbSDimitry Andric       return Align(1);
1375ffd83dbSDimitry Andric 
1385ffd83dbSDimitry Andric     const Align NewAlign = *NewAlignment;
1395ffd83dbSDimitry Andric     const Align NewIncAlign = *NewIncAlignment;
1405ffd83dbSDimitry Andric     if (NewAlign > NewIncAlign) {
1415ffd83dbSDimitry Andric       LLVM_DEBUG(dbgs() << "\tnew start/inc alignment: "
1425ffd83dbSDimitry Andric                         << DebugStr(NewIncAlign) << "\n");
1435ffd83dbSDimitry Andric       return NewIncAlign;
1440b57cec5SDimitry Andric     }
1455ffd83dbSDimitry Andric     if (NewIncAlign > NewAlign) {
1465ffd83dbSDimitry Andric       LLVM_DEBUG(dbgs() << "\tnew start/inc alignment: " << DebugStr(NewAlign)
1470b57cec5SDimitry Andric                         << "\n");
1485ffd83dbSDimitry Andric       return NewAlign;
1490b57cec5SDimitry Andric     }
1505ffd83dbSDimitry Andric     assert(NewIncAlign == NewAlign);
1515ffd83dbSDimitry Andric     LLVM_DEBUG(dbgs() << "\tnew start/inc alignment: " << DebugStr(NewAlign)
1520b57cec5SDimitry Andric                       << "\n");
1535ffd83dbSDimitry Andric     return NewAlign;
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric 
1565ffd83dbSDimitry Andric   return Align(1);
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric bool AlignmentFromAssumptionsPass::extractAlignmentInfo(CallInst *I,
160e8d8bef9SDimitry Andric                                                         unsigned Idx,
1610b57cec5SDimitry Andric                                                         Value *&AAPtr,
1620b57cec5SDimitry Andric                                                         const SCEV *&AlignSCEV,
1630b57cec5SDimitry Andric                                                         const SCEV *&OffSCEV) {
164e8d8bef9SDimitry Andric   Type *Int64Ty = Type::getInt64Ty(I->getContext());
165e8d8bef9SDimitry Andric   OperandBundleUse AlignOB = I->getOperandBundleAt(Idx);
166e8d8bef9SDimitry Andric   if (AlignOB.getTagName() != "align")
1670b57cec5SDimitry Andric     return false;
168e8d8bef9SDimitry Andric   assert(AlignOB.Inputs.size() >= 2);
169e8d8bef9SDimitry Andric   AAPtr = AlignOB.Inputs[0].get();
170e8d8bef9SDimitry Andric   // TODO: Consider accumulating the offset to the base.
171e8d8bef9SDimitry Andric   AAPtr = AAPtr->stripPointerCastsSameRepresentation();
172e8d8bef9SDimitry Andric   AlignSCEV = SE->getSCEV(AlignOB.Inputs[1].get());
173e8d8bef9SDimitry Andric   AlignSCEV = SE->getTruncateOrZeroExtend(AlignSCEV, Int64Ty);
17469ade1e0SDimitry Andric   if (!isa<SCEVConstant>(AlignSCEV))
17569ade1e0SDimitry Andric     // Added to suppress a crash because consumer doesn't expect non-constant
17669ade1e0SDimitry Andric     // alignments in the assume bundle.  TODO: Consider generalizing caller.
17769ade1e0SDimitry Andric     return false;
178*5f757f3fSDimitry Andric   if (!cast<SCEVConstant>(AlignSCEV)->getAPInt().isPowerOf2())
179*5f757f3fSDimitry Andric     // Only power of two alignments are supported.
180*5f757f3fSDimitry Andric     return false;
181e8d8bef9SDimitry Andric   if (AlignOB.Inputs.size() == 3)
182e8d8bef9SDimitry Andric     OffSCEV = SE->getSCEV(AlignOB.Inputs[2].get());
183e8d8bef9SDimitry Andric   else
1840b57cec5SDimitry Andric     OffSCEV = SE->getZero(Int64Ty);
185e8d8bef9SDimitry Andric   OffSCEV = SE->getTruncateOrZeroExtend(OffSCEV, Int64Ty);
1860b57cec5SDimitry Andric   return true;
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
189e8d8bef9SDimitry Andric bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall,
190e8d8bef9SDimitry Andric                                                      unsigned Idx) {
1910b57cec5SDimitry Andric   Value *AAPtr;
1920b57cec5SDimitry Andric   const SCEV *AlignSCEV, *OffSCEV;
193e8d8bef9SDimitry Andric   if (!extractAlignmentInfo(ACall, Idx, AAPtr, AlignSCEV, OffSCEV))
1940b57cec5SDimitry Andric     return false;
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   // Skip ConstantPointerNull and UndefValue.  Assumptions on these shouldn't
1970b57cec5SDimitry Andric   // affect other users.
1980b57cec5SDimitry Andric   if (isa<ConstantData>(AAPtr))
1990b57cec5SDimitry Andric     return false;
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   const SCEV *AASCEV = SE->getSCEV(AAPtr);
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   // Apply the assumption to all other users of the specified pointer.
2040b57cec5SDimitry Andric   SmallPtrSet<Instruction *, 32> Visited;
2050b57cec5SDimitry Andric   SmallVector<Instruction*, 16> WorkList;
2060b57cec5SDimitry Andric   for (User *J : AAPtr->users()) {
2070b57cec5SDimitry Andric     if (J == ACall)
2080b57cec5SDimitry Andric       continue;
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric     if (Instruction *K = dyn_cast<Instruction>(J))
2110b57cec5SDimitry Andric         WorkList.push_back(K);
2120b57cec5SDimitry Andric   }
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   while (!WorkList.empty()) {
2150b57cec5SDimitry Andric     Instruction *J = WorkList.pop_back_val();
2160b57cec5SDimitry Andric     if (LoadInst *LI = dyn_cast<LoadInst>(J)) {
217e8d8bef9SDimitry Andric       if (!isValidAssumeForContext(ACall, J, DT))
218e8d8bef9SDimitry Andric         continue;
2195ffd83dbSDimitry Andric       Align NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV,
2200b57cec5SDimitry Andric                                            LI->getPointerOperand(), SE);
2215ffd83dbSDimitry Andric       if (NewAlignment > LI->getAlign()) {
2225ffd83dbSDimitry Andric         LI->setAlignment(NewAlignment);
2230b57cec5SDimitry Andric         ++NumLoadAlignChanged;
2240b57cec5SDimitry Andric       }
2250b57cec5SDimitry Andric     } else if (StoreInst *SI = dyn_cast<StoreInst>(J)) {
226e8d8bef9SDimitry Andric       if (!isValidAssumeForContext(ACall, J, DT))
227e8d8bef9SDimitry Andric         continue;
2285ffd83dbSDimitry Andric       Align NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV,
2290b57cec5SDimitry Andric                                            SI->getPointerOperand(), SE);
2305ffd83dbSDimitry Andric       if (NewAlignment > SI->getAlign()) {
2315ffd83dbSDimitry Andric         SI->setAlignment(NewAlignment);
2320b57cec5SDimitry Andric         ++NumStoreAlignChanged;
2330b57cec5SDimitry Andric       }
2340b57cec5SDimitry Andric     } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(J)) {
235e8d8bef9SDimitry Andric       if (!isValidAssumeForContext(ACall, J, DT))
236e8d8bef9SDimitry Andric         continue;
2375ffd83dbSDimitry Andric       Align NewDestAlignment =
2385ffd83dbSDimitry Andric           getNewAlignment(AASCEV, AlignSCEV, OffSCEV, MI->getDest(), SE);
2390b57cec5SDimitry Andric 
2405ffd83dbSDimitry Andric       LLVM_DEBUG(dbgs() << "\tmem inst: " << DebugStr(NewDestAlignment)
2415ffd83dbSDimitry Andric                         << "\n";);
2425ffd83dbSDimitry Andric       if (NewDestAlignment > *MI->getDestAlign()) {
2430b57cec5SDimitry Andric         MI->setDestAlignment(NewDestAlignment);
2440b57cec5SDimitry Andric         ++NumMemIntAlignChanged;
2450b57cec5SDimitry Andric       }
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric       // For memory transfers, there is also a source alignment that
2480b57cec5SDimitry Andric       // can be set.
2490b57cec5SDimitry Andric       if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) {
2505ffd83dbSDimitry Andric         Align NewSrcAlignment =
2515ffd83dbSDimitry Andric             getNewAlignment(AASCEV, AlignSCEV, OffSCEV, MTI->getSource(), SE);
2520b57cec5SDimitry Andric 
2535ffd83dbSDimitry Andric         LLVM_DEBUG(dbgs() << "\tmem trans: " << DebugStr(NewSrcAlignment)
2545ffd83dbSDimitry Andric                           << "\n";);
2550b57cec5SDimitry Andric 
2565ffd83dbSDimitry Andric         if (NewSrcAlignment > *MTI->getSourceAlign()) {
2570b57cec5SDimitry Andric           MTI->setSourceAlignment(NewSrcAlignment);
2580b57cec5SDimitry Andric           ++NumMemIntAlignChanged;
2590b57cec5SDimitry Andric         }
2600b57cec5SDimitry Andric       }
2610b57cec5SDimitry Andric     }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric     // Now that we've updated that use of the pointer, look for other uses of
2640b57cec5SDimitry Andric     // the pointer to update.
2650b57cec5SDimitry Andric     Visited.insert(J);
266*5f757f3fSDimitry Andric     if (isa<GetElementPtrInst>(J) || isa<PHINode>(J))
267*5f757f3fSDimitry Andric       for (auto &U : J->uses()) {
268*5f757f3fSDimitry Andric         if (U->getType()->isPointerTy()) {
269*5f757f3fSDimitry Andric           Instruction *K = cast<Instruction>(U.getUser());
270*5f757f3fSDimitry Andric           StoreInst *SI = dyn_cast<StoreInst>(K);
271*5f757f3fSDimitry Andric           if (SI && SI->getPointerOperandIndex() != U.getOperandNo())
272*5f757f3fSDimitry Andric             continue;
273e8d8bef9SDimitry Andric           if (!Visited.count(K))
2740b57cec5SDimitry Andric             WorkList.push_back(K);
2750b57cec5SDimitry Andric         }
2760b57cec5SDimitry Andric       }
277*5f757f3fSDimitry Andric   }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   return true;
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric bool AlignmentFromAssumptionsPass::runImpl(Function &F, AssumptionCache &AC,
2830b57cec5SDimitry Andric                                            ScalarEvolution *SE_,
2840b57cec5SDimitry Andric                                            DominatorTree *DT_) {
2850b57cec5SDimitry Andric   SE = SE_;
2860b57cec5SDimitry Andric   DT = DT_;
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   bool Changed = false;
2890b57cec5SDimitry Andric   for (auto &AssumeVH : AC.assumptions())
290e8d8bef9SDimitry Andric     if (AssumeVH) {
291e8d8bef9SDimitry Andric       CallInst *Call = cast<CallInst>(AssumeVH);
292e8d8bef9SDimitry Andric       for (unsigned Idx = 0; Idx < Call->getNumOperandBundles(); Idx++)
293e8d8bef9SDimitry Andric         Changed |= processAssumption(Call, Idx);
294e8d8bef9SDimitry Andric     }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   return Changed;
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric PreservedAnalyses
3000b57cec5SDimitry Andric AlignmentFromAssumptionsPass::run(Function &F, FunctionAnalysisManager &AM) {
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F);
3030b57cec5SDimitry Andric   ScalarEvolution &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
3040b57cec5SDimitry Andric   DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F);
3050b57cec5SDimitry Andric   if (!runImpl(F, AC, &SE, &DT))
3060b57cec5SDimitry Andric     return PreservedAnalyses::all();
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   PreservedAnalyses PA;
3090b57cec5SDimitry Andric   PA.preserveSet<CFGAnalyses>();
3100b57cec5SDimitry Andric   PA.preserve<ScalarEvolutionAnalysis>();
3110b57cec5SDimitry Andric   return PA;
3120b57cec5SDimitry Andric }
313