[LLVMdev] MergeFunctions: reduce complexity to O(log(N))
Stepan Dyatkovskiy
stpworld at narod.ru
Fri May 16 07:17:05 PDT 2014
Hi Nick,
Thanks for reviews!
I have committed 0003 - 0005 as 208953, 208973 and 208976.
> + // TODO: Already checked in cmpOps
Yup. I have fixed it with "Already checked in cmpOperation".
The reason I put this TODO, is because we don't need this check,
operation types were already checked in cmpOperation. But I didn't
remove this code, because its not mine (it was in old code as well), and
actually it is subject of additional cosmetic commit.
Thanks!
-Stepan
Nick Lewycky wrote:
> 0003:
>
> + // Mostly cloned from BitcodeWriter, but simplified a bit.
>
> Please remove that comment, it isn't adding anything for the reader.
>
> And submit.
>
> 0004:
>
> I *really* like the comment block!! This is going to save developers so
> much time!
>
> No changes, please submit!
>
> 0005:
>
> Perfect. Please submit.
>
> 0006:
>
> + // TODO: Already checked in cmpOps
>
> cmpOps?
>
> Nick
>
> On 15 May 2014 06:32, Stepan Dyatkovskiy <stpworld at narod.ru
> <mailto:stpworld at narod.ru>> wrote:
>
> Hi Nick,
> What about rest of patches? I have fixed 0004 and 0005, others seems
> to be OK for you.. Can I commit them?
>
> Thanks!
> -Stepan
>
> Stepan Dyatkovskiy wrote:
>
> Hi Nick,
> Thanks you for reviews. I have corrected for of comments from FAQ to
> what seems to be regular in LLVM.
> Patches has been committed as r208173 and r208189.
>
> Thanks!
> -Stepan
>
> Nick Lewycky wrote:
>
> On 29 April 2014 04:36, Stepan Dyatkovskiy
> <stpworld at narod.ru <mailto:stpworld at narod.ru>
> <mailto:stpworld at narod.ru <mailto:stpworld at narod.ru>>> wrote:
>
> Hi Nick.
>
> I have fixed and reattached all the patches from 0001
> till 0011.
>
> 0001, 0002:
> I have added detailed order descriptions to the methods
> declaration.
> I have also fixed everything as you asked.
>
>
> 0001:
>
> + for (uint64_t i = 0; i < NumElementsL; ++i) {
> vs.
> + for (unsigned i = 0, e = NumElementsL; i != e; ++i) {
>
> This difference is necessary to avoid a warning? I don't
> actually care
> which form you use here given that NumElementsL is already
> an integer
> there's no recalculation we're avoiding like getting the end
> iterator
> each time, I just want it to look consistent. If it's
> working around a
> warning that's more important than consistent looks.
>
> 0001 looks good. Please commit it.
>
> 0002:
>
> One note, you use a writing style of asking a question,
> followed by
> answering it. For instance, "Will we still get the same
> numbering? As
> follows from FunctionComparator::compare(), we do CFG walk,
> ...". I
> don't think it's worth your time to rewrite it now, but we
> generally
> don't use that construction in llvm's comments, instead
> preferring to
> explain what the code does an including an argument that
> explains why
> the approach is correct. This amounts to the same thing,
> it's just a
> different style.
>
> + /// their functions. If right value was meet
> first during
> scanning,
>
> "was meet" --> "was met"
>
> Please commit it.
>
> Nick
>
>
> 0003, cmpStrings
> StringRef::compare performs lexicographical comparison,
> and it isn't
> the fastest one.
> In case, when strings has different length, it still
> compares their
> prefixes lexicographically.
> We need ordering among strings set, but we don't need
> to compare
> strings contents lexicographically all the time. So we
> can compare
> their sizes first, and do lexicographical comparison
> only when we
> really need it: only when strings are equal in size.
>
> I have added short version of these explanations into
> cmpStrings. So
> we could get really well documented methods based on
> our posts ;-)
> Those were good questions and definitely the answers
> should be in
> documentation somewhere.
>
> 0004: I have added ordering description.
> 0005: Fixed.
> 0007: Fixed.
> 0009:
>
> > Okay, I'm confused. We do all this work to produce a
> 3-way
> comparison,
> > then we wrap it up in an operator< for a std::set
> that will only
> look at
> > less-than...
> Actually, on top level we don't need 3-way comparison.
> But we do
> need it to determine whether functions are equal on
> some stage, just
> to proceed to the next "less significant" stage.
> Consider two functions (where BB1 and BB11 are equal)
>
> "F1: {BB1, BB2}" and
> "F2: {BB11, BB3}".
>
> First we have to realize that BB1 and BB11 are equal.
> And then
> determine which one of BB2 and BB3 is less than another.
> So finally we got 3-way comparison: less, equal and
> greater (in fact
> just neither less nor equal).
>
>
> > When we start detecting equal functions, do we
> merge them
> immediately? If so, can't that cause functions already
> in the set to
> have their equality comparisons change
> Yes we merge them immediately. And no, it won't cause
> situation you
> have mentioned. Once we changed function X, we lookup
> for functions
> that uses X, remove them from FnTree (former FnSet) and
> put them
> into Deferred list. Then we fill up worklist with
> Deferred contents
> and repeat comparison routine for these functions.
>
>
> Thanks for reviews!
>
> -Stepan
>
> Stepan Dyatkovskiy wrote:
>
> ping
> Stepan Dyatkovskiy wrote:
>
> Hi Nick,
> Thank you for reviews! Here is my answers for
> first two
> patches.
>
> Though as additional, I think its important
> answer to this
> question
> first:
> > Okay, I'm confused. We do all this work to
> produce a
> 3-way comparison,
> > then we wrap it up in an operator< for a
> std::set that
> will only
> look at
> > less-than...
> Actually, on top level we don't need 3-way
> comparison. But
> we do need it
> to determine whether functions are equal on
> some stage just
> to proceed
> to the next "less meaningful" stage.
> Consider two functions
> "F1: {BB1, BB2}" and
> "F2: {BB-equal-to-BB1, BB3}".
> First we have to realize that BB1 and
> BB-equal-to-BB1 are
> equal. And
> then determine which one of BB2 and BB3 is less.
>
> First patch.
>
> > + /// 1. Bitcastability.
> > + /// Check whether L's type could be
> losslessly
> bitcasted to R's
> type.
> > + /// On this stage method, in case when
> lossless
> bitcast is not
> possible
> > + /// method returns -1 or 1, thus also
> defining which
> type is
> greater in
> > + /// context of bitcastability.
> I have added detailed order description for
> this method. You
> also can
> find this description in cmpConstantsComment.txt.
>
> > Optional: "Return its pointers comparison
> result" ->
> "Return the
> result
> > of comparing the types"?
> Oops! Fixed.
>
> > + if (TyL->getTypeID() == Type::X86_MMXTyID)
> > + TyLWidth = 64;
> > + else if (const VectorType *VecTyL =
> dyn_cast<VectorType>(TyL))
> > + TyLWidth = VecTyL->getBitWidth();
> >
> > Yikes! We never merge function A using a
> vector and
> function B
> using an
> > x86_mmx type together, right?
> Fixed!
>
> > "Nor of TyL and TyR" -> "Neither Tyl nor TyR".
> >
> > Optional: "Return its pointers comparison
> result" ->
> "Return the
> result
> > of comparing the types"?
> Fixed.
>
> > + case Value::UndefValueVal: return
> cmpType(L->getType(),
> R->getType());
> >
> > You already have L->getType() and
> R->getType() in TyL
> and TyR.
> Fixed. Sorry.
>
> Second patch.
>
> > I'm curious whether we guarantee that
> > we get the same numbering when comparing
> two functions
> if I simply
> > reorder the BasicBlocks in one of the
> functions, will we
> still assign
> > the same numberings or not?
> ...
> > Why not just start at the beginning and run to
> > the end, relying on the SSA dominance property.
> Good questions!
>
> For first one I have added these notes:
> [quote]
> As follows from FunctionComparator::compare(),
> we do CFG
> walk, we start
> from entry, and then take each terminator. So
> it doesn't
> matter how in
> fact BBs are ordered in function. And since
> cmpValues are
> called during
> this walk, the numbering depends only on how
> BBs located
> inside the CFG.
> [/quote]
>
> As for second question, I have added next notes:
>
> [quote]
> We also can't use dominance properties.
> Consider situation:
> If we compare two instruction operands: first
> is usage of
> local variable
> AL from function FL, and second is usage of
> local variable
> AR from FR.
> We are still not able to compare operands of
> PHI, since
> those could be
> operands from further BBs we didn't scan yet.
> [/quote]
>
> You can find comments also in sn_mapLRComment.txt
> I have also described lexicographical ordering
> for cmpValues
> in method
> comments. I have also put them in separated txt
> file:
> cmpValuesComment.txt.
>
> > + if (L == R) return 0;
> > + // Compare C1 and the bitcast result.
> > + if (int Res = cmpConstants(ConstL,
> ConstR))
> > + return Res;
> > [...]
> > + return 0;
> >
> > Isn't that just:
> > return cmpConstants(ConstL, ConstR);
> OOOPS! Fixed.
>
> I'm working on rest of patches.
> Thanks!
>
> -Stepan.
>
> Nick Lewycky wrote:
>
> Stepan Dyatkovskiy wrote:
>
> Hello Nick!
>
> Can we proceed to work on patch series?
>
>
> Just in case, I have reattached them to
> this post.
> Would you prefer to see them in
> http://reviews.llvm.org ?
>
>
> Oddly, I prefer attachments, but we can use
> reviews.llvm.org <http://reviews.llvm.org>
> <http://reviews.llvm.org> if you
> prefer?
>
> 0001-constants-comparison.____patch
>
> + /// 1. Bitcastability.
> + /// Check whether L's type could be
> losslessly
> bitcasted to R's type.
> + /// On this stage method, in case when
> lossless
> bitcast is not
> possible
> + /// method returns -1 or 1, thus also
> defining which
> type is
> greater in
> + /// context of bitcastability.
>
> Looking at the code, it looks like the
> order is:
> 1. first class types, by typeid
> 2. vectors (by element size? by number
> of elements?
> the two
> multiplied together?)
>
> + // Nor of TyL and TyR are values of
> first class
> type. Return
> + // its pointers comparison result.
>
> "Nor of TyL and TyR" -> "Neither Tyl nor TyR".
>
> Optional: "Return its pointers comparison
> result" ->
> "Return the result
> of comparing the types"?
>
> + if (TyL->getTypeID() == Type::X86_MMXTyID)
> + TyLWidth = 64;
> + else if (const VectorType *VecTyL =
> dyn_cast<VectorType>(TyL))
> + TyLWidth = VecTyL->getBitWidth();
>
> Yikes! We never merge function A using a
> vector and
> function B using an
> x86_mmx type together, right? Note what the
> LangRef says
> about x86_mmx:
> "The operations allowed on it are quite
> limited:
> parameters and return
> values, load and store, and bitcast."
>
> + case Value::UndefValueVal: return
> cmpType(L->getType(),
> R->getType());
>
> You already have L->getType() and
> R->getType() in TyL
> and TyR. You also
> already have cmpType(TyL, TyR) in TypesRes.
> Please just
> reuse them in
> the rest of this function.
>
>
> 0002-values-comparison-____replacement-for-enumerate.____patch
>
> + // Assign serial numbers to values from left
> function, and values
> from
> + // right function.
> + // Explanation:
> + // Being comparing functions we need to
> compare
> values we meet at
> left and
> + // right sides.
> + // Its easy to sort things out for
> external values.
> It just should be
> + // the same value at left and right.
> + // But for local values (those were
> introduced inside
> function body)
> + // we have to ensure they were
> introduced at exactly
> the same place,
> + // and plays the same role. How to do it?
> + // Just assign serial number to each
> value when we
> meet it first
> time.
> + // Values that were met at same place
> will be with
> same serial
> numbers.
>
> This explanation is correct, but I'm
> curious whether we
> guarantee that
> we get the same numbering when comparing
> two functions
> if I simply
> reorder the BasicBlocks in one of the
> functions, will we
> still assign
> the same numberings or not?
>
> Also, it's not clear from the comment why
> we need the
> complexity of
> numbering them anyways. Why not just start
> at the
> beginning and run to
> the end, relying on the SSA dominance
> property to
> guarantee that we
> visit definitions before uses, and assume
> we'll visit
> each value in the
> same order (look at each instruction and
> operand in
> order and just
> complain about differences)? The answer is
> that PHI
> nodes mean we will
> visit some uses before some definitions.
>
> Anyways, changing this text is optional in
> my mind. I
> think it could be
> better, but it's not worth spending much
> time on it.
>
> +int
> FunctionComparator::cmpValues(____const Value *L,
> const Value *R) {
>
> I wouldn't mind an explanation of the
> lexographic
> ordering on this one
> either. Constants before non-constants,
> then InlineAsm
> (ordered by
> address), then visit order.
>
> + if (L == R) return 0;
> + // Compare C1 and the bitcast result.
> + if (int Res = cmpConstants(ConstL,
> ConstR))
> + return Res;
> [...]
> + return 0;
>
> Isn't that just:
> return cmpConstants(ConstL, ConstR);
> ?
>
> 0003-attributes-comparison.____patch
>
> +int
> FunctionComparator::____cmpStrings(StringRef L,
> StringRef R) const {
> + // Prevent heavy comparison, compare
> sizes first.
> + if (int Res = cmpNumbers(L.size(),
> R.size()))
> + return Res;
> +
> + return L.compare(R);
> +}
>
> Optional: I'm curious whether that's
> actually worth it?
> I checked
> StringRef and it does the length comparison
> last. It
> could be that you
> know that your strings tend to be longer
> than StringRef
> which tries to
> be efficient in general.
>
> 0004-operations-comparison.____patch
>
> +int FunctionComparator::____cmpOperation(const
> Instruction *L,
>
> Optional: Again, a description of the
> ordering would be
> interesting.
> Opcode number, then number of operands,
> then type, then
> 'nsw/nuw/exact/volatile'.
>
> 0005-GEP-comparison.patch
>
> +int FunctionComparator::cmpGEP(____const
> GEPOperator
> *GEPL,
> + const
> GEPOperator
> *GEPR) {
>
> + unsigned int ASL =
> GEPL->getPointerAddressSpace()____;
>
> Extra line after {
>
> if (DL) {
> [...]
> + unsigned BitWidth = DL ?
> DL->getPointerSizeInBits(ASL) : 1;
>
> BitWidth doesn't need to test DL for null-ness.
>
> 0006-top-level-compare-method.____patch
>
> Perfect!
>
> 0007-sanity-check.patch
>
> + // Check symmetricity.
>
> "symmetricity" -> "symmetry".
>
> 0008-removed-unused-methods.____patch
>
> Perfect
>
> 0009-FnSet-replaced-with-____FnTree.patch
>
> Okay, I'm confused. We do all this work to
> produce a
> 3-way comparison,
> then we wrap it up in an operator< for a
> std::set that
> will only look at
> less-than, but never uses the equals
> result. We want to
> do one
> comparison between two functions, not two
> (ie., std::set
> does
> func1<func2 and func2<func1 to see whether
> they're equal
> or less than,
> and we don't need that since cmp(func1,
> func2) tells us
> directly). Maybe
> this comes in a future patch?
>
> One other question, I should probably know
> the answer to
> this but it's
> been a while. :) When we start detecting equal
> functions, do we merge
> them immediately? If so, can't that cause
> functions
> already in the set
> to have their equality comparisons change
> (ie., A calls
> X, B calls Y, A
> and B are in the set, then we merge X and Y
> for being
> equal, now we've
> changed A and B to both called the same
> merged function,
> so they start
> to compare the same). Sets tend not to like
> having their
> comparison
> functions change on elements that they contain.
>
> 0010-updated-comments.patch
>
> Okay.
>
> 0011-removed-DenseMap-helpers.____patch
>
> Yay deleting dead code!
>
> Nick
>
>
> Thanks!
> -Stepan.
>
> Stepan Dyatkovskiy wrote:
>
> ping
> Stepan Dyatkovskiy wrote:
>
> Hi Nick,
>
> Please find the fixed patches
> in attachment.
> Series starts from "constants
> comparison".
>
> Below small report of what has
> been fixed,
> and answers on your
> questions.
>
> cmpTypes:
> > Please add a comment for
> this method.
> Include the meaning of the
> returned value. ("man strcmp" for
> inspiration.)
> Fixed and committed. So you can
> look in
> trunk, may be I forgot to do
> something (hope not :-) )
>
> checkForLosslessBitcast,
> cmpConstants:
> > Why isn't this using cmpType?
> Fixed.
>
> > Please put the else on the
> same line as
> the closing brace.
> Fixed.
>
> >> + else if (const VectorType
> *thisPTy =
> dyn_cast<VectorType>(L))
> > Missing initial capital
> Sorry. Fixed. Actually these
> typos has been
> cloned from
> Type::canLosslesslyBitCastTo.
>
> >> + return
> cmpNumbers((uint64_t)L,
> (uint64_t)R);
> >>
> > Please assert on unknown
> constant.
> That's possible. But what if we
> really got
> unknown constant? New
> comming
> constant types merely depends on
> MergeFunctions implementation.
> So we
> get crash if it will happen.
> And we loose
> nothing comparing them
> just as
> pointers. So, do we really need an
> assertion? Currently I kept it
> as it
> was. If your answer is "yes, we
> need it", it
> would easy to add it:
>
> case Value::FunctionVal:
> case Value::GlobalVariableVal:
> - case Value::GlobalAliasVal:
> - default: // Unknown constant
> - return cmpNumbers((uint64_t)L,
> (uint64_t)R);
> + case Value::GlobalAliasVal:
> + return cmpNumbers((uint64_t)L,
> (uint64_t)R);
> + default:
> + llvm_unreachable("Unknown
> constant.");
>
> About variable names: Var1, Var2 vs
> VarL,VarR.
> I think its better to use L/R
> concept. Easer
> to understand what to
> return (-1, or 1) when you see
> L/R rather
> than Var1/Var2.
> Var1/Var2 has been kept for
> functions that
> are to be removed till the
> end of patch series.
> F1 and F2 names were also kept
> till the "top
> level compare method"
> patch.
>
> > Alternatively, any reason
> not to have
> cmpPointers(const void *L,
> const void *R)?
> I could do it. I just wanted to
> show that
> pointers are compared
> like a
> numbers in some situations.
> Actually we do
> it in cases when we have
> absolutely no idea of smarter
> comparison.
> And back to cmpPonters. Its
> rather about
> what intuition tells. If
> pointers are equal as numbers,
> could they be
> different somehow? Could
> they be non-castable to numbers
> on some
> platforms? The last one is
> big
> trouble for DenseMapInfo
> implementation..
> If there is any (even very small)
> possibility of such cases - then
> yes,
> I vote for cmpPointers. The
> last word is up
> to you anyway.
>
> Attributes (0005):
> > Attributes already have
> operator< and
> operator==. Please reuse
> them.
> Fixed. I used simple "if":
>
> if (LA < RA)
> return -1;
> if (RA < LA)
> return 1;
>
> Though its possible to use:
>
> if (int Res = (LA < RA) ? -1 :
> (RA < LA) ? 1
> : 0)
> return Res;
>
> Which one is more preferable?
>
> cmpGEP (0007):
> > + int cmpGEP(const
> GEPOperator *GEP1,
> const GEPOperator *GEP2);
> > + int cmpGEP(const
> GetElementPtrInst
> *GEP1,
> > + const GetElementPtrInst
> *GEP2) {
> >
> > Const members?
> We can't make it constant,
> since it compares
> values (cmpValues, aka
> enumerate). So, if we see Value
> first time,
> we have to add it into
> sn_mapL/R.
>
> > I think you should put this
> under if (DL)
> { /* declare Offset1,
> Offset2, etc. */ }
> Fixed.
>
> About 0008:
> > Did you mean "cmpOperation"?
> Yes. We could keep it in one
> place. I have
> fixed this case and
> removed
> TODO.
>
> > "compare" still returns
> "bool". I'm going
> to assume this was
> meant to
> go in 0009.
> Yes.
>
> About 0011:
> > std::set is frowned upon, see
>
> http://llvm.org/docs/____ProgrammersManual.html#set
> <http://llvm.org/docs/__ProgrammersManual.html#set>
>
> <http://llvm.org/docs/__ProgrammersManual.html#set
> <http://llvm.org/docs/ProgrammersManual.html#set>>
> . Do you actually
> rely
> on the stable iterator
> guarantee? Or would
> another set-like container
> be a
> better fit?
> Huh.. I have looked for
> alternatives.
> Unfortunately SmallSet is not
> suitable, since we need to
> lookup existing
> items, and SmallSet::find
> method is not present. May be I
> have missed
> something.
> Actually we need binary tree
> implementation.
> Do we have better
> analogue?
> I could implement new one.
> Think it should
> be just one more patch
> afterwards.
>
> >No. An identifier with
> underscore then
> capital letter is reserved
> for
> the implementation. You can
> just call them
> "F" and "DL", then the
> ctor
> initializer list can be "F(F),
> DL(DL)" and
> that will work fine.
> Fixed.
>
> 0013:
> > Sorry, I'm not sure what
> this sentence
> means? The thing your
> example
> is talking about is showing is
> that two
> functions in an SCC may be
> equivalent, and detecting them
> requires
> "blinding" (ignoring) certain
> details of the function when
> you do the
> comparison. We blind
> ourselves
> to the pointee types, but not
> to callees of
> functions in the same
> SCC.
>
> I meant generalising of
> cross-reference case:
> in old implementation, while
> comparing F and
> G functions, we treat as
> equal case when F uses G, with
> case when G
> uses F (at the same
> place).
> It could happen that F uses G1,
> while G1
> uses G2, while G2 uses F.
> So it
> still the same. But currently
> we have to
> invent way how to detect
> such
> cases.
>
> Thanks for reviews!
> -Stepan
>
> Stepan Dyatkovskiy wrote:
>
> Hi Nick,
> I have committed 0001 as
> r203788.
> I'm working on fixes for
> 0002 - 0014.
>
> > After reading through
> this patch
> series, I feel like I'm missing
> > something important.
> Where's the sort
> function? It looks like
> we're
> > still comparing all
> functions to all
> other functions.
> When you insert functions
> into std::set
> or its analo g s it does all
> the
> job for you. Since
> internally it builds
> a binary tree using "less"
> comparison, and each
> insert/look-up
> operation takes O(log(N)) time.
>
> -Stepan.
>
> Nick Lewycky wrote:
>
> On 27 February 2014
> 08:23, Stepan
> Dyatkovskiy
> <stpworld at narod.ru <mailto:stpworld at narod.ru>
>
> <mailto:stpworld at narod.ru <mailto:stpworld at narod.ru>>
>
> <mailto:stpworld at narod.ru <mailto:stpworld at narod.ru>
>
> <mailto:stpworld at narod.ru <mailto:stpworld at narod.ru>>>> wrote:
>
> Hi Nick,
>
> I tried to rework
> changes as you
> requested. One of
> patches (0004
> with extra assertions)
> has been
> removed.
>
>
> > + bool
> isEquivalentType(Type
> *Ty1, Type *Ty2) const {
> > + return
> cmpType(Ty1, Ty2) == 0;
> > + }
> >
> > Why do we still need
> isEquivalentType? Can
> we nuke this?
> Yup. After applying all
> the patches
> isEquivalentType will be
> totally
> replaced with cmpType.
> All isEqXXXX
> and friends will be
> removed in
> 0011 (old 0012). No
> traces left.
> Old function wasn't
> removed in 0001
> just for keeping patches
> without
> extra noise like:
>
> - something that uses
> isEquivalentType
> + something that uses
> cmpType
>
> The point is, that
> "something" that
> uses isEquivalentType,
> will be
> also replaced with one
> of next
> patches in this series.
>
>
> >
> > +static int
> cmpNumbers(uint64_t
> L, uint64_t R) {
> > + if (L < R) return -1;
> > + if (L > R) return 1;
> > + return 0;
> > +}
> >
> > At a high level, you
> don't
> actually need a <=>
> operator to use a
> sort. A
> > strict ordering ( <
> operator) is
> sufficient. (Note that for
> mergefunc, a
> > strict weak ordering
> is not
> sufficient, it must be
> a total
> ordering.)
> That could be done with int
>
> FunctionComparator::compare(). We can
> replace it with bool
>
> FunctionComparator::less(). Though
> for all
> other cmp methods need
> at least 2
> bits of information as
> result:
> 1. Whether things are
> equal.
> 2. Whether left less
> than right.
>
> As for
>
> FunctionComparator::compare(),
> conversion into less() will
> increase time of sanity
> check (patch
> #0010).
> Sanity check is just a
> sweet bonus.
> It checks that ordering
> implemented properly
> (checks order
> relation properties).
> Turning compare() into
> less() mean,
> that we'll have to run
> comparison two times:
> L.less(R) and
> R.less(L). But may be
> sanity
> check is not a thing to
> be published
> at all.
>
>
> >
> > Consider hoisting
> this inside the
> FunctionComparator
> class? That
> class
> > should have a bunch of
> implementations of
> comparisons
> between
> various
> > different things,
> which can pass
> down to other methods
> in the
> same class.
> In new patch series
> attached to this
> post, I have moved all
> static
> methods into
> FunctionComparator.
>
>
> > + // Replacement for
>
> type::canLosslesslyBitCastTo, that
> > + // establish order
> relation on
> this kind of properties.
> > + int
>
> checkForLosslessBitcast(const Type
> *L, const Type *R);
> >
> > Type:: not type:: .
> Please make
> this comment more
> descriptive.
> Done.
> [new comment]
> Replacement for
>
> Type::canLosslesslyBitCastTo, that
>
> establish order
> relation on this
> kind of properties
> Returns 0, if L and R
> types could be
> converted to each other
> without
> reinterpretation of bits.
> Otherwise method
> returns -1 or 1,
> defining total ordering
> between
> types in context of
> lossless
> bitcastability trait.
> E.g.: if L is less than
> R (result is
> -1), than every type that
> could be
> losslessly bitcasted to
> L is less
> than R.
> [/new comment]
>
>
> >
> > + /// Replacement
> for C1 ==
> getBitCast(C2, C1Ty)
> > + /// Its more
> controllable, and
> supposed to be simpler and
> more
> > predictionable.
> > + /// As very important
> advantage: it allows to
> introduce
> order
> relation on
> > + /// constants set,
> and thus use
> it as trait in refinement
> routines.
> >
> > "Its" --> "It's".
> "predictionable" -->
> "predictable".
> And how is
> it more
> > predictable? I think
> this comment
> would be better if it
> described the
> > function instead of
> making
> comparisons between it
> and other
> functions.
> > Something like, "Compare
> constants under a
> system where
> pointer
> to X and
> > pointer to Y are
> considered
> equal" or whatever is
> actually true
> here.
> Done.
> [new comment]
>
> Replacement for C1 ==
> getBitCast(C2,
> C1Ty)
> Parses constants
> contents, assuming
> that types are losslessly
> bitcasted between each
> other. So
> actually it ignores
> types and only
> compares bits from L and R.
> Returns 0, if L and R
> has equivalent
> content.
> -1 or 1 if values are
> different.
> Maintaining total ordering
> requires
> two values that indicates
> non-equivalence (L less
> R, L
> greater R).
> [/new comment]
>
>
> >
> > +enum ConstantType {
> > I'm not sure that
> this buys you
> much. All the "isa"
> tests can be
> broken
> > down into a switch on
> getValueID() with the one
> exception of
> isNullValue().
> Done.
>
>
> > + assert(
> > +
>
> C1->getType()->______canLosslesslyBitCastTo(C2->______getType())
> &&
> > + "Pass is healthless.
> checkForLosslessBitcast
> should be
> twin of "
> > +
> "canLosslesslyBitCastTo method,
> except the case when the
> last one "
> > + "returns false,
> the first one
> should return -1 or 1");
> ...
>
> > I think we can skip
> the asserts
> here. They aren't
> detecting a
> specific
> > bug, they're
> checking whether the
> new code does a certain
> task
> relative
> > to the old code.
> Drop the old
> code, your new code is
> the new
> sheriff in
> > town.
> Asserts has been removed.
>
>
> >
> > + DenseMap<const
> Value*, int>
> sn_map1, sn_map2;
> >
> > What is sn short for
> ("seen")?
> Why are there two of these?
> Serial number :-)
>
> >
> > +
> std::pair<DenseMap<const Value
> *, int>::iterator, bool>
> > + LeftSN =
>
> sn_map1.insert(std::make_pair(______V1,
> sn_map1.size())),
> > + RightSN =
>
> sn_map2.insert(std::make_pair(______V2,
> sn_map2.size()));
> >
> > So I think I get it,
> this is easy
> to reason about. You number
> each value
> > going down both
> functions. But I
> think you can eliminate
> one of
> these
> > maps because you
> know that if the
> left and right were ever
> different
> > then we terminate
> the comparison
> immediately. You can at
> least
> share one
> > map with both V1 and
> V2, but I
> think you can reduce
> the number
> of map
> > insertions.
> Not sure. Consider that
> in left you
> have:
> %A = alloca i32
> %B = alloca i32
> store i32 1, i32* %A
>
> And in right:
> %A = alloca i32
> %B = alloca i32
> store i32 1, i32* %B
>
> When we meet 'store'
> instruction we
> need to check in which
> order %A
> was allocated at left
> and in which
> order %B was allocated
> at right.
> So for each value in
> function we
> have to assign serial
> number. Then
> comparing to local
> values from
> different functions we
> can just
> check
> their serial numbers.
> Though, may be I missed
> something?
> May be there is another
> way to
> determine "who was first".
>
>
> > High-level question, are
> attributes ordered? Your
> comparison is
> ordered.
> > So if I have
> function F with
> string attributes "sse2",
> "gc=hemisphere"
> > and another function
> G with
> string attributes
> "gc=hemisphere",
> "sse2"
> > then they would be
> considered
>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0006-top-level-comparisons.patch
Type: text/x-diff
Size: 9942 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140516/a6c25b18/attachment.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0007-sanity-check.patch
Type: text/x-diff
Size: 3933 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140516/a6c25b18/attachment-0001.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0008-removed-unused-methods.patch
Type: text/x-diff
Size: 2231 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140516/a6c25b18/attachment-0002.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0009-FnSet-replaced-with-FnTree.patch
Type: text/x-diff
Size: 6834 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140516/a6c25b18/attachment-0003.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0010-updated-comments.patch
Type: text/x-diff
Size: 3322 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140516/a6c25b18/attachment-0004.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0011-removed-DenseMap-helpers.patch
Type: text/x-diff
Size: 4629 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140516/a6c25b18/attachment-0005.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: apply-patches.sh
Type: application/x-sh
Size: 355 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140516/a6c25b18/attachment.sh>
More information about the llvm-commits
mailing list