[PATCH] D36963: Use sorting instead of a lot of stable_partitions for `ICF::segregate` function
Alex Telishev via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 23 01:02:37 PDT 2017
alex.telishev added inline comments.
================
Comment at: lld/COFF/ICF.cpp:214
+
+ return B1 < B2;
};
----------------
ruiu wrote:
> alex.telishev wrote:
> > alex.telishev wrote:
> > > ruiu wrote:
> > > > I think this comparison breaks determinism because it compares pointer values that change on every process invocation. You may be able to just return `false`?
> > > Unfortunately, no - that would break strict ordering (`A < B == false` and `B < A == false`, like NaN) and `stable_sort` will break in this case. It's possible to `return true` and make them all be equal to each other for the purposes of sorting. But in this case loop after `stable_sort` in `segregate` function needs to use different comparison. It's possible to use `equalsConstant` from before this patch (as we only need equality there), but it'll be a lot of copy-paste.
> > Sorry, it's exact opposite to what I said, `stable_sort` will break if `return true` is used, and on `return false;` everything works, but we need to change comparison in `segregate`.
> I'm not sure if I understand your point correctly. If a comparison function returns false for both (A, B) and (B, A), then it means that A == B, and std::stable_sort sort them accordingly (i.e. do not alter relative order of A and B), no?
>
> On the other hand, I believe returning true for both (A, B) and (B, A) breaks strict weak ordering, as A<B && B<A cannot be true.
Yes, you're right. But comparison after that still needs to be changed. Are you ok with using old version that do only equality comparison for this case?
================
Comment at: lld/COFF/ICF.cpp:247
+
+ return lexicographicalCompareRelocs(A, B, Less);
+}
----------------
ruiu wrote:
> It looks like this `lexicographicalCompareRelocs` function doesn't help code readability that much. You might want to just do things in-place instead of passing a callback function to another function. I'd do something like this:
>
> for (size_t I = 0; I != A->NumRelocs; ++I) {
> const coff_relocation *R1 = A->Relocs.begin() + I;
> const coff_relocation *R2 = B->Relocs.begin() + I;
>
> if (R1.Type != R2.Type)
> return R1.Type < R2.Type;
> if (R1.VirtualAddress != R2.VirtualAddress)
> return R1.VirtualAddress < R2.VirtualAddress;
>
> SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex);
> SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex);
> if (B1 == B2)
> continue;
>
> auto *D1 = dyn_cast<DefinedRegular>(B1);
> auto *D2 = dyn_cast<DefinedRegular>(B2);
> if (!D1 || D2)
> continue;
> if (D1->getValue() != D2->getValue())
> return D1->getValue() < D2->getValue();
>
> uint32_t C1 = D1->getChunk()->Class[Cnt % 2];
> uint32_t C2 = D2->getChunk()->Class[Cnt % 2];
> if (C1 != C2)
> return C1 < C2;
> }
> return false;
>
> Note that when the control reaches this loop, A->NumReloc == B->NumReloc is guaranteed because we do have a check for that at the beginning of this function.
Agreed, that way it even will be faster, because no need to call comparison function twice.
================
Comment at: lld/COFF/ICF.cpp:112
+ for (size_t Pos = Begin + 1; Pos < End; Pos++) {
+ if (Equal(Chunks[GroupBegin], Chunks[Pos]))
+ continue;
----------------
ruiu wrote:
> I believe you can use Less instead of Equal and remove equals{Constant,Variables} functions. What am I missing?
We changed `Less{Constant,Variables}` functions so now every non-`DefinedRegular` relocations are equal to each other. As the result they will all receive the same Class if we use `Less` function in the loop.
https://reviews.llvm.org/D36963
More information about the llvm-commits
mailing list