1515//
1616
1717#include " llvm/Transforms/Vectorize/LoopVectorizationLegality.h"
18+ #include " llvm/Analysis/AliasAnalysis.h"
1819#include " llvm/Analysis/Loads.h"
1920#include " llvm/Analysis/LoopInfo.h"
21+ #include " llvm/Analysis/MustExecute.h"
2022#include " llvm/Analysis/OptimizationRemarkEmitter.h"
2123#include " llvm/Analysis/ScalarEvolutionExpressions.h"
2224#include " llvm/Analysis/TargetLibraryInfo.h"
@@ -1223,8 +1225,18 @@ bool LoopVectorizationLegality::canVectorizeMemory() {
12231225 });
12241226 }
12251227
1226- if (!LAI->canVectorizeMemory ())
1228+ if (!LAI->canVectorizeMemory ()) {
1229+ if (hasUncountableExitWithSideEffects ()) {
1230+ reportVectorizationFailure (
1231+ " Cannot vectorize unsafe dependencies in uncountable exit loop with "
1232+ " side effects" ,
1233+ " CantVectorizeUnsafeDependencyForEELoopWithSideEffects" , ORE,
1234+ TheLoop);
1235+ return false ;
1236+ }
1237+
12271238 return canVectorizeIndirectUnsafeDependences ();
1239+ }
12281240
12291241 if (LAI->hasLoadStoreDependenceInvolvingLoopInvariantAddress ()) {
12301242 reportVectorizationFailure (" We don't allow storing to uniform addresses" ,
@@ -1755,16 +1767,24 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
17551767 }
17561768 };
17571769
1770+ bool HasSideEffects = false ;
17581771 for (auto *BB : TheLoop->blocks ())
17591772 for (auto &I : *BB) {
17601773 if (I.mayWriteToMemory ()) {
1761- // We don't support writes to memory.
1774+ if (isa<StoreInst>(&I) && cast<StoreInst>(&I)->isSimple ()) {
1775+ HasSideEffects = true ;
1776+ continue ;
1777+ }
1778+
1779+ // We don't support complex writes to memory.
17621780 reportVectorizationFailure (
1763- " Writes to memory unsupported in early exit loops" ,
1764- " Cannot vectorize early exit loop with writes to memory" ,
1781+ " Complex writes to memory unsupported in early exit loops" ,
1782+ " Cannot vectorize early exit loop with complex writes to memory" ,
17651783 " WritesInEarlyExitLoop" , ORE, TheLoop);
17661784 return false ;
1767- } else if (!IsSafeOperation (&I)) {
1785+ }
1786+
1787+ if (!IsSafeOperation (&I)) {
17681788 reportVectorizationFailure (" Early exit loop contains operations that "
17691789 " cannot be speculatively executed" ,
17701790 " UnsafeOperationsEarlyExitLoop" , ORE,
@@ -1777,15 +1797,22 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
17771797 assert (LatchBB->getUniquePredecessor () == SingleUncountableExitingBlock &&
17781798 " Expected latch predecessor to be the early exiting block" );
17791799
1780- Predicates.clear ();
17811800 SmallVector<LoadInst *, 4 > NonDerefLoads;
1782- if (!isReadOnlyLoop (TheLoop, PSE.getSE (), DT, AC, NonDerefLoads,
1783- &Predicates)) {
1784- reportVectorizationFailure (" Loop may fault" ,
1785- " Cannot vectorize non-read-only early exit loop" ,
1786- " NonReadOnlyEarlyExitLoop" , ORE, TheLoop);
1801+ // TODO: Handle loops that may fault.
1802+ if (!HasSideEffects) {
1803+ // Read-only loop.
1804+ Predicates.clear ();
1805+ if (!isReadOnlyLoop (TheLoop, PSE.getSE (), DT, AC, NonDerefLoads,
1806+ &Predicates)) {
1807+ reportVectorizationFailure (
1808+ " Loop may fault" , " Cannot vectorize non-read-only early exit loop" ,
1809+ " NonReadOnlyEarlyExitLoop" , ORE, TheLoop);
1810+ return false ;
1811+ }
1812+ } else if (!canUncountableExitConditionLoadBeMoved (
1813+ SingleUncountableExitingBlock))
17871814 return false ;
1788- }
1815+
17891816 // Check non-dereferenceable loads if any.
17901817 for (LoadInst *LI : NonDerefLoads) {
17911818 // Only support unit-stride access for now.
@@ -1813,6 +1840,99 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
18131840 " backedge taken count: "
18141841 << *SymbolicMaxBTC << ' \n ' );
18151842 UncountableExitingBB = SingleUncountableExitingBlock;
1843+ UncountableExitWithSideEffects = HasSideEffects;
1844+ return true ;
1845+ }
1846+
1847+ bool LoopVectorizationLegality::canUncountableExitConditionLoadBeMoved (
1848+ BasicBlock *ExitingBlock) {
1849+ // Try to find a load in the critical path for the uncountable exit condition.
1850+ // This is currently matching about the simplest form we can, expecting
1851+ // only one in-loop load, the result of which is directly compared against
1852+ // a loop-invariant value.
1853+ // FIXME: We're insisting on a single use for now, because otherwise we will
1854+ // need to make PHI nodes for other users. That can be done once the initial
1855+ // transform code lands.
1856+ auto *Br = cast<BranchInst>(ExitingBlock->getTerminator ());
1857+
1858+ using namespace llvm ::PatternMatch;
1859+ Instruction *L = nullptr ;
1860+ Value *Ptr = nullptr ;
1861+ Value *R = nullptr ;
1862+ if (!match (Br->getCondition (),
1863+ m_OneUse (m_ICmp (m_OneUse (m_Instruction (L, m_Load (m_Value (Ptr)))),
1864+ m_Value (R))))) {
1865+ reportVectorizationFailure (
1866+ " Early exit loop with store but no supported condition load" ,
1867+ " NoConditionLoadForEarlyExitLoop" , ORE, TheLoop);
1868+ return false ;
1869+ }
1870+
1871+ // FIXME: Don't rely on operand ordering for the comparison.
1872+ if (!TheLoop->isLoopInvariant (R)) {
1873+ reportVectorizationFailure (
1874+ " Early exit loop with store but no supported condition load" ,
1875+ " NoConditionLoadForEarlyExitLoop" , ORE, TheLoop);
1876+ return false ;
1877+ }
1878+
1879+ // Make sure that the load address is not loop invariant; we want an
1880+ // address calculation that we can rotate to the next vector iteration.
1881+ const SCEV *PtrScev = PSE.getSE ()->getSCEV (Ptr);
1882+ if (!isa<SCEVAddRecExpr>(PtrScev)) {
1883+ reportVectorizationFailure (
1884+ " Uncountable exit condition depends on load with an address that is "
1885+ " not an add recurrence" ,
1886+ " EarlyExitLoadInvariantAddress" , ORE, TheLoop);
1887+ return false ;
1888+ }
1889+
1890+ // FIXME: Support gathers after first-faulting load support lands.
1891+ SmallVector<const SCEVPredicate *, 4 > Predicates;
1892+ LoadInst *Load = cast<LoadInst>(L);
1893+ if (!isDereferenceableAndAlignedInLoop (Load, TheLoop, *PSE.getSE (), *DT, AC,
1894+ &Predicates)) {
1895+ reportVectorizationFailure (
1896+ " Loop may fault" ,
1897+ " Cannot vectorize potentially faulting early exit loop" ,
1898+ " PotentiallyFaultingEarlyExitLoop" , ORE, TheLoop);
1899+ return false ;
1900+ }
1901+
1902+ ICFLoopSafetyInfo SafetyInfo;
1903+ SafetyInfo.computeLoopSafetyInfo (TheLoop);
1904+ // We need to know that load will be executed before we can hoist a
1905+ // copy out to run just before the first iteration.
1906+ // FIXME: Currently, other restrictions prevent us from reaching this point
1907+ // with a loop where the uncountable exit condition is determined
1908+ // by a conditional load.
1909+ assert (SafetyInfo.isGuaranteedToExecute (*Load, DT, TheLoop) &&
1910+ " Unhandled control flow in uncountable exit loop with side effects" );
1911+
1912+ // Prohibit any potential aliasing with any instruction in the loop which
1913+ // might store to memory.
1914+ // FIXME: Relax this constraint where possible.
1915+ for (auto *BB : TheLoop->blocks ()) {
1916+ for (auto &I : *BB) {
1917+ if (&I == Load)
1918+ continue ;
1919+
1920+ if (I.mayWriteToMemory ()) {
1921+ if (auto *SI = dyn_cast<StoreInst>(&I)) {
1922+ AliasResult AR = AA->alias (Ptr, SI->getPointerOperand ());
1923+ if (AR == AliasResult::NoAlias)
1924+ continue ;
1925+ }
1926+
1927+ reportVectorizationFailure (
1928+ " Cannot determine whether critical uncountable exit load address "
1929+ " does not alias with a memory write" ,
1930+ " CantVectorizeAliasWithCriticalUncountableExitLoad" , ORE, TheLoop);
1931+ return false ;
1932+ }
1933+ }
1934+ }
1935+
18161936 return true ;
18171937}
18181938
@@ -1885,6 +2005,7 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) {
18852005 } else {
18862006 if (!isVectorizableEarlyExitLoop ()) {
18872007 assert (!hasUncountableEarlyExit () &&
2008+ !hasUncountableExitWithSideEffects () &&
18882009 " Must be false without vectorizable early-exit loop" );
18892010 if (DoExtraAnalysis)
18902011 Result = false ;
@@ -1903,6 +2024,15 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) {
19032024 return false ;
19042025 }
19052026
2027+ // Bail out for state-changing loops with uncountable exits for now.
2028+ if (UncountableExitWithSideEffects) {
2029+ reportVectorizationFailure (
2030+ " Writes to memory unsupported in early exit loops" ,
2031+ " Cannot vectorize early exit loop with writes to memory" ,
2032+ " WritesInEarlyExitLoop" , ORE, TheLoop);
2033+ return false ;
2034+ }
2035+
19062036 if (Result) {
19072037 LLVM_DEBUG (dbgs () << " LV: We can vectorize this loop"
19082038 << (LAI->getRuntimePointerChecking ()->Need
0 commit comments