A ConstantStruct is renamed when the LLVM context sees a new one. This
makes global variable initializers appear different when they aren't.
Instead, check the ConstantStruct for equivalence.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
llvm/tools/llvm-diff/DifferenceEngine.cpp | ||
---|---|---|
480 | Hmm. I don't think it's okay to just compare the number of elements: if the types might be different, they might have different layouts. |
llvm/tools/llvm-diff/DifferenceEngine.cpp | ||
---|---|---|
480 | The individual elements are checked in the loop below. I made it recursive because I couldn't count on the types to be uniqued, because of the naming differences. |
llvm/tools/llvm-diff/DifferenceEngine.cpp | ||
---|---|---|
480 | Sure, I see that, but you could have different struct types with different layouts but compatible elements. Because one is packed and the other isn't, or so on. |
llvm/tools/llvm-diff/DifferenceEngine.cpp | ||
---|---|---|
480 | Ah! I see what you mean. There's a method called isLayoutIdentical, but it checks each element's pointer value. The only other thing it checks is the Packed attribute. I added that. |
Structures are the only types which can reference themselves. If I don't stop processing already seen types then it's possible they could infinitely recurse. The stack / std::find code is very hackish. I'm open to suggestions on making it non-gross. :-)
Well, they can't reference themselves as sub-aggregates; you'll never see another field of this exact type.
Check to ensure we don't analyze the global variable we're currently analyzing. This causes an infinite loop.
Doh! Of course. I found the actual problem. A global variable may occur in its own initializer as part of a GEP or bitcast. I added a more sane check. PTAL
Oh, yeah, if we recurse into initializers in equivalentAsOperands then we'll have that problem for sure. I don't think you can just check at the top level of a struct initializer, though — you need to be able to do this check in recursive positions, like if the element initializer is a bitcast. I would suggest doing the check specifically in the case where you've found global variables.
Also, you should record both GVL and GVR in the difference engine you construct, and then do something like if (GVL == SavedGVL) return GVR == SavedGVR;. If you see a self-reference in the LHS but the RHS is like a null pointer or some other global, that's a difference, not something we should skip! This will make it a sort of maximal fixed point.
I would suggest just setting SavedGVL and SavedGVR on the temporary difference engine instead of passing them in to all uses of equivalentOnOperands.
Improve the check of the global variable initializers. Both LHS and RHS need to
match the global variable at the same time when recursing or they don't match.
llvm/tools/llvm-diff/DifferenceEngine.cpp | ||
---|---|---|
581 | The other constructors doesn't initialize these. Might be best to just = nullptr them and then override them, either here or separately after construction. |
Hmm. I don't think it's okay to just compare the number of elements: if the types might be different, they might have different layouts.