xref: /aosp_15_r20/external/llvm/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===----------------------- AlignmentFromAssumptions.cpp -----------------===//
2*9880d681SAndroid Build Coastguard Worker //                  Set Load/Store Alignments From Assumptions
3*9880d681SAndroid Build Coastguard Worker //
4*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
5*9880d681SAndroid Build Coastguard Worker //
6*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
7*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
8*9880d681SAndroid Build Coastguard Worker //
9*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
10*9880d681SAndroid Build Coastguard Worker //
11*9880d681SAndroid Build Coastguard Worker // This file implements a ScalarEvolution-based transformation to set
12*9880d681SAndroid Build Coastguard Worker // the alignments of load, stores and memory intrinsics based on the truth
13*9880d681SAndroid Build Coastguard Worker // expressions of assume intrinsics. The primary motivation is to handle
14*9880d681SAndroid Build Coastguard Worker // complex alignment assumptions that apply to vector loads and stores that
15*9880d681SAndroid Build Coastguard Worker // appear after vectorization and unrolling.
16*9880d681SAndroid Build Coastguard Worker //
17*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
18*9880d681SAndroid Build Coastguard Worker 
19*9880d681SAndroid Build Coastguard Worker #define AA_NAME "alignment-from-assumptions"
20*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE AA_NAME
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Scalar.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallPtrSet.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AliasAnalysis.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/GlobalsModRef.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AssumptionCache.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/LoopInfo.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ScalarEvolutionExpressions.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ValueTracking.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constant.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Dominators.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instruction.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Intrinsics.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
38*9880d681SAndroid Build Coastguard Worker using namespace llvm;
39*9880d681SAndroid Build Coastguard Worker 
40*9880d681SAndroid Build Coastguard Worker STATISTIC(NumLoadAlignChanged,
41*9880d681SAndroid Build Coastguard Worker   "Number of loads changed by alignment assumptions");
42*9880d681SAndroid Build Coastguard Worker STATISTIC(NumStoreAlignChanged,
43*9880d681SAndroid Build Coastguard Worker   "Number of stores changed by alignment assumptions");
44*9880d681SAndroid Build Coastguard Worker STATISTIC(NumMemIntAlignChanged,
45*9880d681SAndroid Build Coastguard Worker   "Number of memory intrinsics changed by alignment assumptions");
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker namespace {
48*9880d681SAndroid Build Coastguard Worker struct AlignmentFromAssumptions : public FunctionPass {
49*9880d681SAndroid Build Coastguard Worker   static char ID; // Pass identification, replacement for typeid
AlignmentFromAssumptions__anonb22d2fa40111::AlignmentFromAssumptions50*9880d681SAndroid Build Coastguard Worker   AlignmentFromAssumptions() : FunctionPass(ID) {
51*9880d681SAndroid Build Coastguard Worker     initializeAlignmentFromAssumptionsPass(*PassRegistry::getPassRegistry());
52*9880d681SAndroid Build Coastguard Worker   }
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker   bool runOnFunction(Function &F) override;
55*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage__anonb22d2fa40111::AlignmentFromAssumptions56*9880d681SAndroid Build Coastguard Worker   void getAnalysisUsage(AnalysisUsage &AU) const override {
57*9880d681SAndroid Build Coastguard Worker     AU.addRequired<AssumptionCacheTracker>();
58*9880d681SAndroid Build Coastguard Worker     AU.addRequired<ScalarEvolutionWrapperPass>();
59*9880d681SAndroid Build Coastguard Worker     AU.addRequired<DominatorTreeWrapperPass>();
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker     AU.setPreservesCFG();
62*9880d681SAndroid Build Coastguard Worker     AU.addPreserved<AAResultsWrapperPass>();
63*9880d681SAndroid Build Coastguard Worker     AU.addPreserved<GlobalsAAWrapperPass>();
64*9880d681SAndroid Build Coastguard Worker     AU.addPreserved<LoopInfoWrapperPass>();
65*9880d681SAndroid Build Coastguard Worker     AU.addPreserved<DominatorTreeWrapperPass>();
66*9880d681SAndroid Build Coastguard Worker     AU.addPreserved<ScalarEvolutionWrapperPass>();
67*9880d681SAndroid Build Coastguard Worker   }
68*9880d681SAndroid Build Coastguard Worker 
69*9880d681SAndroid Build Coastguard Worker   AlignmentFromAssumptionsPass Impl;
70*9880d681SAndroid Build Coastguard Worker };
71*9880d681SAndroid Build Coastguard Worker }
72*9880d681SAndroid Build Coastguard Worker 
73*9880d681SAndroid Build Coastguard Worker char AlignmentFromAssumptions::ID = 0;
74*9880d681SAndroid Build Coastguard Worker static const char aip_name[] = "Alignment from assumptions";
INITIALIZE_PASS_BEGIN(AlignmentFromAssumptions,AA_NAME,aip_name,false,false)75*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(AlignmentFromAssumptions, AA_NAME,
76*9880d681SAndroid Build Coastguard Worker                       aip_name, false, false)
77*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
78*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
79*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
80*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(AlignmentFromAssumptions, AA_NAME,
81*9880d681SAndroid Build Coastguard Worker                     aip_name, false, false)
82*9880d681SAndroid Build Coastguard Worker 
83*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createAlignmentFromAssumptionsPass() {
84*9880d681SAndroid Build Coastguard Worker   return new AlignmentFromAssumptions();
85*9880d681SAndroid Build Coastguard Worker }
86*9880d681SAndroid Build Coastguard Worker 
87*9880d681SAndroid Build Coastguard Worker // Given an expression for the (constant) alignment, AlignSCEV, and an
88*9880d681SAndroid Build Coastguard Worker // expression for the displacement between a pointer and the aligned address,
89*9880d681SAndroid Build Coastguard Worker // DiffSCEV, compute the alignment of the displaced pointer if it can be reduced
90*9880d681SAndroid Build Coastguard Worker // to a constant. Using SCEV to compute alignment handles the case where
91*9880d681SAndroid Build Coastguard Worker // DiffSCEV is a recurrence with constant start such that the aligned offset
92*9880d681SAndroid Build Coastguard Worker // is constant. e.g. {16,+,32} % 32 -> 16.
getNewAlignmentDiff(const SCEV * DiffSCEV,const SCEV * AlignSCEV,ScalarEvolution * SE)93*9880d681SAndroid Build Coastguard Worker static unsigned getNewAlignmentDiff(const SCEV *DiffSCEV,
94*9880d681SAndroid Build Coastguard Worker                                     const SCEV *AlignSCEV,
95*9880d681SAndroid Build Coastguard Worker                                     ScalarEvolution *SE) {
96*9880d681SAndroid Build Coastguard Worker   // DiffUnits = Diff % int64_t(Alignment)
97*9880d681SAndroid Build Coastguard Worker   const SCEV *DiffAlignDiv = SE->getUDivExpr(DiffSCEV, AlignSCEV);
98*9880d681SAndroid Build Coastguard Worker   const SCEV *DiffAlign = SE->getMulExpr(DiffAlignDiv, AlignSCEV);
99*9880d681SAndroid Build Coastguard Worker   const SCEV *DiffUnitsSCEV = SE->getMinusSCEV(DiffAlign, DiffSCEV);
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "\talignment relative to " << *AlignSCEV << " is " <<
102*9880d681SAndroid Build Coastguard Worker                   *DiffUnitsSCEV << " (diff: " << *DiffSCEV << ")\n");
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker   if (const SCEVConstant *ConstDUSCEV =
105*9880d681SAndroid Build Coastguard Worker       dyn_cast<SCEVConstant>(DiffUnitsSCEV)) {
106*9880d681SAndroid Build Coastguard Worker     int64_t DiffUnits = ConstDUSCEV->getValue()->getSExtValue();
107*9880d681SAndroid Build Coastguard Worker 
108*9880d681SAndroid Build Coastguard Worker     // If the displacement is an exact multiple of the alignment, then the
109*9880d681SAndroid Build Coastguard Worker     // displaced pointer has the same alignment as the aligned pointer, so
110*9880d681SAndroid Build Coastguard Worker     // return the alignment value.
111*9880d681SAndroid Build Coastguard Worker     if (!DiffUnits)
112*9880d681SAndroid Build Coastguard Worker       return (unsigned)
113*9880d681SAndroid Build Coastguard Worker         cast<SCEVConstant>(AlignSCEV)->getValue()->getSExtValue();
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker     // If the displacement is not an exact multiple, but the remainder is a
116*9880d681SAndroid Build Coastguard Worker     // constant, then return this remainder (but only if it is a power of 2).
117*9880d681SAndroid Build Coastguard Worker     uint64_t DiffUnitsAbs = std::abs(DiffUnits);
118*9880d681SAndroid Build Coastguard Worker     if (isPowerOf2_64(DiffUnitsAbs))
119*9880d681SAndroid Build Coastguard Worker       return (unsigned) DiffUnitsAbs;
120*9880d681SAndroid Build Coastguard Worker   }
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker   return 0;
123*9880d681SAndroid Build Coastguard Worker }
124*9880d681SAndroid Build Coastguard Worker 
125*9880d681SAndroid Build Coastguard Worker // There is an address given by an offset OffSCEV from AASCEV which has an
126*9880d681SAndroid Build Coastguard Worker // alignment AlignSCEV. Use that information, if possible, to compute a new
127*9880d681SAndroid Build Coastguard Worker // alignment for Ptr.
getNewAlignment(const SCEV * AASCEV,const SCEV * AlignSCEV,const SCEV * OffSCEV,Value * Ptr,ScalarEvolution * SE)128*9880d681SAndroid Build Coastguard Worker static unsigned getNewAlignment(const SCEV *AASCEV, const SCEV *AlignSCEV,
129*9880d681SAndroid Build Coastguard Worker                                 const SCEV *OffSCEV, Value *Ptr,
130*9880d681SAndroid Build Coastguard Worker                                 ScalarEvolution *SE) {
131*9880d681SAndroid Build Coastguard Worker   const SCEV *PtrSCEV = SE->getSCEV(Ptr);
132*9880d681SAndroid Build Coastguard Worker   const SCEV *DiffSCEV = SE->getMinusSCEV(PtrSCEV, AASCEV);
133*9880d681SAndroid Build Coastguard Worker 
134*9880d681SAndroid Build Coastguard Worker   // On 32-bit platforms, DiffSCEV might now have type i32 -- we've always
135*9880d681SAndroid Build Coastguard Worker   // sign-extended OffSCEV to i64, so make sure they agree again.
136*9880d681SAndroid Build Coastguard Worker   DiffSCEV = SE->getNoopOrSignExtend(DiffSCEV, OffSCEV->getType());
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker   // What we really want to know is the overall offset to the aligned
139*9880d681SAndroid Build Coastguard Worker   // address. This address is displaced by the provided offset.
140*9880d681SAndroid Build Coastguard Worker   DiffSCEV = SE->getMinusSCEV(DiffSCEV, OffSCEV);
141*9880d681SAndroid Build Coastguard Worker 
142*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "AFI: alignment of " << *Ptr << " relative to " <<
143*9880d681SAndroid Build Coastguard Worker                   *AlignSCEV << " and offset " << *OffSCEV <<
144*9880d681SAndroid Build Coastguard Worker                   " using diff " << *DiffSCEV << "\n");
145*9880d681SAndroid Build Coastguard Worker 
146*9880d681SAndroid Build Coastguard Worker   unsigned NewAlignment = getNewAlignmentDiff(DiffSCEV, AlignSCEV, SE);
147*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "\tnew alignment: " << NewAlignment << "\n");
148*9880d681SAndroid Build Coastguard Worker 
149*9880d681SAndroid Build Coastguard Worker   if (NewAlignment) {
150*9880d681SAndroid Build Coastguard Worker     return NewAlignment;
151*9880d681SAndroid Build Coastguard Worker   } else if (const SCEVAddRecExpr *DiffARSCEV =
152*9880d681SAndroid Build Coastguard Worker              dyn_cast<SCEVAddRecExpr>(DiffSCEV)) {
153*9880d681SAndroid Build Coastguard Worker     // The relative offset to the alignment assumption did not yield a constant,
154*9880d681SAndroid Build Coastguard Worker     // but we should try harder: if we assume that a is 32-byte aligned, then in
155*9880d681SAndroid Build Coastguard Worker     // for (i = 0; i < 1024; i += 4) r += a[i]; not all of the loads from a are
156*9880d681SAndroid Build Coastguard Worker     // 32-byte aligned, but instead alternate between 32 and 16-byte alignment.
157*9880d681SAndroid Build Coastguard Worker     // As a result, the new alignment will not be a constant, but can still
158*9880d681SAndroid Build Coastguard Worker     // be improved over the default (of 4) to 16.
159*9880d681SAndroid Build Coastguard Worker 
160*9880d681SAndroid Build Coastguard Worker     const SCEV *DiffStartSCEV = DiffARSCEV->getStart();
161*9880d681SAndroid Build Coastguard Worker     const SCEV *DiffIncSCEV = DiffARSCEV->getStepRecurrence(*SE);
162*9880d681SAndroid Build Coastguard Worker 
163*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "\ttrying start/inc alignment using start " <<
164*9880d681SAndroid Build Coastguard Worker                     *DiffStartSCEV << " and inc " << *DiffIncSCEV << "\n");
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker     // Now compute the new alignment using the displacement to the value in the
167*9880d681SAndroid Build Coastguard Worker     // first iteration, and also the alignment using the per-iteration delta.
168*9880d681SAndroid Build Coastguard Worker     // If these are the same, then use that answer. Otherwise, use the smaller
169*9880d681SAndroid Build Coastguard Worker     // one, but only if it divides the larger one.
170*9880d681SAndroid Build Coastguard Worker     NewAlignment = getNewAlignmentDiff(DiffStartSCEV, AlignSCEV, SE);
171*9880d681SAndroid Build Coastguard Worker     unsigned NewIncAlignment = getNewAlignmentDiff(DiffIncSCEV, AlignSCEV, SE);
172*9880d681SAndroid Build Coastguard Worker 
173*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "\tnew start alignment: " << NewAlignment << "\n");
174*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "\tnew inc alignment: " << NewIncAlignment << "\n");
175*9880d681SAndroid Build Coastguard Worker 
176*9880d681SAndroid Build Coastguard Worker     if (!NewAlignment || !NewIncAlignment) {
177*9880d681SAndroid Build Coastguard Worker       return 0;
178*9880d681SAndroid Build Coastguard Worker     } else if (NewAlignment > NewIncAlignment) {
179*9880d681SAndroid Build Coastguard Worker       if (NewAlignment % NewIncAlignment == 0) {
180*9880d681SAndroid Build Coastguard Worker         DEBUG(dbgs() << "\tnew start/inc alignment: " <<
181*9880d681SAndroid Build Coastguard Worker                         NewIncAlignment << "\n");
182*9880d681SAndroid Build Coastguard Worker         return NewIncAlignment;
183*9880d681SAndroid Build Coastguard Worker       }
184*9880d681SAndroid Build Coastguard Worker     } else if (NewIncAlignment > NewAlignment) {
185*9880d681SAndroid Build Coastguard Worker       if (NewIncAlignment % NewAlignment == 0) {
186*9880d681SAndroid Build Coastguard Worker         DEBUG(dbgs() << "\tnew start/inc alignment: " <<
187*9880d681SAndroid Build Coastguard Worker                         NewAlignment << "\n");
188*9880d681SAndroid Build Coastguard Worker         return NewAlignment;
189*9880d681SAndroid Build Coastguard Worker       }
190*9880d681SAndroid Build Coastguard Worker     } else if (NewIncAlignment == NewAlignment) {
191*9880d681SAndroid Build Coastguard Worker       DEBUG(dbgs() << "\tnew start/inc alignment: " <<
192*9880d681SAndroid Build Coastguard Worker                       NewAlignment << "\n");
193*9880d681SAndroid Build Coastguard Worker       return NewAlignment;
194*9880d681SAndroid Build Coastguard Worker     }
195*9880d681SAndroid Build Coastguard Worker   }
196*9880d681SAndroid Build Coastguard Worker 
197*9880d681SAndroid Build Coastguard Worker   return 0;
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker 
extractAlignmentInfo(CallInst * I,Value * & AAPtr,const SCEV * & AlignSCEV,const SCEV * & OffSCEV)200*9880d681SAndroid Build Coastguard Worker bool AlignmentFromAssumptionsPass::extractAlignmentInfo(CallInst *I,
201*9880d681SAndroid Build Coastguard Worker                                                         Value *&AAPtr,
202*9880d681SAndroid Build Coastguard Worker                                                         const SCEV *&AlignSCEV,
203*9880d681SAndroid Build Coastguard Worker                                                         const SCEV *&OffSCEV) {
204*9880d681SAndroid Build Coastguard Worker   // An alignment assume must be a statement about the least-significant
205*9880d681SAndroid Build Coastguard Worker   // bits of the pointer being zero, possibly with some offset.
206*9880d681SAndroid Build Coastguard Worker   ICmpInst *ICI = dyn_cast<ICmpInst>(I->getArgOperand(0));
207*9880d681SAndroid Build Coastguard Worker   if (!ICI)
208*9880d681SAndroid Build Coastguard Worker     return false;
209*9880d681SAndroid Build Coastguard Worker 
210*9880d681SAndroid Build Coastguard Worker   // This must be an expression of the form: x & m == 0.
211*9880d681SAndroid Build Coastguard Worker   if (ICI->getPredicate() != ICmpInst::ICMP_EQ)
212*9880d681SAndroid Build Coastguard Worker     return false;
213*9880d681SAndroid Build Coastguard Worker 
214*9880d681SAndroid Build Coastguard Worker   // Swap things around so that the RHS is 0.
215*9880d681SAndroid Build Coastguard Worker   Value *CmpLHS = ICI->getOperand(0);
216*9880d681SAndroid Build Coastguard Worker   Value *CmpRHS = ICI->getOperand(1);
217*9880d681SAndroid Build Coastguard Worker   const SCEV *CmpLHSSCEV = SE->getSCEV(CmpLHS);
218*9880d681SAndroid Build Coastguard Worker   const SCEV *CmpRHSSCEV = SE->getSCEV(CmpRHS);
219*9880d681SAndroid Build Coastguard Worker   if (CmpLHSSCEV->isZero())
220*9880d681SAndroid Build Coastguard Worker     std::swap(CmpLHS, CmpRHS);
221*9880d681SAndroid Build Coastguard Worker   else if (!CmpRHSSCEV->isZero())
222*9880d681SAndroid Build Coastguard Worker     return false;
223*9880d681SAndroid Build Coastguard Worker 
224*9880d681SAndroid Build Coastguard Worker   BinaryOperator *CmpBO = dyn_cast<BinaryOperator>(CmpLHS);
225*9880d681SAndroid Build Coastguard Worker   if (!CmpBO || CmpBO->getOpcode() != Instruction::And)
226*9880d681SAndroid Build Coastguard Worker     return false;
227*9880d681SAndroid Build Coastguard Worker 
228*9880d681SAndroid Build Coastguard Worker   // Swap things around so that the right operand of the and is a constant
229*9880d681SAndroid Build Coastguard Worker   // (the mask); we cannot deal with variable masks.
230*9880d681SAndroid Build Coastguard Worker   Value *AndLHS = CmpBO->getOperand(0);
231*9880d681SAndroid Build Coastguard Worker   Value *AndRHS = CmpBO->getOperand(1);
232*9880d681SAndroid Build Coastguard Worker   const SCEV *AndLHSSCEV = SE->getSCEV(AndLHS);
233*9880d681SAndroid Build Coastguard Worker   const SCEV *AndRHSSCEV = SE->getSCEV(AndRHS);
234*9880d681SAndroid Build Coastguard Worker   if (isa<SCEVConstant>(AndLHSSCEV)) {
235*9880d681SAndroid Build Coastguard Worker     std::swap(AndLHS, AndRHS);
236*9880d681SAndroid Build Coastguard Worker     std::swap(AndLHSSCEV, AndRHSSCEV);
237*9880d681SAndroid Build Coastguard Worker   }
238*9880d681SAndroid Build Coastguard Worker 
239*9880d681SAndroid Build Coastguard Worker   const SCEVConstant *MaskSCEV = dyn_cast<SCEVConstant>(AndRHSSCEV);
240*9880d681SAndroid Build Coastguard Worker   if (!MaskSCEV)
241*9880d681SAndroid Build Coastguard Worker     return false;
242*9880d681SAndroid Build Coastguard Worker 
243*9880d681SAndroid Build Coastguard Worker   // The mask must have some trailing ones (otherwise the condition is
244*9880d681SAndroid Build Coastguard Worker   // trivial and tells us nothing about the alignment of the left operand).
245*9880d681SAndroid Build Coastguard Worker   unsigned TrailingOnes = MaskSCEV->getAPInt().countTrailingOnes();
246*9880d681SAndroid Build Coastguard Worker   if (!TrailingOnes)
247*9880d681SAndroid Build Coastguard Worker     return false;
248*9880d681SAndroid Build Coastguard Worker 
249*9880d681SAndroid Build Coastguard Worker   // Cap the alignment at the maximum with which LLVM can deal (and make sure
250*9880d681SAndroid Build Coastguard Worker   // we don't overflow the shift).
251*9880d681SAndroid Build Coastguard Worker   uint64_t Alignment;
252*9880d681SAndroid Build Coastguard Worker   TrailingOnes = std::min(TrailingOnes,
253*9880d681SAndroid Build Coastguard Worker     unsigned(sizeof(unsigned) * CHAR_BIT - 1));
254*9880d681SAndroid Build Coastguard Worker   Alignment = std::min(1u << TrailingOnes, +Value::MaximumAlignment);
255*9880d681SAndroid Build Coastguard Worker 
256*9880d681SAndroid Build Coastguard Worker   Type *Int64Ty = Type::getInt64Ty(I->getParent()->getParent()->getContext());
257*9880d681SAndroid Build Coastguard Worker   AlignSCEV = SE->getConstant(Int64Ty, Alignment);
258*9880d681SAndroid Build Coastguard Worker 
259*9880d681SAndroid Build Coastguard Worker   // The LHS might be a ptrtoint instruction, or it might be the pointer
260*9880d681SAndroid Build Coastguard Worker   // with an offset.
261*9880d681SAndroid Build Coastguard Worker   AAPtr = nullptr;
262*9880d681SAndroid Build Coastguard Worker   OffSCEV = nullptr;
263*9880d681SAndroid Build Coastguard Worker   if (PtrToIntInst *PToI = dyn_cast<PtrToIntInst>(AndLHS)) {
264*9880d681SAndroid Build Coastguard Worker     AAPtr = PToI->getPointerOperand();
265*9880d681SAndroid Build Coastguard Worker     OffSCEV = SE->getZero(Int64Ty);
266*9880d681SAndroid Build Coastguard Worker   } else if (const SCEVAddExpr* AndLHSAddSCEV =
267*9880d681SAndroid Build Coastguard Worker              dyn_cast<SCEVAddExpr>(AndLHSSCEV)) {
268*9880d681SAndroid Build Coastguard Worker     // Try to find the ptrtoint; subtract it and the rest is the offset.
269*9880d681SAndroid Build Coastguard Worker     for (SCEVAddExpr::op_iterator J = AndLHSAddSCEV->op_begin(),
270*9880d681SAndroid Build Coastguard Worker          JE = AndLHSAddSCEV->op_end(); J != JE; ++J)
271*9880d681SAndroid Build Coastguard Worker       if (const SCEVUnknown *OpUnk = dyn_cast<SCEVUnknown>(*J))
272*9880d681SAndroid Build Coastguard Worker         if (PtrToIntInst *PToI = dyn_cast<PtrToIntInst>(OpUnk->getValue())) {
273*9880d681SAndroid Build Coastguard Worker           AAPtr = PToI->getPointerOperand();
274*9880d681SAndroid Build Coastguard Worker           OffSCEV = SE->getMinusSCEV(AndLHSAddSCEV, *J);
275*9880d681SAndroid Build Coastguard Worker           break;
276*9880d681SAndroid Build Coastguard Worker         }
277*9880d681SAndroid Build Coastguard Worker   }
278*9880d681SAndroid Build Coastguard Worker 
279*9880d681SAndroid Build Coastguard Worker   if (!AAPtr)
280*9880d681SAndroid Build Coastguard Worker     return false;
281*9880d681SAndroid Build Coastguard Worker 
282*9880d681SAndroid Build Coastguard Worker   // Sign extend the offset to 64 bits (so that it is like all of the other
283*9880d681SAndroid Build Coastguard Worker   // expressions).
284*9880d681SAndroid Build Coastguard Worker   unsigned OffSCEVBits = OffSCEV->getType()->getPrimitiveSizeInBits();
285*9880d681SAndroid Build Coastguard Worker   if (OffSCEVBits < 64)
286*9880d681SAndroid Build Coastguard Worker     OffSCEV = SE->getSignExtendExpr(OffSCEV, Int64Ty);
287*9880d681SAndroid Build Coastguard Worker   else if (OffSCEVBits > 64)
288*9880d681SAndroid Build Coastguard Worker     return false;
289*9880d681SAndroid Build Coastguard Worker 
290*9880d681SAndroid Build Coastguard Worker   AAPtr = AAPtr->stripPointerCasts();
291*9880d681SAndroid Build Coastguard Worker   return true;
292*9880d681SAndroid Build Coastguard Worker }
293*9880d681SAndroid Build Coastguard Worker 
processAssumption(CallInst * ACall)294*9880d681SAndroid Build Coastguard Worker bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) {
295*9880d681SAndroid Build Coastguard Worker   Value *AAPtr;
296*9880d681SAndroid Build Coastguard Worker   const SCEV *AlignSCEV, *OffSCEV;
297*9880d681SAndroid Build Coastguard Worker   if (!extractAlignmentInfo(ACall, AAPtr, AlignSCEV, OffSCEV))
298*9880d681SAndroid Build Coastguard Worker     return false;
299*9880d681SAndroid Build Coastguard Worker 
300*9880d681SAndroid Build Coastguard Worker   const SCEV *AASCEV = SE->getSCEV(AAPtr);
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker   // Apply the assumption to all other users of the specified pointer.
303*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<Instruction *, 32> Visited;
304*9880d681SAndroid Build Coastguard Worker   SmallVector<Instruction*, 16> WorkList;
305*9880d681SAndroid Build Coastguard Worker   for (User *J : AAPtr->users()) {
306*9880d681SAndroid Build Coastguard Worker     if (J == ACall)
307*9880d681SAndroid Build Coastguard Worker       continue;
308*9880d681SAndroid Build Coastguard Worker 
309*9880d681SAndroid Build Coastguard Worker     if (Instruction *K = dyn_cast<Instruction>(J))
310*9880d681SAndroid Build Coastguard Worker       if (isValidAssumeForContext(ACall, K, DT))
311*9880d681SAndroid Build Coastguard Worker         WorkList.push_back(K);
312*9880d681SAndroid Build Coastguard Worker   }
313*9880d681SAndroid Build Coastguard Worker 
314*9880d681SAndroid Build Coastguard Worker   while (!WorkList.empty()) {
315*9880d681SAndroid Build Coastguard Worker     Instruction *J = WorkList.pop_back_val();
316*9880d681SAndroid Build Coastguard Worker 
317*9880d681SAndroid Build Coastguard Worker     if (LoadInst *LI = dyn_cast<LoadInst>(J)) {
318*9880d681SAndroid Build Coastguard Worker       unsigned NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV,
319*9880d681SAndroid Build Coastguard Worker         LI->getPointerOperand(), SE);
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker       if (NewAlignment > LI->getAlignment()) {
322*9880d681SAndroid Build Coastguard Worker         LI->setAlignment(NewAlignment);
323*9880d681SAndroid Build Coastguard Worker         ++NumLoadAlignChanged;
324*9880d681SAndroid Build Coastguard Worker       }
325*9880d681SAndroid Build Coastguard Worker     } else if (StoreInst *SI = dyn_cast<StoreInst>(J)) {
326*9880d681SAndroid Build Coastguard Worker       unsigned NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV,
327*9880d681SAndroid Build Coastguard Worker         SI->getPointerOperand(), SE);
328*9880d681SAndroid Build Coastguard Worker 
329*9880d681SAndroid Build Coastguard Worker       if (NewAlignment > SI->getAlignment()) {
330*9880d681SAndroid Build Coastguard Worker         SI->setAlignment(NewAlignment);
331*9880d681SAndroid Build Coastguard Worker         ++NumStoreAlignChanged;
332*9880d681SAndroid Build Coastguard Worker       }
333*9880d681SAndroid Build Coastguard Worker     } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(J)) {
334*9880d681SAndroid Build Coastguard Worker       unsigned NewDestAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV,
335*9880d681SAndroid Build Coastguard Worker         MI->getDest(), SE);
336*9880d681SAndroid Build Coastguard Worker 
337*9880d681SAndroid Build Coastguard Worker       // For memory transfers, we need a common alignment for both the
338*9880d681SAndroid Build Coastguard Worker       // source and destination. If we have a new alignment for this
339*9880d681SAndroid Build Coastguard Worker       // instruction, but only for one operand, save it. If we reach the
340*9880d681SAndroid Build Coastguard Worker       // other operand through another assumption later, then we may
341*9880d681SAndroid Build Coastguard Worker       // change the alignment at that point.
342*9880d681SAndroid Build Coastguard Worker       if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) {
343*9880d681SAndroid Build Coastguard Worker         unsigned NewSrcAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV,
344*9880d681SAndroid Build Coastguard Worker           MTI->getSource(), SE);
345*9880d681SAndroid Build Coastguard Worker 
346*9880d681SAndroid Build Coastguard Worker         DenseMap<MemTransferInst *, unsigned>::iterator DI =
347*9880d681SAndroid Build Coastguard Worker           NewDestAlignments.find(MTI);
348*9880d681SAndroid Build Coastguard Worker         unsigned AltDestAlignment = (DI == NewDestAlignments.end()) ?
349*9880d681SAndroid Build Coastguard Worker                                     0 : DI->second;
350*9880d681SAndroid Build Coastguard Worker 
351*9880d681SAndroid Build Coastguard Worker         DenseMap<MemTransferInst *, unsigned>::iterator SI =
352*9880d681SAndroid Build Coastguard Worker           NewSrcAlignments.find(MTI);
353*9880d681SAndroid Build Coastguard Worker         unsigned AltSrcAlignment = (SI == NewSrcAlignments.end()) ?
354*9880d681SAndroid Build Coastguard Worker                                    0 : SI->second;
355*9880d681SAndroid Build Coastguard Worker 
356*9880d681SAndroid Build Coastguard Worker         DEBUG(dbgs() << "\tmem trans: " << NewDestAlignment << " " <<
357*9880d681SAndroid Build Coastguard Worker                         AltDestAlignment << " " << NewSrcAlignment <<
358*9880d681SAndroid Build Coastguard Worker                         " " << AltSrcAlignment << "\n");
359*9880d681SAndroid Build Coastguard Worker 
360*9880d681SAndroid Build Coastguard Worker         // Of these four alignments, pick the largest possible...
361*9880d681SAndroid Build Coastguard Worker         unsigned NewAlignment = 0;
362*9880d681SAndroid Build Coastguard Worker         if (NewDestAlignment <= std::max(NewSrcAlignment, AltSrcAlignment))
363*9880d681SAndroid Build Coastguard Worker           NewAlignment = std::max(NewAlignment, NewDestAlignment);
364*9880d681SAndroid Build Coastguard Worker         if (AltDestAlignment <= std::max(NewSrcAlignment, AltSrcAlignment))
365*9880d681SAndroid Build Coastguard Worker           NewAlignment = std::max(NewAlignment, AltDestAlignment);
366*9880d681SAndroid Build Coastguard Worker         if (NewSrcAlignment <= std::max(NewDestAlignment, AltDestAlignment))
367*9880d681SAndroid Build Coastguard Worker           NewAlignment = std::max(NewAlignment, NewSrcAlignment);
368*9880d681SAndroid Build Coastguard Worker         if (AltSrcAlignment <= std::max(NewDestAlignment, AltDestAlignment))
369*9880d681SAndroid Build Coastguard Worker           NewAlignment = std::max(NewAlignment, AltSrcAlignment);
370*9880d681SAndroid Build Coastguard Worker 
371*9880d681SAndroid Build Coastguard Worker         if (NewAlignment > MI->getAlignment()) {
372*9880d681SAndroid Build Coastguard Worker           MI->setAlignment(ConstantInt::get(Type::getInt32Ty(
373*9880d681SAndroid Build Coastguard Worker             MI->getParent()->getContext()), NewAlignment));
374*9880d681SAndroid Build Coastguard Worker           ++NumMemIntAlignChanged;
375*9880d681SAndroid Build Coastguard Worker         }
376*9880d681SAndroid Build Coastguard Worker 
377*9880d681SAndroid Build Coastguard Worker         NewDestAlignments.insert(std::make_pair(MTI, NewDestAlignment));
378*9880d681SAndroid Build Coastguard Worker         NewSrcAlignments.insert(std::make_pair(MTI, NewSrcAlignment));
379*9880d681SAndroid Build Coastguard Worker       } else if (NewDestAlignment > MI->getAlignment()) {
380*9880d681SAndroid Build Coastguard Worker         assert((!isa<MemIntrinsic>(MI) || isa<MemSetInst>(MI)) &&
381*9880d681SAndroid Build Coastguard Worker                "Unknown memory intrinsic");
382*9880d681SAndroid Build Coastguard Worker 
383*9880d681SAndroid Build Coastguard Worker         MI->setAlignment(ConstantInt::get(Type::getInt32Ty(
384*9880d681SAndroid Build Coastguard Worker           MI->getParent()->getContext()), NewDestAlignment));
385*9880d681SAndroid Build Coastguard Worker         ++NumMemIntAlignChanged;
386*9880d681SAndroid Build Coastguard Worker       }
387*9880d681SAndroid Build Coastguard Worker     }
388*9880d681SAndroid Build Coastguard Worker 
389*9880d681SAndroid Build Coastguard Worker     // Now that we've updated that use of the pointer, look for other uses of
390*9880d681SAndroid Build Coastguard Worker     // the pointer to update.
391*9880d681SAndroid Build Coastguard Worker     Visited.insert(J);
392*9880d681SAndroid Build Coastguard Worker     for (User *UJ : J->users()) {
393*9880d681SAndroid Build Coastguard Worker       Instruction *K = cast<Instruction>(UJ);
394*9880d681SAndroid Build Coastguard Worker       if (!Visited.count(K) && isValidAssumeForContext(ACall, K, DT))
395*9880d681SAndroid Build Coastguard Worker         WorkList.push_back(K);
396*9880d681SAndroid Build Coastguard Worker     }
397*9880d681SAndroid Build Coastguard Worker   }
398*9880d681SAndroid Build Coastguard Worker 
399*9880d681SAndroid Build Coastguard Worker   return true;
400*9880d681SAndroid Build Coastguard Worker }
401*9880d681SAndroid Build Coastguard Worker 
runOnFunction(Function & F)402*9880d681SAndroid Build Coastguard Worker bool AlignmentFromAssumptions::runOnFunction(Function &F) {
403*9880d681SAndroid Build Coastguard Worker   if (skipFunction(F))
404*9880d681SAndroid Build Coastguard Worker     return false;
405*9880d681SAndroid Build Coastguard Worker 
406*9880d681SAndroid Build Coastguard Worker   auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
407*9880d681SAndroid Build Coastguard Worker   ScalarEvolution *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
408*9880d681SAndroid Build Coastguard Worker   DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
409*9880d681SAndroid Build Coastguard Worker 
410*9880d681SAndroid Build Coastguard Worker   return Impl.runImpl(F, AC, SE, DT);
411*9880d681SAndroid Build Coastguard Worker }
412*9880d681SAndroid Build Coastguard Worker 
runImpl(Function & F,AssumptionCache & AC,ScalarEvolution * SE_,DominatorTree * DT_)413*9880d681SAndroid Build Coastguard Worker bool AlignmentFromAssumptionsPass::runImpl(Function &F, AssumptionCache &AC,
414*9880d681SAndroid Build Coastguard Worker                                            ScalarEvolution *SE_,
415*9880d681SAndroid Build Coastguard Worker                                            DominatorTree *DT_) {
416*9880d681SAndroid Build Coastguard Worker   SE = SE_;
417*9880d681SAndroid Build Coastguard Worker   DT = DT_;
418*9880d681SAndroid Build Coastguard Worker 
419*9880d681SAndroid Build Coastguard Worker   NewDestAlignments.clear();
420*9880d681SAndroid Build Coastguard Worker   NewSrcAlignments.clear();
421*9880d681SAndroid Build Coastguard Worker 
422*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
423*9880d681SAndroid Build Coastguard Worker   for (auto &AssumeVH : AC.assumptions())
424*9880d681SAndroid Build Coastguard Worker     if (AssumeVH)
425*9880d681SAndroid Build Coastguard Worker       Changed |= processAssumption(cast<CallInst>(AssumeVH));
426*9880d681SAndroid Build Coastguard Worker 
427*9880d681SAndroid Build Coastguard Worker   return Changed;
428*9880d681SAndroid Build Coastguard Worker }
429*9880d681SAndroid Build Coastguard Worker 
430*9880d681SAndroid Build Coastguard Worker PreservedAnalyses
run(Function & F,FunctionAnalysisManager & AM)431*9880d681SAndroid Build Coastguard Worker AlignmentFromAssumptionsPass::run(Function &F, FunctionAnalysisManager &AM) {
432*9880d681SAndroid Build Coastguard Worker 
433*9880d681SAndroid Build Coastguard Worker   AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F);
434*9880d681SAndroid Build Coastguard Worker   ScalarEvolution &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
435*9880d681SAndroid Build Coastguard Worker   DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F);
436*9880d681SAndroid Build Coastguard Worker   bool Changed = runImpl(F, AC, &SE, &DT);
437*9880d681SAndroid Build Coastguard Worker   if (!Changed)
438*9880d681SAndroid Build Coastguard Worker     return PreservedAnalyses::all();
439*9880d681SAndroid Build Coastguard Worker   PreservedAnalyses PA;
440*9880d681SAndroid Build Coastguard Worker   PA.preserve<AAManager>();
441*9880d681SAndroid Build Coastguard Worker   PA.preserve<ScalarEvolutionAnalysis>();
442*9880d681SAndroid Build Coastguard Worker   PA.preserve<GlobalsAA>();
443*9880d681SAndroid Build Coastguard Worker   PA.preserve<LoopAnalysis>();
444*9880d681SAndroid Build Coastguard Worker   PA.preserve<DominatorTreeAnalysis>();
445*9880d681SAndroid Build Coastguard Worker   return PA;
446*9880d681SAndroid Build Coastguard Worker }
447