This is an archive of the discontinued LLVM Phabricator instance.

Speed up Function::isIntrinsic() by adding a bit to GlobalValue. NFC
ClosedPublic

Authored by jlebar on Jul 28 2016, 5:00 PM.

Details

Summary

Previously isIntrinsic() called getName(). This involves a hashtable
lookup, so is nontrivially expensive. And isIntrinsic() is called
frequently, particularly by dyn_cast<IntrinsicInstr>.

This patch steals a bit of IntID and uses that to store whether or not
getName() starts with "llvm."

Diff Detail

Event Timeline

jlebar updated this revision to Diff 66062.Jul 28 2016, 5:00 PM
jlebar retitled this revision from to Speed up Function::isIntrinsic() by adding a bit to GlobalValue. NFC.
jlebar updated this object.
jlebar added subscribers: llvm-commits, sanjoy.

I reverted the old change in rL277087.

Justin Bogner wrote in an email to the list:

I'm a bit less comfortable with this change than I was with the other
one - it's more of a straight performance hack this way, whereas the
other way fit better in a future where target-specific intrinsics are
more of a first class idea.

I'll let others comment on whether or not this is worth it as a
hopefully temporary thing for the performance gain in the short term.

Anyone else want to chime in here? To me it seems like a relatively simple change that gets us a substantial win, but I hear Justin B.'s position as well.

jlebar edited reviewers, added: rnk; removed: chandlerc.Aug 17 2016, 5:09 PM
rnk edited edge metadata.Aug 18 2016, 9:25 AM
rnk added a subscriber: beanz.

Justin Bogner wrote in an email to the list:

I'm a bit less comfortable with this change than I was with the other
one - it's more of a straight performance hack this way, whereas the
other way fit better in a future where target-specific intrinsics are
more of a first class idea.

Do you think we should move more towards LLVM having a single enum of all target intrinsics, or more towards a place where LLVM has target neutral intrinsics, and then there is a separate target-specific intrinsic ID space that mid-level optimizers can't know about?

This change actually seems like a step towards that world, which the AMDGPU backend is already half-in: all intrinsics are named "llvm.*" and many of them are not included in Intrinsic::ID.

Maybe in the long run we should move all target intrinsics out of include/llvm/IR/Intrinsics*.td, and down into lib/Target. We'd use TargetIntrinsicInfo to look up the ID. Then we can go back to the old, non-bitfield solution. It also makes it easier for us to compile out the intrinsic name to ID tables for disabled targets, which I think @beanz wanted to do. I don't think IR can talk to Target, so we probably can't do this the obvious way.

Sean Silva wrote on the list:

Sorry if I missed it, but do you have perf measurements posted somewhere?

Sorry, those were in the patch for the last way I tried to do this. It's good for a 1.5% e2e speedup compiling an Eigen benchmark.

In D22949#519623, @rnk wrote:

which I think @beanz wanted to do.

@bogner has taken over my primary interests in that. In general I think pushing target-specific things (like intrinsics) into targets is a really great idea. I have this pipe dream of someday being able to make dynamically loadable targets, which I think would be really cool.

chandlerc accepted this revision.Dec 28 2016, 2:22 PM
chandlerc edited edge metadata.

LGTM, let's ship it.

I alse hear Justin's concern here, especially what he wrote up on the mailing list. However, I like one thing he said: this will essentially get reverted if/when we go down that path. That seems totally fine to me considering how isolated this change is. When the time comes, it'll be easy and transparent to rip out. I think the performance hack in the interim is worth it, and will also keep us honest as we explore options to fix intrinsics in a more fundamental way by holding the higher performance bar.

-Chandler

This revision is now accepted and ready to land.Dec 28 2016, 2:22 PM
This revision was automatically updated to reflect the committed changes.
rnk added a comment.Dec 28 2016, 4:07 PM

Also, this comment in Value.h could use an update:

/// \brief Return a constant reference to the value's name.
///
/// This is cheap and guaranteed to return the same reference as long as the
/// value is not modified.
StringRef getName() const;

A hash table lookup is only cheap in grad school.

llvm/trunk/include/llvm/IR/GlobalValue.h
145 ↗(On Diff #82623)

Please use unsigned so this doesn't grow Value on Windows. This program compiles without error with MSVC:

enum IntrinsicID : unsigned { ID0 = 0 };
struct Foo { IntrinsicID id : 31; bool bit : 1; };
struct Bar { IntrinsicID id : 31; unsigned bit : 1; };
static_assert(sizeof(Foo) == 8, "");
static_assert(sizeof(Bar) == 4, "");