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