1d67e4639SHal Finkel //===----------------------- AlignmentFromAssumptions.cpp -----------------===//
2d67e4639SHal Finkel //                  Set Load/Store Alignments From Assumptions
3d67e4639SHal Finkel //
42946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
52946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
62946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7d67e4639SHal Finkel //
8d67e4639SHal Finkel //===----------------------------------------------------------------------===//
9d67e4639SHal Finkel //
10d67e4639SHal Finkel // This file implements a ScalarEvolution-based transformation to set
11d67e4639SHal Finkel // the alignments of load, stores and memory intrinsics based on the truth
12d67e4639SHal Finkel // expressions of assume intrinsics. The primary motivation is to handle
13d67e4639SHal Finkel // complex alignment assumptions that apply to vector loads and stores that
14d67e4639SHal Finkel // appear after vectorization and unrolling.
15d67e4639SHal Finkel //
16d67e4639SHal Finkel //===----------------------------------------------------------------------===//
17d67e4639SHal Finkel 
18a4c2d150SSean Silva #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h"
19d67e4639SHal Finkel #include "llvm/ADT/SmallPtrSet.h"
20d67e4639SHal Finkel #include "llvm/ADT/Statistic.h"
21494393b7SHal Finkel #include "llvm/Analysis/AliasAnalysis.h"
22aec2fa35SDaniel Jasper #include "llvm/Analysis/AssumptionCache.h"
236bda14b3SChandler Carruth #include "llvm/Analysis/GlobalsModRef.h"
24d67e4639SHal Finkel #include "llvm/Analysis/LoopInfo.h"
25d67e4639SHal Finkel #include "llvm/Analysis/ScalarEvolutionExpressions.h"
26799003bfSBenjamin Kramer #include "llvm/Analysis/ValueTracking.h"
27d67e4639SHal Finkel #include "llvm/IR/Dominators.h"
28d67e4639SHal Finkel #include "llvm/IR/Instruction.h"
29*59630917Sserge-sans-paille #include "llvm/IR/Instructions.h"
301c2d2c88SSimon Pilgrim #include "llvm/IR/IntrinsicInst.h"
31*59630917Sserge-sans-paille #include "llvm/InitializePasses.h"
32d67e4639SHal Finkel #include "llvm/Support/Debug.h"
33d67e4639SHal Finkel #include "llvm/Support/raw_ostream.h"
346bda14b3SChandler Carruth #include "llvm/Transforms/Scalar.h"
3571acce68SMindong Chen 
3671acce68SMindong Chen #define AA_NAME "alignment-from-assumptions"
3771acce68SMindong Chen #define DEBUG_TYPE AA_NAME
38d67e4639SHal Finkel using namespace llvm;
39d67e4639SHal Finkel 
40d67e4639SHal Finkel STATISTIC(NumLoadAlignChanged,
41d67e4639SHal Finkel   "Number of loads changed by alignment assumptions");
42d67e4639SHal Finkel STATISTIC(NumStoreAlignChanged,
43d67e4639SHal Finkel   "Number of stores changed by alignment assumptions");
44d67e4639SHal Finkel STATISTIC(NumMemIntAlignChanged,
45d67e4639SHal Finkel   "Number of memory intrinsics changed by alignment assumptions");
46d67e4639SHal Finkel 
47d67e4639SHal Finkel namespace {
48d67e4639SHal Finkel struct AlignmentFromAssumptions : public FunctionPass {
49d67e4639SHal Finkel   static char ID; // Pass identification, replacement for typeid
AlignmentFromAssumptions__anonce0ea23c0111::AlignmentFromAssumptions50d67e4639SHal Finkel   AlignmentFromAssumptions() : FunctionPass(ID) {
51d67e4639SHal Finkel     initializeAlignmentFromAssumptionsPass(*PassRegistry::getPassRegistry());
52d67e4639SHal Finkel   }
53d67e4639SHal Finkel 
54f817c1cbSAlexander Kornienko   bool runOnFunction(Function &F) override;
55d67e4639SHal Finkel 
getAnalysisUsage__anonce0ea23c0111::AlignmentFromAssumptions56f817c1cbSAlexander Kornienko   void getAnalysisUsage(AnalysisUsage &AU) const override {
57aec2fa35SDaniel Jasper     AU.addRequired<AssumptionCacheTracker>();
582f1fd165SChandler Carruth     AU.addRequired<ScalarEvolutionWrapperPass>();
59d67e4639SHal Finkel     AU.addRequired<DominatorTreeWrapperPass>();
60d67e4639SHal Finkel 
61d67e4639SHal Finkel     AU.setPreservesCFG();
62494393b7SHal Finkel     AU.addPreserved<AAResultsWrapperPass>();
63494393b7SHal Finkel     AU.addPreserved<GlobalsAAWrapperPass>();
644f8f307cSChandler Carruth     AU.addPreserved<LoopInfoWrapperPass>();
65d67e4639SHal Finkel     AU.addPreserved<DominatorTreeWrapperPass>();
662f1fd165SChandler Carruth     AU.addPreserved<ScalarEvolutionWrapperPass>();
67d67e4639SHal Finkel   }
68d67e4639SHal Finkel 
69a4c2d150SSean Silva   AlignmentFromAssumptionsPass Impl;
70d67e4639SHal Finkel };
71f00654e3SAlexander Kornienko }
72d67e4639SHal Finkel 
73d67e4639SHal Finkel char AlignmentFromAssumptions::ID = 0;
74d67e4639SHal Finkel static const char aip_name[] = "Alignment from assumptions";
INITIALIZE_PASS_BEGIN(AlignmentFromAssumptions,AA_NAME,aip_name,false,false)75d67e4639SHal Finkel INITIALIZE_PASS_BEGIN(AlignmentFromAssumptions, AA_NAME,
76d67e4639SHal Finkel                       aip_name, false, false)
77aec2fa35SDaniel Jasper INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
78d67e4639SHal Finkel INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
792f1fd165SChandler Carruth INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
80d67e4639SHal Finkel INITIALIZE_PASS_END(AlignmentFromAssumptions, AA_NAME,
81d67e4639SHal Finkel                     aip_name, false, false)
82d67e4639SHal Finkel 
83d67e4639SHal Finkel FunctionPass *llvm::createAlignmentFromAssumptionsPass() {
84d67e4639SHal Finkel   return new AlignmentFromAssumptions();
85d67e4639SHal Finkel }
86d67e4639SHal Finkel 
87d67e4639SHal Finkel // Given an expression for the (constant) alignment, AlignSCEV, and an
88d67e4639SHal Finkel // expression for the displacement between a pointer and the aligned address,
898fc3c6c0SAndrew Trick // DiffSCEV, compute the alignment of the displaced pointer if it can be reduced
908fc3c6c0SAndrew Trick // to a constant. Using SCEV to compute alignment handles the case where
918fc3c6c0SAndrew Trick // DiffSCEV is a recurrence with constant start such that the aligned offset
928fc3c6c0SAndrew Trick // is constant. e.g. {16,+,32} % 32 -> 16.
getNewAlignmentDiff(const SCEV * DiffSCEV,const SCEV * AlignSCEV,ScalarEvolution * SE)9380828634SGuillaume Chatelet static MaybeAlign getNewAlignmentDiff(const SCEV *DiffSCEV,
94d67e4639SHal Finkel                                       const SCEV *AlignSCEV,
95d67e4639SHal Finkel                                       ScalarEvolution *SE) {
96d67e4639SHal Finkel   // DiffUnits = Diff % int64_t(Alignment)
973fc933afSFangrui Song   const SCEV *DiffUnitsSCEV = SE->getURemExpr(DiffSCEV, AlignSCEV);
98d67e4639SHal Finkel 
99d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << "\talignment relative to " << *AlignSCEV << " is "
100d34e60caSNicola Zaghen                     << *DiffUnitsSCEV << " (diff: " << *DiffSCEV << ")\n");
101d67e4639SHal Finkel 
102d67e4639SHal Finkel   if (const SCEVConstant *ConstDUSCEV =
103d67e4639SHal Finkel       dyn_cast<SCEVConstant>(DiffUnitsSCEV)) {
104d67e4639SHal Finkel     int64_t DiffUnits = ConstDUSCEV->getValue()->getSExtValue();
105d67e4639SHal Finkel 
106d67e4639SHal Finkel     // If the displacement is an exact multiple of the alignment, then the
107d67e4639SHal Finkel     // displaced pointer has the same alignment as the aligned pointer, so
108d67e4639SHal Finkel     // return the alignment value.
109d67e4639SHal Finkel     if (!DiffUnits)
11080828634SGuillaume Chatelet       return cast<SCEVConstant>(AlignSCEV)->getValue()->getAlignValue();
111d67e4639SHal Finkel 
112d67e4639SHal Finkel     // If the displacement is not an exact multiple, but the remainder is a
113d67e4639SHal Finkel     // constant, then return this remainder (but only if it is a power of 2).
1147bd1f7cbSBenjamin Kramer     uint64_t DiffUnitsAbs = std::abs(DiffUnits);
115d67e4639SHal Finkel     if (isPowerOf2_64(DiffUnitsAbs))
11680828634SGuillaume Chatelet       return Align(DiffUnitsAbs);
117d67e4639SHal Finkel   }
118d67e4639SHal Finkel 
11980828634SGuillaume Chatelet   return None;
120d67e4639SHal Finkel }
121d67e4639SHal Finkel 
122d67e4639SHal Finkel // There is an address given by an offset OffSCEV from AASCEV which has an
123d67e4639SHal Finkel // alignment AlignSCEV. Use that information, if possible, to compute a new
124d67e4639SHal Finkel // alignment for Ptr.
getNewAlignment(const SCEV * AASCEV,const SCEV * AlignSCEV,const SCEV * OffSCEV,Value * Ptr,ScalarEvolution * SE)12580828634SGuillaume Chatelet static Align getNewAlignment(const SCEV *AASCEV, const SCEV *AlignSCEV,
126d67e4639SHal Finkel                              const SCEV *OffSCEV, Value *Ptr,
127d67e4639SHal Finkel                              ScalarEvolution *SE) {
128d67e4639SHal Finkel   const SCEV *PtrSCEV = SE->getSCEV(Ptr);
1294bf015c0SRichard Diamond   // On a platform with 32-bit allocas, but 64-bit flat/global pointer sizes
1304bf015c0SRichard Diamond   // (*cough* AMDGPU), the effective SCEV type of AASCEV and PtrSCEV
1314bf015c0SRichard Diamond   // may disagree. Trunc/extend so they agree.
1324bf015c0SRichard Diamond   PtrSCEV = SE->getTruncateOrZeroExtend(
1334bf015c0SRichard Diamond       PtrSCEV, SE->getEffectiveSCEVType(AASCEV->getType()));
134d67e4639SHal Finkel   const SCEV *DiffSCEV = SE->getMinusSCEV(PtrSCEV, AASCEV);
1357ac1c7beSEli Friedman   if (isa<SCEVCouldNotCompute>(DiffSCEV))
1367ac1c7beSEli Friedman     return Align(1);
137d67e4639SHal Finkel 
138f83e1f7fSHal Finkel   // On 32-bit platforms, DiffSCEV might now have type i32 -- we've always
139f83e1f7fSHal Finkel   // sign-extended OffSCEV to i64, so make sure they agree again.
140f83e1f7fSHal Finkel   DiffSCEV = SE->getNoopOrSignExtend(DiffSCEV, OffSCEV->getType());
141f83e1f7fSHal Finkel 
142d67e4639SHal Finkel   // What we really want to know is the overall offset to the aligned
143d67e4639SHal Finkel   // address. This address is displaced by the provided offset.
144c6647693SJuneyoung Lee   DiffSCEV = SE->getAddExpr(DiffSCEV, OffSCEV);
145d67e4639SHal Finkel 
146d34e60caSNicola Zaghen   LLVM_DEBUG(dbgs() << "AFI: alignment of " << *Ptr << " relative to "
147d34e60caSNicola Zaghen                     << *AlignSCEV << " and offset " << *OffSCEV
148d34e60caSNicola Zaghen                     << " using diff " << *DiffSCEV << "\n");
149d67e4639SHal Finkel 
15080828634SGuillaume Chatelet   if (MaybeAlign NewAlignment = getNewAlignmentDiff(DiffSCEV, AlignSCEV, SE)) {
15180828634SGuillaume Chatelet     LLVM_DEBUG(dbgs() << "\tnew alignment: " << DebugStr(NewAlignment) << "\n");
15280828634SGuillaume Chatelet     return *NewAlignment;
15380828634SGuillaume Chatelet   }
154d67e4639SHal Finkel 
15580828634SGuillaume Chatelet   if (const SCEVAddRecExpr *DiffARSCEV = dyn_cast<SCEVAddRecExpr>(DiffSCEV)) {
156d67e4639SHal Finkel     // The relative offset to the alignment assumption did not yield a constant,
157d67e4639SHal Finkel     // but we should try harder: if we assume that a is 32-byte aligned, then in
158d67e4639SHal Finkel     // for (i = 0; i < 1024; i += 4) r += a[i]; not all of the loads from a are
159d67e4639SHal Finkel     // 32-byte aligned, but instead alternate between 32 and 16-byte alignment.
160d67e4639SHal Finkel     // As a result, the new alignment will not be a constant, but can still
161d67e4639SHal Finkel     // be improved over the default (of 4) to 16.
162d67e4639SHal Finkel 
163d67e4639SHal Finkel     const SCEV *DiffStartSCEV = DiffARSCEV->getStart();
164d67e4639SHal Finkel     const SCEV *DiffIncSCEV = DiffARSCEV->getStepRecurrence(*SE);
165d67e4639SHal Finkel 
166d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "\ttrying start/inc alignment using start "
167d34e60caSNicola Zaghen                       << *DiffStartSCEV << " and inc " << *DiffIncSCEV << "\n");
168d67e4639SHal Finkel 
169d67e4639SHal Finkel     // Now compute the new alignment using the displacement to the value in the
170d67e4639SHal Finkel     // first iteration, and also the alignment using the per-iteration delta.
171d67e4639SHal Finkel     // If these are the same, then use that answer. Otherwise, use the smaller
172d67e4639SHal Finkel     // one, but only if it divides the larger one.
17380828634SGuillaume Chatelet     MaybeAlign NewAlignment = getNewAlignmentDiff(DiffStartSCEV, AlignSCEV, SE);
17480828634SGuillaume Chatelet     MaybeAlign NewIncAlignment =
17580828634SGuillaume Chatelet         getNewAlignmentDiff(DiffIncSCEV, AlignSCEV, SE);
176d67e4639SHal Finkel 
17780828634SGuillaume Chatelet     LLVM_DEBUG(dbgs() << "\tnew start alignment: " << DebugStr(NewAlignment)
17880828634SGuillaume Chatelet                       << "\n");
17980828634SGuillaume Chatelet     LLVM_DEBUG(dbgs() << "\tnew inc alignment: " << DebugStr(NewIncAlignment)
18080828634SGuillaume Chatelet                       << "\n");
1811e34ab98SGuillaume Chatelet 
18280828634SGuillaume Chatelet     if (!NewAlignment || !NewIncAlignment)
18380828634SGuillaume Chatelet       return Align(1);
18480828634SGuillaume Chatelet 
18580828634SGuillaume Chatelet     const Align NewAlign = *NewAlignment;
18680828634SGuillaume Chatelet     const Align NewIncAlign = *NewIncAlignment;
18780828634SGuillaume Chatelet     if (NewAlign > NewIncAlign) {
18880828634SGuillaume Chatelet       LLVM_DEBUG(dbgs() << "\tnew start/inc alignment: "
18980828634SGuillaume Chatelet                         << DebugStr(NewIncAlign) << "\n");
19080828634SGuillaume Chatelet       return NewIncAlign;
191d67e4639SHal Finkel     }
19280828634SGuillaume Chatelet     if (NewIncAlign > NewAlign) {
19380828634SGuillaume Chatelet       LLVM_DEBUG(dbgs() << "\tnew start/inc alignment: " << DebugStr(NewAlign)
1946000478fSGuillaume Chatelet                         << "\n");
19580828634SGuillaume Chatelet       return NewAlign;
1966000478fSGuillaume Chatelet     }
19780828634SGuillaume Chatelet     assert(NewIncAlign == NewAlign);
19880828634SGuillaume Chatelet     LLVM_DEBUG(dbgs() << "\tnew start/inc alignment: " << DebugStr(NewAlign)
1996000478fSGuillaume Chatelet                       << "\n");
20080828634SGuillaume Chatelet     return NewAlign;
201d67e4639SHal Finkel   }
202d67e4639SHal Finkel 
20380828634SGuillaume Chatelet   return Align(1);
204d67e4639SHal Finkel }
205d67e4639SHal Finkel 
extractAlignmentInfo(CallInst * I,unsigned Idx,Value * & AAPtr,const SCEV * & AlignSCEV,const SCEV * & OffSCEV)206a4c2d150SSean Silva bool AlignmentFromAssumptionsPass::extractAlignmentInfo(CallInst *I,
20778de7297STyker                                                         unsigned Idx,
208a4c2d150SSean Silva                                                         Value *&AAPtr,
209a4c2d150SSean Silva                                                         const SCEV *&AlignSCEV,
210d67e4639SHal Finkel                                                         const SCEV *&OffSCEV) {
21178de7297STyker   Type *Int64Ty = Type::getInt64Ty(I->getContext());
21278de7297STyker   OperandBundleUse AlignOB = I->getOperandBundleAt(Idx);
21378de7297STyker   if (AlignOB.getTagName() != "align")
214c95ffadbSTyker     return false;
21578de7297STyker   assert(AlignOB.Inputs.size() >= 2);
21678de7297STyker   AAPtr = AlignOB.Inputs[0].get();
21778de7297STyker   // TODO: Consider accumulating the offset to the base.
21878de7297STyker   AAPtr = AAPtr->stripPointerCastsSameRepresentation();
21978de7297STyker   AlignSCEV = SE->getSCEV(AlignOB.Inputs[1].get());
22078de7297STyker   AlignSCEV = SE->getTruncateOrZeroExtend(AlignSCEV, Int64Ty);
2219b45fd90SPhilip Reames   if (!isa<SCEVConstant>(AlignSCEV))
2229b45fd90SPhilip Reames     // Added to suppress a crash because consumer doesn't expect non-constant
2239b45fd90SPhilip Reames     // alignments in the assume bundle.  TODO: Consider generalizing caller.
2249b45fd90SPhilip Reames     return false;
22578de7297STyker   if (AlignOB.Inputs.size() == 3)
22678de7297STyker     OffSCEV = SE->getSCEV(AlignOB.Inputs[2].get());
22778de7297STyker   else
2287ea46aeeSRoman Lebedev     OffSCEV = SE->getZero(Int64Ty);
22978de7297STyker   OffSCEV = SE->getTruncateOrZeroExtend(OffSCEV, Int64Ty);
2307ea46aeeSRoman Lebedev   return true;
231c95ffadbSTyker }
232d67e4639SHal Finkel 
processAssumption(CallInst * ACall,unsigned Idx)23378de7297STyker bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall,
23478de7297STyker                                                      unsigned Idx) {
235d67e4639SHal Finkel   Value *AAPtr;
236d67e4639SHal Finkel   const SCEV *AlignSCEV, *OffSCEV;
23778de7297STyker   if (!extractAlignmentInfo(ACall, Idx, AAPtr, AlignSCEV, OffSCEV))
238d67e4639SHal Finkel     return false;
239d67e4639SHal Finkel 
2404fd9b7e1SDuncan P. N. Exon Smith   // Skip ConstantPointerNull and UndefValue.  Assumptions on these shouldn't
2414fd9b7e1SDuncan P. N. Exon Smith   // affect other users.
2424fd9b7e1SDuncan P. N. Exon Smith   if (isa<ConstantData>(AAPtr))
2434fd9b7e1SDuncan P. N. Exon Smith     return false;
2444fd9b7e1SDuncan P. N. Exon Smith 
245d67e4639SHal Finkel   const SCEV *AASCEV = SE->getSCEV(AAPtr);
246d67e4639SHal Finkel 
247d67e4639SHal Finkel   // Apply the assumption to all other users of the specified pointer.
248d67e4639SHal Finkel   SmallPtrSet<Instruction *, 32> Visited;
249d67e4639SHal Finkel   SmallVector<Instruction*, 16> WorkList;
250d67e4639SHal Finkel   for (User *J : AAPtr->users()) {
251d67e4639SHal Finkel     if (J == ACall)
252d67e4639SHal Finkel       continue;
253d67e4639SHal Finkel 
254d67e4639SHal Finkel     if (Instruction *K = dyn_cast<Instruction>(J))
255d67e4639SHal Finkel         WorkList.push_back(K);
256d67e4639SHal Finkel   }
257d67e4639SHal Finkel 
258d67e4639SHal Finkel   while (!WorkList.empty()) {
259d67e4639SHal Finkel     Instruction *J = WorkList.pop_back_val();
260d67e4639SHal Finkel     if (LoadInst *LI = dyn_cast<LoadInst>(J)) {
26178de7297STyker       if (!isValidAssumeForContext(ACall, J, DT))
26278de7297STyker         continue;
26380828634SGuillaume Chatelet       Align NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV,
264d67e4639SHal Finkel                                            LI->getPointerOperand(), SE);
26552e98f62SNikita Popov       if (NewAlignment > LI->getAlign()) {
26680828634SGuillaume Chatelet         LI->setAlignment(NewAlignment);
267d67e4639SHal Finkel         ++NumLoadAlignChanged;
268d67e4639SHal Finkel       }
269d67e4639SHal Finkel     } else if (StoreInst *SI = dyn_cast<StoreInst>(J)) {
27078de7297STyker       if (!isValidAssumeForContext(ACall, J, DT))
27178de7297STyker         continue;
27280828634SGuillaume Chatelet       Align NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV,
273d67e4639SHal Finkel                                            SI->getPointerOperand(), SE);
27452e98f62SNikita Popov       if (NewAlignment > SI->getAlign()) {
27580828634SGuillaume Chatelet         SI->setAlignment(NewAlignment);
276d67e4639SHal Finkel         ++NumStoreAlignChanged;
277d67e4639SHal Finkel       }
278d67e4639SHal Finkel     } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(J)) {
27978de7297STyker       if (!isValidAssumeForContext(ACall, J, DT))
28078de7297STyker         continue;
28180828634SGuillaume Chatelet       Align NewDestAlignment =
28280828634SGuillaume Chatelet           getNewAlignment(AASCEV, AlignSCEV, OffSCEV, MI->getDest(), SE);
283d67e4639SHal Finkel 
28480828634SGuillaume Chatelet       LLVM_DEBUG(dbgs() << "\tmem inst: " << DebugStr(NewDestAlignment)
28580828634SGuillaume Chatelet                         << "\n";);
28680828634SGuillaume Chatelet       if (NewDestAlignment > *MI->getDestAlign()) {
28720c9207bSDaniel Neilson         MI->setDestAlignment(NewDestAlignment);
28820c9207bSDaniel Neilson         ++NumMemIntAlignChanged;
28920c9207bSDaniel Neilson       }
29020c9207bSDaniel Neilson 
29120c9207bSDaniel Neilson       // For memory transfers, there is also a source alignment that
29220c9207bSDaniel Neilson       // can be set.
293d67e4639SHal Finkel       if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) {
29480828634SGuillaume Chatelet         Align NewSrcAlignment =
29580828634SGuillaume Chatelet             getNewAlignment(AASCEV, AlignSCEV, OffSCEV, MTI->getSource(), SE);
296d67e4639SHal Finkel 
29780828634SGuillaume Chatelet         LLVM_DEBUG(dbgs() << "\tmem trans: " << DebugStr(NewSrcAlignment)
29880828634SGuillaume Chatelet                           << "\n";);
299d67e4639SHal Finkel 
30080828634SGuillaume Chatelet         if (NewSrcAlignment > *MTI->getSourceAlign()) {
30120c9207bSDaniel Neilson           MTI->setSourceAlignment(NewSrcAlignment);
302d67e4639SHal Finkel           ++NumMemIntAlignChanged;
303d67e4639SHal Finkel         }
304d67e4639SHal Finkel       }
305d67e4639SHal Finkel     }
306d67e4639SHal Finkel 
307d67e4639SHal Finkel     // Now that we've updated that use of the pointer, look for other uses of
308d67e4639SHal Finkel     // the pointer to update.
309d67e4639SHal Finkel     Visited.insert(J);
310d67e4639SHal Finkel     for (User *UJ : J->users()) {
311d67e4639SHal Finkel       Instruction *K = cast<Instruction>(UJ);
31278de7297STyker       if (!Visited.count(K))
313d67e4639SHal Finkel         WorkList.push_back(K);
314d67e4639SHal Finkel     }
315d67e4639SHal Finkel   }
316d67e4639SHal Finkel 
317d67e4639SHal Finkel   return true;
318d67e4639SHal Finkel }
319d67e4639SHal Finkel 
runOnFunction(Function & F)320d67e4639SHal Finkel bool AlignmentFromAssumptions::runOnFunction(Function &F) {
32150271f78SAndrew Kaylor   if (skipFunction(F))
32250271f78SAndrew Kaylor     return false;
32350271f78SAndrew Kaylor 
324aec2fa35SDaniel Jasper   auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
325a4c2d150SSean Silva   ScalarEvolution *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
326a4c2d150SSean Silva   DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
327a4c2d150SSean Silva 
328aec2fa35SDaniel Jasper   return Impl.runImpl(F, AC, SE, DT);
329a4c2d150SSean Silva }
330a4c2d150SSean Silva 
runImpl(Function & F,AssumptionCache & AC,ScalarEvolution * SE_,DominatorTree * DT_)331aec2fa35SDaniel Jasper bool AlignmentFromAssumptionsPass::runImpl(Function &F, AssumptionCache &AC,
332aec2fa35SDaniel Jasper                                            ScalarEvolution *SE_,
333a4c2d150SSean Silva                                            DominatorTree *DT_) {
334a4c2d150SSean Silva   SE = SE_;
335a4c2d150SSean Silva   DT = DT_;
336d67e4639SHal Finkel 
337a4c2d150SSean Silva   bool Changed = false;
338606aa622SMichael Kruse   for (auto &AssumeVH : AC.assumptions())
339606aa622SMichael Kruse     if (AssumeVH) {
340606aa622SMichael Kruse       CallInst *Call = cast<CallInst>(AssumeVH);
34178de7297STyker       for (unsigned Idx = 0; Idx < Call->getNumOperandBundles(); Idx++)
34278de7297STyker         Changed |= processAssumption(Call, Idx);
34378de7297STyker     }
344d67e4639SHal Finkel 
345d67e4639SHal Finkel   return Changed;
346d67e4639SHal Finkel }
347d67e4639SHal Finkel 
348a4c2d150SSean Silva PreservedAnalyses
run(Function & F,FunctionAnalysisManager & AM)349a4c2d150SSean Silva AlignmentFromAssumptionsPass::run(Function &F, FunctionAnalysisManager &AM) {
350a4c2d150SSean Silva 
351aec2fa35SDaniel Jasper   AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F);
352a4c2d150SSean Silva   ScalarEvolution &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
353a4c2d150SSean Silva   DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F);
3546acdca78SChandler Carruth   if (!runImpl(F, AC, &SE, &DT))
355a4c2d150SSean Silva     return PreservedAnalyses::all();
356ca68a3ecSChandler Carruth 
357a4c2d150SSean Silva   PreservedAnalyses PA;
358ca68a3ecSChandler Carruth   PA.preserveSet<CFGAnalyses>();
359a4c2d150SSean Silva   PA.preserve<ScalarEvolutionAnalysis>();
360a4c2d150SSean Silva   return PA;
361a4c2d150SSean Silva }
362