17
17
#include " llvm/Transforms/Vectorize/LoopVectorizationLegality.h"
18
18
#include " llvm/Analysis/Loads.h"
19
19
#include " llvm/Analysis/LoopInfo.h"
20
+ #include " llvm/Analysis/MustExecute.h"
20
21
#include " llvm/Analysis/OptimizationRemarkEmitter.h"
21
22
#include " llvm/Analysis/ScalarEvolutionExpressions.h"
22
23
#include " llvm/Analysis/TargetLibraryInfo.h"
@@ -1209,6 +1210,36 @@ bool LoopVectorizationLegality::canVectorizeMemory() {
1209
1210
});
1210
1211
}
1211
1212
1213
+ // FIXME: Remove or reduce this restriction. We're in a bit of an odd spot
1214
+ // since we're (potentially) doing the load out of its normal order
1215
+ // in the loop and that may throw off dependency checking.
1216
+ // A forward dependency should be fine, but a backwards dep may not
1217
+ // be even if LAA thinks it is due to performing the load for the
1218
+ // vector iteration i+1 in vector iteration i.
1219
+ if (isConditionCopyRequired ()) {
1220
+ assert (EarlyExitLoad.has_value () && " EE Store without condition load." );
1221
+
1222
+ if (LAI->canVectorizeMemory ()) {
1223
+ const MemoryDepChecker &DepChecker = LAI->getDepChecker ();
1224
+ const auto *Deps = DepChecker.getDependences ();
1225
+
1226
+ for (const MemoryDepChecker::Dependence &Dep : *Deps) {
1227
+ if (Dep.getDestination (DepChecker) == EarlyExitLoad ||
1228
+ Dep.getSource (DepChecker) == EarlyExitLoad) {
1229
+ // Refine language a little? This currently only applies when a store
1230
+ // is present in the early exit loop.
1231
+ reportVectorizationFailure (
1232
+ " No dependencies allowed for early exit condition load" ,
1233
+ " Early exit condition loads may not have a dependence with another"
1234
+ " memory operation." ,
1235
+ " CantVectorizeStoreToLoopInvariantAddress" , ORE,
1236
+ TheLoop);
1237
+ return false ;
1238
+ }
1239
+ }
1240
+ }
1241
+ }
1242
+
1212
1243
if (!LAI->canVectorizeMemory ())
1213
1244
return canVectorizeIndirectUnsafeDependences ();
1214
1245
@@ -1627,6 +1658,7 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
1627
1658
// Keep a record of all the exiting blocks.
1628
1659
SmallVector<const SCEVPredicate *, 4 > Predicates;
1629
1660
std::optional<std::pair<BasicBlock *, BasicBlock *>> SingleUncountableEdge;
1661
+ std::optional<LoadInst *> EELoad;
1630
1662
for (BasicBlock *BB : ExitingBlocks) {
1631
1663
const SCEV *EC =
1632
1664
PSE.getSE ()->getPredicatedExitCount (TheLoop, BB, &Predicates);
@@ -1656,6 +1688,21 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
1656
1688
return false ;
1657
1689
}
1658
1690
1691
+ // For loops with stores.
1692
+ // Record load for analysis by isDereferenceableAndAlignedInLoop
1693
+ // and later by dependence analysis.
1694
+ if (BranchInst *Br = dyn_cast<BranchInst>(BB->getTerminator ())) {
1695
+ // FIXME: Handle exit conditions with multiple users, more complex exit
1696
+ // conditions than br(icmp(load, loop_inv)).
1697
+ ICmpInst *Cmp = dyn_cast<ICmpInst>(Br->getCondition ());
1698
+ if (Cmp && Cmp->hasOneUse () &&
1699
+ TheLoop->isLoopInvariant (Cmp->getOperand (1 ))) {
1700
+ LoadInst *Load = dyn_cast<LoadInst>(Cmp->getOperand (0 ));
1701
+ if (Load && Load->hasOneUse () && TheLoop->contains (Load))
1702
+ EELoad = Load;
1703
+ }
1704
+ }
1705
+
1659
1706
SingleUncountableEdge = {BB, ExitBlock};
1660
1707
} else
1661
1708
CountableExitingBlocks.push_back (BB);
@@ -1708,16 +1755,31 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
1708
1755
}
1709
1756
};
1710
1757
1758
+ bool HasStore = false ;
1711
1759
for (auto *BB : TheLoop->blocks ())
1712
1760
for (auto &I : *BB) {
1761
+ if (StoreInst *SI = dyn_cast<StoreInst>(&I)) {
1762
+ HasStore = true ;
1763
+ if (SI->isSimple ())
1764
+ continue ;
1765
+
1766
+ reportVectorizationFailure (
1767
+ " Complex writes to memory unsupported in early exit loops" ,
1768
+ " Cannot vectorize early exit loop with complex writes to memory" ,
1769
+ " WritesInEarlyExitLoop" , ORE, TheLoop);
1770
+ return false ;
1771
+ }
1772
+
1713
1773
if (I.mayWriteToMemory ()) {
1714
1774
// We don't support writes to memory.
1715
1775
reportVectorizationFailure (
1716
- " Writes to memory unsupported in early exit loops" ,
1717
- " Cannot vectorize early exit loop with writes to memory" ,
1776
+ " Complex writes to memory unsupported in early exit loops" ,
1777
+ " Cannot vectorize early exit loop with complex writes to memory" ,
1718
1778
" WritesInEarlyExitLoop" , ORE, TheLoop);
1719
1779
return false ;
1720
- } else if (!IsSafeOperation (&I)) {
1780
+ }
1781
+
1782
+ if (!IsSafeOperation (&I)) {
1721
1783
reportVectorizationFailure (" Early exit loop contains operations that "
1722
1784
" cannot be speculatively executed" ,
1723
1785
" UnsafeOperationsEarlyExitLoop" , ORE,
@@ -1732,13 +1794,53 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
1732
1794
1733
1795
// TODO: Handle loops that may fault.
1734
1796
Predicates.clear ();
1735
- if (!isDereferenceableReadOnlyLoop (TheLoop, PSE.getSE (), DT, AC,
1736
- &Predicates)) {
1797
+
1798
+ if (HasStore && EELoad.has_value ()) {
1799
+ LoadInst *LI = *EELoad;
1800
+ if (isDereferenceableAndAlignedInLoop (LI, TheLoop, *PSE.getSE (), *DT, AC,
1801
+ &Predicates)) {
1802
+ ICFLoopSafetyInfo SafetyInfo;
1803
+ SafetyInfo.computeLoopSafetyInfo (TheLoop);
1804
+ // FIXME: We may have multiple levels of conditional loads, so will
1805
+ // need to improve on outright rejection at some point.
1806
+ if (!SafetyInfo.isGuaranteedToExecute (*LI, DT, TheLoop)) {
1807
+ LLVM_DEBUG (
1808
+ dbgs () << " Early exit condition load not guaranteed to execute.\n " );
1809
+ reportVectorizationFailure (
1810
+ " Early exit condition load not guaranteed to execute" ,
1811
+ " Cannot vectorize early exit loop when condition load is not "
1812
+ " guaranteed to execute" ,
1813
+ " EarlyExitLoadNotGuaranteed" , ORE, TheLoop);
1814
+ }
1815
+ } else {
1816
+ LLVM_DEBUG (dbgs () << " Early exit condition load potentially unsafe.\n " );
1817
+ reportVectorizationFailure (" Uncounted loop condition not known safe" ,
1818
+ " Cannot vectorize early exit loop with "
1819
+ " possibly unsafe condition load" ,
1820
+ " PotentiallyFaultingEarlyExitLoop" , ORE,
1821
+ TheLoop);
1822
+ return false ;
1823
+ }
1824
+ } else if (HasStore) {
1825
+ LLVM_DEBUG (dbgs () << " Found early exit store but no condition load.\n " );
1737
1826
reportVectorizationFailure (
1738
- " Loop may fault " ,
1739
- " Cannot vectorize potentially faulting early exit loop" ,
1740
- " PotentiallyFaultingEarlyExitLoop " , ORE, TheLoop);
1827
+ " Early exit loop with store but no condition load " ,
1828
+ " Cannot vectorize early exit loop with store but no condition load " ,
1829
+ " NoConditionLoadForEarlyExitLoop " , ORE, TheLoop);
1741
1830
return false ;
1831
+ } else {
1832
+ // Read-only loop.
1833
+ // FIXME: as with the loops with stores, only the loads contributing to
1834
+ // the loop condition need to be guaranteed dereferenceable and
1835
+ // aligned.
1836
+ if (!isDereferenceableReadOnlyLoop (TheLoop, PSE.getSE (), DT, AC,
1837
+ &Predicates)) {
1838
+ reportVectorizationFailure (
1839
+ " Loop may fault" ,
1840
+ " Cannot vectorize potentially faulting early exit loop" ,
1841
+ " PotentiallyFaultingEarlyExitLoop" , ORE, TheLoop);
1842
+ return false ;
1843
+ }
1742
1844
}
1743
1845
1744
1846
[[maybe_unused]] const SCEV *SymbolicMaxBTC =
@@ -1751,6 +1853,11 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
1751
1853
" backedge taken count: "
1752
1854
<< *SymbolicMaxBTC << ' \n ' );
1753
1855
UncountableEdge = SingleUncountableEdge;
1856
+ if (HasStore) {
1857
+ RequiresEarlyExitConditionCopy = true ;
1858
+ EarlyExitLoad = EELoad;
1859
+ }
1860
+
1754
1861
return true ;
1755
1862
}
1756
1863
@@ -1823,6 +1930,8 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) {
1823
1930
} else {
1824
1931
if (!isVectorizableEarlyExitLoop ()) {
1825
1932
UncountableEdge = std::nullopt;
1933
+ EarlyExitLoad = std::nullopt;
1934
+ RequiresEarlyExitConditionCopy = false ;
1826
1935
if (DoExtraAnalysis)
1827
1936
Result = false ;
1828
1937
else
0 commit comments