// read and write of A[i]), LAA will locally deem the dependence "safe"
// without querying the MemoryDepChecker. Therefore we can miss
// enumerating loop-independent forward dependences in
- // getInterestingDependences. Note that as soon as there are different
+ // getDependences. Note that as soon as there are different
// indices used to access the same array, the MemoryDepChecker *is*
// queried and the dependence list is complete.
Forward,
/// \brief Dependence types that don't prevent vectorization.
static bool isSafeForVectorization(DepType Type);
- /// \brief Dependence types that can be queried from the analysis.
- static bool isInterestingDependence(DepType Type);
-
/// \brief Lexically backward dependence types.
bool isPossiblyBackward() const;
SCEVUnionPredicate &Preds)
: SE(Se), InnermostLoop(L), AccessIdx(0),
ShouldRetryWithRuntimeCheck(false), SafeForVectorization(true),
- RecordInterestingDependences(true), Preds(Preds) {}
+ RecordDependences(true), Preds(Preds) {}
/// \brief Register the location (instructions are given increasing numbers)
/// of a write access.
/// vectorize the loop with a dynamic array access check.
bool shouldRetryWithRuntimeCheck() { return ShouldRetryWithRuntimeCheck; }
- /// \brief Returns the interesting dependences. If null is returned we
- /// exceeded the MaxInterestingDependence threshold and this information is
- /// not available.
- const SmallVectorImpl<Dependence> *getInterestingDependences() const {
- return RecordInterestingDependences ? &InterestingDependences : nullptr;
+ /// \brief Returns the memory dependences. If null is returned we exceeded
+ /// the MaxDependences threshold and this information is not
+ /// available.
+ const SmallVectorImpl<Dependence> *getDependences() const {
+ return RecordDependences ? &Dependences : nullptr;
}
- void clearInterestingDependences() { InterestingDependences.clear(); }
+ void clearDependences() { Dependences.clear(); }
/// \brief The vector of memory access instructions. The indices are used as
/// instruction identifiers in the Dependence class.
/// vectorization.
bool SafeForVectorization;
- //// \brief True if InterestingDependences reflects the dependences in the
- //// loop. If false we exceeded MaxInterestingDependence and
- //// InterestingDependences is invalid.
- bool RecordInterestingDependences;
+ //// \brief True if Dependences reflects the dependences in the
+ //// loop. If false we exceeded MaxDependences and
+ //// Dependences is invalid.
+ bool RecordDependences;
- /// \brief Interesting memory dependences collected during the analysis as
- /// defined by isInterestingDependence. Only valid if
- /// RecordInterestingDependences is true.
- SmallVector<Dependence, 8> InterestingDependences;
+ /// \brief Memory dependences collected during the analysis. Only valid if
+ /// RecordDependences is true.
+ SmallVector<Dependence, 8> Dependences;
/// \brief Check whether there is a plausible dependence between the two
/// accesses.
/// Maximum SIMD width.
const unsigned VectorizerParams::MaxVectorWidth = 64;
-/// \brief We collect interesting dependences up to this threshold.
-static cl::opt<unsigned> MaxInterestingDependence(
- "max-interesting-dependences", cl::Hidden,
- cl::desc("Maximum number of interesting dependences collected by "
- "loop-access analysis (default = 100)"),
- cl::init(100));
+/// \brief We collect dependences up to this threshold.
+static cl::opt<unsigned>
+ MaxDependences("max-dependences", cl::Hidden,
+ cl::desc("Maximum number of dependences collected by "
+ "loop-access analysis (default = 100)"),
+ cl::init(100));
bool VectorizerParams::isInterleaveForced() {
return ::VectorizationInterleave.getNumOccurrences() > 0;
/// We decided that no dependence analysis would be used. Reset the state.
void resetDepChecks(MemoryDepChecker &DepChecker) {
CheckDeps.clear();
- DepChecker.clearInterestingDependences();
+ DepChecker.clearDependences();
}
MemAccessInfoSet &getDependenciesToCheck() { return CheckDeps; }
llvm_unreachable("unexpected DepType!");
}
-bool MemoryDepChecker::Dependence::isInterestingDependence(DepType Type) {
- return Type != NoDep;
-}
-
bool MemoryDepChecker::Dependence::isPossiblyBackward() const {
switch (Type) {
case NoDep:
isDependent(*A.first, A.second, *B.first, B.second, Strides);
SafeForVectorization &= Dependence::isSafeForVectorization(Type);
- // Gather dependences unless we accumulated MaxInterestingDependence
+ // Gather dependences unless we accumulated MaxDependences
// dependences. In that case return as soon as we find the first
// unsafe dependence. This puts a limit on this quadratic
// algorithm.
- if (RecordInterestingDependences) {
- if (Dependence::isInterestingDependence(Type))
- InterestingDependences.push_back(
- Dependence(A.second, B.second, Type));
-
- if (InterestingDependences.size() >= MaxInterestingDependence) {
- RecordInterestingDependences = false;
- InterestingDependences.clear();
+ if (RecordDependences) {
+ if (Type != Dependence::NoDep)
+ Dependences.push_back(Dependence(A.second, B.second, Type));
+
+ if (Dependences.size() >= MaxDependences) {
+ RecordDependences = false;
+ Dependences.clear();
DEBUG(dbgs() << "Too many dependences, stopped recording\n");
}
}
- if (!RecordInterestingDependences && !SafeForVectorization)
+ if (!RecordDependences && !SafeForVectorization)
return false;
}
++OI;
}
}
- DEBUG(dbgs() << "Total Interesting Dependences: "
- << InterestingDependences.size() << "\n");
+ DEBUG(dbgs() << "Total Dependences: " << Dependences.size() << "\n");
return SafeForVectorization;
}
if (Report)
OS.indent(Depth) << "Report: " << Report->str() << "\n";
- if (auto *InterestingDependences = DepChecker.getInterestingDependences()) {
- OS.indent(Depth) << "Interesting Dependences:\n";
- for (auto &Dep : *InterestingDependences) {
+ if (auto *Dependences = DepChecker.getDependences()) {
+ OS.indent(Depth) << "Dependences:\n";
+ for (auto &Dep : *Dependences) {
Dep.print(OS, Depth + 2, DepChecker.getMemoryInstructions());
OS << "\n";
}
} else
- OS.indent(Depth) << "Too many interesting dependences, not recorded\n";
+ OS.indent(Depth) << "Too many dependences, not recorded\n";
// List the pair of accesses need run-time checks to prove independence.
PtrRtChecking.print(OS, Depth);
MemoryInstructionDependences(
const SmallVectorImpl<Instruction *> &Instructions,
- const SmallVectorImpl<Dependence> &InterestingDependences) {
+ const SmallVectorImpl<Dependence> &Dependences) {
Accesses.append(Instructions.begin(), Instructions.end());
DEBUG(dbgs() << "Backward dependences:\n");
- for (auto &Dep : InterestingDependences)
+ for (auto &Dep : Dependences)
if (Dep.isPossiblyBackward()) {
// Note that the designations source and destination follow the program
// order, i.e. source is always first. (The direction is given by the
DEBUG(dbgs() << "Skipping; memory operations are safe for vectorization");
return false;
}
- auto *InterestingDependences =
- LAI.getDepChecker().getInterestingDependences();
- if (!InterestingDependences || InterestingDependences->empty()) {
+ auto *Dependences = LAI.getDepChecker().getDependences();
+ if (!Dependences || Dependences->empty()) {
DEBUG(dbgs() << "Skipping; No unsafe dependences to isolate");
return false;
}
// NumUnsafeDependencesActive reaches 0.
const MemoryDepChecker &DepChecker = LAI.getDepChecker();
MemoryInstructionDependences MID(DepChecker.getMemoryInstructions(),
- *InterestingDependences);
+ *Dependences);
int NumUnsafeDependencesActive = 0;
for (auto &InstDep : MID) {
define void @f(i32* %A, i32* %B, i32* %C, i64 %N) {
-; CHECK: Interesting Dependences:
+; CHECK: Dependences:
; CHECK-NEXT: Forward:
; CHECK-NEXT: store i32 %a_p1, i32* %Aidx_ahead, align 4 ->
; CHECK-NEXT: %a = load i32, i32* %Aidx, align 4
define void @f(i32* noalias %A, i32* noalias %B, i32* noalias %C, i64 %N) {
-; CHECK: Interesting Dependences:
+; CHECK: Dependences:
; CHECK-NEXT: Forward:
; CHECK-NEXT: store i32 %b_p1, i32* %Aidx, align 4 ->
; CHECK-NEXT: %a = load i32, i32* %Aidx, align 4
; CHECK: for.body:
; CHECK: Report: unsafe dependent memory operations in loop
; CHECK-NOT: Report: cannot identify array bounds
-; CHECK: Interesting Dependences:
+; CHECK: Dependences:
; CHECK: Unknown:
; CHECK: %loadA = load i16, i16* %arrayidxA, align 2 ->
; CHECK: store i16 %mul, i16* %arrayidxA, align 2
; We give up analyzing the dependences in this loop due to non-constant
; distance between A[i+offset] and A[i] and add memchecks to prove
-; independence. Make sure that no interesting dependences are reported in
+; independence. Make sure that no dependences are reported in
; this case.
;
; for (i = 0; i < n; i++)
target triple = "x86_64-apple-macosx10.10.0"
; CHECK: Memory dependences are safe with run-time checks
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: 0:
; CHECK-NEXT: Comparing group
; store of A[i];
; CHECK: Memory dependences are safe{{$}}
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Forward:
; CHECK-NEXT: %loadA_plus_2 = load i16, i16* %arrayidxA_plus_2, align 2 ->
; CHECK-NEXT: store i16 %mul1, i16* %arrayidxA, align 2
; CHECK: function 'nodep_Read_Write':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Memory dependences are safe
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Run-time memory checks:
define void @nodep_Read_Write(i32* nocapture %A) {
; CHECK: function 'nodep_Write_Read':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Memory dependences are safe
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Run-time memory checks:
define i32 @nodep_Write_Read(i32* nocapture %A) {
; CHECK: function 'nodep_Write_Write':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Memory dependences are safe
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Run-time memory checks:
define void @nodep_Write_Write(i32* nocapture %A) {
; CHECK: function 'unsafe_Read_Write':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: %0 = load i32, i32* %arrayidx, align 4 ->
; CHECK-NEXT: store i32 %add, i32* %arrayidx3, align 4
; CHECK: function 'unsafe_Write_Read':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 ->
; CHECK-NEXT: %1 = load i32, i32* %arrayidx2, align 4
; CHECK: function 'unsafe_Write_Write':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 ->
; CHECK-NEXT: store i32 %2, i32* %arrayidx3, align 4
; CHECK: function 'vectorizable_Read_Write':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Memory dependences are safe
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: BackwardVectorizable:
; CHECK-NEXT: %0 = load i32, i32* %arrayidx, align 4 ->
; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4
; CHECK: function 'vectorizable_Write_Read':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Memory dependences are safe
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: BackwardVectorizable:
; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 ->
; CHECK-NEXT: %1 = load i32, i32* %arrayidx2, align 4
; CHECK: function 'vectorizable_Write_Write':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Memory dependences are safe
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: BackwardVectorizable:
; CHECK-NEXT: store i32 %0, i32* %arrayidx, align 4 ->
; CHECK-NEXT: store i32 %2, i32* %arrayidx2, align 4
; CHECK: function 'vectorizable_unscaled_Read_Write':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: BackwardVectorizableButPreventsForwarding:
; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 ->
; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4
; CHECK: for function 'vectorizable_unscaled_Write_Read':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Memory dependences are safe
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: BackwardVectorizable:
; CHECK-NEXT: store i32 %2, i32* %arrayidx, align 4 ->
; CHECK-NEXT: %3 = load i32, i32* %arrayidx2, align 4
; CHECK: function 'unsafe_unscaled_Read_Write':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 ->
; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4
; CHECK: function 'unsafe_unscaled_Read_Write2':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: %2 = load i32, i32* %arrayidx, align 4 ->
; CHECK-NEXT: store i32 %add, i32* %arrayidx2, align 4
; CHECK: function 'interleaved_stores':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: store i32 %4, i32* %arrayidx5, align 4 ->
; CHECK-NEXT: store i32 %4, i32* %arrayidx9, align 4
; CHECK: for_j.body:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: %loadB = load i8, i8* %gepB, align 1 ->
; CHECK-NEXT: store i8 2, i8* %gepB_plus_one, align 1
target triple = "x86_64-apple-macosx10.10.0"
; CHECK: Report: unsafe dependent memory operations in loop
-; CHECK-NEXT: Interesting Dependences:
+; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: %loadA = load i16, i16* %arrayidxA, align 2 ->
; CHECK-NEXT: store i16 %mul1, i16* %arrayidxA_plus_2, align 2