diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 9090f19a761d3..16fcd7a02a687 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3747,7 +3747,7 @@ class Compiler //------------------------------------------------------------------------- - GenTree* gtFoldExpr(GenTree* tree); + GenTree* gtFoldExpr(GenTree* tree, bool* folded = nullptr); GenTree* gtFoldExprConst(GenTree* tree); GenTree* gtFoldIndirConst(GenTreeIndir* indir); GenTree* gtFoldExprSpecial(GenTree* tree); diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index ae55c80b13cf7..80ce88eb7c494 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -13572,10 +13572,13 @@ void Compiler::gtDispLIRNode(GenTree* node, const char* prefixMsg /* = nullptr * * and call the methods to perform the folding */ -GenTree* Compiler::gtFoldExpr(GenTree* tree) +GenTree* Compiler::gtFoldExpr(GenTree* tree, bool* folded) { unsigned kind = tree->OperKind(); + if (folded != nullptr) + *folded = false; + /* We must have a simple operation to fold */ // If we're in CSE, it's not safe to perform tree @@ -13595,13 +13598,19 @@ GenTree* Compiler::gtFoldExpr(GenTree* tree) { if (tree->OperIsConditional()) { - return gtFoldExprConditional(tree); + GenTree* newTree = gtFoldExprConditional(tree); + if (folded != nullptr) + *folded = newTree != tree; + return newTree; } #if defined(FEATURE_HW_INTRINSICS) if (tree->OperIsHWIntrinsic()) { - return gtFoldExprHWIntrinsic(tree->AsHWIntrinsic()); + GenTree* newTree = gtFoldExprHWIntrinsic(tree->AsHWIntrinsic()); + if (folded != nullptr) + *folded = newTree != tree; + return newTree; } #endif // FEATURE_HW_INTRINSICS @@ -13629,6 +13638,7 @@ GenTree* Compiler::gtFoldExpr(GenTree* tree) { if (op1->OperIsConst()) { + // constants folding results in a new tree that may be folded again, don't mark it as folded return gtFoldExprConst(tree); } } @@ -13640,7 +13650,8 @@ GenTree* Compiler::gtFoldExpr(GenTree* tree) // one of their arguments is an address. if (op1->OperIsConst() && op2->OperIsConst() && !tree->OperIsAtomicOp()) { - /* both nodes are constants - fold the expression */ + // both nodes are constants - fold the expression + // constants folding results in a new tree that may be folded again, don't mark it as folded return gtFoldExprConst(tree); } else if (op1->OperIsConst() || op2->OperIsConst()) @@ -13655,13 +13666,19 @@ GenTree* Compiler::gtFoldExpr(GenTree* tree) return tree; } - return gtFoldExprSpecial(tree); + GenTree* newTree = gtFoldExprSpecial(tree); + if (folded != nullptr) + *folded = newTree != tree; + return newTree; } else if (tree->OperIsCompare()) { /* comparisons of two local variables can sometimes be folded */ - return gtFoldExprCompare(tree); + GenTree* newTree = gtFoldExprCompare(tree); + if (folded != nullptr) + *folded = newTree != tree; + return newTree; } } diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index c0b7a6417b298..b0ac4a65d8136 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -8305,10 +8305,17 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA } // Try to fold it, maybe we get lucky, - tree = gtFoldExpr(tree); + bool folded; + tree = gtFoldExpr(tree, &folded); if (oldTree != tree) { + if (folded) + { + INDEBUG(tree->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); + return tree; + } + /* if gtFoldExpr returned op1 or op2 then we are done */ if ((tree == op1) || (tree == op2) || (tree == qmarkOp1) || (tree == qmarkOp2)) {