Skip to content

Comments

Intrinsic: idempotent#8354

Open
kripken wants to merge 29 commits intoWebAssembly:mainfrom
kripken:idempotent
Open

Intrinsic: idempotent#8354
kripken wants to merge 29 commits intoWebAssembly:mainfrom
kripken:idempotent

Conversation

@kripken
Copy link
Member

@kripken kripken commented Feb 20, 2026

An idempotent function may do work when called, but if called again with
the same parameters, it does no work and it returns the same value (if it
returns a value).

This uses the new intrinsic in OptimizeInstructions. More things are
possible too.

See discussion in #7574

@kripken
Copy link
Member Author

kripken commented Feb 20, 2026

The refactoring in OptimizeInstructions had an additional benefit, it turns out. I moved that out to #8355

@kripken kripken marked this pull request as ready for review February 20, 2026 19:40
@kripken kripken requested a review from tlively February 20, 2026 19:40
@kripken
Copy link
Member Author

kripken commented Feb 20, 2026

Btw, I noticed that C has something similar to this: [reproducible]. However that is "effectless and idempotent", and here we only want idempotency. There is a request for idempotency like ours on gcc but it wasn't added AFAICT. (cc @dschuff )

Comment on lines +29 to +30
// If the called function is idempotent, then it does not generate new
// values on each call.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is correct. An idempotent function could return new values on each call as long as it gets different parameters each time (for example if it's either creating new values or looking them up in a cache). It seems like this would cause problems for users of isShallowlyGenerative, at least.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's already in the definition of generative?

// A "generative" expression is one that can generate different results for the
// same inputs, and that difference is *not* explained by other expressions that

If the inputs change, all bets are off.

Users of isShallowlyGenerative need to look at children, correct. LocalCSE does that, basically the "shallow" version is an incremental one, more efficient sometimes, but the children must be scanned as well.

Comment on lines +2879 to +2880
// No effects are possible.
rightMightHaveEffects = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also expect us to have to check that the child values match here. Do we not?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We check that the entire expressions match, including children, on line 2891.

It is just that it seems more efficient to do it in this order (the equality check scans both inputs, not just one, so early exit can avoid scanning half the data).

Comment on lines +2336 to +2337
// We may want to move the function-level annotations to a dedicated
// field outside the map.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think this would be a nice cleanup anyway.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sg, will do it soon.

;; CHECK: (func $potent (type $0) (param $x f32) (result f32)
;; CHECK-NEXT: (call $import)
;; CHECK-NEXT: )
(func $potent (param $x f32) (result f32)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or "alipotent" from the Latin root "Ali-" meaning "different" 😀

)
)
)
;; Here we succeed, as the calls are marked idempotent.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add cases where just one or the other of the calls is marked idempotent. (Although what would the meaning of that be? Optimizable whenever the second call is marked idempotent, perhaps?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, when the second is marked, that seems right. Added.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this enough to write CSE tests that show idempotent function calls being deduplicated?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CSE needs to actually find the two calls, and only then can it infer that the second is removable. So this does require logic in each pass, like the areEqualAndFoldable part here. That and OnceReduction I can do later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants