mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-11 18:20:26 +09:00
Delete GT_INDEX
(#69917)
* Do not set NO_CSE on ARR_ADDRs It is effectively no-CSE already because of how "optIsCSECandidate" works. * Delete GT_INDEX Instead: 1) For "ldelem", import "IND/OBJ(INDEX_ADDR)". 2) For "ldelema", import "INDEX_ADDR". This deletes two usages of "ADDR": 1) "OBJ(ADDR(INDEX))" from "ldelem<struct>". 2) "ADDR(INDEX)" from "ldelema". * Add a zero-diff quirk * Update the first class structs document Remove references to things that no longer exist.
This commit is contained in:
parent
7439a889cb
commit
7bccc676c8
16 changed files with 332 additions and 528 deletions
|
@ -70,11 +70,6 @@ Current Representation of Struct Values
|
|||
|
||||
These struct-typed nodes are created by the importer, but transformed in morph, and so are not
|
||||
encountered by most phases of the JIT:
|
||||
* `GT_INDEX`: This is transformed to a `GT_IND`
|
||||
* Currently, the IND is marked with `GTF_IND_ARR_INDEX` and the node pointer of the `GT_IND` acts as a key
|
||||
into the array info map.
|
||||
* Proposed: This should be transformed into a `GT_OBJ` when it represents a struct type, and then the
|
||||
class handle would no longer need to be obtained from the array info map.
|
||||
* `GT_FIELD`: This is transformed to a `GT_LCL_VAR` by the `Compiler::fgMarkAddressExposedLocals()` phase
|
||||
if it's a promoted struct field, or to a `GT_LCL_FLD` or GT_IND` by `fgMorphField()`.
|
||||
* Proposed: A non-promoted struct typed field should be transformed into a `GT_OBJ`, so that consistently all struct
|
||||
|
@ -90,9 +85,7 @@ encountered by most phases of the JIT:
|
|||
### Struct “objects” as lvalues
|
||||
|
||||
* The lhs of a struct assignment is a block or local node:
|
||||
* `GT_OBJ` nodes represent the “shape” info via a struct handle, along with the GC info
|
||||
(location and type of GC references within the struct).
|
||||
* These are currently used only to represent struct values that contain GC references (although see below).
|
||||
* `GT_OBJ` nodes represent struct types with a handle, and store a pointer to the `ClassLayout` object.
|
||||
* `GT_BLK` nodes represent struct types with no GC references, or opaque blocks of fixed size.
|
||||
* These have no struct handle, resulting in some pessimization or even incorrect
|
||||
code when the appropriate struct handle can't be determined.
|
||||
|
@ -101,12 +94,12 @@ encountered by most phases of the JIT:
|
|||
[#21705](https://github.com/dotnet/coreclr/pull/21705) they are no longer large nodes.
|
||||
* `GT_STORE_OBJ` and `GT_STORE_BLK` have the same structure as `GT_OBJ` and `GT_BLK`, respectively
|
||||
* `Data()` is op2
|
||||
* `GT_DYN_BLK` and `GT_STORE_DYN_BLK` (GenTreeDynBlk extends GenTreeBlk)
|
||||
* `GT_STORE_DYN_BLK` (GenTreeStoreDynBlk extends GenTreeBlk)
|
||||
* Additional child `gtDynamicSize`
|
||||
* Note that these aren't really struct types; they represent dynamically sized blocks
|
||||
* Note that these aren't really struct stores; they represent dynamically sized blocks
|
||||
of arbitrary data.
|
||||
* For `GT_LCL_FLD` nodes, we don't retain shape information, except indirectly via the `FieldSeqNode`.
|
||||
* For `GT_LCL_VAR` nodes, the`ClassLayout` is obtained from the `LclVarDsc`.
|
||||
* For `GT_LCL_FLD` nodes, we store a pointer to `ClassLayout` in the node.
|
||||
* For `GT_LCL_VAR` nodes, the `ClassLayout` is obtained from the `LclVarDsc`.
|
||||
|
||||
### Struct “objects” as rvalues
|
||||
|
||||
|
@ -131,10 +124,6 @@ After morph, a struct-typed value on the RHS of assignment is one of:
|
|||
* `GT_CALL`
|
||||
* `GT_LCL_VAR`
|
||||
* `GT_LCL_FLD`
|
||||
* Note: With `compDoOldStructRetyping()`, a GT_LCL_FLD` with a primitive type of the same size as the struct
|
||||
is used to represent a reference to the full struct when it is passed in a register.
|
||||
This forces the struct to live on the stack, and makes it more difficult to optimize these struct values,
|
||||
which is why this mechanism is being phased out.
|
||||
* `GT_SIMD`
|
||||
* `GT_OBJ` nodes can also be used as rvalues when they are call arguments
|
||||
* Proposed: `GT_OBJ` nodes can be used in any context where a struct rvalue or lvalue might occur,
|
||||
|
@ -173,8 +162,7 @@ There are three main phases in the JIT that make changes to the representation o
|
|||
registers. The necessary transformations for correct code generation would be
|
||||
made in `Lowering`.
|
||||
|
||||
* With `compDoOldStructRetyping()`, if it is passed in a single register, it is morphed into a
|
||||
`GT_LCL_FLD` node of the appropriate primitive type.
|
||||
* If it is passed in a single register, it is morphed into a `GT_LCL_FLD` node of the appropriate primitive type.
|
||||
* This may involve making a copy, if the size cannot be safely loaded.
|
||||
* Proposed: This would remain a `GT_OBJ` and would be appropriately transformed in `Lowering`,
|
||||
e.g. using `GT_BITCAST`.
|
||||
|
@ -310,22 +298,13 @@ This would be enabled first by [Defer ABI-specific transformations to Lowering](
|
|||
for block copies. See [\#21711 Improve init/copy block codegen](https://github.com/dotnet/coreclr/pull/21711).
|
||||
|
||||
* This also includes cleanup of the block morphing methods such that block nodes needn't be visited multiple
|
||||
times, such as `fgMorphBlkToInd` (may be simply unneeded), `fgMorphBlkNode` and `fgMorphBlkOperand`.
|
||||
times, such as `fgMorphBlkNode` and `fgMorphBlkOperand`.
|
||||
These methods were introduced to preserve old behavior, but should be simplified.
|
||||
|
||||
* Somewhat related is the handling of struct-typed array elements. Currently, after the `GT_INDEX` is transformed
|
||||
into a `GT_IND`, that node must be retained as the key into the `ArrayInfoMap`. For structs, this is then
|
||||
wrapped in `OBJ(ADDR(...))`. We should be able to change the IND to OBJ and avoid wrapping, and should also be
|
||||
able to remove the class handle from the array info map and instead used the one provided by the `GT_OBJ`.
|
||||
|
||||
### Miscellaneous Cleanup
|
||||
|
||||
These are all marked with `TODO-1stClassStructs` or `TODO-Cleanup` in the last case:
|
||||
|
||||
* The handling of `DYN_BLK` is unnecessarily complicated to duplicate previous behavior (i.e. to enable previous
|
||||
refactorings to be zero-diff). These nodes are infrequent so the special handling should just be eliminated
|
||||
(e.g. see `GenTree::GetChild()`).
|
||||
|
||||
* The checking at the end of `gtNewTempAssign()` should be simplified.
|
||||
|
||||
* When we create a struct assignment, we use `impAssignStruct()`. This code will, in some cases, create
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue