Don't rely on the DepCands iteration order when constructing checking pointer groups

Summary:
The checking pointer group construction algorithm relied on the iteration on DepCands.
We would need the same leaders across runs and the same iteration order over the underlying std::set for determinism.

This changes the algorithm to process the pointers in the order in which they were added to the runtime check, which is deterministic.
We need to update the tests, since the order in which pointers appear has changed.

No new tests were added, since it is impossible to test for non-determinism.

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D11064

llvm-svn: 241809
This commit is contained in:
Silviu Baranga 2015-07-09 15:18:25 +00:00
parent b870e9ca93
commit ce3877fc8c
3 changed files with 59 additions and 37 deletions

View File

@ -222,18 +222,40 @@ void LoopAccessInfo::RuntimePointerCheck::groupChecks(
for (unsigned Pointer = 0; Pointer < Pointers.size(); ++Pointer) for (unsigned Pointer = 0; Pointer < Pointers.size(); ++Pointer)
PositionMap[Pointers[Pointer]] = Pointer; PositionMap[Pointers[Pointer]] = Pointer;
// We need to keep track of what pointers we've already seen so we
// don't process them twice.
SmallSet<unsigned, 2> Seen;
// Go through all equivalence classes, get the the "pointer check groups" // Go through all equivalence classes, get the the "pointer check groups"
// and add them to the overall solution. // and add them to the overall solution. We use the order in which accesses
for (auto DI = DepCands.begin(), DE = DepCands.end(); DI != DE; ++DI) { // appear in 'Pointers' to enforce determinism.
if (!DI->isLeader()) for (unsigned I = 0; I < Pointers.size(); ++I) {
// We've seen this pointer before, and therefore already processed
// its equivalence class.
if (Seen.count(I))
continue; continue;
SmallVector<CheckingPtrGroup, 2> Groups; MemoryDepChecker::MemAccessInfo Access(Pointers[I], IsWritePtr[I]);
for (auto MI = DepCands.member_begin(DI), ME = DepCands.member_end(); SmallVector<CheckingPtrGroup, 2> Groups;
auto LeaderI = DepCands.findValue(DepCands.getLeaderValue(Access));
SmallVector<unsigned, 2> MemberIndices;
// Get all indeces of the members of this equivalence class and sort them.
// This will allow us to process all accesses in the order in which they
// were added to the RuntimePointerCheck.
for (auto MI = DepCands.member_begin(LeaderI), ME = DepCands.member_end();
MI != ME; ++MI) { MI != ME; ++MI) {
unsigned Pointer = PositionMap[MI->getPointer()]; unsigned Pointer = PositionMap[MI->getPointer()];
MemberIndices.push_back(Pointer);
}
std::sort(MemberIndices.begin(), MemberIndices.end());
for (unsigned Pointer : MemberIndices) {
bool Merged = false; bool Merged = false;
// Mark this pointer as seen.
Seen.insert(Pointer);
// Go through all the existing sets and see if we can find one // Go through all the existing sets and see if we can find one
// which can include this pointer. // which can include this pointer.

View File

@ -82,29 +82,29 @@ for.end: ; preds = %for.body
; CHECK: Run-time memory checks: ; CHECK: Run-time memory checks:
; CHECK-NEXT: Check 0: ; CHECK-NEXT: Check 0:
; CHECK-NEXT: Comparing group 0: ; CHECK-NEXT: Comparing group 0:
; CHECK-NEXT: %arrayidxA1 = getelementptr inbounds i16, i16* %a, i64 %add ; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
; CHECK-NEXT: Against group 1:
; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind ; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind
; CHECK-NEXT: Against group 2: ; CHECK-NEXT: %arrayidxA1 = getelementptr inbounds i16, i16* %a, i64 %add
; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
; CHECK-NEXT: Check 1: ; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group 1: ; CHECK-NEXT: Comparing group 0:
; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind
; CHECK-NEXT: Against group 2:
; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind ; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
; CHECK-NEXT: Against group 2:
; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind
; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group 0: ; CHECK-NEXT: Group 0:
; CHECK-NEXT: (Low: %a High: (40 + %a)) ; CHECK-NEXT: (Low: %c High: (78 + %c))
; CHECK-NEXT: Member: {(2 + %a),+,2} ; CHECK-NEXT: Member: {%c,+,4}
; CHECK-NEXT: Member: {%a,+,2} ; CHECK-NEXT: Member: {(2 + %c),+,4}
; CHECK-NEXT: Group 1: ; CHECK-NEXT: Group 1:
; CHECK-NEXT: (Low: %a High: (40 + %a))
; CHECK-NEXT: Member: {%a,+,2}
; CHECK-NEXT: Member: {(2 + %a),+,2}
; CHECK-NEXT: Group 2:
; CHECK-NEXT: (Low: %b High: (38 + %b)) ; CHECK-NEXT: (Low: %b High: (38 + %b))
; CHECK-NEXT: Member: {%b,+,2} ; CHECK-NEXT: Member: {%b,+,2}
; CHECK-NEXT: Group 2:
; CHECK-NEXT: (Low: %c High: (78 + %c))
; CHECK-NEXT: Member: {(2 + %c),+,4}
; CHECK-NEXT: Member: {%c,+,4}
define void @testg(i16* %a, define void @testg(i16* %a,
i16* %b, i16* %b,
@ -154,29 +154,29 @@ for.end: ; preds = %for.body
; CHECK: Run-time memory checks: ; CHECK: Run-time memory checks:
; CHECK-NEXT: Check 0: ; CHECK-NEXT: Check 0:
; CHECK-NEXT: Comparing group 0: ; CHECK-NEXT: Comparing group 0:
; CHECK-NEXT: %arrayidxA1 = getelementptr i16, i16* %a, i64 %add ; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
; CHECK-NEXT: Against group 1:
; CHECK-NEXT: %arrayidxA = getelementptr i16, i16* %a, i64 %ind ; CHECK-NEXT: %arrayidxA = getelementptr i16, i16* %a, i64 %ind
; CHECK-NEXT: Against group 2: ; CHECK-NEXT: %arrayidxA1 = getelementptr i16, i16* %a, i64 %add
; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
; CHECK-NEXT: Check 1: ; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group 1: ; CHECK-NEXT: Comparing group 0:
; CHECK-NEXT: %arrayidxB = getelementptr i16, i16* %b, i64 %ind
; CHECK-NEXT: Against group 2:
; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind ; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %store_ind
; CHECK-NEXT: %arrayidxC1 = getelementptr inbounds i16, i16* %c, i64 %store_ind_inc
; CHECK-NEXT: Against group 2:
; CHECK-NEXT: %arrayidxB = getelementptr i16, i16* %b, i64 %ind
; CHECK-NEXT: Grouped accesses: ; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group 0: ; CHECK-NEXT: Group 0:
; CHECK-NEXT: (Low: %a High: (40 + %a)) ; CHECK-NEXT: (Low: %c High: (78 + %c))
; CHECK-NEXT: Member: {(2 + %a),+,2} ; CHECK-NEXT: Member: {%c,+,4}
; CHECK-NEXT: Member: {%a,+,2} ; CHECK-NEXT: Member: {(2 + %c),+,4}
; CHECK-NEXT: Group 1: ; CHECK-NEXT: Group 1:
; CHECK-NEXT: (Low: %a High: (40 + %a))
; CHECK-NEXT: Member: {%a,+,2}
; CHECK-NEXT: Member: {(2 + %a),+,2}
; CHECK-NEXT: Group 2:
; CHECK-NEXT: (Low: %b High: (38 + %b)) ; CHECK-NEXT: (Low: %b High: (38 + %b))
; CHECK-NEXT: Member: {%b,+,2} ; CHECK-NEXT: Member: {%b,+,2}
; CHECK-NEXT: Group 2:
; CHECK-NEXT: (Low: %c High: (78 + %c))
; CHECK-NEXT: Member: {(2 + %c),+,4}
; CHECK-NEXT: Member: {%c,+,4}
define void @testh(i16* %a, define void @testh(i16* %a,
i16* %b, i16* %b,

View File

@ -15,14 +15,14 @@ target triple = "x86_64-apple-macosx10.10.0"
; CHECK: Run-time memory checks: ; CHECK: Run-time memory checks:
; CHECK-NEXT: 0: ; CHECK-NEXT: 0:
; CHECK-NEXT: Comparing group ; CHECK-NEXT: Comparing group
; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %storemerge3
; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add ; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add
; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %storemerge3
; CHECK-NEXT: Against group ; CHECK-NEXT: Against group
; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %storemerge3 ; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %storemerge3
; CHECK-NEXT: 1: ; CHECK-NEXT: 1:
; CHECK-NEXT: Comparing group ; CHECK-NEXT: Comparing group
; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %storemerge3
; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add ; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, i16* %a, i64 %add
; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %storemerge3
; CHECK-NEXT: Against group ; CHECK-NEXT: Against group
; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %storemerge3 ; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %storemerge3