| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Co-Authored-By: Jules <57632293+JuliaPoo@users.noreply.github.com>
There was a problem hiding this comment.
Nit comment:
Even if the explanation about type is described at https://github.com/Fidget-Spinner/cpython_optimization_notes/blob/main/3.13/uops_optimizer.md,
But are you going to write a simple explanation about what is pure, mandatory and guard in somewhere of the CPython repository?
Sorry, something went wrong.
Yep I definitely will. Probably at the top of the bytecodes.c file or the interpreter definition documentation. |
Sorry, something went wrong.
There was a problem hiding this comment.
The mandatory annotation makes no sense to me.
All uops are mandatory unless you can prove that they can be safely removed.
No uop is mandatory if you can prove that it can be safely removed.
RESUME_CHECK is no more mandatory than anything else.
guard makes more sense, but it needs to be precisely defined before we add it.
I'm ok with adding the pure annotation, even though it isn't used yet.
Sorry, something went wrong.
| }; | ||
|
|
||
| op(_GUARD_BOTH_INT, (left, right -- left, right)) { | ||
| guard op(_GUARD_BOTH_INT, (left, right -- left: ~(PYINT_TYPE), right: ~(PYINT_TYPE))) { |
There was a problem hiding this comment.
Why the ~ prefix to the type. That implies that left is not a "PYINT_TYPE" which is the opposite of what happens.
Can you use int or PyLong_Type, rather than introducing new names?
Sorry, something went wrong.
There was a problem hiding this comment.
Perhaps use an & prefix and the C names. That way left: ~(PYINT_TYPE) becomes left: &PyLong_Type which matches the C syntax for the pointer to the int type.
Sorry, something went wrong.
There was a problem hiding this comment.
I'll use the & prefix but not the existing names. The main reason is that we have types that aren't represented by either the C or Python types. An example is GUARD_DORV_VALUES_TYPE. That's a shape check that makes sure it's a values layout. However it does not correspond to other Py_Type or C type.
Sorry, something went wrong.
| }; | ||
|
|
||
| op(_GUARD_TYPE_VERSION, (type_version/2, owner -- owner)) { | ||
| guard op(_GUARD_TYPE_VERSION, (type_version/2, owner -- owner: ~(GUARD_TYPE_VERSION_TYPE + type_version))) { |
There was a problem hiding this comment.
What does ~(GUARD_TYPE_VERSION_TYPE + type_version) mean?
Sorry, something went wrong.
There was a problem hiding this comment.
Sorry, something went wrong.
There was a problem hiding this comment.
Basically, it tells it to grab the type_version from the operand, and add it to GUARD_TYPE_VERSION_TYPE.
Sorry, something went wrong.
There was a problem hiding this comment.
Annotations need to have meaning independent of any tool.
A flag that tells some tool to do something isn't maintainable. If someone changes _GUARD_TYPE_VERSION how do they know what to do with the annotation?
Sorry, something went wrong.
There was a problem hiding this comment.
It signals the type information is a combination of both GUARD_TYPE_VERSION_TYPE + type_version (where type_version was defined in the instruction's cache entries earlier). Without it, I don't see how any tool would know that there the type information is a combination of both -- how do you know a /2 is not just a generic cache entry but used for type information?
Sorry, something went wrong.
| } | ||
|
|
||
| op(_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, (owner -- owner)) { | ||
| guard op(_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, (owner -- owner: ~(GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_TYPE))) { |
There was a problem hiding this comment.
What does GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_TYPE mean?
Is this just saying that a value guarded by _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT has been guarded by _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT? That seems redundant.
Sorry, something went wrong.
There was a problem hiding this comment.
Yes it does. It's not redundant because some guards don't add type information (like state guards, or check stack space).
Sorry, something went wrong.
There was a problem hiding this comment.
All guards add information, whether that is type information depends on the type system being used.
This implies that your type system includes whether an object has a __dict__ or not, but that's not part of the what most people would consider the Python type system.
A type system that tracks stack space is plausible. In which case _CHECK_STACK_SPACE would carry type information.
Sorry, something went wrong.
The example and explanation I gave is ill-defined. The more correct definition of mandatory is that it cannot be const evaluated or type prop eliminated. An example is _CHECK_STACK_SPACE. This guard is only known at runtime, not compile-time. This just tells the abstract interpreter generator not to attempt to const/type-evaluate it. |
Sorry, something went wrong.
guard is a misnomer I think, I will likely rename it to passthrough. Basically for correctness' sake, the abstract interpreter invalidates all mutable type information gained at the boundaries between pure and impure instructions. The reasoning is that the impure instruction could have modified it. E.g. a.attr b() # Can't use the same type information here. Needs to guard again. a.attr However, for passthrough instructions, this won't happen. |
Sorry, something went wrong.
There was a problem hiding this comment.
I just have some very tiny nits; Mark already gave some substantial feedback.
I'm with Dong-hee: please introduce some form of docs (e.g. an update of Tools/cases_generator/interpreter_definition.md, which describes the syntax of bytecodes.c).
Please run the files you touched through Black.
Sorry, something went wrong.
Nothing is known initially when optimizing, but any instruction can potentially become redundant as more is known about the state of the program. _CHECK_STACK_SPACE can be eliminated: _CHECK_STACK_SPACE 20; _CHECK_STACK_SPACE 16 can be replaced with _CHECK_STACK_SPACE 20. |
Sorry, something went wrong.
Whether the second a.attr can be replaced with the result of the first lookup depends on what global guards have been inserted. For example, if a were a class and we added a type watcher on that class to invalidate the trace, then we could make assumptions about a.attr. The point is this sort of reasoning is as much or more a property of the optimizer than the micro-op. |
Sorry, something went wrong.
Yes, but the point is that we still need some sort of passthrough annotation. I'm not saying I'm adding it just for the optimizer. We just need some way to signal to the abstract interpreter that some things just move data around and don't transform it. I'm giving an example of how the information is useful for the optimizer. I'm not saying that is strictly the use case for it. Another example of a property we infer is that the abstract interpreter treats passthrough as having the same value numbering right now, and that is the most important part. Whereas impure creates new numbers.
I really dislike the example you gave. In reality that sequence of instructions will never occur like that -- in practice we know a _CHECK_STACK_SPACE always precedes a _PUSH_FRAME so that means it's always needed. If the frame is inlined, the _CHECK_STACK_SPACE will be gone. So there will never be two consecutive _CHECK_STACK_SPACE 20; _CHECK_STACK_SPACE 16 that occur from bytecode. The only way I can see to "eliminate" it is by merging them into one giant one at the top. In any case, what you said doesn't disagree with my new/correct definition:
I don't think _CHECK_STACK_SPACE can be const evaluated or type prop eliminated. I think the fact that this is causing so much confusion and pushback is a sign that the annotation name is misleading. I think a better name might be no_abstract_body or no_trivial_elimination or something better to signal my new definition. Any thoughts? The main idea is that pure automatically causes the abstract interpreter to try to const/type eliminate it (because by definition, that should be safe if an op is pure, but in reality these operations depend on runtime state of some sort so are not truly pure). |
Sorry, something went wrong.
|
Also a comment on
Which is why I said above:
The scenario you pointed out above is counted as immutable type information in the type system. So it won't be invalidated. |
Sorry, something went wrong.
|
In any case -- I think bikeshedding the name is actually a good thing here. If you're confused by the names they need to be renamed so I don't inadvertently confused more people. |
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM, but it’s up to Mark.
Sorry, something went wrong.
There was a problem hiding this comment.
There are still things that need clarifying.
_POP_FRAME and _PUSH_FRAME are not pure, they have side effects.
Why are you marking them as "pure"?
Sorry, something went wrong.
There was a problem hiding this comment.
The code, looks good.
The commentary needs a bit of tweaking.
Sorry, something went wrong.
|
When you're done making the requested changes, leave the comment: I have made the requested changes; please review again. |
Sorry, something went wrong.
There was a problem hiding this comment.
Thanks for making all the changes.
Sorry, something went wrong.
Co-authored-by: Jules <57632293+JuliaPoo@users.noreply.github.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Jules <57632293+JuliaPoo@users.noreply.github.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Jules <57632293+JuliaPoo@users.noreply.github.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
| Back | FazBrowse Home | New Git URL |
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.