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 1805da2fe5SReid Kleckner #include "llvm/InitializePasses.h" 19d67e4639SHal Finkel #define AA_NAME "alignment-from-assumptions" 20d67e4639SHal Finkel #define DEBUG_TYPE AA_NAME 21a4c2d150SSean Silva #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h" 22d67e4639SHal Finkel #include "llvm/ADT/SmallPtrSet.h" 23d67e4639SHal Finkel #include "llvm/ADT/Statistic.h" 24494393b7SHal Finkel #include "llvm/Analysis/AliasAnalysis.h" 25aec2fa35SDaniel Jasper #include "llvm/Analysis/AssumptionCache.h" 266bda14b3SChandler Carruth #include "llvm/Analysis/GlobalsModRef.h" 27d67e4639SHal Finkel #include "llvm/Analysis/LoopInfo.h" 28d67e4639SHal Finkel #include "llvm/Analysis/ScalarEvolutionExpressions.h" 29799003bfSBenjamin Kramer #include "llvm/Analysis/ValueTracking.h" 30d67e4639SHal Finkel #include "llvm/IR/Constant.h" 31d67e4639SHal Finkel #include "llvm/IR/Dominators.h" 32d67e4639SHal Finkel #include "llvm/IR/Instruction.h" 331c2d2c88SSimon Pilgrim #include "llvm/IR/IntrinsicInst.h" 34d67e4639SHal Finkel #include "llvm/IR/Intrinsics.h" 3546a43556SMehdi Amini #include "llvm/IR/Module.h" 36d67e4639SHal Finkel #include "llvm/Support/Debug.h" 37d67e4639SHal Finkel #include "llvm/Support/raw_ostream.h" 386bda14b3SChandler Carruth #include "llvm/Transforms/Scalar.h" 39d67e4639SHal Finkel using namespace llvm; 40d67e4639SHal Finkel 41d67e4639SHal Finkel STATISTIC(NumLoadAlignChanged, 42d67e4639SHal Finkel "Number of loads changed by alignment assumptions"); 43d67e4639SHal Finkel STATISTIC(NumStoreAlignChanged, 44d67e4639SHal Finkel "Number of stores changed by alignment assumptions"); 45d67e4639SHal Finkel STATISTIC(NumMemIntAlignChanged, 46d67e4639SHal Finkel "Number of memory intrinsics changed by alignment assumptions"); 47d67e4639SHal Finkel 48d67e4639SHal Finkel namespace { 49d67e4639SHal Finkel struct AlignmentFromAssumptions : public FunctionPass { 50d67e4639SHal Finkel static char ID; // Pass identification, replacement for typeid 51d67e4639SHal Finkel AlignmentFromAssumptions() : FunctionPass(ID) { 52d67e4639SHal Finkel initializeAlignmentFromAssumptionsPass(*PassRegistry::getPassRegistry()); 53d67e4639SHal Finkel } 54d67e4639SHal Finkel 55f817c1cbSAlexander Kornienko bool runOnFunction(Function &F) override; 56d67e4639SHal Finkel 57f817c1cbSAlexander Kornienko void getAnalysisUsage(AnalysisUsage &AU) const override { 58aec2fa35SDaniel Jasper AU.addRequired<AssumptionCacheTracker>(); 592f1fd165SChandler Carruth AU.addRequired<ScalarEvolutionWrapperPass>(); 60d67e4639SHal Finkel AU.addRequired<DominatorTreeWrapperPass>(); 61d67e4639SHal Finkel 62d67e4639SHal Finkel AU.setPreservesCFG(); 63494393b7SHal Finkel AU.addPreserved<AAResultsWrapperPass>(); 64494393b7SHal Finkel AU.addPreserved<GlobalsAAWrapperPass>(); 654f8f307cSChandler Carruth AU.addPreserved<LoopInfoWrapperPass>(); 66d67e4639SHal Finkel AU.addPreserved<DominatorTreeWrapperPass>(); 672f1fd165SChandler Carruth AU.addPreserved<ScalarEvolutionWrapperPass>(); 68d67e4639SHal Finkel } 69d67e4639SHal Finkel 70a4c2d150SSean Silva AlignmentFromAssumptionsPass Impl; 71d67e4639SHal Finkel }; 72f00654e3SAlexander Kornienko } 73d67e4639SHal Finkel 74d67e4639SHal Finkel char AlignmentFromAssumptions::ID = 0; 75d67e4639SHal Finkel static const char aip_name[] = "Alignment from assumptions"; 76d67e4639SHal Finkel INITIALIZE_PASS_BEGIN(AlignmentFromAssumptions, AA_NAME, 77d67e4639SHal Finkel aip_name, false, false) 78aec2fa35SDaniel Jasper INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) 79d67e4639SHal Finkel INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 802f1fd165SChandler Carruth INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) 81d67e4639SHal Finkel INITIALIZE_PASS_END(AlignmentFromAssumptions, AA_NAME, 82d67e4639SHal Finkel aip_name, false, false) 83d67e4639SHal Finkel 84d67e4639SHal Finkel FunctionPass *llvm::createAlignmentFromAssumptionsPass() { 85d67e4639SHal Finkel return new AlignmentFromAssumptions(); 86d67e4639SHal Finkel } 87d67e4639SHal Finkel 88d67e4639SHal Finkel // Given an expression for the (constant) alignment, AlignSCEV, and an 89d67e4639SHal Finkel // expression for the displacement between a pointer and the aligned address, 908fc3c6c0SAndrew Trick // DiffSCEV, compute the alignment of the displaced pointer if it can be reduced 918fc3c6c0SAndrew Trick // to a constant. Using SCEV to compute alignment handles the case where 928fc3c6c0SAndrew Trick // DiffSCEV is a recurrence with constant start such that the aligned offset 938fc3c6c0SAndrew Trick // is constant. e.g. {16,+,32} % 32 -> 16. 9480828634SGuillaume Chatelet static MaybeAlign getNewAlignmentDiff(const SCEV *DiffSCEV, 95d67e4639SHal Finkel const SCEV *AlignSCEV, 96d67e4639SHal Finkel ScalarEvolution *SE) { 97d67e4639SHal Finkel // DiffUnits = Diff % int64_t(Alignment) 983fc933afSFangrui Song const SCEV *DiffUnitsSCEV = SE->getURemExpr(DiffSCEV, AlignSCEV); 99d67e4639SHal Finkel 100d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\talignment relative to " << *AlignSCEV << " is " 101d34e60caSNicola Zaghen << *DiffUnitsSCEV << " (diff: " << *DiffSCEV << ")\n"); 102d67e4639SHal Finkel 103d67e4639SHal Finkel if (const SCEVConstant *ConstDUSCEV = 104d67e4639SHal Finkel dyn_cast<SCEVConstant>(DiffUnitsSCEV)) { 105d67e4639SHal Finkel int64_t DiffUnits = ConstDUSCEV->getValue()->getSExtValue(); 106d67e4639SHal Finkel 107d67e4639SHal Finkel // If the displacement is an exact multiple of the alignment, then the 108d67e4639SHal Finkel // displaced pointer has the same alignment as the aligned pointer, so 109d67e4639SHal Finkel // return the alignment value. 110d67e4639SHal Finkel if (!DiffUnits) 11180828634SGuillaume Chatelet return cast<SCEVConstant>(AlignSCEV)->getValue()->getAlignValue(); 112d67e4639SHal Finkel 113d67e4639SHal Finkel // If the displacement is not an exact multiple, but the remainder is a 114d67e4639SHal Finkel // constant, then return this remainder (but only if it is a power of 2). 1157bd1f7cbSBenjamin Kramer uint64_t DiffUnitsAbs = std::abs(DiffUnits); 116d67e4639SHal Finkel if (isPowerOf2_64(DiffUnitsAbs)) 11780828634SGuillaume Chatelet return Align(DiffUnitsAbs); 118d67e4639SHal Finkel } 119d67e4639SHal Finkel 12080828634SGuillaume Chatelet return None; 121d67e4639SHal Finkel } 122d67e4639SHal Finkel 123d67e4639SHal Finkel // There is an address given by an offset OffSCEV from AASCEV which has an 124d67e4639SHal Finkel // alignment AlignSCEV. Use that information, if possible, to compute a new 125d67e4639SHal Finkel // alignment for Ptr. 12680828634SGuillaume Chatelet static Align getNewAlignment(const SCEV *AASCEV, const SCEV *AlignSCEV, 127d67e4639SHal Finkel const SCEV *OffSCEV, Value *Ptr, 128d67e4639SHal Finkel ScalarEvolution *SE) { 129d67e4639SHal Finkel const SCEV *PtrSCEV = SE->getSCEV(Ptr); 1304bf015c0SRichard Diamond // On a platform with 32-bit allocas, but 64-bit flat/global pointer sizes 1314bf015c0SRichard Diamond // (*cough* AMDGPU), the effective SCEV type of AASCEV and PtrSCEV 1324bf015c0SRichard Diamond // may disagree. Trunc/extend so they agree. 1334bf015c0SRichard Diamond PtrSCEV = SE->getTruncateOrZeroExtend( 1344bf015c0SRichard Diamond PtrSCEV, SE->getEffectiveSCEVType(AASCEV->getType())); 135d67e4639SHal Finkel const SCEV *DiffSCEV = SE->getMinusSCEV(PtrSCEV, AASCEV); 136d67e4639SHal Finkel 137f83e1f7fSHal Finkel // On 32-bit platforms, DiffSCEV might now have type i32 -- we've always 138f83e1f7fSHal Finkel // sign-extended OffSCEV to i64, so make sure they agree again. 139f83e1f7fSHal Finkel DiffSCEV = SE->getNoopOrSignExtend(DiffSCEV, OffSCEV->getType()); 140f83e1f7fSHal Finkel 141d67e4639SHal Finkel // What we really want to know is the overall offset to the aligned 142d67e4639SHal Finkel // address. This address is displaced by the provided offset. 143d67e4639SHal Finkel DiffSCEV = SE->getMinusSCEV(DiffSCEV, OffSCEV); 144d67e4639SHal Finkel 145d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "AFI: alignment of " << *Ptr << " relative to " 146d34e60caSNicola Zaghen << *AlignSCEV << " and offset " << *OffSCEV 147d34e60caSNicola Zaghen << " using diff " << *DiffSCEV << "\n"); 148d67e4639SHal Finkel 14980828634SGuillaume Chatelet if (MaybeAlign NewAlignment = getNewAlignmentDiff(DiffSCEV, AlignSCEV, SE)) { 15080828634SGuillaume Chatelet LLVM_DEBUG(dbgs() << "\tnew alignment: " << DebugStr(NewAlignment) << "\n"); 15180828634SGuillaume Chatelet return *NewAlignment; 15280828634SGuillaume Chatelet } 153d67e4639SHal Finkel 15480828634SGuillaume Chatelet if (const SCEVAddRecExpr *DiffARSCEV = dyn_cast<SCEVAddRecExpr>(DiffSCEV)) { 155d67e4639SHal Finkel // The relative offset to the alignment assumption did not yield a constant, 156d67e4639SHal Finkel // but we should try harder: if we assume that a is 32-byte aligned, then in 157d67e4639SHal Finkel // for (i = 0; i < 1024; i += 4) r += a[i]; not all of the loads from a are 158d67e4639SHal Finkel // 32-byte aligned, but instead alternate between 32 and 16-byte alignment. 159d67e4639SHal Finkel // As a result, the new alignment will not be a constant, but can still 160d67e4639SHal Finkel // be improved over the default (of 4) to 16. 161d67e4639SHal Finkel 162d67e4639SHal Finkel const SCEV *DiffStartSCEV = DiffARSCEV->getStart(); 163d67e4639SHal Finkel const SCEV *DiffIncSCEV = DiffARSCEV->getStepRecurrence(*SE); 164d67e4639SHal Finkel 165d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "\ttrying start/inc alignment using start " 166d34e60caSNicola Zaghen << *DiffStartSCEV << " and inc " << *DiffIncSCEV << "\n"); 167d67e4639SHal Finkel 168d67e4639SHal Finkel // Now compute the new alignment using the displacement to the value in the 169d67e4639SHal Finkel // first iteration, and also the alignment using the per-iteration delta. 170d67e4639SHal Finkel // If these are the same, then use that answer. Otherwise, use the smaller 171d67e4639SHal Finkel // one, but only if it divides the larger one. 17280828634SGuillaume Chatelet MaybeAlign NewAlignment = getNewAlignmentDiff(DiffStartSCEV, AlignSCEV, SE); 17380828634SGuillaume Chatelet MaybeAlign NewIncAlignment = 17480828634SGuillaume Chatelet getNewAlignmentDiff(DiffIncSCEV, AlignSCEV, SE); 175d67e4639SHal Finkel 17680828634SGuillaume Chatelet LLVM_DEBUG(dbgs() << "\tnew start alignment: " << DebugStr(NewAlignment) 17780828634SGuillaume Chatelet << "\n"); 17880828634SGuillaume Chatelet LLVM_DEBUG(dbgs() << "\tnew inc alignment: " << DebugStr(NewIncAlignment) 17980828634SGuillaume Chatelet << "\n"); 1801e34ab98SGuillaume Chatelet 18180828634SGuillaume Chatelet if (!NewAlignment || !NewIncAlignment) 18280828634SGuillaume Chatelet return Align(1); 18380828634SGuillaume Chatelet 18480828634SGuillaume Chatelet const Align NewAlign = *NewAlignment; 18580828634SGuillaume Chatelet const Align NewIncAlign = *NewIncAlignment; 18680828634SGuillaume Chatelet if (NewAlign > NewIncAlign) { 18780828634SGuillaume Chatelet LLVM_DEBUG(dbgs() << "\tnew start/inc alignment: " 18880828634SGuillaume Chatelet << DebugStr(NewIncAlign) << "\n"); 18980828634SGuillaume Chatelet return NewIncAlign; 190d67e4639SHal Finkel } 19180828634SGuillaume Chatelet if (NewIncAlign > NewAlign) { 19280828634SGuillaume Chatelet LLVM_DEBUG(dbgs() << "\tnew start/inc alignment: " << DebugStr(NewAlign) 1936000478fSGuillaume Chatelet << "\n"); 19480828634SGuillaume Chatelet return NewAlign; 1956000478fSGuillaume Chatelet } 19680828634SGuillaume Chatelet assert(NewIncAlign == NewAlign); 19780828634SGuillaume Chatelet LLVM_DEBUG(dbgs() << "\tnew start/inc alignment: " << DebugStr(NewAlign) 1986000478fSGuillaume Chatelet << "\n"); 19980828634SGuillaume Chatelet return NewAlign; 200d67e4639SHal Finkel } 201d67e4639SHal Finkel 20280828634SGuillaume Chatelet return Align(1); 203d67e4639SHal Finkel } 204d67e4639SHal Finkel 205a4c2d150SSean Silva bool AlignmentFromAssumptionsPass::extractAlignmentInfo(CallInst *I, 206a4c2d150SSean Silva Value *&AAPtr, 207a4c2d150SSean Silva const SCEV *&AlignSCEV, 208d67e4639SHal Finkel const SCEV *&OffSCEV) { 209*7ea46aeeSRoman Lebedev // An alignment assume must be a statement about the least-significant 210*7ea46aeeSRoman Lebedev // bits of the pointer being zero, possibly with some offset. 211*7ea46aeeSRoman Lebedev ICmpInst *ICI = dyn_cast<ICmpInst>(I->getArgOperand(0)); 212*7ea46aeeSRoman Lebedev if (!ICI) 213c95ffadbSTyker return false; 214*7ea46aeeSRoman Lebedev 215*7ea46aeeSRoman Lebedev // This must be an expression of the form: x & m == 0. 216*7ea46aeeSRoman Lebedev if (ICI->getPredicate() != ICmpInst::ICMP_EQ) 217*7ea46aeeSRoman Lebedev return false; 218*7ea46aeeSRoman Lebedev 219*7ea46aeeSRoman Lebedev // Swap things around so that the RHS is 0. 220*7ea46aeeSRoman Lebedev Value *CmpLHS = ICI->getOperand(0); 221*7ea46aeeSRoman Lebedev Value *CmpRHS = ICI->getOperand(1); 222*7ea46aeeSRoman Lebedev const SCEV *CmpLHSSCEV = SE->getSCEV(CmpLHS); 223*7ea46aeeSRoman Lebedev const SCEV *CmpRHSSCEV = SE->getSCEV(CmpRHS); 224*7ea46aeeSRoman Lebedev if (CmpLHSSCEV->isZero()) 225*7ea46aeeSRoman Lebedev std::swap(CmpLHS, CmpRHS); 226*7ea46aeeSRoman Lebedev else if (!CmpRHSSCEV->isZero()) 227*7ea46aeeSRoman Lebedev return false; 228*7ea46aeeSRoman Lebedev 229*7ea46aeeSRoman Lebedev BinaryOperator *CmpBO = dyn_cast<BinaryOperator>(CmpLHS); 230*7ea46aeeSRoman Lebedev if (!CmpBO || CmpBO->getOpcode() != Instruction::And) 231*7ea46aeeSRoman Lebedev return false; 232*7ea46aeeSRoman Lebedev 233*7ea46aeeSRoman Lebedev // Swap things around so that the right operand of the and is a constant 234*7ea46aeeSRoman Lebedev // (the mask); we cannot deal with variable masks. 235*7ea46aeeSRoman Lebedev Value *AndLHS = CmpBO->getOperand(0); 236*7ea46aeeSRoman Lebedev Value *AndRHS = CmpBO->getOperand(1); 237*7ea46aeeSRoman Lebedev const SCEV *AndLHSSCEV = SE->getSCEV(AndLHS); 238*7ea46aeeSRoman Lebedev const SCEV *AndRHSSCEV = SE->getSCEV(AndRHS); 239*7ea46aeeSRoman Lebedev if (isa<SCEVConstant>(AndLHSSCEV)) { 240*7ea46aeeSRoman Lebedev std::swap(AndLHS, AndRHS); 241*7ea46aeeSRoman Lebedev std::swap(AndLHSSCEV, AndRHSSCEV); 242*7ea46aeeSRoman Lebedev } 243*7ea46aeeSRoman Lebedev 244*7ea46aeeSRoman Lebedev const SCEVConstant *MaskSCEV = dyn_cast<SCEVConstant>(AndRHSSCEV); 245*7ea46aeeSRoman Lebedev if (!MaskSCEV) 246*7ea46aeeSRoman Lebedev return false; 247*7ea46aeeSRoman Lebedev 248*7ea46aeeSRoman Lebedev // The mask must have some trailing ones (otherwise the condition is 249*7ea46aeeSRoman Lebedev // trivial and tells us nothing about the alignment of the left operand). 250*7ea46aeeSRoman Lebedev unsigned TrailingOnes = MaskSCEV->getAPInt().countTrailingOnes(); 251*7ea46aeeSRoman Lebedev if (!TrailingOnes) 252*7ea46aeeSRoman Lebedev return false; 253*7ea46aeeSRoman Lebedev 254*7ea46aeeSRoman Lebedev // Cap the alignment at the maximum with which LLVM can deal (and make sure 255*7ea46aeeSRoman Lebedev // we don't overflow the shift). 256*7ea46aeeSRoman Lebedev uint64_t Alignment; 257*7ea46aeeSRoman Lebedev TrailingOnes = std::min(TrailingOnes, 258*7ea46aeeSRoman Lebedev unsigned(sizeof(unsigned) * CHAR_BIT - 1)); 259*7ea46aeeSRoman Lebedev Alignment = std::min(1u << TrailingOnes, +Value::MaximumAlignment); 260*7ea46aeeSRoman Lebedev 261*7ea46aeeSRoman Lebedev Type *Int64Ty = Type::getInt64Ty(I->getParent()->getParent()->getContext()); 262*7ea46aeeSRoman Lebedev AlignSCEV = SE->getConstant(Int64Ty, Alignment); 263*7ea46aeeSRoman Lebedev 264*7ea46aeeSRoman Lebedev // The LHS might be a ptrtoint instruction, or it might be the pointer 265*7ea46aeeSRoman Lebedev // with an offset. 266*7ea46aeeSRoman Lebedev AAPtr = nullptr; 267*7ea46aeeSRoman Lebedev OffSCEV = nullptr; 268*7ea46aeeSRoman Lebedev if (PtrToIntInst *PToI = dyn_cast<PtrToIntInst>(AndLHS)) { 269*7ea46aeeSRoman Lebedev AAPtr = PToI->getPointerOperand(); 270*7ea46aeeSRoman Lebedev OffSCEV = SE->getZero(Int64Ty); 271*7ea46aeeSRoman Lebedev } else if (const SCEVAddExpr* AndLHSAddSCEV = 272*7ea46aeeSRoman Lebedev dyn_cast<SCEVAddExpr>(AndLHSSCEV)) { 273*7ea46aeeSRoman Lebedev // Try to find the ptrtoint; subtract it and the rest is the offset. 274*7ea46aeeSRoman Lebedev for (SCEVAddExpr::op_iterator J = AndLHSAddSCEV->op_begin(), 275*7ea46aeeSRoman Lebedev JE = AndLHSAddSCEV->op_end(); J != JE; ++J) 276*7ea46aeeSRoman Lebedev if (const SCEVUnknown *OpUnk = dyn_cast<SCEVUnknown>(*J)) 277*7ea46aeeSRoman Lebedev if (PtrToIntInst *PToI = dyn_cast<PtrToIntInst>(OpUnk->getValue())) { 278*7ea46aeeSRoman Lebedev AAPtr = PToI->getPointerOperand(); 279*7ea46aeeSRoman Lebedev OffSCEV = SE->getMinusSCEV(AndLHSAddSCEV, *J); 280*7ea46aeeSRoman Lebedev break; 281*7ea46aeeSRoman Lebedev } 282*7ea46aeeSRoman Lebedev } 283*7ea46aeeSRoman Lebedev 284*7ea46aeeSRoman Lebedev if (!AAPtr) 285*7ea46aeeSRoman Lebedev return false; 286*7ea46aeeSRoman Lebedev 287*7ea46aeeSRoman Lebedev // Sign extend the offset to 64 bits (so that it is like all of the other 288*7ea46aeeSRoman Lebedev // expressions). 289*7ea46aeeSRoman Lebedev unsigned OffSCEVBits = OffSCEV->getType()->getPrimitiveSizeInBits(); 290*7ea46aeeSRoman Lebedev if (OffSCEVBits < 64) 291*7ea46aeeSRoman Lebedev OffSCEV = SE->getSignExtendExpr(OffSCEV, Int64Ty); 292*7ea46aeeSRoman Lebedev else if (OffSCEVBits > 64) 293*7ea46aeeSRoman Lebedev return false; 294*7ea46aeeSRoman Lebedev 295*7ea46aeeSRoman Lebedev AAPtr = AAPtr->stripPointerCasts(); 296*7ea46aeeSRoman Lebedev return true; 297c95ffadbSTyker } 298d67e4639SHal Finkel 299a4c2d150SSean Silva bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) { 300d67e4639SHal Finkel Value *AAPtr; 301d67e4639SHal Finkel const SCEV *AlignSCEV, *OffSCEV; 302d67e4639SHal Finkel if (!extractAlignmentInfo(ACall, AAPtr, AlignSCEV, OffSCEV)) 303d67e4639SHal Finkel return false; 304d67e4639SHal Finkel 3054fd9b7e1SDuncan P. N. Exon Smith // Skip ConstantPointerNull and UndefValue. Assumptions on these shouldn't 3064fd9b7e1SDuncan P. N. Exon Smith // affect other users. 3074fd9b7e1SDuncan P. N. Exon Smith if (isa<ConstantData>(AAPtr)) 3084fd9b7e1SDuncan P. N. Exon Smith return false; 3094fd9b7e1SDuncan P. N. Exon Smith 310d67e4639SHal Finkel const SCEV *AASCEV = SE->getSCEV(AAPtr); 311d67e4639SHal Finkel 312d67e4639SHal Finkel // Apply the assumption to all other users of the specified pointer. 313d67e4639SHal Finkel SmallPtrSet<Instruction *, 32> Visited; 314d67e4639SHal Finkel SmallVector<Instruction*, 16> WorkList; 315d67e4639SHal Finkel for (User *J : AAPtr->users()) { 316d67e4639SHal Finkel if (J == ACall) 317d67e4639SHal Finkel continue; 318d67e4639SHal Finkel 319d67e4639SHal Finkel if (Instruction *K = dyn_cast<Instruction>(J)) 320*7ea46aeeSRoman Lebedev if (isValidAssumeForContext(ACall, K, DT)) 321d67e4639SHal Finkel WorkList.push_back(K); 322d67e4639SHal Finkel } 323d67e4639SHal Finkel 324d67e4639SHal Finkel while (!WorkList.empty()) { 325d67e4639SHal Finkel Instruction *J = WorkList.pop_back_val(); 326d67e4639SHal Finkel if (LoadInst *LI = dyn_cast<LoadInst>(J)) { 32780828634SGuillaume Chatelet Align NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV, 328d67e4639SHal Finkel LI->getPointerOperand(), SE); 32952e98f62SNikita Popov if (NewAlignment > LI->getAlign()) { 33080828634SGuillaume Chatelet LI->setAlignment(NewAlignment); 331d67e4639SHal Finkel ++NumLoadAlignChanged; 332d67e4639SHal Finkel } 333d67e4639SHal Finkel } else if (StoreInst *SI = dyn_cast<StoreInst>(J)) { 33480828634SGuillaume Chatelet Align NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV, 335d67e4639SHal Finkel SI->getPointerOperand(), SE); 33652e98f62SNikita Popov if (NewAlignment > SI->getAlign()) { 33780828634SGuillaume Chatelet SI->setAlignment(NewAlignment); 338d67e4639SHal Finkel ++NumStoreAlignChanged; 339d67e4639SHal Finkel } 340d67e4639SHal Finkel } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(J)) { 34180828634SGuillaume Chatelet Align NewDestAlignment = 34280828634SGuillaume Chatelet getNewAlignment(AASCEV, AlignSCEV, OffSCEV, MI->getDest(), SE); 343d67e4639SHal Finkel 34480828634SGuillaume Chatelet LLVM_DEBUG(dbgs() << "\tmem inst: " << DebugStr(NewDestAlignment) 34580828634SGuillaume Chatelet << "\n";); 34680828634SGuillaume Chatelet if (NewDestAlignment > *MI->getDestAlign()) { 34720c9207bSDaniel Neilson MI->setDestAlignment(NewDestAlignment); 34820c9207bSDaniel Neilson ++NumMemIntAlignChanged; 34920c9207bSDaniel Neilson } 35020c9207bSDaniel Neilson 35120c9207bSDaniel Neilson // For memory transfers, there is also a source alignment that 35220c9207bSDaniel Neilson // can be set. 353d67e4639SHal Finkel if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) { 35480828634SGuillaume Chatelet Align NewSrcAlignment = 35580828634SGuillaume Chatelet getNewAlignment(AASCEV, AlignSCEV, OffSCEV, MTI->getSource(), SE); 356d67e4639SHal Finkel 35780828634SGuillaume Chatelet LLVM_DEBUG(dbgs() << "\tmem trans: " << DebugStr(NewSrcAlignment) 35880828634SGuillaume Chatelet << "\n";); 359d67e4639SHal Finkel 36080828634SGuillaume Chatelet if (NewSrcAlignment > *MTI->getSourceAlign()) { 36120c9207bSDaniel Neilson MTI->setSourceAlignment(NewSrcAlignment); 362d67e4639SHal Finkel ++NumMemIntAlignChanged; 363d67e4639SHal Finkel } 364d67e4639SHal Finkel } 365d67e4639SHal Finkel } 366d67e4639SHal Finkel 367d67e4639SHal Finkel // Now that we've updated that use of the pointer, look for other uses of 368d67e4639SHal Finkel // the pointer to update. 369d67e4639SHal Finkel Visited.insert(J); 370d67e4639SHal Finkel for (User *UJ : J->users()) { 371d67e4639SHal Finkel Instruction *K = cast<Instruction>(UJ); 372*7ea46aeeSRoman Lebedev if (!Visited.count(K) && isValidAssumeForContext(ACall, K, DT)) 373d67e4639SHal Finkel WorkList.push_back(K); 374d67e4639SHal Finkel } 375d67e4639SHal Finkel } 376d67e4639SHal Finkel 377d67e4639SHal Finkel return true; 378d67e4639SHal Finkel } 379d67e4639SHal Finkel 380d67e4639SHal Finkel bool AlignmentFromAssumptions::runOnFunction(Function &F) { 38150271f78SAndrew Kaylor if (skipFunction(F)) 38250271f78SAndrew Kaylor return false; 38350271f78SAndrew Kaylor 384aec2fa35SDaniel Jasper auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); 385a4c2d150SSean Silva ScalarEvolution *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); 386a4c2d150SSean Silva DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 387a4c2d150SSean Silva 388aec2fa35SDaniel Jasper return Impl.runImpl(F, AC, SE, DT); 389a4c2d150SSean Silva } 390a4c2d150SSean Silva 391aec2fa35SDaniel Jasper bool AlignmentFromAssumptionsPass::runImpl(Function &F, AssumptionCache &AC, 392aec2fa35SDaniel Jasper ScalarEvolution *SE_, 393a4c2d150SSean Silva DominatorTree *DT_) { 394a4c2d150SSean Silva SE = SE_; 395a4c2d150SSean Silva DT = DT_; 396d67e4639SHal Finkel 397a4c2d150SSean Silva bool Changed = false; 398aec2fa35SDaniel Jasper for (auto &AssumeVH : AC.assumptions()) 399aec2fa35SDaniel Jasper if (AssumeVH) 400aec2fa35SDaniel Jasper Changed |= processAssumption(cast<CallInst>(AssumeVH)); 401d67e4639SHal Finkel 402d67e4639SHal Finkel return Changed; 403d67e4639SHal Finkel } 404d67e4639SHal Finkel 405a4c2d150SSean Silva PreservedAnalyses 406a4c2d150SSean Silva AlignmentFromAssumptionsPass::run(Function &F, FunctionAnalysisManager &AM) { 407a4c2d150SSean Silva 408aec2fa35SDaniel Jasper AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F); 409a4c2d150SSean Silva ScalarEvolution &SE = AM.getResult<ScalarEvolutionAnalysis>(F); 410a4c2d150SSean Silva DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F); 4116acdca78SChandler Carruth if (!runImpl(F, AC, &SE, &DT)) 412a4c2d150SSean Silva return PreservedAnalyses::all(); 413ca68a3ecSChandler Carruth 414a4c2d150SSean Silva PreservedAnalyses PA; 415ca68a3ecSChandler Carruth PA.preserveSet<CFGAnalyses>(); 416a4c2d150SSean Silva PA.preserve<AAManager>(); 417a4c2d150SSean Silva PA.preserve<ScalarEvolutionAnalysis>(); 418a4c2d150SSean Silva PA.preserve<GlobalsAA>(); 419a4c2d150SSean Silva return PA; 420a4c2d150SSean Silva } 421