forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[InferAlignment] Implement InferAlignmentPass
This pass aims to infer alignment for instructions as a separate pass, to reduce redundant work done by InstCombine running multiple times. It runs late in the pipeline, just before the back-end passes where this information is most useful. Differential Revision: https://reviews.llvm.org/D158529
- Loading branch information
Showing
20 changed files
with
250 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
//===- InferAlignment.h -----------------------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Infer alignment for load, stores and other memory operations based on | ||
// trailing zero known bits information. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_TRANSFORMS_SCALAR_INFERALIGNMENT_H | ||
#define LLVM_TRANSFORMS_SCALAR_INFERALIGNMENT_H | ||
|
||
#include "llvm/IR/PassManager.h" | ||
|
||
namespace llvm { | ||
|
||
struct InferAlignmentPass : public PassInfoMixin<InferAlignmentPass> { | ||
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); | ||
}; | ||
|
||
} // namespace llvm | ||
|
||
#endif // LLVM_TRANSFORMS_SCALAR_INFERALIGNMENT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
//===- InferAlignment.cpp -------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Infer alignment for load, stores and other memory operations based on | ||
// trailing zero known bits information. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/Transforms/Scalar/InferAlignment.h" | ||
#include "llvm/Analysis/AssumptionCache.h" | ||
#include "llvm/Analysis/ValueTracking.h" | ||
#include "llvm/IR/Instructions.h" | ||
#include "llvm/InitializePasses.h" | ||
#include "llvm/Support/KnownBits.h" | ||
#include "llvm/Transforms/Scalar.h" | ||
#include "llvm/Transforms/Utils/Local.h" | ||
|
||
using namespace llvm; | ||
|
||
static bool tryToImproveAlign( | ||
const DataLayout &DL, Instruction *I, | ||
function_ref<Align(Value *PtrOp, Align OldAlign, Align PrefAlign)> Fn) { | ||
if (auto *LI = dyn_cast<LoadInst>(I)) { | ||
Value *PtrOp = LI->getPointerOperand(); | ||
Align OldAlign = LI->getAlign(); | ||
Align NewAlign = Fn(PtrOp, OldAlign, DL.getPrefTypeAlign(LI->getType())); | ||
if (NewAlign > OldAlign) { | ||
LI->setAlignment(NewAlign); | ||
return true; | ||
} | ||
} else if (auto *SI = dyn_cast<StoreInst>(I)) { | ||
Value *PtrOp = SI->getPointerOperand(); | ||
Value *ValOp = SI->getValueOperand(); | ||
Align OldAlign = SI->getAlign(); | ||
Align NewAlign = Fn(PtrOp, OldAlign, DL.getPrefTypeAlign(ValOp->getType())); | ||
if (NewAlign > OldAlign) { | ||
SI->setAlignment(NewAlign); | ||
return true; | ||
} | ||
} | ||
// TODO: Also handle memory intrinsics. | ||
return false; | ||
} | ||
|
||
bool inferAlignment(Function &F, AssumptionCache &AC, DominatorTree &DT) { | ||
const DataLayout &DL = F.getParent()->getDataLayout(); | ||
bool Changed = false; | ||
|
||
// Enforce preferred type alignment if possible. We do this as a separate | ||
// pass first, because it may improve the alignments we infer below. | ||
for (BasicBlock &BB : F) { | ||
for (Instruction &I : BB) { | ||
Changed |= tryToImproveAlign( | ||
DL, &I, [&](Value *PtrOp, Align OldAlign, Align PrefAlign) { | ||
if (PrefAlign > OldAlign) | ||
return std::max(OldAlign, | ||
tryEnforceAlignment(PtrOp, PrefAlign, DL)); | ||
return OldAlign; | ||
}); | ||
} | ||
} | ||
|
||
// Compute alignment from known bits. | ||
for (BasicBlock &BB : F) { | ||
for (Instruction &I : BB) { | ||
Changed |= tryToImproveAlign( | ||
DL, &I, [&](Value *PtrOp, Align OldAlign, Align PrefAlign) { | ||
KnownBits Known = computeKnownBits(PtrOp, DL, 0, &AC, &I, &DT); | ||
unsigned TrailZ = std::min(Known.countMinTrailingZeros(), | ||
+Value::MaxAlignmentExponent); | ||
return Align(1ull << std::min(Known.getBitWidth() - 1, TrailZ)); | ||
}); | ||
} | ||
} | ||
|
||
return Changed; | ||
} | ||
|
||
PreservedAnalyses InferAlignmentPass::run(Function &F, | ||
FunctionAnalysisManager &AM) { | ||
AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F); | ||
DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F); | ||
inferAlignment(F, AC, DT); | ||
// Changes to alignment shouldn't invalidated analyses. | ||
return PreservedAnalyses::all(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.