From adde7ec38451448518c429d69f540db24e21ec99 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 30 Sep 2022 13:23:47 +0200 Subject: [PATCH 1/4] Fix codegen for string unroll --- src/coreclr/jit/importer_vectorization.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/coreclr/jit/importer_vectorization.cpp b/src/coreclr/jit/importer_vectorization.cpp index dea8b5c8bc36ae..beeed341ac77d8 100644 --- a/src/coreclr/jit/importer_vectorization.cpp +++ b/src/coreclr/jit/importer_vectorization.cpp @@ -722,9 +722,11 @@ GenTree* Compiler::impStringEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO if (unrolled->OperIs(GT_QMARK)) { // QMARK nodes cannot reside on the evaluation stack + unrolled->ChangeType(TYP_BOOL); unsigned rootTmp = lvaGrabTemp(true DEBUGARG("spilling unroll qmark")); impAssignTempGen(rootTmp, unrolled); unrolled = gtNewLclvNode(rootTmp, TYP_INT); + lvaTable[rootTmp].lvType = TYP_BOOL; } JITDUMP("\n... Successfully unrolled to:\n") @@ -872,9 +874,11 @@ GenTree* Compiler::impSpanEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO* if (unrolled->OperIs(GT_QMARK)) { // QMARK can't be a root node, spill it to a temp + unrolled->ChangeType(TYP_BOOL); unsigned rootTmp = lvaGrabTemp(true DEBUGARG("spilling unroll qmark")); impAssignTempGen(rootTmp, unrolled); unrolled = gtNewLclvNode(rootTmp, TYP_INT); + lvaTable[rootTmp].lvType = TYP_BOOL; } JITDUMP("... Successfully unrolled to:\n") From a213f621ad59f0fabe8601cf1241e6dde9d160ab Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 30 Sep 2022 19:06:05 +0200 Subject: [PATCH 2/4] better fix --- src/coreclr/jit/importer_vectorization.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/importer_vectorization.cpp b/src/coreclr/jit/importer_vectorization.cpp index beeed341ac77d8..6b9817d3be597b 100644 --- a/src/coreclr/jit/importer_vectorization.cpp +++ b/src/coreclr/jit/importer_vectorization.cpp @@ -526,7 +526,7 @@ GenTree* Compiler::impExpandHalfConstEquals(GenTreeLclVar* data, GenTreeColon* lenCheckColon = gtNewColonNode(TYP_INT, indirCmp, gtNewFalse()); // For StartsWith we use GT_GE, e.g.: `x.Length >= 10` - lenCheckNode = gtNewQmarkNode(TYP_INT, gtNewOperNode(cmpOp, TYP_INT, lengthFld, elementsCount), lenCheckColon); + lenCheckNode = gtNewQmarkNode(TYP_BOOL, gtNewOperNode(cmpOp, TYP_INT, lengthFld, elementsCount), lenCheckColon); } GenTree* rootQmark; @@ -534,7 +534,7 @@ GenTree* Compiler::impExpandHalfConstEquals(GenTreeLclVar* data, { // varData == nullptr GenTreeColon* nullCheckColon = gtNewColonNode(TYP_INT, lenCheckNode, gtNewFalse()); - rootQmark = gtNewQmarkNode(TYP_INT, gtNewOperNode(GT_NE, TYP_INT, data, gtNewNull()), nullCheckColon); + rootQmark = gtNewQmarkNode(TYP_BOOL, gtNewOperNode(GT_NE, TYP_INT, data, gtNewNull()), nullCheckColon); } else { @@ -722,11 +722,9 @@ GenTree* Compiler::impStringEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO if (unrolled->OperIs(GT_QMARK)) { // QMARK nodes cannot reside on the evaluation stack - unrolled->ChangeType(TYP_BOOL); unsigned rootTmp = lvaGrabTemp(true DEBUGARG("spilling unroll qmark")); impAssignTempGen(rootTmp, unrolled); unrolled = gtNewLclvNode(rootTmp, TYP_INT); - lvaTable[rootTmp].lvType = TYP_BOOL; } JITDUMP("\n... Successfully unrolled to:\n") @@ -874,11 +872,9 @@ GenTree* Compiler::impSpanEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO* if (unrolled->OperIs(GT_QMARK)) { // QMARK can't be a root node, spill it to a temp - unrolled->ChangeType(TYP_BOOL); unsigned rootTmp = lvaGrabTemp(true DEBUGARG("spilling unroll qmark")); impAssignTempGen(rootTmp, unrolled); unrolled = gtNewLclvNode(rootTmp, TYP_INT); - lvaTable[rootTmp].lvType = TYP_BOOL; } JITDUMP("... Successfully unrolled to:\n") From 6b07d3fce1bde674ea596d1407e201f5e30f7b8c Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 30 Sep 2022 22:53:47 +0200 Subject: [PATCH 3/4] Experiment with FromNode --- src/coreclr/jit/assertionprop.cpp | 21 +++++++++++++++++++++ src/coreclr/jit/compiler.h | 1 + src/coreclr/jit/gentree.h | 10 ++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 8ec78ddcb2c4d0..4485661a3b76c2 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -175,6 +175,21 @@ bool IntegralRange::Contains(int64_t value) const } break; + case GT_CNS_INT: + if (node->IsIntegralConst(0)) + { + return {SymbolicIntegerValue::Zero, SymbolicIntegerValue::Zero}; + } + if (node->IsIntegralConst(1)) + { + return {SymbolicIntegerValue::One, SymbolicIntegerValue::One}; + } + break; + + case GT_QMARK: + return Union(ForNode(node->AsQmark()->ThenNode(), compiler), + ForNode(node->AsQmark()->ElseNode(), compiler)); + case GT_CAST: return ForCastOutput(node->AsCast()); @@ -430,6 +445,12 @@ bool IntegralRange::Contains(int64_t value) const return {lowerBound, upperBound}; } +/* static */ IntegralRange IntegralRange::Union(IntegralRange range1, IntegralRange range2) +{ + return IntegralRange(min(range1.GetLowerBound(), range2.GetLowerBound()), + max(range1.GetUpperBound(), range2.GetUpperBound())); +} + #ifdef DEBUG /* static */ void IntegralRange::Print(IntegralRange range) { diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 7f65f012426543..345a627a715893 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -1268,6 +1268,7 @@ class IntegralRange static IntegralRange ForNode(GenTree* node, Compiler* compiler); static IntegralRange ForCastInput(GenTreeCast* cast); static IntegralRange ForCastOutput(GenTreeCast* cast); + static IntegralRange Union(IntegralRange range1, IntegralRange range2); #ifdef DEBUG static void Print(IntegralRange range); diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 38eb63944ed9bb..9199d6e57f889c 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -5712,6 +5712,16 @@ struct GenTreeQmark : public GenTreeOp assert((colon != nullptr) && colon->OperIs(GT_COLON)); } + GenTree* ThenNode() + { + return gtOp2->AsColon()->ThenNode(); + } + + GenTree* ElseNode() + { + return gtOp2->AsColon()->ElseNode(); + } + #if DEBUGGABLE_GENTREE GenTreeQmark() : GenTreeOp() { From 62021c52fa12b17726dcb0081ca8e45dd8f45d30 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 30 Sep 2022 23:19:36 +0200 Subject: [PATCH 4/4] revert TYP_BOOL --- src/coreclr/jit/assertionprop.cpp | 8 ++------ src/coreclr/jit/importer_vectorization.cpp | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 4485661a3b76c2..9e9a076eac8ee5 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -176,13 +176,9 @@ bool IntegralRange::Contains(int64_t value) const break; case GT_CNS_INT: - if (node->IsIntegralConst(0)) + if (node->IsIntegralConst(0) || node->IsIntegralConst(1)) { - return {SymbolicIntegerValue::Zero, SymbolicIntegerValue::Zero}; - } - if (node->IsIntegralConst(1)) - { - return {SymbolicIntegerValue::One, SymbolicIntegerValue::One}; + return {SymbolicIntegerValue::Zero, SymbolicIntegerValue::One}; } break; diff --git a/src/coreclr/jit/importer_vectorization.cpp b/src/coreclr/jit/importer_vectorization.cpp index 6b9817d3be597b..dea8b5c8bc36ae 100644 --- a/src/coreclr/jit/importer_vectorization.cpp +++ b/src/coreclr/jit/importer_vectorization.cpp @@ -526,7 +526,7 @@ GenTree* Compiler::impExpandHalfConstEquals(GenTreeLclVar* data, GenTreeColon* lenCheckColon = gtNewColonNode(TYP_INT, indirCmp, gtNewFalse()); // For StartsWith we use GT_GE, e.g.: `x.Length >= 10` - lenCheckNode = gtNewQmarkNode(TYP_BOOL, gtNewOperNode(cmpOp, TYP_INT, lengthFld, elementsCount), lenCheckColon); + lenCheckNode = gtNewQmarkNode(TYP_INT, gtNewOperNode(cmpOp, TYP_INT, lengthFld, elementsCount), lenCheckColon); } GenTree* rootQmark; @@ -534,7 +534,7 @@ GenTree* Compiler::impExpandHalfConstEquals(GenTreeLclVar* data, { // varData == nullptr GenTreeColon* nullCheckColon = gtNewColonNode(TYP_INT, lenCheckNode, gtNewFalse()); - rootQmark = gtNewQmarkNode(TYP_BOOL, gtNewOperNode(GT_NE, TYP_INT, data, gtNewNull()), nullCheckColon); + rootQmark = gtNewQmarkNode(TYP_INT, gtNewOperNode(GT_NE, TYP_INT, data, gtNewNull()), nullCheckColon); } else {