Where does go assign noop to empty functions?

510 views
Skip to first unread message

iamory...@gmail.com

unread,
Aug 3, 2018, 5:05:52 PM8/3/18
to golang-dev
Hi, I'm working on an issue where I need to optimize calls to deffered empty functions out of the asm. I have tried adding it in the SSA stage but it seems impossible without data being collected about the call during ast.

What I'm trying to find out is where do empty functions currently get assigned with the opcode OEMPTY, and get inspiration for the logic from there.

I have found a way to check that about inlineable functions (under func, sym, inl I have and opcode identifying it as empty) but I'm not sure it's the best I can do.

It's somewhere in the ast stage, I think it's in walk.go or pgen.go, but I can't find it.

Any help?

Oryan Moshe

unread,
Aug 3, 2018, 6:49:28 PM8/3/18
to golang-dev
Correction, SSA seems to have enough data, but still, I cannot find the place where we decide that a function is empty. 
Seems like we can check if the length of Blocks is zero (or one but a BlockPlain), but I just can't find where we do it currently for empty functions that are not deffered. 

--
You received this message because you are subscribed to a topic in the Google Groups "golang-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-dev/u13RSPKRqC4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Josh Bleecher Snyder

unread,
Aug 5, 2018, 2:42:18 PM8/5/18
to Oryan Moshe, golang-dev
> Correction, SSA seems to have enough data, but still, I cannot find the
> place where we decide that a function is empty.

There isn't such a place. You'd need to write such a thing yourself.
Start with the gc.Func and gc.Inline structs.

General tip for working on the compiler: Start with an absolutely
minimal Go program that exhibits the behavior you want. Understand
carefully what the compiler does with it. Useful flags often include
"-w -w", "-W -W", "-S", "-m -m", and the GOSSAFUNC env var. Add plenty
of your own (transient) print debugging. And write lots of tests.


> Seems like we can check if the length of Blocks is zero (or one but a
> BlockPlain), but I just can't find where we do it currently for empty
> functions that are not deffered.

Only the function currently being compiled has Blocks and Values that
you can get at. For other functions, you'll probably need to work off
their syntax tree (gc.Node, cmd/compile/internal/gc/syntax.go).



>> Hi, I'm working on an issue where I need to optimize calls to deffered
>> empty functions out of the asm. I have tried adding it in the SSA stage but
>> it seems impossible without data being collected about the call during ast.

I think you should try this during walk.go. Among other things, you'll
want to avoid Node.HasDefer being set if not necessary.


>> What I'm trying to find out is where do empty functions currently get
>> assigned with the opcode OEMPTY, and get inspiration for the logic from
>> there.

OEMPTY is an opcode for empty (no-op) statements. It is not used for functions.


-josh

Oryan Moshe

unread,
Aug 5, 2018, 2:51:05 PM8/5/18
to Josh Bleecher Snyder, golang-dev
Today I debugged the compiler for 8 hours straight, I finally understand where everything happens. 
After about 3 hours I finally understood I can't change it during SSA.
But still, even in walk (when getting to ODEFER) I don't have any indication on what the deferred function does, and whether it's empty or not. 
Should I do the check by number of operations inside? 
Should I add a flag to the function earlier in the walk? 

Oryan Moshe

unread,
Aug 5, 2018, 2:51:40 PM8/5/18
to Josh Bleecher Snyder, golang-dev
Thanks for the answers by the way! At least I know I'm in the right direction

Josh Bleecher Snyder

unread,
Aug 5, 2018, 3:02:25 PM8/5/18
to Oryan Moshe, golang-dev
> Today I debugged the compiler for 8 hours straight, I finally understand
> where everything happens.

If that took you only 8 hours, I am very impressed. :)

> But still, even in walk (when getting to ODEFER) I don't have any indication
> on what the deferred function does, and whether it's empty or not.
> Should I do the check by number of operations inside?
> Should I add a flag to the function earlier in the walk?

I'd inspect the function there (lazily), rather than adding a flag.
Very few functions are deferred.

-josh

Oryan Moshe

unread,
Aug 5, 2018, 5:32:08 PM8/5/18
to Josh Bleecher Snyder, golang-dev
I'll look at it tomorrow, I'm wondering how I can tell if a function is empty, I'll probably create two functions and compare the output while debugging (unless you have an idea for that) 

Keith Randall

unread,
Aug 5, 2018, 7:15:10 PM8/5/18
to iamory...@gmail.com, Josh Bleecher Snyder, golang-dev
You might be able to tell if a function is empty by looking at its inlineable body.  The compiler keeps that around for inlineable functions, and the empty function should always be inlineable.

--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.

Oryan Moshe

unread,
Aug 6, 2018, 12:46:17 AM8/6/18
to Keith Randall, Josh Bleecher Snyder, golang-dev
Unless we used the noinline directive, any idea about that case? 

Keith Randall

unread,
Aug 6, 2018, 12:54:10 AM8/6/18
to iamory...@gmail.com, Josh Bleecher Snyder, golang-dev
Don't handle that case.  noinline is really only for testing.

Oryan Moshe

unread,
Aug 6, 2018, 3:19:39 AM8/6/18
to Keith Randall, Josh Bleecher Snyder, golang-dev
OK, and about cutting out the empty defer, how do I do it? Can I just replace the defer with it's content (empty in line) and let the rest of the chain handle it? Should I charge it to OEMPTY (even though it's a function call)? 

Josh Bleecher Snyder

unread,
Aug 6, 2018, 8:09:15 AM8/6/18
to Oryan Moshe, Keith Randall, golang-dev
I think you should replace the ODEFER node with an OBLOCK node that evaluates the function’s arguments and anything else that must be evaluated for side effects (see my comments in the issue). 
Reply all
Reply to author
Forward
0 new messages