-
Notifications
You must be signed in to change notification settings - Fork 41
[AIEX] Loop Strength Reduction #780
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: aie-public
Are you sure you want to change the base?
Changes from 2 commits
97deaa2
ec9111a
1c9e047
edf5618
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ | |
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| // Modifications (c) Copyright 2023-2024 Advanced Micro Devices, Inc. or its | ||
| // Modifications (c) Copyright 2023-2026 Advanced Micro Devices, Inc. or its | ||
| // affiliates | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
@@ -66,6 +66,8 @@ class SmallBitVector; | |
| class StoreInst; | ||
| class SwitchInst; | ||
| class TargetLibraryInfo; | ||
| class TruncInst; | ||
| class GetElementPtrInst; | ||
| class Type; | ||
| class VPIntrinsic; | ||
| struct KnownBits; | ||
|
|
@@ -798,6 +800,22 @@ class TargetTransformInfo { | |
| AddressingModeKind getPreferredAddressingMode(const Loop *L, | ||
| ScalarEvolution *SE) const; | ||
|
|
||
| /// Return true if IVUsers() should look through the instruction to collect | ||
| /// its users instead. If true, populates GEPsToProcess with the GEP | ||
| /// instructions to process as IV users. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's just collecting interesting GEPs. This can be reflected in the name and its return value can be replaced by !GEPsToProcess.empty(); |
||
| /// This is useful for targets where pointer and integer bit sizes differ | ||
| /// (e.g., 20-bit pointers with 32-bit integers), causing truncs to index | ||
| /// size that feed GEP indices. | ||
| bool shouldIVUsersLookThroughInst( | ||
| Instruction *I, | ||
| SmallVectorImpl<GetElementPtrInst *> &GEPsToProcess) const; | ||
|
|
||
| /// Return true if the given type is valid for IV user collection. | ||
| /// By default, only legal integer widths up to 64 bits are allowed. | ||
| /// Targets where pointer and integer bit sizes differ may override this | ||
| /// to allow index-sized integers or pointers. | ||
| bool isValidIVUserType(Type *Ty) const; | ||
|
|
||
| /// Return true if the target supports masked store. | ||
| bool isLegalMaskedStore(Type *DataType, Align Alignment) const; | ||
| /// Return true if the target supports masked load. | ||
|
|
@@ -2009,6 +2027,10 @@ class TargetTransformInfo::Concept { | |
| TargetLibraryInfo *LibInfo) = 0; | ||
| virtual AddressingModeKind | ||
| getPreferredAddressingMode(const Loop *L, ScalarEvolution *SE) const = 0; | ||
| virtual bool shouldIVUsersLookThroughInst( | ||
| Instruction *I, | ||
| SmallVectorImpl<GetElementPtrInst *> &GEPsToProcess) const = 0; | ||
| virtual bool isValidIVUserType(Type *Ty) const = 0; | ||
| virtual bool isLegalMaskedStore(Type *DataType, Align Alignment) = 0; | ||
| virtual bool isLegalMaskedLoad(Type *DataType, Align Alignment) = 0; | ||
| virtual bool isLegalNTStore(Type *DataType, Align Alignment) = 0; | ||
|
|
@@ -2553,6 +2575,14 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { | |
| ScalarEvolution *SE) const override { | ||
| return Impl.getPreferredAddressingMode(L, SE); | ||
| } | ||
| bool shouldIVUsersLookThroughInst( | ||
| Instruction *I, | ||
| SmallVectorImpl<GetElementPtrInst *> &GEPsToProcess) const override { | ||
| return Impl.shouldIVUsersLookThroughInst(I, GEPsToProcess); | ||
| } | ||
| bool isValidIVUserType(Type *Ty) const override { | ||
| return Impl.isValidIVUserType(Ty); | ||
| } | ||
| bool isLegalMaskedStore(Type *DataType, Align Alignment) override { | ||
| return Impl.isLegalMaskedStore(DataType, Alignment); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,9 @@ | |
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| // Modifications (c) Copyright 2026 Advanced Micro Devices, Inc. or its | ||
| // affiliates | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This file implements bookkeeping for "interesting" users of expressions | ||
|
|
@@ -18,6 +21,7 @@ | |
| #include "llvm/Analysis/LoopInfo.h" | ||
| #include "llvm/Analysis/LoopPass.h" | ||
| #include "llvm/Analysis/ScalarEvolutionExpressions.h" | ||
| #include "llvm/Analysis/TargetTransformInfo.h" | ||
| #include "llvm/Analysis/ValueTracking.h" | ||
| #include "llvm/Config/llvm-config.h" | ||
| #include "llvm/IR/DataLayout.h" | ||
|
|
@@ -35,7 +39,7 @@ AnalysisKey IVUsersAnalysis::Key; | |
|
|
||
| IVUsers IVUsersAnalysis::run(Loop &L, LoopAnalysisManager &AM, | ||
| LoopStandardAnalysisResults &AR) { | ||
| return IVUsers(&L, &AR.AC, &AR.LI, &AR.DT, &AR.SE); | ||
| return IVUsers(&L, &AR.AC, &AR.LI, &AR.DT, &AR.SE, &AR.TTI); | ||
| } | ||
|
|
||
| char IVUsersWrapperPass::ID = 0; | ||
|
|
@@ -133,7 +137,7 @@ static bool IVUseShouldUsePostIncValue(Instruction *User, Value *Operand, | |
| /// Inspect the specified instruction. If it is a reducible SCEV, recursively | ||
| /// add its users to the IVUsesByStride set and return true. Otherwise, return | ||
| /// false. | ||
| bool IVUsers::AddUsersIfInteresting(Instruction *I) { | ||
| bool IVUsers::AddUsersIfInteresting(Instruction *I, bool BypassWidthCheck) { | ||
| const DataLayout &DL = I->getDataLayout(); | ||
|
|
||
| // Add this IV user to the Processed set before returning false to ensure that | ||
|
|
@@ -153,9 +157,16 @@ bool IVUsers::AddUsersIfInteresting(Instruction *I) { | |
| // LSR is not APInt clean, do not touch integers bigger than 64-bits. | ||
| // Also avoid creating IVs of non-native types. For example, we don't want a | ||
| // 64-bit IV in 32-bit code just because the loop has one 64-bit cast. | ||
|
F-Stuckmann marked this conversation as resolved.
|
||
| uint64_t Width = SE->getTypeSizeInBits(I->getType()); | ||
| if (Width > 64 || !DL.isLegalInteger(Width)) | ||
| return false; | ||
| // Use TTI hook if available to allow targets where pointer and integer bit | ||
| // sizes differ (e.g., 20-bit pointers with 32-bit integers) to enable IV | ||
| // user collection for index-sized types. | ||
| if (!BypassWidthCheck) { | ||
| const uint64_t Width = SE->getTypeSizeInBits(I->getType()); | ||
| const bool IsValidType = TTI ? TTI->isValidIVUserType(I->getType()) | ||
| : (Width <= 64 && DL.isLegalInteger(Width)); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need the BypassWidthCheck parameter? We override it with a TTI callback. |
||
| if (!IsValidType) | ||
| return false; | ||
| } | ||
|
|
||
| // Don't attempt to promote ephemeral values to indvars. They will be removed | ||
| // later anyway. | ||
|
|
@@ -170,6 +181,18 @@ bool IVUsers::AddUsersIfInteresting(Instruction *I) { | |
| if (!isInteresting(ISE, I, L, SE, LI)) | ||
| return false; | ||
|
|
||
| // Allow targets to look through certain instructions (e.g., truncs to index | ||
| // size on targets where pointer and integer bit sizes differ) to collect | ||
| // their users instead. This enables LSR to create pointer PHIs. | ||
| SmallVector<GetElementPtrInst *, 4> GEPsToProcess; | ||
| if (TTI && TTI->shouldIVUsersLookThroughInst(I, GEPsToProcess)) { | ||
| LLVM_DEBUG(dbgs() << "Looking through instruction: " << *I << '\n'); | ||
| bool AnyInteresting = false; | ||
| for (GetElementPtrInst *GEP : GEPsToProcess) | ||
| AnyInteresting |= AddUsersIfInteresting(GEP, /*BypassWidthCheck=*/true); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we don't skip it, it will be our TTI call back doing the check. Doesn't that give sufficient tuning freedom? |
||
| return AnyInteresting; | ||
|
F-Stuckmann marked this conversation as resolved.
|
||
| } | ||
|
|
||
| SmallPtrSet<Instruction *, 4> UniqueUsers; | ||
| for (Use &U : I->uses()) { | ||
| Instruction *User = cast<Instruction>(U.getUser()); | ||
|
|
@@ -249,8 +272,8 @@ IVStrideUse &IVUsers::AddUser(Instruction *User, Value *Operand) { | |
| } | ||
|
|
||
| IVUsers::IVUsers(Loop *L, AssumptionCache *AC, LoopInfo *LI, DominatorTree *DT, | ||
| ScalarEvolution *SE) | ||
| : L(L), AC(AC), LI(LI), DT(DT), SE(SE) { | ||
| ScalarEvolution *SE, const TargetTransformInfo *TTI) | ||
| : L(L), AC(AC), LI(LI), DT(DT), SE(SE), TTI(TTI) { | ||
| // Collect ephemeral values so that AddUsersIfInteresting skips them. | ||
| EphValues.clear(); | ||
| CodeMetrics::collectEphemeralValues(L, AC, EphValues); | ||
|
|
@@ -306,6 +329,7 @@ void IVUsersWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { | |
| AU.addRequired<LoopInfoWrapperPass>(); | ||
| AU.addRequired<DominatorTreeWrapperPass>(); | ||
| AU.addRequired<ScalarEvolutionWrapperPass>(); | ||
| AU.addRequired<TargetTransformInfoWrapperPass>(); | ||
| AU.setPreservesAll(); | ||
| } | ||
|
|
||
|
|
@@ -315,8 +339,10 @@ bool IVUsersWrapperPass::runOnLoop(Loop *L, LPPassManager &LPM) { | |
| auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); | ||
| auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); | ||
| auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); | ||
| auto *TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI( | ||
| *L->getHeader()->getParent()); | ||
|
|
||
| IU.reset(new IVUsers(L, AC, LI, DT, SE)); | ||
| IU.reset(new IVUsers(L, AC, LI, DT, SE, TTI)); | ||
| return false; | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.