Skip to content

Commit 778b455

Browse files
committed
[LAA] Add Memory dependence remarks.
Adds new optimization remarks when vectorization fails. More specifically, new remarks are added for following 4 cases: - Backward dependency - Backward dependency that prevents Store-to-load forwarding - Forward dependency that prevents Store-to-load forwarding - Unknown dependency It is important to note that only one of the sources of failures (to vectorize) is reported by the remarks. This source of failure may not be first in program order. A regression test has been added to test the following cases: a) Loop can be vectorized: No optimization remark is emitted b) Loop can not be vectorized: In this case an optimization remark will be emitted for one source of failure. Reviewed By: sdesmalen, david-arm Differential Revision: https://reviews.llvm.org/D108371
1 parent 5aa2acc commit 778b455

File tree

12 files changed

+491
-11
lines changed

12 files changed

+491
-11
lines changed

llvm/include/llvm/Analysis/LoopAccessAnalysis.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,11 @@ class LoopAccessInfo {
605605
/// invariant.
606606
void collectStridedAccess(Value *LoadOrStoreInst);
607607

608+
// Emits the first unsafe memory dependence in a loop.
609+
// Emits nothing if there are no unsafe dependences
610+
// or if the dependences were not recorded.
611+
void emitUnsafeDependenceRemark();
612+
608613
std::unique_ptr<PredicatedScalarEvolution> PSE;
609614

610615
/// We need to check that all of the pointers in this list are disjoint

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,13 +2129,61 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
21292129
dbgs() << "LAA: No unsafe dependent memory operations in loop. We"
21302130
<< (PtrRtChecking->Need ? "" : " don't")
21312131
<< " need runtime memory checks.\n");
2132-
else {
2133-
recordAnalysis("UnsafeMemDep")
2134-
<< "unsafe dependent memory operations in loop. Use "
2135-
"#pragma loop distribute(enable) to allow loop distribution "
2136-
"to attempt to isolate the offending operations into a separate "
2137-
"loop";
2138-
LLVM_DEBUG(dbgs() << "LAA: unsafe dependent memory operations in loop\n");
2132+
else
2133+
emitUnsafeDependenceRemark();
2134+
}
2135+
2136+
void LoopAccessInfo::emitUnsafeDependenceRemark() {
2137+
auto Deps = getDepChecker().getDependences();
2138+
if (!Deps)
2139+
return;
2140+
auto Found = std::find_if(
2141+
Deps->begin(), Deps->end(), [](const MemoryDepChecker::Dependence &D) {
2142+
return MemoryDepChecker::Dependence::isSafeForVectorization(D.Type) !=
2143+
MemoryDepChecker::VectorizationSafetyStatus::Safe;
2144+
});
2145+
if (Found == Deps->end())
2146+
return;
2147+
MemoryDepChecker::Dependence Dep = *Found;
2148+
2149+
LLVM_DEBUG(dbgs() << "LAA: unsafe dependent memory operations in loop\n");
2150+
2151+
// Emit remark for first unsafe dependence
2152+
OptimizationRemarkAnalysis &R =
2153+
recordAnalysis("UnsafeDep", Dep.getDestination(*this))
2154+
<< "unsafe dependent memory operations in loop. Use "
2155+
"#pragma loop distribute(enable) to allow loop distribution "
2156+
"to attempt to isolate the offending operations into a separate "
2157+
"loop";
2158+
2159+
switch (Dep.Type) {
2160+
case MemoryDepChecker::Dependence::NoDep:
2161+
case MemoryDepChecker::Dependence::Forward:
2162+
case MemoryDepChecker::Dependence::BackwardVectorizable:
2163+
llvm_unreachable("Unexpected dependence");
2164+
case MemoryDepChecker::Dependence::Backward:
2165+
R << "\nBackward loop carried data dependence.";
2166+
break;
2167+
case MemoryDepChecker::Dependence::ForwardButPreventsForwarding:
2168+
R << "\nForward loop carried data dependence that prevents "
2169+
"store-to-load forwarding.";
2170+
break;
2171+
case MemoryDepChecker::Dependence::BackwardVectorizableButPreventsForwarding:
2172+
R << "\nBackward loop carried data dependence that prevents "
2173+
"store-to-load forwarding.";
2174+
break;
2175+
case MemoryDepChecker::Dependence::Unknown:
2176+
R << "\nUnknown data dependence.";
2177+
break;
2178+
}
2179+
2180+
if (Instruction *I = Dep.getSource(*this)) {
2181+
DebugLoc SourceLoc = I->getDebugLoc();
2182+
if (auto *DD = dyn_cast_or_null<Instruction>(getPointerOperand(I)))
2183+
SourceLoc = DD->getDebugLoc();
2184+
if (SourceLoc)
2185+
R << " Memory location is the same as accessed at "
2186+
<< ore::NV("Location", SourceLoc);
21392187
}
21402188
}
21412189

llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ exit:
7878
; CHECK-LABEL: function 'backdep_type_store_size_equivalence':
7979
; CHECK-NEXT: loop:
8080
; CHECK-NEXT: Report: unsafe dependent memory operations in loop.
81+
; CHECK-NEXT: Unknown data dependence.
8182
; CHECK-NEXT: Dependences:
8283
; CHECK-NEXT: Unknown:
8384
; CHECK-NEXT: %ld.f32 = load float, float* %gep.iv.f32, align 8 ->
@@ -120,6 +121,7 @@ exit:
120121
; CHECK-LABEL: function 'neg_dist_dep_type_size_equivalence':
121122
; CHECK-NEXT: loop:
122123
; CHECK-NEXT: Report: unsafe dependent memory operations in loop.
124+
; CHECK-NEXT: Unknown data dependence.
123125
; CHECK-NEXT: Dependences:
124126
; CHECK-NEXT: Unknown:
125127
; CHECK-NEXT: %ld.i64 = load i64, i64* %gep.iv, align 8 ->

llvm/test/Analysis/LoopAccessAnalysis/pointer-phis.ll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ define i32 @load_with_pointer_phi_outside_loop(double* %A, double* %B, double* %
127127
; CHECK-LABEL: 'load_with_pointer_phi_outside_loop'
128128
; CHECK-NEXT: loop.header:
129129
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
130+
; CHECK-NEXT: Unknown data dependence.
130131
; CHECK-NEXT: Dependences:
131132
; CHECK-NEXT: Unknown:
132133
; CHECK-NEXT: %v8 = load double, double* %ptr, align 8 ->
@@ -164,6 +165,7 @@ define i32 @store_with_pointer_phi_outside_loop(double* %A, double* %B, double*
164165
; CHECK-LABEL: 'store_with_pointer_phi_outside_loop'
165166
; CHECK-NEXT: loop.header:
166167
; CHECK-NEXT: Report: unsafe dependent memory operations in loop.
168+
; CHECK-NEXT: Unknown data dependence.
167169
; CHECK-NEXT: Dependences:
168170
; CHECK-NEXT: Unknown:
169171
; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 ->
@@ -201,6 +203,7 @@ define i32 @store_with_pointer_phi_incoming_phi(double* %A, double* %B, double*
201203
; CHECK-LABEL: 'store_with_pointer_phi_incoming_phi'
202204
; CHECK-NEXT: loop.header:
203205
; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
206+
; CHECK-NEXT: Unknown data dependence.
204207
; CHECK-NEXT: Dependences:
205208
; CHECK-NEXT: Unknown:
206209
; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 ->
@@ -277,6 +280,7 @@ define i32 @store_with_pointer_phi_incoming_phi_irreducible_cycle(double* %A, do
277280
; CHECK-LABEL: 'store_with_pointer_phi_incoming_phi_irreducible_cycle'
278281
; CHECK-NEXT: loop.header:
279282
; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
283+
; CHECK-NEXT: Unknown data dependence.
280284
; CHECK-NEXT: Dependences:
281285
; CHECK-NEXT: Unknown:
282286
; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 ->
@@ -348,6 +352,7 @@ define i32 @store_with_pointer_phi_outside_loop_select(double* %A, double* %B, d
348352
; CHECK-LABEL: 'store_with_pointer_phi_outside_loop_select'
349353
; CHECK-NEXT: loop.header:
350354
; CHECK-NEXT: Report: unsafe dependent memory operations in loop.
355+
; CHECK-NEXT: Unknown data dependence.
351356
; CHECK-NEXT: Dependences:
352357
; CHECK-NEXT: Unknown:
353358
; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 ->
@@ -413,6 +418,7 @@ define void @phi_load_store_memdep_check(i1 %c, i16* %A, i16* %B, i16* %C) {
413418
; CHECK-LABEL: Loop access info in function 'phi_load_store_memdep_check':
414419
; CHECK-NEXT: for.body:
415420
; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
421+
; CHECK-NEXT: Unknown data dependence.
416422
; CHECK-NEXT: Dependences:
417423
; CHECK-NEXT: Unknown:
418424
; CHECK-NEXT: %lv3 = load i16, i16* %c.sink, align 2 ->

llvm/test/Analysis/LoopAccessAnalysis/pointer-with-unknown-bounds.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
1313
; CHECK-NEXT: for.body:
1414
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
1515
; CHECK-NOT: Report: cannot identify array bounds
16+
; CHECK-NEXT: Unknown data dependence.
1617
; CHECK-NEXT: Dependences:
1718
; CHECK-NEXT: Unknown:
1819
; CHECK-NEXT: %loadA = load i16, i16* %arrayidxA, align 2 ->

llvm/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ for.body: ; preds = %entry, %for.body
118118
; CHECK: function 'unsafe_Read_Write':
119119
; CHECK-NEXT: for.body:
120120
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
121+
; CHECK-NEXT: Backward loop carried data dependence.
121122
; CHECK-NEXT: Dependences:
122123
; CHECK-NEXT: Backward:
123124
; CHECK-NEXT: %0 = load i32, i32* %arrayidx, align 4 ->
@@ -157,6 +158,7 @@ for.body: ; preds = %entry, %for.body
157158
; CHECK: function 'unsafe_Write_Read':
158159
; CHECK-NEXT: for.body:
159160
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
161+
; CHECK-NEXT: Backward loop carried data dependence.
160162
; CHECK-NEXT: Dependences:
161163
; CHECK-NEXT: Backward:
162164
; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 ->
@@ -193,6 +195,7 @@ for.body: ; preds = %entry, %for.body
193195
; CHECK: function 'unsafe_Write_Write':
194196
; CHECK-NEXT: for.body:
195197
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
198+
; CHECK-NEXT: Backward loop carried data dependence.
196199
; CHECK-NEXT: Dependences:
197200
; CHECK-NEXT: Backward:
198201
; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 ->
@@ -346,6 +349,7 @@ for.body: ; preds = %entry, %for.body
346349
; CHECK: function 'vectorizable_unscaled_Read_Write':
347350
; CHECK-NEXT: for.body:
348351
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
352+
; CHECK-NEXT: Backward loop carried data dependence that prevents store-to-load forwarding.
349353
; CHECK-NEXT: Dependences:
350354
; CHECK-NEXT: BackwardVectorizableButPreventsForwarding:
351355
; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 ->
@@ -425,6 +429,7 @@ for.body: ; preds = %entry, %for.body
425429
; CHECK: function 'unsafe_unscaled_Read_Write':
426430
; CHECK-NEXT: for.body:
427431
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
432+
; CHECK-NEXT: Backward loop carried data dependence.
428433
; CHECK-NEXT: Dependences:
429434
; CHECK-NEXT: Backward:
430435
; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 ->
@@ -455,6 +460,7 @@ for.body: ; preds = %entry, %for.body
455460
; CHECK: function 'unsafe_unscaled_Read_Write2':
456461
; CHECK-NEXT: for.body:
457462
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
463+
; CHECK-NEXT: Backward loop carried data dependence.
458464
; CHECK-NEXT: Dependences:
459465
; CHECK-NEXT: Backward:
460466
; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 ->
@@ -505,6 +511,7 @@ for.body: ; preds = %entry, %for.body
505511
; CHECK: function 'interleaved_stores':
506512
; CHECK-NEXT: for.body:
507513
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
514+
; CHECK-NEXT: Backward loop carried data dependence.
508515
; CHECK-NEXT: Dependences:
509516
; CHECK-NEXT: Backward:
510517
; CHECK-NEXT: store i32 %4, i32* %arrayidx5, align 4 ->

llvm/test/Analysis/LoopAccessAnalysis/symbolic-stride.ll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ define void @single_stride(i32* noalias %A, i32* noalias %B, i64 %N, i64 %stride
88
; CHECK-LABEL: Loop access info in function 'single_stride':
99
; CHECK-NEXT: loop:
1010
; CHECK-NEXT: Report: unsafe dependent memory operations in loop.
11+
; CHECK-NEXT: Backward loop carried data dependence.
1112
; CHECK-NEXT: Dependences:
1213
; CHECK-NEXT: Backward:
1314
; CHECK-NEXT: %load = load i32, i32* %gep.A, align 4 ->
@@ -51,6 +52,7 @@ define void @single_stride_struct({ i32, i8 }* noalias %A, { i32, i8 }* noalias
5152
; CHECK-LABEL: Loop access info in function 'single_stride_struct':
5253
; CHECK-NEXT: loop:
5354
; CHECK-NEXT: Report: unsafe dependent memory operations in loop.
55+
; CHECK-NEXT: Backward loop carried data dependence.
5456
; CHECK-NEXT: Dependences:
5557
; CHECK-NEXT: Backward:
5658
; CHECK-NEXT: %load = load { i32, i8 }, { i32, i8 }* %gep.A, align 4 ->
@@ -97,6 +99,7 @@ define void @two_strides(i32* noalias %A, i32* noalias %B, i64 %N, i64 %stride.1
9799
; CHECK-LABEL: Loop access info in function 'two_strides':
98100
; CHECK-NEXT: loop:
99101
; CHECK-NEXT: Report: unsafe dependent memory operations in loop.
102+
; CHECK-NEXT: Backward loop carried data dependence.
100103
; CHECK-NEXT: Dependences:
101104
; CHECK-NEXT: Backward:
102105
; CHECK-NEXT: %load = load i32, i32* %gep.A, align 4 ->

llvm/test/Analysis/LoopAccessAnalysis/underlying-objects-2.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ target triple = "x86_64-apple-macosx10.10.0"
3939
; CHECK-LABEL: function 'f'
4040
; CHECK: for_j.body:
4141
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
42+
; CHECK-NEXT: Backward loop carried data dependence.
4243
; CHECK-NEXT: Dependences:
4344
; CHECK-NEXT: Backward:
4445
; CHECK-NEXT: %loadB = load i8, i8* %gepB, align 1 ->

llvm/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
88
target triple = "x86_64-apple-macosx10.10.0"
99

1010
; CHECK: Report: unsafe dependent memory operations in loop
11+
; CHECK-NEXT: Backward loop carried data dependence.
1112
; CHECK-NEXT: Dependences:
1213
; CHECK-NEXT: Backward:
1314
; CHECK-NEXT: %loadA = load i16, i16* %arrayidxA, align 2 ->

llvm/test/Transforms/LoopVectorize/diag-with-hotness-info-2.ll

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@
2222
; 19 }
2323
; 20 }
2424

25-
; CHECK: remark: /tmp/s.c:2:3: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop (hotness: 300)
26-
; CHECK: remark: /tmp/s.c:9:3: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop (hotness: 5000)
27-
; CHECK: remark: /tmp/s.c:16:3: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop{{$}}
25+
; CHECK: remark: /tmp/s.c:3:14: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
26+
; CHECK-NEXT: Backward loop carried data dependence. Memory location is the same as accessed at /tmp/s.c:3:16 (hotness: 300)
27+
; CHECK: remark: /tmp/s.c:10:14: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
28+
; CHECK-NEXT: Backward loop carried data dependence. Memory location is the same as accessed at /tmp/s.c:10:16 (hotness: 5000)
29+
; CHECK: remark: /tmp/s.c:17:14: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
30+
; CHECK-NEXT: Backward loop carried data dependence. Memory location is the same as accessed at /tmp/s.c:17:16{{$}}
2831

2932
; ModuleID = '/tmp/s.c'
3033
source_filename = "/tmp/s.c"

0 commit comments

Comments
 (0)