Skip to content

Commit d5aa5ef

Browse files
committed
* Improved comments
* Check for !AddRec instead of Invariant * Flattened check logic with better patternmatch use
1 parent 83e10d9 commit d5aa5ef

File tree

3 files changed

+40
-54
lines changed

3 files changed

+40
-54
lines changed

llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,9 @@ class LoopVectorizationLegality {
411411
}
412412

413413
/// Returns true if this is an early exit loop with state-changing or
414-
/// potentially-faulting operations and the IR representing the condition
415-
/// for the uncountable exit must be determined before any of the state
416-
/// changes or potentially faulting operations take place.
414+
/// potentially-faulting operations and the condition for the uncountable
415+
/// exit must be determined before any of the state changes or potentially
416+
/// faulting operations take place.
417417
bool hasUncountableExitWithSideEffects() const {
418418
return UncountableExitWithSideEffects;
419419
}
@@ -535,8 +535,8 @@ class LoopVectorizationLegality {
535535
/// Returns true if this is an early exit loop that can be vectorized.
536536
/// Currently, a loop with an uncountable early exit is considered
537537
/// vectorizable if:
538-
/// 1. Writes to memory do not form a dependence with any load used as
539-
/// part of the uncounted exit condition.
538+
/// 1. Writes to memory will access different underlying objects than
539+
/// any load used as part of the uncountable exit condition.
540540
/// 2. The loop has only one early uncountable exit
541541
/// 3. The early exit block dominates the latch block.
542542
/// 4. The latch block has an exact exit count.

llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp

Lines changed: 32 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,8 +1846,6 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
18461846

18471847
bool LoopVectorizationLegality::canUncountableExitConditionLoadBeMoved(
18481848
BasicBlock *ExitingBlock) {
1849-
LoadInst *CriticalUncountableExitConditionLoad = nullptr;
1850-
18511849
// Try to find a load in the critical path for the uncountable exit condition.
18521850
// This is currently matching about the simplest form we can, expecting
18531851
// only one in-loop load, the result of which is directly compared against
@@ -1858,10 +1856,12 @@ bool LoopVectorizationLegality::canUncountableExitConditionLoadBeMoved(
18581856
auto *Br = cast<BranchInst>(ExitingBlock->getTerminator());
18591857

18601858
using namespace llvm::PatternMatch;
1861-
Value *L = nullptr;
1859+
Instruction *L = nullptr;
1860+
Value *Ptr = nullptr;
18621861
Value *R = nullptr;
18631862
if (!match(Br->getCondition(),
1864-
m_OneUse(m_ICmp(m_OneUse(m_Value(L)), (m_Value(R)))))) {
1863+
m_OneUse(m_ICmp(m_OneUse(m_Instruction(L, m_Load(m_Value(Ptr)))),
1864+
m_Value(R))))) {
18651865
reportVectorizationFailure(
18661866
"Early exit loop with store but no supported condition load",
18671867
"NoConditionLoadForEarlyExitLoop", ORE, TheLoop);
@@ -1876,59 +1876,45 @@ bool LoopVectorizationLegality::canUncountableExitConditionLoadBeMoved(
18761876
return false;
18771877
}
18781878

1879-
if (auto *Load = dyn_cast<LoadInst>(L)) {
1880-
// Make sure that the load address is not loop invariant; we want an
1881-
// address calculation that we can rotate to the next vector iteration.
1882-
const SCEV *PtrScev = PSE.getSE()->getSCEV(Load->getPointerOperand());
1883-
if (PSE.getSE()->isLoopInvariant(PtrScev, TheLoop)) {
1884-
reportVectorizationFailure(
1885-
"Uncountable exit condition depends on load from invariant address",
1886-
"EarlyExitLoadInvariantAddress", ORE, TheLoop);
1887-
return false;
1888-
}
1889-
1890-
// The following call also checks that the load address is either
1891-
// invariant (which we've just ruled out) or is an affine SCEVAddRecExpr
1892-
// with a constant step. In either case, we're not relying on another
1893-
// load within the loop.
1894-
// FIXME: Support gathers after first-faulting load support lands.
1895-
SmallVector<const SCEVPredicate *, 4> Predicates;
1896-
if (!isDereferenceableAndAlignedInLoop(Load, TheLoop, *PSE.getSE(), *DT, AC,
1897-
&Predicates)) {
1898-
reportVectorizationFailure(
1899-
"Loop may fault",
1900-
"Cannot vectorize potentially faulting early exit loop",
1901-
"PotentiallyFaultingEarlyExitLoop", ORE, TheLoop);
1902-
return false;
1903-
}
1904-
1905-
ICFLoopSafetyInfo SafetyInfo;
1906-
SafetyInfo.computeLoopSafetyInfo(TheLoop);
1907-
// We need to know that load will be executed before we can hoist a
1908-
// copy out to run just before the first iteration.
1909-
// FIXME: Currently, other restrictions prevent us from reaching this point
1910-
// with a loop where the uncountable exit condition is determined
1911-
// by a conditional load.
1912-
assert(SafetyInfo.isGuaranteedToExecute(*Load, DT, TheLoop) &&
1913-
"Unhandled control flow in uncountable exit loop with side effects");
1914-
1915-
CriticalUncountableExitConditionLoad = Load;
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;
19161888
}
19171889

1918-
if (!CriticalUncountableExitConditionLoad) {
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)) {
19191895
reportVectorizationFailure(
1920-
"Early exit loop with store but no supported condition load",
1921-
"NoConditionLoadForEarlyExitLoop", ORE, TheLoop);
1896+
"Loop may fault",
1897+
"Cannot vectorize potentially faulting early exit loop",
1898+
"PotentiallyFaultingEarlyExitLoop", ORE, TheLoop);
19221899
return false;
19231900
}
19241901

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+
19251912
// Prohibit any potential aliasing with any instruction in the loop which
19261913
// might store to memory.
19271914
// FIXME: Relax this constraint where possible.
1928-
Value *Ptr = CriticalUncountableExitConditionLoad->getPointerOperand();
19291915
for (auto *BB : TheLoop->blocks()) {
19301916
for (auto &I : *BB) {
1931-
if (&I == CriticalUncountableExitConditionLoad)
1917+
if (&I == Load)
19321918
continue;
19331919

19341920
if (I.mayWriteToMemory()) {

llvm/test/Transforms/LoopVectorize/early_exit_store_legality.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ exit:
353353

354354
define void @loop_contains_store_condition_load_is_chained(ptr dereferenceable(40) noalias %array, ptr align 8 dereferenceable(160) readonly %offsets, ptr align 2 dereferenceable(40) readonly %pred) {
355355
; CHECK-LABEL: LV: Checking a loop in 'loop_contains_store_condition_load_is_chained'
356-
; CHECK: LV: Not vectorizing: Loop may fault.
356+
; CHECK: LV: Not vectorizing: Uncountable exit condition depends on load with an address that is not an add recurrence.
357357
entry:
358358
br label %for.body
359359

@@ -407,7 +407,7 @@ exit:
407407

408408
define void @loop_contains_store_condition_load_requires_gather(ptr dereferenceable(40) noalias %array, ptr align 2 dereferenceable(512) readonly %pred, ptr align 1 dereferenceable(20) readonly %offsets) {
409409
; CHECK-LABEL: LV: Checking a loop in 'loop_contains_store_condition_load_requires_gather'
410-
; CHECK: LV: Not vectorizing: Loop may fault.
410+
; CHECK: LV: Not vectorizing: Uncountable exit condition depends on load with an address that is not an add recurrence.
411411
entry:
412412
br label %for.body
413413

@@ -544,7 +544,7 @@ exit:
544544

545545
define void @uncountable_exit_condition_address_is_invariant(ptr dereferenceable(40) noalias %array, ptr align 2 dereferenceable(2) readonly %pred) {
546546
; CHECK-LABEL: LV: Checking a loop in 'uncountable_exit_condition_address_is_invariant'
547-
; CHECK: LV: Not vectorizing: Uncountable exit condition depends on load from invariant address.
547+
; CHECK: LV: Not vectorizing: Uncountable exit condition depends on load with an address that is not an add recurrence.
548548
entry:
549549
br label %for.body
550550

0 commit comments

Comments
 (0)