15f757f3fSDimitry Andric //===- InferAlignment.cpp -------------------------------------------------===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric // 95f757f3fSDimitry Andric // Infer alignment for load, stores and other memory operations based on 105f757f3fSDimitry Andric // trailing zero known bits information. 115f757f3fSDimitry Andric // 125f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 135f757f3fSDimitry Andric 145f757f3fSDimitry Andric #include "llvm/Transforms/Scalar/InferAlignment.h" 155f757f3fSDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 165f757f3fSDimitry Andric #include "llvm/Analysis/ValueTracking.h" 175f757f3fSDimitry Andric #include "llvm/IR/Instructions.h" 185f757f3fSDimitry Andric #include "llvm/InitializePasses.h" 195f757f3fSDimitry Andric #include "llvm/Support/KnownBits.h" 205f757f3fSDimitry Andric #include "llvm/Transforms/Scalar.h" 215f757f3fSDimitry Andric #include "llvm/Transforms/Utils/Local.h" 225f757f3fSDimitry Andric 235f757f3fSDimitry Andric using namespace llvm; 245f757f3fSDimitry Andric 255f757f3fSDimitry Andric static bool tryToImproveAlign( 265f757f3fSDimitry Andric const DataLayout &DL, Instruction *I, 275f757f3fSDimitry Andric function_ref<Align(Value *PtrOp, Align OldAlign, Align PrefAlign)> Fn) { 285f757f3fSDimitry Andric if (auto *LI = dyn_cast<LoadInst>(I)) { 295f757f3fSDimitry Andric Value *PtrOp = LI->getPointerOperand(); 305f757f3fSDimitry Andric Align OldAlign = LI->getAlign(); 315f757f3fSDimitry Andric Align NewAlign = Fn(PtrOp, OldAlign, DL.getPrefTypeAlign(LI->getType())); 325f757f3fSDimitry Andric if (NewAlign > OldAlign) { 335f757f3fSDimitry Andric LI->setAlignment(NewAlign); 345f757f3fSDimitry Andric return true; 355f757f3fSDimitry Andric } 365f757f3fSDimitry Andric } else if (auto *SI = dyn_cast<StoreInst>(I)) { 375f757f3fSDimitry Andric Value *PtrOp = SI->getPointerOperand(); 385f757f3fSDimitry Andric Value *ValOp = SI->getValueOperand(); 395f757f3fSDimitry Andric Align OldAlign = SI->getAlign(); 405f757f3fSDimitry Andric Align NewAlign = Fn(PtrOp, OldAlign, DL.getPrefTypeAlign(ValOp->getType())); 415f757f3fSDimitry Andric if (NewAlign > OldAlign) { 425f757f3fSDimitry Andric SI->setAlignment(NewAlign); 435f757f3fSDimitry Andric return true; 445f757f3fSDimitry Andric } 455f757f3fSDimitry Andric } 465f757f3fSDimitry Andric // TODO: Also handle memory intrinsics. 475f757f3fSDimitry Andric return false; 485f757f3fSDimitry Andric } 495f757f3fSDimitry Andric 505f757f3fSDimitry Andric bool inferAlignment(Function &F, AssumptionCache &AC, DominatorTree &DT) { 51*0fca6ea1SDimitry Andric const DataLayout &DL = F.getDataLayout(); 525f757f3fSDimitry Andric bool Changed = false; 535f757f3fSDimitry Andric 545f757f3fSDimitry Andric // Enforce preferred type alignment if possible. We do this as a separate 555f757f3fSDimitry Andric // pass first, because it may improve the alignments we infer below. 565f757f3fSDimitry Andric for (BasicBlock &BB : F) { 575f757f3fSDimitry Andric for (Instruction &I : BB) { 585f757f3fSDimitry Andric Changed |= tryToImproveAlign( 595f757f3fSDimitry Andric DL, &I, [&](Value *PtrOp, Align OldAlign, Align PrefAlign) { 605f757f3fSDimitry Andric if (PrefAlign > OldAlign) 615f757f3fSDimitry Andric return std::max(OldAlign, 625f757f3fSDimitry Andric tryEnforceAlignment(PtrOp, PrefAlign, DL)); 635f757f3fSDimitry Andric return OldAlign; 645f757f3fSDimitry Andric }); 655f757f3fSDimitry Andric } 665f757f3fSDimitry Andric } 675f757f3fSDimitry Andric 685f757f3fSDimitry Andric // Compute alignment from known bits. 695f757f3fSDimitry Andric for (BasicBlock &BB : F) { 705f757f3fSDimitry Andric for (Instruction &I : BB) { 715f757f3fSDimitry Andric Changed |= tryToImproveAlign( 725f757f3fSDimitry Andric DL, &I, [&](Value *PtrOp, Align OldAlign, Align PrefAlign) { 735f757f3fSDimitry Andric KnownBits Known = computeKnownBits(PtrOp, DL, 0, &AC, &I, &DT); 745f757f3fSDimitry Andric unsigned TrailZ = std::min(Known.countMinTrailingZeros(), 755f757f3fSDimitry Andric +Value::MaxAlignmentExponent); 765f757f3fSDimitry Andric return Align(1ull << std::min(Known.getBitWidth() - 1, TrailZ)); 775f757f3fSDimitry Andric }); 785f757f3fSDimitry Andric } 795f757f3fSDimitry Andric } 805f757f3fSDimitry Andric 815f757f3fSDimitry Andric return Changed; 825f757f3fSDimitry Andric } 835f757f3fSDimitry Andric 845f757f3fSDimitry Andric PreservedAnalyses InferAlignmentPass::run(Function &F, 855f757f3fSDimitry Andric FunctionAnalysisManager &AM) { 865f757f3fSDimitry Andric AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F); 875f757f3fSDimitry Andric DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F); 885f757f3fSDimitry Andric inferAlignment(F, AC, DT); 895f757f3fSDimitry Andric // Changes to alignment shouldn't invalidated analyses. 905f757f3fSDimitry Andric return PreservedAnalyses::all(); 915f757f3fSDimitry Andric } 92