From e05deac7ea5314ba529b5a04e1210ade07a9e5bd Mon Sep 17 00:00:00 2001 From: TIHan Date: Tue, 31 Jan 2023 19:34:57 -0800 Subject: [PATCH 01/27] Experiment with folding IND(GT_LCL_VAR_ADDR) --- src/coreclr/jit/lclmorph.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index ce52720fe33edf..dcdf600cc93732 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -573,11 +573,36 @@ class LocalAddressVisitor final : public GenTreeVisitor // to the visited node is encountered. fgWalkResult PreOrderVisit(GenTree** use, GenTree* user) { - GenTree* const node = *use; + GenTree* node = *use; if (node->OperIs(GT_IND, GT_FIELD, GT_FIELD_ADDR)) { - MorphStructField(node, user); + if (m_compiler->opts.OptimizationEnabled() && node->OperIs(GT_IND) && + node->gtGetOp1()->OperIs(GT_LCL_VAR_ADDR)) + { + GenTreeLclVar* lclVar = node->gtGetOp1()->AsLclVar(); + + var_types lclType = m_compiler->lvaGetDesc(lclVar)->lvType; + + if ((lclType == TYP_INT) && varTypeIsSmall(node)) + { + lclVar->ChangeOper(GT_LCL_VAR); + lclVar->ChangeType(lclType); + + GenTree* cast = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); + + node = *use = cast; + m_stmtModified = true; + } + else + { + MorphStructField(node, user); + } + } + else + { + MorphStructField(node, user); + } } else if (node->OperIs(GT_LCL_FLD)) { From afdf05665bfc18352f9b3fc5131ab37033c4ede4 Mon Sep 17 00:00:00 2001 From: TIHan Date: Tue, 31 Jan 2023 19:50:32 -0800 Subject: [PATCH 02/27] Fix assertion --- src/coreclr/jit/lclmorph.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index dcdf600cc93732..cff8d98ef1882b 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -589,9 +589,17 @@ class LocalAddressVisitor final : public GenTreeVisitor lclVar->ChangeOper(GT_LCL_VAR); lclVar->ChangeType(lclType); - GenTree* cast = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); + if (user->OperIs(GT_ASG)) + { + node = *use = lclVar; + } + else + { + GenTree* cast = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); + + node = *use = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); + } - node = *use = cast; m_stmtModified = true; } else From 19f19ef6871aeb13c1003367480dc8f324ac2b96 Mon Sep 17 00:00:00 2001 From: TIHan Date: Tue, 31 Jan 2023 19:52:08 -0800 Subject: [PATCH 03/27] Remove duplicate code --- src/coreclr/jit/lclmorph.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index cff8d98ef1882b..1305cc9d188994 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -595,8 +595,6 @@ class LocalAddressVisitor final : public GenTreeVisitor } else { - GenTree* cast = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); - node = *use = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); } From c17e46c70bcb35bf0240f9496208d3811b84920b Mon Sep 17 00:00:00 2001 From: TIHan Date: Wed, 1 Feb 2023 10:53:12 -0800 Subject: [PATCH 04/27] Handling long types --- src/coreclr/jit/lclmorph.cpp | 39 ++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 1305cc9d188994..87937c40b07b6b 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -584,6 +584,18 @@ class LocalAddressVisitor final : public GenTreeVisitor var_types lclType = m_compiler->lvaGetDesc(lclVar)->lvType; + //if (node->TypeIs(lclType)) + //{ + // lclVar->ChangeOper(GT_LCL_VAR); + // lclVar->ChangeType(lclType); + + // *use = lclVar; + + // DEBUG_DESTROY_NODE(node); + + // node = *use; + // m_stmtModified = true; + //} if ((lclType == TYP_INT) && varTypeIsSmall(node)) { lclVar->ChangeOper(GT_LCL_VAR); @@ -591,13 +603,36 @@ class LocalAddressVisitor final : public GenTreeVisitor if (user->OperIs(GT_ASG)) { - node = *use = lclVar; + *use = lclVar; + } + else + { + *use = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); + } + + DEBUG_DESTROY_NODE(node); + + node = *use; + m_stmtModified = true; + } + else if ((lclType == TYP_LONG) && varTypeIsSmall(node)) + { + lclVar->ChangeOper(GT_LCL_VAR); + lclVar->ChangeType(lclType); + + if (user->OperIs(GT_ASG)) + { + *use = lclVar; } else { - node = *use = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); + *use = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, TYP_UINT); + *use = m_compiler->gtNewCastNode(TYP_LONG, *use, varTypeIsSigned(node), TYP_LONG); } + DEBUG_DESTROY_NODE(node); + + node = *use; m_stmtModified = true; } else From 343d82769e46dfc089cb32d932e1248d127b8220 Mon Sep 17 00:00:00 2001 From: TIHan Date: Wed, 1 Feb 2023 11:19:12 -0800 Subject: [PATCH 05/27] Handling long types --- src/coreclr/jit/lclmorph.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 87937c40b07b6b..c38eea359b102a 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -626,8 +626,8 @@ class LocalAddressVisitor final : public GenTreeVisitor } else { - *use = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, TYP_UINT); - *use = m_compiler->gtNewCastNode(TYP_LONG, *use, varTypeIsSigned(node), TYP_LONG); + *use = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); + *use = m_compiler->gtNewCastNode(TYP_LONG, *use, varTypeIsUnsigned(node), TYP_LONG); } DEBUG_DESTROY_NODE(node); From 3a141c0d9a66479e5b70da0555faeb8cd603b706 Mon Sep 17 00:00:00 2001 From: TIHan Date: Wed, 1 Feb 2023 11:25:29 -0800 Subject: [PATCH 06/27] Handling long types --- src/coreclr/jit/lclmorph.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index c38eea359b102a..8aa01a50fea79a 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -627,7 +627,6 @@ class LocalAddressVisitor final : public GenTreeVisitor else { *use = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); - *use = m_compiler->gtNewCastNode(TYP_LONG, *use, varTypeIsUnsigned(node), TYP_LONG); } DEBUG_DESTROY_NODE(node); From af037ec510270eac5bd69d352213ec36c0861c8f Mon Sep 17 00:00:00 2001 From: TIHan Date: Wed, 1 Feb 2023 12:02:38 -0800 Subject: [PATCH 07/27] Handling long types --- src/coreclr/jit/lclmorph.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 8aa01a50fea79a..f409e2aad99fad 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -624,6 +624,13 @@ class LocalAddressVisitor final : public GenTreeVisitor { *use = lclVar; } + else if (user->OperIs(GT_CAST)) + { + *use = lclVar; + user->AsCast()->gtCastType = node->TypeGet(); + user->ClearUnsigned(); + user->ChangeType(TYP_INT); + } else { *use = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); From 936dbae6517a6247b433c7548b3da0482fc4be1c Mon Sep 17 00:00:00 2001 From: TIHan Date: Wed, 1 Feb 2023 14:19:23 -0800 Subject: [PATCH 08/27] Trying to fix build --- src/coreclr/jit/lclmorph.cpp | 134 +++++++++++++++++------------------ 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index f409e2aad99fad..eefa95ecf6120d 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -565,91 +565,91 @@ class LocalAddressVisitor final : public GenTreeVisitor #endif // DEBUG } - // Morph promoted struct fields and count local occurrences. - // - // Also create and push the value produced by the visited node. This is done here - // rather than in PostOrderVisit because it makes it easy to handle nodes with an - // arbitrary number of operands - just pop values until the value corresponding - // to the visited node is encountered. - fgWalkResult PreOrderVisit(GenTree** use, GenTree* user) + GenTree* OptimizeIndir(GenTree* tree, GenTree* parent) { - GenTree* node = *use; + assert(tree->OperIs(GT_IND)); - if (node->OperIs(GT_IND, GT_FIELD, GT_FIELD_ADDR)) - { - if (m_compiler->opts.OptimizationEnabled() && node->OperIs(GT_IND) && - node->gtGetOp1()->OperIs(GT_LCL_VAR_ADDR)) - { - GenTreeLclVar* lclVar = node->gtGetOp1()->AsLclVar(); - - var_types lclType = m_compiler->lvaGetDesc(lclVar)->lvType; + if (m_compiler->opts.OptimizationDisabled()) + return tree; - //if (node->TypeIs(lclType)) - //{ - // lclVar->ChangeOper(GT_LCL_VAR); - // lclVar->ChangeType(lclType); + if ((parent != nullptr) && parent->OperIs(GT_CAST)) + return tree; - // *use = lclVar; - - // DEBUG_DESTROY_NODE(node); + if (tree->gtGetOp1()->OperIs(GT_LCL_VAR_ADDR)) + { + GenTreeLclVar* lclVar = tree->gtGetOp1()->AsLclVar(); + var_types lclType = m_compiler->lvaGetDesc(lclVar)->lvType; - // node = *use; - // m_stmtModified = true; - //} - if ((lclType == TYP_INT) && varTypeIsSmall(node)) - { - lclVar->ChangeOper(GT_LCL_VAR); - lclVar->ChangeType(lclType); + if (tree->TypeIs(lclType)) + { + lclVar->ChangeOper(GT_LCL_VAR); + lclVar->ChangeType(lclType); - if (user->OperIs(GT_ASG)) - { - *use = lclVar; - } - else - { - *use = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); - } + DEBUG_DESTROY_NODE(tree); - DEBUG_DESTROY_NODE(node); + return lclVar; + } + if ((lclType == TYP_INT) && varTypeIsSmall(tree)) + { + lclVar->ChangeOper(GT_LCL_VAR); + lclVar->ChangeType(lclType); - node = *use; - m_stmtModified = true; + GenTree* newTree; + if ((parent != nullptr) && parent->OperIs(GT_ASG)) + { + newTree = lclVar; } - else if ((lclType == TYP_LONG) && varTypeIsSmall(node)) + else { - lclVar->ChangeOper(GT_LCL_VAR); - lclVar->ChangeType(lclType); + newTree = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, tree->TypeGet()); + } - if (user->OperIs(GT_ASG)) - { - *use = lclVar; - } - else if (user->OperIs(GT_CAST)) - { - *use = lclVar; - user->AsCast()->gtCastType = node->TypeGet(); - user->ClearUnsigned(); - user->ChangeType(TYP_INT); - } - else - { - *use = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, node->TypeGet()); - } + DEBUG_DESTROY_NODE(tree); - DEBUG_DESTROY_NODE(node); + return newTree; + } + else if ((lclType == TYP_LONG) && varTypeIsSmall(tree)) + { + lclVar->ChangeOper(GT_LCL_VAR); + lclVar->ChangeType(lclType); - node = *use; - m_stmtModified = true; + GenTree* newTree; + if ((parent != nullptr) && parent->OperIs(GT_ASG)) + { + newTree = lclVar; } else { - MorphStructField(node, user); + newTree = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, tree->TypeGet()); } + + DEBUG_DESTROY_NODE(tree); + + return newTree; } - else - { - MorphStructField(node, user); - } + } + + return tree; + } + + // Morph promoted struct fields and count local occurrences. + // + // Also create and push the value produced by the visited node. This is done here + // rather than in PostOrderVisit because it makes it easy to handle nodes with an + // arbitrary number of operands - just pop values until the value corresponding + // to the visited node is encountered. + fgWalkResult PreOrderVisit(GenTree** use, GenTree* user) + { + GenTree* node = *use; + + if (node->OperIs(GT_IND)) + { + node = *use = OptimizeIndir(node, user); + } + + if (node->OperIs(GT_IND, GT_FIELD, GT_FIELD_ADDR)) + { + MorphStructField(node, user); } else if (node->OperIs(GT_LCL_FLD)) { From 69ff4b2a8ffdab89758339004753790ffc82b493 Mon Sep 17 00:00:00 2001 From: TIHan Date: Wed, 1 Feb 2023 14:31:08 -0800 Subject: [PATCH 09/27] Trying to fix build --- src/coreclr/jit/lclmorph.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index eefa95ecf6120d..75977efe2097e9 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -565,15 +565,15 @@ class LocalAddressVisitor final : public GenTreeVisitor #endif // DEBUG } - GenTree* OptimizeIndir(GenTree* tree, GenTree* parent) + GenTree* TryOptimizeIndir(GenTree* tree, GenTree* parent) { assert(tree->OperIs(GT_IND)); if (m_compiler->opts.OptimizationDisabled()) - return tree; + return nullptr; if ((parent != nullptr) && parent->OperIs(GT_CAST)) - return tree; + return nullptr; if (tree->gtGetOp1()->OperIs(GT_LCL_VAR_ADDR)) { @@ -589,7 +589,7 @@ class LocalAddressVisitor final : public GenTreeVisitor return lclVar; } - if ((lclType == TYP_INT) && varTypeIsSmall(tree)) + else if ((lclType == TYP_INT) && varTypeIsSmall(tree)) { lclVar->ChangeOper(GT_LCL_VAR); lclVar->ChangeType(lclType); @@ -629,7 +629,7 @@ class LocalAddressVisitor final : public GenTreeVisitor } } - return tree; + return nullptr; } // Morph promoted struct fields and count local occurrences. @@ -644,7 +644,12 @@ class LocalAddressVisitor final : public GenTreeVisitor if (node->OperIs(GT_IND)) { - node = *use = OptimizeIndir(node, user); + GenTree* optimizedNode = TryOptimizeIndir(node, user); + if (optimizedNode != nullptr) + { + node = *use = optimizedNode; + m_stmtModified = true; + } } if (node->OperIs(GT_IND, GT_FIELD, GT_FIELD_ADDR)) From be3674c2e210883440d8b22c091f4772ddc5a5e3 Mon Sep 17 00:00:00 2001 From: TIHan Date: Fri, 3 Feb 2023 14:46:39 -0800 Subject: [PATCH 10/27] Trying to fix builds --- src/coreclr/jit/lclmorph.cpp | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 75977efe2097e9..3a86a114b2b37b 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -580,16 +580,7 @@ class LocalAddressVisitor final : public GenTreeVisitor GenTreeLclVar* lclVar = tree->gtGetOp1()->AsLclVar(); var_types lclType = m_compiler->lvaGetDesc(lclVar)->lvType; - if (tree->TypeIs(lclType)) - { - lclVar->ChangeOper(GT_LCL_VAR); - lclVar->ChangeType(lclType); - - DEBUG_DESTROY_NODE(tree); - - return lclVar; - } - else if ((lclType == TYP_INT) && varTypeIsSmall(tree)) + if ((lclType == TYP_INT) && varTypeIsSmall(tree)) { lclVar->ChangeOper(GT_LCL_VAR); lclVar->ChangeType(lclType); @@ -606,25 +597,6 @@ class LocalAddressVisitor final : public GenTreeVisitor DEBUG_DESTROY_NODE(tree); - return newTree; - } - else if ((lclType == TYP_LONG) && varTypeIsSmall(tree)) - { - lclVar->ChangeOper(GT_LCL_VAR); - lclVar->ChangeType(lclType); - - GenTree* newTree; - if ((parent != nullptr) && parent->OperIs(GT_ASG)) - { - newTree = lclVar; - } - else - { - newTree = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, tree->TypeGet()); - } - - DEBUG_DESTROY_NODE(tree); - return newTree; } } From 832666e45b38128bfc5497dcd25c2451d05f810b Mon Sep 17 00:00:00 2001 From: TIHan Date: Fri, 3 Feb 2023 17:52:00 -0800 Subject: [PATCH 11/27] Added IndirTransform::CastOfLclVar --- src/coreclr/jit/lclmorph.cpp | 94 ++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 52 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 5eea80b6373860..49d1b84bef5027 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -469,7 +469,8 @@ class LocalAddressVisitor final : public GenTreeVisitor WithElement, #endif // FEATURE_HW_INTRINSICS LclVar, - LclFld + LclFld, + CastOfLclVar }; ArrayStack m_valueStack; @@ -565,45 +566,6 @@ class LocalAddressVisitor final : public GenTreeVisitor #endif // DEBUG } - GenTree* TryOptimizeIndir(GenTree* tree, GenTree* parent) - { - assert(tree->OperIs(GT_IND)); - - if (m_compiler->opts.OptimizationDisabled()) - return nullptr; - - if ((parent != nullptr) && parent->OperIs(GT_CAST)) - return nullptr; - - if (tree->gtGetOp1()->OperIs(GT_LCL_VAR_ADDR)) - { - GenTreeLclVar* lclVar = tree->gtGetOp1()->AsLclVar(); - var_types lclType = m_compiler->lvaGetDesc(lclVar)->lvType; - - if ((lclType == TYP_INT) && varTypeIsSmall(tree)) - { - lclVar->ChangeOper(GT_LCL_VAR); - lclVar->ChangeType(lclType); - - GenTree* newTree; - if ((parent != nullptr) && parent->OperIs(GT_ASG)) - { - newTree = lclVar; - } - else - { - newTree = m_compiler->gtNewCastNode(TYP_INT, lclVar, false, tree->TypeGet()); - } - - DEBUG_DESTROY_NODE(tree); - - return newTree; - } - } - - return nullptr; - } - // Morph promoted struct fields and count local occurrences. // // Also create and push the value produced by the visited node. This is done here @@ -612,17 +574,7 @@ class LocalAddressVisitor final : public GenTreeVisitor // to the visited node is encountered. fgWalkResult PreOrderVisit(GenTree** use, GenTree* user) { - GenTree* node = *use; - - if (node->OperIs(GT_IND)) - { - GenTree* optimizedNode = TryOptimizeIndir(node, user); - if (optimizedNode != nullptr) - { - node = *use = optimizedNode; - m_stmtModified = true; - } - } + GenTree* const node = *use; if (node->OperIs(GT_IND, GT_FIELD, GT_FIELD_ADDR)) { @@ -1187,6 +1139,11 @@ class LocalAddressVisitor final : public GenTreeVisitor unsigned lclNum = val.LclNum(); LclVarDsc* varDsc = m_compiler->lvaGetDesc(lclNum); GenTreeLclVarCommon* lclNode = nullptr; + bool isDef = user->OperIs(GT_ASG) && (user->AsOp()->gtGetOp1() == indir); + +#ifdef DEBUG + bool removeIndir = false; +#endif // DEBUG switch (transform) { @@ -1285,6 +1242,23 @@ class LocalAddressVisitor final : public GenTreeVisitor lclNode = indir->AsLclVarCommon(); break; + case IndirTransform::CastOfLclVar: + assert(varTypeIsSmall(indir)); + assert(varTypeIsIntegral(varDsc->TypeGet())); + assert(*val.Use() == indir); + + removeIndir = true; + lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); + if (isDef) + { + *val.Use() = lclNode; + } + else + { + *val.Use() = m_compiler->gtNewCastNode(varDsc->TypeGet(), lclNode, false, indir->TypeGet()); + } + break; + case IndirTransform::LclFld: indir->ChangeOper(GT_LCL_FLD); indir->AsLclFld()->SetLclNum(lclNum); @@ -1307,7 +1281,7 @@ class LocalAddressVisitor final : public GenTreeVisitor GenTreeFlags lclNodeFlags = GTF_EMPTY; - if (user->OperIs(GT_ASG) && (user->AsOp()->gtGetOp1() == indir)) + if (isDef) { lclNodeFlags |= (GTF_VAR_DEF | GTF_DONT_CSE); @@ -1325,6 +1299,15 @@ class LocalAddressVisitor final : public GenTreeVisitor lclNode->gtFlags = lclNodeFlags; m_stmtModified = true; + +#ifdef DEBUG + if (removeIndir) + { + DEBUG_DESTROY_NODE(indir); + } +#endif // DEBUG + + return; } //------------------------------------------------------------------------ @@ -1368,6 +1351,11 @@ class LocalAddressVisitor final : public GenTreeVisitor return IndirTransform::LclVar; } + if (varTypeIsSmall(indir) && varTypeIsIntegral(varDsc->TypeGet()) && !varTypeIsLong(varDsc->TypeGet())) + { + return IndirTransform::CastOfLclVar; + } + bool isDef = user->OperIs(GT_ASG) && (user->gtGetOp1() == indir); // For small locals on the LHS we can ignore the signed/unsigned diff. @@ -1551,6 +1539,8 @@ class LocalAddressVisitor final : public GenTreeVisitor m_stmtModified = true; } } + + return; } //------------------------------------------------------------------------ From 579b41528fefdbb84c66a196144d80b17a393d63 Mon Sep 17 00:00:00 2001 From: TIHan Date: Fri, 3 Feb 2023 17:54:59 -0800 Subject: [PATCH 12/27] Fixing build --- src/coreclr/jit/lclmorph.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 49d1b84bef5027..7897126608c8b3 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1247,7 +1247,9 @@ class LocalAddressVisitor final : public GenTreeVisitor assert(varTypeIsIntegral(varDsc->TypeGet())); assert(*val.Use() == indir); +#ifdef DEBUG removeIndir = true; +#endif // DEBUG lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); if (isDef) { From 054c955d34ba0be075b9809a87c6a08463f91ca6 Mon Sep 17 00:00:00 2001 From: TIHan Date: Fri, 3 Feb 2023 18:12:01 -0800 Subject: [PATCH 13/27] Some formatting --- src/coreclr/jit/lclmorph.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 7897126608c8b3..85a7e489ec1422 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1250,7 +1250,7 @@ class LocalAddressVisitor final : public GenTreeVisitor #ifdef DEBUG removeIndir = true; #endif // DEBUG - lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); + lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); if (isDef) { *val.Use() = lclNode; @@ -1353,11 +1353,6 @@ class LocalAddressVisitor final : public GenTreeVisitor return IndirTransform::LclVar; } - if (varTypeIsSmall(indir) && varTypeIsIntegral(varDsc->TypeGet()) && !varTypeIsLong(varDsc->TypeGet())) - { - return IndirTransform::CastOfLclVar; - } - bool isDef = user->OperIs(GT_ASG) && (user->gtGetOp1() == indir); // For small locals on the LHS we can ignore the signed/unsigned diff. @@ -1372,6 +1367,11 @@ class LocalAddressVisitor final : public GenTreeVisitor return IndirTransform::LclFld; } + if (varTypeIsSmall(indir) && varTypeIsIntegral(varDsc->TypeGet()) && !varTypeIsLong(varDsc->TypeGet())) + { + return IndirTransform::CastOfLclVar; + } + #ifdef FEATURE_HW_INTRINSICS if (varTypeIsSIMD(varDsc)) { From 04429cb2970bc409c42e529811b51a460d64e146 Mon Sep 17 00:00:00 2001 From: TIHan Date: Fri, 3 Feb 2023 19:37:55 -0800 Subject: [PATCH 14/27] Skip isDef --- src/coreclr/jit/lclmorph.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 85a7e489ec1422..e7ccf565bf1aba 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1244,21 +1244,15 @@ class LocalAddressVisitor final : public GenTreeVisitor case IndirTransform::CastOfLclVar: assert(varTypeIsSmall(indir)); - assert(varTypeIsIntegral(varDsc->TypeGet())); + assert(varTypeIsIntegral(varDsc)); assert(*val.Use() == indir); + assert(!isDef); #ifdef DEBUG removeIndir = true; #endif // DEBUG - lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); - if (isDef) - { - *val.Use() = lclNode; - } - else - { - *val.Use() = m_compiler->gtNewCastNode(varDsc->TypeGet(), lclNode, false, indir->TypeGet()); - } + lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); + *val.Use() = m_compiler->gtNewCastNode(TYP_INT, lclNode, false, indir->TypeGet()); break; case IndirTransform::LclFld: @@ -1367,7 +1361,11 @@ class LocalAddressVisitor final : public GenTreeVisitor return IndirTransform::LclFld; } - if (varTypeIsSmall(indir) && varTypeIsIntegral(varDsc->TypeGet()) && !varTypeIsLong(varDsc->TypeGet())) +#ifdef TARGET_64BIT + if (!isDef && varTypeIsSmall(indir) && varTypeIsIntegral(varDsc) && !varTypeIsLong(varDsc)) +#else // TARGET_64BIT + if (!isDef && varTypeIsSmall(indir) && varTypeIsIntegral(varDsc) && !varTypeIsLong(varDsc)) +#endif // !TARGET_64BIT { return IndirTransform::CastOfLclVar; } From 3a96f83c852d48962a17fa6e64de64951e54b90d Mon Sep 17 00:00:00 2001 From: TIHan Date: Fri, 3 Feb 2023 19:43:26 -0800 Subject: [PATCH 15/27] Formatting --- src/coreclr/jit/lclmorph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index e7ccf565bf1aba..76a56277d560d4 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1251,7 +1251,7 @@ class LocalAddressVisitor final : public GenTreeVisitor #ifdef DEBUG removeIndir = true; #endif // DEBUG - lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); + lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); *val.Use() = m_compiler->gtNewCastNode(TYP_INT, lclNode, false, indir->TypeGet()); break; From 9e1299297554325a6d517e1f2d7db817b193db9c Mon Sep 17 00:00:00 2001 From: TIHan Date: Fri, 3 Feb 2023 20:04:47 -0800 Subject: [PATCH 16/27] Fixed AV --- src/coreclr/jit/lclmorph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 76a56277d560d4..ea09e23a7ca4e0 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1139,7 +1139,7 @@ class LocalAddressVisitor final : public GenTreeVisitor unsigned lclNum = val.LclNum(); LclVarDsc* varDsc = m_compiler->lvaGetDesc(lclNum); GenTreeLclVarCommon* lclNode = nullptr; - bool isDef = user->OperIs(GT_ASG) && (user->AsOp()->gtGetOp1() == indir); + bool isDef = (user != nullptr) && user->OperIs(GT_ASG) && (user->AsOp()->gtGetOp1() == indir); #ifdef DEBUG bool removeIndir = false; From e40b1b72b8ead6c27aadd57bacf307b4bd6bfb9a Mon Sep 17 00:00:00 2001 From: TIHan Date: Mon, 6 Feb 2023 10:37:16 -0800 Subject: [PATCH 17/27] Enable long --- src/coreclr/jit/lclmorph.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index ea09e23a7ca4e0..cbe46161a8d80f 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1302,8 +1302,6 @@ class LocalAddressVisitor final : public GenTreeVisitor DEBUG_DESTROY_NODE(indir); } #endif // DEBUG - - return; } //------------------------------------------------------------------------ @@ -1362,7 +1360,7 @@ class LocalAddressVisitor final : public GenTreeVisitor } #ifdef TARGET_64BIT - if (!isDef && varTypeIsSmall(indir) && varTypeIsIntegral(varDsc) && !varTypeIsLong(varDsc)) + if (!isDef && varTypeIsSmall(indir) && varTypeIsIntegral(varDsc)) #else // TARGET_64BIT if (!isDef && varTypeIsSmall(indir) && varTypeIsIntegral(varDsc) && !varTypeIsLong(varDsc)) #endif // !TARGET_64BIT From e81aad1b4eb36ccec86ac9571f9f922e68c50bae Mon Sep 17 00:00:00 2001 From: TIHan Date: Mon, 6 Feb 2023 17:22:39 -0800 Subject: [PATCH 18/27] Renamed CastOfLclVar to NarrowCastOfLclVar --- src/coreclr/jit/lclmorph.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index cbe46161a8d80f..8049fc8ae7b5a1 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -470,7 +470,7 @@ class LocalAddressVisitor final : public GenTreeVisitor #endif // FEATURE_HW_INTRINSICS LclVar, LclFld, - CastOfLclVar + NarrowCastOfLclVar }; ArrayStack m_valueStack; @@ -1242,17 +1242,22 @@ class LocalAddressVisitor final : public GenTreeVisitor lclNode = indir->AsLclVarCommon(); break; - case IndirTransform::CastOfLclVar: - assert(varTypeIsSmall(indir)); + case IndirTransform::NarrowCastOfLclVar: + assert(varTypeIsIntegral(indir)); assert(varTypeIsIntegral(varDsc)); assert(*val.Use() == indir); assert(!isDef); + lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); + *val.Use() = m_compiler->gtNewCastNode(genActualType(indir), lclNode, false, indir->TypeGet()); + + // Check to make sure this is narrow. + assert(genTypeSize(lclNode) >= genTypeSize(indir)); + #ifdef DEBUG removeIndir = true; #endif // DEBUG - lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); - *val.Use() = m_compiler->gtNewCastNode(TYP_INT, lclNode, false, indir->TypeGet()); + break; case IndirTransform::LclFld: @@ -1360,12 +1365,12 @@ class LocalAddressVisitor final : public GenTreeVisitor } #ifdef TARGET_64BIT - if (!isDef && varTypeIsSmall(indir) && varTypeIsIntegral(varDsc)) + if (!isDef && varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc)) #else // TARGET_64BIT - if (!isDef && varTypeIsSmall(indir) && varTypeIsIntegral(varDsc) && !varTypeIsLong(varDsc)) + if (!isDef && varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc) && !varTypeIsLong(varDsc)) #endif // !TARGET_64BIT { - return IndirTransform::CastOfLclVar; + return IndirTransform::NarrowCastOfLclVar; } #ifdef FEATURE_HW_INTRINSICS From a4b8bd84ce86bba1eb2c32efb4b1f06b8f4b76bf Mon Sep 17 00:00:00 2001 From: TIHan Date: Mon, 6 Feb 2023 18:05:06 -0800 Subject: [PATCH 19/27] Trying out wide-cast ind(lcl_var_addr) => cast(lcl_var) --- src/coreclr/jit/lclmorph.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 8049fc8ae7b5a1..c10ba5b4836bce 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1001,10 +1001,25 @@ class LocalAddressVisitor final : public GenTreeVisitor if (isWide) { - m_compiler->lvaSetVarAddrExposed(varDsc->lvIsStructField - ? varDsc->lvParentLcl - : val.LclNum() DEBUGARG(AddressExposedReason::WIDE_INDIR)); - MorphWideLocalIndir(val); + bool isDef = (user != nullptr) && user->OperIs(GT_ASG) && (user->AsOp()->gtGetOp1() == node); + + if (m_compiler->opts.OptimizationEnabled() && !isDef && node->OperIs(GT_IND) && varTypeIsIntegral(node) && + varTypeIsIntegral(varDsc)) + { + GenTree* lclNode = BashToLclVar(node->gtGetOp1(), lclNum); + *val.Use() = m_compiler->gtNewCastNode(genActualType(node), lclNode, false, node->TypeGet()); + + DEBUG_DESTROY_NODE(node); + + m_stmtModified = true; + } + else + { + m_compiler->lvaSetVarAddrExposed(varDsc->lvIsStructField + ? varDsc->lvParentLcl + : val.LclNum() DEBUGARG(AddressExposedReason::WIDE_INDIR)); + MorphWideLocalIndir(val); + } } else { From 8ebd1ef8a2f3a264b17bdf22515894f245bd3b27 Mon Sep 17 00:00:00 2001 From: TIHan Date: Mon, 6 Feb 2023 19:42:02 -0800 Subject: [PATCH 20/27] Formatting --- src/coreclr/jit/lclmorph.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index c10ba5b4836bce..417a66327f284c 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1003,8 +1003,8 @@ class LocalAddressVisitor final : public GenTreeVisitor { bool isDef = (user != nullptr) && user->OperIs(GT_ASG) && (user->AsOp()->gtGetOp1() == node); - if (m_compiler->opts.OptimizationEnabled() && !isDef && node->OperIs(GT_IND) && varTypeIsIntegral(node) && - varTypeIsIntegral(varDsc)) + if (m_compiler->opts.OptimizationEnabled() && !isDef && node->OperIs(GT_IND) && + node->gtGetOp1()->OperIs(GT_LCL_VAR_ADDR) && varTypeIsIntegral(node) && varTypeIsIntegral(varDsc)) { GenTree* lclNode = BashToLclVar(node->gtGetOp1(), lclNum); *val.Use() = m_compiler->gtNewCastNode(genActualType(node), lclNode, false, node->TypeGet()); @@ -1381,7 +1381,7 @@ class LocalAddressVisitor final : public GenTreeVisitor #ifdef TARGET_64BIT if (!isDef && varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc)) -#else // TARGET_64BIT +#else // TARGET_64BIT if (!isDef && varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc) && !varTypeIsLong(varDsc)) #endif // !TARGET_64BIT { @@ -1557,8 +1557,6 @@ class LocalAddressVisitor final : public GenTreeVisitor m_stmtModified = true; } } - - return; } //------------------------------------------------------------------------ From 73ffc26ff3deefa9d4dd20a7c2a264c5277e0825 Mon Sep 17 00:00:00 2001 From: TIHan Date: Mon, 6 Feb 2023 20:02:55 -0800 Subject: [PATCH 21/27] Remove widening --- src/coreclr/jit/lclmorph.cpp | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 417a66327f284c..5b3cbdf1179503 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1001,25 +1001,10 @@ class LocalAddressVisitor final : public GenTreeVisitor if (isWide) { - bool isDef = (user != nullptr) && user->OperIs(GT_ASG) && (user->AsOp()->gtGetOp1() == node); - - if (m_compiler->opts.OptimizationEnabled() && !isDef && node->OperIs(GT_IND) && - node->gtGetOp1()->OperIs(GT_LCL_VAR_ADDR) && varTypeIsIntegral(node) && varTypeIsIntegral(varDsc)) - { - GenTree* lclNode = BashToLclVar(node->gtGetOp1(), lclNum); - *val.Use() = m_compiler->gtNewCastNode(genActualType(node), lclNode, false, node->TypeGet()); - - DEBUG_DESTROY_NODE(node); - - m_stmtModified = true; - } - else - { - m_compiler->lvaSetVarAddrExposed(varDsc->lvIsStructField - ? varDsc->lvParentLcl - : val.LclNum() DEBUGARG(AddressExposedReason::WIDE_INDIR)); - MorphWideLocalIndir(val); - } + m_compiler->lvaSetVarAddrExposed(varDsc->lvIsStructField + ? varDsc->lvParentLcl + : val.LclNum() DEBUGARG(AddressExposedReason::WIDE_INDIR)); + MorphWideLocalIndir(val); } else { From 97b7bf162457c4d32bec61bc814a7a6143f4551e Mon Sep 17 00:00:00 2001 From: TIHan Date: Tue, 14 Feb 2023 15:20:57 -0800 Subject: [PATCH 22/27] Added a comment. Added disasm tests. --- src/coreclr/jit/lclmorph.cpp | 5 +- src/tests/JIT/opt/Unsafe/Unsafe.cs | 112 +++++++++++++++++++++++++ src/tests/JIT/opt/Unsafe/Unsafe.csproj | 17 ++++ 3 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 src/tests/JIT/opt/Unsafe/Unsafe.cs create mode 100644 src/tests/JIT/opt/Unsafe/Unsafe.csproj diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index b2477680ef834f..be92613c972329 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -464,13 +464,13 @@ class LocalAddressVisitor final : public GenTreeVisitor None, Nop, BitCast, + NarrowCastOfLclVar, #ifdef FEATURE_HW_INTRINSICS GetElement, WithElement, #endif // FEATURE_HW_INTRINSICS LclVar, - LclFld, - NarrowCastOfLclVar + LclFld }; ArrayStack m_valueStack; @@ -1375,6 +1375,7 @@ class LocalAddressVisitor final : public GenTreeVisitor #ifdef TARGET_64BIT if (!isDef && varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc)) #else // TARGET_64BIT + // For non-64bit targets, do not do this for long types. if (!isDef && varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc) && !varTypeIsLong(varDsc)) #endif // !TARGET_64BIT { diff --git a/src/tests/JIT/opt/Unsafe/Unsafe.cs b/src/tests/JIT/opt/Unsafe/Unsafe.cs new file mode 100644 index 00000000000000..7ea7d89b76f2b6 --- /dev/null +++ b/src/tests/JIT/opt/Unsafe/Unsafe.cs @@ -0,0 +1,112 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; + +namespace CodeGenTests +{ + class IntOr + { + [MethodImpl(MethodImplOptions.NoInlining)] + static void SideEffect() + { + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static bool Test_UInt32_UInt32_CastByte_Or(uint x, uint y) + { + // X64-NOT: movzx + + // We expect 'or reg8, reg8'. + // X64: or {{[a-z]+[l|b]}}, {{[a-z]+[l|b]}} + + if ((byte)((byte)x | y) == 0) + { + SideEffect(); + return true; + } + return false; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static bool Test_UInt32_ByRef_CastByte_CastByte_Or(uint x, ref uint y) + { + // X64-NOT: movzx + + // We expect 'or reg8, mem8'. + // X64: or {{[a-z]+[l|b]}}, byte ptr + + if ((byte)((byte)x | (byte)y) == 0) + { + SideEffect(); + return true; + } + return false; + } + + static int Main() + { + uint leftMostBit = 0b10000000000000000000000000000000; + uint rightMostBit = 0b00000000000000000000000000000001; + uint noBits = 0b00000000000000000000000000000000; + + if (!Test_UInt32_UInt32_CastByte_Or(leftMostBit, leftMostBit)) + return 0; + + if (Test_UInt32_UInt32_CastByte_Or(leftMostBit, rightMostBit)) + return 0; + + if (!Test_UInt32_UInt32_CastByte_Or(leftMostBit, noBits)) + return 0; + + if (Test_UInt32_UInt32_CastByte_Or(rightMostBit, leftMostBit)) + return 0; + + if (Test_UInt32_UInt32_CastByte_Or(rightMostBit, rightMostBit)) + return 0; + + if (Test_UInt32_UInt32_CastByte_Or(rightMostBit, noBits)) + return 0; + + if (!Test_UInt32_UInt32_CastByte_Or(noBits, leftMostBit)) + return 0; + + if (Test_UInt32_UInt32_CastByte_Or(noBits, rightMostBit)) + return 0; + + if (!Test_UInt32_UInt32_CastByte_Or(noBits, noBits)) + return 0; + + // ByRef + if (!Test_UInt32_ByRef_CastByte_CastByte_Or(leftMostBit, ref leftMostBit)) + return 0; + + if (Test_UInt32_ByRef_CastByte_CastByte_Or(leftMostBit, ref rightMostBit)) + return 0; + + if (!Test_UInt32_ByRef_CastByte_CastByte_Or(leftMostBit, ref noBits)) + return 0; + + if (Test_UInt32_ByRef_CastByte_CastByte_Or(rightMostBit, ref leftMostBit)) + return 0; + + if (Test_UInt32_ByRef_CastByte_CastByte_Or(rightMostBit, ref rightMostBit)) + return 0; + + if (Test_UInt32_ByRef_CastByte_CastByte_Or(rightMostBit, ref noBits)) + return 0; + + if (!Test_UInt32_ByRef_CastByte_CastByte_Or(noBits, ref leftMostBit)) + return 0; + + if (Test_UInt32_ByRef_CastByte_CastByte_Or(noBits, ref rightMostBit)) + return 0; + + if (!Test_UInt32_ByRef_CastByte_CastByte_Or(noBits, ref noBits)) + return 0; + + return 100; + } + } +} diff --git a/src/tests/JIT/opt/Unsafe/Unsafe.csproj b/src/tests/JIT/opt/Unsafe/Unsafe.csproj new file mode 100644 index 00000000000000..42a89c8384d74e --- /dev/null +++ b/src/tests/JIT/opt/Unsafe/Unsafe.csproj @@ -0,0 +1,17 @@ + + + Exe + + + None + True + + + + true + + + + + + From d48d744115055a8ffa535d56ee35a8af6b5121ac Mon Sep 17 00:00:00 2001 From: TIHan Date: Tue, 14 Feb 2023 15:21:56 -0800 Subject: [PATCH 23/27] Fixing tests --- src/tests/JIT/opt/Unsafe/Unsafe.cs | 92 +++++------------------------- 1 file changed, 13 insertions(+), 79 deletions(-) diff --git a/src/tests/JIT/opt/Unsafe/Unsafe.cs b/src/tests/JIT/opt/Unsafe/Unsafe.cs index 7ea7d89b76f2b6..dd9134b5125cc0 100644 --- a/src/tests/JIT/opt/Unsafe/Unsafe.cs +++ b/src/tests/JIT/opt/Unsafe/Unsafe.cs @@ -6,104 +6,38 @@ namespace CodeGenTests { - class IntOr + class UnsafeTests { [MethodImpl(MethodImplOptions.NoInlining)] - static void SideEffect() + static byte UnsafeAsNarrowCast_Short(short value) { + // X64-NOT: dword ptr + return Unsafe.As(ref value); } [MethodImpl(MethodImplOptions.NoInlining)] - public static bool Test_UInt32_UInt32_CastByte_Or(uint x, uint y) + static byte UnsafeAsNarrowCast_Int(int value) { - // X64-NOT: movzx - - // We expect 'or reg8, reg8'. - // X64: or {{[a-z]+[l|b]}}, {{[a-z]+[l|b]}} - - if ((byte)((byte)x | y) == 0) - { - SideEffect(); - return true; - } - return false; + // X64-NOT: dword ptr + return Unsafe.As(ref value); } [MethodImpl(MethodImplOptions.NoInlining)] - public static bool Test_UInt32_ByRef_CastByte_CastByte_Or(uint x, ref uint y) + static byte UnsafeAsNarrowCast_Long(long value) { - // X64-NOT: movzx - - // We expect 'or reg8, mem8'. - // X64: or {{[a-z]+[l|b]}}, byte ptr - - if ((byte)((byte)x | (byte)y) == 0) - { - SideEffect(); - return true; - } - return false; + // X64-NOT: qword ptr + return Unsafe.As(ref value); } static int Main() { - uint leftMostBit = 0b10000000000000000000000000000000; - uint rightMostBit = 0b00000000000000000000000000000001; - uint noBits = 0b00000000000000000000000000000000; - - if (!Test_UInt32_UInt32_CastByte_Or(leftMostBit, leftMostBit)) - return 0; - - if (Test_UInt32_UInt32_CastByte_Or(leftMostBit, rightMostBit)) - return 0; - - if (!Test_UInt32_UInt32_CastByte_Or(leftMostBit, noBits)) - return 0; - - if (Test_UInt32_UInt32_CastByte_Or(rightMostBit, leftMostBit)) - return 0; - - if (Test_UInt32_UInt32_CastByte_Or(rightMostBit, rightMostBit)) - return 0; - - if (Test_UInt32_UInt32_CastByte_Or(rightMostBit, noBits)) - return 0; - - if (!Test_UInt32_UInt32_CastByte_Or(noBits, leftMostBit)) - return 0; - - if (Test_UInt32_UInt32_CastByte_Or(noBits, rightMostBit)) - return 0; - - if (!Test_UInt32_UInt32_CastByte_Or(noBits, noBits)) - return 0; - - // ByRef - if (!Test_UInt32_ByRef_CastByte_CastByte_Or(leftMostBit, ref leftMostBit)) - return 0; - - if (Test_UInt32_ByRef_CastByte_CastByte_Or(leftMostBit, ref rightMostBit)) - return 0; - - if (!Test_UInt32_ByRef_CastByte_CastByte_Or(leftMostBit, ref noBits)) - return 0; - - if (Test_UInt32_ByRef_CastByte_CastByte_Or(rightMostBit, ref leftMostBit)) - return 0; - - if (Test_UInt32_ByRef_CastByte_CastByte_Or(rightMostBit, ref rightMostBit)) - return 0; - - if (Test_UInt32_ByRef_CastByte_CastByte_Or(rightMostBit, ref noBits)) - return 0; - - if (!Test_UInt32_ByRef_CastByte_CastByte_Or(noBits, ref leftMostBit)) + if (UnsafeAsNarrowCast_Short(255) != 255) return 0; - if (Test_UInt32_ByRef_CastByte_CastByte_Or(noBits, ref rightMostBit)) + if (UnsafeAsNarrowCast_Int(255) != 255) return 0; - if (!Test_UInt32_ByRef_CastByte_CastByte_Or(noBits, ref noBits)) + if (UnsafeAsNarrowCast_Long(255) != 255) return 0; return 100; From ccc56b142b3d7a816a5533d2885b133ad8aca14d Mon Sep 17 00:00:00 2001 From: TIHan Date: Tue, 14 Feb 2023 15:31:10 -0800 Subject: [PATCH 24/27] Rename NarrowCastOfLclVar to NarrowCast --- src/coreclr/jit/lclmorph.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index be92613c972329..7da7c87a120c76 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -464,7 +464,7 @@ class LocalAddressVisitor final : public GenTreeVisitor None, Nop, BitCast, - NarrowCastOfLclVar, + NarrowCast, #ifdef FEATURE_HW_INTRINSICS GetElement, WithElement, @@ -1250,7 +1250,7 @@ class LocalAddressVisitor final : public GenTreeVisitor lclNode = indir->AsLclVarCommon(); break; - case IndirTransform::NarrowCastOfLclVar: + case IndirTransform::NarrowCast: assert(varTypeIsIntegral(indir)); assert(varTypeIsIntegral(varDsc)); assert(*val.Use() == indir); @@ -1379,7 +1379,7 @@ class LocalAddressVisitor final : public GenTreeVisitor if (!isDef && varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc) && !varTypeIsLong(varDsc)) #endif // !TARGET_64BIT { - return IndirTransform::NarrowCastOfLclVar; + return IndirTransform::NarrowCast; } #ifdef FEATURE_HW_INTRINSICS From 4ac5f4cdf8146beadedf8600284202fd1b1b5836 Mon Sep 17 00:00:00 2001 From: TIHan Date: Wed, 15 Feb 2023 12:12:44 -0800 Subject: [PATCH 25/27] Feedback --- src/coreclr/jit/lclmorph.cpp | 50 ++++++++++++------------------------ 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 7da7c87a120c76..51c442b18e1b26 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1141,10 +1141,6 @@ class LocalAddressVisitor final : public GenTreeVisitor GenTreeLclVarCommon* lclNode = nullptr; bool isDef = (user != nullptr) && user->OperIs(GT_ASG) && (user->AsOp()->gtGetOp1() == indir); -#ifdef DEBUG - bool removeIndir = false; -#endif // DEBUG - switch (transform) { case IndirTransform::None: @@ -1253,19 +1249,12 @@ class LocalAddressVisitor final : public GenTreeVisitor case IndirTransform::NarrowCast: assert(varTypeIsIntegral(indir)); assert(varTypeIsIntegral(varDsc)); - assert(*val.Use() == indir); + assert(genTypeSize(varDsc) >= genTypeSize(indir)); assert(!isDef); lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); *val.Use() = m_compiler->gtNewCastNode(genActualType(indir), lclNode, false, indir->TypeGet()); - // Check to make sure this is narrow. - assert(genTypeSize(lclNode) >= genTypeSize(indir)); - -#ifdef DEBUG - removeIndir = true; -#endif // DEBUG - break; case IndirTransform::LclFld: @@ -1308,13 +1297,6 @@ class LocalAddressVisitor final : public GenTreeVisitor lclNode->gtFlags = lclNodeFlags; m_stmtModified = true; - -#ifdef DEBUG - if (removeIndir) - { - DEBUG_DESTROY_NODE(indir); - } -#endif // DEBUG } //------------------------------------------------------------------------ @@ -1372,16 +1354,6 @@ class LocalAddressVisitor final : public GenTreeVisitor return IndirTransform::LclFld; } -#ifdef TARGET_64BIT - if (!isDef && varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc)) -#else // TARGET_64BIT - // For non-64bit targets, do not do this for long types. - if (!isDef && varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc) && !varTypeIsLong(varDsc)) -#endif // !TARGET_64BIT - { - return IndirTransform::NarrowCast; - } - #ifdef FEATURE_HW_INTRINSICS if (varTypeIsSIMD(varDsc)) { @@ -1406,13 +1378,23 @@ class LocalAddressVisitor final : public GenTreeVisitor } #endif // FEATURE_HW_INTRINSICS - // Turn this into a bitcast if we can. - if ((genTypeSize(indir) == genTypeSize(varDsc)) && (varTypeIsFloating(indir) || varTypeIsFloating(varDsc))) + if (!isDef) { - // TODO-ADDR: enable this optimization for all users and all targets. - if (user->OperIs(GT_RETURN) && (genTypeSize(indir) <= TARGET_POINTER_SIZE)) + // Turn this into a narrow-cast if we can. + if (varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc)) { - return IndirTransform::BitCast; + return IndirTransform::NarrowCast; + } + + // Turn this into a bitcast if we can. + if ((genTypeSize(indir) == genTypeSize(varDsc)) && + (varTypeIsFloating(indir) || varTypeIsFloating(varDsc))) + { + // TODO-ADDR: enable this optimization for all users and all targets. + if (user->OperIs(GT_RETURN) && (genTypeSize(indir) <= TARGET_POINTER_SIZE)) + { + return IndirTransform::BitCast; + } } } From 7e695f3c7771a5add25dea8a233bd3a3e1c8680f Mon Sep 17 00:00:00 2001 From: TIHan Date: Wed, 15 Feb 2023 12:21:39 -0800 Subject: [PATCH 26/27] Feedback --- src/coreclr/jit/lclmorph.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 51c442b18e1b26..4f66b8ea2f03c3 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1378,23 +1378,19 @@ class LocalAddressVisitor final : public GenTreeVisitor } #endif // FEATURE_HW_INTRINSICS - if (!isDef) + // Turn this into a narrow-cast if we can. + if (!isDef && varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc)) { - // Turn this into a narrow-cast if we can. - if (varTypeIsIntegral(indir) && varTypeIsIntegral(varDsc)) - { - return IndirTransform::NarrowCast; - } + return IndirTransform::NarrowCast; + } - // Turn this into a bitcast if we can. - if ((genTypeSize(indir) == genTypeSize(varDsc)) && - (varTypeIsFloating(indir) || varTypeIsFloating(varDsc))) + // Turn this into a bitcast if we can. + if ((genTypeSize(indir) == genTypeSize(varDsc)) && (varTypeIsFloating(indir) || varTypeIsFloating(varDsc))) + { + // TODO-ADDR: enable this optimization for all users and all targets. + if (user->OperIs(GT_RETURN) && (genTypeSize(indir) <= TARGET_POINTER_SIZE)) { - // TODO-ADDR: enable this optimization for all users and all targets. - if (user->OperIs(GT_RETURN) && (genTypeSize(indir) <= TARGET_POINTER_SIZE)) - { - return IndirTransform::BitCast; - } + return IndirTransform::BitCast; } } From 93d81b6a2486d6828c3e35a159f9f64da8edfb3c Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 15 Feb 2023 13:12:24 -0800 Subject: [PATCH 27/27] Update src/coreclr/jit/lclmorph.cpp Co-authored-by: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> --- src/coreclr/jit/lclmorph.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 4f66b8ea2f03c3..78994398456b0a 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1254,7 +1254,6 @@ class LocalAddressVisitor final : public GenTreeVisitor lclNode = BashToLclVar(indir->gtGetOp1(), lclNum); *val.Use() = m_compiler->gtNewCastNode(genActualType(indir), lclNode, false, indir->TypeGet()); - break; case IndirTransform::LclFld: