Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
dc5b7c1
[LV] Add initial legality checks for loops with non-dereferenceable l…
arcbbb Aug 7, 2025
78f05df
Fix braces
arcbbb Aug 8, 2025
f5315f8
Limit to single unbound access. Add tests
arcbbb Aug 9, 2025
d3246bd
clang-formatted
arcbbb Aug 9, 2025
eb316ee
trivial fix: use lower case
arcbbb Aug 9, 2025
faa6112
trivial fix
arcbbb Aug 9, 2025
b206c9f
Address comment and refine TTI to check data type
arcbbb Aug 12, 2025
72383dd
Query subtarget feature for misaligned access support
arcbbb Aug 21, 2025
0c1d007
Add align 1 case
arcbbb Aug 22, 2025
e22c486
Rename isLegalSpeculativeLoad to isLegalFaultOnlyFirstLoad
arcbbb Aug 27, 2025
2a37216
Rename isReadOnlyLoopWithSafeOrSpeculativeLoads to
arcbbb Aug 27, 2025
abb0120
Rename SpeculativeLoads to FaultOnlyFirstLoads
arcbbb Aug 27, 2025
6b920f4
Refine comments with ff loads
arcbbb Aug 27, 2025
22dee5b
Update unittest to check the returned instructions
arcbbb Aug 27, 2025
e88d5d4
Refine report messages
arcbbb Aug 27, 2025
12e6dc9
Remove TTI isLegalFaultOnlyFirstLoad
arcbbb Aug 28, 2025
3284452
Update tests
arcbbb Aug 28, 2025
10156ca
Refine description
arcbbb Sep 2, 2025
16b5376
Rename isLoopSafeWithLoadOnlyFaults to isReadOnlyLoop
arcbbb Sep 2, 2025
357ff34
Refine error message
arcbbb Sep 2, 2025
ead7a78
Refine LoadTest
arcbbb Sep 2, 2025
9e98d12
clang-format
arcbbb Sep 2, 2025
f18dae7
Update tests
arcbbb Sep 2, 2025
9dc5a7a
Rename IsLoadOnlyFaultingLoop to IsReadOnlyLoop
arcbbb Sep 3, 2025
380e064
Assert the size of NonDerefLoads
arcbbb Sep 3, 2025
93db706
pass NonDereferenceableAndAlignedLoads as reference
arcbbb Sep 3, 2025
43976f7
Rename FaultOnlyFirstLoads to PotentiallyFaultingLoads
arcbbb Sep 3, 2025
51a8329
Update report message in LoopVectorize
arcbbb Sep 3, 2025
7a99472
Update descriptions
arcbbb Sep 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions llvm/include/llvm/Analysis/Loads.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ LLVM_ABI bool isDereferenceableReadOnlyLoop(
Loop *L, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC,
SmallVectorImpl<const SCEVPredicate *> *Predicates = nullptr);

/// Return true if the loop \p L cannot fault on any iteration and only
/// contains read-only memory accesses. Also collect loads that are not
/// guaranteed to be dereferenceable.
LLVM_ABI bool isReadOnlyLoopWithSafeOrSpeculativeLoads(
Loop *L, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC,
SmallVectorImpl<LoadInst *> *SpeculativeLoads,
SmallVectorImpl<const SCEVPredicate *> *Predicates = nullptr);

/// Return true if we know that executing a load from this value cannot trap.
///
/// If DT and ScanFrom are specified this method performs context-sensitive
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/Analysis/TargetTransformInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1857,6 +1857,10 @@ class TargetTransformInfo {
/// \returns True if the target supports scalable vectors.
LLVM_ABI bool supportsScalableVectors() const;

/// \returns True if the target supports speculative load intrinsics (e.g.,
/// vp.load.ff).
LLVM_ABI bool supportsSpeculativeLoads() const;

/// \return true when scalable vectorization is preferred.
LLVM_ABI bool enableScalableVectorization() const;

Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,8 @@ class TargetTransformInfoImplBase {

virtual bool supportsScalableVectors() const { return false; }

virtual bool supportsSpeculativeLoads() const { return false; }

virtual bool enableScalableVectorization() const { return false; }

virtual bool hasActiveVectorLength() const { return false; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,11 @@ class LoopVectorizationLegality {
/// Returns a list of all known histogram operations in the loop.
bool hasHistograms() const { return !Histograms.empty(); }

/// Returns the loads that may fault and need to be speculative.
const SmallPtrSetImpl<const Instruction *> &getSpeculativeLoads() const {
return SpeculativeLoads;
}

PredicatedScalarEvolution *getPredicatedScalarEvolution() const {
return &PSE;
}
Expand Down Expand Up @@ -630,6 +635,9 @@ class LoopVectorizationLegality {
/// may work on the same memory location.
SmallVector<HistogramInfo, 1> Histograms;

/// Hold all loads that need to be speculative.
SmallPtrSet<const Instruction *, 4> SpeculativeLoads;

/// BFI and PSI are used to check for profile guided size optimizations.
BlockFrequencyInfo *BFI;
ProfileSummaryInfo *PSI;
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Analysis/Loads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -870,3 +870,19 @@ bool llvm::isDereferenceableReadOnlyLoop(
}
return true;
}

bool llvm::isReadOnlyLoopWithSafeOrSpeculativeLoads(
Loop *L, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC,
SmallVectorImpl<LoadInst *> *SpeculativeLoads,
SmallVectorImpl<const SCEVPredicate *> *Predicates) {
for (BasicBlock *BB : L->blocks()) {
for (Instruction &I : *BB) {
if (auto *LI = dyn_cast<LoadInst>(&I)) {
if (!isDereferenceableAndAlignedInLoop(LI, L, *SE, *DT, AC, Predicates))
SpeculativeLoads->push_back(LI);
} else if (I.mayReadFromMemory() || I.mayWriteToMemory() || I.mayThrow())
return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Braces

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Thanks!

}
}
return true;
}
4 changes: 4 additions & 0 deletions llvm/lib/Analysis/TargetTransformInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,10 @@ bool TargetTransformInfo::supportsScalableVectors() const {
return TTIImpl->supportsScalableVectors();
}

bool TargetTransformInfo::supportsSpeculativeLoads() const {
return TTIImpl->supportsSpeculativeLoads();
}

bool TargetTransformInfo::enableScalableVectorization() const {
return TTIImpl->enableScalableVectorization();
}
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ class RISCVTTIImpl final : public BasicTTIImplBase<RISCVTTIImpl> {
bool supportsScalableVectors() const override {
return ST->hasVInstructions();
}
bool supportsSpeculativeLoads() const override {
return ST->hasVInstructions();
}
bool enableOrderedReductions() const override { return true; }
bool enableScalableVectorization() const override {
return ST->hasVInstructions();
Expand Down
31 changes: 28 additions & 3 deletions llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1760,16 +1760,41 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
assert(LatchBB->getUniquePredecessor() == SingleUncountableExitingBlock &&
"Expected latch predecessor to be the early exiting block");

// TODO: Handle loops that may fault.
Predicates.clear();
if (!isDereferenceableReadOnlyLoop(TheLoop, PSE.getSE(), DT, AC,
&Predicates)) {
SmallVector<LoadInst *, 4> NonDerefLoads;
bool HasSafeAccess =
TTI->supportsSpeculativeLoads()
? isReadOnlyLoopWithSafeOrSpeculativeLoads(
TheLoop, PSE.getSE(), DT, AC, &NonDerefLoads, &Predicates)
: isDereferenceableReadOnlyLoop(TheLoop, PSE.getSE(), DT, AC,
&Predicates);
if (!HasSafeAccess) {
reportVectorizationFailure(
"Loop may fault",
"Cannot vectorize potentially faulting early exit loop",
"PotentiallyFaultingEarlyExitLoop", ORE, TheLoop);
return false;
}
// Speculative loads need to be unit-stride.
for (LoadInst *LI : NonDerefLoads) {
if (LI->getParent() != TheLoop->getHeader()) {
reportVectorizationFailure("Cannot vectorize predicated speculative load",
"SpeculativeLoadNeedsPredication", ORE,
TheLoop);
return false;
}
int Stride = isConsecutivePtr(LI->getType(), LI->getPointerOperand());
if (Stride != 1) {
reportVectorizationFailure("Loop contains non-unit-stride load",
"Cannot vectorize early exit loop with "
"speculative non-unit-stride load",
"SpeculativeNonUnitStrideLoadEarlyExitLoop",
ORE, TheLoop);
return false;
}
SpeculativeLoads.insert(LI);
LLVM_DEBUG(dbgs() << "LV: Found speculative load: " << *LI << "\n");
}

[[maybe_unused]] const SCEV *SymbolicMaxBTC =
PSE.getSymbolicMaxBackedgeTakenCount();
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10041,6 +10041,13 @@ bool LoopVectorizePass::processLoop(Loop *L) {
return false;
}

if (!LVL.getSpeculativeLoads().empty()) {
reportVectorizationFailure("Auto-vectorization of loops with speculative "
"load is not supported",
"SpeculativeLoadsNotSupported", ORE, L);
return false;
}

// Entrance to the VPlan-native vectorization path. Outer loops are processed
// here. They may require CFG and instruction level transformations before
// even evaluating whether vectorization is profitable. Since we cannot modify
Expand Down