This is an archive of the discontinued LLVM Phabricator instance.

Resolve {GlobalValue,GloalIndirectSymol}::getBaseObject confusion
ClosedPublic

Authored by MaskRay on Sep 14 2021, 4:01 PM.

Details

Summary

While both GlobalAlias and GlobalIFunc are GlobalIndirectSymbol, their
getIndirectSymbol() usage is quite different (GlobalIFunc's resolver
is an entity different from GlobalIFunc itself).

As discussed on https://lists.llvm.org/pipermail/llvm-dev/2020-September/144904.html
("[IR] Modelling of GlobalIFunc"), the name getBaseObject is confusing when
used with GlobalIFunc.

To resolve the confusion:

  • Move GloalIndirectSymol::getBaseObject to GlobalAlias:: (GlobalIFunc should use getResolver instead)
  • Change GlobalValue::getBaseObject not to inspect GlobalIFunc. Note: the function has 7 references.
  • Add GlobalIFunc::getResolverFunction to peel off potential ConstantExpr indirection (strlen in test/LTO/Resolution/X86/ifunc.ll)

Note: GlobalIFunc::getResolver (like GlobalAlias::getAliasee which does not peel
off ConstantExpr indirection) is kept to be used by ValueEnumerator.

Diff Detail

Event Timeline

MaskRay created this revision.Sep 14 2021, 4:01 PM
MaskRay requested review of this revision.Sep 14 2021, 4:01 PM
Herald added a project: Restricted Project. · View Herald TranscriptSep 14 2021, 4:01 PM
MaskRay edited the summary of this revision. (Show Details)Sep 14 2021, 4:09 PM
MaskRay added a reviewer: rjmccall.

Added a couple of comments; I think this change breaks code that wants to get the resolver Function itself because it deprives such code from the ConstantExpr-peeling machinery in findBaseObject.

llvm/include/llvm/IR/GlobalIndirectSymbol.h
65 ↗(On Diff #372582)

When creating my own commit, I noticed that the two overloads below (with DataLayout and APInt) are completely unused. Perhaps we can use this opportunity to remove them?

llvm/lib/Object/IRSymtab.cpp
289

This will crash on bitcasts, see e.g. https://clang.godbolt.org/z/ssxrj9b7d
In other words, code that wants to deal with getting the resolver of a GlobalIFunc took a reliance upon the ConstantExpr-peeling machinery of findBaseObject() that was previously utilized only by GlobalAlias prior to the introduction of GlobalIFunc. It is unclear to me whether all the ConstantExpr handlings in findBaseObject() are needed in the case of GlobalIFunc-s.

llvm/lib/Transforms/Utils/SplitModule.cpp
133

Same as above, will crash on bitcasts

MaskRay updated this revision to Diff 372868.Sep 15 2021, 10:35 PM
MaskRay marked an inline comment as done.
MaskRay edited the summary of this revision. (Show Details)

add a strlen test
fix ConstantExpr issue

MaskRay marked 2 inline comments as done.Sep 15 2021, 10:36 PM
MaskRay added inline comments.
llvm/lib/Object/IRSymtab.cpp
289

Thanks for the example. Added strlen to llvm/test/LTO/Resolution/X86/ifunc.ll to catch the regression.

MaskRay marked an inline comment as done.Sep 15 2021, 10:36 PM
ibookstein accepted this revision.Sep 21 2021, 12:58 PM

I've added one additional minor comment; other than that, I think this makes good progress in resolving the ambiguity currently in trunk.
I still think that to be able to express alias-to-ifunc situations (i.e. @foo1 = ifunc i32 (i32), i64 ()* @foo_resolver; @foo2 = alias i32 (i32), i32 (i32)* @foo1) we'll need to consider https://reviews.llvm.org/D108872, but that's a problem for another day (and I'd appreciate your opinion on that direction).

A couple of questions:

  1. This effectively turns getBaseObject() into getAliaseeObject(), so it might make sense to perform that rename in a later commit - WDYT?
  2. If I understand you correctly, calls to GlobalValue::getBaseObject() are exceedingly rare. Would it make sense to try and remove it from the base class so that only GlobalIFunc::getResolverFunction() and GlobalAlias::getAliaseeObject() remain? I like the explicitness that that would create, but I'm wondering whether that sacrifices utility too much.
llvm/lib/IR/Globals.cpp
467

Should also remove the declaration then, no?

This revision is now accepted and ready to land.Sep 21 2021, 12:58 PM
MaskRay added a comment.EditedSep 21 2021, 1:17 PM

Thanks:) Will push in two days unless someone objects.

I've added one additional minor comment; other than that, I think this makes good progress in resolving the ambiguity currently in trunk.
I still think that to be able to express alias-to-ifunc situations (i.e. @foo1 = ifunc i32 (i32), i64 ()* @foo_resolver; @foo2 = alias i32 (i32), i32 (i32)* @foo1) we'll need to consider https://reviews.llvm.org/D108872, but that's a problem for another day (and I'd appreciate your opinion on that direction).

Inheriting from GlobalObject makes sense to me, since we won't use any facility from GlobalIndirectSymbol.

A couple of questions:

  1. This effectively turns getBaseObject() into getAliaseeObject(), so it might make sense to perform that rename in a later commit - WDYT?

Makes sense to me.

  1. If I understand you correctly, calls to GlobalValue::getBaseObject() are exceedingly rare. Would it make sense to try and remove it from the base class so that only GlobalIFunc::getResolverFunction() and GlobalAlias::getAliaseeObject() remain? I like the explicitness that that would create, but I'm wondering whether that sacrifices utility too much.

Yes, I think removing GlobalValue::getBaseObject() will be worthwhile. My quick glance at the call sites suggest that they don't use the GlobalIFunc::getResolverFunction() facility.