1*5f757f3fSDimitry Andric //===- InferAlignment.cpp -------------------------------------------------===// 2*5f757f3fSDimitry Andric // 3*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5f757f3fSDimitry Andric // 7*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 8*5f757f3fSDimitry Andric // 9*5f757f3fSDimitry Andric // Infer alignment for load, stores and other memory operations based on 10*5f757f3fSDimitry Andric // trailing zero known bits information. 11*5f757f3fSDimitry Andric // 12*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 13*5f757f3fSDimitry Andric 14*5f757f3fSDimitry Andric #include "llvm/Transforms/Scalar/InferAlignment.h" 15*5f757f3fSDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 16*5f757f3fSDimitry Andric #include "llvm/Analysis/ValueTracking.h" 17*5f757f3fSDimitry Andric #include "llvm/IR/Instructions.h" 18*5f757f3fSDimitry Andric #include "llvm/InitializePasses.h" 19*5f757f3fSDimitry Andric #include "llvm/Support/KnownBits.h" 20*5f757f3fSDimitry Andric #include "llvm/Transforms/Scalar.h" 21*5f757f3fSDimitry Andric #include "llvm/Transforms/Utils/Local.h" 22*5f757f3fSDimitry Andric 23*5f757f3fSDimitry Andric using namespace llvm; 24*5f757f3fSDimitry Andric 25*5f757f3fSDimitry Andric static bool tryToImproveAlign( 26*5f757f3fSDimitry Andric const DataLayout &DL, Instruction *I, 27*5f757f3fSDimitry Andric function_ref<Align(Value *PtrOp, Align OldAlign, Align PrefAlign)> Fn) { 28*5f757f3fSDimitry Andric if (auto *LI = dyn_cast<LoadInst>(I)) { 29*5f757f3fSDimitry Andric Value *PtrOp = LI->getPointerOperand(); 30*5f757f3fSDimitry Andric Align OldAlign = LI->getAlign(); 31*5f757f3fSDimitry Andric Align NewAlign = Fn(PtrOp, OldAlign, DL.getPrefTypeAlign(LI->getType())); 32*5f757f3fSDimitry Andric if (NewAlign > OldAlign) { 33*5f757f3fSDimitry Andric LI->setAlignment(NewAlign); 34*5f757f3fSDimitry Andric return true; 35*5f757f3fSDimitry Andric } 36*5f757f3fSDimitry Andric } else if (auto *SI = dyn_cast<StoreInst>(I)) { 37*5f757f3fSDimitry Andric Value *PtrOp = SI->getPointerOperand(); 38*5f757f3fSDimitry Andric Value *ValOp = SI->getValueOperand(); 39*5f757f3fSDimitry Andric Align OldAlign = SI->getAlign(); 40*5f757f3fSDimitry Andric Align NewAlign = Fn(PtrOp, OldAlign, DL.getPrefTypeAlign(ValOp->getType())); 41*5f757f3fSDimitry Andric if (NewAlign > OldAlign) { 42*5f757f3fSDimitry Andric SI->setAlignment(NewAlign); 43*5f757f3fSDimitry Andric return true; 44*5f757f3fSDimitry Andric } 45*5f757f3fSDimitry Andric } 46*5f757f3fSDimitry Andric // TODO: Also handle memory intrinsics. 47*5f757f3fSDimitry Andric return false; 48*5f757f3fSDimitry Andric } 49*5f757f3fSDimitry Andric 50*5f757f3fSDimitry Andric bool inferAlignment(Function &F, AssumptionCache &AC, DominatorTree &DT) { 51*5f757f3fSDimitry Andric const DataLayout &DL = F.getParent()->getDataLayout(); 52*5f757f3fSDimitry Andric bool Changed = false; 53*5f757f3fSDimitry Andric 54*5f757f3fSDimitry Andric // Enforce preferred type alignment if possible. We do this as a separate 55*5f757f3fSDimitry Andric // pass first, because it may improve the alignments we infer below. 56*5f757f3fSDimitry Andric for (BasicBlock &BB : F) { 57*5f757f3fSDimitry Andric for (Instruction &I : BB) { 58*5f757f3fSDimitry Andric Changed |= tryToImproveAlign( 59*5f757f3fSDimitry Andric DL, &I, [&](Value *PtrOp, Align OldAlign, Align PrefAlign) { 60*5f757f3fSDimitry Andric if (PrefAlign > OldAlign) 61*5f757f3fSDimitry Andric return std::max(OldAlign, 62*5f757f3fSDimitry Andric tryEnforceAlignment(PtrOp, PrefAlign, DL)); 63*5f757f3fSDimitry Andric return OldAlign; 64*5f757f3fSDimitry Andric }); 65*5f757f3fSDimitry Andric } 66*5f757f3fSDimitry Andric } 67*5f757f3fSDimitry Andric 68*5f757f3fSDimitry Andric // Compute alignment from known bits. 69*5f757f3fSDimitry Andric for (BasicBlock &BB : F) { 70*5f757f3fSDimitry Andric for (Instruction &I : BB) { 71*5f757f3fSDimitry Andric Changed |= tryToImproveAlign( 72*5f757f3fSDimitry Andric DL, &I, [&](Value *PtrOp, Align OldAlign, Align PrefAlign) { 73*5f757f3fSDimitry Andric KnownBits Known = computeKnownBits(PtrOp, DL, 0, &AC, &I, &DT); 74*5f757f3fSDimitry Andric unsigned TrailZ = std::min(Known.countMinTrailingZeros(), 75*5f757f3fSDimitry Andric +Value::MaxAlignmentExponent); 76*5f757f3fSDimitry Andric return Align(1ull << std::min(Known.getBitWidth() - 1, TrailZ)); 77*5f757f3fSDimitry Andric }); 78*5f757f3fSDimitry Andric } 79*5f757f3fSDimitry Andric } 80*5f757f3fSDimitry Andric 81*5f757f3fSDimitry Andric return Changed; 82*5f757f3fSDimitry Andric } 83*5f757f3fSDimitry Andric 84*5f757f3fSDimitry Andric PreservedAnalyses InferAlignmentPass::run(Function &F, 85*5f757f3fSDimitry Andric FunctionAnalysisManager &AM) { 86*5f757f3fSDimitry Andric AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F); 87*5f757f3fSDimitry Andric DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F); 88*5f757f3fSDimitry Andric inferAlignment(F, AC, DT); 89*5f757f3fSDimitry Andric // Changes to alignment shouldn't invalidated analyses. 90*5f757f3fSDimitry Andric return PreservedAnalyses::all(); 91*5f757f3fSDimitry Andric } 92